From: François Pinard Date: Wed, 16 Nov 1994 02:49:14 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=4ea60be930c2d0350ca297f379fb273d2992ddd9;p=chaz%2Ftar *** empty log message *** --- diff --git a/scripts/level-1 b/scripts/level-1 index 89a79e8..49545ae 100644 --- a/scripts/level-1 +++ b/scripts/level-1 @@ -85,7 +85,7 @@ LOGFILE="log-`date | sed -ne ' 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 if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then diff --git a/src/gnu.c b/src/gnu.c index 806ba1e..7606c0a 100644 --- a/src/gnu.c +++ b/src/gnu.c @@ -25,7 +25,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ extern int errno; #endif #include -time_t time(); +time_t time (); #include "tar.h" #include "port.h" @@ -59,456 +59,498 @@ time_t time(); extern time_t new_time; 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 time_t this_time; 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 -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(!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 - 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 -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 * -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 a directory tree, and put all the directories at the beginning. */ 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 - if (statx (n->name, &statbuf, STATSIZE, STX_HIDDEN|STX_LINK)) + if (statx (n->name, &statbuf, STATSIZE, STX_HIDDEN | STX_LINK)) #else - if(lstat(n->name,&statbuf)<0) + if (lstat (n->name, &statbuf) < 0) #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 -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 -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 * -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 - 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 - if (0 != f_follow_links? stat(namebuf, &hs): lstat(namebuf, &hs)) + if (0 != f_follow_links ? stat (namebuf, &hs) : lstat (namebuf, &hs)) #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 - 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 */ - 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 files is a directory, recurse on the subdirectory. . . */ 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. */ 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 -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 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 -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; } - diff --git a/src/tar.h b/src/tar.h new file mode 100644 index 0000000..e3530c3 --- /dev/null +++ b/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 +#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