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