source: MondoRescue/branches/3.3/mindi-busybox/archival/libarchive/get_header_ar.c@ 3803

Last change on this file since 3803 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 4.4 KB
RevLine 
[2725]1/* vi: set sw=4 ts=4: */
2/* Copyright 2001 Glenn McGrath.
3 *
4 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
5 */
6
7#include "libbb.h"
[3232]8#include "bb_archive.h"
[2725]9#include "ar.h"
10
[3621]11/* WARNING: Clobbers str[len], so fields must be read in reverse order! */
12static unsigned read_num(char *str, int base, int len)
[2725]13{
[3621]14 int err;
15
16 /* ar fields are fixed length text strings (padded with spaces).
17 * Ensure bb_strtou doesn't read past the field in case the full
18 * width is used. */
19 str[len] = 0;
20
[2725]21 /* This code works because
22 * on misformatted numbers bb_strtou returns all-ones */
[3621]23 err = bb_strtou(str, NULL, base);
[2725]24 if (err == -1)
25 bb_error_msg_and_die("invalid ar header");
26 return err;
27}
28
29char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
30{
31 file_header_t *typed = archive_handle->file_header;
32 unsigned size;
33 union {
34 char raw[60];
35 struct ar_header formatted;
36 } ar;
37#if ENABLE_FEATURE_AR_LONG_FILENAMES
38 static char *ar_long_names;
39 static unsigned ar_long_name_size;
40#endif
41
42 /* dont use xread as we want to handle the error ourself */
43 if (read(archive_handle->src_fd, ar.raw, 60) != 60) {
44 /* End Of File */
45 return EXIT_FAILURE;
46 }
47
48 /* ar header starts on an even byte (2 byte aligned)
49 * '\n' is used for padding
50 */
51 if (ar.raw[0] == '\n') {
52 /* fix up the header, we started reading 1 byte too early */
53 memmove(ar.raw, &ar.raw[1], 59);
54 ar.raw[59] = xread_char(archive_handle->src_fd);
55 archive_handle->offset++;
56 }
57 archive_handle->offset += 60;
58
59 if (ar.formatted.magic[0] != '`' || ar.formatted.magic[1] != '\n')
60 bb_error_msg_and_die("invalid ar header");
61
[3621]62 /*
63 * Note that the fields MUST be read in reverse order as
64 * read_num() clobbers the next byte after the field!
65 * Order is: name, date, uid, gid, mode, size, magic.
66 */
67 typed->size = size = read_num(ar.formatted.size, 10,
68 sizeof(ar.formatted.size));
[2725]69
70 /* special filenames have '/' as the first character */
71 if (ar.formatted.name[0] == '/') {
72 if (ar.formatted.name[1] == ' ') {
73 /* This is the index of symbols in the file for compilers */
74 data_skip(archive_handle);
75 archive_handle->offset += size;
76 return get_header_ar(archive_handle); /* Return next header */
77 }
78#if ENABLE_FEATURE_AR_LONG_FILENAMES
79 if (ar.formatted.name[1] == '/') {
80 /* If the second char is a '/' then this entries data section
81 * stores long filename for multiple entries, they are stored
82 * in static variable long_names for use in future entries
83 */
84 ar_long_name_size = size;
85 free(ar_long_names);
86 ar_long_names = xmalloc(size);
87 xread(archive_handle->src_fd, ar_long_names, size);
88 archive_handle->offset += size;
89 /* Return next header */
90 return get_header_ar(archive_handle);
91 }
92#else
93 bb_error_msg_and_die("long filenames not supported");
94#endif
95 }
96 /* Only size is always present, the rest may be missing in
97 * long filename pseudo file. Thus we decode the rest
98 * after dealing with long filename pseudo file.
99 */
[3621]100 typed->mode = read_num(ar.formatted.mode, 8, sizeof(ar.formatted.mode));
101 typed->gid = read_num(ar.formatted.gid, 10, sizeof(ar.formatted.gid));
102 typed->uid = read_num(ar.formatted.uid, 10, sizeof(ar.formatted.uid));
103 typed->mtime = read_num(ar.formatted.date, 10, sizeof(ar.formatted.date));
[2725]104
105#if ENABLE_FEATURE_AR_LONG_FILENAMES
106 if (ar.formatted.name[0] == '/') {
107 unsigned long_offset;
108
109 /* The number after the '/' indicates the offset in the ar data section
110 * (saved in ar_long_names) that conatains the real filename */
[3621]111 long_offset = read_num(&ar.formatted.name[1], 10,
112 sizeof(ar.formatted.name) - 1);
[2725]113 if (long_offset >= ar_long_name_size) {
114 bb_error_msg_and_die("can't resolve long filename");
115 }
116 typed->name = xstrdup(ar_long_names + long_offset);
117 } else
118#endif
119 {
120 /* short filenames */
121 typed->name = xstrndup(ar.formatted.name, 16);
122 }
123
124 typed->name[strcspn(typed->name, " /")] = '\0';
125
126 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
127 archive_handle->action_header(typed);
128#if ENABLE_DPKG || ENABLE_DPKG_DEB
129 if (archive_handle->dpkg__sub_archive) {
130 while (archive_handle->dpkg__action_data_subarchive(archive_handle->dpkg__sub_archive) == EXIT_SUCCESS)
131 continue;
132 } else
133#endif
134 archive_handle->action_data(archive_handle);
135 } else {
136 data_skip(archive_handle);
137 }
138
139 archive_handle->offset += typed->size;
140 /* Set the file pointer to the correct spot, we may have been reading a compressed file */
141 lseek(archive_handle->src_fd, archive_handle->offset, SEEK_SET);
142
143 return EXIT_SUCCESS;
144}
Note: See TracBrowser for help on using the repository browser.