From 3c7511780bce6616ffc6e5ad5f039d610cfc4123 Mon Sep 17 00:00:00 2001 From: ceriel Date: Mon, 12 Jan 1987 17:21:59 +0000 Subject: [PATCH] Initial revision --- util/arch/Makefile | 47 +++ util/arch/aal.1 | 79 +++++ util/arch/arch.1 | 83 ++++++ util/arch/archiver.c | 679 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 888 insertions(+) create mode 100644 util/arch/Makefile create mode 100644 util/arch/aal.1 create mode 100644 util/arch/arch.1 create mode 100644 util/arch/archiver.c diff --git a/util/arch/Makefile b/util/arch/Makefile new file mode 100644 index 000000000..633048ca9 --- /dev/null +++ b/util/arch/Makefile @@ -0,0 +1,47 @@ +EMHOME = ../.. +EMH = $(EMHOME)/h +EMBIN = $(EMHOME)/bin +LIB = $(EMHOME)/modules/lib + +LIBS = $(LIB)/libobject.a $(LIB)/libprint.a \ + $(LIB)/libstring.a $(LIB)/libsystem.a + +CFLAGS=-O -I$(EMH) + +all: arch aal + +arch: arch.o + $(CC) -n -o arch arch.o $(LIBS) + +aal: aal.o + $(CC) -i -o aal aal.o $(LIBS) + +arch.o: $(EMH)/arch.h archiver.c + $(CC) $(CFLAGS) -c archiver.c + mv archiver.o arch.o + +aal.o: $(EMH)/arch.h archiver.c $(EMH)/ranlib.h $(EMH)/out.h + $(CC) -DAAL $(CFLAGS) -c archiver.c + mv archiver.o aal.o + +clean: + rm -f aal arch *.o *.old + +install : all + rm -f $(EMBIN)/arch $(EMBIN)/aal + cp aal $(EMBIN)/aal + cp arch $(EMBIN)/arch + rm -f $(EMHOME)/man/arch.1 $(EMHOME)/man/aal.1 + cp aal.1 $(EMHOME)/man/aal.1 + cp arch.1 $(EMHOME)/man/arch.1 + +cmp : all + -cmp aal $(EMBIN)/aal + -cmp arch $(EMBIN)/arch + -cmp aal.1 $(EMHOME)/man/aal.1 + -cmp arch.1 $(EMHOME)/man/arch.1 + +opr: + make pr ^ opr +pr: + @pr Makefile archiver.c diff --git a/util/arch/aal.1 b/util/arch/aal.1 new file mode 100644 index 000000000..ce73e5e0b --- /dev/null +++ b/util/arch/aal.1 @@ -0,0 +1,79 @@ +.\" $Header$ +.TH ARCH 1ACK +.SH NAME +aal \- archive and library maintainer +.SH SYNOPSIS +.B aal +key afile name ... +.SH DESCRIPTION +.I Aal +maintains groups of ACK-object files +combined into a single archive file. +An index-table is automatically maintained. +The link editor +.IR led (6) +only understands archives made with +.IR aal . +.PP +.I Key +is one character from the set +.B adrtx, +optionally concatenated with +one or more of +.B vl. +.I Afile +is the archive file. +The +.I names +are constituent files in the archive file. +The meanings of the +.I key +characters are: +.TP +.B d +Delete the named files from the archive file. +.TP +.B a +Append the named files to the archive file. +.TP +.B r +Replace the named files in the archive file. +New files are placed at the end. +.TP +.B t +Print a table of contents of the archive file. +If no names are given, all files in the archive are listed. +If names are given, only those files are listed. +.TP +.B x +Extract the named files. +If no names are given, all files in the archive are +extracted. +In neither case does +.B x +alter the archive file. +.TP +.B v +Verbose. +Under the verbose option, +.I aal +gives a file-by-file +description of the making of a +new archive file from the old archive and the constituent files. +When used with +.B t, +it gives a long listing of all information about the files. +.TP +.B l +Local. +Normally +.I aal +places its temporary files in the directory /tmp. +This option causes them to be placed in the local directory. +.SH FILES +/tmp/ar.* temporaries +.SH "SEE ALSO" +em_ass(I), arch(V), +.SH BUGS +If the same file is mentioned twice in an argument list, +it may be put in the archive twice. diff --git a/util/arch/arch.1 b/util/arch/arch.1 new file mode 100644 index 000000000..7d688307a --- /dev/null +++ b/util/arch/arch.1 @@ -0,0 +1,83 @@ +.\" $Header$ +.TH ARCH 1ACK +.SH NAME +arch \- archive and library maintainer +.SH SYNOPSIS +.B arch +key afile name ... +.SH DESCRIPTION +.I Arch +maintains groups of files +combined into a single archive file. +The Amsterdam compiler kit provides its own archiver with a +fixed, machine-independent format, much like the UNIX-V7 +archive format. +.PP +.I Key +is one character from the set +.B adrtpx, +optionally concatenated with +one or more of +.B vl. +.I Afile +is the archive file. +The +.I names +are constituent files in the archive file. +The meanings of the +.I key +characters are: +.TP +.B d +Delete the named files from the archive file. +.TP +.B a +Append the named files to the archive file. +.TP +.B r +Replace the named files in the archive file. +New files are placed at the end. +.TP +.B t +Print a table of contents of the archive file. +If no names are given, all files in the archive are listed. +If names are given, only those files are listed. +.TP +.B p +Print the named files in the archive. +.TP +.B x +Extract the named files. +If no names are given, all files in the archive are +extracted. +In neither case does +.B x +alter the archive file. +.TP +.B v +Verbose. +Under the verbose option, +.I arch +gives a file-by-file +description of the making of a +new archive file from the old archive and the constituent files. +When used with +.B t, +it gives a long listing of all information about the files. +When used with +.BR p , +it precedes each file with a name. +.TP +.B l +Local. +Normally +.I arch +places its temporary files in the directory /tmp. +This option causes them to be placed in the local directory. +.SH FILES +/tmp/ar.* temporaries +.SH "SEE ALSO" +em_ass(I), arch(V), +.SH BUGS +If the same file is mentioned twice in an argument list, +it may be put in the archive twice. diff --git a/util/arch/archiver.c b/util/arch/archiver.c new file mode 100644 index 000000000..2187194e1 --- /dev/null +++ b/util/arch/archiver.c @@ -0,0 +1,679 @@ +/* ar - archiver Author: Michiel Huisjes */ +/* Made into arch/aal by Ceriel Jacobs + */ + +static char RcsId[] = "$Header$"; + +/* + * Usage: [arch|aal] [adprtvx] archive [file] ... + * v: verbose + * x: extract + * a: append + * r: replace (append when not in archive) + * d: delete + * t: print contents of archive + * p: print named files + * l: temporaries in current directory instead of /tmp + */ + +#include +#include +#include +#include +#ifdef AAL +#include +#include +#define MAGIC_NUMBER AALMAG +#ifdef AAL +#define TABSZ 2000 /* maximum # of ranlib table entries */ +#define STRTABSZ 8*TABSZ /* maximum size of string table */ +long offset; +struct ranlib tab[TABSZ]; +long tnum = 0; +char tstrtab[STRTABSZ]; +long tssiz = 0; +char *malloc(), *strcpy(); +long tell(); +long time(); +#endif AAL +#else +#define MAGIC_NUMBER ARMAG +#endif + +#define odd(nr) (nr & 01) +#define even(nr) (odd(nr) ? nr + 1 : nr) + +typedef char BOOL; +#define FALSE 0 +#define TRUE 1 + +#define READ 0 +#define APPEND 2 +#define CREATE 1 + +#define MEMBER struct ar_hdr + +#define NIL_PTR ((char *) 0) +#define NIL_MEM ((MEMBER *) 0) +#define NIL_LONG ((long *) 0) + +#define IO_SIZE (10 * 1024) + +#define equal(str1, str2) (!strncmp((str1), (str2), 14)) + +BOOL verbose; +BOOL app_fl; +BOOL ex_fl; +BOOL show_fl; +BOOL pr_fl; +BOOL rep_fl; +BOOL del_fl; +BOOL local_fl; + +int ar_fd; + +char io_buffer[IO_SIZE]; + +char *progname; + +char temp_buf[32]; +char *temp_arch = &temp_buf[0]; +extern char *mktemp(); +extern char *ctime(); + +usage() +{ + error(TRUE, "usage: %s %s archive [file] ...\n", + progname, +#ifdef AAL + "[adrtxvl]" +#else + "[adprtxvl]" +#endif + ); +} + +/*VARARGS2*/ +error(quit, str1, str2, str3, str4) +BOOL quit; +char *str1, *str2, *str3, *str4; +{ + char errbuf[256]; + + sprint(errbuf, str1, str2, str3, str4); + write(2, errbuf, strlen(errbuf)); + if (quit) { + unlink(temp_arch); + _exit(1); + } +} + +char *basename(path) +char *path; +{ + register char *ptr = path; + register char *last = NIL_PTR; + + while (*ptr != '\0') { + if (*ptr == '/') + last = ptr; + ptr++; + } + if (last == NIL_PTR) + return path; + if (*(last + 1) == '\0') { + *last = '\0'; + return basename(path); + } + return last + 1; +} + +extern unsigned int rd_unsigned2(); + +open_archive(name, mode) +register char *name; +register int mode; +{ + unsigned short magic = 0; + int fd; + + if (mode == CREATE) { + if ((fd = creat(name, 0644)) < 0) + error(TRUE, "cannot creat %s\n", name); + magic = MAGIC_NUMBER; + wr_int2(fd, magic); + return fd; + } + + if ((fd = open(name, mode)) < 0) { + if (mode == APPEND) { + close(open_archive(name, CREATE)); + error(FALSE, "%s: creating %s\n", progname, name); + return open_archive(name, APPEND); + } + error(TRUE, "cannot open %s\n", name); + } + lseek(fd, 0L, 0); + magic = rd_unsigned2(fd); + if (magic != MAGIC_NUMBER) + error(TRUE, "%s is not in ar format\n", name); + + return fd; +} + +catch() +{ + unlink(temp_arch); + _exit (2); +} + +main(argc, argv) +int argc; +char *argv[]; +{ + register char *ptr; + int pow, pid; + + progname = argv[0]; + + if (argc < 3) + usage(); + + for (ptr = argv[1]; *ptr; ptr++) { + switch (*ptr) { + case 't' : + show_fl = TRUE; + break; + case 'v' : + verbose = TRUE; + break; + case 'x' : + ex_fl = TRUE; + break; + case 'a' : + app_fl = TRUE; + break; +#ifndef AAL + case 'p' : + pr_fl = TRUE; + break; +#endif + case 'd' : + del_fl = TRUE; + break; + case 'r' : + rep_fl = TRUE; + break; + case 'l' : + local_fl = TRUE; + break; + default : + usage(); + } + } + if (local_fl) strcpy(temp_arch, "ar.XXXXXX"); + else strcpy(temp_arch, "/tmp/ar.XXXXXX"); + + if (app_fl + ex_fl + del_fl + rep_fl + show_fl + pr_fl != 1) + usage(); + + if (rep_fl || del_fl +#ifdef AAL + || app_fl +#endif + ) { + mktemp(temp_arch); + } + + signal(SIGINT, catch); + get(argc, argv); + + return 0; +} + +MEMBER * +get_member() +{ + static MEMBER member; + register int ret; + +again: + if ((ret = rd_arhdr(ar_fd, &member)) == 0) + return NIL_MEM; +#ifdef AAL + if (equal(SYMDEF, member.ar_name)) { + lseek(ar_fd, member.ar_size, 1); + goto again; + } +#endif + return &member; +} + +char *get_mode(); + +get(argc, argv) +int argc; +register char *argv[]; +{ + register MEMBER *member; + int i = 0; + int temp_fd, read_chars; + + ar_fd = open_archive(argv[2], (show_fl || pr_fl) ? READ : APPEND); + if (rep_fl || del_fl +#ifdef AAL + || app_fl +#endif + ) + temp_fd = open_archive(temp_arch, CREATE); + while ((member = get_member()) != NIL_MEM) { + if (argc > 3) { + for (i = 3; i < argc; i++) { + if (equal(basename(argv[i]), member->ar_name)) + break; + } + if (i == argc || app_fl) { + if (rep_fl || del_fl +#ifdef AAL + || app_fl +#endif + ) { +#ifdef AAL + if (i != argc) { + print("%s: already in archive\n", argv[i]); + argv[i] = ""; + } +#endif + wr_arhdr(temp_fd, member); + copy_member(member, ar_fd, temp_fd, 0); + } +#ifndef AAL + else { + if (app_fl && i != argc) { + print("%s: already in archive\n", argv[i]); + argv[i] = ""; + } + lseek(ar_fd, even(member->ar_size),1); + } +#endif + continue; + } + } + if (ex_fl || pr_fl) + extract(member); + else { + if (rep_fl) + add(argv[i], temp_fd, "r - %s\n"); + else if (show_fl) { + char buf[sizeof(member->ar_name) + 2]; + register char *p = buf, *q = member->ar_name; + + while (q <= &member->ar_name[sizeof(member->ar_name)-1] && *q) { + *p++ = *q++; + } + *p++ = '\n'; + *p = '\0'; + if (verbose) { + char *mode = get_mode(member->ar_mode); + char *date = ctime(&(member->ar_date)); + + *(date + 16) = '\0'; + *(date + 24) = '\0'; + + print("%s%3u/%u%7ld %s %s %s", + mode, + (unsigned) member->ar_uid, + (unsigned) member->ar_gid, + member->ar_size, + date+4, + date+20, + buf); + } + else print(buf); + } + else if (del_fl) + show("d - %s\n", member->ar_name); + lseek(ar_fd, even(member->ar_size), 1); + } + argv[i] = ""; + } + + if (argc > 3) { + for (i = 3; i < argc; i++) + if (argv[i][0] != '\0') { +#ifndef AAL + if (app_fl) + add(argv[i], ar_fd, "a - %s\n"); + else +#endif + if (rep_fl +#ifdef AAL + || app_fl +#endif + ) + add(argv[i], temp_fd, "a - %s\n"); + else { + print("%s: not found\n", argv[i]); + } + } + } + + if (rep_fl || del_fl +#ifdef AAL + || app_fl +#endif + ) { + signal(SIGINT, SIG_IGN); + close(ar_fd); + close(temp_fd); + ar_fd = open_archive(argv[2], CREATE); + temp_fd = open_archive(temp_arch, APPEND); +#ifdef AAL + write_symdef(); +#endif + while ((read_chars = read(temp_fd, io_buffer, IO_SIZE)) > 0) + mwrite(ar_fd, io_buffer, read_chars); + close(temp_fd); + unlink(temp_arch); + } + close(ar_fd); +} + +add(name, fd, mess) +char *name; +int fd; +char *mess; +{ + static MEMBER member; + register int read_chars; + struct stat status; + int src_fd; + + if (stat(name, &status) < 0) { + error(FALSE, "cannot find %s\n", name); + return; + } + else if ((src_fd = open(name, 0)) < 0) { + error(FALSE, "cannot open %s\n", name); + return; + } + + strncpy (member.ar_name, basename (name), sizeof(member.ar_name)); + member.ar_uid = status.st_uid; + member.ar_gid = status.st_gid; + member.ar_mode = status.st_mode; + member.ar_date = status.st_mtime; + member.ar_size = status.st_size; + wr_arhdr(fd, &member); +#ifdef AAL + do_object(src_fd, member.ar_size); + lseek(src_fd, 0L, 0); + offset += AR_TOTAL + even(member.ar_size); +#endif + while (status.st_size > 0) { + int x = IO_SIZE; + + read_chars = x; + if (status.st_size < x) { + x = status.st_size; + read_chars = x; + status.st_size = 0; + x = even(x); + } + else status.st_size -= x; + if (read(src_fd, io_buffer, read_chars) != read_chars) + error(FALSE,"%s seems to shrink\n", name); + mwrite(fd, io_buffer, x); + } + + if (verbose) + show(mess, name); + close(src_fd); +} + +extract(member) +register MEMBER *member; +{ + int fd = 1; + + if (pr_fl == FALSE && (fd = creat(member->ar_name, 0644)) < 0) { + error(FALSE, "cannot create %s\n", member->ar_name); + return; + } + + if (verbose) { + if (pr_fl == FALSE) show("x - %s\n", member->ar_name); + else show("\n<%s>\n\n", member->ar_name); + } + + copy_member(member, ar_fd, fd, 1); + + if (fd != 1) + close(fd); + if (pr_fl == FALSE) chmod(member->ar_name, member->ar_mode); +} + +copy_member(member, from, to, extracting) +register MEMBER *member; +int from, to; +{ + register int rest; + long mem_size = member->ar_size; + BOOL is_odd = odd(mem_size) ? TRUE : FALSE; + +#ifdef AAL + if (! extracting) { + long pos = lseek(from, 0L, 1); + + do_object(from, mem_size); + offset += AR_TOTAL + even(mem_size); + lseek(from, pos, 0); + } +#endif + do { + rest = mem_size > (long) IO_SIZE ? IO_SIZE : (int) mem_size; + if (read(from, io_buffer, rest) != rest) + error(TRUE, "read error on %s\n", member->ar_name); + mwrite(to, io_buffer, rest); + mem_size -= (long) rest; + } while (mem_size != 0L); + + if (is_odd) { + lseek(from, 1L, 1); + if (! extracting) + lseek(to, 1L, 1); + } +} + +char * +get_mode(mode) +register int mode; +{ + static char mode_buf[11]; + register int tmp = mode; + int i; + + mode_buf[9] = ' '; + for (i = 0; i < 3; i++) { + mode_buf[i * 3] = (tmp & S_IREAD) ? 'r' : '-'; + mode_buf[i * 3 + 1] = (tmp & S_IWRITE) ? 'w' : '-'; + mode_buf[i * 3 + 2] = (tmp & S_IEXEC) ? 'x' : '-'; + tmp <<= 3; + } + if (mode & S_ISUID) + mode_buf[2] = 's'; + if (mode & S_ISGID) + mode_buf[5] = 's'; + return mode_buf; +} + +wr_fatal() +{ + error(TRUE, "write error\n"); +} + +rd_fatal() +{ + error(TRUE, "read error\n"); +} + +mwrite(fd, address, bytes) +int fd; +register char *address; +register int bytes; +{ + if (write(fd, address, bytes) != bytes) + error(TRUE, "write error\n"); +} + +show(s, name) +char *s, *name; +{ + MEMBER x; + char buf[sizeof(x.ar_name)+1]; + register char *p = buf, *q = name; + + while (q <= &name[sizeof(x.ar_name)-1] && *q) *p++ = *q++; + *p++ = '\0'; + print(s, buf); +} + +#ifdef AAL +/* + * Write out the ranlib table: first 4 bytes telling how many ranlib structs + * there are, followed by the ranlib structs, + * then 4 bytes giving the size of the string table, followed by the string + * table itself. + */ +write_symdef() +{ + register struct ranlib *ran; + register char *str; + register int i; + register long delta; + MEMBER arbuf; + + if (odd(tssiz)) + tstrtab[tssiz++] = '\0'; + for (i = 0; i < sizeof(arbuf.ar_name); i++) + arbuf.ar_name[i] = '\0'; + strcpy(arbuf.ar_name, SYMDEF); + arbuf.ar_size = 4 + 2 * 4 * tnum + 4 + tssiz; + time(&arbuf.ar_date); + arbuf.ar_uid = getuid(); + arbuf.ar_gid = getgid(); + arbuf.ar_mode = 0444; + wr_arhdr(ar_fd,&arbuf); + wr_long(ar_fd, tnum); + /* + * Account for the space occupied by the magic number + * and the ranlib table. + */ + delta = 2 + AR_TOTAL + arbuf.ar_size; + for (ran = tab; ran < &tab[tnum]; ran++) { + ran->ran_pos += delta; + } + + wr_ranlib(ar_fd, tab, tnum); + wr_long(ar_fd, tssiz); + wr_bytes(ar_fd, tstrtab, tssiz); +} + +/* + * Return whether the bytes in `buf' form a good object header. + * The header is put in `headp'. + */ +int +is_outhead(headp) + register struct outhead *headp; +{ + + return !BADMAGIC(*headp) && headp->oh_nname != 0; +} + +do_object(f, size) + long size; +{ + struct outhead headbuf; + + if (size < SZ_HEAD) { + /* It can't be an object file. */ + return; + } + /* + * Read a header to see if it is an object file. + */ + if (! rd_fdopen(f)) { + rd_fatal(); + } + rd_ohead(&headbuf); + if (!is_outhead(&headbuf)) { + return; + } + do_names(&headbuf); +} + +/* + * First skip the names and read in the string table, then seek back to the + * name table and read and write the names one by one. Update the ranlib table + * accordingly. + */ +do_names(headp) + struct outhead *headp; +{ + register char *strings; + register int nnames = headp->oh_nname; +#define NNAMES 100 + struct outname namebuf[NNAMES]; + char *xxx; + + if ( headp->oh_nchar != (unsigned int)headp->oh_nchar || + (strings = malloc((unsigned int)headp->oh_nchar)) == (char *)0 + ) { + error(TRUE, "string table too big\n"); + } + rd_string(strings, headp->oh_nchar); + xxx = strings - OFF_CHAR(*headp); + while (nnames) { + int i = nnames >= NNAMES ? NNAMES : nnames; + register struct outname *p = namebuf; + + nnames -= i; + rd_name(namebuf, i); + while (i--) { + if (p->on_foff == (long)0) + continue; /* An unrecognizable name. */ + p->on_mptr = xxx + p->on_foff; + /* + * Only enter names that are exported and are really + * defined. + */ + if ( (p->on_type & S_EXT) && + (p->on_type & S_TYP) != S_UND && + !(p->on_type & S_COM) + ) + enter_name(p); + p++; + } + } + free(strings); +} + +enter_name(namep) + struct outname *namep; +{ + register char *cp; + + if (tnum >= TABSZ) { + error(TRUE, "symbol table overflow\n"); + } + tab[tnum].ran_off = tssiz; + tab[tnum].ran_pos = offset; + + for (cp = namep->on_mptr; tstrtab[tssiz++] = *cp++;) + if (tssiz >= STRTABSZ) { + error(TRUE, "string table overflow\n"); + } + tnum++; +} +#endif AAL -- 2.34.1