1*9a747e4fSDavid du Colombier /* $Source: /u/mark/src/pax/RCS/tar.c,v $
2*9a747e4fSDavid du Colombier *
3*9a747e4fSDavid du Colombier * $Revision: 1.2 $
4*9a747e4fSDavid du Colombier *
5*9a747e4fSDavid du Colombier * tar.c - tar specific functions for archive handling
6*9a747e4fSDavid du Colombier *
7*9a747e4fSDavid du Colombier * DESCRIPTION
8*9a747e4fSDavid du Colombier *
9*9a747e4fSDavid du Colombier * These routines provide a tar conforming interface to the pax
10*9a747e4fSDavid du Colombier * program.
11*9a747e4fSDavid du Colombier *
12*9a747e4fSDavid du Colombier * AUTHOR
13*9a747e4fSDavid du Colombier *
14*9a747e4fSDavid du Colombier * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
15*9a747e4fSDavid du Colombier *
16*9a747e4fSDavid du Colombier * Sponsored by The USENIX Association for public distribution.
17*9a747e4fSDavid du Colombier *
18*9a747e4fSDavid du Colombier * Copyright (c) 1989 Mark H. Colburn.
19*9a747e4fSDavid du Colombier * All rights reserved.
20*9a747e4fSDavid du Colombier *
21*9a747e4fSDavid du Colombier * Redistribution and use in source and binary forms are permitted
22*9a747e4fSDavid du Colombier * provided that the above copyright notice is duplicated in all such
23*9a747e4fSDavid du Colombier * forms and that any documentation, advertising materials, and other
24*9a747e4fSDavid du Colombier * materials related to such distribution and use acknowledge that the
25*9a747e4fSDavid du Colombier * software was developed by Mark H. Colburn and sponsored by The
26*9a747e4fSDavid du Colombier * USENIX Association.
27*9a747e4fSDavid du Colombier *
28*9a747e4fSDavid du Colombier * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29*9a747e4fSDavid du Colombier * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30*9a747e4fSDavid du Colombier * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31*9a747e4fSDavid du Colombier *
32*9a747e4fSDavid du Colombier * $Log: tar.c,v $
33*9a747e4fSDavid du Colombier * Revision 1.2 89/02/12 10:06:05 mark
34*9a747e4fSDavid du Colombier * 1.2 release fixes
35*9a747e4fSDavid du Colombier *
36*9a747e4fSDavid du Colombier * Revision 1.1 88/12/23 18:02:38 mark
37*9a747e4fSDavid du Colombier * Initial revision
38*9a747e4fSDavid du Colombier *
39*9a747e4fSDavid du Colombier */
40*9a747e4fSDavid du Colombier
41*9a747e4fSDavid du Colombier #ifndef lint
42*9a747e4fSDavid du Colombier static char *ident = "$Id: tar.c,v 1.2 89/02/12 10:06:05 mark Exp $";
43*9a747e4fSDavid du Colombier static char *copyright ="Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.";
44*9a747e4fSDavid du Colombier #endif /* not lint */
45*9a747e4fSDavid du Colombier
46*9a747e4fSDavid du Colombier /* Headers */
47*9a747e4fSDavid du Colombier
48*9a747e4fSDavid du Colombier #include "pax.h"
49*9a747e4fSDavid du Colombier
50*9a747e4fSDavid du Colombier
51*9a747e4fSDavid du Colombier /* Defines */
52*9a747e4fSDavid du Colombier
53*9a747e4fSDavid du Colombier #define DEF_BLOCKING 20 /* default blocking factor for extract */
54*9a747e4fSDavid du Colombier
55*9a747e4fSDavid du Colombier
56*9a747e4fSDavid du Colombier /* Function Prototypes */
57*9a747e4fSDavid du Colombier
58*9a747e4fSDavid du Colombier #ifdef __STDC__
59*9a747e4fSDavid du Colombier
60*9a747e4fSDavid du Colombier static int taropt(int , char **, char *);
61*9a747e4fSDavid du Colombier static void usage(void);
62*9a747e4fSDavid du Colombier
63*9a747e4fSDavid du Colombier #else /* !__STDC__ */
64*9a747e4fSDavid du Colombier
65*9a747e4fSDavid du Colombier static int taropt();
66*9a747e4fSDavid du Colombier static void usage();
67*9a747e4fSDavid du Colombier
68*9a747e4fSDavid du Colombier #endif /* __STDC__ */
69*9a747e4fSDavid du Colombier
70*9a747e4fSDavid du Colombier
71*9a747e4fSDavid du Colombier /* do_tar - main routine for tar.
72*9a747e4fSDavid du Colombier *
73*9a747e4fSDavid du Colombier * DESCRIPTION
74*9a747e4fSDavid du Colombier *
75*9a747e4fSDavid du Colombier * Provides a tar interface to the PAX program. All tar standard
76*9a747e4fSDavid du Colombier * command line options are supported.
77*9a747e4fSDavid du Colombier *
78*9a747e4fSDavid du Colombier * PARAMETERS
79*9a747e4fSDavid du Colombier *
80*9a747e4fSDavid du Colombier * int argc - argument count (argc from main)
81*9a747e4fSDavid du Colombier * char **argv - argument list (argv from main)
82*9a747e4fSDavid du Colombier *
83*9a747e4fSDavid du Colombier * RETURNS
84*9a747e4fSDavid du Colombier *
85*9a747e4fSDavid du Colombier * zero
86*9a747e4fSDavid du Colombier */
87*9a747e4fSDavid du Colombier
88*9a747e4fSDavid du Colombier #ifdef __STDC__
89*9a747e4fSDavid du Colombier
do_tar(int argc,char ** argv)90*9a747e4fSDavid du Colombier int do_tar(int argc, char **argv)
91*9a747e4fSDavid du Colombier
92*9a747e4fSDavid du Colombier #else
93*9a747e4fSDavid du Colombier
94*9a747e4fSDavid du Colombier int do_tar(argc, argv)
95*9a747e4fSDavid du Colombier int argc; /* argument count (argc from main) */
96*9a747e4fSDavid du Colombier char **argv; /* argument list (argv from main) */
97*9a747e4fSDavid du Colombier
98*9a747e4fSDavid du Colombier #endif
99*9a747e4fSDavid du Colombier {
100*9a747e4fSDavid du Colombier int c; /* Option letter */
101*9a747e4fSDavid du Colombier
102*9a747e4fSDavid du Colombier /* Set default option values */
103*9a747e4fSDavid du Colombier names_from_stdin = 0;
104*9a747e4fSDavid du Colombier ar_file = getenv("TAPE"); /* From environment, or */
105*9a747e4fSDavid du Colombier if (ar_file == 0) {
106*9a747e4fSDavid du Colombier ar_file = DEF_AR_FILE; /* From Makefile */
107*9a747e4fSDavid du Colombier }
108*9a747e4fSDavid du Colombier
109*9a747e4fSDavid du Colombier /*
110*9a747e4fSDavid du Colombier * set up the flags to reflect the default pax inteface. Unfortunately
111*9a747e4fSDavid du Colombier * the pax interface has several options which are completely opposite
112*9a747e4fSDavid du Colombier * of the tar and/or cpio interfaces...
113*9a747e4fSDavid du Colombier */
114*9a747e4fSDavid du Colombier f_unconditional = 1;
115*9a747e4fSDavid du Colombier f_mtime = 1;
116*9a747e4fSDavid du Colombier f_dir_create = 1;
117*9a747e4fSDavid du Colombier blocking = 0;
118*9a747e4fSDavid du Colombier ar_interface = TAR;
119*9a747e4fSDavid du Colombier ar_format = TAR;
120*9a747e4fSDavid du Colombier msgfile=stderr;
121*9a747e4fSDavid du Colombier
122*9a747e4fSDavid du Colombier /* Parse options */
123*9a747e4fSDavid du Colombier while ((c = taropt(argc, argv, "b:cf:hlmortuvwx")) != EOF) {
124*9a747e4fSDavid du Colombier switch (c) {
125*9a747e4fSDavid du Colombier case 'b': /* specify blocking factor */
126*9a747e4fSDavid du Colombier /*
127*9a747e4fSDavid du Colombier * FIXME - we should use a conversion routine that does
128*9a747e4fSDavid du Colombier * some kind of reasonable error checking, but...
129*9a747e4fSDavid du Colombier */
130*9a747e4fSDavid du Colombier blocking = atoi(optarg);
131*9a747e4fSDavid du Colombier break;
132*9a747e4fSDavid du Colombier case 'c': /* create a new archive */
133*9a747e4fSDavid du Colombier f_create = 1;
134*9a747e4fSDavid du Colombier break;
135*9a747e4fSDavid du Colombier case 'f': /* specify input/output file */
136*9a747e4fSDavid du Colombier ar_file = optarg;
137*9a747e4fSDavid du Colombier break;
138*9a747e4fSDavid du Colombier case 'h':
139*9a747e4fSDavid du Colombier f_follow_links = 1; /* follow symbolic links */
140*9a747e4fSDavid du Colombier break;
141*9a747e4fSDavid du Colombier case 'l': /* report unresolved links */
142*9a747e4fSDavid du Colombier f_linksleft = 1;
143*9a747e4fSDavid du Colombier break;
144*9a747e4fSDavid du Colombier case 'm': /* don't restore modification times */
145*9a747e4fSDavid du Colombier f_modified = 1;
146*9a747e4fSDavid du Colombier break;
147*9a747e4fSDavid du Colombier case 'o': /* take on user's group rather than
148*9a747e4fSDavid du Colombier * archives */
149*9a747e4fSDavid du Colombier break;
150*9a747e4fSDavid du Colombier case 'r': /* named files are appended to archive */
151*9a747e4fSDavid du Colombier f_append = 1;
152*9a747e4fSDavid du Colombier break;
153*9a747e4fSDavid du Colombier case 't':
154*9a747e4fSDavid du Colombier f_list = 1; /* list files in archive */
155*9a747e4fSDavid du Colombier break;
156*9a747e4fSDavid du Colombier case 'u': /* named files are added to archive */
157*9a747e4fSDavid du Colombier f_newer = 1;
158*9a747e4fSDavid du Colombier break;
159*9a747e4fSDavid du Colombier case 'v': /* verbose mode */
160*9a747e4fSDavid du Colombier f_verbose = 1;
161*9a747e4fSDavid du Colombier break;
162*9a747e4fSDavid du Colombier case 'w': /* user interactive mode */
163*9a747e4fSDavid du Colombier f_disposition = 1;
164*9a747e4fSDavid du Colombier break;
165*9a747e4fSDavid du Colombier case 'x': /* named files are extracted from archive */
166*9a747e4fSDavid du Colombier f_extract = 1;
167*9a747e4fSDavid du Colombier break;
168*9a747e4fSDavid du Colombier case '?':
169*9a747e4fSDavid du Colombier usage();
170*9a747e4fSDavid du Colombier exit(EX_ARGSBAD);
171*9a747e4fSDavid du Colombier }
172*9a747e4fSDavid du Colombier }
173*9a747e4fSDavid du Colombier
174*9a747e4fSDavid du Colombier /* check command line argument sanity */
175*9a747e4fSDavid du Colombier if (f_create + f_extract + f_list + f_append + f_newer != 1) {
176*9a747e4fSDavid du Colombier (void) fprintf(stderr,
177*9a747e4fSDavid du Colombier "%s: you must specify exactly one of the c, t, r, u or x options\n",
178*9a747e4fSDavid du Colombier myname);
179*9a747e4fSDavid du Colombier usage();
180*9a747e4fSDavid du Colombier exit(EX_ARGSBAD);
181*9a747e4fSDavid du Colombier }
182*9a747e4fSDavid du Colombier
183*9a747e4fSDavid du Colombier /* set the blocking factor, if not set by the user */
184*9a747e4fSDavid du Colombier if (blocking == 0) {
185*9a747e4fSDavid du Colombier #ifdef USG
186*9a747e4fSDavid du Colombier if (f_extract || f_list) {
187*9a747e4fSDavid du Colombier blocking = DEF_BLOCKING;
188*9a747e4fSDavid du Colombier fprintf(stderr, "Tar: blocksize = %d\n", blocking);
189*9a747e4fSDavid du Colombier } else {
190*9a747e4fSDavid du Colombier blocking = 1;
191*9a747e4fSDavid du Colombier }
192*9a747e4fSDavid du Colombier #else /* !USG */
193*9a747e4fSDavid du Colombier blocking = 20;
194*9a747e4fSDavid du Colombier #endif /* USG */
195*9a747e4fSDavid du Colombier }
196*9a747e4fSDavid du Colombier blocksize = blocking * BLOCKSIZE;
197*9a747e4fSDavid du Colombier buf_allocate((OFFSET) blocksize);
198*9a747e4fSDavid du Colombier
199*9a747e4fSDavid du Colombier if (f_create) {
200*9a747e4fSDavid du Colombier open_archive(AR_WRITE);
201*9a747e4fSDavid du Colombier create_archive(); /* create the archive */
202*9a747e4fSDavid du Colombier } else if (f_extract) {
203*9a747e4fSDavid du Colombier open_archive(AR_READ);
204*9a747e4fSDavid du Colombier read_archive(); /* extract files from archive */
205*9a747e4fSDavid du Colombier } else if (f_list) {
206*9a747e4fSDavid du Colombier open_archive(AR_READ);
207*9a747e4fSDavid du Colombier read_archive(); /* read and list contents of archive */
208*9a747e4fSDavid du Colombier } else if (f_append) {
209*9a747e4fSDavid du Colombier open_archive(AR_APPEND);
210*9a747e4fSDavid du Colombier append_archive(); /* append files to archive */
211*9a747e4fSDavid du Colombier }
212*9a747e4fSDavid du Colombier
213*9a747e4fSDavid du Colombier if (f_linksleft) {
214*9a747e4fSDavid du Colombier linkleft(); /* report any unresolved links */
215*9a747e4fSDavid du Colombier }
216*9a747e4fSDavid du Colombier
217*9a747e4fSDavid du Colombier return (0);
218*9a747e4fSDavid du Colombier }
219*9a747e4fSDavid du Colombier
220*9a747e4fSDavid du Colombier
221*9a747e4fSDavid du Colombier /* taropt - tar specific getopt
222*9a747e4fSDavid du Colombier *
223*9a747e4fSDavid du Colombier * DESCRIPTION
224*9a747e4fSDavid du Colombier *
225*9a747e4fSDavid du Colombier * Plug-compatible replacement for getopt() for parsing tar-like
226*9a747e4fSDavid du Colombier * arguments. If the first argument begins with "-", it uses getopt;
227*9a747e4fSDavid du Colombier * otherwise, it uses the old rules used by tar, dump, and ps.
228*9a747e4fSDavid du Colombier *
229*9a747e4fSDavid du Colombier * PARAMETERS
230*9a747e4fSDavid du Colombier *
231*9a747e4fSDavid du Colombier * int argc - argument count (argc from main)
232*9a747e4fSDavid du Colombier * char **argv - argument list (argv from main)
233*9a747e4fSDavid du Colombier * char *optstring - sring which describes allowable options
234*9a747e4fSDavid du Colombier *
235*9a747e4fSDavid du Colombier * RETURNS
236*9a747e4fSDavid du Colombier *
237*9a747e4fSDavid du Colombier * Returns the next option character in the option string(s). If the
238*9a747e4fSDavid du Colombier * option requires an argument and an argument was given, the argument
239*9a747e4fSDavid du Colombier * is pointed to by "optarg". If no option character was found,
240*9a747e4fSDavid du Colombier * returns an EOF.
241*9a747e4fSDavid du Colombier *
242*9a747e4fSDavid du Colombier */
243*9a747e4fSDavid du Colombier
244*9a747e4fSDavid du Colombier #ifdef __STDC__
245*9a747e4fSDavid du Colombier
taropt(int argc,char ** argv,char * optstring)246*9a747e4fSDavid du Colombier static int taropt(int argc, char **argv, char *optstring)
247*9a747e4fSDavid du Colombier
248*9a747e4fSDavid du Colombier #else
249*9a747e4fSDavid du Colombier
250*9a747e4fSDavid du Colombier static int taropt(argc, argv, optstring)
251*9a747e4fSDavid du Colombier int argc;
252*9a747e4fSDavid du Colombier char **argv;
253*9a747e4fSDavid du Colombier char *optstring;
254*9a747e4fSDavid du Colombier
255*9a747e4fSDavid du Colombier #endif
256*9a747e4fSDavid du Colombier {
257*9a747e4fSDavid du Colombier extern char *optarg; /* Points to next arg */
258*9a747e4fSDavid du Colombier extern int optind; /* Global argv index */
259*9a747e4fSDavid du Colombier static char *key; /* Points to next keyletter */
260*9a747e4fSDavid du Colombier static char use_getopt; /* !=0 if argv[1][0] was '-' */
261*9a747e4fSDavid du Colombier char c;
262*9a747e4fSDavid du Colombier char *place;
263*9a747e4fSDavid du Colombier
264*9a747e4fSDavid du Colombier optarg = (char *)NULL;
265*9a747e4fSDavid du Colombier
266*9a747e4fSDavid du Colombier if (key == (char *)NULL) { /* First time */
267*9a747e4fSDavid du Colombier if (argc < 2)
268*9a747e4fSDavid du Colombier return EOF;
269*9a747e4fSDavid du Colombier key = argv[1];
270*9a747e4fSDavid du Colombier if (*key == '-')
271*9a747e4fSDavid du Colombier use_getopt++;
272*9a747e4fSDavid du Colombier else
273*9a747e4fSDavid du Colombier optind = 2;
274*9a747e4fSDavid du Colombier }
275*9a747e4fSDavid du Colombier if (use_getopt) {
276*9a747e4fSDavid du Colombier return getopt(argc, argv, optstring);
277*9a747e4fSDavid du Colombier }
278*9a747e4fSDavid du Colombier
279*9a747e4fSDavid du Colombier c = *key++;
280*9a747e4fSDavid du Colombier if (c == '\0') {
281*9a747e4fSDavid du Colombier key--;
282*9a747e4fSDavid du Colombier return EOF;
283*9a747e4fSDavid du Colombier }
284*9a747e4fSDavid du Colombier place = strchr(optstring, c);
285*9a747e4fSDavid du Colombier
286*9a747e4fSDavid du Colombier if (place == (char *)NULL || c == ':') {
287*9a747e4fSDavid du Colombier fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
288*9a747e4fSDavid du Colombier return ('?');
289*9a747e4fSDavid du Colombier }
290*9a747e4fSDavid du Colombier place++;
291*9a747e4fSDavid du Colombier if (*place == ':') {
292*9a747e4fSDavid du Colombier if (optind < argc) {
293*9a747e4fSDavid du Colombier optarg = argv[optind];
294*9a747e4fSDavid du Colombier optind++;
295*9a747e4fSDavid du Colombier } else {
296*9a747e4fSDavid du Colombier fprintf(stderr, "%s: %c argument missing\n",
297*9a747e4fSDavid du Colombier argv[0], c);
298*9a747e4fSDavid du Colombier return ('?');
299*9a747e4fSDavid du Colombier }
300*9a747e4fSDavid du Colombier }
301*9a747e4fSDavid du Colombier return (c);
302*9a747e4fSDavid du Colombier }
303*9a747e4fSDavid du Colombier
304*9a747e4fSDavid du Colombier
305*9a747e4fSDavid du Colombier /* usage - print a helpful message and exit
306*9a747e4fSDavid du Colombier *
307*9a747e4fSDavid du Colombier * DESCRIPTION
308*9a747e4fSDavid du Colombier *
309*9a747e4fSDavid du Colombier * Usage prints out the usage message for the TAR interface and then
310*9a747e4fSDavid du Colombier * exits with a non-zero termination status. This is used when a user
311*9a747e4fSDavid du Colombier * has provided non-existant or incompatible command line arguments.
312*9a747e4fSDavid du Colombier *
313*9a747e4fSDavid du Colombier * RETURNS
314*9a747e4fSDavid du Colombier *
315*9a747e4fSDavid du Colombier * Returns an exit status of 1 to the parent process.
316*9a747e4fSDavid du Colombier *
317*9a747e4fSDavid du Colombier */
318*9a747e4fSDavid du Colombier
319*9a747e4fSDavid du Colombier #ifdef __STDC__
320*9a747e4fSDavid du Colombier
usage(void)321*9a747e4fSDavid du Colombier static void usage(void)
322*9a747e4fSDavid du Colombier
323*9a747e4fSDavid du Colombier #else
324*9a747e4fSDavid du Colombier
325*9a747e4fSDavid du Colombier static void usage()
326*9a747e4fSDavid du Colombier
327*9a747e4fSDavid du Colombier #endif
328*9a747e4fSDavid du Colombier {
329*9a747e4fSDavid du Colombier fprintf(stderr, "Usage: %s -c[bfvw] device block filename..\n", myname);
330*9a747e4fSDavid du Colombier fprintf(stderr, " %s -r[bvw] device block [filename...]\n", myname);
331*9a747e4fSDavid du Colombier fprintf(stderr, " %s -t[vf] device\n", myname);
332*9a747e4fSDavid du Colombier fprintf(stderr, " %s -u[bvw] device block [filename...]\n", myname);
333*9a747e4fSDavid du Colombier fprintf(stderr, " %s -x[flmovw] device [filename...]\n", myname);
334*9a747e4fSDavid du Colombier exit(1);
335*9a747e4fSDavid du Colombier }
336