extern int errno;
#endif
#include <time.h>
-time_t time();
+time_t time ();
#include "tar.h"
#include "port.h"
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')));
}
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;
}
-
--- /dev/null
+/* 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