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