2.9BSD/usr/contrib/grab/src/grab.c
/*
* grab.c
*
* Name: grab
* Purpose: extract files from remote filesystems
* Usage: grab [-246pxvilLtb#] <filesystem> <files...>
* Environment: V6 or V7 (2.9BSD, 4.1BSD) Unix
* Compile: cc -O -s -D<type> grab.c find.c readi.c bread.c tmode.c -o grab
* Date: 4/29/82
* Author: Donn Seeley RRCF UCSD
* Remarks:
* This is meant to be used with dual-ported disks or controllers
* when it is either impossible or undesirable to mount another
* file system on that medium. It should allow any Version 6 or
* Version 7 (2.9BSD, 4.1BSD) system to read filesystems from any
* Version 6 or Version 7 (2.9BSD, 4.1BSD) system even if the systems
* are not of the same type. Version 6 systems will need at least
* a Phototypesetter level C compiler to make "grab". "Grab" will
* copy any conceivable (?) object on a filesystem including directories
* (recursively), links, file holes, setuid/setgid/sticky files and
* device nodes. "Grab" tries to prevent unauthorized readers from
* gazing at remote files but the only reliable way of maintaining
* security is to make "grab" setgid and then make fs's readable by
* group and not by other. ("Df" should work this way too.)
*
* To compile a V6 grab, define PDPV6. To compile a 2.9 grab define
* PDP, and to compile a 4.1 grab define VAX. If your machine has
* multiplexed files, define MPXFILES, and if it has symbolic links
* you should define SYMLINKS.
*
* Options:
* -246 2.9, 4.1 or V6 system on the remote end.
* -p Preserve all permissions and ownerships, instead of
* just some of them (should be su).
* -x Act like "cat(1)" from the remote fs (but still
* recursively on directories).
* -v Verbose mode: print filenames as they are copied.
* -i The arguments are inode numbers; treat them as
* files with those inode numbers and named by the numbers.
* -l Act like a rudimentary "ls(1)" on a remote fs.
* -L Long version of -l: gives a gruesome inode dump.
* -t Act like "tar(1)" on a remote fs. Output goes to
* the standard output. Digits following the "t" are
* interpreted as a blocksize.
* -b Set blocksize independently: this manipulates the
* internal write buffer size. Digits following, etc.
*
*---------------------------------------------------------------------------
*
* $Header: RCS/grab.c.v Revision 1.2 83/07/01 19:29:13 donn Exp$
* $Log: RCS/grab.c.v $
* Revision 1.2 83/07/01 19:29:13 donn
* Added -i and -L flags for inode grabbing and inode dumping.
* Donn
*
*/
# include "grab.h"
int target_system = TARGET_DEFAULT;
int fsbsiz = FSB_DEFAULT;
int fsys;
int pflag = 0;
int xflag = 0;
int vflag = 0;
int iflag = 0;
int lflag = 0;
int Lflag = 0;
int tflag = 0;
int nblock = B_BUFSIZE;
main( argc, argv )
int argc;
char *argv[];
{
char *tail();
char *name;
int ino;
if ( argc < 3 ) {
fprintf( stderr, "grab: too few arguments\n" );
fprintf( stderr, "Usage: grab [-246pxvilLtb] <file-system> <files>\n" );
exit( 1 );
}
/*
* Process the command line.
*/
while ( *argv[1] == '-' ) {
while ( *++argv[1] != '\0' )
switch ( *argv[1] ) {
/*
* Select type of filesystem to read.
*/
case '2':
target_system = V7_2BSD;
fsbsiz = 1024;
break;
case '4':
target_system = V7_4BSD;
fsbsiz = 1024;
break;
case '6':
target_system = V6;
fsbsiz = 512;
break;
/*
* Restore previous owner, group & protections.
*/
case 'p':
++pflag;
# ifndef PDPV6
umask( 0 );
# endif
break;
/*
* Put files on the standard output.
*/
case 'x':
++xflag;
break;
/*
* Print names of copied files.
*/
case 'v':
++vflag;
break;
/*
* Grab by inode number.
*/
case 'i':
++iflag;
break;
/*
* List directories.
*/
case 'l':
/*
* If only one file then we leave out header.
*/
lflag = argc - 3;
Lflag = 0;
break;
/*
* Long listing.
*/
case 'L':
++Lflag;
lflag = 0;
break;
/*
* Output files in "tar" format.
*/
case 't':
++tflag;
nblock = TAR_BS_DEFAULT;
/* FALL THRU */
/*
* Pick up blocking factor (if any).
*/
case 'b':
if ( *(argv[1] + 1) >= '0' &&
*(argv[1] + 1) <= '9' )
nblock = atoi( ++argv[1] );
while ( *(argv[1]+1) >= '0' && *(argv[1]+1) <= '9' )
++argv[1];
break;
default:
fprintf( stderr, "grab: unknown option -%c\n", argv[1][1] );
fprintf( stderr, "Usage: grab [-246pxvilLtb] <file-system> <files>\n" );
exit( 2 );
}
++argv;
--argc;
}
if ( argc < 3 ) {
fprintf( stderr, "grab: too few arguments\n" );
fprintf( stderr, "Usage: grab [-246pxvilLtb] <file-system> <files>\n" );
exit( 3 );
}
/*
* If the standard output is a file, assume -x by default.
* This is for backward compatibility with Arthur Olsen's grab
* and may go away.
*/
if ( ! (xflag || tflag || lflag || Lflag) ) {
int statbuf[32];
if ( fstat( STDOUT, statbuf ) == 0
# ifdef PDPV6
&& (((struct inode *) statbuf)->i_mode & V6_IFMT) == V6_IFREG )
# else
&& (((struct inode *) statbuf)->i_mode & V7_IFMT) == V7_IFREG )
# endif
++xflag;
}
/*
* Try to separate file output and verbose mode output!
* The method here is a bit nonportable...
*/
if ( tflag || xflag )
fileno( stdout ) = fileno( stderr );
/*
* Open the file system device.
*/
fsys = open( argv[1], 0 );
if ( fsys < 0 ) {
fprintf( stderr, "grab: can't open %s\n", argv[1] );
exit( 4 );
}
/*
* Set id to real id. (V6 isn't setuid because nobody cares.)
*/
# ifndef PDPV6
setuid( getuid() );
setgid( getgid() );
# endif
/*
* Find the files corresponding to the file arguments
* and read them off.
*/
while ( argc > 2 ) {
if ( iflag ) {
name = NULL;
ino = atoi( argv[2] );
} else {
name = tail( argv[2] );
ino = find( argv[2] );
}
readi( ino, name );
++argv, --argc;
}
/*
* Clean up on tape output.
* Tar puts out two blank records followed by junk
* from the buffer when it flushes the buffer...
*/
if ( tflag )
tflush( TFILE );
exit( 0 );
}