[comp.os.minix] comments on backup program recently posted by AST

XBR4D75G%DDATHD21.BITNET@cunyvm.cuny.edu (10/04/89)

I tested the backup-program from Andy Tanenbaum last weekend and
recognized the same deficiencies, Rick Thomas listed in his mail.

Below are the context-diffs to eliminate most of these problems.
I incorporated also, that files already compressed (extension .Z)
do not get compressed for a second time, because the target-file
would get larger than the source-file.

I used the backup-routine successfully to create multiple
360K-floppies for a XT-machine from one 1.2M-floppy on an AT-machine.

Hans-Juegen Knobloch

-------------------------- cut here ----------------------------------
echo x - backup.cdif
sed '/^X/s///' > backup.cdif << '/'
X*** old/backup.c       Fri Sep 29 15:31:12 1989
X--- backup.c   Wed Oct  4 10:39:49 1989
X***************
X*** 20,25 ****
X--- 20,26 ----
X   *   -d  At the top level, only back up directories (not loose files)
X   *   -m  If ENOSPC encountered, ask for another diskette
X   *   -n  No directories, only loose files are backed up
X+  *   -t  set creation date of target-file equal to cdate of source-file
X   *   -v  Verbose (announce what is being done)
X   *   -z  Compress the backed up files
X   *
X***************
X*** 47,58 ****
X  struct sorted {
X    int mode;                          /* file mode */
X    char *namep;                               /* pointer to name in dir_buf */
X    long modtime;                              /* time of last modification */
X  } sorted[MAX_ENTRIES];
X
X  char copybuf[COPY_SIZE];
X
X! unshort dflag, mflag, nflag, rflag, vflag, zflag;
X
X  extern int errno;
X  extern char *environ;
X--- 48,60 ----
X  struct sorted {
X    int mode;                          /* file mode */
X    char *namep;                               /* pointer to name in dir_buf */
X+   long acctime;                              /* time of last access */
X    long modtime;                              /* time of last modification */
X  } sorted[MAX_ENTRIES];
X
X  char copybuf[COPY_SIZE];
X
X! unshort dflag, mflag, nflag, rflag, tflag, vflag, zflag;
X
X  extern int errno;
X  extern char *environ;
X***************
X*** 77,82 ****
X--- 79,85 ----
X                       case 'n':       nflag++;        break;
X                       case 'v':       vflag++;        break;
X                       case 'r':       rflag++;        break;
X+                      case 't':       tflag++;        break;
X                       case 'z':       zflag++;        break;
X                       default :       usage();
X               }
X***************
X*** 190,196 ****
X               continue;
X       }
X       sorted[i].mode = s.st_mode;
X!      sorted[i].modtime = s.st_ctime;
X       sorted[i].namep = dir_buf[i].name;
X    }
X
X--- 193,200 ----
X               continue;
X       }
X       sorted[i].mode = s.st_mode;
X!      sorted[i].acctime = s.st_atime;
X!      sorted[i].modtime = s.st_mtime;
X       sorted[i].namep = dir_buf[i].name;
X    }
X
X***************
X*** 231,237 ****
X   * recursively call the entire program to process the directory.
X   */
X
X!   int er, fmode, res;
X    struct sorted *sp;
X    struct stat s;
X    char cbuf[MAX_PATH];
X--- 235,241 ----
X   * recursively call the entire program to process the directory.
X   */
X
X!   int er, fmode, res, namlen;
X    struct sorted *sp;
X    struct stat s;
X    char cbuf[MAX_PATH];
X***************
X*** 243,252 ****
X               strcpy(cbuf, dir2);
X               strncat(cbuf, "/", 1);
X               strncat(cbuf, sp->namep, NAME_SIZE);
X!              if (zflag) strncat(cbuf, ".Z", 2);
X               er = stat(cbuf, &s);
X               if (er < 0  sp->modtime > s.st_mtime)
X                       res = copy(dir1, sp, cbuf);
X
X               /* Check status of the copy. */
X               if (res == OUT_OF_SPACE) {
X--- 247,259 ----
X               strcpy(cbuf, dir2);
X               strncat(cbuf, "/", 1);
X               strncat(cbuf, sp->namep, NAME_SIZE);
X!              namlen = strlen( sp->namep);
X!              if ( sp->namep[namlen-2] != '.'  sp->namep[namlen-1] != 'Z' )
X!                if (zflag && (namlen<=(NAME_SIZE-2))) strncat(cbuf, ".Z", 2);
X               er = stat(cbuf, &s);
X               if (er < 0  sp->modtime > s.st_mtime)
X                       res = copy(dir1, sp, cbuf);
X+              else res = NONFATAL;
X
X               /* Check status of the copy. */
X               if (res == OUT_OF_SPACE) {
X***************
X*** 294,300 ****
X  {
X  /* Copy a regular file. */
X
X!   int fd1, fd2, nr, nw, res;
X    char cbuf1[MAX_PATH];
X
X    res = 0;
X--- 301,307 ----
X  {
X  /* Copy a regular file. */
X
X!   int fd1, fd2, nr, nw, res, namlen;
X    char cbuf1[MAX_PATH];
X
X    res = 0;
X***************
X*** 307,330 ****
X    fd1 = open(cbuf1, 0);
X    if (fd1 < 0){
X       error(NONFATAL, "cannot open ", cbuf1, "");
X!      return;
X    }
X    fd2 = creat(cbuf2, sp->mode & 07777);
X    if (fd2 < 0) {
X       error(NONFATAL, "cannot create ", cbuf2, "");
X       close(fd1);
X!      return;
X    }
X
X    /* Both files are now open.  Do the copying. */
X!   if (zflag) {
X       close(fd1);
X       close(fd2);
X       res = zcopy(cbuf1, cbuf2);
X       if (res != 0) unlink(cbuf2);    /* if error, get rid of the corpse */
X       if (vflag && res == 0) printf("Backing up %s\n", cbuf1);
X       return(res);
X!   }
X
X    while (1) {
X       nr = read(fd1, copybuf, COPY_SIZE);
X--- 314,340 ----
X    fd1 = open(cbuf1, 0);
X    if (fd1 < 0){
X       error(NONFATAL, "cannot open ", cbuf1, "");
X!      return(res);
X    }
X    fd2 = creat(cbuf2, sp->mode & 07777);
X    if (fd2 < 0) {
X       error(NONFATAL, "cannot create ", cbuf2, "");
X       close(fd1);
X!      return(res);
X    }
X
X    /* Both files are now open.  Do the copying. */
X!   namlen = strlen( sp->namep);
X!   if ( sp->namep[namlen-2] != '.'  sp->namep[namlen-1] != 'Z' )
X!      if (zflag && (namlen<=(NAME_SIZE-2))) {
X       close(fd1);
X       close(fd2);
X       res = zcopy(cbuf1, cbuf2);
X+      if (tflag) utime(cbuf2, (struct utimbuf *) &(sp->acctime));
X       if (res != 0) unlink(cbuf2);    /* if error, get rid of the corpse */
X       if (vflag && res == 0) printf("Backing up %s\n", cbuf1);
X       return(res);
X!      }
X
X    while (1) {
X       nr = read(fd1, copybuf, COPY_SIZE);
X***************
X*** 354,359 ****
X--- 364,370 ----
X    }
X    close(fd1);
X    close(fd2);
X+   if (tflag) utime(cbuf2, (struct utimbuf *) &(sp->acctime));
X    return(res);
X  }
X
X***************
X*** 396,401 ****
X--- 407,413 ----
X    /* Handle directory copy by forking off 'backup' ! */
X    strcpy(fbuf, "-r");
X    if (mflag) strcat(fbuf, "m");
X+   if (tflag) strcat(fbuf, "t");
X    if (vflag) strcat(fbuf, "v");
X    if (zflag) strcat(fbuf, "z");
X    strcpy(d1buf, dir1);
/
-------------------------- cut here ----------------------------------

rbthomas@athos.rutgers.edu (Rick Thomas) (10/09/89)

I downloaded and installed the patches to "backup" that were recently
posted by Hans-Juegen Knobloch.  I have the following comments (don't
say it... you knew I would... right?)

1) The "-t" option is great, but it doesn't go far enough.  I will also
need to add a "-p" option that preserves the file permissions (owner
and group and permissions bits word) for my own usage.  I realize that
this will be of limited usefulness to anyone but the superuser,
because it will inevitably wind up creating a directory and then
giving up the ability to write in that directory!, but for doing
backups as superuser, it will be invaluable.  For that matter, it will
be invaluable for the original intended purpose of "backup" namely
reflecting changes to /dev/ram onto the root image device.

2) Neither Andy nor Hans-Juegen has been careful about dealing with
file names of exactly 14 characters.  They have used strncpy in a way
that indicates that they do not realize that it does not add a
trailing nul character if it copies exactly the maximum number of
characters.  This can lead to file names that are not nul terminated,
and so have garbage trailing.  This is easily fixed, and I will post
the patches soon.  Somewhat harder (so I won't do it myself -- any
volunteers out there?) would be to convert the whole thing to use the
directory access routines.

3) We still need a fix to "compress -c" to make it not care about the
length of the output file name.  Once again, this is easy to do and I
will post a patch soon.

4) Somewhere in the swamps between "XBR4D75G%DDATHD21.BITNET@cunyvm.cuny.edu"
and my machine, a couple of "double-or-bar"s and all of the tabs got
squished out, resulting in a cdif file that required "patch -l" to
apply and even then had one hunk that failed to match.  The places to
put double-or-bars were fairly easy to find, once I realized that was
the problem.  On the other hand, perhaps Hans-Juegen will re-post his
patches in compressed uuencoded format.

5) Multi-floppy backups still have serious problems.  This subject
needs some thought before we barge in with an implementation.  I will
post some of my own thinking on this in another message later on.


Enjoy!

Rick
-- 

Rick Thomas
uucp: {ames, att, harvard}!rutgers!jove.rutgers.edu!rbthomas
internet: rbthomas@JOVE.RUTGERS.EDU
bitnet: rbthomas@zodiac.bitnet
Phone: (201) 932-4301