aboutsummaryrefslogtreecommitdiff
path: root/libbb/get_ar_headers.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbb/get_ar_headers.c')
-rw-r--r--libbb/get_ar_headers.c70
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
33extern ar_headers_t get_ar_headers(int srcFd) 33extern 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}