roy@phri.UUCP (Roy Smith) (05/04/85)
> The bottom line is that I have a program which reads cpio tapes > which I wrote myself working only from the documentation (that makes it > public domain, yes?). If anybody wants it, it's yours for the asking. Well, folks... here it is: ------Taketh all that lies above this line, and cast it into the void----- # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by phri!roy on Fri May 3 22:09:00 EDT 1985 # Contents: READ_ME cpiolist.c cpioextract.c echo x - READ_ME sed 's/^@//' > "READ_ME" <<'@//E*O*F READ_ME//' What we have here is a stripped-down pair of programs which can, in the barest marginal sense, allow you to read cpio tapes. They were written for one particular purpose without the expectation that they would ever be used again, so no attempt was made to support any functionality beyond the dead minimum. The reason I wrote these programs was to be able to read my Sys5 distribution tapes on my 4.2 bsd system. The idea was that I would use cpiolist to get a listing of all the files on the /usr file system, and then (once I knew the names of the required files) use cpioextract to pull off the source for the 'real' cpio, compile that under 4.2, and use it to do the rest of the job correctly. Notice 3 important things. First, cpioextract only extracts a single file per invocation. Second, it expects all of the directories along the path to that file to be created already. Third, these programs only know about binary header type cpio archives (i.e. tapes made WITHOUT the -c flag). This is the way the Sys5 distribution was done (at least the distribution I got). Various caveats: These programs were written from the Sys 5 documentation describing the cpio file formats. From what I can gather, since I did not look at the Sys 5 cpio sources while I was writing this, it should qualify as public domain. The primary purpose of these programs is to bootstrap a full-fledged cpio from a Sys 5 distribution tape onto a system which doesn't have cpio already (i.e. 4.2 bsd). Having these programs will give you the technical means of doing this; it may not give you the legal right. I am far from qualified to pass judgement on the issues of what a particular Unix (tm) license allow you to do. Use these programs at your own risk. All I will say is that as a holder of both Sys 5 and 4.2 bsd source licenses, I am allowed to port the Sys 5 utilities to my 4.2 system. If you don't hold both licenses, you probably aren't. Eventually, I will get around to adding more functionality to these programs. The top of the list features are the '-c' and '-d' flags, and then pattern matching for file names. If I ever get around to doing those, I'll post the updated versions. If you find any problems with either of these programs, please feel free to contact me. I'll be happy to help if I can, but please don't expect me to have the updated versions ready on any particular schedule. allegra!phri!roy (Roy Smith) System Administrator, Public Health Research Institute @//E*O*F READ_ME// chmod u=rw,g=r,o=r READ_ME echo x - cpiolist.c sed 's/^@//' > "cpiolist.c" <<'@//E*O*F cpiolist.c//' /* * Cpiolist.c -- list a cpio tape written with binary headers * (i.e. written without the -c option). Usage is "cpiolist file" * where 'file' is the cpio archive (probably /dev/rmt12). * * Writen, produced, and directed by: * Roy Smith <allegra!phri!roy> * The Public Health Research Institute * of the City of New York, Inc. * 455 First Avenue * New York, NY 10016 */ struct hdr { short h_magic; short h_dev; unsigned short h_ino; unsigned short h_mode; unsigned short h_uid; unsigned short h_gid; short h_nlink; short h_rdev; short h_mtime[2]; short h_namesize; short h_filesize[2]; }; struct longword { short word[2]; }; main (argc, argv) int argc; char *argv []; { struct hdr header; int n, i, fd, odd, size; struct longword *lwp; char c, *ctime(), name[100]; short temp; /* * Attempt to open the cpio archive file. */ if ((fd = open (argv[1], 0)) < 0) { printf ("can't open file\n"); exit (1); } while (1) { /* Read in a header */ n = read (fd, &header, sizeof (header)); /* * The high and low order words of the time are * in the wrong order on the tape; swap them. */ temp = header.h_mtime[0]; header.h_mtime[0] = header.h_mtime[1]; header.h_mtime[1] = temp; /* likewise, swap the high and low order sizes */ lwp = (struct longword *) &size; lwp->word[0] = header.h_filesize[1]; lwp->word[1] = header.h_filesize[0]; /* check for trouble */ if (header.h_magic != 070707) { printf ("out of sync!\n"); exit (1); } /* print the header info */ printf ("%5d", header.h_ino); printf ("%9#o ", header.h_mode); printf ("%.24s", ctime (header.h_mtime)); printf ("%7d ", size); /* * read in the file name -- notice that if the name is * an odd number of bytes long, it is padded to be even. */ if ((n = header.h_namesize) % 2 != 0) odd = 1; else odd = 0; i = 0; while (n--) { read (fd, &c, 1); name [i++] = c; } printf ("%s\n", name); if (odd) read (fd, &c, 1); /* the file data is likewise padded */ if (size % 2 != 0) size++; /* * we don't actually want the file, * so just skip to the next header. */ lseek (fd, size, 1); } } @//E*O*F cpiolist.c// chmod u=rw,g=r,o=r cpiolist.c echo x - cpioextract.c sed 's/^@//' > "cpioextract.c" <<'@//E*O*F cpioextract.c//' /* * Cpioextract.c -- extract a single file from a cpio archive * written with binary headers (i.e. without the -c option) * * Usage is: cpioextract cpio_archive_file archived_file_name * * Written by: * Roy Smith <allegra!phri!roy> * The Public Health Research Institute * of the City of New York, Inc. * 455 First Avenue, New York, NY 10016 */ struct hdr { short h_magic; short h_dev; unsigned short h_ino; unsigned short h_mode; unsigned short h_uid; unsigned short h_gid; short h_nlink; short h_rdev; short h_mtime[2]; short h_namesize; short h_filesize[2]; }; struct longword { short word[2]; }; main (argc, argv) int argc; char *argv []; { struct hdr header; int n, i, fd, odd, size; struct longword *lwp; char c, *ctime(), name[100]; short temp; /* attempt to open cpio archive file */ if ((fd = open (argv[1], 0)) < 0) { printf ("can't open file\n"); exit (1); } while (1) { /* read in a header */ n = read (fd, &header, sizeof (header)); /* tape has high and low order times reversed, fix them */ temp = header.h_mtime[0]; header.h_mtime[0] = header.h_mtime[1]; header.h_mtime[1] = temp; /* likewise, the file size */ lwp = (struct longword *) &size; lwp->word[0] = header.h_filesize[1]; lwp->word[1] = header.h_filesize[0]; /* sanity check */ if (header.h_magic != 070707) { printf ("out of sync!\n"); exit (1); } /* * if the file name is an odd number of characters, it is * padded on the tape to be even; deal with this. */ if ((n = header.h_namesize) % 2 != 0) odd = 1; else odd = 0; /* read the file name from the archive */ i = 0; while (n--) { read (fd, &c, 1); name [i++] = c; } if (odd) read (fd, &c, 1); /* is this the file we want? */ if (strcmp (name, argv[2]) == 0) { copyout (fd, size); exit (0); } else { /* * this wasn't the right file; skip past it (and one * extra padding byte if the file size was odd). */ if (size % 2 != 0) size++; lseek (fd, size, 1); } } } /* * pull a file out of the archive. fd is a file descriptor for the * cpio archive, n is the size of the file we are supposed to get. * the file is output to standard output. */ copyout (fd, n) int fd, n; { int nk; char buf[1024]; /* * how many full kilobyte blocks are there, * and how many bytes left over? */ */ nk = n / 1024; n %= 1024; /* get all the whole blocks */ while (nk--) { read (fd, buf, 1024); write (1, buf, 1024); } /* and get the residual fractional kilobyte */ read (fd, buf, n); write (1, buf, n); } @//E*O*F cpioextract.c// chmod u=rw,g=r,o=r cpioextract.c echo Inspecting for damage in transit... temp=/tmp/shar$$; dtemp=/tmp/.shar$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 41 448 2496 READ_ME 113 369 2210 cpiolist.c 139 462 2626 cpioextract.c 293 1279 7332 total !!! wc READ_ME cpiolist.c cpioextract.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if [ -s $dtemp ] then echo "Ouch [diff of wc output]:" ; cat $dtemp else echo "No problems found." fi exit 0 -- allegra!phri!roy (Roy Smith) System Administrator, Public Health Research Institute