/* * ar - portable (ascii) format version */#include <u.h>#include <libc.h>#include <bio.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. Temp file astart * contains existing members up to and including the pivot member. Temp * file amiddle contains new files moved or inserted behind the pivot. * Temp file aend, contains the existing members of the archive 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 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 */ Armember *head; /* head of member chain */ Armember *tail; /* tail of member chain */} Arfile; /* constants and flags */char *man = "mrxtdpq";char *opt = "uvnbailo";char artemp[] = "/tmp/vXXXXX";char movtemp[] = "/tmp/v1XXXXX";char tailtemp[] = "/tmp/v2XXXXX"; int aflag; /* command line flags */int bflag;int cflag;int dflag;int iflag;int lflag;int mflag;int nflag;int oflag;int pflag;int qflag;int rflag;int tflag;int uflag;int vflag;int xflag; Arfile *astart, *amiddle, *aend; /* Temp file control block pointers */ #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; void arcopy(int, Arfile*, Armember*);int arcreate(char*);void arfree(Arfile*);void arinsert(Arfile*, Armember*);char *armalloc(int);void armove(int, Arfile*, Armember*);void arread(int, Armember*, int);void arstream(int, Arfile*);int arwrite(int, Armember*);int bamatch(char*, char*);Armember *getdir(int);int getspace(void);void install(char*, Arfile*, Arfile*, Arfile*);void longt(Armember*);int match(int, char**);void mesg(int, char*);Arfile *newtempfile(char*);Armember *newmember(void);int openar(char*, int, int);int page(Arfile*);void pmode(long);void select(int*, long);void setcom(void(*)(char*, int, char**));void skip(int, long);void trim(char*, char*, int);void usage(void);void wrerr(void); 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 'n': nflag = 1; 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, fd2; int i; Arfile *ap; Armember *bp; Dir d; fd = openar(arname, ORDWR, 1); astart = newtempfile(artemp); ap = astart; aend = 0; while (fd > 0) { bp = getdir(fd); if (!bp) break; if (bamatch(file, poname)) { /* check for pivot */ aend = newtempfile(tailtemp); ap = aend; } if (count == 0 || match(count, files)) { fd2 = open(file, OREAD); if (fd2 < 0) { if (count != 0) fprint(2, "ar: cannot open %s\n", file); arcopy(fd, ap, bp); } else if (uflag) { if (dirfstat(fd2, &d) < 0) { fprint(2, "ar: cannot stat %s\n", file); arcopy(fd, ap, bp); } else if (d.mtime <= bp->date) arcopy(fd, ap, bp); else { mesg('r', file); skip(fd, bp->size); armove(fd2, ap, bp); } close(fd2); } else { mesg('r', file); skip(fd, bp->size); armove(fd2, ap, bp); close(fd2); } } else arcopy(fd, ap, bp); } if(fd < 0) { if(!cflag) fprint(2, "ar: creating %s\n", arname); } else 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; fd2 = open(file, OREAD); if (fd2 < 0) fprint(2, "ar: %s cannot open\n", file); else { mesg('a', file); armove(fd2, astart, newmember()); close(fd2); } } install(arname, astart, 0, aend);}voiddcmd(char *arname, int count, char **files){ Armember *bp; int fd; if (!count) return; fd = openar(arname, ORDWR, 0); astart = newtempfile(artemp); while (bp = getdir(fd)) { if(match(count, files)) { mesg('d', file); skip(fd, bp->size); } else arcopy(fd, astart, bp); } install(arname, astart, 0, 0);} voidxcmd(char *arname, int count, char **files){ int fd, f, mode, i; Armember *bp; Dir d; fd = openar(arname, OREAD, 0); i = 0; while (bp = getdir(fd)) { 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(fd, bp->size); } else { mesg('x', file); arcopy(fd, 0, bp); if (write(f, bp->member, bp->size) < 0) wrerr(); if(oflag) { if(dirfstat(f, &d) < 0) perror(file); else { d.atime = bp->date; d.mtime = bp->date; if(dirwstat(file, &d) < 0) perror(file); } } free(bp->member); close(f); } free(bp); if (count && ++i >= count) break; } else { skip(fd, bp->size); free(bp); } } close(fd);}voidpcmd(char *arname, int count, char **files){ int fd; Armember *bp; fd = openar(arname, OREAD, 0); while(bp = getdir(fd)) { if(count == 0 || match(count, files)) { if(vflag) print("\n<%s>\n\n", file); arcopy(fd, 0, bp); if (write(1, bp->member, bp->size) < 0) wrerr(); } else skip(fd, bp->size); free(bp); } close(fd);}voidmcmd(char *arname, int count, char **files){ int fd; Arfile *ap; Armember *bp; if (count == 0) return; fd = openar(arname, ORDWR, 0); astart = newtempfile(artemp); amiddle = newtempfile(movtemp); aend = 0; ap = astart; while(bp = getdir(fd)) { if (bamatch(file, poname)) { aend = newtempfile(tailtemp); ap = aend; } if(match(count, files)) { mesg('m', file); arcopy(fd, amiddle, bp); } else arcopy(fd, 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);}voidtcmd(char *arname, int count, char **files){ int fd; Armember *bp; char name[ARNAMESIZE+1]; fd = openar(arname, OREAD, 0); while(bp = getdir(fd)) { if(count == 0 || match(count, files)) { if(vflag) longt(bp); trim(file, name, sizeof(name)); Bprint(&bout, "%s\n", name); } skip(fd, bp->size); free(bp); } close(fd);}voidqcmd(char *arname, int count, char **files){ int fd, fd2, i; Armember *bp; 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); } /* leave note group behind when writing archive; i.e. sidestep interrupts */ rfork(RFNOTEG); seek(fd, 0, 2); bp = newmember(); for(i=0; i<count && files[i]; i++) { file = files[i]; files[i] = 0; fd2 = open(file, OREAD); if(fd2 < 0) fprint(2, "ar: %s cannot open\n", file); else { mesg('q', file); armove(fd2, 0, bp); if (!arwrite(fd, bp)) wrerr(); free(bp->member); bp->member = 0; close(fd2); } } free(bp); close(fd);}/* * open an archive and validate its header */intopenar(char *arname, int mode, int errok){ int fd; char mbuf[SARMAG]; fd = open(arname, mode); if(fd >= 0){ if(read(fd, mbuf, SARMAG) != SARMAG || strncmp(mbuf, ARMAG, SARMAG)) { fprint(2, "ar: %s not in archive format\n", arname); exits("error"); } }else if(!errok){ fprint(2, "ar: cannot open %s: %r\n", arname); exits("error"); } return fd;}/* * create an archive and set its header */intarcreate(char *arname){ int fd; fd = create(arname, OWRITE, 0664); if(fd < 0){ fprint(2, "ar: cannot create %s: %r\n", arname); exits("error"); } if(write(fd, ARMAG, SARMAG) != SARMAG) wrerr(); return fd;}/* * error handling */voidwrerr(void){ perror("ar: write error"); exits("error");} voidrderr(void){ perror("ar: read error"); exits("error");} voidphaseerr(int offset){ fprint(2, "ar: phase error at offset %d\n", offset); exits("error");} voidusage(void){ fprint(2, "usage: ar [%s][%s] archive files ...\n", opt, man); exits("error");}/*Lines 1–500 of 924. Load more
/* * ar - portable (ascii) format version */ #include <u.h> #include <libc.h> #include <bio.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. Temp file astart * contains existing members up to and including the pivot member. Temp * file amiddle contains new files moved or inserted behind the pivot. * Temp file aend, contains the existing members of the archive 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 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 */ Armember *head; /* head of member chain */ Armember *tail; /* tail of member chain */ } Arfile; /* constants and flags */ char *man = "mrxtdpq"; char *opt = "uvnbailo"; char artemp[] = "/tmp/vXXXXX"; char movtemp[] = "/tmp/v1XXXXX"; char tailtemp[] = "/tmp/v2XXXXX"; int aflag; /* command line flags */ int bflag; int cflag; int dflag; int iflag; int lflag; int mflag; int nflag; int oflag; int pflag; int qflag; int rflag; int tflag; int uflag; int vflag; int xflag; Arfile *astart, *amiddle, *aend; /* Temp file control block pointers */ #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; void arcopy(int, Arfile*, Armember*); int arcreate(char*); void arfree(Arfile*); void arinsert(Arfile*, Armember*); char *armalloc(int); void armove(int, Arfile*, Armember*); void arread(int, Armember*, int); void arstream(int, Arfile*); int arwrite(int, Armember*); int bamatch(char*, char*); Armember *getdir(int); int getspace(void); void install(char*, Arfile*, Arfile*, Arfile*); void longt(Armember*); int match(int, char**); void mesg(int, char*); Arfile *newtempfile(char*); Armember *newmember(void); int openar(char*, int, int); int page(Arfile*); void pmode(long); void select(int*, long); void setcom(void(*)(char*, int, char**)); void skip(int, long); void trim(char*, char*, int); void usage(void); void wrerr(void); 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 'n': nflag = 1; 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, fd2; int i; Arfile *ap; Armember *bp; Dir d; fd = openar(arname, ORDWR, 1); astart = newtempfile(artemp); ap = astart; aend = 0; while (fd > 0) { bp = getdir(fd); if (!bp) break; if (bamatch(file, poname)) { /* check for pivot */ aend = newtempfile(tailtemp); ap = aend; } if (count == 0 || match(count, files)) { fd2 = open(file, OREAD); if (fd2 < 0) { if (count != 0) fprint(2, "ar: cannot open %s\n", file); arcopy(fd, ap, bp); } else if (uflag) { if (dirfstat(fd2, &d) < 0) { fprint(2, "ar: cannot stat %s\n", file); arcopy(fd, ap, bp); } else if (d.mtime <= bp->date) arcopy(fd, ap, bp); else { mesg('r', file); skip(fd, bp->size); armove(fd2, ap, bp); } close(fd2); } else { mesg('r', file); skip(fd, bp->size); armove(fd2, ap, bp); close(fd2); } } else arcopy(fd, ap, bp); } if(fd < 0) { if(!cflag) fprint(2, "ar: creating %s\n", arname); } else 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; fd2 = open(file, OREAD); if (fd2 < 0) fprint(2, "ar: %s cannot open\n", file); else { mesg('a', file); armove(fd2, astart, newmember()); close(fd2); } } install(arname, astart, 0, aend); } void dcmd(char *arname, int count, char **files) { Armember *bp; int fd; if (!count) return; fd = openar(arname, ORDWR, 0); astart = newtempfile(artemp); while (bp = getdir(fd)) { if(match(count, files)) { mesg('d', file); skip(fd, bp->size); } else arcopy(fd, astart, bp); } install(arname, astart, 0, 0); } void xcmd(char *arname, int count, char **files) { int fd, f, mode, i; Armember *bp; Dir d; fd = openar(arname, OREAD, 0); i = 0; while (bp = getdir(fd)) { 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(fd, bp->size); } else { mesg('x', file); arcopy(fd, 0, bp); if (write(f, bp->member, bp->size) < 0) wrerr(); if(oflag) { if(dirfstat(f, &d) < 0) perror(file); else { d.atime = bp->date; d.mtime = bp->date; if(dirwstat(file, &d) < 0) perror(file); } } free(bp->member); close(f); } free(bp); if (count && ++i >= count) break; } else { skip(fd, bp->size); free(bp); } } close(fd); } void pcmd(char *arname, int count, char **files) { int fd; Armember *bp; fd = openar(arname, OREAD, 0); while(bp = getdir(fd)) { if(count == 0 || match(count, files)) { if(vflag) print("\n<%s>\n\n", file); arcopy(fd, 0, bp); if (write(1, bp->member, bp->size) < 0) wrerr(); } else skip(fd, bp->size); free(bp); } close(fd); } void mcmd(char *arname, int count, char **files) { int fd; Arfile *ap; Armember *bp; if (count == 0) return; fd = openar(arname, ORDWR, 0); astart = newtempfile(artemp); amiddle = newtempfile(movtemp); aend = 0; ap = astart; while(bp = getdir(fd)) { if (bamatch(file, poname)) { aend = newtempfile(tailtemp); ap = aend; } if(match(count, files)) { mesg('m', file); arcopy(fd, amiddle, bp); } else arcopy(fd, 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); } void tcmd(char *arname, int count, char **files) { int fd; Armember *bp; char name[ARNAMESIZE+1]; fd = openar(arname, OREAD, 0); while(bp = getdir(fd)) { if(count == 0 || match(count, files)) { if(vflag) longt(bp); trim(file, name, sizeof(name)); Bprint(&bout, "%s\n", name); } skip(fd, bp->size); free(bp); } close(fd); } void qcmd(char *arname, int count, char **files) { int fd, fd2, i; Armember *bp; 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); } /* leave note group behind when writing archive; i.e. sidestep interrupts */ rfork(RFNOTEG); seek(fd, 0, 2); bp = newmember(); for(i=0; i<count && files[i]; i++) { file = files[i]; files[i] = 0; fd2 = open(file, OREAD); if(fd2 < 0) fprint(2, "ar: %s cannot open\n", file); else { mesg('q', file); armove(fd2, 0, bp); if (!arwrite(fd, bp)) wrerr(); free(bp->member); bp->member = 0; close(fd2); } } free(bp); close(fd); } /* * open an archive and validate its header */ int openar(char *arname, int mode, int errok) { int fd; char mbuf[SARMAG]; fd = open(arname, mode); if(fd >= 0){ if(read(fd, mbuf, SARMAG) != SARMAG || strncmp(mbuf, ARMAG, SARMAG)) { fprint(2, "ar: %s not in archive format\n", arname); exits("error"); } }else if(!errok){ fprint(2, "ar: cannot open %s: %r\n", arname); exits("error"); } return fd; } /* * create an archive and set its header */ int arcreate(char *arname) { int fd; fd = create(arname, OWRITE, 0664); if(fd < 0){ fprint(2, "ar: cannot create %s: %r\n", arname); exits("error"); } if(write(fd, ARMAG, SARMAG) != SARMAG) wrerr(); return fd; } /* * error handling */ void wrerr(void) { perror("ar: write error"); exits("error"); } void rderr(void) { perror("ar: read error"); exits("error"); } void phaseerr(int offset) { fprint(2, "ar: phase error at offset %d\n", offset); exits("error"); } void usage(void) { fprint(2, "usage: ar [%s][%s] archive files ...\n", opt, man); exits("error"); } /*