[comp.sources.misc] v06i066: compress 4.0 bug fixes

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (03/21/89)

Posting-number: Volume 6, Issue 66
Submitted-by: res@cbnews.ATT.COM (Robert E. Stampfli)
Archive-name: compress-patch

[These are NOT official patches.  Make sure you save your original compress 4.0
sources, so you have them if/when official patches come out.

In the meantime, you're crazy if you don't apply them (or, alternatively, only
use compress/uncompress as filters as I do).  I've been bit by these a few times
myself.  ++bsa]

I use compress 4.0 (and its variants uncompress and zcat) daily and have
come to find them invaluable.  One pesky problem, though, is that they
occasionally go overboard while trying to cleanup after themselves and
remove valuable files.  In an effort to break them of these nasty
habits, I sat down the other night and studied the code.  I think I have
isolated and resolved several problems:

1. I had just finished porting a file, gcc.33-34diffZ, or some such 14
   character gobbledegook, from osu-cis and typed "zcat gcc.33-34diffZ".
   Not realizing it did not end in ".Z", everything appeared to be
   uncompressing fine.  It was a large file, so I broke out of it, only
   to discover to my horror that the file was no longer among the living:
   zcat had dutifully removed it, thinking it was the object of the aborted
   uncompress.

2. Recently, I typed "compress xxx", to which the program responded with the
   fact that a file xxx.Z already existed and asked if I wanted to overwrite
   it.  Thankful for this degree of error checking, I hit DELETE to abort
   the compress.  In this case, DELETE was very aptly named, much to my
   chagrin.

3. I have found that there are small windows of vulnerability when
   (de)compressing a number of files, where an ill-timed DELETE will
   remove all references to a file which has just finished being
   successfully (de)compressed.

Actually, the changes are fairly minimal.  I inserted a few sanity checks
and created a variable that indicates to the various interrupt handlers
when it is proper to remove a object, and when it is not.  The diffs against
the official version 4.0 compress.c file are included below.  Of course,
no warrantee, expressed or implied.  Happy compressing.

Rob Stampfli
att!cblpe!res (work)
osu-cis!n8emr!kd8wk!rees (home)

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The original 4.0 compress.c, upon which this diff is based, sums to 47475 78
(2nd number may vary according to your blocksize) and wc stats it as
1486 6313 39614.  It is 19141 bytes long, compressed of course.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

*** ocompress.c	Tue Mar  7 00:31:20 1989
--- compress.c	Tue Mar  7 11:27:37 1989
***************
*** 356,361
  #define	CLEAR	256	/* table clear output code */
  
  int force = 0;
  char ofname [100];
  #ifdef DEBUG
  int verbose = 0;

--- 356,362 -----
  #define	CLEAR	256	/* table clear output code */
  
  int force = 0;
+ int valid = 0;		/* set when signal can remove ofname -- added by res */
  char ofname [100];
  #ifdef DEBUG
  int verbose = 0;
***************
*** 414,420
  
      if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
  	signal ( SIGINT, onintr );
- 	signal ( SIGSEGV, oops );
      }
  
  #ifdef COMPATIBLE

--- 415,420 -----
  
      if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
  	signal ( SIGINT, onintr );
      }
      signal ( SIGSEGV, oops );
  
***************
*** 416,421
  	signal ( SIGINT, onintr );
  	signal ( SIGSEGV, oops );
      }
  
  #ifdef COMPATIBLE
      nomagic = 1;	/* Original didn't have a magic number */

--- 416,422 -----
      if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
  	signal ( SIGINT, onintr );
      }
+     signal ( SIGSEGV, oops );
  
  #ifdef COMPATIBLE
      nomagic = 1;	/* Original didn't have a magic number */
***************
*** 529,534
  		/* Check for .Z suffix */
  		if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) {
  		    /* No .Z: tack one on */
  		    strcpy(tempname, *fileptr);
  		    strcat(tempname, ".Z");
  		    *fileptr = tempname;

--- 530,543 -----
  		/* Check for .Z suffix */
  		if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) {
  		    /* No .Z: tack one on */
+ #ifndef BSD4_2	    /* Short filenames */
+ 		    if ((cp=rindex(*fileptr,'/')) != NULL)	cp++;
+ 		    else					cp = *fileptr;
+ 		    if (strlen(cp) > 12) {
+ 			fprintf(stderr,"%s.Z: No such file or directory\n",cp);
+ 			continue;
+ 		    }
+ #endif  /* BSD4_2	Long filenames allowed */
  		    strcpy(tempname, *fileptr);
  		    strcat(tempname, ".Z");
  		    *fileptr = tempname;
***************
*** 607,614
  		    response[0] = 'n';
  		    fprintf(stderr, "%s already exists;", ofname);
  		    if (foreground()) {
! 			fprintf(stderr, " do you wish to overwrite %s (y or n)? ",
! 			ofname);
  			fflush(stderr);
  			read(2, response, 2);
  			while (response[1] != '\n') {

--- 616,622 -----
  		    response[0] = 'n';
  		    fprintf(stderr, "%s already exists;", ofname);
  		    if (foreground()) {
! 			fprintf(stderr," OK to overwrite (y or n)? ");
  			fflush(stderr);
  			read(2, response, 2);
  			while (response[1] != '\n') {
***************
*** 624,629
  		}
  	    }
  	    if(zcat_flg == 0) {		/* Open output file */
  		if (freopen(ofname, "w", stdout) == NULL) {
  		    perror(ofname);
  		    continue;

--- 632,638 -----
  		}
  	    }
  	    if(zcat_flg == 0) {		/* Open output file */
+ 		valid = 1;	/* added by res */
  		if (freopen(ofname, "w", stdout) == NULL) {
  		    perror(ofname);
  		    continue;
***************
*** 633,639
  	    }
  
  	    /* Actually do the compression/decompression */
! 	    if (do_decomp == 0)	compress();
  #ifndef DEBUG
  	    else			decompress();
  #else

--- 642,648 -----
  	    }
  
  	    /* Actually do the compression/decompression */
! 	    if (do_decomp == 0)		compress();
  #ifndef DEBUG
  	    else			decompress();
  #else
***************
*** 1264,1270
  writeerr()
  {
      perror ( ofname );
!     unlink ( ofname );
      exit ( 1 );
  }
  

--- 1273,1280 -----
  writeerr()
  {
      perror ( ofname );
!     if( valid )
! 	unlink ( ofname );
      exit ( 1 );
  }
  
***************
*** 1303,1308
  	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)

--- 1313,1319 -----
  	timep[0] = statbuf.st_atime;
  	timep[1] = statbuf.st_mtime;
  	utime(ofname, timep);	/* Update last accessed and modified times */
+ 	valid = 0;	/* added by res -- prevents latent ofname removal */
  	if (unlink(ifname))	/* Remove input file */
  	    perror(ifname);
  	if(!quiet)
***************
*** 1333,1339
  
  onintr ( )
  {
!     unlink ( ofname );
      exit ( 1 );
  }
  

--- 1344,1351 -----
  
  onintr ( )
  {
!     if( valid )
! 	unlink ( ofname );
      exit ( 1 );
  }
  
***************
*** 1341,1347
  {
      if ( do_decomp == 1 ) 
      	fprintf ( stderr, "uncompress: corrupt input\n" );
!     unlink ( ofname );
      exit ( 1 );
  }
  

--- 1353,1360 -----
  {
      if ( do_decomp == 1 ) 
      	fprintf ( stderr, "uncompress: corrupt input\n" );
!     if( valid )
! 	unlink ( ofname );
      exit ( 1 );
  }