csu@alembic.ACS.COM (Dave Mack) (06/30/91)
Submitted-by: Dave Mack <csu@alembic.ACS.COM> Posting-number: Volume 20, Issue 74 Archive-name: compress/patch01 Patch-To: compress: Volume 20, Issue 64-65 Environment: UNIX Patch Priority: COSMIC This patch brings the version of compress 4.1 posted to comp.sources.misc up to patchlevel 1. It corrects one severe bug, a number of minor annoyances, and some diagnostic and documentation errors. Please apply it using "patch [-d compress41-source-dir] < patch-file". Dave Mack ----- diff -rc compress.posted/compress.1 compress41/compress.1 *** compress.posted/compress.1 Fri Jun 28 19:07:12 1991 --- compress41/compress.1 Fri Jun 28 19:08:45 1991 *************** *** 51,65 **** while keeping the same ownership modes, access and modification times. If no files are specified, the standard input is compressed to the standard output. ! Compressed files can be restored to their original form using ! .I uncompress ! or ! .I zcat. ! .PP ! The .B \-f ! option will force compression of ! .I name. If .B \-f is not given and --- 51,65 ---- while keeping the same ownership modes, access and modification times. If no files are specified, the standard input is compressed to the standard output. ! .I Compress ! will only attempt to compress regular files. ! In particular, it will ignore symbolic links. If a file has multiple ! hard links, ! .I compress ! will refuse to compress it unless the .B \-f ! flag is given. ! .PP If .B \-f is not given and *************** *** 67,82 **** is run in the foreground, the user is prompted as to whether an existing file should be overwritten. .PP The .B \-c option makes .I compress/uncompress write to the standard output; no files are changed. ! The nondestructive behavior of .I zcat ! is identical to that of .I uncompress .B \-c. .PP If the .B \-r --- 67,105 ---- is run in the foreground, the user is prompted as to whether an existing file should be overwritten. .PP + Compressed files can be restored to their original form using + .I uncompress + or + .I zcat. + .PP + .I uncompress + takes a list of files on its command line and replaces each + file whose name ends with + .B "\&.Z" + and which begins with the correct magic number with an uncompressed + file without the + .B "\&.Z." + The uncompressed file will have the mode, ownership and + timestamps of the compressed file. + .PP The .B \-c option makes .I compress/uncompress write to the standard output; no files are changed. ! .PP .I zcat ! is identical to .I uncompress .B \-c. + .I zcat + uncompresses either a list of files on the command line or its + standard input and writes the uncompressed data on standard output. + .I zcat + will uncompress files that have the correct magic number whether + they have a + .B "\&.Z" + suffix or not. .PP If the .B \-r *************** *** 87,92 **** --- 110,121 ---- .I compress will descend into the directory and compress all the files it finds there. .PP + The + .B \-V + flag tells each of these programs to print its version and patchlevel, + along with any preprocessor flags specified during compilation, on + stderr before doing any compression or uncompression. + .PP .I Compress uses the modified Lempel-Ziv algorithm popularized in "A Technique for High Performance Data Compression", *************** *** 147,157 **** a message is printed yielding the percentage of reduction for each file compressed. .PP - If the - .B \-V - option is specified, the current version and compile options are printed on - stderr. - .PP Exit status is normally 0; if the last file is larger after (attempted) compression, the status is 2; if an error occurs, exit status is 1. --- 176,181 ---- *************** *** 158,164 **** .SH "SEE ALSO" pack(1), compact(1) .SH "DIAGNOSTICS" ! Usage: compress [\-dfvcV] [\-b maxbits] [file ...] .in +8 Invalid options were specified on the command line. .in -8 --- 182,188 ---- .SH "SEE ALSO" pack(1), compact(1) .SH "DIAGNOSTICS" ! Usage: compress [\-dfvcVr] [\-b maxbits] [file ...] .in +8 Invalid options were specified on the command line. .in -8 *************** *** 220,229 **** (Relevant only for .BR \-v \.) .in -8 ! -- not a regular file: unchanged .in +8 ! When the input file is not a regular file, ! (e.g. a directory), it is left unaltered. .in -8 -- has --- 244,253 ---- (Relevant only for .BR \-v \.) .in -8 ! -- not a regular file or directory: ignored .in +8 ! When the input file is not a regular file or directory, ! (e.g. a symbolic link, socket, FIFO, device file), it is left unaltered. .in -8 -- has *************** *** 232,238 **** .in +8 The input file has links; it is left unchanged. See .IR ln "(1)" ! for more information. .in -8 -- file unchanged .in +8 --- 256,264 ---- .in +8 The input file has links; it is left unchanged. See .IR ln "(1)" ! for more information. Use the ! .B \-f ! flag to force compression of multiply-linked files. .in -8 -- file unchanged .in +8 *************** *** 245,247 **** --- 271,284 ---- should be used for file transfer to architectures with a small process data space (64KB or less, as exhibited by the DEC PDP series, the Intel 80286, etc.) + .PP + Invoking compress with a \-r + flag will occasionally cause it to produce spurious error warnings of the form + .PP + .in 8 + "<filename>.Z already has .Z suffix - ignored" + .in -8 + .PP + These warnings can be ignored. See the comments in compress.c:compdir() + for an explanation. + diff -rc compress.posted/compress.c compress41/compress.c *** compress.posted/compress.c Fri Jun 28 19:07:09 1991 --- compress41/compress.c Fri Jun 28 19:08:41 1991 *************** *** 3,8 **** --- 3,11 ---- */ #define min(a,b) ((a>b) ? b : a) + /* MAXPATHLEN - maximum length of a pathname we allow */ + #define MAXPATHLEN 1024 + /* * machine variants which require cc -Dmachine: pdp11, z8000, pcxt */ *************** *** 373,379 **** #define CLEAR 256 /* table clear output code */ int force = 0; ! char ofname [100]; #ifdef DEBUG int verbose = 0; #endif /* DEBUG */ --- 376,382 ---- #define CLEAR 256 /* table clear output code */ int force = 0; ! char ofname[MAXPATHLEN]; #ifdef DEBUG int verbose = 0; #endif /* DEBUG */ *************** *** 386,391 **** --- 389,395 ---- int do_decomp = 0; + struct stat statbuf, insbuf; /***************************************************************** * TAG( main ) *************** *** 596,603 **** comprexx(fileptr) char **fileptr; { ! struct stat statbuf,insbuf; ! char tempname[1024], *cp; strcpy(tempname,*fileptr); errno = 0; --- 600,606 ---- comprexx(fileptr) char **fileptr; { ! char tempname[MAXPATHLEN], *cp; strcpy(tempname,*fileptr); errno = 0; *************** *** 647,652 **** --- 650,658 ---- case S_IFDIR: /* directory */ if (recursive) compdir(tempname); + else if ( ! quiet ) + fprintf(stderr,"%s is a directory -- ignored\n", + tempname); break; case S_IFREG: /* regular file */ *************** *** 697,706 **** else { /* COMPRESSION */ if (strcmp(tempname + strlen(tempname) - 2, ".Z") == 0) { ! fprintf(stderr, "%s: already has .Z suffix -- no change\n", ! tempname); ! return; } /* Open input file */ if ((freopen(tempname, "r", stdin)) == NULL) { perror(tempname); return; --- 703,717 ---- else { /* COMPRESSION */ if (strcmp(tempname + strlen(tempname) - 2, ".Z") == 0) { ! fprintf(stderr, "%s: already has .Z suffix -- no change\n", ! tempname); ! return; } + if (insbuf.st_nlink > 1 && (! force) ) { + fprintf(stderr, "%s has %d other links: unchanged\n", + tempname,insbuf.st_nlink - 1); + return; + } /* Open input file */ if ((freopen(tempname, "r", stdin)) == NULL) { perror(tempname); return; *************** *** 787,794 **** if((exit_stat == 1) || (!quiet)) putc('\n', stderr); } default: ! break; } /* end switch */ return; } /* end comprexx */ --- 798,808 ---- if((exit_stat == 1) || (!quiet)) putc('\n', stderr); } + break; default: ! fprintf(stderr,"%s is not a directory or a regular file - ignored\n", ! tempname); ! break; } /* end switch */ return; } /* end comprexx */ *************** *** 802,808 **** #else register struct dirent *dp; #endif ! char nbuf[1024]; char *nptr = nbuf; dirp = opendir(dir); if (dirp == NULL) { --- 816,822 ---- #else register struct dirent *dp; #endif ! char nbuf[MAXPATHLEN]; char *nptr = nbuf; dirp = opendir(dir); if (dirp == NULL) { *************** *** 809,823 **** printf("%s unreadable\n", dir); /* not stderr! */ return ; } while (dp = readdir(dirp)) { if (dp->d_ino == 0) continue; ! if (strcmp(dp->d_name,".") == 0 || strcmp(dp->d_name,"..") == 0) continue; ! strcpy(nbuf,dir); ! strcat(nbuf,"/"); ! strcat(nbuf,dp->d_name); ! comprexx(&nptr); } closedir(dirp); return; --- 823,856 ---- printf("%s unreadable\n", dir); /* not stderr! */ return ; } + /* + ** WARNING: the following algorithm will occasionally cause + ** compress to produce error warnings of the form "<filename>.Z + ** already has .Z suffix - ignored". This occurs when the + ** .Z output file is inserted into the directory below + ** readdir's current pointer. + ** These warnings are harmless but annoying. The alternative + ** to allowing this would be to store the entire directory + ** list in memory, then compress the entries in the stored + ** list. Given the depth-first recursive algorithm used here, + ** this could use up a tremendous amount of memory. I don't + ** think it's worth it. -- Dave Mack + */ while (dp = readdir(dirp)) { if (dp->d_ino == 0) continue; ! if (strcmp(dp->d_name,".") == 0 || ! strcmp(dp->d_name,"..") == 0) continue; ! if ( (strlen(dir)+strlen(dp->d_name)+1) < (MAXPATHLEN - 1)){ ! strcpy(nbuf,dir); ! strcat(nbuf,"/"); ! strcat(nbuf,dp->d_name); ! comprexx(&nptr); ! } ! else { ! fprintf(stderr,"Pathname too long: %s/%s\n",dir,dp->d_name); ! } } closedir(dirp); return; *************** *** 1407,1448 **** copystat(ifname, ofname) char *ifname, *ofname; { - struct stat statbuf; int mode; time_t timep[2]; fclose(stdout); ! if (stat(ifname, &statbuf)) { /* Get stat on input file */ ! perror(ifname); ! return; ! } ! if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) { ! if(quiet) ! fprintf(stderr, "%s: ", ifname); ! fprintf(stderr, " -- not a regular file: unchanged"); ! exit_stat = 1; ! } else if (statbuf.st_nlink > 1 && (! force) ) { ! if(quiet) ! fprintf(stderr, "%s: ", ifname); ! fprintf(stderr, " -- has %d other links: unchanged", ! statbuf.st_nlink - 1); ! exit_stat = 1; ! } else if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */ if(!quiet) ! fprintf(stderr, " -- file unchanged"); } else { /* ***** Successful Compression ***** */ exit_stat = 0; ! mode = statbuf.st_mode & 07777; if (chmod(ofname, mode)) /* Copy modes */ perror(ofname); ! chown(ofname, statbuf.st_uid, statbuf.st_gid); /* Copy ownership */ ! timep[0] = statbuf.st_atime; ! timep[1] = statbuf.st_mtime; utime(ofname, timep); /* Update last accessed and modified times */ if (unlink(ifname)) /* Remove input file */ perror(ifname); if(!quiet) ! fprintf(stderr, " -- replaced with %s", ofname); return; /* Successful return */ } --- 1440,1466 ---- copystat(ifname, ofname) char *ifname, *ofname; { int mode; time_t timep[2]; fclose(stdout); ! if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */ if(!quiet) ! fprintf(stderr, "No compression -- %s unchanged", ! ifname); } else { /* ***** Successful Compression ***** */ exit_stat = 0; ! mode = insbuf.st_mode & 07777; if (chmod(ofname, mode)) /* Copy modes */ perror(ofname); ! chown(ofname, insbuf.st_uid, insbuf.st_gid); /* Copy ownership */ ! timep[0] = insbuf.st_atime; ! timep[1] = insbuf.st_mtime; utime(ofname, timep); /* Update last accessed and modified times */ if (unlink(ifname)) /* Remove input file */ perror(ifname); if(!quiet) ! fprintf(stderr, " -- replaced with %s",ofname); return; /* Successful return */ } diff -rc compress.posted/patchlevel.h compress41/patchlevel.h *** compress.posted/patchlevel.h Fri Jun 28 19:07:16 1991 --- compress41/patchlevel.h Fri Jun 28 19:12:42 1991 *************** *** 1 **** ! #define PATCHLEVEL 0 --- 1 ---- ! #define PATCHLEVEL 1 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.