351 lines
8.2 KiB
C
351 lines
8.2 KiB
C
|
/* $Source: /u/mark/src/pax/RCS/tar.c,v $
|
||
|
*
|
||
|
* $Revision: 1.2 $
|
||
|
*
|
||
|
* tar.c - tar specific functions for archive handling
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* These routines provide a tar conforming interface to the pax
|
||
|
* program.
|
||
|
*
|
||
|
* AUTHOR
|
||
|
*
|
||
|
* Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
|
||
|
*
|
||
|
* Sponsored by The USENIX Association for public distribution.
|
||
|
*
|
||
|
* Copyright (c) 1989 Mark H. Colburn.
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms are permitted
|
||
|
* provided that the above copyright notice is duplicated in all such
|
||
|
* forms and that any documentation, advertising materials, and other
|
||
|
* materials related to such distribution and use acknowledge that the
|
||
|
* software was developed by Mark H. Colburn and sponsored by The
|
||
|
* USENIX Association.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
*
|
||
|
* $Log: tar.c,v $
|
||
|
* Revision 1.2 89/02/12 10:06:05 mark
|
||
|
* 1.2 release fixes
|
||
|
*
|
||
|
* Revision 1.1 88/12/23 18:02:38 mark
|
||
|
* Initial revision
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#ifndef lint
|
||
|
static char *ident = "$Id: tar.c,v 1.2 89/02/12 10:06:05 mark Exp $";
|
||
|
static char *copyright ="Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.";
|
||
|
#endif /* not lint */
|
||
|
|
||
|
/* Headers */
|
||
|
|
||
|
#include "pax.h"
|
||
|
|
||
|
|
||
|
/* Defines */
|
||
|
|
||
|
#define DEF_BLOCKING 20 /* default blocking factor for extract */
|
||
|
|
||
|
|
||
|
/* Function Prototypes */
|
||
|
|
||
|
#ifdef __STDC__
|
||
|
|
||
|
static int taropt(int , char **, char *);
|
||
|
static void usage(void);
|
||
|
|
||
|
#else /* !__STDC__ */
|
||
|
|
||
|
static int taropt();
|
||
|
static void usage();
|
||
|
|
||
|
#endif /* __STDC__ */
|
||
|
|
||
|
|
||
|
/* do_tar - main routine for tar.
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* Provides a tar interface to the PAX program. All tar standard
|
||
|
* command line options are supported.
|
||
|
*
|
||
|
* PARAMETERS
|
||
|
*
|
||
|
* int argc - argument count (argc from main)
|
||
|
* char **argv - argument list (argv from main)
|
||
|
*
|
||
|
* RETURNS
|
||
|
*
|
||
|
* zero
|
||
|
*/
|
||
|
|
||
|
#ifdef __STDC__
|
||
|
|
||
|
void do_tar(int argc, char **argv) /* Xn */
|
||
|
|
||
|
#else
|
||
|
|
||
|
void do_tar(argc, argv) /* Xn */
|
||
|
int argc; /* argument count (argc from main) */
|
||
|
char **argv; /* argument list (argv from main) */
|
||
|
|
||
|
#endif
|
||
|
{
|
||
|
int c; /* Option letter */
|
||
|
|
||
|
/* Set default option values */
|
||
|
names_from_stdin = 0;
|
||
|
#ifdef DF_TRACE_DEBUG
|
||
|
printf("DF_TRACE_DEBUG: void do_tar() in tar.c\n");
|
||
|
#endif
|
||
|
ar_file = getenv("TAPE"); /* From environment, or */
|
||
|
if (ar_file == 0) {
|
||
|
ar_file = DEF_AR_FILE; /* From Makefile */
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* set up the flags to reflect the default pax inteface. Unfortunately
|
||
|
* the pax interface has several options which are completely opposite
|
||
|
* of the tar and/or cpio interfaces...
|
||
|
*/
|
||
|
f_unconditional = 1;
|
||
|
f_mtime = 1;
|
||
|
f_dir_create = 1;
|
||
|
blocking = 0;
|
||
|
ar_interface = TAR;
|
||
|
ar_format = TAR;
|
||
|
msgfile=stderr;
|
||
|
|
||
|
/* Parse options */
|
||
|
while ((c = taropt(argc, argv, "b:cf:hlmortuvwx")) != EOF) {
|
||
|
switch (c) {
|
||
|
case 'b': /* specify blocking factor */
|
||
|
/*
|
||
|
* FIXME - we should use a conversion routine that does
|
||
|
* some kind of reasonable error checking, but...
|
||
|
*/
|
||
|
blocking = atoi(optarg);
|
||
|
break;
|
||
|
case 'c': /* create a new archive */
|
||
|
f_create = 1;
|
||
|
break;
|
||
|
case 'f': /* specify input/output file */
|
||
|
ar_file = optarg;
|
||
|
break;
|
||
|
case 'h':
|
||
|
f_follow_links = 1; /* follow symbolic links */
|
||
|
break;
|
||
|
case 'l': /* report unresolved links */
|
||
|
f_linksleft = 1;
|
||
|
break;
|
||
|
case 'm': /* don't restore modification times */
|
||
|
f_modified = 1;
|
||
|
break;
|
||
|
case 'o': /* take on user's group rather than
|
||
|
* archives */
|
||
|
break;
|
||
|
case 'r': /* named files are appended to archive */
|
||
|
f_append = 1;
|
||
|
break;
|
||
|
case 't':
|
||
|
f_list = 1; /* list files in archive */
|
||
|
break;
|
||
|
case 'u': /* named files are added to archive */
|
||
|
f_newer = 1;
|
||
|
break;
|
||
|
case 'v': /* verbose mode */
|
||
|
f_verbose = 1;
|
||
|
break;
|
||
|
case 'w': /* user interactive mode */
|
||
|
f_disposition = 1;
|
||
|
break;
|
||
|
case 'x': /* named files are extracted from archive */
|
||
|
f_extract = 1;
|
||
|
break;
|
||
|
case '?':
|
||
|
usage();
|
||
|
exit(EX_ARGSBAD);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* check command line argument sanity */
|
||
|
if (f_create + f_extract + f_list + f_append + f_newer != 1) {
|
||
|
(void) fprintf(stderr,
|
||
|
"%s: you must specify exactly one of the c, t, r, u or x options\n",
|
||
|
myname);
|
||
|
usage();
|
||
|
exit(EX_ARGSBAD);
|
||
|
}
|
||
|
|
||
|
/* set the blocking factor, if not set by the user */
|
||
|
if (blocking == 0) {
|
||
|
#ifdef USG
|
||
|
if (f_extract || f_list) {
|
||
|
blocking = DEF_BLOCKING;
|
||
|
fprintf(stderr, "Tar: blocksize = %d\n", blocking);
|
||
|
} else {
|
||
|
blocking = 1;
|
||
|
}
|
||
|
#else /* !USG */
|
||
|
blocking = 20;
|
||
|
#endif /* USG */
|
||
|
}
|
||
|
blocksize = blocking * BLOCKSIZE;
|
||
|
buf_allocate((OFFSET) blocksize);
|
||
|
|
||
|
if (f_create) {
|
||
|
open_archive(AR_WRITE);
|
||
|
create_archive(); /* create the archive */
|
||
|
} else if (f_extract) {
|
||
|
open_archive(AR_READ);
|
||
|
read_archive(); /* extract files from archive */
|
||
|
} else if (f_list) {
|
||
|
open_archive(AR_READ);
|
||
|
read_archive(); /* read and list contents of archive */
|
||
|
} else if (f_append) {
|
||
|
open_archive(AR_APPEND);
|
||
|
append_archive(); /* append files to archive */
|
||
|
}
|
||
|
|
||
|
if (f_linksleft) {
|
||
|
linkleft(); /* report any unresolved links */
|
||
|
}
|
||
|
#if 0 /* Xn */
|
||
|
|
||
|
return (0);
|
||
|
#endif /* Xn */
|
||
|
}
|
||
|
|
||
|
|
||
|
/* taropt - tar specific getopt
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* Plug-compatible replacement for getopt() for parsing tar-like
|
||
|
* arguments. If the first argument begins with "-", it uses getopt;
|
||
|
* otherwise, it uses the old rules used by tar, dump, and ps.
|
||
|
*
|
||
|
* PARAMETERS
|
||
|
*
|
||
|
* int argc - argument count (argc from main)
|
||
|
* char **argv - argument list (argv from main)
|
||
|
* char *optstring - sring which describes allowable options
|
||
|
*
|
||
|
* RETURNS
|
||
|
*
|
||
|
* Returns the next option character in the option string(s). If the
|
||
|
* option requires an argument and an argument was given, the argument
|
||
|
* is pointed to by "optarg". If no option character was found,
|
||
|
* returns an EOF.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#ifdef __STDC__
|
||
|
|
||
|
static int taropt(int argc, char **argv, char *optstring)
|
||
|
|
||
|
#else
|
||
|
|
||
|
static int taropt(argc, argv, optstring)
|
||
|
int argc;
|
||
|
char **argv;
|
||
|
char *optstring;
|
||
|
|
||
|
#endif
|
||
|
{
|
||
|
extern char *optarg; /* Points to next arg */
|
||
|
extern int optind; /* Global argv index */
|
||
|
static char *key = NULL; /* Points to next keyletter */ /* Xn */
|
||
|
static char use_getopt = 0; /* !=0 if argv[1][0] was '-' */ /* Xn */
|
||
|
char c;
|
||
|
char *place;
|
||
|
|
||
|
#ifdef DF_TRACE_DEBUG
|
||
|
printf("DF_TRACE_DEBUG: static int taropt() in tar.c\n");
|
||
|
#endif
|
||
|
optarg = (char *)NULL;
|
||
|
|
||
|
if (key == (char *)NULL) { /* First time */
|
||
|
if (argc < 2)
|
||
|
return EOF;
|
||
|
key = argv[1];
|
||
|
if (*key == '-')
|
||
|
use_getopt++;
|
||
|
else
|
||
|
optind = 2;
|
||
|
}
|
||
|
if (use_getopt) {
|
||
|
#ifdef _POSIX2_SOURCE /* Xn */
|
||
|
return getopt(argc, (const char * const *) argv, optstring); /* Xn */
|
||
|
#else /* Xn */
|
||
|
return getopt(argc, argv, optstring);
|
||
|
#endif /* Xn */
|
||
|
}
|
||
|
|
||
|
c = *key++;
|
||
|
if (c == '\0') {
|
||
|
key--;
|
||
|
return EOF;
|
||
|
}
|
||
|
place = strchr(optstring, c);
|
||
|
|
||
|
if (place == (char *)NULL || c == ':') {
|
||
|
fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
|
||
|
return ('?');
|
||
|
}
|
||
|
place++;
|
||
|
if (*place == ':') {
|
||
|
if (optind < argc) {
|
||
|
optarg = argv[optind];
|
||
|
optind++;
|
||
|
} else {
|
||
|
fprintf(stderr, "%s: %c argument missing\n",
|
||
|
argv[0], c);
|
||
|
return ('?');
|
||
|
}
|
||
|
}
|
||
|
return (c);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* usage - print a helpful message and exit
|
||
|
*
|
||
|
* DESCRIPTION
|
||
|
*
|
||
|
* Usage prints out the usage message for the TAR interface and then
|
||
|
* exits with a non-zero termination status. This is used when a user
|
||
|
* has provided non-existant or incompatible command line arguments.
|
||
|
*
|
||
|
* RETURNS
|
||
|
*
|
||
|
* Returns an exit status of 1 to the parent process.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#ifdef __STDC__
|
||
|
|
||
|
static void usage(void)
|
||
|
|
||
|
#else
|
||
|
|
||
|
static void usage()
|
||
|
|
||
|
#endif
|
||
|
{
|
||
|
#ifdef DF_TRACE_DEBUG
|
||
|
printf("DF_TRACE_DEBUG: static void usage() in tar.c\n");
|
||
|
#endif
|
||
|
fprintf(stderr, "Usage: %s -c[bfvw] device block filename..\n", myname);
|
||
|
fprintf(stderr, " %s -r[bvw] device block [filename...]\n", myname);
|
||
|
fprintf(stderr, " %s -t[vf] device\n", myname);
|
||
|
fprintf(stderr, " %s -u[bvw] device block [filename...]\n", myname);
|
||
|
fprintf(stderr, " %s -x[flmovw] device [filename...]\n", myname);
|
||
|
exit(1);
|
||
|
}
|