joe@dayton.DHDSC.MN.ORG (Joseph P. Larson) (10/07/88)
Posting-number: Volume 4, Issue 118 Submitted-by: "Joseph P. Larson" <joe@dayton.DHDSC.MN.ORG> Archive-name: fcpio In any case, I wrote up the enclosed program one day when I got a little too annoyed with cpio while dealing with some rather large cpio archives. It doesn't need a makefile (I just say make fcpio). The two include files are from our <dayton/> directory, so people will need to patch the .c a little to specify where these came from. (They AREN'T replacements for the regular includes of the same name!) Hope someone finds this useful. -Joe ----Cut Here---- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # fcpio.doc # fcpio.c # math.h # stdtyp.h # This archive created: Wed Oct 5 09:54:01 1988 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'fcpio.doc' then echo shar: "will not over-write existing file 'fcpio.doc'" else cat << \SHAR_EOF > 'fcpio.doc' PROGRAM: fcpio -- a fast cpio for seekable devices SYNOPSIS: fcpio [-options] archive-name [extract-pattern1 [ ... extract-patternn]] Options implemented to date: x - extract files t - table of contents DESCRIPTION: fcpio is a partial cpio (tm Ma Bell) replacement. It is very useful when performing extracts or retrieving a table of contents from a disk-resident cpio archive. This is due to use of seeks to skip over unwanted data. (Our copy of cpio reads through everything as it must assume it can't seek.) Thus, a -t on a 3.3 Meg file runs at output (9600 baud) speeds with fcpio but has long pauses with cpio at all the long (> 20K) files within the archive. An extract of a few items is also very fast. The extract patterns do not support wild carding or anything fancy -- fcpio will extract any files that begin with one of the extract patterns (or all files if no extract pattern is specified). AUTHOR: Joe Larson Dayton-Hudson Department Store Company 700 On the Mall Minneapolis, Minnesota 55402 612-375-3537 BUGS: 1. Does not support non-seekable devices (like pipes?) 2. Does not maintain the files original magic number, UID or GID. 3. May not handle garbage at the end of the archive terribly well. (Our cpio puts an item called "TRAILER!!!" at the end, so fcpio equates that with EOF as well as ending on EOF. Other cpios may behave differently....) SHAR_EOF fi if test -f 'fcpio.c' then echo shar: "will not over-write existing file 'fcpio.c'" else cat << \SHAR_EOF > 'fcpio.c' #include <stdio.h> #include <sys/types.h> #include <fcntl.h> #include <errno.h> #include <dayton/math.h> #include <dayton/stdtyp.h> /* * fcpio - fast cpio for seek-able devices. * * Usage: * * fcpio [-options] cpio-archive [extract-pattern-list] * * Implemented options are: * * x - extract the named extract-pattern files. * t - print a table of contents. * * In extract mode, the extracted files are the ones whose names begin * with anything in the named list. Skipped items are displayed * by a "." to indicate progress being made. * * Author: * * Joe Larson * Dayton-Hudson Dept. Store Co. * 700 On The Mall * Minneapolis, Minnesota 55402 * * UUCP:joe@dayton */ struct Hdr { short h_magic, h_dev; ushort h_ino, h_mode, h_uid, h_gid, h_nlink, h_rdev, h_mtime[2], h_namesize, h_filesize[2]; char h_name[80]; }; #define READBUFSIZE 100000 char readbuf[READBUFSIZE]; main(argc,argv) int argc; char **argv; { struct Hdr hstruct; /* Indiv. file header in ifile. */ int ifile, /* Archive file */ cur_pos, /* Position in ifile */ fpos, /* Another position in ifile */ dummy, /* Holds length of current file in ifile */ i, /* Counter for lots of things */ ilens[20], /* Lengths of x_names[]. */ count, /* # of files we've skipped. */ x_count, /* Number of x_names[]. */ isize; /* Used in seeking... */ char *a_name, /* Name of archive file */ *options, /* Option string from cmnd line. */ *x_names[20]; /* Name of extract file beginnings. */ bool do_extract, /* Extract files? */ do_table, /* Do a table of contents? */ x_here; /* Extract this file? */ a_name = NULL; options = "x"; x_count = 0; do_extract = 0; do_table = 0; for (i = 1; i < argc; i++) { if (*argv[i] == '-') options = argv[i]+1; else if (a_name == NULL) a_name = argv[i]; else x_names[x_count++] = argv[i]; } if (a_name == NULL) { usage(argv[0]); exit(0); } do_extract = (strchr(options, 'x') != NULL); do_table = (strchr(options, 't') != NULL); ifile = open(a_name, O_RDONLY); if (ifile == -1) { perror(a_name); exit(errno); } for (i = 0; i < x_count; i++) ilens[i] = strlen(x_names[i]); cur_pos = 0; count = 0; while(1) { if (read(ifile, &hstruct, sizeof(struct Hdr)) < sizeof(struct Hdr)) break; if (!strcmp(hstruct.h_name, "TRAILER!!!")) break; dummy = (hstruct.h_filesize[0] << 16) + hstruct.h_filesize[1]; if (do_table) { fprintf(stderr, "%6ld %s\n", dummy, hstruct.h_name); fflush(stderr); } isize = (hstruct.h_namesize + 1) & ~(1L); if (do_extract) { x_here = !(x_count); /* If no x_names, extract all */ for (i = 0; i < x_count; i++) if (!strncmp(x_names[i], hstruct.h_name, ilens[i])) { x_here = 1; break; } if (x_here) { if (count) fprintf(stderr, "\n"); count = 0; fpos = cur_pos + sizeof(struct Hdr) - 80 + isize; fprintf(stderr, "X: %s", hstruct.h_name); fflush(stderr); copy_file(ifile, fpos, &hstruct, dummy); fprintf(stderr, ".\n"); } else { fprintf(stderr, "."); if (++count == 60) { fprintf(stderr, "\n"); count = 0; } else fflush(stderr); } } cur_pos += (dummy + sizeof(struct Hdr) - 80 + isize + 1) & ~(1L); lseek(ifile, cur_pos, 0); } close(ifile); } copy_file(ifile, fpos, hstruct, ilen) int ifile, fpos, ilen; struct Hdr *hstruct; /* * Copy out this file. This routine still needs to do some things. * * For instance, no attempt is made to preserve the original files * magic number, c/m/a times, owner or group. */ { int ofile, rlen, nlen; char name[132], *c1, *c2; if (hstruct->h_mode & 0040000L) { make_path(hstruct->h_name, 1); return; } for (c1 = NULL, c2=hstruct->h_name; *c2; c2++) if (*c2 == '/') c1 = c2; if (c1 != NULL) { nlen = c1 - hstruct->h_name; strncpy(name, hstruct->h_name, nlen); name[nlen] = 0; make_path(name, 1); } ofile = open(hstruct->h_name, O_WRONLY | O_CREAT, hstruct->h_mode&07777L); if (ofile == -1) { perror(hstruct->h_name); return; } lseek(ifile, fpos, 0L); while (ilen > 0) { rlen = MIN(READBUFSIZE, ilen); rlen = read(ifile, readbuf, rlen); if (rlen > 0) write(ofile, readbuf, rlen); else break; ilen -= rlen; } close(ofile); } usage(arg) char *arg; { fprintf(stderr, "Usage: %s infilename\n", arg); } make_path(p, flag) char *p, flag; /* * Make sure this entire pathname exists. */ { short ilen; char name[132], *c1, *c2; if (access(p, 00)) { if (flag) { for (c1 = NULL, c2 = p; *c2; c2++) { if (*c2 == '/') { if (c1 != NULL) { ilen = c2 - p; strncpy(name, p, ilen); name[ilen] = 0; if (access(name, 00)) make_path(p, 0); } c1 = c2; } } } if (!fork()) { execlp("mkdir", "mkdir", p, 0); exit(errno); } else wait(0); } } SHAR_EOF fi if test -f 'math.h' then echo shar: "will not over-write existing file 'math.h'" else cat << \SHAR_EOF > 'math.h' /* * Dayton's math library definitions. */ #define MIN(x,y) ((x < y) ? x : y) #define MAX(x,y) ((x > y) ? x : y) #define ABS(x) ((x < 0) ? -x : x) SHAR_EOF fi if test -f 'stdtyp.h' then echo shar: "will not over-write existing file 'stdtyp.h'" else cat << \SHAR_EOF > 'stdtyp.h' /* * Standard types and defines for Dayton-Hudson. * */ #include <stdtyp.h> #ifndef TRUE #define TRUE (1) #endif #ifndef FALSE #define FALSE (0) #endif #define ULONG unsigned long SHAR_EOF fi exit 0 # End of shell archive