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