cpi.c source
BostonU SysMgr
root%bostonu.csnet at csnet-relay.arpa
Sat Mar 23 07:24:37 AEST 1985
People asked me to post my short program for reading cpio tapes
so here it is.
Ok, with comments and the util routines it's a little longer than
100 lines but not much (<200 lines). As I said, it's a hack to
read a cpio tape but all the hard work is done.
cpi.c -- cc cpi.c -o cpi
-Barry Shein, Boston University
--------------------cut here--------------------
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
/*
* cpi.c - read a cpio tape
* usage: cpi prefix
* will read in and create all files (and dirs) that
* match the prefix, for example 'cpi src/cmd' will
* read in src/cmd/foo.c src/cmd/thing/goo.c etc.
* TODO-
* cmd line: add tape drive, blksize,word/byte swap
* maybe more sophisticated selection of files
* doesn't check for TRAILER record at end of tape,
* just gives an error message and gives up
*
* Look, this was a hack to get cpio.c off of a SYSV tape.
* It could use some cosmetics but all the hard work is done.
* although at some point in its history it ran on a 3B5 it's
* been changed and has at least one 4.2bsd/VAX dependancy (mkdir()).
*
* (C) Barry Shein, Boston University
* You have the right to distribute this to whomever you
* like as long as you don't remove my name so I can become
* famous for adding yet another unsupportable hack to the UNIX
* environment. If you give this away, give it with source, please.
*/
FILE *fcreat() ;
struct cpio {
short h_magic,
h_dev;
ushort h_ino,
h_mode,
h_uid,
h_gid;
ushort h_nlink,
h_rdev,
h_mtime[2],
h_namesize,
h_filesize[2] ;
} ;
#define BSIZE 5120 /* oughta be settable from cmd line */
char fbuf[BSIZE], *fbufp ;
int fbufk = 0 ;
#define MAXNAME 256 /* actually a cpio limit */
#define DEFTAPE "/dev/rmt0" /* oughta be settable from cmd line */
main(argc,argv) int argc ; char **argv ;
{
struct cpio cpio ;
char namebuf[MAXNAME] ;
char buf[BSIZE] ;
register short *sip ;
int fd ;
int siz ;
int i,j ;
int *ip ;
int fsize ;
char *prfx ;
int prfxl ;
FILE *fp ;
if(argc != 2) exit(printf("usage: %s prefix\n",*argv)) ;
if((fd = open(DEFTAPE,0)) < 0)
exit(perror(DEFTAPE)) ;
prfx = argv[1] ;
prfxl = strlen(prfx) ;
siz = sizeof(cpio) ;
again:
cread(fd,&cpio,siz) ;
#ifdef notdef /* 3B5 needed byte swapping */
swabw(&cpio,siz/2) ;
printf("MAGIC: %07o\tUID: %6d\n",cpio.h_magic,
cpio.h_uid) ;
#endif
/* rebuild the long, if you re-declare as long alignment gets ya */
fsize = (cpio.h_filesize[0] << 16) | cpio.h_filesize[1] ;
#ifdef notdef
printf("NSIZE: %8d\tFSIZE: %8d\n",cpio.h_namesize,fsize) ;
#endif
/* this is also what you will hear on end-of-tape */
if((cpio.h_namesize < 0) || (cpio.h_namesize > MAXNAME))
{
printf("ridiculous name, giving up\n") ;
printf("(fbufk = %d)\n",fbufk) ;
exit(1) ;
}
/* NOTE: rounded up to even, will be padded on tape */
i = (cpio.h_namesize & 01) ? cpio.h_namesize + 1 : cpio.h_namesize ;
cread(fd,namebuf,i) ;
/* printf("NAME: %s\n",namebuf) ;*/
j = fsize ;
if((j > 0) && (strncmp(namebuf,prfx,prfxl) == 0))
{
if((fp = fcreat(namebuf)) == NULL)
perror(namebuf) ;
else printf("%s\n",namebuf) ; /* always 'verbose' */
}
else fp = NULL ;
while(j > 0)
{
/* read in BSIZE pieces */
if((i = cread(fd,buf,(j >= BSIZE) ? BSIZE : j)) <= 0)
{
printf("Error reading tape? (%s)\n",namebuf) ;
exit(1) ;
}
j -= i ;
/* see, I already had fcreat() from another thing I wrote */
/* really shoulda made it not stdio but who cares */
if(fp != NULL) write(fileno(fp),buf,i) ;
}
if(fp != NULL) fclose(fp) ;
if(fsize & 1) cread(fd,buf,1) ; /* get pad byte */
goto again ;
}
/* buffered read */
cread(fd,bp,n) int fd ; register char *bp ; register int n ;
{
int nb = 0 ;
while(n--)
{
if(fbufk <= 0)
if((fbufk = read(fd,fbufp = fbuf,BSIZE)) <= 0)
return(nb) ;
*bp++ = *fbufp++ ;
--fbufk ;
nb++ ;
}
return(nb) ;
}
wswab(i) int i ;
{
return(((i & 0xff00) >> 8) | ((i & 0xff) << 8)) ;
}
swabw(sip,l) register short int *sip ; register int l ;
{
while(l--) *sip++ = wswab(*sip) ;
}
/*
* bit of craziness to create output file. Will
* attempt to create all intervening path names.
* you're gonna need a mkdir() routine.
*/
FILE *
fcreat(path) char *path ;
{
char buf[BUFSIZ] ;
register char *bp ;
strcpy(buf,path) ;
bp = &buf[strlen(buf) - 1] ;
while((*bp != '/') && (bp >= &buf[0]))
bp-- ;
if(*bp != '/') return(NULL) ;
*bp = '\0' ;
if(access(buf,F_OK) < 0)
{
char c ;
for(bp = buf ;; bp++)
{
if((c = *bp) && (*bp != '/')) continue ;
*bp = '\0' ;
if(access(buf,F_OK) < 0)
if(mkdir(buf,0777) < 0) return(NULL) ;
if(c == '\0') break ;
*bp = '/' ;
}
}
return(fopen(path,"w")) ;
}
More information about the Comp.unix.wizards
mailing list