aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archival/rpm.c287
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
82static void *map; 82struct globals {
83static rpm_index **mytags; 83 void *map;
84static int tagcount; 84 rpm_index **mytags;
85 85 int tagcount;
86static void extract_cpio(int fd, const char *source_rpm); 86} FIX_ALIASING;
87static rpm_index **rpm_gettags(int fd, int *num_tags); 87#define G (*(struct globals*)&bb_common_bufsiz1)
88static int bsearch_rpmtag(const void *key, const void *item); 88#define INIT_G() do { } while (0)
89static char *rpm_getstr(int tag, int itemindex);
90static int rpm_getint(int tag, int itemindex);
91static int rpm_getcount(int tag);
92static void fileaction_dobackup(char *filename, int fileref);
93static void fileaction_setowngrp(char *filename, int fileref);
94static void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref));
95
96int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
97int 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
224static void extract_cpio(int fd, const char *source_rpm) 90static 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)
305static int rpm_getcount(int tag) 171static 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)
314static char *rpm_getstr(int tag, int itemindex) 180static 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
266int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
267int 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}