diff options
-rw-r--r-- | archival/rpm.c | 287 |
1 files changed, 141 insertions, 146 deletions
diff --git a/archival/rpm.c b/archival/rpm.c index 6b227d537..b506f1779 100644 --- a/archival/rpm.c +++ b/archival/rpm.c | |||
@@ -79,147 +79,13 @@ typedef struct { | |||
79 | uint32_t count; /* 4 byte count */ | 79 | uint32_t count; /* 4 byte count */ |
80 | } rpm_index; | 80 | } rpm_index; |
81 | 81 | ||
82 | static void *map; | 82 | struct globals { |
83 | static rpm_index **mytags; | 83 | void *map; |
84 | static int tagcount; | 84 | rpm_index **mytags; |
85 | 85 | int tagcount; | |
86 | static void extract_cpio(int fd, const char *source_rpm); | 86 | } FIX_ALIASING; |
87 | static rpm_index **rpm_gettags(int fd, int *num_tags); | 87 | #define G (*(struct globals*)&bb_common_bufsiz1) |
88 | static int bsearch_rpmtag(const void *key, const void *item); | 88 | #define INIT_G() do { } while (0) |
89 | static char *rpm_getstr(int tag, int itemindex); | ||
90 | static int rpm_getint(int tag, int itemindex); | ||
91 | static int rpm_getcount(int tag); | ||
92 | static void fileaction_dobackup(char *filename, int fileref); | ||
93 | static void fileaction_setowngrp(char *filename, int fileref); | ||
94 | static void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref)); | ||
95 | |||
96 | int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
97 | int rpm_main(int argc, char **argv) | ||
98 | { | ||
99 | int opt, func = 0; | ||
100 | const unsigned pagesize = getpagesize(); | ||
101 | |||
102 | while ((opt = getopt(argc, argv, "iqpldc")) != -1) { | ||
103 | switch (opt) { | ||
104 | case 'i': /* First arg: Install mode, with q: Information */ | ||
105 | if (!func) func = rpm_install; | ||
106 | else func |= rpm_query_info; | ||
107 | break; | ||
108 | case 'q': /* First arg: Query mode */ | ||
109 | if (func) bb_show_usage(); | ||
110 | func = rpm_query; | ||
111 | break; | ||
112 | case 'p': /* Query a package */ | ||
113 | func |= rpm_query_package; | ||
114 | break; | ||
115 | case 'l': /* List files in a package */ | ||
116 | func |= rpm_query_list; | ||
117 | break; | ||
118 | case 'd': /* List doc files in a package (implies list) */ | ||
119 | func |= rpm_query_list; | ||
120 | func |= rpm_query_list_doc; | ||
121 | break; | ||
122 | case 'c': /* List config files in a package (implies list) */ | ||
123 | func |= rpm_query_list; | ||
124 | func |= rpm_query_list_config; | ||
125 | break; | ||
126 | default: | ||
127 | bb_show_usage(); | ||
128 | } | ||
129 | } | ||
130 | argv += optind; | ||
131 | //argc -= optind; | ||
132 | if (!argv[0]) { | ||
133 | bb_show_usage(); | ||
134 | } | ||
135 | |||
136 | while (*argv) { | ||
137 | int rpm_fd; | ||
138 | unsigned offset; | ||
139 | const char *source_rpm; | ||
140 | |||
141 | rpm_fd = xopen(*argv++, O_RDONLY); | ||
142 | mytags = rpm_gettags(rpm_fd, &tagcount); | ||
143 | if (!mytags) | ||
144 | bb_error_msg_and_die("error reading rpm header"); | ||
145 | offset = xlseek(rpm_fd, 0, SEEK_CUR); | ||
146 | /* Some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */ | ||
147 | map = mmap(0, (offset + pagesize) & (-(int)pagesize), PROT_READ, MAP_PRIVATE, rpm_fd, 0); | ||
148 | |||
149 | source_rpm = rpm_getstr(TAG_SOURCERPM, 0); | ||
150 | |||
151 | if (func & rpm_install) { | ||
152 | /* Backup any config files */ | ||
153 | loop_through_files(TAG_BASENAMES, fileaction_dobackup); | ||
154 | /* Extact the archive */ | ||
155 | extract_cpio(rpm_fd, source_rpm); | ||
156 | /* Set the correct file uid/gid's */ | ||
157 | loop_through_files(TAG_BASENAMES, fileaction_setowngrp); | ||
158 | } | ||
159 | else if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) { | ||
160 | if (!(func & (rpm_query_info|rpm_query_list))) { | ||
161 | /* If just a straight query, just give package name */ | ||
162 | printf("%s-%s-%s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_RELEASE, 0)); | ||
163 | } | ||
164 | if (func & rpm_query_info) { | ||
165 | /* Do the nice printout */ | ||
166 | time_t bdate_time; | ||
167 | struct tm *bdate_ptm; | ||
168 | char bdatestring[50]; | ||
169 | const char *p; | ||
170 | |||
171 | printf("%-12s: %s\n", "Name" , rpm_getstr(TAG_NAME, 0)); | ||
172 | /* TODO compat: add "Epoch" here */ | ||
173 | printf("%-12s: %s\n", "Version" , rpm_getstr(TAG_VERSION, 0)); | ||
174 | printf("%-12s: %s\n", "Release" , rpm_getstr(TAG_RELEASE, 0)); | ||
175 | /* add "Architecture" */ | ||
176 | printf("%-12s: %s\n", "Install Date", "(not installed)"); | ||
177 | printf("%-12s: %s\n", "Group" , rpm_getstr(TAG_GROUP, 0)); | ||
178 | printf("%-12s: %d\n", "Size" , rpm_getint(TAG_SIZE, 0)); | ||
179 | printf("%-12s: %s\n", "License" , rpm_getstr(TAG_LICENSE, 0)); | ||
180 | /* add "Signature" */ | ||
181 | printf("%-12s: %s\n", "Source RPM" , source_rpm ? source_rpm : "(none)"); | ||
182 | bdate_time = rpm_getint(TAG_BUILDTIME, 0); | ||
183 | bdate_ptm = localtime(&bdate_time); | ||
184 | strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); | ||
185 | printf("%-12s: %s\n", "Build Date" , bdatestring); | ||
186 | printf("%-12s: %s\n", "Build Host" , rpm_getstr(TAG_BUILDHOST, 0)); | ||
187 | p = rpm_getstr(TAG_PREFIXS, 0); | ||
188 | printf("%-12s: %s\n", "Relocations" , p ? p : "(not relocatable)"); | ||
189 | /* add "Packager" */ | ||
190 | p = rpm_getstr(TAG_VENDOR, 0); | ||
191 | printf("%-12s: %s\n", "Vendor" , p ? p : "(none)"); | ||
192 | printf("%-12s: %s\n", "URL" , rpm_getstr(TAG_URL, 0)); | ||
193 | printf("%-12s: %s\n", "Summary" , rpm_getstr(TAG_SUMMARY, 0)); | ||
194 | printf("Description :\n%s\n", rpm_getstr(TAG_DESCRIPTION, 0)); | ||
195 | } | ||
196 | if (func & rpm_query_list) { | ||
197 | int count, it, flags; | ||
198 | count = rpm_getcount(TAG_BASENAMES); | ||
199 | for (it = 0; it < count; it++) { | ||
200 | flags = rpm_getint(TAG_FILEFLAGS, it); | ||
201 | switch (func & (rpm_query_list_doc|rpm_query_list_config)) { | ||
202 | case rpm_query_list_doc: | ||
203 | if (!(flags & RPMFILE_DOC)) continue; | ||
204 | break; | ||
205 | case rpm_query_list_config: | ||
206 | if (!(flags & RPMFILE_CONFIG)) continue; | ||
207 | break; | ||
208 | case rpm_query_list_doc|rpm_query_list_config: | ||
209 | if (!(flags & (RPMFILE_CONFIG|RPMFILE_DOC))) continue; | ||
210 | break; | ||
211 | } | ||
212 | printf("%s%s\n", | ||
213 | rpm_getstr(TAG_DIRNAMES, rpm_getint(TAG_DIRINDEXES, it)), | ||
214 | rpm_getstr(TAG_BASENAMES, it)); | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | free(mytags); | ||
219 | close(rpm_fd); | ||
220 | } | ||
221 | return 0; | ||
222 | } | ||
223 | 89 | ||
224 | static void extract_cpio(int fd, const char *source_rpm) | 90 | static void extract_cpio(int fd, const char *source_rpm) |
225 | { | 91 | { |
@@ -305,7 +171,7 @@ static int bsearch_rpmtag(const void *key, const void *item) | |||
305 | static int rpm_getcount(int tag) | 171 | static int rpm_getcount(int tag) |
306 | { | 172 | { |
307 | rpm_index **found; | 173 | rpm_index **found; |
308 | found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | 174 | found = bsearch(&tag, G.mytags, G.tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); |
309 | if (!found) | 175 | if (!found) |
310 | return 0; | 176 | return 0; |
311 | return found[0]->count; | 177 | return found[0]->count; |
@@ -314,7 +180,7 @@ static int rpm_getcount(int tag) | |||
314 | static char *rpm_getstr(int tag, int itemindex) | 180 | static char *rpm_getstr(int tag, int itemindex) |
315 | { | 181 | { |
316 | rpm_index **found; | 182 | rpm_index **found; |
317 | found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | 183 | found = bsearch(&tag, G.mytags, G.tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); |
318 | if (!found || itemindex >= found[0]->count) | 184 | if (!found || itemindex >= found[0]->count) |
319 | return NULL; | 185 | return NULL; |
320 | if (found[0]->type == RPM_STRING_TYPE | 186 | if (found[0]->type == RPM_STRING_TYPE |
@@ -322,7 +188,7 @@ static char *rpm_getstr(int tag, int itemindex) | |||
322 | || found[0]->type == RPM_STRING_ARRAY_TYPE | 188 | || found[0]->type == RPM_STRING_ARRAY_TYPE |
323 | ) { | 189 | ) { |
324 | int n; | 190 | int n; |
325 | char *tmpstr = (char *) map + found[0]->offset; | 191 | char *tmpstr = (char *) G.map + found[0]->offset; |
326 | for (n = 0; n < itemindex; n++) | 192 | for (n = 0; n < itemindex; n++) |
327 | tmpstr = tmpstr + strlen(tmpstr) + 1; | 193 | tmpstr = tmpstr + strlen(tmpstr) + 1; |
328 | return tmpstr; | 194 | return tmpstr; |
@@ -337,11 +203,11 @@ static int rpm_getint(int tag, int itemindex) | |||
337 | 203 | ||
338 | /* gcc throws warnings here when sizeof(void*)!=sizeof(int) ... | 204 | /* gcc throws warnings here when sizeof(void*)!=sizeof(int) ... |
339 | * it's ok to ignore it because tag won't be used as a pointer */ | 205 | * it's ok to ignore it because tag won't be used as a pointer */ |
340 | found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | 206 | found = bsearch(&tag, G.mytags, G.tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); |
341 | if (!found || itemindex >= found[0]->count) | 207 | if (!found || itemindex >= found[0]->count) |
342 | return -1; | 208 | return -1; |
343 | 209 | ||
344 | tmpint = (char *) map + found[0]->offset; | 210 | tmpint = (char *) G.map + found[0]->offset; |
345 | if (found[0]->type == RPM_INT32_TYPE) { | 211 | if (found[0]->type == RPM_INT32_TYPE) { |
346 | tmpint += itemindex*4; | 212 | tmpint += itemindex*4; |
347 | return ntohl(*(int32_t*)tmpint); | 213 | return ntohl(*(int32_t*)tmpint); |
@@ -396,3 +262,132 @@ static void loop_through_files(int filetag, void (*fileaction)(char *filename, i | |||
396 | free(filename); | 262 | free(filename); |
397 | } | 263 | } |
398 | } | 264 | } |
265 | |||
266 | int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
267 | int rpm_main(int argc, char **argv) | ||
268 | { | ||
269 | int opt, func = 0; | ||
270 | const unsigned pagesize = getpagesize(); | ||
271 | |||
272 | while ((opt = getopt(argc, argv, "iqpldc")) != -1) { | ||
273 | switch (opt) { | ||
274 | case 'i': /* First arg: Install mode, with q: Information */ | ||
275 | if (!func) func = rpm_install; | ||
276 | else func |= rpm_query_info; | ||
277 | break; | ||
278 | case 'q': /* First arg: Query mode */ | ||
279 | if (func) bb_show_usage(); | ||
280 | func = rpm_query; | ||
281 | break; | ||
282 | case 'p': /* Query a package */ | ||
283 | func |= rpm_query_package; | ||
284 | break; | ||
285 | case 'l': /* List files in a package */ | ||
286 | func |= rpm_query_list; | ||
287 | break; | ||
288 | case 'd': /* List doc files in a package (implies list) */ | ||
289 | func |= rpm_query_list; | ||
290 | func |= rpm_query_list_doc; | ||
291 | break; | ||
292 | case 'c': /* List config files in a package (implies list) */ | ||
293 | func |= rpm_query_list; | ||
294 | func |= rpm_query_list_config; | ||
295 | break; | ||
296 | default: | ||
297 | bb_show_usage(); | ||
298 | } | ||
299 | } | ||
300 | argv += optind; | ||
301 | //argc -= optind; | ||
302 | if (!argv[0]) { | ||
303 | bb_show_usage(); | ||
304 | } | ||
305 | |||
306 | while (*argv) { | ||
307 | int rpm_fd; | ||
308 | unsigned offset; | ||
309 | const char *source_rpm; | ||
310 | |||
311 | rpm_fd = xopen(*argv++, O_RDONLY); | ||
312 | G.mytags = rpm_gettags(rpm_fd, &G.tagcount); | ||
313 | if (!G.mytags) | ||
314 | bb_error_msg_and_die("error reading rpm header"); | ||
315 | offset = xlseek(rpm_fd, 0, SEEK_CUR); | ||
316 | /* Some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */ | ||
317 | G.map = mmap(0, (offset + pagesize) & (-(int)pagesize), PROT_READ, MAP_PRIVATE, rpm_fd, 0); | ||
318 | //FIXME: error check? | ||
319 | |||
320 | source_rpm = rpm_getstr(TAG_SOURCERPM, 0); | ||
321 | |||
322 | if (func & rpm_install) { | ||
323 | /* Backup any config files */ | ||
324 | loop_through_files(TAG_BASENAMES, fileaction_dobackup); | ||
325 | /* Extact the archive */ | ||
326 | extract_cpio(rpm_fd, source_rpm); | ||
327 | /* Set the correct file uid/gid's */ | ||
328 | loop_through_files(TAG_BASENAMES, fileaction_setowngrp); | ||
329 | } | ||
330 | else if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) { | ||
331 | if (!(func & (rpm_query_info|rpm_query_list))) { | ||
332 | /* If just a straight query, just give package name */ | ||
333 | printf("%s-%s-%s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_RELEASE, 0)); | ||
334 | } | ||
335 | if (func & rpm_query_info) { | ||
336 | /* Do the nice printout */ | ||
337 | time_t bdate_time; | ||
338 | struct tm *bdate_ptm; | ||
339 | char bdatestring[50]; | ||
340 | const char *p; | ||
341 | |||
342 | printf("%-12s: %s\n", "Name" , rpm_getstr(TAG_NAME, 0)); | ||
343 | /* TODO compat: add "Epoch" here */ | ||
344 | printf("%-12s: %s\n", "Version" , rpm_getstr(TAG_VERSION, 0)); | ||
345 | printf("%-12s: %s\n", "Release" , rpm_getstr(TAG_RELEASE, 0)); | ||
346 | /* add "Architecture" */ | ||
347 | printf("%-12s: %s\n", "Install Date", "(not installed)"); | ||
348 | printf("%-12s: %s\n", "Group" , rpm_getstr(TAG_GROUP, 0)); | ||
349 | printf("%-12s: %d\n", "Size" , rpm_getint(TAG_SIZE, 0)); | ||
350 | printf("%-12s: %s\n", "License" , rpm_getstr(TAG_LICENSE, 0)); | ||
351 | /* add "Signature" */ | ||
352 | printf("%-12s: %s\n", "Source RPM" , source_rpm ? source_rpm : "(none)"); | ||
353 | bdate_time = rpm_getint(TAG_BUILDTIME, 0); | ||
354 | bdate_ptm = localtime(&bdate_time); | ||
355 | strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); | ||
356 | printf("%-12s: %s\n", "Build Date" , bdatestring); | ||
357 | printf("%-12s: %s\n", "Build Host" , rpm_getstr(TAG_BUILDHOST, 0)); | ||
358 | p = rpm_getstr(TAG_PREFIXS, 0); | ||
359 | printf("%-12s: %s\n", "Relocations" , p ? p : "(not relocatable)"); | ||
360 | /* add "Packager" */ | ||
361 | p = rpm_getstr(TAG_VENDOR, 0); | ||
362 | printf("%-12s: %s\n", "Vendor" , p ? p : "(none)"); | ||
363 | printf("%-12s: %s\n", "URL" , rpm_getstr(TAG_URL, 0)); | ||
364 | printf("%-12s: %s\n", "Summary" , rpm_getstr(TAG_SUMMARY, 0)); | ||
365 | printf("Description :\n%s\n", rpm_getstr(TAG_DESCRIPTION, 0)); | ||
366 | } | ||
367 | if (func & rpm_query_list) { | ||
368 | int count, it, flags; | ||
369 | count = rpm_getcount(TAG_BASENAMES); | ||
370 | for (it = 0; it < count; it++) { | ||
371 | flags = rpm_getint(TAG_FILEFLAGS, it); | ||
372 | switch (func & (rpm_query_list_doc|rpm_query_list_config)) { | ||
373 | case rpm_query_list_doc: | ||
374 | if (!(flags & RPMFILE_DOC)) continue; | ||
375 | break; | ||
376 | case rpm_query_list_config: | ||
377 | if (!(flags & RPMFILE_CONFIG)) continue; | ||
378 | break; | ||
379 | case rpm_query_list_doc|rpm_query_list_config: | ||
380 | if (!(flags & (RPMFILE_CONFIG|RPMFILE_DOC))) continue; | ||
381 | break; | ||
382 | } | ||
383 | printf("%s%s\n", | ||
384 | rpm_getstr(TAG_DIRNAMES, rpm_getint(TAG_DIRINDEXES, it)), | ||
385 | rpm_getstr(TAG_BASENAMES, it)); | ||
386 | } | ||
387 | } | ||
388 | } | ||
389 | free(G.mytags); | ||
390 | close(rpm_fd); | ||
391 | } | ||
392 | return 0; | ||
393 | } | ||