djm@eng.umd.edu (David J. MacKenzie) (06/27/91)
> This new version of compress seems to have the old problem with zcat > somtimes deleting the compressed file when interrupted. I thought > this bug was fixed long ago. To be precise, comp.sources.misc "v06i066: compress 4.0 bug fixes" submitted by res@cbnews.ATT.COM (Robert E. Stampfli) contains that fix. It drops in to 4.1 with only a few small changes. Below, I have adapted Robert's fixes for compress 4.1. I also fixed a problem with declaring signal handlers in the wrong place, which prevented compress from compiling with gcc. And I fixed the problem that the error messages that compress prints #ifdef SHORTNAMES when it can't tack on a .Z only mentioned the last component of the pathname. This happened both in Robert's patch and in the stock code, when creating the output file. --- compress.c.dist Tue Jun 25 17:36:59 1991 +++ compress.c Thu Jun 27 02:19:55 1991 @@ -373,6 +373,7 @@ #define CLEAR 256 /* table clear output code */ int force = 0; +int valid = 0; /* set when signal can remove ofname */ char ofname [100]; #ifdef DEBUG int verbose = 0; @@ -429,18 +430,18 @@ int overwrite = 0; /* Do not overwrite unless given -f flag */ int recursive = 0; /* compress directories */ +extern onintr(), oops(); main( argc, argv ) register int argc; char **argv; { char **filelist, **fileptr; char *cp, *rindex(), *malloc(); - extern onintr(), oops(); if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) { signal ( SIGINT, onintr ); - signal ( SIGSEGV, oops ); } + signal ( SIGSEGV, oops ); #ifdef COMPATIBLE nomagic = 1; /* Original didn't have a magic number */ @@ -615,6 +616,14 @@ ** directory, but it shouldn't do any harm. */ if (strcmp(tempname + strlen(tempname) - 2, ".Z") != 0) { +#ifdef SHORTNAMES + if ((cp=rindex(tempname,'/')) != NULL) cp++; + else cp = tempname; + if (strlen(cp) > 12) { + fprintf(stderr,"%s.Z: No such file or directory\n",tempname); + return; + } +#endif /* SHORTNAMES */ strcat(tempname,".Z"); errno = 0; #ifdef BSD4 @@ -732,7 +741,7 @@ if ((cp=rindex(ofname,'/')) != NULL) cp++; else cp = ofname; if (strlen(cp) > 12) { - fprintf(stderr,"%s: filename too long to tack on .Z\n",cp); + fprintf(stderr,"%s: filename too long to tack on .Z\n",ofname); signal(SIGINT,onintr); return; } @@ -746,8 +755,7 @@ response[0] = 'n'; fprintf(stderr, "%s already exists;", ofname); if (foreground()) { - fprintf(stderr, " do you wish to overwrite %s (y or n)? ", - ofname); + fprintf(stderr, " OK to overwrite (y or n)? "); fflush(stderr); read(2, response, 2); while (response[1] != '\n') { @@ -765,6 +773,7 @@ } signal(SIGINT,onintr); if(zcat_flg == 0) { /* Open output file */ + valid = 1; if (freopen(ofname, "w", stdout) == NULL) { perror(ofname); return; @@ -1400,7 +1409,8 @@ writeerr() { perror ( ofname ); - unlink ( ofname ); + if (valid) + unlink ( ofname ); exit ( 1 ); } @@ -1439,6 +1449,7 @@ timep[0] = statbuf.st_atime; timep[1] = statbuf.st_mtime; utime(ofname, timep); /* Update last accessed and modified times */ + valid = 0; /* prevent latent ofname removal */ if (unlink(ifname)) /* Remove input file */ perror(ifname); if(!quiet) @@ -1469,7 +1480,8 @@ onintr ( ) { - unlink ( ofname ); + if (valid) + unlink ( ofname ); exit ( 1 ); } @@ -1477,7 +1489,8 @@ { if ( do_decomp == 1 ) fprintf ( stderr, "uncompress: corrupt input\n" ); - unlink ( ofname ); + if (valid) + unlink ( ofname ); exit ( 1 ); } -- David J. MacKenzie <djm@eng.umd.edu> <djm@ai.mit.edu>
djm@eng.umd.edu (David J. MacKenzie) (06/29/91)
> Pardon the ignorance, but what kind of diff format is the one above? > Larry Wall's patch doesn't seem to recognise it. Sorry, I forgot to mention it. It's a unified diff, produced by GNU diff 1.15. It's like context format except that it omits duplicate context lines to save space. If you can anonymous ftp, prep.ai.mit.edu:pub/gnu/patch-2.0.12u4.tar.Z is a version of patch that recognizes unified diffs. If not, here is a short program called unipatch that converts unified diffs to context diffs. It came from comp.sources.misc "v14i070: Unified context diff tools" plus a patch in comp.sources.bugs. You'll likely be seeing more unified diffs on the net as time goes on, so it's worth while having programs that can deal with them. /* A filter to turn a unidiff into a degenerate context diff (no '!'s) for patch. Author: davison@dri.com (uunet!drivax!davison). */ #include <stdio.h> #define ERR(a) {fputs(a,stderr);exit(1);} struct Ln { struct Ln *lk; char t; char s[1]; } r,*h,*ln; char *malloc(); main() { char bf[2048],*cp,ch; long os,ol,ns,nl,ne,lncnt=0; for(;;){ for(;;){ if(!fgets(bf,sizeof bf,stdin)) exit(0); lncnt++; if(!strncmp(bf,"@@ -",4)) break; if(!strncmp(bf,"+++ ",4)) printf("***%s",bf+3); else fputs(bf,stdout); } if(sscanf(bf+4,"%ld,%ld +%ld,%ld %c",&os,&ol,&ns,&nl,&ch)!=5||ch!='@') goto bad; r.lk=0, h= &r, ne=ns+nl-1; printf("***************\n*** %ld,%ld ****\n",os,os+ol-(os>0)); while(ol||nl){ if(!fgets(bf,sizeof bf,stdin)){ if(nl>2) ERR("Unexpected end of file.\n"); strcpy(bf," \n"); } lncnt++; if(*bf=='\t'||*bf=='\n') ch=' ', cp=bf; else ch= *bf, cp=bf+1; switch(ch){ case'-':if(!ol--) goto bad; printf("- %s",cp); break; case'=':ch=' '; case' ':if(!ol--) goto bad; printf(" %s",cp); case'+':if(!nl--) goto bad; ln = (struct Ln*)malloc(sizeof(*ln)+strlen(cp)); if(!ln) ERR("Out of memory!\n"); ln->lk=0, ln->t=ch, strcpy(ln->s,cp); h->lk=ln, h=ln; break; default: bad: fprintf(stderr,"Malformed unidiff at line %ld: ",lncnt); ERR(bf); } } printf("--- %ld,%ld ----\n",ns,ne); for(ln=r.lk;ln;ln=h){ printf("%c %s",ln->t,ln->s); h=ln->lk; free(ln); } } } -- David J. MacKenzie <djm@eng.umd.edu> <djm@ai.mit.edu>