home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-12-11 | 62.0 KB | 1,997 lines |
- Path: sparky!uunet!cs.utexas.edu!sun-barr!ames!agate!ucbvax!mhs.attmail.com!simons/G=Colin/I=CB/S=Sewell/O=H.A.Simons.Ltd/OU=CORP
- From: simons/G=Colin/I=CB/S=Sewell/O=H.A.Simons.Ltd/OU=CORP@mhs.attmail.com
- Newsgroups: comp.os.vms
- Subject: Re: tar for vms
- Message-ID: <9212120130.AA07805@ucbvax.Berkeley.EDU>
- Date: 11 Dec 92 22:09:19 GMT
- Sender: daemon@ucbvax.BERKELEY.EDU
- Distribution: world
- Organization: The Internet
- Lines: 1985
-
- #pragma nostandard
- #module VMSTAR "V2.0"
- #pragma builtins
-
- /*
- ** VMSTAR.C - a Un*x-like tar reader/writer for VMS
- ** based on TAR2VMS and VMS2TAR
- **
- ** Usage:
- ** tar x|t|c[vwbd][f tarfile] [file [file...]]
- ** x - extract from tarfile
- ** t - type contents of tarfile
- ** c - create tarfile, archive VMS files
- ** v - verbose
- ** w - wait for confirmation before extracting/archiving
- ** b - binary mode extract, create (rfm=fixed, rat=none, mrs=512) files
- ** z - automatic mode, try to guess if files are text or binary, extract
- ** text files as (rfm=stream-LF, rat=cr) binary files as
- ** (rfm=fixed, rat=none, mrs=512)
- ** d - keep trailing dots in file names
- ** o - restore original owner
- ** f - specify tarfile name, default is $TAPE
- ** file - space-separated list of file names, can include VMS-style
- ** string wildcards on extract, can be any VMS file name
- ** specification (except DECnet) on create archive.
- **
- ** Original author of the VMS2TAR and TAR2VMS programs:
- ** Copyright 1986, Sid Penstone,
- ** Department of Electrical Engineering,
- ** Queen's University,
- ** Kingston, Ontario, Canada K7L3N6
- ** (613)-545-2925
- ** BITNET: PENSTONE@QUCDNEE1
- **
- ** Also deeply modified by:
- ** Colin Sewell
- ** H. A. Simons Ltd.
- ** Vancouver, BC
- **
- ** Deeply modified by:
- ** Alain Fauconnet
- ** System Manager
- ** SIM - Public Health Research Laboratories
- ** 91 Boulevard de l'Hopital
- ** 75634 PARIS CEDEX 13 - FRANCE
- ** Bitnet: FAUCONNE@FRSIM51
- **
- ** PROBLEMS SHOULD BE REPORTED TO ME. PLEASE DON'T BOTHER SID PENSTONE
- ** WITH MY OWN BUGS !
- **
- ** Version 2.0 21-NOV-1992
- ** Based on TAR2VMS V2.2 21-OCT-1986 and VMS2TAR V1.8 23-DEC-1986
- **
- ** Sid Penstone did not include any copyright information in his program so
- ** this only applies if Sid Penstone agrees: you may use VMSTAR, distribute it,
- ** modify it freely provided you don't use it for commercial
- ** or military purposes. Please include the two above author names in the
- ** source file of any modified version of VMSTAR.
- **
- ** Modification history:
- **
- ** 2.0 - complete rewrite
- ** 1.6-0 - added 'z' option for automatic determination of file type on
- ** extraction
- ** - reworked copyfile() to close files and exit on fatal error -
- ** error status not returned, they weren't checked anyway
- ** - some code cleanup (much, much more to do...)
- ** 1.5-3 - removed duplicate error message
- ** 1.5-2 - removed duplicate #include iodef
- ** - added write status checking in copyfile and cleaned up error
- ** handling (avoids duplicate messages)
- ** 1.5-1 - fix by Mark Parisi <MPARISI@RIPPLE.JPL.NASA.GOV>
- ** fixed bug in out_file: if the length of a text file was an
- ** exact multiple of DSIZE, flushout was called an additional
- ** time.
- ** - added some code for empty files handling.
- ** 1.5 - when archiving a non-text file with rfm=stream_lf, rat=cr
- ** attributes, VMSTAR truncated the file. Modified out_file
- ** to more cleanly handle various RMS file formats: only
- ** variable and stream_cr record formats need two passes to compute
- ** the actual file size and need to be read record by record.
- ** All other formats should by read buffer by buffer and written
- ** as-is in the tar archive, thus out_file now fopens the file
- ** in binary mode and freads buffers.
- ** In the case of a stream_cr file, if a single record cannot fit in
- ** our buffers (probably because the file is non-text and has
- ** incorrect RMS attributes) out_file now error exits.
- ** 1.4 - fixed a bug in scan_title that caused VMSTAR to fail on
- ** extraction of absolute tarfiles (thanks to Tom Allebrandi
- ** for this one)
- ** - added some code in scan_title to correctly handle dots in
- ** directory names found in tarfile (replaced by "_")
- ** 1.3 - changed tar2vms to use standard IO calls (fopen, fread) to
- ** read input tarfile in binary mode i.e. no translation of
- ** RMS record attributes done by C RTL. This fixes problem reading
- ** tarfiles created with rfm=fix, rat=cr
- ** - more room for file size in output formats
- ** 1.2 - fixed bug in out_file not closing input VMS file, limited
- ** maximum number of files archived to FILLM quota
- ** - added mapping to underscores of some more characters found
- ** in Un*x file names illegal in VMS file names
- ** 1.1 - reworked handling of current VMS default
- ** - will now create *relative* tarfiles (i.e. files known
- ** as "./..." in tar archive directory) except when
- ** device name is specified or wilcard search gives filenames
- ** located above current default (tar cvf foo.tar [-...]*.* will
- ** lead to this kind of situation)
- ** - attempt to handle more than 8 levels of directories upon
- ** extract : .../d7/d8/d9 will be mapped to [...D7.D8$D9]
- ** - greatly simplified make_new() because mkdir() creates
- ** intermediate levels of directories if missing
- ** 1.0 Original version from Sid Penstone's code
- ** - merged VMS2TAR & TAR2VMS into a single source file
- ** - code reworked, messages cleaned up
- ** - added support for 'f tarfile' option, changed default to $TAPE
- ** - added support for VMS style wildcard file names on extract
- ** - added support for 'b' (binary file extract) option
- ** - suppressed usage of intermediate scratch file for create operation
- ** - file list on create should now be space separated (removed difficult
- ** support of comma-separated list with context "a la BACKUP")
- ** - global code simplification attempt, may have broken some
- ** odd case handling
- ** - added some error handling in tarfile write operations
- ** - probably millions of bugs introduced... sorry.
- */
-
-
- /****************************************************************************/
- /* declarations */
- /****************************************************************************/
-
- #include stdlib
- #include stdio
- #include time
- #include ssdef
- #include iodef
- #include dvidef
- #include dcdef
- #include descrip
- #include ctype
- #include strdef
- #include rms
- #include stsdef
- #include file
- #include stat
- #include types
- #include string
- #include errno
- #include hlpdef
-
- #define ISFILE 0 /* is a file */
- #define ISDIRE 1 /* is a directory */
- #define BLKSIZE 20 /* Block size */
- #define DSIZE 512 /* Data block size */
- #define EOS '\0' /* End of string character */
-
- #define NAMSIZE 100
- #define MODESIZE 8
- #define UIDSIZE 8
- #define GIDSIZE 8
- #define COUNTSIZE 12
- #define TIMESIZE 12
- #define CHKSUMSIZE 8
-
- struct tarhdr /* A tar header */
- {
- char title[NAMSIZE]; /* name of entry */
- char mode[MODESIZE]; /* file mode */
- char uid[UIDSIZE]; /* this is the user id */
- char gid[GIDSIZE]; /* this is the group id */
- char count[COUNTSIZE]; /* was 11 in error */
- char time[TIMESIZE]; /* UNIX format date */
- char chksum[CHKSUMSIZE]; /* header checksum */
- char linkcount; /* hope this is right */
- char linkname[NAMSIZE]; /* Space for the name of the link */
- char dummy[255]; /* and the rest */
- };
-
-
- /****************************************************************************/
- /* Function flags, options */
- /****************************************************************************/
-
- static int extract = 0; /* x option, extract */
- static int list = 0; /* t option, list tape contents */
- static int create = 0; /* c option, create */
- static int verbose = 0; /* v option, report actions */
- static int wait = 0; /* w option, prompt */
- static int dot = 0; /* d option, suppress dots */
- static int binmode = 0; /* b option, binary mode */
- static int automode = 0; /* z option, automatic mode */
- static int foption = 0; /* f option, specify tarfile */
- static int debug = 0; /* D option, debug */
- static int owner = 0;
- static int help = 0;
-
- static int devclass = 0; /* Tar file device class */
-
- /****************************************************************************/
- /* Miscellaneous globals, etc. */
- /****************************************************************************/
-
- static char tarfile[NAM$C_MAXRSS] = "$TAPE";/* Tarfile name */
- static char curdir[NAM$C_MAXRSS]; /* Current directory */
- static FILE *tarfp; /* tar file pointer */
-
-
- /****************************************************************************/
- /* Global file characteristics */
- /****************************************************************************/
-
- /* Chars found in Un*x file names, illegal in VMS */
-
- static const char badchars[] = { ",+~`@#%^*?|\&[]{}" };
-
- /* only get the most recent version */
-
- static const char default_name[] = { "*.*;" };
-
-
- /****************************************************************************/
- /* Forward definitions/prototypes */
- /****************************************************************************/
- char *vmserr( int ); /* return ptr to vms error text */
- char *tar_format_mode( int, char * ); /* format file mode */
- char *tar_format_time( int ); /* format time */
-
-
-
- /****************************************************************************/
- /* */
- /* main program -- parses options, dispatches to tar2vms and vms2tar */
- /* */
- /****************************************************************************/
- static int vmstar( int argc, char *argv[] ) MAIN_PROGRAM
-
- {
-
- register char *cp;
- register char c;
-
-
- /************************************************************************/
- /* decode the options and parameters: */
- /************************************************************************/
-
- if (argc == 1) tar_usage();
-
-
- cp = argv[1];
-
- while (c = *cp++)
- {
- switch(c)
- {
- case 't':
- list = 1;
- break;
-
- case 'x':
- extract = 1;
- break;
-
- case 'c':
- create = 1;
- break;
-
- case 'v':
- verbose = 1;
- break;
-
- case 'w':
- wait = 1;
- break;
-
- case 'd':
- dot = 1;
- break;
-
- case 'b':
- binmode = 1;
- break;
-
- case 'z':
- automode = 1;
- break;
-
- case 'D':
- debug = 1;
- break;
-
- case 'o':
- owner = 1;
- break;
-
- case 'h':
- help = 1;
- break;
-
- case 'f':
- if (*cp != '\0' || argc < 3)
- tar_usage();
- else
- foption = 1;
- strcpy( tarfile, argv[2] );
- break;
-
- case '-':
- break;
-
- default:
- fprintf( stderr, "tar: option '%c' not recognized.\n",c );
- tar_usage();
- }
- }
-
-
-
- if (help)
- {
- int status;
- int lib$put_output();
- int lib$get_input();
- $DESCRIPTOR( vmstardsc, "VMSTAR" );
- $DESCRIPTOR( helplibdsc, "SOE$UTIL:VMSTAR" );
- status = lbr$output_help( &lib$put_output, 0, &vmstardsc, &helplibdsc,
- &HLP$M_PROMPT, &lib$get_input );
- return status;
- }
-
-
-
- /************************************************************************/
- /* check options are coherent */
- /************************************************************************/
-
- if (extract + list + create == 0)
- {
- fprintf( stderr, "tar: no action specified.\n" );
- exit(1);
- }
-
- if (extract + create == 2)
- {
- fprintf( stderr, "tar: incompatible options 'x' and 'c' specified.\n" );
- exit(1);
- }
-
- if (binmode + automode == 2)
- fprintf( stderr, "tar: incompatible options 'b' and 'z' specified.\n" );
-
-
- /************************************************************************/
- /* get current directory */
- /************************************************************************/
-
- strcpy( curdir, getenv("PATH") );
-
- cp = strchr( curdir, ':' ); /* extract directory */
- strcpy( curdir, cp+1 );
- tar_clean_dir( curdir );
-
- if (debug)
- printf( "curdir = %s\n", curdir );
-
- if (create == 0)
- tar2vms( argc, argv );
- else
- vms2tar( argc, argv );
-
- return SS$_NORMAL;
-
- }
-
-
-
- /****************************************************************************/
- /* tar2vms -- handles extract and list options */
- /****************************************************************************/
- static tar2vms( int argc, char **argv )
-
- {
-
- int status;
- int ftype;
- char *ptr;
- char pathname[NAMSIZE+1];
- char linkname[NAMSIZE+1];
- char filespec[NAM$C_MAXRSS+1];
- char dirnam[NAM$C_MAXRSS];
- char filnam[NAM$C_MAXRSS];
- struct stat sblock;
- struct tarhdr header;
- struct dsc$descriptor pattern = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
- struct dsc$descriptor candidate = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
-
-
-
- /************************************************************************/
- /* open the file for reading */
- /************************************************************************/
-
- if ((tarfp = fopen( tarfile, "rb" )) == NULL)
- {
- fprintf( stderr, "tar: error opening tarfile.\n" );
- perror( "tar" );
- exit( 1 );
- }
-
- fgetname( tarfp, tarfile );
- lowercase( tarfile );
-
- candidate.dsc$w_length = strlen( tarfile );
- candidate.dsc$a_pointer = tarfile;
-
- status = lib$getdvi( &DVI$_DEVCLASS, 0, &candidate, &devclass );
- if (!(status & 1))
- {
- fprintf( stderr, "tar: error getting device information for %s\n", tarfile );
- fprintf( stderr, "tar: %s\n", vmserr( status ) );
- exit( SS$_NORMAL );
- }
-
-
- /************************************************************************/
- /* Now keep reading headers from this file, and decode the names, etc. */
- /************************************************************************/
-
-
- while ((status = fread( &header, 1, DSIZE, tarfp )) == DSIZE) /* 0 on end of file */
- {
-
- /********************************************************************/
- /* exit on empty header */
- /********************************************************************/
-
- if (!strlen(header.title)) exit( SS$_NORMAL );
-
-
-
- /********************************************************************/
- /* decode the header info */
- /********************************************************************/
-
- tar_decode_hdr( &header, pathname, linkname, &sblock );
-
-
-
- /********************************************************************/
- /* Now if file names were specified on the command line, check */
- /* if they match the current one */
- /********************************************************************/
-
- if ((foption == 0 && argc > 2) || argc > 3)
- {
-
- register int argi = foption ? 3 : 2;
-
- candidate.dsc$w_length = strlen( pathname );
- candidate.dsc$a_pointer = pathname;
-
- while (argi < argc)
- {
- pattern.dsc$w_length = strlen( argv[argi] );
- pattern.dsc$a_pointer = argv[argi];
-
- ++argi;
-
- if ((status = STR$MATCH_WILD( &candidate, &pattern )) == STR$_MATCH)
- break;
- }
-
- if (status != STR$_MATCH)
- {
- if (!sblock.st_nlink) tar_skip( sblock.st_size );
- continue;
- }
-
- }
-
-
- /********************************************************************/
- /* listing only */
- /********************************************************************/
-
- if (list)
- {
- tar_display_hdr( pathname, linkname, &sblock );
- if (!sblock.st_nlink) tar_skip( sblock.st_size );
- continue;
- }
-
-
- /********************************************************************/
- /* prompt to process file */
- /********************************************************************/
-
- if (wait)
- {
- char temp[4] = EOS;
-
- while (*temp != 'y' && *temp != 'n')
- {
- printf( "x %s: ", pathname );
- scanf( "%s", temp );
- *temp = _tolower( *temp );
- }
-
- if (*temp != 'y')
- {
- tar_skip( sblock.st_size );
- continue;
- }
- }
-
-
- ftype = tar_cvt_unixname_to_vmsname( pathname, dirnam, filnam );
-
- tar_clean_dir( dirnam );
-
- if (tar_create_dir( dirnam ))
- {
- fprintf( stderr, "tar: error creating %s\n", dirnam );
- perror( "tar" );
- if (!sblock.st_nlink) tar_skip( sblock.st_size );
- continue;
- }
-
-
- if (ftype == ISFILE)
- {
- strcpy( filespec, dirnam );
- strcat( filespec, filnam );
- tar_extract_file( filespec, linkname, &sblock );
- }
-
- }
-
-
- if (!status) /* End of tar file */
- {
- fprintf( stderr, "tar: EOF hit on tarfile.\n" );
- exit( SS$_NORMAL );
- }
-
-
- if (status < 0) /* An error */
- {
- fprintf( stderr, "tar: error reading tarfile.\n" );
- perror( "tar" );
- exit( SS$_NORMAL );
- }
-
- }
-
-
-
-
- /****************************************************************************/
- /* This function simply copies the file to the output, no conversion */
- /****************************************************************************/
- static tar_extract_file
- ( char outfile[], /* name of output file */
- char linkname[],
- struct stat *sblock )
-
- {
-
- char buffer[DSIZE]; /* buffer for a tarfile record */
- int nbytes = sblock->st_size;
- int inbytes = 0;
- int outbytes = 0;
- int outfd;
- int binfile = binmode;
-
-
- /************************************************************************/
- /* Read the first block of the tarred file */
- /************************************************************************/
-
- if (sblock->st_nlink == 0 && nbytes)
- {
-
- if ((inbytes = fread( buffer, 1, DSIZE, tarfp )) < 0)
- {
- fprintf( stderr, "tar: error reading tar file.\n" );
- perror( "tar" );
- tar_skip( nbytes );
- return;
- }
-
-
- /********************************************************************/
- /* If automatic mode is set, then try to figure out what kind */
- /* of file this is. */
- /********************************************************************/
-
- if (automode && inbytes)
- {
-
- int i;
- int ctlchars = 0;
- int eightbitchars = 0;
- int nchars = nbytes < inbytes ? nbytes : inbytes;
- char c;
-
- /****************************************************************/
- /* Scan the buffer, counting chars with msb set and control */
- /* chars not CR, LF or FF */
- /****************************************************************/
-
- for (i = 0; i < nchars; ++i)
- {
-
- c = buffer[i];
-
- if (c < ' ' && c != 0x0a && c != 0x0c && c != 0x0d && c != 0x09)
- ctlchars++;
-
- if (c > 127)
- eightbitchars++;
-
- }
-
- /****************************************************************/
- /* Apply some heuristics to determine file is text or binary */
- /****************************************************************/
-
- ctlchars = ctlchars * 100 / nchars;
-
- eightbitchars = eightbitchars * 100 / nchars;
-
- if (ctlchars > 10 || eightbitchars > 30 ||
- (ctlchars > 5 && eightbitchars > 20))
- binfile = 1;
-
- }
- }
-
-
-
-
- /************************************************************************/
- /* Open the output file */
- /************************************************************************/
-
- if (binfile)
- outfd = creat( outfile, sblock->st_mode, "rfm=fix", "mrs=512", "alq=5" );
- else
- outfd = creat( outfile, sblock->st_mode, "rfm=stmlf", "rat=cr" );
-
-
- if (outfd < 0)
- {
- fprintf( stderr, "tar: error creating %s \n", outfile );
- perror( "tar" );
- if (!sblock->st_nlink) tar_skip( nbytes - inbytes );
- return;
- }
-
-
- getname( outfd, outfile );
- lowercase( outfile );
-
- if (sblock->st_nlink)
- {
- sprintf( buffer, "*** This file is a link to %s\n", linkname );
- outbytes = write( outfd, buffer, strlen( buffer ) );
- }
- else
- {
- while (nbytes > 0 && inbytes >= 0 && outbytes >= 0)
- {
- outbytes = write( outfd, buffer, inbytes <= nbytes ? inbytes : nbytes );
- if (outbytes > 0)
- {
- nbytes -= inbytes;
- if (nbytes > 0) inbytes = fread( buffer, 1, DSIZE, tarfp );
- }
- }
- }
-
-
- if (!inbytes && inbytes)
- {
- fprintf( stderr, "tar: unexpected EOF on tar file.\n" );
- perror("tar");
- close( outfd );
- return;
- }
-
- if (inbytes < 0)
- {
- fprintf( stderr, "tar: error reading tar file.\n" );
- perror("tar");
- close( outfd );
- return;
- }
-
- if (outbytes < 0)
- {
- fprintf( stderr, "tar: error writing file %s\n", outfile );
- perror( "tar" );
- close( outfd );
- tar_skip( nbytes );
- return;
- }
-
-
- close( outfd );
-
- if (owner)
- chown( outfile, sblock->st_uid, sblock->st_gid );
-
- if (verbose)
- {
- printf( "x %c%s%s%s, %d byte%s\n",
- binfile ? '*' : ' ',
- outfile,
- sblock->st_nlink ? " -> " : "",
- sblock->st_nlink ? linkname : "",
- sblock->st_size,
- sblock->st_size != 1 ? "s" : "" );
- }
-
- return;
-
- }
-
-
-
- /****************************************************************************/
- /* tar_cvt_unixname_to_vmsname */
- /* */
- /* decode a Un*x file name into the directory and name */
- /* */
- /* Return a value to indicate if this is a directory name, or another file */
- /* We return the extracted directory string in "dire", and the */
- /* filename (if it exists) in "fname". The full title is in "line" */
- /* at input. */
- /****************************************************************************/
- static int tar_cvt_unixname_to_vmsname
- ( char pathname[],
- char dirnam[],
- char filnam[] )
-
- {
-
- char temp[NAM$C_MAXRSS+1];
- register char *cp;
- register char *cp1;
-
-
- *dirnam = *filnam = EOS;
-
- /************************************************************************/
- /* The format will be UNIX at input, so we have to scan for the */
- /* UNIX directory separator '/' */
- /* If the name ends with '/' then it is actually a directory name. */
- /* If the directory consists only of '.', then don't add a */
- /* subdirectory. The output directory will be a complete file spec, */
- /* based on the default directory. */
- /************************************************************************/
-
- if (!strncmp( pathname, "./", 2))
- strcpy( pathname, pathname + 2 ); /* ignore "./" */
-
- strcpy( temp, pathname ); /* work on a copy */
-
- tar_clean_filespec( temp ); /* Remove illegal vms characters*/
-
-
- if (cp = strrchr( temp, '/' ))
- {
- if (cp != &temp[strlen(temp) - 1]) /* no trailing "/" */
- strcpy( filnam, cp + 1 );
-
- *cp = EOS;
-
- while (cp = strchr( temp, '.' )) *cp = '_';
- while (cp = strchr( temp, '/' )) *cp = '.';
-
- if (*temp == '.') /* absolute path */
- {
- strcpy( dirnam, "[" );
- strcat( dirnam, temp );
- }
- else /* relative path */
- {
- strcpy( dirnam, curdir );
- dirnam[ strlen(dirnam) - 1 ] = '.';
- strcat( dirnam, temp );
- }
-
- strcat( dirnam, "]" );
-
- }
- else
- {
- strcpy( filnam, temp ); /* no "/", a file */
- strcpy( dirnam, curdir );
- }
-
-
-
- /************************************************************************/
- /* fix up filename; replaces all '.' after first '.' with '_' */
- /************************************************************************/
-
- if (cp = strchr( filnam, '.' ))
- while (cp1 = strchr( cp+1, '.' )) *cp1 = '_';
-
-
- if (*filnam == EOS)
- return ISDIRE;
- else
- return ISFILE;
-
- }
-
-
-
-
- /****************************************************************************/
- /* tar_create_dir -- create a new directory */
- /****************************************************************************/
- static int tar_create_dir( char want[] )
-
- {
-
- int status;
- int created = 1;
- char *dotp;
-
-
- status = mkdir( want, 0 ); /* mkdir in VAX C creates all missing levels */
-
- if (status)
- {
-
- if (errno == EEXIST) /* exists */
- return 0;
-
- if (errno != EINVAL)
- return -1; /* unknown error, simply return */
-
- /* maybe too many levels of directories */
- /* change "[...FOO.BAR]" to "[...FOO$BAR]" */
-
- for (dotp = &want[strlen(want) - 1]; dotp > want && status != 0; )
- if (*--dotp == '.')
- {
- *dotp = '$';
- status = mkdir( want, 0 );
- if (status && (errno == EEXIST))
- {
- status = created = 0;
- break;
- }
- }
- }
-
- if (status)
- return -1;
-
- if (verbose && created)
- printf( "x %s%\n", want );
-
- return 0;
-
- }
-
-
-
-
- /****************************************************************************/
- /* This is supposed to skip over data to get to the desired position */
- /* Position is the number of bytes to skip. */
- /****************************************************************************/
- static int tar_skip( int bytes )
-
- {
-
- register int i;
-
- if (bytes <= 0) return 0;
-
- if (devclass != DC$_TAPE)
- {
-
- int skipsize = (DSIZE * (bytes / DSIZE)) + ((bytes % DSIZE) ? DSIZE : 0);
-
- if ((i = fseek( tarfp, skipsize, 1 )) == EOF)
- {
- fprintf( stderr, "tar: EOF hit on tar file while skipping.\n" );
- return -1;
- }
-
- }
- else
- {
-
- int skipsize = (bytes / DSIZE) + ((bytes % DSIZE) ? 1 : 0);
- char buffer[DSIZE];
- int j;
-
- for (j = 0; j < skipsize; j++)
- {
- if (( i = fread( buffer, 1, DSIZE, tarfp )) == 0)
- {
- fprintf( stderr, "tar: EOF hit on tar file while skipping.\n" );
- return -1;
- }
- }
-
- }
-
- return 0;
-
- }
-
-
-
- /****************************************************************************/
- /* Display the header */
- /****************************************************************************/
- static int tar_display_hdr
- ( char *pathname,
- char *linkname,
- struct stat *sblock )
-
-
- {
- int link = (sblock->st_nlink == 1 || sblock->st_nlink == 2);
-
- if (verbose)
- {
-
- char uidstr[9];
- char gidstr[9];
- int status;
- short namlen;
- $DESCRIPTOR( uiddsc, uidstr );
-
- switch (sblock->st_uid)
- {
- case 0:
- strcpy( uidstr, "root" );
- break;
- case 1:
- strcpy( uidstr, "system" );
- break;
- default:
- if ((status = sys$idtoasc( sblock->st_uid, &namlen, &uiddsc, 0, 0, 0 )) & 1)
- {
- uidstr[namlen] = EOS;
- lowercase( uidstr );
- }
- else
- sprintf( uidstr, "%-8d", sblock->st_uid );
- }
-
-
- switch (sblock->st_gid)
- {
- case 0:
- strcpy( gidstr, "root" );
- break;
- case 1:
- strcpy( gidstr, "system" );
- break;
- default:
- sprintf( gidstr, "%-8d", sblock->st_gid );
- break;
- }
-
- printf( "%s 1 %-8s %-8s %8d %s %s%s%s\n",
- tar_format_mode( sblock->st_mode, pathname ),
- uidstr,
- gidstr,
- sblock->st_size,
- tar_format_time( sblock->st_mtime ),
- pathname,
- link ? " -> " : "",
- link ? linkname : "" );
- }
- else
- printf( "%s%s%s\n", pathname, link ? " -> " : "", link ? linkname : "" );
-
- }
-
-
-
-
- /****************************************************************************/
- /* Decode the fields of the header */
- /****************************************************************************/
- static int tar_decode_hdr
- ( struct tarhdr *header,
- char *pathname,
- char *linkname,
- struct stat *sblock )
-
- {
-
- register int i;
- int chksum;
- int value;
- char *ptr;
- int filetype;
-
-
-
- if (debug)
- {
- printf( "title = %.*s\n", NAMSIZE, header->title );
- printf( " mode = %.*s\n", MODESIZE, header->mode );
- printf( " uid = %.*s\n", UIDSIZE, header->uid );
- printf( " gid = %.*s\n", GIDSIZE, header->gid );
- printf( "count = %.*s\n", COUNTSIZE, header->count );
- printf( " time = %.*s\n", TIMESIZE, header->time );
- printf( "cksum = %.*s\n", CHKSUMSIZE, header->chksum );
- printf( " lcnt = %d\n", header->linkcount );
- printf( " lnam = %.*s\n", NAMSIZE, header->linkname );
- printf( " junk = %s\n", header->dummy );
- }
-
-
- sblock->st_nlink = 0;
- sscanf( header->title, "%100s",pathname );
- sscanf( header->mode, "%8o", &sblock->st_mode );
- sscanf( header->uid, "%8o", &sblock->st_uid );
- sscanf( header->gid, "%8o", &sblock->st_gid );
- sscanf( header->count, "%12o", &sblock->st_size );
- sscanf( header->time, "%12o", &sblock->st_mtime );
- sscanf( header->chksum, "%8o", &chksum );
- *linkname = EOS;
-
-
- /************************************************************************/
- /* Verify checksum */
- /************************************************************************/
-
- for (value = 0, ptr = header; ptr < &header->chksum; ptr++)
- value += *ptr; /* make the checksum */
-
- for (ptr = &header->linkcount; ptr < &header->dummy[255]; ptr++)
- value += *ptr;
-
- value += (8 * ' '); /* checksum considered as all spaces */
-
- if (chksum != value)
- { /* abort if incorrect */
- fprintf( stderr, "tar: directory checksum error for %s\n", pathname );
- /* exit(1);*/
- }
-
-
- /************************************************************************/
- /* We may have the link written as binary or as character: */
- /************************************************************************/
-
- sblock->st_nlink = isdigit( header->linkcount ) ? (header->linkcount - '0') : header->linkcount;
-
- if (sblock->st_nlink)
- sscanf( header->linkname, "%100s", linkname );
-
- return 0;
-
- }
-
-
-
- /****************************************************************************/
- /* tar_format_time */
- /* */
- /* format file time into readable string */
- /* */
- /****************************************************************************/
- static char *tar_format_time
- ( int idate )
-
- {
-
- time_t now = time( NULL );
- struct tm *tim;
- int curyear;
- int filyear;
- static char strtim[26];
-
- strcpy( strtim, ctime( &idate ) );
- strcpy( strtim, &strtim[4] );
- strtim[12] = EOS;
-
-
- tim = localtime( &now );
- curyear = tim->tm_year;
-
- tim = localtime( &idate );
- filyear = tim->tm_year;
-
- if (curyear != filyear)
- {
- strtim[7] = ' ';
- sprintf( &strtim[8], "%4d", filyear + 1900 );
- }
-
- return strtim;
-
- }
-
-
-
-
- /****************************************************************************/
- /* tar_format_mode */
- /* */
- /* format file mode into readable string */
- /* */
- /****************************************************************************/
- static char *tar_format_mode
- ( int mode,
- char pathname[] )
-
- {
- static char modestr[10];
- register int filetype;
- register int i;
-
-
- strcpy( modestr, "----------" );
-
- filetype = (mode & S_IFMT);
-
- if (pathname[ strlen(pathname) - 1 ] != '/')
- {
- switch (filetype & S_IFMPB)
- {
- case 0:
- break;
- case S_IFCHR:
- modestr[0] = 'l';
- break;
- default:
- modestr[0] = 'x';
- break;
- }
- }
- else
- {
- switch (filetype)
- {
- case 0:
- case S_IFDIR:
- modestr[0] = 'd';
- break;
- case S_IFCHR:
- case S_IFBLK:
- modestr[0] = 'b';
- break;
- default:
- modestr[0] = 'x';
- break;
- }
- }
-
- for (i = 1; i < 8; i += 3)
- {
- if (mode & (S_IREAD >> (i-1))) modestr[i] = 'r';
- if (mode & (S_IWRITE >> (i-1))) modestr[i+1] = 'w';
- if (mode & (S_IEXEC >> (i-1))) modestr[i+2] = 'x';
- }
-
- if (mode & S_ISUID)
- modestr[3] = (modestr[3] == 'x') ? 's' : 'S';
-
- if (mode & S_ISGID)
- modestr[6] = (modestr[6] == 'x') ? 's' : 'S';
-
- if (mode & S_ISVTX)
- modestr[9] = (modestr[9] == 'x') ? 't' : 'T';
-
-
- return modestr;
-
- }
-
-
-
-
-
- /****************************************************************************/
- /* tar_clean_filespec -- removes illegal characters from directory and */
- /* file names. Replaces hyphens and commas with underscores. */
- /****************************************************************************/
- static tar_clean_filespec( char string[] )
-
- {
- register char *c;
-
- for ( c = string; *c; c++ )
- if (strchr( badchars, *c))
- *c = '_'; /* Replace illegal characters by underscores */
-
- }
-
-
-
- /****************************************************************************/
- /* */
- /* vms2tar -- handles create function */
- /* */
- /****************************************************************************/
- static vms2tar( int argc, char **argv )
-
- {
- int status;
- struct dsc$descriptor fsdsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
- char rs[NAM$C_MAXRSS+1];
- struct dsc$descriptor rsdsc = { sizeof(rs) - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, rs };
- struct dsc$descriptor dsdsc = { strlen(default_name), DSC$K_DTYPE_T, DSC$K_CLASS_S, default_name };
- struct FAB *fab = NULL;
- struct NAM *nam = NULL;
- int argi;
- int tarfd; /* File descriptor of output tarfile*/
- int ftype;
- int absolute = 0;
- char pathname[NAMSIZE];
- char dirnam[NAMSIZE];
- char filnam[NAMSIZE];
- char filtyp[NAMSIZE];
- struct tarhdr header; /* A tar header */
- struct stat sblock; /* structure returned from stat() */
- struct dsc$descriptor tarfdsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, tarfile };
-
-
- if (argc < 3 || (foption && argc < 4)) tar_usage();
-
- rs[sizeof(rs)-1] = EOS;
-
-
-
-
- /************************************************************************/
- /* Open the output file */
- /************************************************************************/
-
- tarfd = creat( tarfile, 0600, "rfm=fix", "mrs=512" );
-
- if (tarfd < 0)
- {
- fprintf( stderr, "tar: error opening output tarfile %s\n", tarfile );
- perror( "tar" );
- exit( SS$_NORMAL );
- }
-
- getname( tarfd, tarfile );
- lowercase( tarfile );
-
- tarfdsc.dsc$w_length = strlen( tarfile );
-
- status = lib$getdvi( &DVI$_DEVCLASS, 0, &tarfdsc, &devclass );
- if (!(status & 1))
- {
- fprintf( stderr, "tar: error getting device information for %s\n", tarfile );
- fprintf( stderr, "tar: %s\n", vmserr( status ) );
- exit( SS$_NORMAL );
- }
-
-
-
- /************************************************************************/
- /* For all files on the command line ... */
- /************************************************************************/
-
- for (argi = foption ? 3 : 2; argi < argc; ++argi)
- {
-
- fsdsc.dsc$w_length = strlen( argv[argi] );
- fsdsc.dsc$a_pointer = argv[argi];
-
- /********************************************************************/
- /* start the search */
- /********************************************************************/
-
- status = lib$find_file( &fsdsc, &rsdsc, &fab, &dsdsc );
-
- nam = fab->fab$l_nam;
-
-
- /********************************************************************/
- /* check for network file access */
- /********************************************************************/
-
- if (nam->nam$b_node)
- {
- fprintf( stderr, "tar: network file access is not supported.\n" );
- lib$find_file_end( &fab );
- continue;
- }
-
-
- /********************************************************************/
- /* store absolute UNIX pathnames if explicit device or directory */
- /********************************************************************/
-
- if (nam->nam$v_exp_dev)
- absolute = 1;
- else
- if (nam->nam$v_exp_dir)
- if (!strstr( argv[argi], "[-" ) &&
- !strstr( argv[argi], "[." ) &&
- !strstr( argv[argi], "<-" ) &&
- !strstr( argv[argi], "<." ))
- absolute = 1;
-
-
- do
- {
-
- tar_trim( rs );
-
- lowercase( rs );
-
- if (!(status & 1))
- {
- switch (status)
- {
- case RMS$_DNF:
- fprintf( stderr, "tar: directory not found %s\n", rs );
- break;
- case RMS$_FNF:
- fprintf( stderr, "tar: file not found %s\n", rs );
- break;
- case RMS$_PRV:
- fprintf( stderr, "tar: no privilege to access %s\n", rs );
- break;
- default:
- fprintf( stderr, "tar: error searching for %s\n", rs );
- fprintf( stderr, "tar: %s.\n", vmserr( status ) );
- break;
- }
- continue;
- }
-
-
- /****************************************************************/
- /* split filespec into directory, name, and type+version */
- /****************************************************************/
-
-
- strncpy( dirnam, nam->nam$l_dir, nam->nam$b_dir );
- dirnam[nam->nam$b_dir] = EOS;
-
- strncpy( filnam, nam->nam$l_name, nam->nam$b_name );
- filnam[nam->nam$b_name] = EOS;
-
- strncpy( filtyp, nam->nam$l_type, nam->nam$b_type + nam->nam$b_ver );
- filtyp[nam->nam$b_type + nam->nam$b_ver] = EOS;
-
-
- /****************************************************************/
- /* convert vms filespec to UNIX */
- /****************************************************************/
-
- ftype = tar_cvt_vmsname_to_unixname( dirnam, filnam, filtyp, absolute );
-
- strcpy( pathname, dirnam );
- strcat( pathname, filnam );
- strcat( pathname, filtyp );
-
- if (tar_get_fattr( rs, &sblock )) continue;
-
- /****************************************************************/
- /* prompt to process file */
- /****************************************************************/
-
- if (wait)
- {
- char temp[4] = EOS;
- while (*temp != 'y' && *temp != 'n')
- {
- printf( "a %s: ", rs );
- scanf( "%s", temp );
- *temp = _tolower( *temp );
- }
- if (*temp != 'y') continue;
- }
-
-
- switch (ftype)
- {
-
- case ISDIRE:
- sblock.st_size = 0;
- tar_fill_hdr( pathname, &sblock, &header );
- tar_write_hdr( tarfd, &header );
- break;
-
- case ISFILE:
-
- if (tar_insert_file( rs, pathname, &sblock, tarfd ) < 0)
- continue;
- break;
-
- }
-
- if (verbose)
- {
- int blocks = (sblock.st_size / DSIZE) + ((sblock.st_size % DSIZE) ? 1 : 0);
- printf( "a %s %d block%s\n", pathname, blocks, (blocks != 1 ? "s" : "") );
- }
-
- }
- while ( rsdsc.dsc$w_length = sizeof(rs) - 1,
- (status = lib$find_file( &fsdsc, &rsdsc, &fab, &dsdsc )) != RMS$_NMF );
-
- }
-
-
- tar_write_trailer( tarfd );
- close( tarfd );
-
- }
-
-
-
- /****************************************************************************/
- /* tar_insert_file - insert file into tar file. */
- /* */
- /* Move data from input file to tar file. */
- /* Always pad the output to a full DSIZE */
- /****************************************************************************/
- static int tar_insert_file
- ( char filename[],
- char pathname[],
- struct stat *sblock,
- int tarfd )
-
- {
-
- int nbytes = sblock->st_size;
- char buffer[DSIZE];
- int inbytes;
- FILE *infd;
- struct tarhdr header;
- int tarhdrpos;
-
-
- tarhdrpos = lseek( tarfd, 0, SEEK_CUR );
-
-
-
- if (sblock->st_fab_rfm == FAB$C_FIX ||
- sblock->st_fab_rfm == FAB$C_STM ||
- sblock->st_fab_rfm == FAB$C_STMLF)
- {
-
- if ((infd = fopen( filename, "rb" )) == NULL)
- {
- fprintf( stderr, "tar: error opening input file %s\n", filename );
- perror( "tar" );
- return -1;
- }
-
- tar_fill_hdr( pathname, sblock, &header ); /* We have all of the information */
- tar_write_hdr( tarfd, &header ); /* So write to the output */
-
- while (nbytes > 0)
- {
-
- inbytes = fread( buffer, 1, nbytes > DSIZE ? DSIZE : nbytes, infd );
-
- if (!inbytes)
- {
- fprintf( stderr, "tar: error reading input file %s\n", filename );
- perror( "tar" );
- fclose( infd );
-
- if (devclass != DC$_TAPE)
- {
- lseek( tarfd, tarhdrpos, SEEK_SET );
- return -1;
- }
- else
- exit( SS$_NORMAL );
-
- }
- nbytes -= inbytes;
- tar_flush( tarfd, buffer );
- }
-
- fclose( infd );
-
- }
- else
- {
-
- char *bufp = buffer;
- char *linep;
- char dbuffer[DSIZE];
-
- if ((infd = fopen( filename, "r" )) == NULL)
- {
- fprintf( stderr, "tar: error opening input file %s\n", filename );
- perror( "tar" );
- return -1;
- }
-
- sblock->st_size = 0;
-
- if (devclass == DC$_TAPE)
- {
- if ((sblock->st_size = tar_find_filesize( infd, filename )) < 0)
- {
- fclose( infd );
- return -1;
- }
- }
-
- tar_fill_hdr( pathname, sblock, &header ); /* Compute the header */
- tar_write_hdr( tarfd, &header ); /* Write it */
-
- nbytes = 0;
-
- while (fgets( dbuffer, DSIZE, infd ) != NULL)
- {
-
- nbytes += strlen( dbuffer );
-
- linep = dbuffer;
-
- while (*linep != EOS) /* read source file line by line*/
- {
- if (bufp >= &buffer[DSIZE])
- {
- bufp = buffer;
- tar_flush( tarfd, buffer ); /* if buffer full, flush it */
- } /* copy in fixed size output buffer */
- *bufp++ = *linep++;
- }
- }
-
- tar_flush( tarfd, buffer );
-
- fclose( infd );
-
- if (devclass != DC$_TAPE)
- if (nbytes)
- {
- sblock->st_size = nbytes;
- tar_rewrite_hdr( tarfd, tarhdrpos, nbytes );
- }
- else
- lseek( tarfd, tarhdrpos, SEEK_SET );
-
- }
-
- return 0;
-
- }
-
-
- /****************************************************************************/
- /* tar_find_filesize - calc bytes inf file by reading entire file */
- /****************************************************************************/
- static tar_find_filesize
- ( FILE *infd,
- char filename[] )
-
- {
-
- register int bytes = 0;
- char buffer[DSIZE];
-
-
- while (fgets( buffer, DSIZE, infd ) != NULL)
- bytes += strlen( buffer );
-
- if (!feof(infd))
- {
- fprintf( stderr, "tar: error reading input file %s\n", filename );
- fprintf( stderr, "tar: record too large or incorrect RMS attributes\n" );
- return -1;
- }
-
- rewind( infd ); /* Back to the beginning */
-
- return bytes;
-
- }
-
-
-
- /****************************************************************************/
- /* tar_flush - write a fixed size block in output tarfile */
- /****************************************************************************/
- static tar_flush
- ( int tarfd,
- char buffer[] )
-
- {
-
- if (write( tarfd, buffer, DSIZE) != DSIZE)
- {
- fprintf( stderr, "tar: error writing tarfile.\n" );
- perror( "tar" );
- exit( SS$_NORMAL );
- }
-
- }
-
-
-
- /****************************************************************************/
- /* tar_write_hdr - copy the header to the output file */
- /****************************************************************************/
- static int tar_write_hdr
- ( int tarfd,
- struct tarhdr *header )
-
- {
-
- register int n;
-
- if ((n = write( tarfd, header, DSIZE )) != DSIZE)
- {
- fprintf( stderr, "tar: error writing header in tarfile.\n" );
- perror( "tar" );
- exit( SS$_NORMAL );
- }
-
- return n;
-
- }
-
-
-
- /****************************************************************************/
- /* tar_rewrite_hdr - rewrite header with proper count and checksum */
- /****************************************************************************/
- static int tar_rewrite_hdr
- ( int tarfd,
- int hdrpos,
- int bytecount )
-
- {
-
- register int status;
- int chksum;
- char *ptr;
- int curpos;
- struct tarhdr header;
- char tmp[15];
-
-
- /************************************************************************/
- /* save current position in file */
- /************************************************************************/
-
- curpos = lseek( tarfd, 0, SEEK_CUR );
-
-
- /************************************************************************/
- /* position to header */
- /************************************************************************/
-
- status = lseek( tarfd, hdrpos, SEEK_SET );
-
-
- /************************************************************************/
- /* read the old header */
- /************************************************************************/
-
- status = read( tarfd, &header, DSIZE );
-
-
- /************************************************************************/
- /* store new count and checksum */
- /************************************************************************/
-
- sprintf( tmp, "%11o ", bytecount );
- strncpy( header.count, tmp, 12 );
-
- strncpy( header.chksum, " ", 8);
-
- for (chksum = 0, ptr = &header; ptr < &header.linkcount; ptr++)
- chksum += *ptr; /* make the checksum */
-
- sprintf( header.chksum, "%6o", chksum );
-
-
- /************************************************************************/
- /* rewrite the header */
- /************************************************************************/
-
- status = lseek( tarfd, hdrpos, SEEK_SET );
- status = write( tarfd, &header, DSIZE );
-
- /************************************************************************/
- /* back to our original position */
- /************************************************************************/
-
- status = lseek( tarfd, curpos, SEEK_SET );
-
- }
-
-
-
- /****************************************************************************/
- /* tar_get_fattr - get the file attributes via stat() */
- /****************************************************************************/
- static int tar_get_fattr
- ( char filespec[],
- struct stat *sblock )
-
- {
-
- if (stat( filespec, sblock ))
- {
- fprintf( stderr, "tar: can't get file status on %s\n", filespec );
- perror( "tar" );
- return -1;
- }
- else
- return 0;
-
- }
-
-
-
-
- /****************************************************************************/
- /* tar_write_trailer - write the two blank blocks on the output file */
- /* pad the output to a full blocksize if needed. */
- /****************************************************************************/
- static tar_write_trailer( int tarfd )
-
- {
- register int i;
- struct tarhdr header;
- register int tarfilepos;
-
- memset( &header, 0, DSIZE );
-
- tar_write_hdr( tarfd, &header );
- tar_write_hdr( tarfd, &header );
-
- tarfilepos = (lseek( tarfd, 0, SEEK_CUR ) / DSIZE) % BLKSIZE;
-
- for ( i = tarfilepos; i < BLKSIZE; i++ )
- tar_write_hdr( tarfd, &header );
-
- return 1;
-
- }
-
-
- /****************************************************************************/
- /* tar_cvt_vmsname_to_unixname */
- /* */
- /* Convert a VMS filename to UNIX format. Return a value to indicate */
- /* if this is a directory name, or another file. */
- /****************************************************************************/
- static int tar_cvt_vmsname_to_unixname
- ( char dirnam[],
- char filnam[],
- char filtyp[],
- int absolute )
-
- {
- register char *cp;
-
-
- /************************************************************************/
- /* fix up directory name, getting rid of rooted directories and mfd */
- /************************************************************************/
-
- tar_clean_dir( dirnam );
-
-
- /************************************************************************/
- /* lowercase the lot of em */
- /************************************************************************/
-
- lowercase( dirnam );
- lowercase( filnam );
- lowercase( filtyp );
-
-
- if (!absolute)
- {
-
- char tmp1[NAM$C_MAXRSS];
- char tmp2[NAM$C_MAXRSS];
- register char *cp1 = tmp1;
- register char *cp2 = tmp2;
- register char *dotp1;
- register char *dotp2;
-
- strcpy( tmp1, dirnam );
- tmp1[strlen(tmp1) - 1] = '.';
-
- strcpy( tmp2, curdir );
- tmp2[strlen(tmp2) - 1] = '.';
-
- while ( (dotp1 = strchr( cp1, '.' )) && (dotp2 = strchr( cp2, '.' )) )
- {
- *dotp1 = *dotp2 = EOS;
- if (strcmp( cp1, cp2 )) break;
- cp1 = ++dotp1;
- cp2 = ++dotp2;
- }
-
- if (dotp1) *dotp1 = '.';
- strcpy( dirnam, cp1 );
- }
-
-
- if (*dirnam == '[') *dirnam = '/';
-
- while (cp = dirnam, cp = strchr(cp, '.'))
- *cp = '/';
-
- while (cp = dirnam, cp = strchr(cp, ']'))
- *cp = '/';
-
- if (!strcmp( filtyp, ".dir;1" ))
- {
- strcat( dirnam, filnam );
- strcat( dirnam, "/" );
- *filnam = *filtyp = EOS;
- return ISDIRE;
- }
-
- if (cp = strchr( filtyp, ';' )) *cp = EOS; /* strip version number */
-
- if (!strcmp( filtyp, "." ) && !dot) /* strip trailing dot maybe */
- *filtyp = EOS;
-
- return ISFILE;
-
- }
-
-
-
-
- /****************************************************************************/
- /* tar_fill_hdr - fill the fields of the header */
- /* */
- /* enter with the file name, if the file name is empty, */
- /* then this is a trailer, and we should fill it with zeroes. */
- /****************************************************************************/
- static int tar_fill_hdr
- ( char path[],
- struct stat *sblock,
- struct tarhdr *header )
-
- {
-
- int chksum;
- char *ptr;
- char tmp[15];
-
-
- /************************************************************************/
- /* Fill the header with zeroes */
- /************************************************************************/
-
- memset( header, 0, DSIZE );
-
- if (strlen( path )) /* only fill if there is a file */
- {
- sprintf( header->title, "%s", path );
- sprintf( header->mode, "%6o ", sblock->st_mode );
- sprintf( header->uid, "%6o ", sblock->st_uid );
- sprintf( header->gid, "%6o ", sblock->st_gid );
- sprintf( tmp, "%11o ", sblock->st_size );
- strncpy( header->count, tmp, 12 );
- sprintf( tmp, "%11o ", sblock->st_mtime );
- strncpy( header->time, tmp, 12 );
- strncpy( header->chksum, " ", 8);
-
- for (chksum = 0, ptr = header; ptr < &header->linkcount; ptr++)
- chksum += *ptr; /* make the checksum */
-
- sprintf( header->chksum, "%6o", chksum );
- }
-
- return 0;
-
- }
-
-
-
- /****************************************************************************/
- /* lowercase - function to change a string to lower case */
- /****************************************************************************/
- static int lowercase( char string[] )
-
- {
- int i;
-
- for (i=0; string[i] = _tolower( string[i] ); i++ );
-
- return --i; /* return string length */
-
- }
-
-
-
-
- /****************************************************************************/
- /* tar_trim - trim string of trailing spaces/tabs */
- /****************************************************************************/
- static tar_trim( char *string )
-
- {
- int i;
-
- for ( i = strlen(string) - 1; string[i] == ' ' || string[i] == '\t'; i-- );
-
- string[i+1] = EOS;
-
- }
-
-
-
- /****************************************************************************/
- /* tar_clean_dir - routine to get rid of rooted directory problems */
- /* and any others that turn up */
- /****************************************************************************/
- static int tar_clean_dir( char string[] )
-
- {
- register char *cp;
-
-
-
- if (cp = strstr( string, "][" ))
- strcpy( cp, cp+2 ); /* Just collapse around the string */
-
- if (cp = strstr( string, "[000000." ))
- strcpy( cp + 1, cp + 8 ); /* remove "000000." */
-
- if (cp = strchr( string, '<' ))
- *cp = '[';
-
- if (cp = strchr( string, '>' ))
- *cp = ']';
-
- }
-
-
-
- /****************************************************************************/
- /* Syntax error exit */
- /****************************************************************************/
- static tar_usage()
- {
- printf( "usage: tar x|c|t[vwbdz][f tarfile] [file [file...]]\n" );
- exit( 1 );
- }
-
-
-
- /************************************************************************/
- /* return pointer to C-string vms error message */
- /************************************************************************/
- static char *vmserr
- ( int status )
-
- {
- static char errmsg[133];
- $DESCRIPTOR( errmsgdsc, errmsg );
- long i;
-
- sys$getmsg( status, &errmsgdsc.dsc$w_length, &errmsgdsc, 15, 0 );
- errmsg[errmsgdsc.dsc$w_length] = EOS;
- for (i = 0; errmsg[i]; i++)
- errmsg[i] = _tolower(errmsg[i]);
-
- return errmsg;
- }
-
-