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