Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide 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 niro 532 /* 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 niro 984 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 niro 816 char FAST_FUNC get_header_ar(archive_handle_t *archive_handle)
21 niro 532 {
22     file_header_t *typed = archive_handle->file_header;
23 niro 984 unsigned size;
24 niro 532 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 niro 816 #if ENABLE_FEATURE_AR_LONG_FILENAMES
37 niro 532 static char *ar_long_names;
38 niro 816 static unsigned ar_long_name_size;
39 niro 532 #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 niro 984 /* 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 niro 532
67 niro 984 /* special filenames have '/' as the first character */
68 niro 532 if (ar.formatted.name[0] == '/') {
69 niro 984 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 niro 816 #if ENABLE_FEATURE_AR_LONG_FILENAMES
76 niro 532 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 niro 984 * 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 niro 816 }
89 niro 984 #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 niro 816
102 niro 984 #if ENABLE_FEATURE_AR_LONG_FILENAMES
103     if (ar.formatted.name[0] == '/') {
104     unsigned long_offset;
105 niro 816
106     /* The number after the '/' indicates the offset in the ar data section
107 niro 984 * (saved in ar_long_names) that conatains the real filename */
108     long_offset = read_num(&ar.formatted.name[1], 10);
109 niro 816 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 niro 984 } else
114 niro 532 #endif
115 niro 984 {
116 niro 532 /* 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 niro 816 #if ENABLE_DPKG || ENABLE_DPKG_DEB
125 niro 984 if (archive_handle->dpkg__sub_archive) {
126     while (archive_handle->dpkg__action_data_subarchive(archive_handle->dpkg__sub_archive) == EXIT_SUCCESS)
127 niro 816 continue;
128     } else
129     #endif
130 niro 532 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     }