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