|
|
1.1 root 1: /* $Source: /newbits/usr/bin/pax/shipping/RCS/pax.c,v $
2: *
3: * $Revision: 1.2 $
4: *
5: * DESCRIPTION
6: *
7: * Pax is the archiver described in IEEE P1003.2. It is an archiver
8: * which understands both tar and cpio archives and has a new interface.
9: *
10: * SYNOPSIS
11: *
12: * pax -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
13: * pax -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
14: * pax -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]...]
15: * [-t device][-x format][pathname...]
16: * pax -r -w [-ilmopuvy][-s replstr][pathname...] directory
17: *
18: * DESCRIPTION
19: *
20: * PAX - POSIX conforming tar and cpio archive handler. This
21: * program implements POSIX conformant versions of tar, cpio and pax
22: * archive handlers for UNIX. These handlers have defined befined
23: * by the IEEE P1003.2 commitee.
24: *
25: * COMPILATION
26: *
27: * A number of different compile time configuration options are
28: * available, please see the Makefile and config.h for more details.
29: *
30: * AUTHOR
31: *
32: * Mark H. Colburn, NAPS International ([email protected])
33: *
34: *
35: * Sponsored by The USENIX Association for public distribution.
36: *
37: * Copyright (c) 1989 Mark H. Colburn.
38: * All rights reserved.
39: *
40: * Redistribution and use in source and binary forms are permitted
41: * provided that the above copyright notice is duplicated in all such
42: * forms and that any documentation, advertising materials, and other
43: * materials related to such distribution and use acknowledge that the
44: * software was developed * by Mark H. Colburn and sponsored by The
45: * USENIX Association.
46: *
47: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
48: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
49: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
50: *
51: * $Log: pax.c,v $
52: * Revision 1.2 92/06/11 07:51:11 bin
53: * vlad: added recognition of ustar AND tar
54: *
55: * Revision 1.1 91/02/05 11:58:29 bin
56: * Initial revision
57: *
58: * Revision 1.2 89/02/12 10:05:17 mark
59: * 1.2 release fixes
60: *
61: * Revision 1.1 88/12/23 18:02:23 mark
62: * Initial revision
63: *
64: */
65:
66: #ifndef lint
67: static char *ident = "$Id: pax.c,v 1.2 92/06/11 07:51:11 bin Exp Locker: bin $";
68: static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
69: #endif /* ! lint */
70:
71:
72: /* Headers */
73:
74: #define NO_EXTERN
75: #include "pax.h"
76:
77:
78: /* Globally Available Identifiers */
79:
80: char *ar_file; /* File containing name of archive */
81: char *bufend; /* End of data within archive buffer */
82: char *bufstart; /* Archive buffer */
83: char *bufidx; /* Archive buffer index */
84: char *myname; /* name of executable (argv[0]) */
85: char **n_argv; /* Argv used by name routines */
86: int n_argc; /* Argc used by name routines */
87: int archivefd; /* Archive file descriptor */
88: int blocking; /* Size of each block, in records */
89: int gid; /* Group ID */
90: int head_standard; /* true if archive is POSIX format */
91: int ar_interface; /* defines interface we are using */
92: int ar_format; /* defines current archve format */
93: int mask; /* File creation mask */
94: int ttyf; /* For interactive queries */
95: int uid; /* User ID */
96: int names_from_stdin; /* names for files are from stdin */
97: OFFSET total; /* Total number of bytes transferred */
98: short f_access_time; /* Reset access times of input files */
99: short areof; /* End of input volume reached */
100: short f_dir_create; /* Create missing directories */
101: short f_append; /* Add named files to end of archive */
102: short f_create; /* create a new archive */
103: short f_extract; /* Extract named files from archive */
104: short f_follow_links; /* follow symbolic links */
105: short f_interactive; /* Interactivly extract files */
106: short f_linksleft; /* Report on unresolved links */
107: short f_list; /* List files on the archive */
108: short f_modified; /* Don't restore modification times */
109: short f_verbose; /* Turn on verbose mode */
110: short f_link; /* link files where possible */
111: short f_owner; /* extract files as the user */
112: short f_pass; /* pass files between directories */
113: short f_disposition; /* ask for file disposition */
114: short f_reverse_match; /* Reverse sense of pattern match */
115: short f_mtime; /* Retain file modification time */
116: short f_unconditional; /* Copy unconditionally */
117: time_t now = 0; /* Current time */
118: uint arvolume; /* Volume number */
119: uint blocksize = BLOCKSIZE; /* Archive block size */
120: FILE *msgfile; /* message outpu file stdout/stderr */
121: Replstr *rplhead = (Replstr *)NULL; /* head of replstr list */
122: Replstr *rpltail; /* pointer to tail of replstr list */
123:
124:
125: /* Function Prototypes */
126:
127: #if __STDC__
128:
129: static void usage(void);
130: static OFFSET pax_optsize(char *);
131:
132: #else /* !__STDC__ */
133:
134: static void usage();
135: static OFFSET pax_optsize();
136:
137: #endif /* __STDC__ */
138:
139:
140: /* main - main routine for handling all archive formats.
141: *
142: * DESCRIPTION
143: *
144: * Set up globals and call the proper interface as specified by the user.
145: *
146: * PARAMETERS
147: *
148: * int argc - count of user supplied arguments
149: * char **argv - user supplied arguments
150: *
151: * RETURNS
152: *
153: * Returns an exit code of 0 to the parent process.
154: */
155:
156: #if __STDC__
157:
158: int main(int argc, char **argv)
159:
160: #else
161:
162: int main(argc, argv)
163: int argc;
164: char **argv;
165:
166: #endif
167: {
168: /* strip the pathname off of the name of the executable */
169: if ((myname = strrchr(argv[0], '/')) != (char *)NULL) {
170: myname++;
171: } else {
172: myname = argv[0];
173: }
174:
175: /* set upt for collecting other command line arguments */
176: name_init(argc, argv);
177:
178: /* get all our necessary information */
179: mask = umask(0);
180: uid = getuid();
181: gid = getgid();
182: now = time((time_t *) 0);
183:
184: /* open terminal for interactive queries */
185: ttyf = open_tty();
186:
187: if (strcmp(myname, "ustar")==0 || strcmp(myname, "tar")==0) {
188: do_tar(argc, argv);
189: } else if (strcmp(myname, "cpio")==0) {
190: do_cpio(argc, argv);
191: } else {
192: do_pax(argc, argv);
193: }
194: exit(0);
195: /* NOTREACHED */
196: }
197:
198:
199: /* do_pax - provide a PAX conformant user interface for archive handling
200: *
201: * DESCRIPTION
202: *
203: * Process the command line parameters given, doing some minimal sanity
204: * checking, and then launch the specified archiving functions.
205: *
206: * PARAMETERS
207: *
208: * int ac - A count of arguments in av. Should be passed argc
209: * from main
210: * char **av - A pointer to an argument list. Should be passed
211: * argv from main
212: *
213: * RETURNS
214: *
215: * Normally returns 0. If an error occurs, -1 is returned
216: * and state is set to reflect the error.
217: *
218: */
219:
220: #if __STDC__
221:
222: int do_pax(int ac, char **av)
223:
224: #else
225:
226: int do_pax(ac, av)
227: int ac; /* argument counter */
228: char **av; /* arguments */
229:
230: #endif
231: {
232: int c;
233: char *dirname;
234: Stat st;
235:
236: /* default input/output file for PAX is STDIN/STDOUT */
237: ar_file = "-";
238:
239: /*
240: * set up the flags to reflect the default pax inteface. Unfortunately
241: * the pax interface has several options which are completely opposite
242: * of the ustar and/or cpio interfaces...
243: */
244: f_unconditional = 1;
245: f_mtime = 1;
246: f_dir_create = 1;
247: f_list = 1;
248: blocksize = 0;
249: blocking = 0;
250: ar_interface = PAX;
251: ar_format = TAR; /* default interface if none given for -w */
252: msgfile=stdout;
253:
254: while ((c = getopt(ac, av, "ab:cdf:ilmoprs:t:uvwx:y")) != EOF) {
255: switch (c) {
256: case 'a':
257: f_append = 1;
258: f_list = 0;
259: break;
260: case 'b':
261: if ((blocksize = pax_optsize(optarg)) == 0) {
262: fatal("Bad block size");
263: }
264: break;
265: case 'c':
266: f_reverse_match = 1;
267: break;
268: case 'd':
269: f_dir_create = 0;
270: break;
271: case 'f':
272: if (blocksize == 0) {
273: blocking = 1;
274: blocksize = 1 * BLOCKSIZE;
275: }
276: ar_file = optarg;
277: break;
278: case 'i':
279: f_interactive = 1;
280: break;
281: case 'l':
282: f_link = 1;
283: break;
284: case 'm':
285: f_mtime = 0;
286: break;
287: case 'o':
288: f_owner = 1;
289: break;
290: case 'p':
291: f_access_time = 1;
292: break;
293: case 'r':
294: if (f_create) {
295: f_create = 0;
296: f_pass = 1;
297: } else {
298: f_list = 0;
299: f_extract = 1;
300: }
301: msgfile=stderr;
302: break;
303: case 's':
304: add_replstr(optarg);
305: break;
306: case 't':
307: if (blocksize == 0) {
308: blocking = 1;
309: blocksize = 10 * BLOCKSIZE;
310: }
311: ar_file = optarg;
312: break;
313: case 'u':
314: f_unconditional = 1;
315: break;
316: case 'v':
317: f_verbose = 1;
318: break;
319: case 'w':
320: if (f_extract) {
321: f_extract = 0;
322: f_pass = 1;
323: } else {
324: f_list = 0;
325: f_create = 1;
326: }
327: msgfile=stderr;
328: break;
329: case 'x':
330: if (strcmp(optarg, "ustar") == 0) {
331: ar_format = TAR;
332: } else if (strcmp(optarg, "cpio") == 0) {
333: ar_format = CPIO;
334: } else {
335: usage();
336: }
337: break;
338: case 'y':
339: f_disposition = 1;
340: break;
341: default:
342: usage();
343: }
344: }
345:
346: if (blocksize == 0) {
347: blocking = 1;
348: blocksize = blocking * BLOCKSIZE;
349: }
350: buf_allocate((OFFSET) blocksize);
351:
352: if (f_extract || f_list) {
353: open_archive(AR_READ);
354: get_archive_type();
355: read_archive();
356: } else if (f_create) {
357: if (optind >= n_argc) {
358: names_from_stdin++; /* args from stdin */
359: }
360: open_archive(AR_WRITE);
361: create_archive();
362: } else if (f_append) {
363: open_archive(AR_APPEND);
364: get_archive_type();
365: append_archive();
366: } else if (f_pass && optind < n_argc) {
367: dirname = n_argv[--n_argc];
368: if (LSTAT(dirname, &st) < 0) {
369: fatal(strerror());
370: }
371: if ((st.sb_mode & S_IFMT) != S_IFDIR) {
372: fatal("Not a directory");
373: }
374: if (optind >= n_argc) {
375: names_from_stdin++; /* args from stdin */
376: }
377: pass(dirname);
378: } else {
379: usage();
380: }
381:
382: return (0);
383: }
384:
385:
386: /* get_archive_type - determine input archive type from archive header
387: *
388: * DESCRIPTION
389: *
390: * reads the first block of the archive and determines the archive
391: * type from the data. If the archive type cannot be determined,
392: * processing stops, and a 1 is returned to the caller. If verbose
393: * mode is on, then the archive type will be printed on the standard
394: * error device as it is determined.
395: *
396: * FIXME
397: *
398: * be able to understand TAR and CPIO magic numbers
399: */
400:
401: #if __STDC__
402:
403: void get_archive_type(void)
404:
405: #else
406:
407: void get_archive_type()
408:
409: #endif
410: {
411: if (ar_read() != 0) {
412: fatal("Unable to determine archive type.");
413: }
414: if (strncmp(bufstart, "070707", 6) == 0) {
415: ar_format = CPIO;
416: if (f_verbose) {
417: fputs("CPIO format archive\n", stderr);
418: }
419: } else if (strncmp(&bufstart[257], "ustar", 5) == 0) {
420: ar_format = TAR;
421: if (f_verbose) {
422: fputs("USTAR format archive\n", stderr);
423: }
424: } else {
425: ar_format = TAR;
426: if (f_verbose) {
427: fputs("TAR(v7) format archive\n", stderr);
428: }
429: }
430: }
431:
432:
433: /* pax_optsize - interpret a size argument
434: *
435: * DESCRIPTION
436: *
437: * Recognizes suffixes for blocks (512-bytes), k-bytes and megabytes.
438: * Also handles simple expressions containing '+' for addition.
439: *
440: * PARAMETERS
441: *
442: * char *str - A pointer to the string to interpret
443: *
444: * RETURNS
445: *
446: * Normally returns the value represented by the expression in the
447: * the string.
448: *
449: * ERRORS
450: *
451: * If the string cannot be interpretted, the program will fail, since
452: * the buffering will be incorrect.
453: *
454: */
455:
456: #if __STDC__
457:
458: static OFFSET pax_optsize(char *str)
459:
460: #else
461:
462: static OFFSET pax_optsize(str)
463: char *str; /* pointer to string to interpret */
464:
465: #endif
466: {
467: char *idx;
468: OFFSET number; /* temporary storage for current number */
469: OFFSET result; /* cumulative total to be returned to caller */
470:
471: result = 0;
472: idx = str;
473: for (;;) {
474: number = 0;
475: while (*idx >= '0' && *idx <= '9')
476: number = number * 10 + *idx++ - '0';
477: switch (*idx++) {
478: case 'b':
479: result += number * 512L;
480: continue;
481: case 'k':
482: result += number * 1024L;
483: continue;
484: case 'm':
485: result += number * 1024L * 1024L;
486: continue;
487: case '+':
488: result += number;
489: continue;
490: case '\0':
491: result += number;
492: break;
493: default:
494: break;
495: }
496: break;
497: }
498: if (*--idx) {
499: fatal("Unrecognizable value");
500: }
501: return (result);
502: }
503:
504:
505: /* usage - print a helpful message and exit
506: *
507: * DESCRIPTION
508: *
509: * Usage prints out the usage message for the PAX interface and then
510: * exits with a non-zero termination status. This is used when a user
511: * has provided non-existant or incompatible command line arguments.
512: *
513: * RETURNS
514: *
515: * Returns an exit status of 1 to the parent process.
516: *
517: */
518:
519: #if __STDC__
520:
521: static void usage(void)
522:
523: #else
524:
525: static void usage()
526:
527: #endif
528: {
529: fprintf(stderr, "Usage: %s -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
530: myname);
531: fprintf(stderr, " %s -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
532: myname);
533: fprintf(stderr, " %s -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]\n [-t device] [-x format] [pathname...]\n",
534: myname);
535: fprintf(stderr, " %s -r -w [-ilmopuvy] [-s replstr] [pathname...] directory\n",
536: myname);
537: exit(1);
538: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.