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