Browse Source

*** empty log message ***

François Pinard 31 years ago
parent
commit
4ea60be930
3 changed files with 825 additions and 487 deletions
  1. 1 1
      scripts/level-1
  2. 540 486
      src/gnu.c
  3. 284 0
      src/tar.h

+ 1 - 1
scripts/level-1

@@ -85,7 +85,7 @@ LOGFILE="log-`date | sed -ne '
 
 
 localhost="`hostname | sed -e 's/\..*//'`"
 localhost="`hostname | sed -e 's/\..*//'`"
 
 
-TAR_PART1="${TAR} -c --multi-volume --one-file-system --block=${BLOCKING} --sparse --volno-file=${VOLNO_FILE}"
+TAR_PART1="${TAR} -c --multi-volume --one-file-system --block-size=${BLOCKING} --sparse --volno-file=${VOLNO_FILE}"
 
 
 # Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
 # Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
 if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then
 if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then

+ 540 - 486
src/gnu.c

@@ -25,7 +25,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 extern int errno;
 extern int errno;
 #endif
 #endif
 #include <time.h>
 #include <time.h>
-time_t time();
+time_t time ();
 
 
 #include "tar.h"
 #include "tar.h"
 #include "port.h"
 #include "port.h"
@@ -59,456 +59,498 @@ time_t time();
 extern time_t new_time;
 extern time_t new_time;
 extern FILE *msg_file;
 extern FILE *msg_file;
 
 
-void addname();
-int check_exclude();
-extern PTR ck_malloc();
-extern PTR ck_realloc();
-int confirm();
-extern PTR init_buffer();
-extern char *get_buffer();
-int is_dot_or_dotdot();
-extern void add_buffer();
-extern void flush_buffer();
-void name_gather();
-int recursively_delete();
-void skip_file();
-char *un_quote_string();
-
-extern char *new_name();
-
-static void add_dir_name();
-
-struct dirname {
-	struct dirname *next;
-	char *name;
-	char *dir_text;
-	int dev;
-	int ino;
-	int allnew;
-};
+void addname ();
+int check_exclude ();
+extern PTR ck_malloc ();
+extern PTR ck_realloc ();
+int confirm ();
+extern PTR init_buffer ();
+extern char *get_buffer ();
+int is_dot_or_dotdot ();
+extern void add_buffer ();
+extern void flush_buffer ();
+void name_gather ();
+int recursively_delete ();
+void skip_file ();
+char *un_quote_string ();
+
+extern char *new_name ();
+
+static void add_dir_name ();
+
+struct dirname
+  {
+    struct dirname *next;
+    char *name;
+    char *dir_text;
+    int dev;
+    int ino;
+    int allnew;
+  };
 static struct dirname *dir_list;
 static struct dirname *dir_list;
 static time_t this_time;
 static time_t this_time;
 
 
 void
 void
-add_dir(name,dev,ino,text)
-char *name;
-char *text;
-dev_t dev;
-ino_t ino;
+add_dir (name, dev, ino, text)
+     char *name;
+     char *text;
+     dev_t dev;
+     ino_t ino;
 {
 {
-	struct dirname *dp;
-
-	dp=(struct dirname *)malloc(sizeof(struct dirname));
-	if(!dp)
-		abort();
-	dp->next=dir_list;
-	dir_list=dp;
-	dp->dev=dev;
-	dp->ino=ino;
-	dp->name=malloc(strlen(name)+1);
-	strcpy(dp->name,name);
-	dp->dir_text=text;
-	dp->allnew=0;
+  struct dirname *dp;
+
+  dp = (struct dirname *) malloc (sizeof (struct dirname));
+  if (!dp)
+    abort ();
+  dp->next = dir_list;
+  dir_list = dp;
+  dp->dev = dev;
+  dp->ino = ino;
+  dp->name = malloc (strlen (name) + 1);
+  strcpy (dp->name, name);
+  dp->dir_text = text;
+  dp->allnew = 0;
 }
 }
 
 
 void
 void
-read_dir_file()
+read_dir_file ()
 {
 {
-	int dev;
-	int ino;
-	char *strp;
-	FILE *fp;
-	char buf[512];
-	static char *path = 0;
-
-	if (path == 0)
-		path = ck_malloc(PATH_MAX);
-	time(&this_time);
-	if(gnu_dumpfile[0]!='/') {
+  int dev;
+  int ino;
+  char *strp;
+  FILE *fp;
+  char buf[512];
+  static char *path = 0;
+
+  if (path == 0)
+    path = ck_malloc (PATH_MAX);
+  time (&this_time);
+  if (gnu_dumpfile[0] != '/')
+    {
 #if defined(__MSDOS__) || defined(USG) || defined(_POSIX_VERSION)
 #if defined(__MSDOS__) || defined(USG) || defined(_POSIX_VERSION)
-			if(!getcwd(path,PATH_MAX)) {
-				msg("Couldn't get current directory.");
-				exit(EX_SYSTEM);
-			}
+      if (!getcwd (path, PATH_MAX))
+	{
+	  msg ("Couldn't get current directory.");
+	  exit (EX_SYSTEM);
+	}
 #else
 #else
-			char *getwd();
+      char *getwd ();
 
 
-			if(!getwd(path)) {
-				msg("Couldn't get current directory: %s",path);
-				exit(EX_SYSTEM);
-			}
-#endif
-		/* If this doesn't fit, we're in serious trouble */
-		strcat(path,"/");
-		strcat(path,gnu_dumpfile);
-		gnu_dumpfile=path;
-	}
-	fp=fopen(gnu_dumpfile,"r");
-	if(fp==0 && errno!=ENOENT) {
-		msg_perror("Can't open %s",gnu_dumpfile);
-		return;
-	}
-	if(!fp)
-		return;
-	fgets(buf,sizeof(buf),fp);
-	if(!f_new_files) {
-		f_new_files++;
-		new_time=atol(buf);
+      if (!getwd (path))
+	{
+	  msg ("Couldn't get current directory: %s", path);
+	  exit (EX_SYSTEM);
 	}
 	}
-	while(fgets(buf,sizeof(buf),fp)) {
-		strp= &buf[strlen(buf)];
-		if(strp[-1]=='\n')
-			strp[-1]='\0';
-		strp=buf;
-		dev=atol(strp);
-		while(isdigit(*strp))
-			strp++;
-		ino=atol(strp);
-		while(isspace(*strp))
-			strp++;
-		while(isdigit(*strp))
-			strp++;
-		strp++;
-		add_dir(un_quote_string(strp),dev,ino,(char *)0);
-	}
-	fclose(fp);
+#endif
+      /* If this doesn't fit, we're in serious trouble */
+      strcat (path, "/");
+      strcat (path, gnu_dumpfile);
+      gnu_dumpfile = path;
+    }
+  fp = fopen (gnu_dumpfile, "r");
+  if (fp == 0 && errno != ENOENT)
+    {
+      msg_perror ("Can't open %s", gnu_dumpfile);
+      return;
+    }
+  if (!fp)
+    return;
+  fgets (buf, sizeof (buf), fp);
+  if (!f_new_files)
+    {
+      f_new_files++;
+      new_time = atol (buf);
+    }
+  while (fgets (buf, sizeof (buf), fp))
+    {
+      strp = &buf[strlen (buf)];
+      if (strp[-1] == '\n')
+	strp[-1] = '\0';
+      strp = buf;
+      dev = atol (strp);
+      while (isdigit (*strp))
+	strp++;
+      ino = atol (strp);
+      while (isspace (*strp))
+	strp++;
+      while (isdigit (*strp))
+	strp++;
+      strp++;
+      add_dir (un_quote_string (strp), dev, ino, (char *) 0);
+    }
+  fclose (fp);
 }
 }
 
 
 void
 void
-write_dir_file()
+write_dir_file ()
 {
 {
-	FILE *fp;
-	struct dirname *dp;
-	char *str;
-	extern char *quote_copy_string();
-
-	fp=fopen(gnu_dumpfile,"w");
-	if(fp==0) {
-		msg_perror("Can't write to %s",gnu_dumpfile);
-		return;
-	}
-	fprintf(fp,"%lu\n",this_time);
-	for(dp=dir_list;dp;dp=dp->next) {
-		if(!dp->dir_text)
-			continue;
-		str=quote_copy_string(dp->name);
-		if(str) {
-			fprintf(fp,"%u %u %s\n",dp->dev,dp->ino,str);
-			free(str);
-		} else
-			fprintf(fp,"%u %u %s\n",dp->dev,dp->ino,dp->name);
+  FILE *fp;
+  struct dirname *dp;
+  char *str;
+  extern char *quote_copy_string ();
+
+  fp = fopen (gnu_dumpfile, "w");
+  if (fp == 0)
+    {
+      msg_perror ("Can't write to %s", gnu_dumpfile);
+      return;
+    }
+  fprintf (fp, "%lu\n", this_time);
+  for (dp = dir_list; dp; dp = dp->next)
+    {
+      if (!dp->dir_text)
+	continue;
+      str = quote_copy_string (dp->name);
+      if (str)
+	{
+	  fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, str);
+	  free (str);
 	}
 	}
-	fclose(fp);
+      else
+	fprintf (fp, "%u %u %s\n", dp->dev, dp->ino, dp->name);
+    }
+  fclose (fp);
 }
 }
 
 
 struct dirname *
 struct dirname *
-get_dir(name)
-char *name;
+get_dir (name)
+     char *name;
 {
 {
-	struct dirname *dp;
-
-	for(dp=dir_list;dp;dp=dp->next) {
-		if(!strcmp(dp->name,name))
-			return dp;
-	}
-	return 0;
+  struct dirname *dp;
+
+  for (dp = dir_list; dp; dp = dp->next)
+    {
+      if (!strcmp (dp->name, name))
+	return dp;
+    }
+  return 0;
 }
 }
 
 
 
 
 /* Collect all the names from argv[] (or whatever), then expand them into
 /* Collect all the names from argv[] (or whatever), then expand them into
    a directory tree, and put all the directories at the beginning. */
    a directory tree, and put all the directories at the beginning. */
 void
 void
-collect_and_sort_names()
+collect_and_sort_names ()
 {
 {
-	struct name *n,*n_next;
-	int num_names;
-	struct stat statbuf;
-	int name_cmp();
-	char *merge_sort();
-
-	name_gather();
-
-	if(gnu_dumpfile)
-		read_dir_file();
-	if(!namelist) addname(".");
-	for(n=namelist;n;n=n_next) {
-		n_next=n->next;
-		if(n->found || n->dir_contents)
-			continue;
-		if(n->regexp)		/* FIXME just skip regexps for now */
-			continue;
-		if(n->change_dir)
-			if(chdir(n->change_dir)<0) {
-				msg_perror("can't chdir to %s",n->change_dir);
-				continue;
-			}
+  struct name *n, *n_next;
+  int num_names;
+  struct stat statbuf;
+  int name_cmp ();
+  char *merge_sort ();
+
+  name_gather ();
+
+  if (gnu_dumpfile)
+    read_dir_file ();
+  if (!namelist)
+    addname (".");
+  for (n = namelist; n; n = n_next)
+    {
+      n_next = n->next;
+      if (n->found || n->dir_contents)
+	continue;
+      if (n->regexp)		/* FIXME just skip regexps for now */
+	continue;
+      if (n->change_dir)
+	if (chdir (n->change_dir) < 0)
+	  {
+	    msg_perror ("can't chdir to %s", n->change_dir);
+	    continue;
+	  }
 
 
 #ifdef AIX
 #ifdef AIX
-		if (statx (n->name, &statbuf, STATSIZE, STX_HIDDEN|STX_LINK))
+      if (statx (n->name, &statbuf, STATSIZE, STX_HIDDEN | STX_LINK))
 #else
 #else
-		if(lstat(n->name,&statbuf)<0)
+      if (lstat (n->name, &statbuf) < 0)
 #endif /* AIX */
 #endif /* AIX */
-		{
-			msg_perror("can't stat %s",n->name);
-			continue;
-		}
-		if(S_ISDIR(statbuf.st_mode)) {
-			n->found++;
-			add_dir_name(n->name,statbuf.st_dev);
-		}
+	{
+	  msg_perror ("can't stat %s", n->name);
+	  continue;
 	}
 	}
-
-	num_names=0;
-	for(n=namelist;n;n=n->next)
-		num_names++;
-	namelist=(struct name *)merge_sort((PTR)namelist,num_names,(char *)(&(namelist->next))-(char *)namelist,name_cmp);
-
-	for(n=namelist;n;n=n->next) {
-		n->found=0;
+      if (S_ISDIR (statbuf.st_mode))
+	{
+	  n->found++;
+	  add_dir_name (n->name, statbuf.st_dev);
 	}
 	}
-	if(gnu_dumpfile)
-		write_dir_file();
+    }
+
+  num_names = 0;
+  for (n = namelist; n; n = n->next)
+    num_names++;
+  namelist = (struct name *) merge_sort ((PTR) namelist, num_names, (char *) (&(namelist->next)) - (char *) namelist, name_cmp);
+
+  for (n = namelist; n; n = n->next)
+    {
+      n->found = 0;
+    }
+  if (gnu_dumpfile)
+    write_dir_file ();
 }
 }
 
 
 int
 int
-name_cmp(n1,n2)
-struct name *n1,*n2;
+name_cmp (n1, n2)
+     struct name *n1, *n2;
 {
 {
-	if(n1->found) {
-		if(n2->found)
-			return strcmp(n1->name,n2->name);
-		else
-			return -1;
-	} else if(n2->found)
-		return 1;
-	else
-		return strcmp(n1->name,n2->name);
+  if (n1->found)
+    {
+      if (n2->found)
+	return strcmp (n1->name, n2->name);
+      else
+	return -1;
+    }
+  else if (n2->found)
+    return 1;
+  else
+    return strcmp (n1->name, n2->name);
 }
 }
 
 
 int
 int
-dirent_cmp(p1,p2)
-const PTR p1;
-const PTR p2;
+dirent_cmp (p1, p2)
+     const PTR p1;
+     const PTR p2;
 {
 {
-	char *frst,*scnd;
+  char *frst, *scnd;
 
 
-	frst= (*(char **)p1)+1;
-	scnd= (*(char **)p2)+1;
+  frst = (*(char **) p1) + 1;
+  scnd = (*(char **) p2) + 1;
 
 
-	return strcmp(frst,scnd);
+  return strcmp (frst, scnd);
 }
 }
 
 
 char *
 char *
-get_dir_contents(p,device)
-char *p;
-int device;
+get_dir_contents (p, device)
+     char *p;
+     int device;
 {
 {
-	DIR *dirp;
-	register struct direct *d;
-	char *new_buf;
-	char *namebuf;
-	int bufsiz;
-	int len;
-	PTR the_buffer;
-	char *buf;
-	size_t n_strs;
-/*	int n_size;*/
-	char *p_buf;
-	char **vec,**p_vec;
-
-	extern int errno;
-
-	errno=0;
-	dirp=opendir(p);
-	bufsiz=strlen(p)+NAMSIZ;
-	namebuf=ck_malloc(bufsiz+2);
-	if(!dirp) {
-		if(errno)
-			msg_perror("can't open directory %s",p);
-		else
-			msg("error opening directory %s",p);
-		new_buf=NULL;
-	} else {
-		struct dirname *dp;
-		int all_children;
-
-		dp=get_dir(p);
-		all_children= dp ? dp->allnew : 0;
-		(void) strcpy(namebuf,p);
-		if(p[strlen(p)-1]!='/')
-			(void) strcat(namebuf,"/");
-		len=strlen(namebuf);
-
-		the_buffer=init_buffer();
-		while(d=readdir(dirp)) {
-			struct stat hs;
-
-			/* Skip . and .. */
-			if(is_dot_or_dotdot(d->d_name))
-				continue;
-			if(DP_NAMELEN(d) + len >=bufsiz) {
-				bufsiz+=NAMSIZ;
-				namebuf=ck_realloc(namebuf,bufsiz+2);
-			}
-			(void) strcpy(namebuf+len,d->d_name);
+  DIR *dirp;
+  register struct direct *d;
+  char *new_buf;
+  char *namebuf;
+  int bufsiz;
+  int len;
+  PTR the_buffer;
+  char *buf;
+  size_t n_strs;
+  /*	int n_size;*/
+  char *p_buf;
+  char **vec, **p_vec;
+
+  extern int errno;
+
+  errno = 0;
+  dirp = opendir (p);
+  bufsiz = strlen (p) + NAMSIZ;
+  namebuf = ck_malloc (bufsiz + 2);
+  if (!dirp)
+    {
+      if (errno)
+	msg_perror ("can't open directory %s", p);
+      else
+	msg ("error opening directory %s", p);
+      new_buf = NULL;
+    }
+  else
+    {
+      struct dirname *dp;
+      int all_children;
+
+      dp = get_dir (p);
+      all_children = dp ? dp->allnew : 0;
+      (void) strcpy (namebuf, p);
+      if (p[strlen (p) - 1] != '/')
+	(void) strcat (namebuf, "/");
+      len = strlen (namebuf);
+
+      the_buffer = init_buffer ();
+      while (d = readdir (dirp))
+	{
+	  struct stat hs;
+
+	  /* Skip . and .. */
+	  if (is_dot_or_dotdot (d->d_name))
+	    continue;
+	  if (DP_NAMELEN (d) + len >= bufsiz)
+	    {
+	      bufsiz += NAMSIZ;
+	      namebuf = ck_realloc (namebuf, bufsiz + 2);
+	    }
+	  (void) strcpy (namebuf + len, d->d_name);
 #ifdef AIX
 #ifdef AIX
-			if (0 != f_follow_links?
-			    statx(namebuf, &hs, STATSIZE, STX_HIDDEN):
-			    statx(namebuf, &hs, STATSIZE, STX_HIDDEN|STX_LINK))
+	  if (0 != f_follow_links ?
+	      statx (namebuf, &hs, STATSIZE, STX_HIDDEN) :
+	      statx (namebuf, &hs, STATSIZE, STX_HIDDEN | STX_LINK))
 #else
 #else
-			if (0 != f_follow_links? stat(namebuf, &hs): lstat(namebuf, &hs))
+	  if (0 != f_follow_links ? stat (namebuf, &hs) : lstat (namebuf, &hs))
 #endif
 #endif
-			{
-				msg_perror("can't stat %s",namebuf);
-				continue;
-			}
-			if(   (f_local_filesys && device!=hs.st_dev)
-			   || (f_exclude && check_exclude(namebuf)))
-				add_buffer(the_buffer,"N",1);
+	    {
+	      msg_perror ("can't stat %s", namebuf);
+	      continue;
+	    }
+	  if ((f_local_filesys && device != hs.st_dev)
+	      || (f_exclude && check_exclude (namebuf)))
+	    add_buffer (the_buffer, "N", 1);
 #ifdef AIX
 #ifdef AIX
-			else if (S_ISHIDDEN (hs.st_mode)) {
-				add_buffer (the_buffer, "D", 1);
-				strcat (d->d_name, "A");
-				d->d_namlen++;
-			}	
+	  else if (S_ISHIDDEN (hs.st_mode))
+	    {
+	      add_buffer (the_buffer, "D", 1);
+	      strcat (d->d_name, "A");
+	      d->d_namlen++;
+	    }
 #endif /* AIX */
 #endif /* AIX */
-			else if(S_ISDIR(hs.st_mode)) {
-				if(dp=get_dir(namebuf)) {
-					if(   dp->dev!=hs.st_dev
- 					   || dp->ino!=hs.st_ino) {
-					   	if(f_verbose)
-							msg("directory %s has been renamed.",namebuf);
-						dp->allnew=1;
-						dp->dev=hs.st_dev;
-						dp->ino=hs.st_ino;
-					}
-					dp->dir_text="";
-				} else {
-					if(f_verbose)
-						msg("Directory %s is new",namebuf);
-					add_dir(namebuf,hs.st_dev,hs.st_ino,"");
-					dp=get_dir(namebuf);
-					dp->allnew=1;
-				}
-				if(all_children)
-					dp->allnew=1;
-
-				add_buffer(the_buffer,"D",1);
-			} else if(   !all_children
-   				&& f_new_files
- 				&& new_time>hs.st_mtime
-				&& (   f_new_files>1
- 				    || new_time>hs.st_ctime))
-				add_buffer(the_buffer,"N",1);
-			else
-				add_buffer(the_buffer,"Y",1);
-			add_buffer(the_buffer,d->d_name,(int)(DP_NAMELEN(d)+1));
+	  else if (S_ISDIR (hs.st_mode))
+	    {
+	      if (dp = get_dir (namebuf))
+		{
+		  if (dp->dev != hs.st_dev
+		      || dp->ino != hs.st_ino)
+		    {
+		      if (f_verbose)
+			msg ("directory %s has been renamed.", namebuf);
+		      dp->allnew = 1;
+		      dp->dev = hs.st_dev;
+		      dp->ino = hs.st_ino;
+		    }
+		  dp->dir_text = "";
 		}
 		}
-		add_buffer(the_buffer,"\000\000",2);
-		closedir(dirp);
-
-		/* Well, we've read in the contents of the dir, now sort them */
-		buf=get_buffer(the_buffer);
-		if(buf[0]=='\0') {
-			flush_buffer(the_buffer);
-			new_buf=NULL;
-		} else {
-			n_strs=0;
-			for(p_buf=buf;*p_buf;) {
-				int tmp;
-
-				tmp=strlen(p_buf)+1;
-				n_strs++;
-				p_buf+=tmp;
-			}
-			vec=(char **)malloc(sizeof(char *)*(n_strs+1));
-			for(p_vec=vec,p_buf=buf;*p_buf;p_buf+=strlen(p_buf)+1)
-				*p_vec++= p_buf;
-			*p_vec= 0;
-			qsort((PTR)vec,n_strs,sizeof(char *),dirent_cmp);
-			new_buf=(char *)malloc(p_buf-buf+2);
-			for(p_vec=vec,p_buf=new_buf;*p_vec;p_vec++) {
-				char *p_tmp;
-
-				for(p_tmp= *p_vec;*p_buf++= *p_tmp++;)
-					;
-			}
-			*p_buf++='\0';
-			free(vec);
-			flush_buffer(the_buffer);
+	      else
+		{
+		  if (f_verbose)
+		    msg ("Directory %s is new", namebuf);
+		  add_dir (namebuf, hs.st_dev, hs.st_ino, "");
+		  dp = get_dir (namebuf);
+		  dp->allnew = 1;
 		}
 		}
+	      if (all_children)
+		dp->allnew = 1;
+
+	      add_buffer (the_buffer, "D", 1);
+	    }
+	  else if (!all_children
+		   && f_new_files
+		   && new_time > hs.st_mtime
+		   && (f_new_files > 1
+		       || new_time > hs.st_ctime))
+	    add_buffer (the_buffer, "N", 1);
+	  else
+	    add_buffer (the_buffer, "Y", 1);
+	  add_buffer (the_buffer, d->d_name, (int) (DP_NAMELEN (d) + 1));
+	}
+      add_buffer (the_buffer, "\000\000", 2);
+      closedir (dirp);
+
+      /* Well, we've read in the contents of the dir, now sort them */
+      buf = get_buffer (the_buffer);
+      if (buf[0] == '\0')
+	{
+	  flush_buffer (the_buffer);
+	  new_buf = NULL;
 	}
 	}
-	free(namebuf);
-	return new_buf;
+      else
+	{
+	  n_strs = 0;
+	  for (p_buf = buf; *p_buf;)
+	    {
+	      int tmp;
+
+	      tmp = strlen (p_buf) + 1;
+	      n_strs++;
+	      p_buf += tmp;
+	    }
+	  vec = (char **) malloc (sizeof (char *) * (n_strs + 1));
+	  for (p_vec = vec, p_buf = buf; *p_buf; p_buf += strlen (p_buf) + 1)
+	    *p_vec++ = p_buf;
+	  *p_vec = 0;
+	  qsort ((PTR) vec, n_strs, sizeof (char *), dirent_cmp);
+	  new_buf = (char *) malloc (p_buf - buf + 2);
+	  for (p_vec = vec, p_buf = new_buf; *p_vec; p_vec++)
+	    {
+	      char *p_tmp;
+
+	      for (p_tmp = *p_vec; *p_buf++ = *p_tmp++;)
+		;
+	    }
+	  *p_buf++ = '\0';
+	  free (vec);
+	  flush_buffer (the_buffer);
+	}
+    }
+  free (namebuf);
+  return new_buf;
 }
 }
 
 
 /* p is a directory.  Add all the files in P to the namelist.  If any of the
 /* p is a directory.  Add all the files in P to the namelist.  If any of the
    files is a directory, recurse on the subdirectory. . . */
    files is a directory, recurse on the subdirectory. . . */
 static void
 static void
-add_dir_name(p,device)
-char *p;
-int device;
+add_dir_name (p, device)
+     char *p;
+     int device;
 {
 {
-	char *new_buf;
-	char *p_buf;
+  char *new_buf;
+  char *p_buf;
 
 
-	char *namebuf;
-	int buflen;
-	register int len;
-	int sublen;
+  char *namebuf;
+  int buflen;
+  register int len;
+  int sublen;
 
 
-/*	PTR the_buffer;*/
+  /*	PTR the_buffer;*/
 
 
-/*	char *buf;*/
-/*	char **vec,**p_vec;*/
-/*	int n_strs,n_size;*/
+  /*	char *buf;*/
+  /*	char **vec,**p_vec;*/
+  /*	int n_strs,n_size;*/
 
 
-	struct name *n;
+  struct name *n;
 
 
-	int dirent_cmp();
+  int dirent_cmp ();
 
 
-	new_buf=get_dir_contents(p,device);
+  new_buf = get_dir_contents (p, device);
 
 
-	for(n=namelist;n;n=n->next) {
-		if(!strcmp(n->name,p)) {
-		  	n->dir_contents = new_buf ? new_buf : "\0\0\0\0";
-			break;
-		}
+  for (n = namelist; n; n = n->next)
+    {
+      if (!strcmp (n->name, p))
+	{
+	  n->dir_contents = new_buf ? new_buf : "\0\0\0\0";
+	  break;
 	}
 	}
-
-	if (new_buf)
-	  {
-	    len=strlen(p);
-	    buflen= NAMSIZ<=len ? len + NAMSIZ : NAMSIZ;
-	    namebuf= ck_malloc(buflen+1);
-
-	    (void)strcpy(namebuf,p);
-	    if(namebuf[len-1]!='/') {
-	      namebuf[len++]='/';
-	      namebuf[len]='\0';
-	    }
-	    for(p_buf=new_buf;*p_buf;p_buf+=sublen+1) {
-	      sublen=strlen(p_buf);
-	      if(*p_buf=='D') {
-		if(len+sublen>=buflen) {
-		  buflen+=NAMSIZ;
-		  namebuf= ck_realloc(namebuf,buflen+1);
+    }
+
+  if (new_buf)
+    {
+      len = strlen (p);
+      buflen = NAMSIZ <= len ? len + NAMSIZ : NAMSIZ;
+      namebuf = ck_malloc (buflen + 1);
+
+      (void) strcpy (namebuf, p);
+      if (namebuf[len - 1] != '/')
+	{
+	  namebuf[len++] = '/';
+	  namebuf[len] = '\0';
+	}
+      for (p_buf = new_buf; *p_buf; p_buf += sublen + 1)
+	{
+	  sublen = strlen (p_buf);
+	  if (*p_buf == 'D')
+	    {
+	      if (len + sublen >= buflen)
+		{
+		  buflen += NAMSIZ;
+		  namebuf = ck_realloc (namebuf, buflen + 1);
 		}
 		}
-		(void)strcpy(namebuf+len,p_buf+1);
-		addname(namebuf);
-		add_dir_name(namebuf,device);
-	      }
+	      (void) strcpy (namebuf + len, p_buf + 1);
+	      addname (namebuf);
+	      add_dir_name (namebuf, device);
 	    }
 	    }
-	    free(namebuf);
-	  }
+	}
+      free (namebuf);
+    }
 }
 }
 
 
 /* Returns non-zero if p is . or ..   This could be a macro for speed. */
 /* Returns non-zero if p is . or ..   This could be a macro for speed. */
 int
 int
-is_dot_or_dotdot(p)
-char *p;
+is_dot_or_dotdot (p)
+     char *p;
 {
 {
-	return (p[0]=='.' && (p[1]=='\0' || (p[1]=='.' && p[2]=='\0')));
+  return (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')));
 }
 }
 
 
 
 
@@ -517,129 +559,141 @@ char *p;
 
 
 
 
 void
 void
-gnu_restore(skipcrud)
-int skipcrud;
+gnu_restore (skipcrud)
+     int skipcrud;
 {
 {
-	char *current_dir;
-/*	int current_dir_length; */
-
-	char *archive_dir;
-/*	int archive_dir_length; */
-	PTR the_buffer;
-	char	*p;
-	DIR	*dirp;
-	struct direct *d;
-	char *cur,*arc;
-	extern struct stat hstat;		/* Stat struct corresponding */
-	long size,copied;
-	char *from,*to;
-	extern union record *head;
-
-	dirp=opendir(skipcrud+current_file_name);
-
-	if(!dirp) {
-			/* The directory doesn't exist now.  It'll be created.
+  char *current_dir;
+  /*	int current_dir_length; */
+
+  char *archive_dir;
+  /*	int archive_dir_length; */
+  PTR the_buffer;
+  char *p;
+  DIR *dirp;
+  struct direct *d;
+  char *cur, *arc;
+  extern struct stat hstat;	/* Stat struct corresponding */
+  long size, copied;
+  char *from, *to;
+  extern union record *head;
+
+  dirp = opendir (skipcrud + current_file_name);
+
+  if (!dirp)
+    {
+      /* The directory doesn't exist now.  It'll be created.
 			   In any case, we don't have to delete any files out
 			   In any case, we don't have to delete any files out
 			   of it */
 			   of it */
-		skip_file((long)hstat.st_size);
-		return;
-	}
-
-	the_buffer=init_buffer();
-	while(d=readdir(dirp)) {
-		if(is_dot_or_dotdot(d->d_name))
-			continue;
-
-		add_buffer(the_buffer,d->d_name,(int)(DP_NAMELEN(d)+1));
+      skip_file ((long) hstat.st_size);
+      return;
+    }
+
+  the_buffer = init_buffer ();
+  while (d = readdir (dirp))
+    {
+      if (is_dot_or_dotdot (d->d_name))
+	continue;
+
+      add_buffer (the_buffer, d->d_name, (int) (DP_NAMELEN (d) + 1));
+    }
+  closedir (dirp);
+  add_buffer (the_buffer, "", 1);
+
+  current_dir = get_buffer (the_buffer);
+  archive_dir = (char *) malloc (hstat.st_size);
+  if (archive_dir == 0)
+    {
+      msg ("Can't allocate %d bytes for restore", hstat.st_size);
+      skip_file ((long) hstat.st_size);
+      return;
+    }
+  to = archive_dir;
+  for (size = hstat.st_size; size > 0; size -= copied)
+    {
+      from = findrec ()->charptr;
+      if (!from)
+	{
+	  msg ("Unexpected EOF in archive\n");
+	  break;
 	}
 	}
-	closedir(dirp);
-	add_buffer(the_buffer,"",1);
-
-	current_dir=get_buffer(the_buffer);
-	archive_dir=(char *)malloc(hstat.st_size);
-	if(archive_dir==0) {
-		msg("Can't allocate %d bytes for restore",hstat.st_size);
-		skip_file((long)hstat.st_size);
-		return;
+      copied = endofrecs ()->charptr - from;
+      if (copied > size)
+	copied = size;
+      bcopy ((PTR) from, (PTR) to, (int) copied);
+      to += copied;
+      userec ((union record *) (from + copied - 1));
+    }
+
+  for (cur = current_dir; *cur; cur += strlen (cur) + 1)
+    {
+      for (arc = archive_dir; *arc; arc += strlen (arc) + 1)
+	{
+	  arc++;
+	  if (!strcmp (arc, cur))
+	    break;
 	}
 	}
-	to=archive_dir;
-	for(size=hstat.st_size;size>0;size-=copied) {
-		from=findrec()->charptr;
-		if(!from) {
-			msg("Unexpected EOF in archive\n");
-			break;
-		}
-		copied=endofrecs()->charptr - from;
-		if(copied>size)
-			copied=size;
-		bcopy((PTR)from,(PTR)to,(int)copied);
-		to+=copied;
-		userec((union record *)(from+copied-1));
+      if (*arc == '\0')
+	{
+	  p = new_name (skipcrud + current_file_name, cur);
+	  if (f_confirm && !confirm ("delete", p))
+	    {
+	      free (p);
+	      continue;
+	    }
+	  if (f_verbose)
+	    fprintf (msg_file, "%s: deleting %s\n", tar, p);
+	  if (recursively_delete (p))
+	    {
+	      msg ("%s: Error while deleting %s\n", tar, p);
+	    }
+	  free (p);
 	}
 	}
 
 
-	for(cur=current_dir;*cur;cur+=strlen(cur)+1) {
-		for(arc=archive_dir;*arc;arc+=strlen(arc)+1) {
-			arc++;
-			if(!strcmp(arc,cur))
-				break;
-		}
-		if(*arc=='\0') {
-			p=new_name(skipcrud+current_file_name,cur);
-			if(f_confirm && !confirm("delete",p)) {
-				free(p);
-				continue;
-			}
-			if(f_verbose)
-				fprintf(msg_file,"%s: deleting %s\n",tar,p);
-			if(recursively_delete(p)) {
-				msg("%s: Error while deleting %s\n",tar,p);
-			}
-			free(p);
-		}
-
-	}
-	flush_buffer(the_buffer);
-	free(archive_dir);
+    }
+  flush_buffer (the_buffer);
+  free (archive_dir);
 }
 }
 
 
 int
 int
-recursively_delete(path)
-char *path;
+recursively_delete (path)
+     char *path;
 {
 {
-	struct stat sbuf;
-	DIR *dirp;
-	struct direct *dp;
-	char *path_buf;
-	/* int path_len; */
-
-
-	if(lstat(path,&sbuf)<0)
-		return 1;
-	if(S_ISDIR(sbuf.st_mode)) {
-
-		/* path_len=strlen(path); */
-		dirp=opendir(path);
-		if(dirp==0)
-			return 1;
-		while(dp=readdir(dirp)) {
-			if(is_dot_or_dotdot(dp->d_name))
-				continue;
-			path_buf=new_name(path,dp->d_name);
-			if(recursively_delete(path_buf)) {
-				free(path_buf);
-				closedir(dirp);
-				return 1;
-			}
-			free(path_buf);
-		}
-		closedir(dirp);
-
-		if(rmdir(path)<0)
-			return 1;
-		return 0;
+  struct stat sbuf;
+  DIR *dirp;
+  struct direct *dp;
+  char *path_buf;
+  /* int path_len; */
+
+
+  if (lstat (path, &sbuf) < 0)
+    return 1;
+  if (S_ISDIR (sbuf.st_mode))
+    {
+
+      /* path_len=strlen(path); */
+      dirp = opendir (path);
+      if (dirp == 0)
+	return 1;
+      while (dp = readdir (dirp))
+	{
+	  if (is_dot_or_dotdot (dp->d_name))
+	    continue;
+	  path_buf = new_name (path, dp->d_name);
+	  if (recursively_delete (path_buf))
+	    {
+	      free (path_buf);
+	      closedir (dirp);
+	      return 1;
+	    }
+	  free (path_buf);
 	}
 	}
-	if(unlink(path)<0)
-		return 1;
-	return 0;
+      closedir (dirp);
+
+      if (rmdir (path) < 0)
+	return 1;
+      return 0;
+    }
+  if (unlink (path) < 0)
+    return 1;
+  return 0;
 }
 }
-

+ 284 - 0
src/tar.h

@@ -0,0 +1,284 @@
+/* Declarations for tar archives.
+   Copyright (C) 1988, 1992 Free Software Foundation
+
+This file is part of GNU Tar.
+
+GNU Tar is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Tar is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Tar; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "testpad.h"
+
+/* major() and minor() macros (among other things) defined here for hpux */
+#ifdef hpux
+#include <sys/mknod.h>
+#endif
+
+/*
+ * Kludge for handling systems that can't cope with multiple
+ * external definitions of a variable.  In ONE routine (tar.c),
+ * we #define TAR_EXTERN to null; here, we set it to "extern" if
+ * it is not already set.
+ */
+#ifndef TAR_EXTERN
+#define TAR_EXTERN extern
+#endif
+
+/*
+ * Header block on tape.
+ *
+ * I'm going to use traditional DP naming conventions here.
+ * A "block" is a big chunk of stuff that we do I/O on.
+ * A "record" is a piece of info that we care about.
+ * Typically many "record"s fit into a "block".
+ */
+#define	RECORDSIZE	512
+#define	NAMSIZ		100
+#define	TUNMLEN		32
+#define	TGNMLEN		32
+#define SPARSE_EXT_HDR  21
+#define SPARSE_IN_HDR	4
+
+struct sparse {
+	char offset[12];
+	char numbytes[12];
+};
+
+struct sp_array {
+	int offset;
+	int numbytes;
+};
+
+union record {
+	char		charptr[RECORDSIZE];
+	struct header {
+		char	name[NAMSIZ];
+		char	mode[8];
+		char	uid[8];
+		char	gid[8];
+		char	size[12];
+		char	mtime[12];
+		char	chksum[8];
+		char	linkflag;
+		char	linkname[NAMSIZ];
+		char	magic[8];
+		char	uname[TUNMLEN];
+		char	gname[TGNMLEN];
+		char	devmajor[8];
+		char	devminor[8];
+		/* these following fields were added by JF for gnu */
+		/* and are NOT standard */
+		char	atime[12];
+		char	ctime[12];
+		char	offset[12];
+		char	longnames[4];
+#ifdef NEEDPAD
+		char    pad;
+#endif
+		struct	sparse sp[SPARSE_IN_HDR];
+		char	isextended;
+		char	realsize[12];		/* true size of the sparse file */
+/*		char	ending_blanks[12];*/	/* number of nulls at the
+						   end of the file, if any */
+	} header;
+	struct extended_header {
+		struct sparse sp[21];
+		char isextended;
+	} ext_hdr;
+};
+
+/* The checksum field is filled with this while the checksum is computed. */
+#define	CHKBLANKS	"        "	/* 8 blanks, no null */
+
+/* The magic field is filled with this if uname and gname are valid. */
+#define	TMAGIC		"ustar  "	/* 7 chars and a null */
+
+/* The linkflag defines the type of file */
+#define	LF_OLDNORMAL	'\0'		/* Normal disk file, Unix compat */
+#define	LF_NORMAL	'0'		/* Normal disk file */
+#define	LF_LINK		'1'		/* Link to previously dumped file */
+#define	LF_SYMLINK	'2'		/* Symbolic link */
+#define	LF_CHR		'3'		/* Character special file */
+#define	LF_BLK		'4'		/* Block special file */
+#define	LF_DIR		'5'		/* Directory */
+#define	LF_FIFO		'6'		/* FIFO special file */
+#define	LF_CONTIG	'7'		/* Contiguous file */
+/* Further link types may be defined later. */
+
+/* Note that the standards committee allows only capital A through
+   capital Z for user-defined expansion.  This means that defining something
+   as, say '8' is a *bad* idea. */
+#define LF_DUMPDIR	'D'		/* This is a dir entry that contains
+					   the names of files that were in
+					   the dir at the time the dump
+					   was made */
+#define LF_MULTIVOL	'M'		/* This is the continuation
+					   of a file that began on another
+					   volume */
+#define LF_NAMES	'N'		/* For storing filenames that didn't
+					   fit in 100 characters */
+#define LF_SPARSE	'S'		/* This is for sparse files */
+#define LF_VOLHDR	'V'		/* This file is a tape/volume header */
+					/* Ignore it on extraction */
+
+/*
+ * Exit codes from the "tar" program
+ */
+#define	EX_SUCCESS	0		/* success! */
+#define	EX_ARGSBAD	1		/* invalid args */
+#define	EX_BADFILE	2		/* invalid filename */
+#define	EX_BADARCH	3		/* bad archive */
+#define	EX_SYSTEM	4		/* system gave unexpected error */
+#define EX_BADVOL	5		/* Special error code means
+					   Tape volume doesn't match the one
+					   specified on the command line */
+
+/*
+ * Global variables
+ */
+TAR_EXTERN union record	*ar_block;	/* Start of block of archive */
+TAR_EXTERN union record	*ar_record;	/* Current record of archive */
+TAR_EXTERN union record	*ar_last;	/* Last+1 record of archive block */
+TAR_EXTERN char		ar_reading;	/* 0 writing, !0 reading archive */
+TAR_EXTERN int		blocking;	/* Size of each block, in records */
+TAR_EXTERN int		blocksize;	/* Size of each block, in bytes */
+TAR_EXTERN char		*ar_file;	/* File containing archive */
+TAR_EXTERN char		*info_script;	/* Script to run at end of each tape change */
+TAR_EXTERN char		*name_file;	/* File containing names to work on */
+TAR_EXTERN char		filename_terminator; /* \n or \0. */
+TAR_EXTERN char		*tar;		/* Name of this program */
+TAR_EXTERN struct sp_array *sparsearray;/* Pointer to the start of the scratch space */
+TAR_EXTERN int		sp_array_size;	/* Initial size of the sparsearray */
+TAR_EXTERN int 		tot_written;    /* Total written to output */
+TAR_EXTERN struct re_pattern_buffer
+  			*label_pattern;	/* compiled regex for extract label */
+
+/*
+ * Flags from the command line
+ */
+TAR_EXTERN int cmd_mode;
+#define CMD_NONE	0
+#define CMD_CAT		1		/* -A */
+#define CMD_CREATE	2		/* -c */
+#define CMD_DIFF	3		/* -d */
+#define CMD_APPEND	4		/* -r */
+#define CMD_LIST	5		/* -t */
+#define CMD_UPDATE	6		/* -u */
+#define CMD_EXTRACT	7		/* -x */
+#define CMD_DELETE	8		/* -D */
+#define CMD_VERSION	9		/* --version */
+
+					/* -[0-9][lmh] */
+			/* CMD_CAT	   -A */
+					/* -b */
+TAR_EXTERN int	f_reblock;		/* -B */
+			/* CMD_CREATE	   -c */
+					/* -C */
+			/* CMD_DIFF	   -d */
+#if 0
+TAR_EXTERN char	f_dironly;		/* -D */
+#endif
+					/* -f */
+TAR_EXTERN int	f_run_script_at_end;	/* -F */
+TAR_EXTERN int 	f_gnudump;		/* -G */
+TAR_EXTERN int	f_follow_links;		/* -h */
+TAR_EXTERN int	f_ignorez;		/* -i */
+			/* CMD_DELETE	   -J */
+TAR_EXTERN int	f_keep;			/* -k */
+TAR_EXTERN int	f_startfile;		/* -K */
+TAR_EXTERN int	f_local_filesys;	/* -l */
+TAR_EXTERN int  tape_length;		/* -L */
+TAR_EXTERN int	f_modified;		/* -m */
+TAR_EXTERN int 	f_multivol;		/* -M */
+TAR_EXTERN int	f_new_files;		/* -N */
+TAR_EXTERN int	f_oldarch;		/* -o */
+TAR_EXTERN int  f_exstdout;		/* -O */
+TAR_EXTERN int	f_use_protection;	/* -p */
+TAR_EXTERN int  f_absolute_paths;	/* -P */
+TAR_EXTERN int	f_sayblock;		/* -R */
+TAR_EXTERN int	f_sorted_names;		/* -s */
+TAR_EXTERN int	f_sparse_files;		/* -S  ... JK */
+TAR_EXTERN int	f_namefile;		/* -T */
+			/* CMD_UPDATE	   -u */
+TAR_EXTERN int	f_verbose;		/* -v */
+TAR_EXTERN char *f_volhdr;		/* -V */
+TAR_EXTERN int  f_confirm;		/* -w */
+TAR_EXTERN int  f_verify;		/* -W */
+			/* CMD_EXTRACT     -x */
+TAR_EXTERN int  f_exclude;		/* -X */
+TAR_EXTERN int 	f_compress;		/* -z */
+					/* -Z */
+TAR_EXTERN int	f_do_chown;		/* --do-chown */
+TAR_EXTERN int  f_totals;		/* --totals */
+TAR_EXTERN int	f_remove_files;		/* --remove-files */
+TAR_EXTERN int	f_ignore_failed_read;	/* --ignore-failed-read */
+TAR_EXTERN int	f_checkpoint;		/* --checkpoint */
+TAR_EXTERN int	f_show_omitted_dirs;	/* --show-omitted-dirs */
+TAR_EXTERN char *f_volno_file;		/* --volno-file */
+
+/*
+ * We default to Unix Standard format rather than 4.2BSD tar format.
+ * The code can actually produce all three:
+ *	f_standard	ANSI standard
+ *	f_oldarch	V7
+ *	neither		4.2BSD
+ * but we don't bother, since 4.2BSD can read ANSI standard format anyway.
+ * The only advantage to the "neither" option is that we can cmp our
+ * output to the output of 4.2BSD tar, for debugging.
+ */
+#define		f_standard		(!f_oldarch)
+
+/*
+ * Structure for keeping track of filenames and lists thereof.
+ */
+struct name {
+	struct name	*next;
+	short		length;		/* cached strlen(name) */
+	char		found;		/* A matching file has been found */
+	char		firstch;	/* First char is literally matched */
+	char		regexp;		/* This name is a regexp, not literal */
+	char		*change_dir;	/* JF set with the -C option */
+	char		*dir_contents;	/* JF for f_gnudump */
+	char		fake;		/* dummy entry */
+	char		name[1];
+};
+
+TAR_EXTERN struct name	*namelist;	/* Points to first name in list */
+TAR_EXTERN struct name	*namelast;	/* Points to last name in list */
+
+TAR_EXTERN int		archive;	/* File descriptor for archive file */
+TAR_EXTERN int		errors;		/* # of files in error */
+
+TAR_EXTERN char *gnu_dumpfile;
+
+/*
+ * Error recovery stuff
+ */
+TAR_EXTERN char		read_error_flag;
+
+
+/*
+ * Declarations of functions available to the world.
+ */
+union record *findrec();
+void userec();
+union record *endofrecs();
+void anno();
+
+#if !defined (VPRINTF_MISSING) && defined (__STDC__)
+void msg(char *, ...);
+void msg_perror(char *, ...);
+#else
+void msg();
+void msg_perror();
+#endif