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