Magellan Linux

Contents of /trunk/mkinitrd-magellan/busybox/archival/libunarchive/get_header_ar.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (show annotations) (download)
Sun May 30 11:32:42 2010 UTC (13 years, 11 months ago) by niro
File MIME type: text/plain
File size: 4213 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 /* vi: set sw=4 ts=4: */
2 /* Copyright 2001 Glenn McGrath.
3 *
4 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
5 */
6
7 #include "libbb.h"
8 #include "unarchive.h"
9
10 static unsigned read_num(const char *str, int base)
11 {
12 /* This code works because
13 * on misformatted numbers bb_strtou returns all-ones */
14 int err = bb_strtou(str, NULL, base);
15 if (err == -1)
16 bb_error_msg_and_die("invalid ar header");
17 return err;
18 }
19
20 char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
21 {
22 file_header_t *typed = archive_handle->file_header;
23 unsigned size;
24 union {
25 char raw[60];
26 struct {
27 char name[16];
28 char date[12];
29 char uid[6];
30 char gid[6];
31 char mode[8];
32 char size[10];
33 char magic[2];
34 } formatted;
35 } ar;
36 #if ENABLE_FEATURE_AR_LONG_FILENAMES
37 static char *ar_long_names;
38 static unsigned ar_long_name_size;
39 #endif
40
41 /* dont use xread as we want to handle the error ourself */
42 if (read(archive_handle->src_fd, ar.raw, 60) != 60) {
43 /* End Of File */
44 return EXIT_FAILURE;
45 }
46
47 /* ar header starts on an even byte (2 byte aligned)
48 * '\n' is used for padding
49 */
50 if (ar.raw[0] == '\n') {
51 /* fix up the header, we started reading 1 byte too early */
52 memmove(ar.raw, &ar.raw[1], 59);
53 ar.raw[59] = xread_char(archive_handle->src_fd);
54 archive_handle->offset++;
55 }
56 archive_handle->offset += 60;
57
58 /* align the headers based on the header magic */
59 if (ar.formatted.magic[0] != '`' || ar.formatted.magic[1] != '\n')
60 bb_error_msg_and_die("invalid ar header");
61
62 /* FIXME: more thorough routine would be in order here
63 * (we have something like that in tar)
64 * but for now we are lax. */
65 typed->size = size = read_num(ar.formatted.size, 10);
66
67 /* special filenames have '/' as the first character */
68 if (ar.formatted.name[0] == '/') {
69 if (ar.formatted.name[1] == ' ') {
70 /* This is the index of symbols in the file for compilers */
71 data_skip(archive_handle);
72 archive_handle->offset += size;
73 return get_header_ar(archive_handle); /* Return next header */
74 }
75 #if ENABLE_FEATURE_AR_LONG_FILENAMES
76 if (ar.formatted.name[1] == '/') {
77 /* If the second char is a '/' then this entries data section
78 * stores long filename for multiple entries, they are stored
79 * in static variable long_names for use in future entries
80 */
81 ar_long_name_size = size;
82 free(ar_long_names);
83 ar_long_names = xmalloc(size);
84 xread(archive_handle->src_fd, ar_long_names, size);
85 archive_handle->offset += size;
86 /* Return next header */
87 return get_header_ar(archive_handle);
88 }
89 #else
90 bb_error_msg_and_die("long filenames not supported");
91 #endif
92 }
93 /* Only size is always present, the rest may be missing in
94 * long filename pseudo file. Thus we decode the rest
95 * after dealing with long filename pseudo file.
96 */
97 typed->mode = read_num(ar.formatted.mode, 8);
98 typed->mtime = read_num(ar.formatted.date, 10);
99 typed->uid = read_num(ar.formatted.uid, 10);
100 typed->gid = read_num(ar.formatted.gid, 10);
101
102 #if ENABLE_FEATURE_AR_LONG_FILENAMES
103 if (ar.formatted.name[0] == '/') {
104 unsigned long_offset;
105
106 /* The number after the '/' indicates the offset in the ar data section
107 * (saved in ar_long_names) that conatains the real filename */
108 long_offset = read_num(&ar.formatted.name[1], 10);
109 if (long_offset >= ar_long_name_size) {
110 bb_error_msg_and_die("can't resolve long filename");
111 }
112 typed->name = xstrdup(ar_long_names + long_offset);
113 } else
114 #endif
115 {
116 /* short filenames */
117 typed->name = xstrndup(ar.formatted.name, 16);
118 }
119
120 typed->name[strcspn(typed->name, " /")] = '\0';
121
122 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
123 archive_handle->action_header(typed);
124 #if ENABLE_DPKG || ENABLE_DPKG_DEB
125 if (archive_handle->dpkg__sub_archive) {
126 while (archive_handle->dpkg__action_data_subarchive(archive_handle->dpkg__sub_archive) == EXIT_SUCCESS)
127 continue;
128 } else
129 #endif
130 archive_handle->action_data(archive_handle);
131 } else {
132 data_skip(archive_handle);
133 }
134
135 archive_handle->offset += typed->size;
136 /* Set the file pointer to the correct spot, we may have been reading a compressed file */
137 lseek(archive_handle->src_fd, archive_handle->offset, SEEK_SET);
138
139 return EXIT_SUCCESS;
140 }