1 /* vi: set sw=4 ts=4: */
2 /* Copyright 2001 Glenn McGrath.
4 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
10 char FAST_FUNC
get_header_ar(archive_handle_t
*archive_handle
)
13 file_header_t
*typed
= archive_handle
->file_header
;
26 #if ENABLE_FEATURE_AR_LONG_FILENAMES
27 static char *ar_long_names
;
28 static unsigned ar_long_name_size
;
31 /* dont use xread as we want to handle the error ourself */
32 if (read(archive_handle
->src_fd
, ar
.raw
, 60) != 60) {
37 /* ar header starts on an even byte (2 byte aligned)
38 * '\n' is used for padding
40 if (ar
.raw
[0] == '\n') {
41 /* fix up the header, we started reading 1 byte too early */
42 memmove(ar
.raw
, &ar
.raw
[1], 59);
43 ar
.raw
[59] = xread_char(archive_handle
->src_fd
);
44 archive_handle
->offset
++;
46 archive_handle
->offset
+= 60;
48 /* align the headers based on the header magic */
49 if (ar
.formatted
.magic
[0] != '`' || ar
.formatted
.magic
[1] != '\n')
50 bb_error_msg_and_die("invalid ar header");
52 /* FIXME: more thorough routine would be in order here */
53 /* (we have something like that in tar) */
54 /* but for now we are lax. This code works because */
55 /* on misformatted numbers bb_strtou returns all-ones */
56 typed
->mode
= err
= bb_strtou(ar
.formatted
.mode
, NULL
, 8);
57 if (err
== -1) bb_error_msg_and_die("invalid ar header");
58 typed
->mtime
= err
= bb_strtou(ar
.formatted
.date
, NULL
, 10);
59 if (err
== -1) bb_error_msg_and_die("invalid ar header");
60 typed
->uid
= err
= bb_strtou(ar
.formatted
.uid
, NULL
, 10);
61 if (err
== -1) bb_error_msg_and_die("invalid ar header");
62 typed
->gid
= err
= bb_strtou(ar
.formatted
.gid
, NULL
, 10);
63 if (err
== -1) bb_error_msg_and_die("invalid ar header");
64 typed
->size
= err
= bb_strtou(ar
.formatted
.size
, NULL
, 10);
65 if (err
== -1) bb_error_msg_and_die("invalid ar header");
67 /* long filenames have '/' as the first character */
68 if (ar
.formatted
.name
[0] == '/') {
69 #if ENABLE_FEATURE_AR_LONG_FILENAMES
72 if (ar
.formatted
.name
[1] == '/') {
73 /* If the second char is a '/' then this entries data section
74 * stores long filename for multiple entries, they are stored
75 * in static variable long_names for use in future entries */
76 ar_long_name_size
= typed
->size
;
77 ar_long_names
= xmalloc(ar_long_name_size
);
78 xread(archive_handle
->src_fd
, ar_long_names
, ar_long_name_size
);
79 archive_handle
->offset
+= ar_long_name_size
;
80 /* This ar entries data section only contained filenames for other records
81 * they are stored in the static ar_long_names for future reference */
82 return get_header_ar(archive_handle
); /* Return next header */
85 if (ar
.formatted
.name
[1] == ' ') {
86 /* This is the index of symbols in the file for compilers */
87 data_skip(archive_handle
);
88 archive_handle
->offset
+= typed
->size
;
89 return get_header_ar(archive_handle
); /* Return next header */
92 /* The number after the '/' indicates the offset in the ar data section
93 * (saved in variable long_name) that conatains the real filename */
94 long_offset
= atoi(&ar
.formatted
.name
[1]);
95 if (long_offset
>= ar_long_name_size
) {
96 bb_error_msg_and_die("can't resolve long filename");
98 typed
->name
= xstrdup(ar_long_names
+ long_offset
);
100 bb_error_msg_and_die("long filenames not supported");
103 /* short filenames */
104 typed
->name
= xstrndup(ar
.formatted
.name
, 16);
107 typed
->name
[strcspn(typed
->name
, " /")] = '\0';
109 if (archive_handle
->filter(archive_handle
) == EXIT_SUCCESS
) {
110 archive_handle
->action_header(typed
);
111 #if ENABLE_DPKG || ENABLE_DPKG_DEB
112 if (archive_handle
->sub_archive
) {
113 while (archive_handle
->action_data_subarchive(archive_handle
->sub_archive
) == EXIT_SUCCESS
)
117 archive_handle
->action_data(archive_handle
);
119 data_skip(archive_handle
);
122 archive_handle
->offset
+= typed
->size
;
123 /* Set the file pointer to the correct spot, we may have been reading a compressed file */
124 lseek(archive_handle
->src_fd
, archive_handle
->offset
, SEEK_SET
);