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