mark@cbosgd.UUCP (Mark Horton) (07/17/84)
Enclosed is a pair of programs to pack and unpack in the portable archive format. For chicken-and-egg reasons, they are in shell archive format. echo x - Makefile cat >Makefile <<'!Funky!Stuff!' par: arwrite.o main.o cc -o par main.o arwrite.o unpar: unpar.o cc -o unpar unpar.o clean: rm par unpar *.o !Funky!Stuff! echo x - README cat >README <<'!Funky!Stuff!' These programs pack and unpack files in the portable archive format. This format is compatible with the ar command on 4BSD and System V release 2. These programs are available for use by anyone without fee or license. The par program packs into portable archive format. The files to write are named on the command line, the resulting archive is written on stdout: par file1 file2 ... filen > files.a The unpar program unpacks from stdin and writes the named files out directly: unpar < files.a !Funky!Stuff! echo x - arwrite.c cat >arwrite.c <<'!Funky!Stuff!' /* * COPYRIGHT (c) HEWLETT-PACKARD COMPANY, 1984 * * Permission is granted for unlimited modification, use, and * distribution except that this software may not be sold for * profit. No warranty is implied or expressed. * *Author: * Paul Bame, HEWLETT-PACKARD LOGIC SYSTEMS DIVISION - Colorado Springs * { ihnp4!hpfcla | hplabs | harpo!hp-pcd }!hp-lsd!paul */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #define ARFMAG "`\n" #define ARMAG "!<arch>\n" int arwrite(filename,stream) char *filename; FILE *stream; /* * Write the file denoted by 'filename' to 'stream' in portable ar format. * Any stream positioning is assumed to already be done. * * arwrite() normally returns 0 but returns -1 in case of errors. errno * may be inspected to determine the cause of the error. * * If necessary, the stream is padded with \n's to match the even boundary * condition. */ { struct stat statbuf; FILE *instream; long i; /* stat() the file to get the stuff for the header */ if( stat(filename,&statbuf) < 0 ) { /* error! */ return(-1); } /* Open file for reading */ if( (instream = fopen(filename,"r")) == NULL ) { /* error! */ return(-1); } /* Now write the header */ /* This information gleaned from ar(4) in V.2 */ fprintf(stream, "%-16s%-12ld%-6d%-6d%-8o%-10ld%2s", filename, statbuf.st_mtime, statbuf.st_uid, statbuf.st_gid, statbuf.st_mode, statbuf.st_size, ARFMAG ); /* And copy the file */ /* Note that there is no error recovery here! */ for( i = 0 ; i < statbuf.st_size ; i++ ) { fputc(fgetc(instream),stream); } /* and close */ close(instream); /* and pad output stream */ if( (ftell(stream) & 0x1) != 0 ) { /* if offset is odd, pad with a nuline */ fputc('\n',stream); } return(0); } arhdwrite(stream) FILE *stream; /* * Write the archive header onto 'stream' */ { fprintf(stream,"%s",ARMAG); } !Funky!Stuff! echo x - main.c cat >main.c <<'!Funky!Stuff!' /* * COPYRIGHT (c) HEWLETT-PACKARD COMPANY, 1984 * * Permission is granted for unlimited modification, use, and * distribution except that this software may not be sold for * profit. No warranty is implied or expressed. * *Author: * Paul Bame, HEWLETT-PACKARD LOGIC SYSTEMS DIVISION - Colorado Springs * { ihnp4!hpfcla | hplabs | harpo!hp-pcd }!hp-lsd!paul */ #include <stdio.h> extern int arwrite(); extern arhdwrite(); main(argc,argv) int argc; char *argv[]; /* * Write the named files (in argv) to stdout in portable ar format. */ { int i; if( argc < 2 ) { fprintf(stderr,"Usage: %s file1 [file...]\n",argv[0]); exit(1); } /* Write the header */ arhdwrite(stdout); /* and the files */ for( i = 1 ; i < argc ; i++ ) { if( arwrite(argv[i],stdout) < 0 ) { perror(argv[i]); exit(1); } } exit(0); } !Funky!Stuff! echo x - sample cat >sample <<'!Funky!Stuff!' !<arch> foo 458764309 12 0 100666 29 ` Sun Jul 15 14:31:49 EDT 1984 bar 458764313 12 0 100666 189 ` sarge ttya Jul 13 10:02 jgs ttys1 Jul 15 10:45 mark ttyp0 Jul 15 14:07 (cbosgd) mark ttyp1 Jul 13 09:36 mark ttyp2 Jul 13 09:36 mark ttyp3 Jul 13 16:57 !Funky!Stuff! echo x - unpar.c cat >unpar.c <<'!Funky!Stuff!' /* unpack portable archives - written by Bill Welch */ #include <stdio.h> #include <sys/types.h> char buf[512]; main() { char name[80]; struct utimbuf { time_t actime; time_t modtime; } times; long mtime; int uid, gid, mode; long len, i; FILE *fp; while(gets(buf) != NULL){ if (buf[strlen(buf) - 1] == '`') { printf("%s\n", buf); sscanf(buf, "%s %ld %d %d %o %ld", name,&mtime,&uid,&gid, &mode, &len); printf("%s %ld\n", name, len); fp = fopen(name, "w"); for (i=0; i<len; i++) putc(getchar(), fp); fclose(fp); times.actime = times.modtime = mtime; /* If you don't have utime, just remove next 4 lines */ if( utime(name,×) < 0 ) { perror("Can't modify date"); } if( chmod(name,mode) < 0 ) { perror("Can't modify mode"); } } } } !Funky!Stuff!