v04i118: fcpio - a fast cpio partial replacement
Joseph P. Larson
joe at dayton.DHDSC.MN.ORG
Fri Oct 7 10:16:54 AEST 1988
Posting-number: Volume 4, Issue 118
Submitted-by: "Joseph P. Larson" <joe at 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 at 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
More information about the Comp.sources.misc
mailing list