/* * ar - portable (ascii) format version */#include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>#include <ar.h> /* * The algorithm uses up to 3 temp files. The "pivot member" is the * archive member specified by and a, b, or i option. The temp files are * astart - contains existing members up to and including the pivot member. * amiddle - contains new files moved or inserted behind the pivot. * aend - contains the existing members that follow the pivot member. * When all members have been processed, function 'install' streams the * temp files, in order, back into the archive. */ typedef struct Arsymref{ char *name; int type; int len; vlong offset; struct Arsymref *next;} Arsymref; typedef struct Armember /* Temp file entry - one per archive member */{ struct Armember *next; struct ar_hdr hdr; long size; long date; void *member;} Armember; typedef struct Arfile /* Temp file control block - one per tempfile */{ int paged; /* set when some data paged to disk */ char *fname; /* paging file name */ int fd; /* paging file descriptor */ vlong size; Armember *head; /* head of member chain */ Armember *tail; /* tail of member chain */ Arsymref *sym; /* head of defined symbol chain */} Arfile; typedef struct Hashchain{ char *name; struct Hashchain *next;} Hashchain; #define NHASH 1024 /* * macro to portably read/write archive header. * 'cmd' is read/write/Bread/Bwrite, etc. */#define HEADER_IO(cmd, f, h) cmd(f, h.name, sizeof(h.name)) != sizeof(h.name)\ || cmd(f, h.date, sizeof(h.date)) != sizeof(h.date)\ || cmd(f, h.uid, sizeof(h.uid)) != sizeof(h.uid)\ || cmd(f, h.gid, sizeof(h.gid)) != sizeof(h.gid)\ || cmd(f, h.mode, sizeof(h.mode)) != sizeof(h.mode)\ || cmd(f, h.size, sizeof(h.size)) != sizeof(h.size)\ || cmd(f, h.fmag, sizeof(h.fmag)) != sizeof(h.fmag) /* constants and flags */char *man = "mrxtdpq";char *opt = "uvnbailo";char artemp[] = "/tmp/vXXXXX";char movtemp[] = "/tmp/v1XXXXX";char tailtemp[] = "/tmp/v2XXXXX";char symdef[] = "__.SYMDEF"; int aflag; /* command line flags */int bflag;int cflag;int oflag;int uflag;int vflag; Arfile *astart, *amiddle, *aend; /* Temp file control block pointers */int allobj = 1; /* set when all members are object files of the same type */int symdefsize; /* size of symdef file */int dupfound; /* flag for duplicate symbol */Hashchain *hash[NHASH]; /* hash table of text symbols */ #define ARNAMESIZE sizeof(astart->tail->hdr.name) char poname[ARNAMESIZE+1]; /* name of pivot member */char *file; /* current file or member being worked on */Biobuf bout;Biobuf bar; void arcopy(Biobuf*, Arfile*, Armember*);int arcreate(char*);void arfree(Arfile*);void arinsert(Arfile*, Armember*);char *armalloc(int);void armove(Biobuf*, Arfile*, Armember*);void arread(Biobuf*, Armember*, int);void arstream(int, Arfile*);int arwrite(int, Armember*);int bamatch(char*, char*);int duplicate(char*);Armember *getdir(Biobuf*);int getspace(void);void install(char*, Arfile*, Arfile*, Arfile*, int);void longt(Armember*);int match(int, char**);void mesg(int, char*);Arfile *newtempfile(char*);Armember *newmember(void);void objsym(Sym*, void*);int openar(char*, int, int);int page(Arfile*);void pmode(long);void rl(int);void scanobj(Biobuf*, Arfile*, long);void select(int*, long);void setcom(void(*)(char*, int, char**));void skip(Biobuf*, vlong);int symcomp(void*, void*);void trim(char*, char*, int);void usage(void);void wrerr(void);void wrsym(Biobuf*, long, Arsymref*); void rcmd(char*, int, char**); /* command processing */void dcmd(char*, int, char**);void xcmd(char*, int, char**);void tcmd(char*, int, char**);void pcmd(char*, int, char**);void mcmd(char*, int, char**);void qcmd(char*, int, char**);void (*comfun)(char*, int, char**); voidmain(int argc, char *argv[]){ char *cp; Binit(&bout, 1, OWRITE); if(argc < 3) usage(); for (cp = argv[1]; *cp; cp++) { switch(*cp) { case 'a': aflag = 1; break; case 'b': bflag = 1; break; case 'c': cflag = 1; break; case 'd': setcom(dcmd); break; case 'i': bflag = 1; break; case 'l': strcpy(artemp, "vXXXXX"); strcpy(movtemp, "v1XXXXX"); strcpy(tailtemp, "v2XXXXX"); break; case 'm': setcom(mcmd); break; case 'o': oflag = 1; break; case 'p': setcom(pcmd); break; case 'q': setcom(qcmd); break; case 'r': setcom(rcmd); break; case 't': setcom(tcmd); break; case 'u': uflag = 1; break; case 'v': vflag = 1; break; case 'x': setcom(xcmd); break; default: fprint(2, "ar: bad option `%c'\n", *cp); exits("error"); } } if (aflag && bflag) { fprint(2, "ar: only one of 'a' and 'b' can be specified\n"); usage(); } if(aflag || bflag) { trim(argv[2], poname, sizeof(poname)); argv++; argc--; if(argc < 3) usage(); } if(comfun == 0) { if(uflag == 0) { fprint(2, "ar: one of [%s] must be specified\n", man); usage(); } setcom(rcmd); } cp = argv[2]; argc -= 3; argv += 3; (*comfun)(cp, argc, argv); /* do the command */ cp = 0; while (argc--) { if (*argv) { fprint(2, "ar: %s not found\n", *argv); cp = "error"; } argv++; } exits(cp);}/* * select a command */voidsetcom(void (*fun)(char *, int, char**)){ if(comfun != 0) { fprint(2, "ar: only one of [%s] allowed\n", man); usage(); } comfun = fun;}/* * perform the 'r' and 'u' commands */voidrcmd(char *arname, int count, char **files){ int fd; int i; Arfile *ap; Armember *bp; Dir *d; Biobuf *bfile; fd = openar(arname, ORDWR, 1); if (fd >= 0) { Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); } astart = newtempfile(artemp); ap = astart; aend = 0; for(i = 0; fd >= 0; i++) { bp = getdir(&bar); if (!bp) break; if (bamatch(file, poname)) { /* check for pivot */ aend = newtempfile(tailtemp); ap = aend; } /* pitch symdef file */ if (i == 0 && strcmp(file, symdef) == 0) { skip(&bar, bp->size); continue; } if (count && !match(count, files)) { scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); continue; } bfile = Bopen(file, OREAD); if (!bfile) { if (count != 0) fprint(2, "ar: cannot open %s\n", file); scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); continue; } d = dirfstat(Bfildes(bfile)); if(d == nil) fprint(2, "ar: cannot stat %s: %r\n", file); if (uflag && (d==nil || d->mtime <= bp->date)) { scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); Bterm(bfile); free(d); continue; } mesg('r', file); skip(&bar, bp->size); scanobj(bfile, ap, d->length); free(d); armove(bfile, ap, bp); Bterm(bfile); } if(fd >= 0) close(fd); /* copy in remaining files named on command line */ for (i = 0; i < count; i++) { file = files[i]; if(file == 0) continue; files[i] = 0; bfile = Bopen(file, OREAD); if (!bfile) fprint(2, "ar: %s cannot open\n", file); else { mesg('a', file); d = dirfstat(Bfildes(bfile)); if (d == nil) fprint(2, "can't stat %s\n", file); else { scanobj(bfile, astart, d->length); armove(bfile, astart, newmember()); free(d); } Bterm(bfile); } } if(fd < 0 && !cflag) install(arname, astart, 0, aend, 1); /* issue 'creating' msg */ else install(arname, astart, 0, aend, 0);} voiddcmd(char *arname, int count, char **files){ Armember *bp; int fd, i; if (!count) return; fd = openar(arname, ORDWR, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); astart = newtempfile(artemp); for (i = 0; bp = getdir(&bar); i++) { if(match(count, files)) { mesg('d', file); skip(&bar, bp->size); if (strcmp(file, symdef) == 0) allobj = 0; } else if (i == 0 && strcmp(file, symdef) == 0) skip(&bar, bp->size); else { scanobj(&bar, astart, bp->size); arcopy(&bar, astart, bp); } } close(fd); install(arname, astart, 0, 0, 0);} voidxcmd(char *arname, int count, char **files){ int fd, f, mode, i; Armember *bp; Dir dx; fd = openar(arname, OREAD, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); i = 0; while (bp = getdir(&bar)) { if(count == 0 || match(count, files)) { mode = strtoul(bp->hdr.mode, 0, 8) & 0777; f = create(file, OWRITE, mode); if(f < 0) { fprint(2, "ar: %s cannot create\n", file); skip(&bar, bp->size); } else { mesg('x', file); arcopy(&bar, 0, bp); if (write(f, bp->member, bp->size) < 0) wrerr(); if(oflag) { nulldir(&dx); dx.atime = bp->date; dx.mtime = bp->date; if(dirwstat(file, &dx) < 0) perror(file); } free(bp->member); close(f); } free(bp); if (count && ++i >= count) break; } else { skip(&bar, bp->size); free(bp); } } close(fd);}voidpcmd(char *arname, int count, char **files){ int fd; Armember *bp; fd = openar(arname, OREAD, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); while(bp = getdir(&bar)) { if(count == 0 || match(count, files)) { if(vflag) print("\n<%s>\n\n", file); arcopy(&bar, 0, bp); if (write(1, bp->member, bp->size) < 0) wrerr(); } else skip(&bar, bp->size); free(bp); } close(fd);}voidmcmd(char *arname, int count, char **files){ int fd, i; Arfile *ap; Armember *bp; if (count == 0) return; fd = openar(arname, ORDWR, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); astart = newtempfile(artemp); amiddle = newtempfile(movtemp); aend = 0; ap = astart; for (i = 0; bp = getdir(&bar); i++) { if (bamatch(file, poname)) { aend = newtempfile(tailtemp); ap = aend; } if(match(count, files)) { mesg('m', file); scanobj(&bar, amiddle, bp->size); arcopy(&bar, amiddle, bp); } else /* * pitch the symdef file if it is at the beginning * of the archive and we aren't inserting in front * of it (ap == astart). */ if (ap == astart && i == 0 && strcmp(file, symdef) == 0) skip(&bar, bp->size); else { scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); } } close(fd); if (poname[0] && aend == 0) fprint(2, "ar: %s not found - files moved to end.\n", poname); install(arname, astart, amiddle, aend, 0);}voidtcmd(char *arname, int count, char **files){ int fd; Armember *bp; char name[ARNAMESIZE+1]; fd = openar(arname, OREAD, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); while(bp = getdir(&bar)) { if(count == 0 || match(count, files)) { if(vflag) longt(bp); trim(file, name, ARNAMESIZE); Bprint(&bout, "%s\n", name); } skip(&bar, bp->size); free(bp); } close(fd);}voidqcmd(char *arname, int count, char **files){ int fd, i; Armember *bp; Biobuf *bfile; if(aflag || bflag) { fprint(2, "ar: abi not allowed with q\n"); exits("error"); } fd = openar(arname, ORDWR, 1); if (fd < 0) { if(!cflag) fprint(2, "ar: creating %s\n", arname); fd = arcreate(arname); } Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); /* leave note group behind when writing archive; i.e. sidestep interrupts */ rfork(RFNOTEG); Bseek(&bar, 0, 2); bp = newmember(); for(i=0; i<count && files[i]; i++) { file = files[i]; files[i] = 0; bfile = Bopen(file, OREAD); if(!bfile) fprint(2, "ar: %s cannot open\n", file);Lines 1–500 of 1210. Load more
/* * ar - portable (ascii) format version */ #include <u.h> #include <libc.h> #include <bio.h> #include <mach.h> #include <ar.h> /* * The algorithm uses up to 3 temp files. The "pivot member" is the * archive member specified by and a, b, or i option. The temp files are * astart - contains existing members up to and including the pivot member. * amiddle - contains new files moved or inserted behind the pivot. * aend - contains the existing members that follow the pivot member. * When all members have been processed, function 'install' streams the * temp files, in order, back into the archive. */ typedef struct Arsymref { char *name; int type; int len; vlong offset; struct Arsymref *next; } Arsymref; typedef struct Armember /* Temp file entry - one per archive member */ { struct Armember *next; struct ar_hdr hdr; long size; long date; void *member; } Armember; typedef struct Arfile /* Temp file control block - one per tempfile */ { int paged; /* set when some data paged to disk */ char *fname; /* paging file name */ int fd; /* paging file descriptor */ vlong size; Armember *head; /* head of member chain */ Armember *tail; /* tail of member chain */ Arsymref *sym; /* head of defined symbol chain */ } Arfile; typedef struct Hashchain { char *name; struct Hashchain *next; } Hashchain; #define NHASH 1024 /* * macro to portably read/write archive header. * 'cmd' is read/write/Bread/Bwrite, etc. */ #define HEADER_IO(cmd, f, h) cmd(f, h.name, sizeof(h.name)) != sizeof(h.name)\ || cmd(f, h.date, sizeof(h.date)) != sizeof(h.date)\ || cmd(f, h.uid, sizeof(h.uid)) != sizeof(h.uid)\ || cmd(f, h.gid, sizeof(h.gid)) != sizeof(h.gid)\ || cmd(f, h.mode, sizeof(h.mode)) != sizeof(h.mode)\ || cmd(f, h.size, sizeof(h.size)) != sizeof(h.size)\ || cmd(f, h.fmag, sizeof(h.fmag)) != sizeof(h.fmag) /* constants and flags */ char *man = "mrxtdpq"; char *opt = "uvnbailo"; char artemp[] = "/tmp/vXXXXX"; char movtemp[] = "/tmp/v1XXXXX"; char tailtemp[] = "/tmp/v2XXXXX"; char symdef[] = "__.SYMDEF"; int aflag; /* command line flags */ int bflag; int cflag; int oflag; int uflag; int vflag; Arfile *astart, *amiddle, *aend; /* Temp file control block pointers */ int allobj = 1; /* set when all members are object files of the same type */ int symdefsize; /* size of symdef file */ int dupfound; /* flag for duplicate symbol */ Hashchain *hash[NHASH]; /* hash table of text symbols */ #define ARNAMESIZE sizeof(astart->tail->hdr.name) char poname[ARNAMESIZE+1]; /* name of pivot member */ char *file; /* current file or member being worked on */ Biobuf bout; Biobuf bar; void arcopy(Biobuf*, Arfile*, Armember*); int arcreate(char*); void arfree(Arfile*); void arinsert(Arfile*, Armember*); char *armalloc(int); void armove(Biobuf*, Arfile*, Armember*); void arread(Biobuf*, Armember*, int); void arstream(int, Arfile*); int arwrite(int, Armember*); int bamatch(char*, char*); int duplicate(char*); Armember *getdir(Biobuf*); int getspace(void); void install(char*, Arfile*, Arfile*, Arfile*, int); void longt(Armember*); int match(int, char**); void mesg(int, char*); Arfile *newtempfile(char*); Armember *newmember(void); void objsym(Sym*, void*); int openar(char*, int, int); int page(Arfile*); void pmode(long); void rl(int); void scanobj(Biobuf*, Arfile*, long); void select(int*, long); void setcom(void(*)(char*, int, char**)); void skip(Biobuf*, vlong); int symcomp(void*, void*); void trim(char*, char*, int); void usage(void); void wrerr(void); void wrsym(Biobuf*, long, Arsymref*); void rcmd(char*, int, char**); /* command processing */ void dcmd(char*, int, char**); void xcmd(char*, int, char**); void tcmd(char*, int, char**); void pcmd(char*, int, char**); void mcmd(char*, int, char**); void qcmd(char*, int, char**); void (*comfun)(char*, int, char**); void main(int argc, char *argv[]) { char *cp; Binit(&bout, 1, OWRITE); if(argc < 3) usage(); for (cp = argv[1]; *cp; cp++) { switch(*cp) { case 'a': aflag = 1; break; case 'b': bflag = 1; break; case 'c': cflag = 1; break; case 'd': setcom(dcmd); break; case 'i': bflag = 1; break; case 'l': strcpy(artemp, "vXXXXX"); strcpy(movtemp, "v1XXXXX"); strcpy(tailtemp, "v2XXXXX"); break; case 'm': setcom(mcmd); break; case 'o': oflag = 1; break; case 'p': setcom(pcmd); break; case 'q': setcom(qcmd); break; case 'r': setcom(rcmd); break; case 't': setcom(tcmd); break; case 'u': uflag = 1; break; case 'v': vflag = 1; break; case 'x': setcom(xcmd); break; default: fprint(2, "ar: bad option `%c'\n", *cp); exits("error"); } } if (aflag && bflag) { fprint(2, "ar: only one of 'a' and 'b' can be specified\n"); usage(); } if(aflag || bflag) { trim(argv[2], poname, sizeof(poname)); argv++; argc--; if(argc < 3) usage(); } if(comfun == 0) { if(uflag == 0) { fprint(2, "ar: one of [%s] must be specified\n", man); usage(); } setcom(rcmd); } cp = argv[2]; argc -= 3; argv += 3; (*comfun)(cp, argc, argv); /* do the command */ cp = 0; while (argc--) { if (*argv) { fprint(2, "ar: %s not found\n", *argv); cp = "error"; } argv++; } exits(cp); } /* * select a command */ void setcom(void (*fun)(char *, int, char**)) { if(comfun != 0) { fprint(2, "ar: only one of [%s] allowed\n", man); usage(); } comfun = fun; } /* * perform the 'r' and 'u' commands */ void rcmd(char *arname, int count, char **files) { int fd; int i; Arfile *ap; Armember *bp; Dir *d; Biobuf *bfile; fd = openar(arname, ORDWR, 1); if (fd >= 0) { Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); } astart = newtempfile(artemp); ap = astart; aend = 0; for(i = 0; fd >= 0; i++) { bp = getdir(&bar); if (!bp) break; if (bamatch(file, poname)) { /* check for pivot */ aend = newtempfile(tailtemp); ap = aend; } /* pitch symdef file */ if (i == 0 && strcmp(file, symdef) == 0) { skip(&bar, bp->size); continue; } if (count && !match(count, files)) { scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); continue; } bfile = Bopen(file, OREAD); if (!bfile) { if (count != 0) fprint(2, "ar: cannot open %s\n", file); scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); continue; } d = dirfstat(Bfildes(bfile)); if(d == nil) fprint(2, "ar: cannot stat %s: %r\n", file); if (uflag && (d==nil || d->mtime <= bp->date)) { scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); Bterm(bfile); free(d); continue; } mesg('r', file); skip(&bar, bp->size); scanobj(bfile, ap, d->length); free(d); armove(bfile, ap, bp); Bterm(bfile); } if(fd >= 0) close(fd); /* copy in remaining files named on command line */ for (i = 0; i < count; i++) { file = files[i]; if(file == 0) continue; files[i] = 0; bfile = Bopen(file, OREAD); if (!bfile) fprint(2, "ar: %s cannot open\n", file); else { mesg('a', file); d = dirfstat(Bfildes(bfile)); if (d == nil) fprint(2, "can't stat %s\n", file); else { scanobj(bfile, astart, d->length); armove(bfile, astart, newmember()); free(d); } Bterm(bfile); } } if(fd < 0 && !cflag) install(arname, astart, 0, aend, 1); /* issue 'creating' msg */ else install(arname, astart, 0, aend, 0); } void dcmd(char *arname, int count, char **files) { Armember *bp; int fd, i; if (!count) return; fd = openar(arname, ORDWR, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); astart = newtempfile(artemp); for (i = 0; bp = getdir(&bar); i++) { if(match(count, files)) { mesg('d', file); skip(&bar, bp->size); if (strcmp(file, symdef) == 0) allobj = 0; } else if (i == 0 && strcmp(file, symdef) == 0) skip(&bar, bp->size); else { scanobj(&bar, astart, bp->size); arcopy(&bar, astart, bp); } } close(fd); install(arname, astart, 0, 0, 0); } void xcmd(char *arname, int count, char **files) { int fd, f, mode, i; Armember *bp; Dir dx; fd = openar(arname, OREAD, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); i = 0; while (bp = getdir(&bar)) { if(count == 0 || match(count, files)) { mode = strtoul(bp->hdr.mode, 0, 8) & 0777; f = create(file, OWRITE, mode); if(f < 0) { fprint(2, "ar: %s cannot create\n", file); skip(&bar, bp->size); } else { mesg('x', file); arcopy(&bar, 0, bp); if (write(f, bp->member, bp->size) < 0) wrerr(); if(oflag) { nulldir(&dx); dx.atime = bp->date; dx.mtime = bp->date; if(dirwstat(file, &dx) < 0) perror(file); } free(bp->member); close(f); } free(bp); if (count && ++i >= count) break; } else { skip(&bar, bp->size); free(bp); } } close(fd); } void pcmd(char *arname, int count, char **files) { int fd; Armember *bp; fd = openar(arname, OREAD, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); while(bp = getdir(&bar)) { if(count == 0 || match(count, files)) { if(vflag) print("\n<%s>\n\n", file); arcopy(&bar, 0, bp); if (write(1, bp->member, bp->size) < 0) wrerr(); } else skip(&bar, bp->size); free(bp); } close(fd); } void mcmd(char *arname, int count, char **files) { int fd, i; Arfile *ap; Armember *bp; if (count == 0) return; fd = openar(arname, ORDWR, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); astart = newtempfile(artemp); amiddle = newtempfile(movtemp); aend = 0; ap = astart; for (i = 0; bp = getdir(&bar); i++) { if (bamatch(file, poname)) { aend = newtempfile(tailtemp); ap = aend; } if(match(count, files)) { mesg('m', file); scanobj(&bar, amiddle, bp->size); arcopy(&bar, amiddle, bp); } else /* * pitch the symdef file if it is at the beginning * of the archive and we aren't inserting in front * of it (ap == astart). */ if (ap == astart && i == 0 && strcmp(file, symdef) == 0) skip(&bar, bp->size); else { scanobj(&bar, ap, bp->size); arcopy(&bar, ap, bp); } } close(fd); if (poname[0] && aend == 0) fprint(2, "ar: %s not found - files moved to end.\n", poname); install(arname, astart, amiddle, aend, 0); } void tcmd(char *arname, int count, char **files) { int fd; Armember *bp; char name[ARNAMESIZE+1]; fd = openar(arname, OREAD, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); while(bp = getdir(&bar)) { if(count == 0 || match(count, files)) { if(vflag) longt(bp); trim(file, name, ARNAMESIZE); Bprint(&bout, "%s\n", name); } skip(&bar, bp->size); free(bp); } close(fd); } void qcmd(char *arname, int count, char **files) { int fd, i; Armember *bp; Biobuf *bfile; if(aflag || bflag) { fprint(2, "ar: abi not allowed with q\n"); exits("error"); } fd = openar(arname, ORDWR, 1); if (fd < 0) { if(!cflag) fprint(2, "ar: creating %s\n", arname); fd = arcreate(arname); } Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); /* leave note group behind when writing archive; i.e. sidestep interrupts */ rfork(RFNOTEG); Bseek(&bar, 0, 2); bp = newmember(); for(i=0; i<count && files[i]; i++) { file = files[i]; files[i] = 0; bfile = Bopen(file, OREAD); if(!bfile) fprint(2, "ar: %s cannot open\n", file);