[comp.sources.bugs] PAX - Unofficial Patches

scjones@sdrc.UUCP (Larry Jones) (07/22/89)

I have been using Pax V1.1 for quit some time now and have been
VERY pleased with it -- the automatic archive type detection has
saved me quite a lot of time, effort, and aggravation.

Unfortunately, I've run across a few bugs lately that made me go
back to using the real cpio and tar.  Fortunately, however, I got
motivated, tracked them down, and fixed them.  I sent these
patches to the author, but I haven't gotten any response, so I
thought I sould go ahead and post them.

The problems (and the related source files):

When extracting or listing a cpio archive with absolute path
names, the links get messed up (extract.c).

When end of volume is detected on an archive associated with
stdin or stdout, answering the next volume prompt with "go"
does not read the new volume but rather immediately prompts for
the next volume (fileio.c).

When using the pass option, files with a link count of one are
always copied rather than linked, even when the link flag is
specified (pass.c).

There are numerous problems with the logic that maintains the
link table:  the linked lists are frequently corrupted, defunct
entries are never deleted, and memory is permanently lost when
allocation fails (link.c).

The diffs follow my signature.
----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@SDRC.UU.NET
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
"You can't get a body like mine in a bottle --
unless you push REAL HARD." - Judy Tenuta / Dr. Pepper

*** orig/extract.c	Mon Mar 27 15:26:01 1989
--- extract.c	Thu Jun 22 14:01:42 1989
***************
*** 310,315
  {
      OFFSET          skipped;
      char            magic[M_STRLEN];
      static int      align;
  
      if (align > 0) {

--- 310,316 -----
  {
      OFFSET          skipped;
      char            magic[M_STRLEN];
+     char           *namep;
      static int      align;
  
      if (align > 0) {
***************
*** 360,367
      /* destroy absolute pathnames for security reasons */
      if (name[0] == '/') {
  	if (name[1]) {
! 	    while (name[0] = name[1]) {
! 		++name;
  	    }
  	} else {
  	    name[0] = '.';

--- 361,367 -----
      /* destroy absolute pathnames for security reasons */
      if (name[0] == '/') {
  	if (name[1]) {
! 	    for (namep = name; namep[0] = namep[1]; ++namep) {
  	    }
  	} else {
  	    name[0] = '.';

*** orig/fileio.c	Mon Mar 27 15:26:00 1989
--- fileio.c	Thu Jun 22 13:31:46 1989
***************
*** 83,88
  	} else {
  	    archivefd = STDOUT;
  	}
      } else if (mode == AR_READ) {
  	archivefd = open(ar_file, O_RDONLY | O_BINARY);
  	bufend = bufidx = bufstart;	/* set up for initial read */

--- 83,89 -----
  	} else {
  	    archivefd = STDOUT;
  	}
+ 	lseek(archivefd, (OFFSET) 0, 0);
      } else if (mode == AR_READ) {
  	archivefd = open(ar_file, O_RDONLY | O_BINARY);
  	bufend = bufidx = bufstart;	/* set up for initial read */

*** orig/link.c	Mon Mar 27 15:26:00 1989
--- link.c	Thu Jun 22 11:26:40 1989
***************
*** 113,119
  		linknext->l_back = linkp->l_back;
  	    }
  	    if (linkp->l_back) {
! 		linkp->l_back->l_forw = linkp->l_forw;
  	    }
  	    free((char *) linkp);
  	    *abase = (Link *) NULL;

--- 113,121 -----
  		linknext->l_back = linkp->l_back;
  	    }
  	    if (linkp->l_back) {
! 		linkp->l_back->l_forw = linknext;
! 	    } else {
! 		*abase = linknext;
  	    }
  	    free((char *) linkp);
  	} else if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
***************
*** 116,122
  		linkp->l_back->l_forw = linkp->l_forw;
  	    }
  	    free((char *) linkp);
- 	    *abase = (Link *) NULL;
  	} else if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
  	    /* 
  	     * check to see if a file with the name "name" exists in the 

--- 118,123 -----
  		*abase = linknext;
  	    }
  	    free((char *) linkp);
  	} else if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
  	    /* 
  	     * check to see if a file with the name "name" exists in the 
***************
*** 126,132
  		if (strcmp(path->p_name, name) == 0) {
  		    --linkp->l_nlink;
  		    if (path->p_name) {
! 			free(path->p_name);
  		    }
  		    if (pathnext = path->p_forw) {
  			pathnext->p_back = path->p_back;

--- 127,133 -----
  		if (strcmp(path->p_name, name) == 0) {
  		    --linkp->l_nlink;
  		    if (path->p_name) {
! 			free((char *) path->p_name);
  		    }
  		    if (pathnext = path->p_forw) {
  			pathnext->p_back = path->p_back;
***************
*** 133,140
  		    }
  		    if (path->p_back) {
  			path->p_back->p_forw = pathnext;
! 		    }
! 		    if (linkp->l_path == path) {
  			linkp->l_path = pathnext;
  		    }
  		    free(path);

--- 134,140 -----
  		    }
  		    if (path->p_back) {
  			path->p_back->p_forw = pathnext;
! 		    } else {
  			linkp->l_path = pathnext;
  		    }
  		    free((char *) path);
***************
*** 137,143
  		    if (linkp->l_path == path) {
  			linkp->l_path = pathnext;
  		    }
! 		    free(path);
  		    return (linkp);
  		}
  		pathnext = path->p_forw;

--- 137,143 -----
  		    } else {
  			linkp->l_path = pathnext;
  		    }
! 		    free((char *) path);
  		    return (linkp);
  		}
  		pathnext = path->p_forw;
***************
*** 241,247
      Path           *path;
      Link          **abase;
  
!     for (linkp = *(LINKHASH(asb->sb_ino)); linkp; linkp = linknext) {
  	if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
  	    if ((path = (Path *) mem_get(sizeof(Path))) == (Path *) NULL || 
  		(path->p_name = mem_str(name)) == (char *) NULL) {

--- 241,249 -----
      Path           *path;
      Link          **abase;
  
!     linknext = (Link *) NULL;
!     for (abase = LINKHASH(asb->sb_ino); *abase; abase = &(*abase)->l_forw) {
! 	linkp = linknext = *abase;
  	if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
  	    if ((path = (Path *) mem_get(sizeof(Path))) == (Path *) NULL || 
  		(path->p_name = mem_str(name)) == (char *) NULL) {
***************
*** 245,250
  	if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
  	    if ((path = (Path *) mem_get(sizeof(Path))) == (Path *) NULL || 
  		(path->p_name = mem_str(name)) == (char *) NULL) {
  		return((Link *) NULL);
  	    }
  	    if (path->p_forw = linkp->l_path) {

--- 247,253 -----
  	if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
  	    if ((path = (Path *) mem_get(sizeof(Path))) == (Path *) NULL || 
  		(path->p_name = mem_str(name)) == (char *) NULL) {
+ 		if (path) free((char *) path);
  		return((Link *) NULL);
  	    }
  	    if (path->p_forw = linkp->l_path) {
***************
*** 248,258
  		return((Link *) NULL);
  	    }
  	    if (path->p_forw = linkp->l_path) {
! 		if (linkp->l_path->p_forw) {
! 		    linkp->l_path->p_forw->p_back = path;
! 		}
! 	    } else {
! 		linkp->l_path = path;
  	    }
  	    path->p_back = (Path *) NULL;
  	    return(linkp);

--- 251,257 -----
  		return((Link *) NULL);
  	    }
  	    if (path->p_forw = linkp->l_path) {
! 		path->p_forw->p_back = path;
  	    }
  	    linkp->l_path = path;
  	    path->p_back = (Path *) NULL;
***************
*** 254,259
  	    } else {
  		linkp->l_path = path;
  	    }
  	    path->p_back = (Path *) NULL;
  	    return(linkp);
  	} else {

--- 253,259 -----
  	    if (path->p_forw = linkp->l_path) {
  		path->p_forw->p_back = path;
  	    }
+ 	    linkp->l_path = path;
  	    path->p_back = (Path *) NULL;
  	    return(linkp);
  	}
***************
*** 256,263
  	    }
  	    path->p_back = (Path *) NULL;
  	    return(linkp);
- 	} else {
- 	    linknext = linkp->l_forw;
  	}
      }
      /*

--- 256,261 -----
  	    linkp->l_path = path;
  	    path->p_back = (Path *) NULL;
  	    return(linkp);
  	}
      }
      /*
***************
*** 267,272
      if ((asb->sb_mode & S_IFMT) == S_IFDIR
  	|| (linkp = (Link *) mem_get(sizeof(Link))) == NULL
  	|| (linkp->l_name = mem_str(name)) == NULL) {
  	return ((Link *) NULL);
      }
      linkp->l_dev = asb->sb_dev;

--- 265,271 -----
      if ((asb->sb_mode & S_IFMT) == S_IFDIR
  	|| (linkp = (Link *) mem_get(sizeof(Link))) == NULL
  	|| (linkp->l_name = mem_str(name)) == NULL) {
+ 	if (linkp) free((char *) linkp);
  	return ((Link *) NULL);
      }
      linkp->l_dev = asb->sb_dev;
***************
*** 274,285
      linkp->l_nlink = asb->sb_nlink - 1;
      linkp->l_size = asb->sb_size;
      linkp->l_path = (Path *) NULL;
!     if (linkp->l_forw = *(abase = LINKHASH(asb->sb_ino))) {
! 	linkp->l_forw->l_back = linkp;
!     } else {
! 	*abase = linkp;
!     }
!     linkp->l_back = NULL;
      return (linkp);
  }
  

--- 273,281 -----
      linkp->l_nlink = asb->sb_nlink - 1;
      linkp->l_size = asb->sb_size;
      linkp->l_path = (Path *) NULL;
!     linkp->l_forw = (Link *) NULL;
!     linkp->l_back = linknext;
!     *abase = linkp;
      return (linkp);
  }
  
*** orig/pass.c	Mon Mar 27 15:25:59 1989
--- pass.c	Thu Jun 22 09:45:02 1989
***************
*** 138,147
      if (nameopt(strcat(strcat(strcpy(to, dir), "/"), from)) < 0) {
  	return (-1);
      }
!     if (asb->sb_nlink > 1) {
! 	if (f_link && islink(from, asb) == (Link *) NULL) {
! 	    linkto(from, asb);
! 	}
  	linkto(to, asb);
      }
      if ((ofd = openo(to, asb, islink(to, asb), 1)) < 0) {

--- 138,148 -----
      if (nameopt(strcat(strcat(strcpy(to, dir), "/"), from)) < 0) {
  	return (-1);
      }
!     if (f_link && islink(from, asb) == (Link *) NULL) {
!     	++asb->sb_nlink;    /* need to count first file, too */
!         linkto(from, asb);
!     }
!     if (f_link || asb->sb_nlink > 1) {
  	linkto(to, asb);
      }
      if ((ofd = openo(to, asb, linkfrom(to, asb), 1)) < 0) {
***************
*** 144,150
  	}
  	linkto(to, asb);
      }
!     if ((ofd = openo(to, asb, islink(to, asb), 1)) < 0) {
  	return (-1);
      }
      if (ofd > 0) {

--- 145,151 -----
      if (f_link || asb->sb_nlink > 1) {
  	linkto(to, asb);
      }
!     if ((ofd = openo(to, asb, linkfrom(to, asb), 1)) < 0) {
  	return (-1);
      }
      if (ofd > 0) {

tneff@bfmny0.UUCP (Tom Neff) (07/28/89)

Just for the record, I installed Larry Jones's PAX patches on my Sys V
box (using PAXDIR and Doug's package, variously) and the links still
don't work right.  On extract it always looks as if every link points
to the first file in the archive.  This must be a thorny area, eh?

If anyone has wrestled this one to the ground on SysV I would appreciate
hearing about it.
-- 
"My God, Thiokol, when do you     \\	Tom Neff
want me to launch -- next April?"  \\	uunet!bfmny0!tneff