]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libarchive/archive_read_support_format_ar.c
This commit was generated by cvs2svn to compensate for changes in r178479,
[FreeBSD/FreeBSD.git] / lib / libarchive / archive_read_support_format_ar.c
1 /*-
2  * Copyright (c) 2007 Kai Wang
3  * Copyright (c) 2007 Tim Kientzle
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer
11  *    in this position and unchanged.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "archive_platform.h"
29 __FBSDID("$FreeBSD$");
30
31 #ifdef HAVE_SYS_STAT_H
32 #include <sys/stat.h>
33 #endif
34 #ifdef HAVE_ERRNO_H
35 #include <errno.h>
36 #endif
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40 #ifdef HAVE_STRING_H
41 #include <string.h>
42 #endif
43
44 #include "archive.h"
45 #include "archive_entry.h"
46 #include "archive_private.h"
47 #include "archive_read_private.h"
48
49 struct ar {
50         off_t    entry_bytes_remaining;
51         off_t    entry_offset;
52         off_t    entry_padding;
53         char    *strtab;
54         size_t   strtab_size;
55 };
56
57 /*
58  * Define structure of the "ar" header.
59  */
60 #define AR_name_offset 0
61 #define AR_name_size 16
62 #define AR_date_offset 16
63 #define AR_date_size 12
64 #define AR_uid_offset 28
65 #define AR_uid_size 6
66 #define AR_gid_offset 34
67 #define AR_gid_size 6
68 #define AR_mode_offset 40
69 #define AR_mode_size 8
70 #define AR_size_offset 48
71 #define AR_size_size 10
72 #define AR_fmag_offset 58
73 #define AR_fmag_size 2
74
75 #define isdigit(x)      (x) >= '0' && (x) <= '9'
76
77 static int      archive_read_format_ar_bid(struct archive_read *a);
78 static int      archive_read_format_ar_cleanup(struct archive_read *a);
79 static int      archive_read_format_ar_read_data(struct archive_read *a,
80                     const void **buff, size_t *size, off_t *offset);
81 static int      archive_read_format_ar_skip(struct archive_read *a);
82 static int      archive_read_format_ar_read_header(struct archive_read *a,
83                     struct archive_entry *e);
84 static uint64_t ar_atol8(const char *p, unsigned char_cnt);
85 static uint64_t ar_atol10(const char *p, unsigned char_cnt);
86 static int      ar_parse_gnu_filename_table(struct archive_read *a);
87 static int      ar_parse_common_header(struct ar *ar, struct archive_entry *,
88                     const char *h);
89
90 int
91 archive_read_support_format_ar(struct archive *_a)
92 {
93         struct archive_read *a = (struct archive_read *)_a;
94         struct ar *ar;
95         int r;
96
97         ar = (struct ar *)malloc(sizeof(*ar));
98         if (ar == NULL) {
99                 archive_set_error(&a->archive, ENOMEM,
100                     "Can't allocate ar data");
101                 return (ARCHIVE_FATAL);
102         }
103         memset(ar, 0, sizeof(*ar));
104         ar->strtab = NULL;
105
106         r = __archive_read_register_format(a,
107             ar,
108             archive_read_format_ar_bid,
109             archive_read_format_ar_read_header,
110             archive_read_format_ar_read_data,
111             archive_read_format_ar_skip,
112             archive_read_format_ar_cleanup);
113
114         if (r != ARCHIVE_OK) {
115                 free(ar);
116                 return (r);
117         }
118         return (ARCHIVE_OK);
119 }
120
121 static int
122 archive_read_format_ar_cleanup(struct archive_read *a)
123 {
124         struct ar *ar;
125
126         ar = (struct ar *)(a->format->data);
127         if (ar->strtab)
128                 free(ar->strtab);
129         free(ar);
130         (a->format->data) = NULL;
131         return (ARCHIVE_OK);
132 }
133
134 static int
135 archive_read_format_ar_bid(struct archive_read *a)
136 {
137         struct ar *ar;
138         ssize_t bytes_read;
139         const void *h;
140
141         if (a->archive.archive_format != 0 &&
142             (a->archive.archive_format & ARCHIVE_FORMAT_BASE_MASK) !=
143             ARCHIVE_FORMAT_AR)
144                 return(0);
145
146         ar = (struct ar *)(a->format->data);
147
148         /*
149          * Verify the 8-byte file signature.
150          * TODO: Do we need to check more than this?
151          */
152         bytes_read = (a->decompressor->read_ahead)(a, &h, 8);
153         if (bytes_read < 8)
154                 return (-1);
155         if (strncmp((const char*)h, "!<arch>\n", 8) == 0) {
156                 return (64);
157         }
158         return (-1);
159 }
160
161 static int
162 archive_read_format_ar_read_header(struct archive_read *a,
163     struct archive_entry *entry)
164 {
165         char filename[AR_name_size + 1];
166         struct ar *ar;
167         uint64_t number; /* Used to hold parsed numbers before validation. */
168         ssize_t bytes_read;
169         size_t bsd_name_length, entry_size, s;
170         char *p, *st;
171         const void *b;
172         const char *h;
173         int r;
174
175         ar = (struct ar*)(a->format->data);
176
177         if (a->archive.file_position == 0) {
178                 /*
179                  * We are now at the beginning of the archive,
180                  * so we need first consume the ar global header.
181                  */
182                 (a->decompressor->consume)(a, 8);
183                 /* Set a default format code for now. */
184                 a->archive.archive_format = ARCHIVE_FORMAT_AR;
185         }
186
187         /* Read the header for the next file entry. */
188         bytes_read = (a->decompressor->read_ahead)(a, &b, 60);
189         if (bytes_read < 60) {
190                 /* Broken header. */
191                 return (ARCHIVE_EOF);
192         }
193         (a->decompressor->consume)(a, 60);
194         h = (const char *)b;
195
196         /* Verify the magic signature on the file header. */
197         if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) {
198                 archive_set_error(&a->archive, EINVAL,
199                     "Consistency check failed");
200                 return (ARCHIVE_WARN);
201         }
202
203         /* Copy filename into work buffer. */
204         strncpy(filename, h + AR_name_offset, AR_name_size);
205         filename[AR_name_size] = '\0';
206
207         /*
208          * Guess the format variant based on the filename.
209          */
210         if (a->archive.archive_format == ARCHIVE_FORMAT_AR) {
211                 /* We don't already know the variant, so let's guess. */
212                 /*
213                  * Biggest clue is presence of '/': GNU starts special
214                  * filenames with '/', appends '/' as terminator to
215                  * non-special names, so anything with '/' should be
216                  * GNU except for BSD long filenames.
217                  */
218                 if (strncmp(filename, "#1/", 3) == 0)
219                         a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD;
220                 else if (strchr(filename, '/') != NULL)
221                         a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU;
222                 else if (strncmp(filename, "__.SYMDEF", 9) == 0)
223                         a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD;
224                 /*
225                  * XXX Do GNU/SVR4 'ar' programs ever omit trailing '/'
226                  * if name exactly fills 16-byte field?  If so, we
227                  * can't assume entries without '/' are BSD. XXX
228                  */
229         }
230
231         /* Update format name from the code. */
232         if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU)
233                 a->archive.archive_format_name = "ar (GNU/SVR4)";
234         else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD)
235                 a->archive.archive_format_name = "ar (BSD)";
236         else
237                 a->archive.archive_format_name = "ar";
238
239         /*
240          * Remove trailing spaces from the filename.  GNU and BSD
241          * variants both pad filename area out with spaces.
242          * This will only be wrong if GNU/SVR4 'ar' implementations
243          * omit trailing '/' for 16-char filenames and we have
244          * a 16-char filename that ends in ' '.
245          */
246         p = filename + AR_name_size - 1;
247         while (p >= filename && *p == ' ') {
248                 *p = '\0';
249                 p--;
250         }
251
252         /*
253          * Remove trailing slash unless first character is '/'.
254          * (BSD entries never end in '/', so this will only trim
255          * GNU-format entries.  GNU special entries start with '/'
256          * and are not terminated in '/', so we don't trim anything
257          * that starts with '/'.)
258          */
259         if (filename[0] != '/' && *p == '/')
260                 *p = '\0';
261
262         /*
263          * '//' is the GNU filename table.
264          * Later entries can refer to names in this table.
265          */
266         if (strcmp(filename, "//") == 0) {
267                 /* This must come before any call to _read_ahead. */
268                 ar_parse_common_header(ar, entry, h);
269                 archive_entry_copy_pathname(entry, filename);
270                 archive_entry_set_filetype(entry, AE_IFREG);
271                 /* Get the size of the filename table. */
272                 number = ar_atol10(h + AR_size_offset, AR_size_size);
273                 if (number > SIZE_MAX) {
274                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
275                             "Filename table too large");
276                         return (ARCHIVE_FATAL);
277                 }
278                 entry_size = (size_t)number;
279                 if (entry_size == 0) {
280                         archive_set_error(&a->archive, EINVAL,
281                             "Invalid string table");
282                         return (ARCHIVE_WARN);
283                 }
284                 if (ar->strtab != NULL) {
285                         archive_set_error(&a->archive, EINVAL,
286                             "More than one string tables exist");
287                         return (ARCHIVE_WARN);
288                 }
289
290                 /* Read the filename table into memory. */
291                 st = malloc(entry_size);
292                 if (st == NULL) {
293                         archive_set_error(&a->archive, ENOMEM,
294                             "Can't allocate filename table buffer");
295                         return (ARCHIVE_FATAL);
296                 }
297                 ar->strtab = st;
298                 ar->strtab_size = entry_size;
299                 for (s = entry_size; s > 0; s -= bytes_read) {
300                         bytes_read = (a->decompressor->read_ahead)(a, &b, s);
301                         if (bytes_read <= 0)
302                                 return (ARCHIVE_FATAL);
303                         if (bytes_read > (ssize_t)s)
304                                 bytes_read = s;
305                         memcpy(st, b, bytes_read);
306                         st += bytes_read;
307                         (a->decompressor->consume)(a, bytes_read);
308                 }
309                 /* All contents are consumed. */
310                 ar->entry_bytes_remaining = 0;
311                 archive_entry_set_size(entry, ar->entry_bytes_remaining);
312
313                 /* Parse the filename table. */
314                 return (ar_parse_gnu_filename_table(a));
315         }
316
317         /*
318          * GNU variant handles long filenames by storing /<number>
319          * to indicate a name stored in the filename table.
320          */
321         if (filename[0] == '/' && isdigit(filename[1])) {
322                 number = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1);
323                 /*
324                  * If we can't look up the real name, warn and return
325                  * the entry with the wrong name.
326                  */
327                 if (ar->strtab == NULL || number > ar->strtab_size) {
328                         archive_set_error(&a->archive, EINVAL,
329                             "Can't find long filename for entry");
330                         archive_entry_copy_pathname(entry, filename);
331                         /* Parse the time, owner, mode, size fields. */
332                         ar_parse_common_header(ar, entry, h);
333                         return (ARCHIVE_WARN);
334                 }
335
336                 archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]);
337                 /* Parse the time, owner, mode, size fields. */
338                 return (ar_parse_common_header(ar, entry, h));
339         }
340
341         /*
342          * BSD handles long filenames by storing "#1/" followed by the
343          * length of filename as a decimal number, then prepends the
344          * the filename to the file contents.
345          */
346         if (strncmp(filename, "#1/", 3) == 0) {
347                 /* Parse the time, owner, mode, size fields. */
348                 /* This must occur before _read_ahead is called again. */
349                 ar_parse_common_header(ar, entry, h);
350
351                 /* Parse the size of the name, adjust the file size. */
352                 number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3);
353                 if ((off_t)number > ar->entry_bytes_remaining) {
354                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
355                             "Bad input file size");
356                         return (ARCHIVE_FATAL);
357                 }
358                 bsd_name_length = (size_t)number;
359                 ar->entry_bytes_remaining -= bsd_name_length;
360                 /* Adjust file size reported to client. */
361                 archive_entry_set_size(entry, ar->entry_bytes_remaining);
362
363                 /* Read the long name into memory. */
364                 bytes_read = (a->decompressor->read_ahead)(a, &b, bsd_name_length);
365                 if (bytes_read <= 0)
366                         return (ARCHIVE_FATAL);
367                 if ((size_t)bytes_read < bsd_name_length) {
368                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
369                             "Truncated input file");
370                         return (ARCHIVE_FATAL);
371                 }
372                 (a->decompressor->consume)(a, bsd_name_length);
373
374                 /* Store it in the entry. */
375                 p = (char *)malloc(bsd_name_length + 1);
376                 if (p == NULL) {
377                         archive_set_error(&a->archive, ENOMEM,
378                             "Can't allocate fname buffer");
379                         return (ARCHIVE_FATAL);
380                 }
381                 strncpy(p, b, bsd_name_length);
382                 p[bsd_name_length] = '\0';
383                 archive_entry_copy_pathname(entry, p);
384                 free(p);
385                 return (ARCHIVE_OK);
386         }
387
388         /*
389          * "/" is the SVR4/GNU archive symbol table.
390          */
391         if (strcmp(filename, "/") == 0) {
392                 archive_entry_copy_pathname(entry, "/");
393                 /* Parse the time, owner, mode, size fields. */
394                 r = ar_parse_common_header(ar, entry, h);
395                 /* Force the file type to a regular file. */
396                 archive_entry_set_filetype(entry, AE_IFREG);
397                 return (r);
398         }
399
400         /*
401          * "__.SYMDEF" is a BSD archive symbol table.
402          */
403         if (strcmp(filename, "__.SYMDEF") == 0) {
404                 archive_entry_copy_pathname(entry, filename);
405                 /* Parse the time, owner, mode, size fields. */
406                 return (ar_parse_common_header(ar, entry, h));
407         }
408
409         /*
410          * Otherwise, this is a standard entry.  The filename
411          * has already been trimmed as much as possible, based
412          * on our current knowledge of the format.
413          */
414         archive_entry_copy_pathname(entry, filename);
415         return (ar_parse_common_header(ar, entry, h));
416 }
417
418 static int
419 ar_parse_common_header(struct ar *ar, struct archive_entry *entry,
420     const char *h)
421 {
422         uint64_t n;
423
424         /* Copy remaining header */
425         archive_entry_set_mtime(entry,
426             (time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L);
427         archive_entry_set_uid(entry,
428             (uid_t)ar_atol10(h + AR_uid_offset, AR_uid_size));
429         archive_entry_set_gid(entry,
430             (gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size));
431         archive_entry_set_mode(entry,
432             (mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size));
433         n = ar_atol10(h + AR_size_offset, AR_size_size);
434
435         ar->entry_offset = 0;
436         ar->entry_padding = n % 2;
437         archive_entry_set_size(entry, n);
438         ar->entry_bytes_remaining = n;
439         return (ARCHIVE_OK);
440 }
441
442 static int
443 archive_read_format_ar_read_data(struct archive_read *a,
444     const void **buff, size_t *size, off_t *offset)
445 {
446         ssize_t bytes_read;
447         struct ar *ar;
448
449         ar = (struct ar *)(a->format->data);
450
451         if (ar->entry_bytes_remaining > 0) {
452                 bytes_read = (a->decompressor->read_ahead)(a, buff, 1);
453                 if (bytes_read == 0) {
454                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
455                             "Truncated ar archive");
456                         return (ARCHIVE_FATAL);
457                 }
458                 if (bytes_read < 0)
459                         return (ARCHIVE_FATAL);
460                 if (bytes_read > ar->entry_bytes_remaining)
461                         bytes_read = (ssize_t)ar->entry_bytes_remaining;
462                 *size = bytes_read;
463                 *offset = ar->entry_offset;
464                 ar->entry_offset += bytes_read;
465                 ar->entry_bytes_remaining -= bytes_read;
466                 (a->decompressor->consume)(a, (size_t)bytes_read);
467                 return (ARCHIVE_OK);
468         } else {
469                 while (ar->entry_padding > 0) {
470                         bytes_read = (a->decompressor->read_ahead)(a, buff, 1);
471                         if (bytes_read <= 0)
472                                 return (ARCHIVE_FATAL);
473                         if (bytes_read > ar->entry_padding)
474                                 bytes_read = (ssize_t)ar->entry_padding;
475                         (a->decompressor->consume)(a, (size_t)bytes_read);
476                         ar->entry_padding -= bytes_read;
477                 }
478                 *buff = NULL;
479                 *size = 0;
480                 *offset = ar->entry_offset;
481                 return (ARCHIVE_EOF);
482         }
483 }
484
485 static int
486 archive_read_format_ar_skip(struct archive_read *a)
487 {
488         off_t bytes_skipped;
489         struct ar* ar;
490         int r = ARCHIVE_OK;
491         const void *b;          /* Dummy variables */
492         size_t s;
493         off_t o;
494
495         ar = (struct ar *)(a->format->data);
496         if (a->decompressor->skip == NULL) {
497                 while (r == ARCHIVE_OK)
498                         r = archive_read_format_ar_read_data(a, &b, &s, &o);
499                 return (r);
500         }
501
502         bytes_skipped = (a->decompressor->skip)(a, ar->entry_bytes_remaining +
503             ar->entry_padding);
504         if (bytes_skipped < 0)
505                 return (ARCHIVE_FATAL);
506
507         ar->entry_bytes_remaining = 0;
508         ar->entry_padding = 0;
509
510         return (ARCHIVE_OK);
511 }
512
513 static int
514 ar_parse_gnu_filename_table(struct archive_read *a)
515 {
516         struct ar *ar;
517         char *p;
518         size_t size;
519
520         ar = (struct ar*)(a->format->data);
521         size = ar->strtab_size;
522
523         for (p = ar->strtab; p < ar->strtab + size - 1; ++p) {
524                 if (*p == '/') {
525                         *p++ = '\0';
526                         if (*p != '\n')
527                                 goto bad_string_table;
528                         *p = '\0';
529                 }
530         }
531         /*
532          * Sanity check, last two chars must be `/\n' or '\n\n',
533          * depending on whether the string table is padded by a '\n'
534          * (string table produced by GNU ar always has a even size).
535          */
536         if (p != ar->strtab + size && *p != '\n')
537                 goto bad_string_table;
538
539         /* Enforce zero termination. */
540         ar->strtab[size - 1] = '\0';
541
542         return (ARCHIVE_OK);
543
544 bad_string_table:
545         archive_set_error(&a->archive, EINVAL,
546             "Invalid string table");
547         free(ar->strtab);
548         ar->strtab = NULL;
549         return (ARCHIVE_WARN);
550 }
551
552 static uint64_t
553 ar_atol8(const char *p, unsigned char_cnt)
554 {
555         uint64_t l, limit, last_digit_limit;
556         unsigned int digit, base;
557
558         base = 8;
559         limit = UINT64_MAX / base;
560         last_digit_limit = UINT64_MAX % base;
561
562         while ((*p == ' ' || *p == '\t') && char_cnt-- > 0)
563                 p++;
564
565         l = 0;
566         digit = *p - '0';
567         while (*p >= '0' && digit < base  && char_cnt-- > 0) {
568                 if (l>limit || (l == limit && digit > last_digit_limit)) {
569                         l = UINT64_MAX; /* Truncate on overflow. */
570                         break;
571                 }
572                 l = (l * base) + digit;
573                 digit = *++p - '0';
574         }
575         return (l);
576 }
577
578 static uint64_t
579 ar_atol10(const char *p, unsigned char_cnt)
580 {
581         uint64_t l, limit, last_digit_limit;
582         unsigned int base, digit;
583
584         base = 10;
585         limit = UINT64_MAX / base;
586         last_digit_limit = UINT64_MAX % base;
587
588         while ((*p == ' ' || *p == '\t') && char_cnt-- > 0)
589                 p++;
590         l = 0;
591         digit = *p - '0';
592         while (*p >= '0' && digit < base  && char_cnt-- > 0) {
593                 if (l > limit || (l == limit && digit > last_digit_limit)) {
594                         l = UINT64_MAX; /* Truncate on overflow. */
595                         break;
596                 }
597                 l = (l * base) + digit;
598                 digit = *++p - '0';
599         }
600         return (l);
601 }