[comp.sys.hp] Backing up CDFs

seg@smsdpg.uu.net (Scott Garfinkle) (06/29/89)

Following applies to our 9000/3xx workstations under hp-ux 6.5.

A funny thing happened to me when I tried to restore /usr/lib/X11 the other
day, after carelessly blowing it away:  I noticed that the CDFs therein were
not restored as such.   It seems that if you dump a cdf, e.g. foo+/*, what
you get back is a standard directory -- foo/*.  At least our restore doesn't
do the necessary chmod to set the 04000 bit.  Pretty irritating.  Since we're
using Gnu tar for other reasons, anyway, I went and hacked in support for
dumping/restoring CDFs.  If you apply the following patches to
Gnu tar v1.07, you will have available a -Q switch which, when creating an
archive, causes all CDFs to be dumped as such, not as the local version of
the file.  Note that this is, of course, *not* what you normally want, but
is very useful for system backups.  Any CDFs dumped this way will be restored
this way, if -Q is specified on restore.  Possibly, the -Q should be the
default on extract operations, but to retain compatibility with other tars
and with other filesystems where the SUID bit on directories means something
else (e.g. BSD 4.3), it is not.

(By the way, Gnu tar is *way* nicer than SysV tar.  It's faster, supports
 larger blocking factors, remote tape servers, incremental backups, and
 multi-volume tar tape.
)
---------------------------------------------------------
*** tar/Makefile	Thu Jun 29 08:49:52 1989
--- /home/staff/seg/src/gnu/tar-dist-1.07/Makefile	Wed May 17 14:22:37 1989
***************
*** 1,8 ****
  # Makefile for public domain tar program.
  # @(#)Makefile 1.30	87/11/11
  
- #CC= gcc -g
- 
  ## GNU version
  #DEFS = -DBSD42
  #LOCAL_SRC = 
--- 1,6 ----
***************
*** 15,30 ****
  #DEFBLOCKING = 20
  #O = o
  
! # Berserkeley version (works also for HP-UX except DEF_AR_FILE and COPTS)
  DEFS = -DBSD42
  LOCAL_SRC = getdate.y  rtape_lib.c
  LOCAL_OBJ = getdate.$O rtape_lib.$O
! LDFLAGS = -n
! LIBS = /usr/lib/libgnu.a
  LINT = lint
  LINTFLAGS = -abchx
! #DEF_AR_FILE = \"/dev/rmt8\"
! DEF_AR_FILE = \"/dev/rmt/0h\"
  DEFBLOCKING = 20
  O = o
  
--- 13,27 ----
  #DEFBLOCKING = 20
  #O = o
  
! # Berserkeley version
  DEFS = -DBSD42
  LOCAL_SRC = getdate.y  rtape_lib.c
  LOCAL_OBJ = getdate.$O rtape_lib.$O
! LDFLAGS =
! LIBS =
  LINT = lint
  LINTFLAGS = -abchx
! DEF_AR_FILE = \"/dev/rmt8\"
  DEFBLOCKING = 20
  O = o
  
***************
*** 131,141 ****
  	-DDEF_AR_FILE=$(DEF_AR_FILE) \
  	-DDEFBLOCKING=$(DEFBLOCKING)
  # next line for Debugging
! #COPTS = -g
  # next line for Production
  #COPTS = -O
- # for HP-UX
- COPTS = +x -O
  
  # Add things here like getopt, readdir, etc that aren't in your
  # standard libraries.  (E.g. MSDOS needs getopt, msd_dir.c, msd_dir.obj)
--- 128,136 ----
  	-DDEF_AR_FILE=$(DEF_AR_FILE) \
  	-DDEFBLOCKING=$(DEFBLOCKING)
  # next line for Debugging
! COPTS = -g
  # next line for Production
  #COPTS = -O
  
  # Add things here like getopt, readdir, etc that aren't in your
  # standard libraries.  (E.g. MSDOS needs getopt, msd_dir.c, msd_dir.obj)
*** tar/buffer.c	Thu May 18 21:42:16 1989
--- /home/staff/seg/src/gnu/tar-dist-1.07/buffer.c	Fri Apr 28 15:53:14 1989
***************
*** 72,77 ****
--- 72,79 ----
  extern char	*valloc();
  #endif
  
+ extern char	*index(), *strcat();
+ extern char	*strcpy();
  
  /*
   * V7 doesn't have a #define for this.
*** tar/create.c	Thu Jun 29 07:36:09 1989
--- /home/staff/seg/src/gnu/tar-dist-1.07/create.c	Thu Mar 23 18:01:22 1989
***************
*** 65,71 ****
  #define DP_NAMELEN(x)	(x)->d_namlen
  #endif
  
! #if defined(USG) || defined(hpux)
  #include <sys/sysmacros.h>	/* major() and minor() defined here */
  #endif
  
--- 65,71 ----
  #define DP_NAMELEN(x)	(x)->d_namlen
  #endif
  
! #ifdef USG
  #include <sys/sysmacros.h>	/* major() and minor() defined here */
  #endif
  
***************
*** 101,106 ****
--- 101,110 ----
  #endif
  
  extern char	*malloc();
+ extern char	*strcpy();
+ extern char	*strncpy();
+ extern void	bzero();
+ extern void	bcopy();
  extern int	errno;
  
  extern void print_header();
***************
*** 178,203 ****
  	if(f_confirm && !confirm("add",p))
  		return;
  
- #ifdef hpux
- 	/* horrible hack for hpux CDFs.  In hpux, any file you get from from
- 	 * readdir (or dumping the directory for that matter) may be a CDF,
- 	 * where name "foo" is *really* a directory and file, like
- 	 * "foo+/`cnode -m`" -- in order to do a complete dump of a server,
- 	 * it may be necessary to dump the "hidden" directory, rather than
- 	 * the file so kindly given to us.  Thus, we need to check.
- 	 */
- 	if(f_checkcdf) {
- 		int flen = strlen(p);
- 		char *testcdf, *alloca();
- 
- 		testcdf = alloca(flen+2);
- 		memcpy(testcdf,p,flen);
- 		testcdf[flen++] = '+';
- 		testcdf[flen] = '\0';
- 		if(!(f_follow_links? stat(testcdf, &hstat): lstat(testcdf, &hstat)))
- 			p = testcdf;
- 	}
- #endif /* hpux */
  	/*
  	 * Use stat if following (rather than dumping) 4.2BSD's
  	 * symbolic links.  Otherwise, use lstat (which, on non-4.2
--- 182,187 ----
***************
*** 585,596 ****
  		finish_header(header);
  		break;
  
- #ifdef S_IFSOCK
- 	case S_IFSOCK:			/* socket.  don'd dump */
- 		msg("%s:  socket; file ignored.\n", p);
- 		break;
- #endif
- 
  	default:
  	unknown:
  		msg("%s: Unknown file type; file ignored.\n", p);
--- 569,574 ----
***************
*** 673,678 ****
--- 651,657 ----
  {
  	register int	i, sum;
  	register char	*p;
+ 	void bcopy();
  
  	bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
  
***************
*** 759,764 ****
--- 738,744 ----
  {
  	union record *p;
  	int bufsize;
+ 	void bzero();
  
  	p = findrec();
  	bufsize = endofrecs()->charptr - p->charptr;
*** tar/getoldopt.c	Thu May 18 21:52:58 1989
--- /home/staff/seg/src/gnu/tar-dist-1.07/getoldopt.c	Thu Mar  2 13:00:27 1989
***************
*** 28,36 ****
   */
  
  #include <stdio.h>
- #include <sys/types.h>
- #include "tar.h"
  
  int
  getoldopt(argc, argv, optstring)
  	int	argc;
--- 28,35 ----
   */
  
  #include <stdio.h>
  
+ 
  int
  getoldopt(argc, argv, optstring)
  	int	argc;
***************
*** 41,46 ****
--- 40,46 ----
  	extern int	optind;		/* Global argv index */
  	static char	*key;		/* Points to next keyletter */
  	static char	use_getopt;	/* !=0 if argv[1][0] was '-' */
+ 	extern char	*index();
  	char		c;
  	char		*place;
  
*** tar/list.c	Thu May 18 21:52:58 1989
--- /home/staff/seg/src/gnu/tar-dist-1.07/list.c	Thu Mar 23 18:01:22 1989
***************
*** 34,40 ****
  #include <sys/file.h>
  #endif	/* MSDOS */
  
! #if defined(USG) || defined(hpux)
  #include <sys/sysmacros.h>	/* major() and minor() defined here */
  #endif
  
--- 34,40 ----
  #include <sys/file.h>
  #endif	/* MSDOS */
  
! #ifdef USG
  #include <sys/sysmacros.h>	/* major() and minor() defined here */
  #endif
  
*** tar/rmt.h	Thu May 18 21:37:38 1989
--- /home/staff/seg/src/gnu/tar-dist-1.07/rmt.h	Thu Mar  2 13:05:06 1989
***************
*** 34,39 ****
--- 34,42 ----
  #define rmtisatty	isatty
  
  #else
+ #ifndef USG
+ #define strchr index
+ #endif
  
  #define __REM_BIAS	128
  #define RMTIOCTL
***************
*** 42,47 ****
--- 45,51 ----
  #define O_CREAT	01000
  #endif
  extern char *__rmt_path;
+ extern char *strchr();
  
  #define _remdev(path)	((__rmt_path=strchr(path, ':')) && strncmp(__rmt_path, ":/dev/", 6)==0)
  #define _isrmt(fd)		((fd) >= __REM_BIAS)
*** tar/tar.c	Wed Jun 28 23:18:49 1989
--- /home/staff/seg/src/gnu/tar-dist-1.07/tar.c	Tue May 16 14:06:53 1989
***************
*** 31,36 ****
--- 31,40 ----
  #include <sys/types.h>		/* Needed for typedefs in tar.h */
  #include <sys/stat.h>		/* JF */
  
+ #ifdef USG
+ #define rindex strrchr
+ #endif
+ 
  #ifdef BSD42
  #include <sys/dir.h>
  #else
***************
*** 58,63 ****
--- 62,71 ----
  
  extern char 	*malloc();
  extern char 	*getenv();
+ extern char	*strncpy();
+ extern char	*index();
+ extern char	*strcpy();	/* JF */
+ extern char	*strcat();	/* JF */
  
  extern char	*optarg;	/* Pointer to argument */
  extern int	optind;		/* Global argv index from getopt */
***************
*** 185,195 ****
  		ar_file = DEF_AR_FILE;	/* From Makefile */
  
  	/* Parse options */
- #ifdef hpux
- 	while ((c = getoldopt(argc, argv, "01234567Ab:BcC:dDf:GhikK:lmMN:oOpPQrRstT:uvV:wWxX:zZ")
- #else
  	while ((c = getoldopt(argc, argv, "01234567Ab:BcC:dDf:GhikK:lmMN:oOpPrRstT:uvV:wWxX:zZ")
- #endif
  		) != EOF) {
  		switch (c) {
  		case '0':
--- 193,199 ----
***************
*** 201,209 ****
  		case '6':
  		case '7':
  			{
- 				int d=getoldopt(argc,argv,"lmh");
- 				static char buf[50];
- #ifdef BSD
  				/* JF this'll have to be modified for other
  				   systems, of course! */
  #ifndef LOW_NUM
--- 205,210 ----
***************
*** 211,227 ****
  #define MID_NUM 8
  #define HGH_NUM 16
  #endif
! 
! 				int add;
  
  				if(d=='l') add=LOW_NUM;
  				else if(d=='m') add=MID_NUM;
  				else if(d=='h') add=HGH_NUM;
  				else goto badopt;
  				sprintf(buf,"/dev/rmt%d",add+c-'0');
- #else
- 				sprintf(buf,"/dev/rmt/0%c",d);
- #endif
  				ar_file=buf;
  			}
  			break;
--- 212,226 ----
  #define MID_NUM 8
  #define HGH_NUM 16
  #endif
! 				int d,add;
! 				static char buf[50];
  
+ 				d=getoldopt(argc,argv,"lmh");
  				if(d=='l') add=LOW_NUM;
  				else if(d=='m') add=MID_NUM;
  				else if(d=='h') add=HGH_NUM;
  				else goto badopt;
  				sprintf(buf,"/dev/rmt%d",add+c-'0');
  				ar_file=buf;
  			}
  			break;
***************
*** 352,363 ****
  			f_absolute_paths++;
  			break;
  
- #ifdef hpux
- 		case 'Q':
- 			f_checkcdf++;
- 			break;
- #endif
- 
  		case 'r':			/* Append files to the archive */
  			if(cmd_mode!=CMD_NONE)
  				goto badopt;
--- 351,356 ----
***************
*** 670,676 ****
  		}
  		if(chdir_name[0]!='/') {
  			char path[MAXPATHLEN];
! #if defined(MSDOS) || defined(hpux)
  			int getcwd();
  
  			if(!getcwd(path,MAXPATHLEN))
--- 663,669 ----
  		}
  		if(chdir_name[0]!='/') {
  			char path[MAXPATHLEN];
! #ifdef MSDOS
  			int getcwd();
  
  			if(!getcwd(path,MAXPATHLEN))
*** tar/tar.h	Wed Jun 28 23:19:36 1989
--- /home/staff/seg/src/gnu/tar-dist-1.07/tar.h	Thu Mar 23 18:01:20 1989
***************
*** 164,172 ****
  TAR_EXTERN char f_exstdout;		/* -O */
  TAR_EXTERN char	f_use_protection;	/* -p */
  TAR_EXTERN char f_absolute_paths;	/* -P */
- #ifdef hpux
- TAR_EXTERN char	f_checkcdf;	/* -Q */
- #endif
  TAR_EXTERN char	f_sayblock;		/* -R */
  TAR_EXTERN char	f_sorted_names;		/* -s */
  TAR_EXTERN char	f_namefile;		/* -T */
--- 164,169 ----
***************
*** 222,228 ****
   *
   * Thanks, typedef.  Thanks, USG.
   */
- 
  struct link {
  	struct link	*next;
  	dev_t		dev;
--- 219,224 ----
***************
*** 256,273 ****
  #endif
  /* #define	 annorec(stream, msg)	anno(stream, msg, 0)	/* Cur rec */
  /* #define	annofile(stream, msg)	anno(stream, msg, 1)	/* Saved rec */
- 
- #ifdef hpux
- # define bzero(t,c) memset(t,'\0',c)
- # define bcopy(s,t,c) memcpy(t,s,c)
- # define bcmp memcmp
- # define rindex strrchr
- # define index strchr
- # define valloc malloc
- #endif
- 
- #ifdef BSD
- # include <strings.h>
- #else
- # include <string.h>
- #endif
--- 252,254 ----
*** /home/staff/seg/src/gnu/tar-dist-1.07/extract.c	Thu Mar 23 18:01:21 1989
--- tar/extract.c	Thu Jun 29 10:43:50 1989
***************
*** 64,70 ****
  
  extern int errno;			/* From libc.a */
  extern time_t time();			/* From libc.a */
- extern char *index();			/* From libc.a or port.c */
  
  #include "tar.h"
  #include "port.h"
--- 64,69 ----
***************
*** 294,299 ****
--- 293,316 ----
  		}
  
  		/*
+ 		 * Set the modified time of the file.
+ 		 * 
+ 		 * Note that we set the accessed time to "now", which
+ 		 * is really "the time we started extracting files".
+ 		 * unless f_gnudump is used, in which case .st_atime is used
+ 		 */
+ 		if (!f_modified) {
+ 			/* fixme if f_gnudump should set ctime too, but how? */
+ 			if(f_gnudump) acc_upd_times[0]=hstat.st_atime;
+ 			else acc_upd_times[0] = now;	         /* Accessed now */
+ 			acc_upd_times[1] = hstat.st_mtime; /* Mod'd */
+ 			if (utime(skipcrud+head->header.name,
+ 			    acc_upd_times) < 0) {
+ 				msg_perror("couldn't change access and modification times of %s",skipcrud+head->header.name);
+ 			}
+ 		}
+ 		/*
+ 		 * hpux note: need to change mode *after* doing everything else.
  		 * If '-k' is not set, open() or creat() could have saved
  		 * the permission bits from a previously created file,
  		 * ignoring the ones we specified.
***************
*** 306,311 ****
--- 323,335 ----
  		 * skip the chmod.  This works because we did umask(0) if -p
  		 * is set, so umask will have left the specified mode alone.
  		 */
+ #ifdef hpux
+ 		/* if we're not to restore CDFs, and out that nasty bit.  This
+ 		 * could be useful, e.g. when restoring a directory from a BSD system.
+ 		 */
+ 		if(!f_checkcdf && (hstat.st_mode & S_CDF))
+ 			hstat.st_mode &= ~S_CDF;
+ #endif
  		if ((!f_keep)
  		    || (hstat.st_mode & (S_ISUID|S_ISGID|S_ISVTX))) {
  			if (chmod(skipcrud+head->header.name,
***************
*** 313,335 ****
  				msg_perror("cannot change mode of file %s to %ld",skipcrud+head->header.name,notumask & (int)hstat.st_mode);
  			}
  		}
! 		/*
! 		 * Set the modified time of the file.
! 		 * 
! 		 * Note that we set the accessed time to "now", which
! 		 * is really "the time we started extracting files".
! 		 * unless f_gnudump is used, in which case .st_atime is used
  		 */
! 		if (!f_modified) {
! 			/* fixme if f_gnudump should set ctime too, but how? */
! 			if(f_gnudump) acc_upd_times[0]=hstat.st_atime;
! 			else acc_upd_times[0] = now;	         /* Accessed now */
! 			acc_upd_times[1] = hstat.st_mtime; /* Mod'd */
! 			if (utime(skipcrud+head->header.name,
! 			    acc_upd_times) < 0) {
! 				msg_perror("couldn't change access and modification times of %s",skipcrud+head->header.name);
! 			}
! 		}
  
  	quit:
  		break;
--- 337,351 ----
  				msg_perror("cannot change mode of file %s to %ld",skipcrud+head->header.name,notumask & (int)hstat.st_mode);
  			}
  		}
! #ifdef hpux
! 		/* the other half of the horrible hpux hack:  restore '+'  (see below)
  		 */
! 		if((hstat.st_mode & S_CDF) &&
! 			(head->header.linkflag == LF_DIR ||
! 			 head->header.linkflag == LF_DUMPDIR)
! 		)
! 			head->header.name[skipcrud+ ++namelen] = '+';
! #endif
  
  	quit:
  		break;
***************
*** 407,413 ****
  		} else if(head->header.linkflag==LF_DUMPDIR)
  			skip_file((long)(hstat.st_size));
  
! 	
  	again_dir:
  		check = mkdir(skipcrud+head->header.name,
  			      0300 | (int)hstat.st_mode);
--- 423,436 ----
  		} else if(head->header.linkflag==LF_DUMPDIR)
  			skip_file((long)(hstat.st_size));
  
! #ifdef hpux
! 		/* horrible hpux hack:  if this is a directory and the S_ISCDF
! 		 * bit is set, we need to creat without the trailing '+', as
! 		 * hpux adds one internally (!)
! 		 */
! 		if(f_checkcdf && hstat.st_mode & S_CDF)
! 			head->header.name[skipcrud+namelen--] = '\0';
! #endif
  	again_dir:
  		check = mkdir(skipcrud+head->header.name,
  			      0300 | (int)hstat.st_mode);