[comp.sources.misc] v20i074: compress - Compress 4.1, Patch01

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.