diff options
Diffstat (limited to 'libbb/get_ar_headers.c')
-rw-r--r-- | libbb/get_ar_headers.c | 70 |
1 files changed, 38 insertions, 32 deletions
diff --git a/libbb/get_ar_headers.c b/libbb/get_ar_headers.c index cf7de5c2a..151caafe1 100644 --- a/libbb/get_ar_headers.c +++ b/libbb/get_ar_headers.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <unistd.h> | 30 | #include <unistd.h> |
31 | #include "libbb.h" | 31 | #include "libbb.h" |
32 | 32 | ||
33 | extern ar_headers_t get_ar_headers(int srcFd) | 33 | extern ar_headers_t *get_ar_headers(FILE *in_file) |
34 | { | 34 | { |
35 | typedef struct raw_ar_header_s { /* Byte Offset */ | 35 | typedef struct raw_ar_header_s { /* Byte Offset */ |
36 | char name[16]; /* 0-15 */ | 36 | char name[16]; /* 0-15 */ |
@@ -44,31 +44,33 @@ extern ar_headers_t get_ar_headers(int srcFd) | |||
44 | 44 | ||
45 | raw_ar_header_t raw_ar_header; | 45 | raw_ar_header_t raw_ar_header; |
46 | 46 | ||
47 | ar_headers_t *head, *entry; | 47 | ar_headers_t *ar_list, *ar_tmp, *ar_entry; |
48 | char ar_magic[8]; | 48 | char ar_magic[8]; |
49 | char *long_name=NULL; | 49 | char *long_name=NULL; |
50 | 50 | ||
51 | head = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); | ||
52 | entry = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); | ||
53 | |||
54 | /* check ar magic */ | 51 | /* check ar magic */ |
55 | if (full_read(srcFd, ar_magic, 8) != 8) { | 52 | if (fread(ar_magic, 1, 8, in_file) != 8) { |
56 | error_msg_and_die("cannot read magic"); | 53 | error_msg("cannot read magic"); |
54 | return(NULL); | ||
57 | } | 55 | } |
58 | 56 | ||
59 | if (strncmp(ar_magic,"!<arch>",7) != 0) { | 57 | if (strncmp(ar_magic,"!<arch>",7) != 0) { |
60 | error_msg_and_die("invalid magic"); | 58 | error_msg("invalid magic"); |
59 | return(NULL); | ||
61 | } | 60 | } |
61 | |||
62 | ar_list = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | ||
62 | 63 | ||
63 | while (full_read(srcFd, (char *) &raw_ar_header, 60)==60) { | 64 | while (fread((char *) &raw_ar_header, 1, 60, in_file) == 60) { |
65 | ar_entry = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | ||
64 | /* check the end of header markers are valid */ | 66 | /* check the end of header markers are valid */ |
65 | if ((raw_ar_header.fmag[0]!='`') || (raw_ar_header.fmag[1]!='\n')) { | 67 | if ((raw_ar_header.fmag[0] != '`') || (raw_ar_header.fmag[1] != '\n')) { |
66 | char newline; | 68 | char newline; |
67 | if (raw_ar_header.fmag[1]!='`') { | 69 | if (raw_ar_header.fmag[1] != '`') { |
68 | break; | 70 | break; |
69 | } | 71 | } |
70 | /* some version of ar, have an extra '\n' after each entry */ | 72 | /* some version of ar, have an extra '\n' after each entry */ |
71 | read(srcFd, &newline, 1); | 73 | fread(&newline, 1, 1, in_file); |
72 | if (newline!='\n') { | 74 | if (newline!='\n') { |
73 | break; | 75 | break; |
74 | } | 76 | } |
@@ -77,42 +79,46 @@ extern ar_headers_t get_ar_headers(int srcFd) | |||
77 | /* dont worry about adding the last '\n', we dont need it now */ | 79 | /* dont worry about adding the last '\n', we dont need it now */ |
78 | } | 80 | } |
79 | 81 | ||
80 | entry->size = (off_t) atoi(raw_ar_header.size); | 82 | ar_entry->size = (size_t) atoi(raw_ar_header.size); |
81 | /* long filenames have '/' as the first character */ | 83 | /* long filenames have '/' as the first character */ |
82 | if (raw_ar_header.name[0] == '/') { | 84 | if (raw_ar_header.name[0] == '/') { |
83 | if (raw_ar_header.name[1] == '/') { | 85 | if (raw_ar_header.name[1] == '/') { |
84 | /* multiple long filenames are stored as data in one entry */ | 86 | /* multiple long filenames are stored as data in one entry */ |
85 | long_name = (char *) xrealloc(long_name, entry->size); | 87 | long_name = (char *) xrealloc(long_name, ar_entry->size); |
86 | full_read(srcFd, long_name, entry->size); | 88 | fread(long_name, 1, ar_entry->size, in_file); |
87 | continue; | 89 | continue; |
88 | } | 90 | } |
89 | else { | 91 | else { |
90 | /* The number after the '/' indicates the offset in the ar data section | 92 | /* The number after the '/' indicates the offset in the ar data section |
91 | (saved in variable long_name) that conatains the real filename */ | 93 | (saved in variable long_name) that conatains the real filename */ |
92 | const int long_name_offset = (int) atoi((char *) &raw_ar_header.name[1]); | 94 | const int long_name_offset = (int) atoi((char *) &raw_ar_header.name[1]); |
93 | entry->name = xmalloc(strlen(&long_name[long_name_offset])); | 95 | ar_entry->name = xmalloc(strlen(&long_name[long_name_offset])); |
94 | strcpy(entry->name, &long_name[long_name_offset]); | 96 | strcpy(ar_entry->name, &long_name[long_name_offset]); |
95 | } | 97 | } |
96 | } | 98 | } |
97 | else { | 99 | else { |
98 | /* short filenames */ | 100 | /* short filenames */ |
99 | entry->name = xmalloc(16); | 101 | ar_entry->name = xmalloc(16); |
100 | strncpy(entry->name, raw_ar_header.name, 16); | 102 | ar_entry->name = strncpy(ar_entry->name, raw_ar_header.name, 16); |
101 | } | 103 | } |
102 | entry->name[strcspn(entry->name, " /")]='\0'; | 104 | ar_entry->name[strcspn(ar_entry->name, " /")]='\0'; |
103 | 105 | ||
104 | /* convert the rest of the now valid char header to its typed struct */ | 106 | /* convert the rest of the now valid char header to its typed struct */ |
105 | parse_mode(raw_ar_header.mode, &entry->mode); | 107 | parse_mode(raw_ar_header.mode, &ar_entry->mode); |
106 | entry->mtime = atoi(raw_ar_header.date); | 108 | ar_entry->mtime = atoi(raw_ar_header.date); |
107 | entry->uid = atoi(raw_ar_header.uid); | 109 | ar_entry->uid = atoi(raw_ar_header.uid); |
108 | entry->gid = atoi(raw_ar_header.gid); | 110 | ar_entry->gid = atoi(raw_ar_header.gid); |
109 | entry->offset = lseek(srcFd, 0, SEEK_CUR); | 111 | ar_entry->offset = ftell(in_file); |
112 | ar_entry->next = NULL; | ||
110 | 113 | ||
111 | /* add this entries header to our combined list */ | 114 | fseek(in_file, (off_t) ar_entry->size, SEEK_CUR); |
112 | entry->next = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); | 115 | |
113 | *entry->next = *head; | 116 | ar_tmp = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); |
114 | *head = *entry; | 117 | *ar_tmp = *ar_list; |
115 | lseek(srcFd, (off_t) entry->size, SEEK_CUR); | 118 | *ar_list = *ar_entry; |
119 | free(ar_entry); | ||
120 | ar_list->next = ar_tmp; | ||
116 | } | 121 | } |
117 | return(*head); | 122 | |
118 | } \ No newline at end of file | 123 | return(ar_list); |
124 | } | ||