1*9a747e4fSDavid du Colombier /* $Source: /u/mark/src/pax/RCS/extract.c,v $
2*9a747e4fSDavid du Colombier *
3*9a747e4fSDavid du Colombier * $Revision: 1.3 $
4*9a747e4fSDavid du Colombier *
5*9a747e4fSDavid du Colombier * extract.c - Extract files from a tar archive.
6*9a747e4fSDavid du Colombier *
7*9a747e4fSDavid du Colombier * DESCRIPTION
8*9a747e4fSDavid du Colombier *
9*9a747e4fSDavid du Colombier * AUTHOR
10*9a747e4fSDavid du Colombier *
11*9a747e4fSDavid du Colombier * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
12*9a747e4fSDavid du Colombier *
13*9a747e4fSDavid du Colombier * Sponsored by The USENIX Association for public distribution.
14*9a747e4fSDavid du Colombier *
15*9a747e4fSDavid du Colombier * Copyright (c) 1989 Mark H. Colburn.
16*9a747e4fSDavid du Colombier * All rights reserved.
17*9a747e4fSDavid du Colombier *
18*9a747e4fSDavid du Colombier * Redistribution and use in source and binary forms are permitted
19*9a747e4fSDavid du Colombier * provided that the above copyright notice is duplicated in all such
20*9a747e4fSDavid du Colombier * forms and that any documentation, advertising materials, and other
21*9a747e4fSDavid du Colombier * materials related to such distribution and use acknowledge that the
22*9a747e4fSDavid du Colombier * software was developed * by Mark H. Colburn and sponsored by The
23*9a747e4fSDavid du Colombier * USENIX Association.
24*9a747e4fSDavid du Colombier *
25*9a747e4fSDavid du Colombier * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
26*9a747e4fSDavid du Colombier * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
27*9a747e4fSDavid du Colombier * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28*9a747e4fSDavid du Colombier *
29*9a747e4fSDavid du Colombier * $Log: extract.c,v $
30*9a747e4fSDavid du Colombier * Revision 1.3 89/02/12 10:29:43 mark
31*9a747e4fSDavid du Colombier * Fixed misspelling of Replstr
32*9a747e4fSDavid du Colombier *
33*9a747e4fSDavid du Colombier * Revision 1.2 89/02/12 10:04:24 mark
34*9a747e4fSDavid du Colombier * 1.2 release fixes
35*9a747e4fSDavid du Colombier *
36*9a747e4fSDavid du Colombier * Revision 1.1 88/12/23 18:02:07 mark
37*9a747e4fSDavid du Colombier * Initial revision
38*9a747e4fSDavid du Colombier *
39*9a747e4fSDavid du Colombier */
40*9a747e4fSDavid du Colombier
41*9a747e4fSDavid du Colombier #ifndef lint
42*9a747e4fSDavid du Colombier static char *ident = "$Id: extract.c,v 1.3 89/02/12 10:29:43 mark Exp Locker: mark $";
43*9a747e4fSDavid du Colombier static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
44*9a747e4fSDavid du Colombier #endif /* ! lint */
45*9a747e4fSDavid du Colombier
46*9a747e4fSDavid du Colombier
47*9a747e4fSDavid du Colombier /* Headers */
48*9a747e4fSDavid du Colombier
49*9a747e4fSDavid du Colombier #include "pax.h"
50*9a747e4fSDavid du Colombier
51*9a747e4fSDavid du Colombier
52*9a747e4fSDavid du Colombier /* Defines */
53*9a747e4fSDavid du Colombier
54*9a747e4fSDavid du Colombier /*
55*9a747e4fSDavid du Colombier * Swap bytes.
56*9a747e4fSDavid du Colombier */
57*9a747e4fSDavid du Colombier #define SWAB(n) ((((ushort)(n) >> 8) & 0xff) | (((ushort)(n) << 8) & 0xff00))
58*9a747e4fSDavid du Colombier
59*9a747e4fSDavid du Colombier
60*9a747e4fSDavid du Colombier /* Function Prototypes */
61*9a747e4fSDavid du Colombier
62*9a747e4fSDavid du Colombier #ifdef __STDC__
63*9a747e4fSDavid du Colombier
64*9a747e4fSDavid du Colombier static int inbinary(char *, char *, Stat *);
65*9a747e4fSDavid du Colombier static int inascii(char *, char *, Stat *);
66*9a747e4fSDavid du Colombier static int inswab(char *, char *, Stat *);
67*9a747e4fSDavid du Colombier static int readtar(char *, Stat *);
68*9a747e4fSDavid du Colombier static int readcpio(char *, Stat *);
69*9a747e4fSDavid du Colombier
70*9a747e4fSDavid du Colombier #else /* !__STDC__ */
71*9a747e4fSDavid du Colombier
72*9a747e4fSDavid du Colombier static int inbinary();
73*9a747e4fSDavid du Colombier static int inascii();
74*9a747e4fSDavid du Colombier static int inswab();
75*9a747e4fSDavid du Colombier static int readtar();
76*9a747e4fSDavid du Colombier static int readcpio();
77*9a747e4fSDavid du Colombier
78*9a747e4fSDavid du Colombier #endif /* __STDC__ */
79*9a747e4fSDavid du Colombier
80*9a747e4fSDavid du Colombier
81*9a747e4fSDavid du Colombier /* read_archive - read in an archive
82*9a747e4fSDavid du Colombier *
83*9a747e4fSDavid du Colombier * DESCRIPTION
84*9a747e4fSDavid du Colombier *
85*9a747e4fSDavid du Colombier * Read_archive is the central entry point for reading archives.
86*9a747e4fSDavid du Colombier * Read_archive determines the proper archive functions to call
87*9a747e4fSDavid du Colombier * based upon the archive type being processed.
88*9a747e4fSDavid du Colombier *
89*9a747e4fSDavid du Colombier * RETURNS
90*9a747e4fSDavid du Colombier *
91*9a747e4fSDavid du Colombier */
92*9a747e4fSDavid du Colombier
93*9a747e4fSDavid du Colombier #ifdef __STDC__
94*9a747e4fSDavid du Colombier
read_archive(void)95*9a747e4fSDavid du Colombier int read_archive(void)
96*9a747e4fSDavid du Colombier
97*9a747e4fSDavid du Colombier #else
98*9a747e4fSDavid du Colombier
99*9a747e4fSDavid du Colombier int read_archive()
100*9a747e4fSDavid du Colombier
101*9a747e4fSDavid du Colombier #endif
102*9a747e4fSDavid du Colombier {
103*9a747e4fSDavid du Colombier Stat sb;
104*9a747e4fSDavid du Colombier char name[PATH_MAX + 1];
105*9a747e4fSDavid du Colombier int match;
106*9a747e4fSDavid du Colombier int pad;
107*9a747e4fSDavid du Colombier
108*9a747e4fSDavid du Colombier name_gather(); /* get names from command line */
109*9a747e4fSDavid du Colombier name[0] = '\0';
110*9a747e4fSDavid du Colombier while (get_header(name, &sb) == 0) {
111*9a747e4fSDavid du Colombier match = name_match(name) ^ f_reverse_match;
112*9a747e4fSDavid du Colombier if (f_list) { /* only wanted a table of contents */
113*9a747e4fSDavid du Colombier if (match) {
114*9a747e4fSDavid du Colombier print_entry(name, &sb);
115*9a747e4fSDavid du Colombier }
116*9a747e4fSDavid du Colombier if (((ar_format == TAR)
117*9a747e4fSDavid du Colombier ? buf_skip(ROUNDUP((OFFSET) sb.sb_size, BLOCKSIZE))
118*9a747e4fSDavid du Colombier : buf_skip((OFFSET) sb.sb_size)) < 0) {
119*9a747e4fSDavid du Colombier warn(name, "File data is corrupt");
120*9a747e4fSDavid du Colombier }
121*9a747e4fSDavid du Colombier } else if (match) {
122*9a747e4fSDavid du Colombier if (rplhead != (Replstr *)NULL) {
123*9a747e4fSDavid du Colombier rpl_name(name);
124*9a747e4fSDavid du Colombier if (strlen(name) == 0) {
125*9a747e4fSDavid du Colombier continue;
126*9a747e4fSDavid du Colombier }
127*9a747e4fSDavid du Colombier }
128*9a747e4fSDavid du Colombier if (get_disposition("extract", name) ||
129*9a747e4fSDavid du Colombier get_newname(name, sizeof(name))) {
130*9a747e4fSDavid du Colombier /* skip file... */
131*9a747e4fSDavid du Colombier if (((ar_format == TAR)
132*9a747e4fSDavid du Colombier ? buf_skip(ROUNDUP((OFFSET) sb.sb_size, BLOCKSIZE))
133*9a747e4fSDavid du Colombier : buf_skip((OFFSET) sb.sb_size)) < 0) {
134*9a747e4fSDavid du Colombier warn(name, "File data is corrupt");
135*9a747e4fSDavid du Colombier }
136*9a747e4fSDavid du Colombier continue;
137*9a747e4fSDavid du Colombier }
138*9a747e4fSDavid du Colombier if (inentry(name, &sb) < 0) {
139*9a747e4fSDavid du Colombier warn(name, "File data is corrupt");
140*9a747e4fSDavid du Colombier }
141*9a747e4fSDavid du Colombier if (f_verbose) {
142*9a747e4fSDavid du Colombier print_entry(name, &sb);
143*9a747e4fSDavid du Colombier }
144*9a747e4fSDavid du Colombier if (ar_format == TAR && sb.sb_nlink > 1) {
145*9a747e4fSDavid du Colombier /*
146*9a747e4fSDavid du Colombier * This kludge makes sure that the link table is cleared
147*9a747e4fSDavid du Colombier * before attempting to process any other links.
148*9a747e4fSDavid du Colombier */
149*9a747e4fSDavid du Colombier if (sb.sb_nlink > 1) {
150*9a747e4fSDavid du Colombier linkfrom(name, &sb);
151*9a747e4fSDavid du Colombier }
152*9a747e4fSDavid du Colombier }
153*9a747e4fSDavid du Colombier if (ar_format == TAR && (pad = sb.sb_size % BLOCKSIZE) != 0) {
154*9a747e4fSDavid du Colombier pad = BLOCKSIZE - pad;
155*9a747e4fSDavid du Colombier buf_skip((OFFSET) pad);
156*9a747e4fSDavid du Colombier }
157*9a747e4fSDavid du Colombier } else {
158*9a747e4fSDavid du Colombier if (((ar_format == TAR)
159*9a747e4fSDavid du Colombier ? buf_skip(ROUNDUP((OFFSET) sb.sb_size, BLOCKSIZE))
160*9a747e4fSDavid du Colombier : buf_skip((OFFSET) sb.sb_size)) < 0) {
161*9a747e4fSDavid du Colombier warn(name, "File data is corrupt");
162*9a747e4fSDavid du Colombier }
163*9a747e4fSDavid du Colombier }
164*9a747e4fSDavid du Colombier }
165*9a747e4fSDavid du Colombier
166*9a747e4fSDavid du Colombier close_archive();
167*9a747e4fSDavid du Colombier }
168*9a747e4fSDavid du Colombier
169*9a747e4fSDavid du Colombier
170*9a747e4fSDavid du Colombier
171*9a747e4fSDavid du Colombier /* get_header - figures which type of header needs to be read.
172*9a747e4fSDavid du Colombier *
173*9a747e4fSDavid du Colombier * DESCRIPTION
174*9a747e4fSDavid du Colombier *
175*9a747e4fSDavid du Colombier * This is merely a single entry point for the two types of archive
176*9a747e4fSDavid du Colombier * headers which are supported. The correct header is selected
177*9a747e4fSDavid du Colombier * depending on the archive type.
178*9a747e4fSDavid du Colombier *
179*9a747e4fSDavid du Colombier * PARAMETERS
180*9a747e4fSDavid du Colombier *
181*9a747e4fSDavid du Colombier * char *name - name of the file (passed to header routine)
182*9a747e4fSDavid du Colombier * Stat *asb - Stat block for the file (passed to header routine)
183*9a747e4fSDavid du Colombier *
184*9a747e4fSDavid du Colombier * RETURNS
185*9a747e4fSDavid du Colombier *
186*9a747e4fSDavid du Colombier * Returns the value which was returned by the proper header
187*9a747e4fSDavid du Colombier * function.
188*9a747e4fSDavid du Colombier */
189*9a747e4fSDavid du Colombier
190*9a747e4fSDavid du Colombier #ifdef __STDC__
191*9a747e4fSDavid du Colombier
get_header(char * name,Stat * asb)192*9a747e4fSDavid du Colombier int get_header(char *name, Stat *asb)
193*9a747e4fSDavid du Colombier
194*9a747e4fSDavid du Colombier #else
195*9a747e4fSDavid du Colombier
196*9a747e4fSDavid du Colombier int get_header(name, asb)
197*9a747e4fSDavid du Colombier char *name;
198*9a747e4fSDavid du Colombier Stat *asb;
199*9a747e4fSDavid du Colombier
200*9a747e4fSDavid du Colombier #endif
201*9a747e4fSDavid du Colombier {
202*9a747e4fSDavid du Colombier if (ar_format == TAR) {
203*9a747e4fSDavid du Colombier return(readtar(name, asb));
204*9a747e4fSDavid du Colombier } else {
205*9a747e4fSDavid du Colombier return(readcpio(name, asb));
206*9a747e4fSDavid du Colombier }
207*9a747e4fSDavid du Colombier }
208*9a747e4fSDavid du Colombier
209*9a747e4fSDavid du Colombier
210*9a747e4fSDavid du Colombier /* readtar - read a tar header
211*9a747e4fSDavid du Colombier *
212*9a747e4fSDavid du Colombier * DESCRIPTION
213*9a747e4fSDavid du Colombier *
214*9a747e4fSDavid du Colombier * Tar_head read a tar format header from the archive. The name
215*9a747e4fSDavid du Colombier * and asb parameters are modified as appropriate for the file listed
216*9a747e4fSDavid du Colombier * in the header. Name is assumed to be a pointer to an array of
217*9a747e4fSDavid du Colombier * at least PATH_MAX bytes.
218*9a747e4fSDavid du Colombier *
219*9a747e4fSDavid du Colombier * PARAMETERS
220*9a747e4fSDavid du Colombier *
221*9a747e4fSDavid du Colombier * char *name - name of the file for which the header is
222*9a747e4fSDavid du Colombier * for. This is modified and passed back to
223*9a747e4fSDavid du Colombier * the caller.
224*9a747e4fSDavid du Colombier * Stat *asb - Stat block for the file for which the header
225*9a747e4fSDavid du Colombier * is for. The fields of the stat structure are
226*9a747e4fSDavid du Colombier * extracted from the archive header. This is
227*9a747e4fSDavid du Colombier * also passed back to the caller.
228*9a747e4fSDavid du Colombier *
229*9a747e4fSDavid du Colombier * RETURNS
230*9a747e4fSDavid du Colombier *
231*9a747e4fSDavid du Colombier * Returns 0 if a valid header was found, or -1 if EOF is
232*9a747e4fSDavid du Colombier * encountered.
233*9a747e4fSDavid du Colombier */
234*9a747e4fSDavid du Colombier
235*9a747e4fSDavid du Colombier #ifdef __STDC__
236*9a747e4fSDavid du Colombier
readtar(char * name,Stat * asb)237*9a747e4fSDavid du Colombier static int readtar(char *name, Stat *asb)
238*9a747e4fSDavid du Colombier
239*9a747e4fSDavid du Colombier #else
240*9a747e4fSDavid du Colombier
241*9a747e4fSDavid du Colombier static int readtar(name, asb)
242*9a747e4fSDavid du Colombier char *name;
243*9a747e4fSDavid du Colombier Stat *asb;
244*9a747e4fSDavid du Colombier
245*9a747e4fSDavid du Colombier #endif
246*9a747e4fSDavid du Colombier {
247*9a747e4fSDavid du Colombier int status = 3; /* Initial status at start of archive */
248*9a747e4fSDavid du Colombier static int prev_status;
249*9a747e4fSDavid du Colombier
250*9a747e4fSDavid du Colombier for (;;) {
251*9a747e4fSDavid du Colombier prev_status = status;
252*9a747e4fSDavid du Colombier status = read_header(name, asb);
253*9a747e4fSDavid du Colombier switch (status) {
254*9a747e4fSDavid du Colombier case 1: /* Valid header */
255*9a747e4fSDavid du Colombier return(0);
256*9a747e4fSDavid du Colombier case 0: /* Invalid header */
257*9a747e4fSDavid du Colombier switch (prev_status) {
258*9a747e4fSDavid du Colombier case 3: /* Error on first record */
259*9a747e4fSDavid du Colombier warn(ar_file, "This doesn't look like a tar archive");
260*9a747e4fSDavid du Colombier /* FALLTHRU */
261*9a747e4fSDavid du Colombier case 2: /* Error after record of zeroes */
262*9a747e4fSDavid du Colombier case 1: /* Error after header rec */
263*9a747e4fSDavid du Colombier warn(ar_file, "Skipping to next file...");
264*9a747e4fSDavid du Colombier /* FALLTHRU */
265*9a747e4fSDavid du Colombier default:
266*9a747e4fSDavid du Colombier case 0: /* Error after error */
267*9a747e4fSDavid du Colombier break;
268*9a747e4fSDavid du Colombier }
269*9a747e4fSDavid du Colombier break;
270*9a747e4fSDavid du Colombier
271*9a747e4fSDavid du Colombier case 2: /* Record of zeroes */
272*9a747e4fSDavid du Colombier case EOF: /* End of archive */
273*9a747e4fSDavid du Colombier default:
274*9a747e4fSDavid du Colombier return(-1);
275*9a747e4fSDavid du Colombier }
276*9a747e4fSDavid du Colombier }
277*9a747e4fSDavid du Colombier }
278*9a747e4fSDavid du Colombier
279*9a747e4fSDavid du Colombier
280*9a747e4fSDavid du Colombier /* readcpio - read a CPIO header
281*9a747e4fSDavid du Colombier *
282*9a747e4fSDavid du Colombier * DESCRIPTION
283*9a747e4fSDavid du Colombier *
284*9a747e4fSDavid du Colombier * Read in a cpio header. Understands how to determine and read ASCII,
285*9a747e4fSDavid du Colombier * binary and byte-swapped binary headers. Quietly translates
286*9a747e4fSDavid du Colombier * old-fashioned binary cpio headers (and arranges to skip the possible
287*9a747e4fSDavid du Colombier * alignment byte). Returns zero if successful, -1 upon archive trailer.
288*9a747e4fSDavid du Colombier *
289*9a747e4fSDavid du Colombier * PARAMETERS
290*9a747e4fSDavid du Colombier *
291*9a747e4fSDavid du Colombier * char *name - name of the file for which the header is
292*9a747e4fSDavid du Colombier * for. This is modified and passed back to
293*9a747e4fSDavid du Colombier * the caller.
294*9a747e4fSDavid du Colombier * Stat *asb - Stat block for the file for which the header
295*9a747e4fSDavid du Colombier * is for. The fields of the stat structure are
296*9a747e4fSDavid du Colombier * extracted from the archive header. This is
297*9a747e4fSDavid du Colombier * also passed back to the caller.
298*9a747e4fSDavid du Colombier *
299*9a747e4fSDavid du Colombier * RETURNS
300*9a747e4fSDavid du Colombier *
301*9a747e4fSDavid du Colombier * Returns 0 if a valid header was found, or -1 if EOF is
302*9a747e4fSDavid du Colombier * encountered.
303*9a747e4fSDavid du Colombier */
304*9a747e4fSDavid du Colombier
305*9a747e4fSDavid du Colombier #ifdef __STDC__
306*9a747e4fSDavid du Colombier
readcpio(char * name,Stat * asb)307*9a747e4fSDavid du Colombier static int readcpio(char *name, Stat *asb)
308*9a747e4fSDavid du Colombier
309*9a747e4fSDavid du Colombier #else
310*9a747e4fSDavid du Colombier
311*9a747e4fSDavid du Colombier static int readcpio(name, asb)
312*9a747e4fSDavid du Colombier char *name;
313*9a747e4fSDavid du Colombier Stat *asb;
314*9a747e4fSDavid du Colombier
315*9a747e4fSDavid du Colombier #endif
316*9a747e4fSDavid du Colombier {
317*9a747e4fSDavid du Colombier OFFSET skipped;
318*9a747e4fSDavid du Colombier char magic[M_STRLEN];
319*9a747e4fSDavid du Colombier static int align;
320*9a747e4fSDavid du Colombier
321*9a747e4fSDavid du Colombier if (align > 0) {
322*9a747e4fSDavid du Colombier buf_skip((OFFSET) align);
323*9a747e4fSDavid du Colombier }
324*9a747e4fSDavid du Colombier align = 0;
325*9a747e4fSDavid du Colombier for (;;) {
326*9a747e4fSDavid du Colombier buf_read(magic, M_STRLEN);
327*9a747e4fSDavid du Colombier skipped = 0;
328*9a747e4fSDavid du Colombier while ((align = inascii(magic, name, asb)) < 0
329*9a747e4fSDavid du Colombier && (align = inbinary(magic, name, asb)) < 0
330*9a747e4fSDavid du Colombier && (align = inswab(magic, name, asb)) < 0) {
331*9a747e4fSDavid du Colombier if (++skipped == 1) {
332*9a747e4fSDavid du Colombier if (total - sizeof(magic) == 0) {
333*9a747e4fSDavid du Colombier fatal("Unrecognizable archive");
334*9a747e4fSDavid du Colombier }
335*9a747e4fSDavid du Colombier warnarch("Bad magic number", (OFFSET) sizeof(magic));
336*9a747e4fSDavid du Colombier if (name[0]) {
337*9a747e4fSDavid du Colombier warn(name, "May be corrupt");
338*9a747e4fSDavid du Colombier }
339*9a747e4fSDavid du Colombier }
340*9a747e4fSDavid du Colombier memcpy(magic, magic + 1, sizeof(magic) - 1);
341*9a747e4fSDavid du Colombier buf_read(magic + sizeof(magic) - 1, 1);
342*9a747e4fSDavid du Colombier }
343*9a747e4fSDavid du Colombier if (skipped) {
344*9a747e4fSDavid du Colombier warnarch("Apparently resynchronized", (OFFSET) sizeof(magic));
345*9a747e4fSDavid du Colombier warn(name, "Continuing");
346*9a747e4fSDavid du Colombier }
347*9a747e4fSDavid du Colombier if (strcmp(name, TRAILER) == 0) {
348*9a747e4fSDavid du Colombier return (-1);
349*9a747e4fSDavid du Colombier }
350*9a747e4fSDavid du Colombier if (nameopt(name) >= 0) {
351*9a747e4fSDavid du Colombier break;
352*9a747e4fSDavid du Colombier }
353*9a747e4fSDavid du Colombier buf_skip((OFFSET) asb->sb_size + align);
354*9a747e4fSDavid du Colombier }
355*9a747e4fSDavid du Colombier #ifdef S_IFLNK
356*9a747e4fSDavid du Colombier if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
357*9a747e4fSDavid du Colombier if (buf_read(asb->sb_link, (uint) asb->sb_size) < 0) {
358*9a747e4fSDavid du Colombier warn(name, "Corrupt symbolic link");
359*9a747e4fSDavid du Colombier return (readcpio(name, asb));
360*9a747e4fSDavid du Colombier }
361*9a747e4fSDavid du Colombier asb->sb_link[asb->sb_size] = '\0';
362*9a747e4fSDavid du Colombier asb->sb_size = 0;
363*9a747e4fSDavid du Colombier }
364*9a747e4fSDavid du Colombier #endif /* S_IFLNK */
365*9a747e4fSDavid du Colombier
366*9a747e4fSDavid du Colombier /* destroy absolute pathnames for security reasons */
367*9a747e4fSDavid du Colombier if (name[0] == '/') {
368*9a747e4fSDavid du Colombier if (name[1]) {
369*9a747e4fSDavid du Colombier while (name[0] = name[1]) {
370*9a747e4fSDavid du Colombier ++name;
371*9a747e4fSDavid du Colombier }
372*9a747e4fSDavid du Colombier } else {
373*9a747e4fSDavid du Colombier name[0] = '.';
374*9a747e4fSDavid du Colombier }
375*9a747e4fSDavid du Colombier }
376*9a747e4fSDavid du Colombier asb->sb_atime = asb->sb_ctime = asb->sb_mtime;
377*9a747e4fSDavid du Colombier if (asb->sb_nlink > 1) {
378*9a747e4fSDavid du Colombier linkto(name, asb);
379*9a747e4fSDavid du Colombier }
380*9a747e4fSDavid du Colombier return (0);
381*9a747e4fSDavid du Colombier }
382*9a747e4fSDavid du Colombier
383*9a747e4fSDavid du Colombier
384*9a747e4fSDavid du Colombier /* inswab - read a reversed by order binary header
385*9a747e4fSDavid du Colombier *
386*9a747e4fSDavid du Colombier * DESCRIPTIONS
387*9a747e4fSDavid du Colombier *
388*9a747e4fSDavid du Colombier * Reads a byte-swapped CPIO binary archive header
389*9a747e4fSDavid du Colombier *
390*9a747e4fSDavid du Colombier * PARMAMETERS
391*9a747e4fSDavid du Colombier *
392*9a747e4fSDavid du Colombier * char *magic - magic number to match
393*9a747e4fSDavid du Colombier * char *name - name of the file which is stored in the header.
394*9a747e4fSDavid du Colombier * (modified and passed back to caller).
395*9a747e4fSDavid du Colombier * Stat *asb - stat block for the file (modified and passed back
396*9a747e4fSDavid du Colombier * to the caller).
397*9a747e4fSDavid du Colombier *
398*9a747e4fSDavid du Colombier *
399*9a747e4fSDavid du Colombier * RETURNS
400*9a747e4fSDavid du Colombier *
401*9a747e4fSDavid du Colombier * Returns the number of trailing alignment bytes to skip; -1 if
402*9a747e4fSDavid du Colombier * unsuccessful.
403*9a747e4fSDavid du Colombier *
404*9a747e4fSDavid du Colombier */
405*9a747e4fSDavid du Colombier
406*9a747e4fSDavid du Colombier #ifdef __STDC__
407*9a747e4fSDavid du Colombier
inswab(char * magic,char * name,Stat * asb)408*9a747e4fSDavid du Colombier static int inswab(char *magic, char *name, Stat *asb)
409*9a747e4fSDavid du Colombier
410*9a747e4fSDavid du Colombier #else
411*9a747e4fSDavid du Colombier
412*9a747e4fSDavid du Colombier static int inswab(magic, name, asb)
413*9a747e4fSDavid du Colombier char *magic;
414*9a747e4fSDavid du Colombier char *name;
415*9a747e4fSDavid du Colombier Stat *asb;
416*9a747e4fSDavid du Colombier
417*9a747e4fSDavid du Colombier #endif
418*9a747e4fSDavid du Colombier {
419*9a747e4fSDavid du Colombier ushort namesize;
420*9a747e4fSDavid du Colombier uint namefull;
421*9a747e4fSDavid du Colombier Binary binary;
422*9a747e4fSDavid du Colombier
423*9a747e4fSDavid du Colombier if (*((ushort *) magic) != SWAB(M_BINARY)) {
424*9a747e4fSDavid du Colombier return (-1);
425*9a747e4fSDavid du Colombier }
426*9a747e4fSDavid du Colombier memcpy((char *) &binary,
427*9a747e4fSDavid du Colombier magic + sizeof(ushort),
428*9a747e4fSDavid du Colombier M_STRLEN - sizeof(ushort));
429*9a747e4fSDavid du Colombier if (buf_read((char *) &binary + M_STRLEN - sizeof(ushort),
430*9a747e4fSDavid du Colombier sizeof(binary) - (M_STRLEN - sizeof(ushort))) < 0) {
431*9a747e4fSDavid du Colombier warnarch("Corrupt swapped header",
432*9a747e4fSDavid du Colombier (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
433*9a747e4fSDavid du Colombier return (-1);
434*9a747e4fSDavid du Colombier }
435*9a747e4fSDavid du Colombier asb->sb_dev = (dev_t) SWAB(binary.b_dev);
436*9a747e4fSDavid du Colombier asb->sb_ino = (ino_t) SWAB(binary.b_ino);
437*9a747e4fSDavid du Colombier asb->sb_mode = SWAB(binary.b_mode);
438*9a747e4fSDavid du Colombier asb->sb_uid = SWAB(binary.b_uid);
439*9a747e4fSDavid du Colombier asb->sb_gid = SWAB(binary.b_gid);
440*9a747e4fSDavid du Colombier asb->sb_nlink = SWAB(binary.b_nlink);
441*9a747e4fSDavid du Colombier #ifndef _POSIX_SOURCE
442*9a747e4fSDavid du Colombier asb->sb_rdev = (dev_t) SWAB(binary.b_rdev);
443*9a747e4fSDavid du Colombier #endif
444*9a747e4fSDavid du Colombier asb->sb_mtime = SWAB(binary.b_mtime[0]) << 16 | SWAB(binary.b_mtime[1]);
445*9a747e4fSDavid du Colombier asb->sb_size = SWAB(binary.b_size[0]) << 16 | SWAB(binary.b_size[1]);
446*9a747e4fSDavid du Colombier if ((namesize = SWAB(binary.b_name)) == 0 || namesize >= PATH_MAX) {
447*9a747e4fSDavid du Colombier warnarch("Bad swapped pathname length",
448*9a747e4fSDavid du Colombier (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
449*9a747e4fSDavid du Colombier return (-1);
450*9a747e4fSDavid du Colombier }
451*9a747e4fSDavid du Colombier if (buf_read(name, namefull = namesize + namesize % 2) < 0) {
452*9a747e4fSDavid du Colombier warnarch("Corrupt swapped pathname", (OFFSET) namefull);
453*9a747e4fSDavid du Colombier return (-1);
454*9a747e4fSDavid du Colombier }
455*9a747e4fSDavid du Colombier if (name[namesize - 1] != '\0') {
456*9a747e4fSDavid du Colombier warnarch("Bad swapped pathname", (OFFSET) namefull);
457*9a747e4fSDavid du Colombier return (-1);
458*9a747e4fSDavid du Colombier }
459*9a747e4fSDavid du Colombier return (asb->sb_size % 2);
460*9a747e4fSDavid du Colombier }
461*9a747e4fSDavid du Colombier
462*9a747e4fSDavid du Colombier
463*9a747e4fSDavid du Colombier /* inascii - read in an ASCII cpio header
464*9a747e4fSDavid du Colombier *
465*9a747e4fSDavid du Colombier * DESCRIPTION
466*9a747e4fSDavid du Colombier *
467*9a747e4fSDavid du Colombier * Reads an ASCII format cpio header
468*9a747e4fSDavid du Colombier *
469*9a747e4fSDavid du Colombier * PARAMETERS
470*9a747e4fSDavid du Colombier *
471*9a747e4fSDavid du Colombier * char *magic - magic number to match
472*9a747e4fSDavid du Colombier * char *name - name of the file which is stored in the header.
473*9a747e4fSDavid du Colombier * (modified and passed back to caller).
474*9a747e4fSDavid du Colombier * Stat *asb - stat block for the file (modified and passed back
475*9a747e4fSDavid du Colombier * to the caller).
476*9a747e4fSDavid du Colombier *
477*9a747e4fSDavid du Colombier * RETURNS
478*9a747e4fSDavid du Colombier *
479*9a747e4fSDavid du Colombier * Returns zero if successful; -1 otherwise. Assumes that the entire
480*9a747e4fSDavid du Colombier * magic number has been read.
481*9a747e4fSDavid du Colombier */
482*9a747e4fSDavid du Colombier
483*9a747e4fSDavid du Colombier #ifdef __STDC__
484*9a747e4fSDavid du Colombier
inascii(char * magic,char * name,Stat * asb)485*9a747e4fSDavid du Colombier static int inascii(char *magic, char *name, Stat *asb)
486*9a747e4fSDavid du Colombier
487*9a747e4fSDavid du Colombier #else
488*9a747e4fSDavid du Colombier
489*9a747e4fSDavid du Colombier static int inascii(magic, name, asb)
490*9a747e4fSDavid du Colombier char *magic;
491*9a747e4fSDavid du Colombier char *name;
492*9a747e4fSDavid du Colombier Stat *asb;
493*9a747e4fSDavid du Colombier
494*9a747e4fSDavid du Colombier #endif
495*9a747e4fSDavid du Colombier {
496*9a747e4fSDavid du Colombier uint namelen;
497*9a747e4fSDavid du Colombier char header[H_STRLEN + 1];
498*9a747e4fSDavid du Colombier #ifdef _POSIX_SOURCE
499*9a747e4fSDavid du Colombier dev_t dummyrdev;
500*9a747e4fSDavid du Colombier #endif
501*9a747e4fSDavid du Colombier
502*9a747e4fSDavid du Colombier if (strncmp(magic, M_ASCII, M_STRLEN) != 0) {
503*9a747e4fSDavid du Colombier return (-1);
504*9a747e4fSDavid du Colombier }
505*9a747e4fSDavid du Colombier if (buf_read(header, H_STRLEN) < 0) {
506*9a747e4fSDavid du Colombier warnarch("Corrupt ASCII header", (OFFSET) H_STRLEN);
507*9a747e4fSDavid du Colombier return (-1);
508*9a747e4fSDavid du Colombier }
509*9a747e4fSDavid du Colombier header[H_STRLEN] = '\0';
510*9a747e4fSDavid du Colombier if (sscanf(header, H_SCAN, &asb->sb_dev,
511*9a747e4fSDavid du Colombier &asb->sb_ino, &asb->sb_mode, &asb->sb_uid,
512*9a747e4fSDavid du Colombier #ifdef _POSIX_SOURCE
513*9a747e4fSDavid du Colombier &asb->sb_gid, &asb->sb_nlink, &dummyrdev,
514*9a747e4fSDavid du Colombier #else
515*9a747e4fSDavid du Colombier &asb->sb_gid, &asb->sb_nlink, &asb->sb_rdev,
516*9a747e4fSDavid du Colombier #endif
517*9a747e4fSDavid du Colombier &asb->sb_mtime, &namelen, &asb->sb_size) != H_COUNT) {
518*9a747e4fSDavid du Colombier warnarch("Bad ASCII header", (OFFSET) H_STRLEN);
519*9a747e4fSDavid du Colombier return (-1);
520*9a747e4fSDavid du Colombier }
521*9a747e4fSDavid du Colombier if (namelen == 0 || namelen >= PATH_MAX) {
522*9a747e4fSDavid du Colombier warnarch("Bad ASCII pathname length", (OFFSET) H_STRLEN);
523*9a747e4fSDavid du Colombier return (-1);
524*9a747e4fSDavid du Colombier }
525*9a747e4fSDavid du Colombier if (buf_read(name, namelen) < 0) {
526*9a747e4fSDavid du Colombier warnarch("Corrupt ASCII pathname", (OFFSET) namelen);
527*9a747e4fSDavid du Colombier return (-1);
528*9a747e4fSDavid du Colombier }
529*9a747e4fSDavid du Colombier if (name[namelen - 1] != '\0') {
530*9a747e4fSDavid du Colombier warnarch("Bad ASCII pathname", (OFFSET) namelen);
531*9a747e4fSDavid du Colombier return (-1);
532*9a747e4fSDavid du Colombier }
533*9a747e4fSDavid du Colombier return (0);
534*9a747e4fSDavid du Colombier }
535*9a747e4fSDavid du Colombier
536*9a747e4fSDavid du Colombier
537*9a747e4fSDavid du Colombier /* inbinary - read a binary header
538*9a747e4fSDavid du Colombier *
539*9a747e4fSDavid du Colombier * DESCRIPTION
540*9a747e4fSDavid du Colombier *
541*9a747e4fSDavid du Colombier * Reads a CPIO format binary header.
542*9a747e4fSDavid du Colombier *
543*9a747e4fSDavid du Colombier * PARAMETERS
544*9a747e4fSDavid du Colombier *
545*9a747e4fSDavid du Colombier * char *magic - magic number to match
546*9a747e4fSDavid du Colombier * char *name - name of the file which is stored in the header.
547*9a747e4fSDavid du Colombier * (modified and passed back to caller).
548*9a747e4fSDavid du Colombier * Stat *asb - stat block for the file (modified and passed back
549*9a747e4fSDavid du Colombier * to the caller).
550*9a747e4fSDavid du Colombier *
551*9a747e4fSDavid du Colombier * RETURNS
552*9a747e4fSDavid du Colombier *
553*9a747e4fSDavid du Colombier * Returns the number of trailing alignment bytes to skip; -1 if
554*9a747e4fSDavid du Colombier * unsuccessful.
555*9a747e4fSDavid du Colombier */
556*9a747e4fSDavid du Colombier
557*9a747e4fSDavid du Colombier #ifdef __STDC__
558*9a747e4fSDavid du Colombier
inbinary(char * magic,char * name,Stat * asb)559*9a747e4fSDavid du Colombier static int inbinary(char *magic, char *name, Stat *asb)
560*9a747e4fSDavid du Colombier
561*9a747e4fSDavid du Colombier #else
562*9a747e4fSDavid du Colombier
563*9a747e4fSDavid du Colombier static int inbinary(magic, name, asb)
564*9a747e4fSDavid du Colombier char *magic;
565*9a747e4fSDavid du Colombier char *name;
566*9a747e4fSDavid du Colombier Stat *asb;
567*9a747e4fSDavid du Colombier
568*9a747e4fSDavid du Colombier #endif
569*9a747e4fSDavid du Colombier {
570*9a747e4fSDavid du Colombier uint namefull;
571*9a747e4fSDavid du Colombier Binary binary;
572*9a747e4fSDavid du Colombier
573*9a747e4fSDavid du Colombier if (*((ushort *) magic) != M_BINARY) {
574*9a747e4fSDavid du Colombier return (-1);
575*9a747e4fSDavid du Colombier }
576*9a747e4fSDavid du Colombier memcpy((char *) &binary,
577*9a747e4fSDavid du Colombier magic + sizeof(ushort),
578*9a747e4fSDavid du Colombier M_STRLEN - sizeof(ushort));
579*9a747e4fSDavid du Colombier if (buf_read((char *) &binary + M_STRLEN - sizeof(ushort),
580*9a747e4fSDavid du Colombier sizeof(binary) - (M_STRLEN - sizeof(ushort))) < 0) {
581*9a747e4fSDavid du Colombier warnarch("Corrupt binary header",
582*9a747e4fSDavid du Colombier (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
583*9a747e4fSDavid du Colombier return (-1);
584*9a747e4fSDavid du Colombier }
585*9a747e4fSDavid du Colombier asb->sb_dev = binary.b_dev;
586*9a747e4fSDavid du Colombier asb->sb_ino = binary.b_ino;
587*9a747e4fSDavid du Colombier asb->sb_mode = binary.b_mode;
588*9a747e4fSDavid du Colombier asb->sb_uid = binary.b_uid;
589*9a747e4fSDavid du Colombier asb->sb_gid = binary.b_gid;
590*9a747e4fSDavid du Colombier asb->sb_nlink = binary.b_nlink;
591*9a747e4fSDavid du Colombier #ifndef _POSIX_SOURCE
592*9a747e4fSDavid du Colombier asb->sb_rdev = binary.b_rdev;
593*9a747e4fSDavid du Colombier #endif
594*9a747e4fSDavid du Colombier asb->sb_mtime = binary.b_mtime[0] << 16 | binary.b_mtime[1];
595*9a747e4fSDavid du Colombier asb->sb_size = binary.b_size[0] << 16 | binary.b_size[1];
596*9a747e4fSDavid du Colombier if (binary.b_name == 0 || binary.b_name >= PATH_MAX) {
597*9a747e4fSDavid du Colombier warnarch("Bad binary pathname length",
598*9a747e4fSDavid du Colombier (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
599*9a747e4fSDavid du Colombier return (-1);
600*9a747e4fSDavid du Colombier }
601*9a747e4fSDavid du Colombier if (buf_read(name, namefull = binary.b_name + binary.b_name % 2) < 0) {
602*9a747e4fSDavid du Colombier warnarch("Corrupt binary pathname", (OFFSET) namefull);
603*9a747e4fSDavid du Colombier return (-1);
604*9a747e4fSDavid du Colombier }
605*9a747e4fSDavid du Colombier if (name[binary.b_name - 1] != '\0') {
606*9a747e4fSDavid du Colombier warnarch("Bad binary pathname", (OFFSET) namefull);
607*9a747e4fSDavid du Colombier return (-1);
608*9a747e4fSDavid du Colombier }
609*9a747e4fSDavid du Colombier return (asb->sb_size % 2);
610*9a747e4fSDavid du Colombier }
611