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