]> Dogcows Code - chaz/tar/commitdiff
*** empty log message ***
authorFrançois Pinard <pinard@iro.umontreal.ca>
Wed, 16 Nov 1994 02:48:44 +0000 (02:48 +0000)
committerFrançois Pinard <pinard@iro.umontreal.ca>
Wed, 16 Nov 1994 02:48:44 +0000 (02:48 +0000)
scripts/level-0
scripts/level-1
src/gnu.c [new file with mode: 0644]

index 4e1ffe4d781f5cf5c1ac085b54b2b7ae1975c953..a693ef75e4ef1a45d5531491d065aeeb85540c42 100644 (file)
@@ -86,7 +86,7 @@ LOGFILE="log-`date | sed -ne '
 
 localhost="`hostname | sed -e 's/\..*//'`"
 
-TAR_PART1="/usr/local/bin/tar -c --multi-volume --one-file-system --block=${BLOCKING} --sparse --volno-file=${VOLNO_FILE}"
+TAR_PART1="${TAR} -c --multi-volume --one-file-system --block=${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
index 474e36f8641bd150f683c1a568e7af13e93eda42..d3bc385398dbfe8d5fd3274b9d121033a99e0b48 100644 (file)
@@ -21,11 +21,11 @@ fi
 
 # Maybe sleep until around specified or default hour.
 #
-if [ "$1" != "now" ]; then
-   if [ "$1"x != x ]; then
-      spec=$1
+if [ "${1}" != "now" ]; then
+   if [ "${1}"x != x ]; then
+      spec=${1}
    else
-      spec=$BACKUP_HOUR
+      spec=${BACKUP_HOUR}
    fi
    pausetime=`date | awk '{hr=substr($4,1,2);\\
       mn=substr($4,4,2);\\
@@ -35,7 +35,7 @@ if [ "$1" != "now" ]; then
          print 3600*(spec+(24-hr))-60*mn; }' spec=$spec`
    clear
    cat ./dont_touch
-   sleep $pausetime
+   sleep ${pausetime}
 fi
 
 # start doing things
@@ -43,105 +43,118 @@ fi
 here=`pwd`
 LOGFILE=log-`date | awk '{print $2 "-" $3 "-" $6}'`-level-1
 HOST=`hostname | sed 's/\..*//'`
-TAR_PART1="/usr/local/bin/tar -c --multi-volume --one-file-system --block=$BLOCKING --sparse --volno-file=$VOLNO_FILE"
+TAR_PART1="/usr/local/bin/tar -c --multi-volume --one-file-system --block=${BLOCKING} --sparse --volno-file=${VOLNO_FILE}"
+
+# Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
+if [ x != "x${DUMP_REMIND_SCRIPT}" ]; then
+   TAR_PART1="${TAR_PART1} --info-script=${DUMP_REMIND_SCRIPT}"
+fi
 
 # Make sure the log file did not already exist.  Create it.
 
-if [ -f $LOGFILE ] ; then
-   echo Log file $LOGFILE already exists.
+if [ -f ${LOGFILE} ] ; then
+   echo Log file ${LOGFILE} already exists.
    exit 1
 else
-   touch $LOGFILE
+   touch ${LOGFILE}
 fi
 
-mt -f $TAPE_FILE rewind
-rm $VOLNO_FILE
+mt -f ${TAPE_FILE} rewind
+rm ${VOLNO_FILE}
 
-set $BACKUP_DIRS
+set ${BACKUP_DIRS}
 while [ $# -ne 0 ] ; do
-   host=`echo $1 | sed 's/:.*$//'`
-   fs=`echo $1 | sed 's/^.*://'`
+   host=`echo ${1} | sed 's/:.*$//'`
+   fs=`echo ${1} | sed 's/^.*://'`
    date=`date`
-   fsname=`echo $1 | sed 's/\//:/g'`
+   fsname=`echo ${1} | sed 's/\//:/g'`
 
 # This filename must be absolute; it is opened on the machine that runs tar.
    TAR_PART2="--listed=/etc/tar-backup/temp.level-1"
-   TAR_PART3="--label='level 1 backup of $fs on $host at $date' -C $fs ."
+   TAR_PART3="--label='level 1 backup of ${fs} on ${host} at ${date}' -C ${fs} ."
 
-   echo Backing up $1 at $date | tee -a $LOGFILE
-   echo Last full dump on this filesystem: | tee -a $LOGFILE
+   echo Backing up ${1} at ${date} | tee -a ${LOGFILE}
+   echo Last full dump on this filesystem: | tee -a ${LOGFILE}
 
-   if [ $HOST != $host ] ; then
-     rsh $host "ls -l /etc/tar-backup/$fsname.level-0; \
-       cp /etc/tar-backup/$fsname.level-0 /etc/tar-backup/temp.level-1" \
-       2>&1 | tee -a $LOGFILE
+   if [ ${HOST} != ${host} ] ; then
+     rsh ${host} "ls -l /etc/tar-backup/${fsname}.level-0; \
+       cp /etc/tar-backup/${fsname}.level-0 /etc/tar-backup/temp.level-1" \
+       2>&1 | tee -a ${LOGFILE}
    else
-     ls -l /etc/tar-backup/$fsname.level-0 2>&1 | tee -a $LOGFILE
-     cp /etc/tar-backup/$fsname.level-0 /etc/tar-backup/temp.level-1 2>&1 | tee -a $LOGFILE
+     ls -l /etc/tar-backup/${fsname}.level-0 2>&1 | tee -a ${LOGFILE}
+     cp /etc/tar-backup/${fsname}.level-0 /etc/tar-backup/temp.level-1 2>&1 | tee -a ${LOGFILE}
    fi
 
    # Actually back things up.
 
-   if [ $HOST != $host ] ; then
-      rsh $host $TAR_PART1 -f $HOST:$TAPE_FILE $TAR_PART2 $TAR_PART3 2>&1 | tee -a $LOGFILE
+   if [ ${HOST} != ${host} ] ; then
+      rsh ${host} ${TAR_PART1} -f ${HOST}:${TAPE_FILE} ${TAR_PART2} ${TAR_PART3} 2>&1 | tee -a ${LOGFILE}
    else
 # Using `sh -c exec' causes nested quoting and shell substitution
 # to be handled here in the same way rsh handles it.
-      sh -c "exec $TAR_PART1 -f $TAPE_FILE $TAR_PART2 $TAR_PART3" 2>&1 | tee -a $LOGFILE
+      sh -c "exec ${TAR_PART1} -f ${TAPE_FILE} ${TAR_PART2} ${TAR_PART3}" 2>&1 | tee -a ${LOGFILE}
    fi
+   # This doesn't presently work, of course, because $? is set to the exit
+   # status of the last thing in the pipeline of the previous command,
+   # namely `tee'.  We really want the exit status of the sh command
+   # running tar, but getting this seems to be nontrivial.  --friedman
    if [ $? -ne 0 ] ; then
-      echo Backup of $1 failed. | tee -a $LOGFILE
+      echo Backup of ${1} failed. | tee -a ${LOGFILE}
       # I'm assuming that the tar will have written an empty
       # file to the tape, otherwise I should do a cat here.
    else
-      if [ $HOST != $host ] ; then
-       rsh $host mv -f /etc/tar-backup/temp.level-1 /etc/tar-backup/$fsname.level-1 2>&1 | tee -a $LOGFILE
+      if [ ${HOST} != ${host} ] ; then
+       rsh ${host} mv -f /etc/tar-backup/temp.level-1 /etc/tar-backup/${fsname}.level-1 2>&1 | tee -a ${LOGFILE}
       else
-        mv -f /etc/tar-backup/temp.level-1 /etc/tar-backup/$fsname.level-1 2>&1 | tee -a $LOGFILE
+        mv -f /etc/tar-backup/temp.level-1 /etc/tar-backup/${fsname}.level-1 2>&1 | tee -a ${LOGFILE}
       fi
    fi
-   $TAPE_STATUS  | tee -a $LOGFILE
+   ${TAPE_STATUS}  | tee -a ${LOGFILE}
    sleep 60
    shift
 done
 
 # Dump any individual files requested.
 
-if [ x != "x$BACKUP_FILES" ] ; then
+if [ x != "x${BACKUP_FILES}" ] ; then
    date=`date`
    TAR_PART2="--listed=/etc/tar-backup/temp.level-1"
-   TAR_PART3="--label='Incremental backup of miscellaneous files at $date'"
+   TAR_PART3="--label='Incremental backup of miscellaneous files at ${date}'"
 
-   echo Backing up miscellaneous files at $date | tee -a $LOGFILE
-   echo Last full dump of these files: | tee -a $LOGFILE  
-   ls -l /etc/tar-backup/misc.level-0 2>&1 | tee -a $LOGFILE
+   echo Backing up miscellaneous files at ${date} | tee -a ${LOGFILE}
+   echo Last full dump of these files: | tee -a ${LOGFILE}  
+   ls -l /etc/tar-backup/misc.level-0 2>&1 | tee -a ${LOGFILE}
 
-   rm -f /etc/tar-backup/temp.level-1 2>&1 | tee -a $LOGFILE
-   cp /etc/tar-backup/misc.level-0 /etc/tar-backup/temp.level-1 2>&1 | tee -a $LOGFILE
+   rm -f /etc/tar-backup/temp.level-1 2>&1 | tee -a ${LOGFILE}
+   cp /etc/tar-backup/misc.level-0 /etc/tar-backup/temp.level-1 2>&1 | tee -a ${LOGFILE}
 
-   echo Backing up miscellaneous files at $date | tee -a $LOGFILE
+   echo Backing up miscellaneous files at ${date} | tee -a ${LOGFILE}
 # Using `sh -c exec' causes nested quoting and shell substitution
 # to be handled here in the same way rsh handles it.
-   sh -c "exec $TAR_PART1 -f $TAPE_FILE $TAR_PART2 $TAR_PART3 \
-    $BACKUP_FILES" 2>&1 | tee -a $LOGFILE
+   sh -c "exec ${TAR_PART1} -f ${TAPE_FILE} ${TAR_PART2} ${TAR_PART3} \
+    ${BACKUP_FILES}" 2>&1 | tee -a ${LOGFILE}
+   # This doesn't presently work, of course, because $? is set to the exit
+   # status of the last thing in the pipeline of the previous command,
+   # namely `tee'.  We really want the exit status of the sh command
+   # running tar, but getting this seems to be nontrivial.  --friedman
    if [ $? -ne 0 ] ; then
-     echo Backup of miscellaneous files failed. | tee -a $LOGFILE
+     echo Backup of miscellaneous files failed. | tee -a ${LOGFILE}
      # I'm assuming that the tar will have written an empty
      # file to the tape, otherwise I should do a cat here.
    else
-     mv -f /etc/tar-backup/temp.level-1 /etc/tar-backup/misc.level-1 2>&1 | tee -a $LOGFILE
+     mv -f /etc/tar-backup/temp.level-1 /etc/tar-backup/misc.level-1 2>&1 | tee -a ${LOGFILE}
    fi
-   $TAPE_STATUS | tee -a $LOGFILE
+   ${TAPE_STATUS} | tee -a ${LOGFILE}
 else
-   echo No miscellaneous files specified | tee -a $LOGFILE
+   echo No miscellaneous files specified | tee -a ${LOGFILE}
    false
 fi
 
-mt -f $TAPE_FILE rewind
-mt -f $TAPE_FILE offl
+mt -f ${TAPE_FILE} rewind
+mt -f ${TAPE_FILE} offl
 
-echo Sending the dump log to $ADMINISTRATOR
-cat $LOGFILE | sed -f logfile.sed > $LOGFILE.tmp
-/usr/ucb/mail -s "Results of backup on `date`" $ADMINISTRATOR < $LOGFILE.tmp
-rm -f $LOGFILE.tmp
+echo Sending the dump log to ${ADMINISTRATOR}
+cat ${LOGFILE} | sed -f logfile.sed > ${LOGFILE}.tmp
+/usr/ucb/mail -s "Results of backup on `date`" ${ADMINISTRATOR} < ${LOGFILE}.tmp
+rm -f ${LOGFILE}.tmp
 
diff --git a/src/gnu.c b/src/gnu.c
new file mode 100644 (file)
index 0000000..ba4253f
--- /dev/null
+++ b/src/gnu.c
@@ -0,0 +1,644 @@
+/* GNU dump extensions to tar.
+   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 <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#ifndef STDC_HEADERS
+extern int errno;
+#endif
+#include <time.h>
+time_t time();
+
+#include "tar.h"
+#include "port.h"
+
+#if defined(_POSIX_VERSION) || defined(DIRENT)
+#include <dirent.h>
+#ifdef direct
+#undef direct
+#endif /* direct */
+#define direct dirent
+#define DP_NAMELEN(x) strlen((x)->d_name)
+#endif /* _POSIX_VERSION or DIRENT */
+#if !defined(_POSIX_VERSION) && !defined(DIRENT) && defined(BSD42)
+#include <sys/dir.h>
+#define DP_NAMELEN(x)  (x)->d_namlen
+#endif /* not _POSIX_VERSION and BSD42 */
+#ifdef __MSDOS__
+#include "msd_dir.h"
+#define DP_NAMELEN(x)  (x)->d_namlen
+#define direct dirent
+#endif
+#if defined(USG) && !defined(_POSIX_VERSION) && !defined(DIRENT)
+#include <ndir.h>
+#define DP_NAMELEN(x) strlen((x)->d_name)
+#endif /* USG and not _POSIX_VERSION and not DIRENT */
+
+#ifndef S_ISLNK
+#define lstat stat
+#endif
+
+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;
+};
+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;
+{
+       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()
+{
+       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);
+#else
+                       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);
+       }
+       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()
+{
+       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);
+       }
+       fclose(fp);
+}
+
+struct dirname *
+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;
+}
+
+
+/* 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()
+{
+       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))
+#else
+               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);
+               }
+       }
+
+       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(gnu_dumpfile);
+}
+
+int
+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);
+}
+
+int
+dirent_cmp(p1,p2)
+const PTR p1;
+const PTR p2;
+{
+       char *frst,*scnd;
+
+       frst= (*(char **)p1)+1;
+       scnd= (*(char **)p2)+1;
+
+       return strcmp(frst,scnd);
+}
+
+char *
+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);
+#ifdef AIX
+                       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))
+#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);
+#ifdef AIX
+                       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));
+               }
+               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);
+               }
+       }
+       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;
+{
+       char *new_buf;
+       char *p_buf;
+
+       char *namebuf;
+       int buflen;
+       register int len;
+       int sublen;
+
+/*     PTR the_buffer;*/
+
+/*     char *buf;*/
+/*     char **vec,**p_vec;*/
+/*     int n_strs,n_size;*/
+
+       struct name *n;
+
+       int dirent_cmp();
+
+       new_buf=get_dir_contents(p,device);
+
+       for(n=namelist;n;n=n->next) {
+               if(!strcmp(n->name,p)) {
+                       n->dir_contents = new_buf;
+                       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);
+               }
+               (void)strcpy(namebuf+len,p_buf+1);
+               addname(namebuf);
+               add_dir_name(namebuf,device);
+             }
+           }
+           free(namebuf);
+         }
+}
+
+/* Returns non-zero if p is . or ..   This could be a macro for speed. */
+int
+is_dot_or_dotdot(p)
+char *p;
+{
+       return (p[0]=='.' && (p[1]=='\0' || (p[1]=='.' && p[2]=='\0')));
+}
+
+
+
+
+
+
+void
+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+head->header.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));
+       }
+       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;
+               }
+               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;
+               }
+               if(*arc=='\0') {
+                       p=new_name(skipcrud+head->header.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);
+}
+
+int
+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;
+       }
+       if(unlink(path)<0)
+               return 1;
+       return 0;
+}
+
This page took 0.040266 seconds and 4 git commands to generate.