diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2001-04-16 04:52:19 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2001-04-16 04:52:19 +0000 |
commit | 33431ebb9ace3fba76138198596f8155c2e14354 (patch) | |
tree | 514459eccbc4927b00c0493badb7f12575c9147d | |
parent | 3136904ff69b3f67096dbaf2afd9ac77256c4bae (diff) | |
download | busybox-w32-33431ebb9ace3fba76138198596f8155c2e14354.tar.gz busybox-w32-33431ebb9ace3fba76138198596f8155c2e14354.tar.bz2 busybox-w32-33431ebb9ace3fba76138198596f8155c2e14354.zip |
dpkg improvements, use full package struct, avoid extracting to tmp dir, rename variable.
deb_extract, untar and dpkg_deb modified to make the above possible
-rw-r--r-- | archival/dpkg.c | 371 | ||||
-rw-r--r-- | archival/dpkg_deb.c | 19 | ||||
-rw-r--r-- | dpkg.c | 371 | ||||
-rw-r--r-- | dpkg_deb.c | 19 | ||||
-rw-r--r-- | include/libbb.h | 9 | ||||
-rw-r--r-- | libbb/deb_extract.c | 33 | ||||
-rw-r--r-- | libbb/libbb.h | 9 | ||||
-rw-r--r-- | libbb/untar.c | 42 |
8 files changed, 451 insertions, 422 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c index d0728d995..0d2b2dc3c 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #define DODEPENDS 1 | 20 | #define DODEPENDS 1 |
21 | 21 | ||
22 | /* Should we do debugging? */ | 22 | /* Should we do debugging? */ |
23 | //#define DODEBUG 1 | 23 | #define DODEBUG 0 |
24 | 24 | ||
25 | #ifdef DODEBUG | 25 | #ifdef DODEBUG |
26 | #define SYSTEM(x) do_system(x) | 26 | #define SYSTEM(x) do_system(x) |
@@ -32,63 +32,68 @@ | |||
32 | 32 | ||
33 | /* from dpkg-deb.c */ | 33 | /* from dpkg-deb.c */ |
34 | 34 | ||
35 | static const int dpkg_deb_contents = 1; | ||
36 | static const int dpkg_deb_control = 2; | ||
37 | // const int dpkg_deb_info = 4; | ||
38 | static const int dpkg_deb_extract = 8; | ||
39 | static const int dpkg_deb_verbose_extract = 16; | ||
40 | static const int dpkg_deb_list = 32; | ||
41 | |||
42 | static const char statusfile[] = "/var/lib/dpkg/status.udeb"; | 35 | static const char statusfile[] = "/var/lib/dpkg/status.udeb"; |
43 | static const char new_statusfile[] = "/var/lib/dpkg/status.udeb.new"; | 36 | static const char new_statusfile[] = "/var/lib/dpkg/status.udeb.new"; |
44 | static const char bak_statusfile[] = "/var/lib/dpkg/status.udeb.bak"; | 37 | static const char bak_statusfile[] = "/var/lib/dpkg/status.udeb.bak"; |
45 | 38 | ||
46 | static const char dpkgcidir[] = "/var/lib/dpkg/tmp.ci/"; | ||
47 | |||
48 | static const char infodir[] = "/var/lib/dpkg/info/"; | 39 | static const char infodir[] = "/var/lib/dpkg/info/"; |
49 | static const char udpkg_quiet[] = "UDPKG_QUIET"; | 40 | static const char udpkg_quiet[] = "UDPKG_QUIET"; |
50 | 41 | ||
51 | //static const int status_want_unknown = 1; | 42 | //static const int status_want_unknown = 1; |
52 | static const int status_want_install = 2; | 43 | static const int state_want_install = 2; |
53 | //static const int status_want_hold = 3; | 44 | //static const int state_want_hold = 3; |
54 | //static const int status_want_deinstall = 4; | 45 | //static const int state_want_deinstall = 4; |
55 | //static const int status_want_purge = 5; | 46 | //static const int state_want_purge = 5; |
56 | 47 | ||
57 | static const int status_flag_ok = 1; | 48 | static const int state_flag_ok = 1; |
58 | //static const int status_flag_reinstreq = 2; | 49 | //static const int state_flag_reinstreq = 2; |
59 | //static const int status_flag_hold = 3; | 50 | //static const int state_flag_hold = 3; |
60 | //static const int status_flag_holdreinstreq = 4; | 51 | //static const int state_flag_holdreinstreq = 4; |
61 | 52 | ||
62 | //static const int status_statusnoninstalled = 1; | 53 | //static const int state_statusnoninstalled = 1; |
63 | static const int status_status_unpacked = 2; | 54 | static const int state_status_unpacked = 2; |
64 | static const int status_status_halfconfigured = 3; | 55 | static const int state_status_halfconfigured = 3; |
65 | static const int status_status_installed = 4; | 56 | static const int state_status_installed = 4; |
66 | static const int status_status_halfinstalled = 5; | 57 | static const int state_status_halfinstalled = 5; |
67 | //static const int status_statusconfigfiles = 6; | 58 | //static const int state_statusconfigfiles = 6; |
68 | //static const int status_statuspostinstfailed = 7; | 59 | //static const int state_statuspostinstfailed = 7; |
69 | //static const int status_statusremovalfailed = 8; | 60 | //static const int state_statusremovalfailed = 8; |
70 | 61 | ||
71 | static const char *status_words_want[] = { "unknown", "install", "hold", "deinstall", "purge", 0 }; | 62 | static const char *state_words_want[] = { "unknown", "install", "hold", "deinstall", "purge", 0 }; |
72 | static const char *status_words_flag[] = { "ok", "reinstreq", "hold", "hold-reinstreq", 0 }; | 63 | static const char *state_words_flag[] = { "ok", "reinstreq", "hold", "hold-reinstreq", 0 }; |
73 | static const char *status_words_status[] = { "not-installed", "unpacked", "half-configured", "installed", | 64 | static const char *state_words_status[] = { "not-installed", "unpacked", "half-configured", "installed", |
74 | "half-installed", "config-files", "post-inst-failed", "removal-failed", 0 }; | 65 | "half-installed", "config-files", "post-inst-failed", "removal-failed", 0 }; |
75 | 66 | ||
76 | static const int color_white = 0; | 67 | static const int color_white = 0; |
77 | static const int color_grey = 1; | 68 | static const int color_grey = 1; |
78 | static const int color_black = 2; | 69 | static const int color_black = 2; |
79 | 70 | ||
80 | /* data structures */ | 71 | /* data structures */ |
81 | typedef struct package_s { | 72 | typedef struct package_s { |
82 | char *file; | 73 | char *filename; |
83 | char *package; | 74 | char *package; |
84 | char *version; | 75 | unsigned char state_want; |
76 | unsigned char state_flag; | ||
77 | unsigned char state_status; | ||
85 | char *depends; | 78 | char *depends; |
86 | char *provides; | 79 | char *provides; |
87 | char *description; | 80 | char *description; |
81 | char *priority; | ||
82 | char *section; | ||
83 | char *installed_size; | ||
84 | char *maintainer; | ||
85 | char *source; | ||
86 | char *version; | ||
87 | char *pre_depends; | ||
88 | char *replaces; | ||
89 | char *recommends; | ||
90 | char *suggests; | ||
91 | char *conflicts; | ||
92 | char *conffiles; | ||
93 | char *long_description; | ||
94 | char *architecture; | ||
95 | char *md5sum; | ||
88 | int installer_menu_item; | 96 | int installer_menu_item; |
89 | unsigned char status_want; | ||
90 | unsigned char status_flag; | ||
91 | unsigned char status_status; | ||
92 | char color; /* for topo-sort */ | 97 | char color; /* for topo-sort */ |
93 | struct package_s *requiredfor[DEPENDSMAX]; | 98 | struct package_s *requiredfor[DEPENDSMAX]; |
94 | unsigned short requiredcount; | 99 | unsigned short requiredcount; |
@@ -265,8 +270,8 @@ static package_t *depends_resolve(package_t *pkgs, void *status) | |||
265 | /* Check for dependencies; first look for installed packages */ | 270 | /* Check for dependencies; first look for installed packages */ |
266 | dependpkg.package = dependsvec[i]; | 271 | dependpkg.package = dependsvec[i]; |
267 | if (((found = tfind(&dependpkg, &status, package_compare)) == 0) || | 272 | if (((found = tfind(&dependpkg, &status, package_compare)) == 0) || |
268 | ((chk = *(package_t **)found) && (chk->status_flag & status_flag_ok) && | 273 | ((chk = *(package_t **)found) && (chk->state_flag & state_flag_ok) && |
269 | (chk->status_status & status_status_installed))) { | 274 | (chk->state_status & state_status_installed))) { |
270 | 275 | ||
271 | /* if it fails, we look through the list of packages we are going to | 276 | /* if it fails, we look through the list of packages we are going to |
272 | * install */ | 277 | * install */ |
@@ -328,47 +333,100 @@ static unsigned char status_parse(const char *line, const char **status_words) | |||
328 | } | 333 | } |
329 | 334 | ||
330 | /* | 335 | /* |
331 | * Read a control file (or a stanza of a status file) and parse it, | 336 | * Read the buffered control file and parse it, |
332 | * filling parsed fields into the package structure | 337 | * filling parsed fields into the package structure |
333 | */ | 338 | */ |
334 | static int control_read(FILE *file, package_t *p) | 339 | static int fill_package_struct(package_t *package, const char *package_buffer) |
335 | { | 340 | { |
336 | char *line; | 341 | char *field = NULL; |
337 | 342 | int field_start = 0; | |
338 | while ((line = get_line_from_file(file)) != NULL) { | 343 | int field_length = 0; |
339 | line[strlen(line) - 1] = '\0'; | 344 | while ((field = read_package_field(&package_buffer[field_start])) != NULL) { |
340 | 345 | field_length = strlen(field); | |
341 | if (strlen(line) == 0) { | 346 | field_start += (field_length + 1); |
347 | |||
348 | if (strlen(field) == 0) { | ||
349 | printf("empty line: *this shouldnt happen i dont think*\n"); | ||
342 | break; | 350 | break; |
343 | } | 351 | } |
344 | else if (strstr(line, "Package: ") == line) { | 352 | |
345 | p->package = xstrdup(line + 9); | 353 | /* these are common to both installed and uninstalled packages */ |
346 | } | 354 | if (strstr(field, "Package: ") == field) { |
347 | else if (strstr(line, "Status: ") == line) { | 355 | package->package = strdup(field + 9); |
348 | char *word_pointer; | ||
349 | word_pointer = strchr(line, ' ') + 1; | ||
350 | p->status_want = status_parse(word_pointer, status_words_want); | ||
351 | word_pointer = strchr(word_pointer, ' ') + 1; | ||
352 | p->status_flag = status_parse(word_pointer, status_words_flag); | ||
353 | word_pointer = strchr(word_pointer, ' ') + 1; | ||
354 | p->status_status = status_parse(word_pointer, status_words_status); | ||
355 | } | 356 | } |
356 | else if (strstr(line, "Depends: ") == line) { | 357 | else if (strstr(field, "Depends: ") == field) { |
357 | p->depends = xstrdup(line + 9); | 358 | package->depends = strdup(field + 9); |
358 | } | 359 | } |
359 | else if (strstr(line, "Provides: ") == line) { | 360 | else if (strstr(field, "Provides: ") == field) { |
360 | p->provides = xstrdup(line + 10); | 361 | package->provides = strdup(field + 10); |
361 | } | 362 | } |
362 | else if (strstr(line, "Description: ") == line) { | ||
363 | p->description = xstrdup(line + 13); | ||
364 | /* This is specific to the Debian Installer. Ifdef? */ | 363 | /* This is specific to the Debian Installer. Ifdef? */ |
364 | else if (strstr(field, "installer-menu-item: ") == field) { | ||
365 | package->installer_menu_item = atoi(field + 21); | ||
366 | } | ||
367 | else if (strstr(field, "Description: ") == field) { | ||
368 | package->description = strdup(field + 13); | ||
369 | } | ||
370 | else if (strstr(field, "Priority: ") == field) { | ||
371 | package->priority = strdup(field + 10); | ||
372 | } | ||
373 | else if (strstr(field, "Section: ") == field) { | ||
374 | package->section = strdup(field + 9); | ||
375 | } | ||
376 | else if (strstr(field, "Installed-Size: ") == field) { | ||
377 | package->installed_size = strdup(field + 16); | ||
378 | } | ||
379 | else if (strstr(field, "Maintainer: ") == field) { | ||
380 | package->maintainer = strdup(field + 12); | ||
381 | } | ||
382 | else if (strstr(field, "Version: ") == field) { | ||
383 | package->version = strdup(field + 9); | ||
365 | } | 384 | } |
366 | else if (strstr(line, "installer-menu-item: ") == line) { | 385 | else if (strstr(field, "Suggests: ") == field) { |
367 | p->installer_menu_item = atoi(line + 21); | 386 | package->suggests = strdup(field + 10); |
368 | } | 387 | } |
369 | /* TODO: localized descriptions */ | 388 | else if (strstr(field, "Recommends: ") == field) { |
389 | package->recommends = strdup(field + 12); | ||
390 | } | ||
391 | /* else if (strstr(field, "Conffiles: ") == field) { | ||
392 | package->conffiles = read_block(file); | ||
393 | package->conffiles = xcalloc(1, 1); | ||
394 | while ((field = strtok(NULL, "\n")) != NULL) { | ||
395 | package->long_description = xrealloc(package->conffiles, | ||
396 | strlen(package->conffiles) + strlen(field) + 1); | ||
397 | strcat(package->conffiles, field); | ||
398 | } | ||
399 | } | ||
400 | */ | ||
401 | /* These are only in available file */ | ||
402 | else if (strstr(field, "Architecture: ") == field) { | ||
403 | package->architecture = strdup(field + 14); | ||
404 | } | ||
405 | else if (strstr(field, "Filename: ") == field) { | ||
406 | package->filename = strdup(field + 10); | ||
407 | } | ||
408 | else if (strstr(field, "MD5sum ") == field) { | ||
409 | package->md5sum = strdup(field + 7); | ||
410 | } | ||
411 | |||
412 | /* This is only needed for status file */ | ||
413 | if (strstr(field, "Status: ") == field) { | ||
414 | char *word_pointer; | ||
415 | |||
416 | word_pointer = strchr(field, ' ') + 1; | ||
417 | package->state_want = status_parse(word_pointer, state_words_want); | ||
418 | word_pointer = strchr(word_pointer, ' ') + 1; | ||
419 | package->state_flag = status_parse(word_pointer, state_words_flag); | ||
420 | word_pointer = strchr(word_pointer, ' ') + 1; | ||
421 | package->state_status = status_parse(word_pointer, state_words_status); | ||
422 | } else { | ||
423 | package->state_want = status_parse("purge", state_words_want); | ||
424 | package->state_flag = status_parse("ok", state_words_flag); | ||
425 | package->state_status = status_parse("not-installed", state_words_status); | ||
426 | } | ||
427 | |||
428 | free(field); | ||
370 | } | 429 | } |
371 | free(line); | ||
372 | return EXIT_SUCCESS; | 430 | return EXIT_SUCCESS; |
373 | } | 431 | } |
374 | 432 | ||
@@ -377,6 +435,7 @@ static void *status_read(void) | |||
377 | FILE *f; | 435 | FILE *f; |
378 | void *status = 0; | 436 | void *status = 0; |
379 | package_t *m = 0, *p = 0, *t = 0; | 437 | package_t *m = 0, *p = 0, *t = 0; |
438 | char *package_control_buffer = NULL; | ||
380 | 439 | ||
381 | if (getenv(udpkg_quiet) == NULL) { | 440 | if (getenv(udpkg_quiet) == NULL) { |
382 | printf("(Reading database...)\n"); | 441 | printf("(Reading database...)\n"); |
@@ -386,9 +445,11 @@ static void *status_read(void) | |||
386 | return(NULL); | 445 | return(NULL); |
387 | } | 446 | } |
388 | 447 | ||
389 | while (!feof(f)) { | 448 | while ( (package_control_buffer = read_text_file_to_buffer(f)) != NULL) { |
390 | m = (package_t *)xcalloc(1, sizeof(package_t)); | 449 | m = (package_t *)xcalloc(1, sizeof(package_t)); |
391 | control_read(f, m); | 450 | printf("read buffer [%s]\n", package_control_buffer); |
451 | fill_package_struct(m, package_control_buffer); | ||
452 | printf("package is [%s]\n", m->package); | ||
392 | if (m->package) { | 453 | if (m->package) { |
393 | /* | 454 | /* |
394 | * If there is an item in the tree by this name, | 455 | * If there is an item in the tree by this name, |
@@ -418,9 +479,9 @@ static void *status_read(void) | |||
418 | * packages of different statuses | 479 | * packages of different statuses |
419 | * provide it). | 480 | * provide it). |
420 | */ | 481 | */ |
421 | t->status_want = m->status_want; | 482 | t->state_want = m->state_want; |
422 | t->status_flag = m->status_flag; | 483 | t->state_flag = m->state_flag; |
423 | t->status_status = m->status_status; | 484 | t->state_status = m->state_status; |
424 | } | 485 | } |
425 | } | 486 | } |
426 | } | 487 | } |
@@ -428,6 +489,7 @@ static void *status_read(void) | |||
428 | free(m); | 489 | free(m); |
429 | } | 490 | } |
430 | } | 491 | } |
492 | printf("done\n"); | ||
431 | fclose(f); | 493 | fclose(f); |
432 | return status; | 494 | return status; |
433 | } | 495 | } |
@@ -479,9 +541,9 @@ static int status_merge(void *status, package_t *pkgs) | |||
479 | } | 541 | } |
480 | if (strstr(line, "Status: ") == line && statpkg != 0) { | 542 | if (strstr(line, "Status: ") == line && statpkg != 0) { |
481 | snprintf(line, sizeof(line), "Status: %s %s %s", | 543 | snprintf(line, sizeof(line), "Status: %s %s %s", |
482 | status_words_want[statpkg->status_want - 1], | 544 | state_words_want[statpkg->state_want - 1], |
483 | status_words_flag[statpkg->status_flag - 1], | 545 | state_words_flag[statpkg->state_flag - 1], |
484 | status_words_status[statpkg->status_status - 1]); | 546 | state_words_status[statpkg->state_status - 1]); |
485 | } | 547 | } |
486 | fprintf(fout, "%s\n", line); | 548 | fprintf(fout, "%s\n", line); |
487 | } | 549 | } |
@@ -492,9 +554,9 @@ static int status_merge(void *status, package_t *pkgs) | |||
492 | // Print out packages we processed. | 554 | // Print out packages we processed. |
493 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { | 555 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { |
494 | fprintf(fout, "Package: %s\nStatus: %s %s %s\n", | 556 | fprintf(fout, "Package: %s\nStatus: %s %s %s\n", |
495 | pkg->package, status_words_want[pkg->status_want - 1], | 557 | pkg->package, state_words_want[pkg->state_want - 1], |
496 | status_words_flag[pkg->status_flag - 1], | 558 | state_words_flag[pkg->state_flag - 1], |
497 | status_words_status[pkg->status_status - 1]); | 559 | state_words_status[pkg->state_status - 1]); |
498 | 560 | ||
499 | if (pkg->depends) | 561 | if (pkg->depends) |
500 | fprintf(fout, "Depends: %s\n", pkg->depends); | 562 | fprintf(fout, "Depends: %s\n", pkg->depends); |
@@ -544,144 +606,68 @@ static int dpkg_doconfigure(package_t *pkg) | |||
544 | char buf[1024]; | 606 | char buf[1024]; |
545 | 607 | ||
546 | DPRINTF("Configuring %s\n", pkg->package); | 608 | DPRINTF("Configuring %s\n", pkg->package); |
547 | pkg->status_status = 0; | 609 | pkg->state_status = 0; |
548 | snprintf(postinst, sizeof(postinst), "%s%s.postinst", infodir, pkg->package); | 610 | snprintf(postinst, sizeof(postinst), "%s%s.postinst", infodir, pkg->package); |
549 | 611 | ||
550 | if (is_file(postinst)) { | 612 | if (is_file(postinst)) { |
551 | snprintf(buf, sizeof(buf), "%s configure", postinst); | 613 | snprintf(buf, sizeof(buf), "%s configure", postinst); |
552 | if ((r = do_system(buf)) != 0) { | 614 | if ((r = do_system(buf)) != 0) { |
553 | error_msg("postinst exited with status %d\n", r); | 615 | error_msg("postinst exited with status %d\n", r); |
554 | pkg->status_status = status_status_halfconfigured; | 616 | pkg->state_status = state_status_halfconfigured; |
555 | return 1; | 617 | return 1; |
556 | } | 618 | } |
557 | } | 619 | } |
558 | pkg->status_status = status_status_installed; | 620 | pkg->state_status = state_status_installed; |
559 | 621 | ||
560 | return 0; | 622 | return 0; |
561 | } | 623 | } |
562 | 624 | ||
563 | static int dpkg_dounpack(package_t *pkg) | 625 | static int dpkg_dounpack(package_t *pkg) |
564 | { | 626 | { |
565 | int r = 0, i; | 627 | int r = 0; |
566 | int status = TRUE; | 628 | int status = TRUE; |
567 | char *cwd = xgetcwd(0); | 629 | char *lst_path; |
568 | char *src_filename = NULL; | ||
569 | char *dst_filename = NULL; | ||
570 | // char *lst_file = NULL; | ||
571 | char *adminscripts[] = { "prerm", "postrm", "preinst", "postinst", | ||
572 | "conffiles", "md5sums", "shlibs", "templates" }; | ||
573 | 630 | ||
574 | DPRINTF("Unpacking %s\n", pkg->package); | 631 | DPRINTF("Unpacking %s\n", pkg->package); |
575 | 632 | ||
576 | if(cwd==NULL) | 633 | /* extract the data file */ |
577 | exit(EXIT_FAILURE); | 634 | deb_extract(pkg->filename, extract_extract, "/", NULL); |
578 | chdir("/"); | ||
579 | deb_extract(pkg->file, dpkg_deb_extract, "/"); | ||
580 | 635 | ||
581 | /* Installs the package scripts into the info directory */ | 636 | /* extract the control files */ |
582 | for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) { | 637 | deb_extract(pkg->filename, extract_control, infodir, pkg->package); |
583 | struct stat src_stat_buf; | ||
584 | FILE *src_file = NULL, *dst_file = NULL; | ||
585 | 638 | ||
586 | /* The full path of the current location of the admin file */ | 639 | /* Create the list file */ |
587 | src_filename = xrealloc(src_filename, strlen(dpkgcidir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); | 640 | lst_path = xmalloc(strlen(infodir) + strlen(pkg->package) + 6); |
588 | sprintf(src_filename, "%s%s/%s", dpkgcidir, pkg->package, adminscripts[i]); | 641 | strcpy(lst_path, infodir); |
642 | strcat(lst_path, pkg->package); | ||
643 | strcat(lst_path, ".list"); | ||
644 | deb_extract(pkg->filename, extract_contents_to_file, lst_path, NULL); | ||
589 | 645 | ||
590 | /* the full path of where we want the file to be copied to */ | 646 | pkg->state_want = state_want_install; |
591 | dst_filename = xrealloc(dst_filename, strlen(infodir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); | 647 | pkg->state_flag = state_flag_ok; |
592 | sprintf(dst_filename, "%s%s.%s", infodir, pkg->package, adminscripts[i]); | ||
593 | |||
594 | /* | ||
595 | * copy admin file to permanent home | ||
596 | * NOTE: Maybe merge this behaviour into libb/copy_file.c | ||
597 | */ | ||
598 | if (lstat(src_filename, &src_stat_buf) == 0) { | ||
599 | if ((src_file = wfopen(src_filename, "r")) != NULL) { | ||
600 | if ((dst_file = wfopen(dst_filename, "w")) == NULL) { | ||
601 | status = FALSE; | ||
602 | perror_msg("Opening %s", dst_filename); | ||
603 | } | ||
604 | copy_file_chunk(src_file, dst_file, src_stat_buf.st_size); | ||
605 | fclose(src_file); | ||
606 | fclose(dst_file); | ||
607 | } else { | ||
608 | status = FALSE; | ||
609 | error_msg("couldnt open [%s]\n", src_filename); | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | /* | ||
615 | * create the list file | ||
616 | * FIXME: currently this dumps the lst to stdout instead of a file | ||
617 | */ | ||
618 | /* lst_file = (char *) xmalloc(strlen(infodir) + strlen(pkg->package) + 6); | ||
619 | strcpy(lst_file, infodir); | ||
620 | strcat(lst_file, pkg->package); | ||
621 | strcat(lst_file, ".list"); | ||
622 | deb_extract(dpkg_deb_list, NULL, pkg->file); | ||
623 | */ | ||
624 | |||
625 | pkg->status_want = status_want_install; | ||
626 | pkg->status_flag = status_flag_ok; | ||
627 | 648 | ||
628 | if (status == TRUE) { | 649 | if (status == TRUE) { |
629 | pkg->status_status = status_status_unpacked; | 650 | pkg->state_status = state_status_unpacked; |
630 | } else { | 651 | } else { |
631 | pkg->status_status = status_status_halfinstalled; | 652 | pkg->state_status = state_status_halfinstalled; |
632 | } | 653 | } |
633 | 654 | ||
634 | chdir(cwd); | ||
635 | return r; | 655 | return r; |
636 | } | 656 | } |
637 | 657 | ||
638 | /* | 658 | /* |
639 | * Extract and parse the control.tar.gz from the specified package | 659 | * Extract and parse the control file from control.tar.gz |
640 | */ | 660 | */ |
641 | static int dpkg_unpackcontrol(package_t *pkg) | 661 | static int dpkg_read_control(package_t *pkg) |
642 | { | 662 | { |
643 | char *tmp_name; | 663 | FILE *pkg_file; |
644 | FILE *file; | 664 | char *control_buffer = NULL; |
645 | int length; | ||
646 | 665 | ||
647 | /* clean the temp directory (dpkgcidir) be recreating it */ | 666 | if ((pkg_file = wfopen(pkg->filename, "r")) == NULL) { |
648 | remove_dir(dpkgcidir); | ||
649 | if (create_path(dpkgcidir, S_IRWXU) == FALSE) { | ||
650 | return EXIT_FAILURE; | 667 | return EXIT_FAILURE; |
651 | } | 668 | } |
652 | 669 | control_buffer = deb_extract(pkg->filename, extract_field, NULL, NULL); | |
653 | /* | 670 | fill_package_struct(pkg, control_buffer); |
654 | * Get the package name from the file name, | ||
655 | * first remove the directories | ||
656 | */ | ||
657 | if ((tmp_name = strrchr(pkg->file, '/')) == NULL) { | ||
658 | tmp_name = pkg->file; | ||
659 | } else { | ||
660 | tmp_name++; | ||
661 | } | ||
662 | /* now remove trailing version numbers etc */ | ||
663 | length = strcspn(tmp_name, "_."); | ||
664 | pkg->package = (char *) xcalloc(1, length + 1); | ||
665 | /* store the package name */ | ||
666 | strncpy(pkg->package, tmp_name, length); | ||
667 | |||
668 | /* work out the full extraction path */ | ||
669 | tmp_name = (char *) xcalloc(1, strlen(dpkgcidir) + strlen(pkg->package) + 9); | ||
670 | strcpy(tmp_name, dpkgcidir); | ||
671 | strcat(tmp_name, pkg->package); | ||
672 | |||
673 | /* extract control.tar.gz to the full extraction path */ | ||
674 | deb_extract(pkg->file, dpkg_deb_control, tmp_name); | ||
675 | |||
676 | /* parse the extracted control file */ | ||
677 | strcat(tmp_name, "/control"); | ||
678 | if ((file = wfopen(tmp_name, "r")) == NULL) { | ||
679 | return EXIT_FAILURE; | ||
680 | } | ||
681 | if (control_read(file, pkg) == EXIT_FAILURE) { | ||
682 | return EXIT_FAILURE; | ||
683 | } | ||
684 | |||
685 | return EXIT_SUCCESS; | 671 | return EXIT_SUCCESS; |
686 | } | 672 | } |
687 | 673 | ||
@@ -691,15 +677,12 @@ static int dpkg_unpack(package_t *pkgs, void *status) | |||
691 | package_t *pkg; | 677 | package_t *pkg; |
692 | 678 | ||
693 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { | 679 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { |
694 | if (dpkg_unpackcontrol(pkg) == EXIT_FAILURE) { | 680 | dpkg_read_control(pkg); |
695 | return EXIT_FAILURE; | ||
696 | } | ||
697 | if ((r = dpkg_dounpack(pkg)) != 0 ) { | 681 | if ((r = dpkg_dounpack(pkg)) != 0 ) { |
698 | break; | 682 | break; |
699 | } | 683 | } |
700 | } | 684 | } |
701 | status_merge(status, pkgs); | 685 | status_merge(status, pkgs); |
702 | remove_dir(dpkgcidir); | ||
703 | 686 | ||
704 | return r; | 687 | return r; |
705 | } | 688 | } |
@@ -735,9 +718,7 @@ static int dpkg_install(package_t *pkgs, void *status) | |||
735 | 718 | ||
736 | /* Stage 1: parse all the control information */ | 719 | /* Stage 1: parse all the control information */ |
737 | for (p = pkgs; p != 0; p = p->next) { | 720 | for (p = pkgs; p != 0; p = p->next) { |
738 | if (dpkg_unpackcontrol(p) == EXIT_FAILURE) { | 721 | dpkg_read_control(p); |
739 | return(EXIT_FAILURE); | ||
740 | } | ||
741 | } | 722 | } |
742 | 723 | ||
743 | /* Stage 2: resolve dependencies */ | 724 | /* Stage 2: resolve dependencies */ |
@@ -749,27 +730,26 @@ static int dpkg_install(package_t *pkgs, void *status) | |||
749 | 730 | ||
750 | /* Stage 3: install */ | 731 | /* Stage 3: install */ |
751 | for (p = ordered; p != 0; p = p->next) { | 732 | for (p = ordered; p != 0; p = p->next) { |
752 | p->status_want = status_want_install; | 733 | p->state_want = state_want_install; |
753 | 734 | ||
754 | /* for now the flag is always set to ok... this is probably | 735 | /* for now the flag is always set to ok... this is probably |
755 | * not what we want | 736 | * not what we want |
756 | */ | 737 | */ |
757 | p->status_flag = status_flag_ok; | 738 | p->state_flag = state_flag_ok; |
758 | 739 | ||
759 | DPRINTF("Installing %s\n", p->package); | 740 | DPRINTF("Installing %s\n", p->package); |
760 | if (dpkg_dounpack(p) != 0) { | 741 | if (dpkg_dounpack(p) != 0) { |
761 | perror_msg(p->file); | 742 | perror_msg(p->filename); |
762 | } | 743 | } |
763 | 744 | ||
764 | if (dpkg_doconfigure(p) != 0) { | 745 | if (dpkg_doconfigure(p) != 0) { |
765 | perror_msg(p->file); | 746 | perror_msg(p->filename); |
766 | } | 747 | } |
767 | } | 748 | } |
768 | 749 | ||
769 | if (ordered != 0) { | 750 | if (ordered != 0) { |
770 | status_merge(status, pkgs); | 751 | status_merge(status, pkgs); |
771 | } | 752 | } |
772 | remove_dir(dpkgcidir); | ||
773 | 753 | ||
774 | return 0; | 754 | return 0; |
775 | } | 755 | } |
@@ -822,7 +802,7 @@ extern int dpkg_main(int argc, char **argv) | |||
822 | if (optflag & arg_configure) { | 802 | if (optflag & arg_configure) { |
823 | p->package = xstrdup(argv[optind]); | 803 | p->package = xstrdup(argv[optind]); |
824 | } else { | 804 | } else { |
825 | p->file = xstrdup(argv[optind]); | 805 | p->filename = xstrdup(argv[optind]); |
826 | } | 806 | } |
827 | p->next = packages; | 807 | p->next = packages; |
828 | packages = p; | 808 | packages = p; |
@@ -830,7 +810,6 @@ extern int dpkg_main(int argc, char **argv) | |||
830 | optind++; | 810 | optind++; |
831 | } | 811 | } |
832 | 812 | ||
833 | create_path(dpkgcidir, S_IRWXU); | ||
834 | create_path(infodir, S_IRWXU); | 813 | create_path(infodir, S_IRWXU); |
835 | 814 | ||
836 | status = status_read(); | 815 | status = status_read(); |
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index 7c5a5de58..d08882885 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c | |||
@@ -15,12 +15,14 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <stdlib.h> | 17 | #include <stdlib.h> |
18 | #include <string.h> | ||
18 | #include <getopt.h> | 19 | #include <getopt.h> |
19 | #include "busybox.h" | 20 | #include "busybox.h" |
20 | 21 | ||
21 | extern int dpkg_deb_main(int argc, char **argv) | 22 | extern int dpkg_deb_main(int argc, char **argv) |
22 | { | 23 | { |
23 | char *argument = NULL; | 24 | char *argument = NULL; |
25 | char *output_buffer = NULL; | ||
24 | int opt = 0; | 26 | int opt = 0; |
25 | int optflag = 0; | 27 | int optflag = 0; |
26 | 28 | ||
@@ -86,7 +88,22 @@ extern int dpkg_deb_main(int argc, char **argv) | |||
86 | default: | 88 | default: |
87 | } | 89 | } |
88 | 90 | ||
89 | deb_extract(argv[optind], optflag, argument); | 91 | output_buffer = deb_extract(argv[optind], optflag, argument, NULL); |
92 | |||
93 | if (optflag & extract_field) { | ||
94 | char *field = NULL; | ||
95 | int field_length = 0; | ||
96 | int field_start = 0; | ||
97 | |||
98 | while ((field = read_package_field(&output_buffer[field_start])) != NULL) { | ||
99 | field_length = strlen(field); | ||
100 | field_start += (field_length + 1); | ||
101 | if (strstr(field, argument) == field) { | ||
102 | printf("%s\n", field + strlen(argument) + 2); | ||
103 | } | ||
104 | free(field); | ||
105 | } | ||
106 | } | ||
90 | 107 | ||
91 | return(EXIT_SUCCESS); | 108 | return(EXIT_SUCCESS); |
92 | } | 109 | } |
@@ -20,7 +20,7 @@ | |||
20 | #define DODEPENDS 1 | 20 | #define DODEPENDS 1 |
21 | 21 | ||
22 | /* Should we do debugging? */ | 22 | /* Should we do debugging? */ |
23 | //#define DODEBUG 1 | 23 | #define DODEBUG 0 |
24 | 24 | ||
25 | #ifdef DODEBUG | 25 | #ifdef DODEBUG |
26 | #define SYSTEM(x) do_system(x) | 26 | #define SYSTEM(x) do_system(x) |
@@ -32,63 +32,68 @@ | |||
32 | 32 | ||
33 | /* from dpkg-deb.c */ | 33 | /* from dpkg-deb.c */ |
34 | 34 | ||
35 | static const int dpkg_deb_contents = 1; | ||
36 | static const int dpkg_deb_control = 2; | ||
37 | // const int dpkg_deb_info = 4; | ||
38 | static const int dpkg_deb_extract = 8; | ||
39 | static const int dpkg_deb_verbose_extract = 16; | ||
40 | static const int dpkg_deb_list = 32; | ||
41 | |||
42 | static const char statusfile[] = "/var/lib/dpkg/status.udeb"; | 35 | static const char statusfile[] = "/var/lib/dpkg/status.udeb"; |
43 | static const char new_statusfile[] = "/var/lib/dpkg/status.udeb.new"; | 36 | static const char new_statusfile[] = "/var/lib/dpkg/status.udeb.new"; |
44 | static const char bak_statusfile[] = "/var/lib/dpkg/status.udeb.bak"; | 37 | static const char bak_statusfile[] = "/var/lib/dpkg/status.udeb.bak"; |
45 | 38 | ||
46 | static const char dpkgcidir[] = "/var/lib/dpkg/tmp.ci/"; | ||
47 | |||
48 | static const char infodir[] = "/var/lib/dpkg/info/"; | 39 | static const char infodir[] = "/var/lib/dpkg/info/"; |
49 | static const char udpkg_quiet[] = "UDPKG_QUIET"; | 40 | static const char udpkg_quiet[] = "UDPKG_QUIET"; |
50 | 41 | ||
51 | //static const int status_want_unknown = 1; | 42 | //static const int status_want_unknown = 1; |
52 | static const int status_want_install = 2; | 43 | static const int state_want_install = 2; |
53 | //static const int status_want_hold = 3; | 44 | //static const int state_want_hold = 3; |
54 | //static const int status_want_deinstall = 4; | 45 | //static const int state_want_deinstall = 4; |
55 | //static const int status_want_purge = 5; | 46 | //static const int state_want_purge = 5; |
56 | 47 | ||
57 | static const int status_flag_ok = 1; | 48 | static const int state_flag_ok = 1; |
58 | //static const int status_flag_reinstreq = 2; | 49 | //static const int state_flag_reinstreq = 2; |
59 | //static const int status_flag_hold = 3; | 50 | //static const int state_flag_hold = 3; |
60 | //static const int status_flag_holdreinstreq = 4; | 51 | //static const int state_flag_holdreinstreq = 4; |
61 | 52 | ||
62 | //static const int status_statusnoninstalled = 1; | 53 | //static const int state_statusnoninstalled = 1; |
63 | static const int status_status_unpacked = 2; | 54 | static const int state_status_unpacked = 2; |
64 | static const int status_status_halfconfigured = 3; | 55 | static const int state_status_halfconfigured = 3; |
65 | static const int status_status_installed = 4; | 56 | static const int state_status_installed = 4; |
66 | static const int status_status_halfinstalled = 5; | 57 | static const int state_status_halfinstalled = 5; |
67 | //static const int status_statusconfigfiles = 6; | 58 | //static const int state_statusconfigfiles = 6; |
68 | //static const int status_statuspostinstfailed = 7; | 59 | //static const int state_statuspostinstfailed = 7; |
69 | //static const int status_statusremovalfailed = 8; | 60 | //static const int state_statusremovalfailed = 8; |
70 | 61 | ||
71 | static const char *status_words_want[] = { "unknown", "install", "hold", "deinstall", "purge", 0 }; | 62 | static const char *state_words_want[] = { "unknown", "install", "hold", "deinstall", "purge", 0 }; |
72 | static const char *status_words_flag[] = { "ok", "reinstreq", "hold", "hold-reinstreq", 0 }; | 63 | static const char *state_words_flag[] = { "ok", "reinstreq", "hold", "hold-reinstreq", 0 }; |
73 | static const char *status_words_status[] = { "not-installed", "unpacked", "half-configured", "installed", | 64 | static const char *state_words_status[] = { "not-installed", "unpacked", "half-configured", "installed", |
74 | "half-installed", "config-files", "post-inst-failed", "removal-failed", 0 }; | 65 | "half-installed", "config-files", "post-inst-failed", "removal-failed", 0 }; |
75 | 66 | ||
76 | static const int color_white = 0; | 67 | static const int color_white = 0; |
77 | static const int color_grey = 1; | 68 | static const int color_grey = 1; |
78 | static const int color_black = 2; | 69 | static const int color_black = 2; |
79 | 70 | ||
80 | /* data structures */ | 71 | /* data structures */ |
81 | typedef struct package_s { | 72 | typedef struct package_s { |
82 | char *file; | 73 | char *filename; |
83 | char *package; | 74 | char *package; |
84 | char *version; | 75 | unsigned char state_want; |
76 | unsigned char state_flag; | ||
77 | unsigned char state_status; | ||
85 | char *depends; | 78 | char *depends; |
86 | char *provides; | 79 | char *provides; |
87 | char *description; | 80 | char *description; |
81 | char *priority; | ||
82 | char *section; | ||
83 | char *installed_size; | ||
84 | char *maintainer; | ||
85 | char *source; | ||
86 | char *version; | ||
87 | char *pre_depends; | ||
88 | char *replaces; | ||
89 | char *recommends; | ||
90 | char *suggests; | ||
91 | char *conflicts; | ||
92 | char *conffiles; | ||
93 | char *long_description; | ||
94 | char *architecture; | ||
95 | char *md5sum; | ||
88 | int installer_menu_item; | 96 | int installer_menu_item; |
89 | unsigned char status_want; | ||
90 | unsigned char status_flag; | ||
91 | unsigned char status_status; | ||
92 | char color; /* for topo-sort */ | 97 | char color; /* for topo-sort */ |
93 | struct package_s *requiredfor[DEPENDSMAX]; | 98 | struct package_s *requiredfor[DEPENDSMAX]; |
94 | unsigned short requiredcount; | 99 | unsigned short requiredcount; |
@@ -265,8 +270,8 @@ static package_t *depends_resolve(package_t *pkgs, void *status) | |||
265 | /* Check for dependencies; first look for installed packages */ | 270 | /* Check for dependencies; first look for installed packages */ |
266 | dependpkg.package = dependsvec[i]; | 271 | dependpkg.package = dependsvec[i]; |
267 | if (((found = tfind(&dependpkg, &status, package_compare)) == 0) || | 272 | if (((found = tfind(&dependpkg, &status, package_compare)) == 0) || |
268 | ((chk = *(package_t **)found) && (chk->status_flag & status_flag_ok) && | 273 | ((chk = *(package_t **)found) && (chk->state_flag & state_flag_ok) && |
269 | (chk->status_status & status_status_installed))) { | 274 | (chk->state_status & state_status_installed))) { |
270 | 275 | ||
271 | /* if it fails, we look through the list of packages we are going to | 276 | /* if it fails, we look through the list of packages we are going to |
272 | * install */ | 277 | * install */ |
@@ -328,47 +333,100 @@ static unsigned char status_parse(const char *line, const char **status_words) | |||
328 | } | 333 | } |
329 | 334 | ||
330 | /* | 335 | /* |
331 | * Read a control file (or a stanza of a status file) and parse it, | 336 | * Read the buffered control file and parse it, |
332 | * filling parsed fields into the package structure | 337 | * filling parsed fields into the package structure |
333 | */ | 338 | */ |
334 | static int control_read(FILE *file, package_t *p) | 339 | static int fill_package_struct(package_t *package, const char *package_buffer) |
335 | { | 340 | { |
336 | char *line; | 341 | char *field = NULL; |
337 | 342 | int field_start = 0; | |
338 | while ((line = get_line_from_file(file)) != NULL) { | 343 | int field_length = 0; |
339 | line[strlen(line) - 1] = '\0'; | 344 | while ((field = read_package_field(&package_buffer[field_start])) != NULL) { |
340 | 345 | field_length = strlen(field); | |
341 | if (strlen(line) == 0) { | 346 | field_start += (field_length + 1); |
347 | |||
348 | if (strlen(field) == 0) { | ||
349 | printf("empty line: *this shouldnt happen i dont think*\n"); | ||
342 | break; | 350 | break; |
343 | } | 351 | } |
344 | else if (strstr(line, "Package: ") == line) { | 352 | |
345 | p->package = xstrdup(line + 9); | 353 | /* these are common to both installed and uninstalled packages */ |
346 | } | 354 | if (strstr(field, "Package: ") == field) { |
347 | else if (strstr(line, "Status: ") == line) { | 355 | package->package = strdup(field + 9); |
348 | char *word_pointer; | ||
349 | word_pointer = strchr(line, ' ') + 1; | ||
350 | p->status_want = status_parse(word_pointer, status_words_want); | ||
351 | word_pointer = strchr(word_pointer, ' ') + 1; | ||
352 | p->status_flag = status_parse(word_pointer, status_words_flag); | ||
353 | word_pointer = strchr(word_pointer, ' ') + 1; | ||
354 | p->status_status = status_parse(word_pointer, status_words_status); | ||
355 | } | 356 | } |
356 | else if (strstr(line, "Depends: ") == line) { | 357 | else if (strstr(field, "Depends: ") == field) { |
357 | p->depends = xstrdup(line + 9); | 358 | package->depends = strdup(field + 9); |
358 | } | 359 | } |
359 | else if (strstr(line, "Provides: ") == line) { | 360 | else if (strstr(field, "Provides: ") == field) { |
360 | p->provides = xstrdup(line + 10); | 361 | package->provides = strdup(field + 10); |
361 | } | 362 | } |
362 | else if (strstr(line, "Description: ") == line) { | ||
363 | p->description = xstrdup(line + 13); | ||
364 | /* This is specific to the Debian Installer. Ifdef? */ | 363 | /* This is specific to the Debian Installer. Ifdef? */ |
364 | else if (strstr(field, "installer-menu-item: ") == field) { | ||
365 | package->installer_menu_item = atoi(field + 21); | ||
366 | } | ||
367 | else if (strstr(field, "Description: ") == field) { | ||
368 | package->description = strdup(field + 13); | ||
369 | } | ||
370 | else if (strstr(field, "Priority: ") == field) { | ||
371 | package->priority = strdup(field + 10); | ||
372 | } | ||
373 | else if (strstr(field, "Section: ") == field) { | ||
374 | package->section = strdup(field + 9); | ||
375 | } | ||
376 | else if (strstr(field, "Installed-Size: ") == field) { | ||
377 | package->installed_size = strdup(field + 16); | ||
378 | } | ||
379 | else if (strstr(field, "Maintainer: ") == field) { | ||
380 | package->maintainer = strdup(field + 12); | ||
381 | } | ||
382 | else if (strstr(field, "Version: ") == field) { | ||
383 | package->version = strdup(field + 9); | ||
365 | } | 384 | } |
366 | else if (strstr(line, "installer-menu-item: ") == line) { | 385 | else if (strstr(field, "Suggests: ") == field) { |
367 | p->installer_menu_item = atoi(line + 21); | 386 | package->suggests = strdup(field + 10); |
368 | } | 387 | } |
369 | /* TODO: localized descriptions */ | 388 | else if (strstr(field, "Recommends: ") == field) { |
389 | package->recommends = strdup(field + 12); | ||
390 | } | ||
391 | /* else if (strstr(field, "Conffiles: ") == field) { | ||
392 | package->conffiles = read_block(file); | ||
393 | package->conffiles = xcalloc(1, 1); | ||
394 | while ((field = strtok(NULL, "\n")) != NULL) { | ||
395 | package->long_description = xrealloc(package->conffiles, | ||
396 | strlen(package->conffiles) + strlen(field) + 1); | ||
397 | strcat(package->conffiles, field); | ||
398 | } | ||
399 | } | ||
400 | */ | ||
401 | /* These are only in available file */ | ||
402 | else if (strstr(field, "Architecture: ") == field) { | ||
403 | package->architecture = strdup(field + 14); | ||
404 | } | ||
405 | else if (strstr(field, "Filename: ") == field) { | ||
406 | package->filename = strdup(field + 10); | ||
407 | } | ||
408 | else if (strstr(field, "MD5sum ") == field) { | ||
409 | package->md5sum = strdup(field + 7); | ||
410 | } | ||
411 | |||
412 | /* This is only needed for status file */ | ||
413 | if (strstr(field, "Status: ") == field) { | ||
414 | char *word_pointer; | ||
415 | |||
416 | word_pointer = strchr(field, ' ') + 1; | ||
417 | package->state_want = status_parse(word_pointer, state_words_want); | ||
418 | word_pointer = strchr(word_pointer, ' ') + 1; | ||
419 | package->state_flag = status_parse(word_pointer, state_words_flag); | ||
420 | word_pointer = strchr(word_pointer, ' ') + 1; | ||
421 | package->state_status = status_parse(word_pointer, state_words_status); | ||
422 | } else { | ||
423 | package->state_want = status_parse("purge", state_words_want); | ||
424 | package->state_flag = status_parse("ok", state_words_flag); | ||
425 | package->state_status = status_parse("not-installed", state_words_status); | ||
426 | } | ||
427 | |||
428 | free(field); | ||
370 | } | 429 | } |
371 | free(line); | ||
372 | return EXIT_SUCCESS; | 430 | return EXIT_SUCCESS; |
373 | } | 431 | } |
374 | 432 | ||
@@ -377,6 +435,7 @@ static void *status_read(void) | |||
377 | FILE *f; | 435 | FILE *f; |
378 | void *status = 0; | 436 | void *status = 0; |
379 | package_t *m = 0, *p = 0, *t = 0; | 437 | package_t *m = 0, *p = 0, *t = 0; |
438 | char *package_control_buffer = NULL; | ||
380 | 439 | ||
381 | if (getenv(udpkg_quiet) == NULL) { | 440 | if (getenv(udpkg_quiet) == NULL) { |
382 | printf("(Reading database...)\n"); | 441 | printf("(Reading database...)\n"); |
@@ -386,9 +445,11 @@ static void *status_read(void) | |||
386 | return(NULL); | 445 | return(NULL); |
387 | } | 446 | } |
388 | 447 | ||
389 | while (!feof(f)) { | 448 | while ( (package_control_buffer = read_text_file_to_buffer(f)) != NULL) { |
390 | m = (package_t *)xcalloc(1, sizeof(package_t)); | 449 | m = (package_t *)xcalloc(1, sizeof(package_t)); |
391 | control_read(f, m); | 450 | printf("read buffer [%s]\n", package_control_buffer); |
451 | fill_package_struct(m, package_control_buffer); | ||
452 | printf("package is [%s]\n", m->package); | ||
392 | if (m->package) { | 453 | if (m->package) { |
393 | /* | 454 | /* |
394 | * If there is an item in the tree by this name, | 455 | * If there is an item in the tree by this name, |
@@ -418,9 +479,9 @@ static void *status_read(void) | |||
418 | * packages of different statuses | 479 | * packages of different statuses |
419 | * provide it). | 480 | * provide it). |
420 | */ | 481 | */ |
421 | t->status_want = m->status_want; | 482 | t->state_want = m->state_want; |
422 | t->status_flag = m->status_flag; | 483 | t->state_flag = m->state_flag; |
423 | t->status_status = m->status_status; | 484 | t->state_status = m->state_status; |
424 | } | 485 | } |
425 | } | 486 | } |
426 | } | 487 | } |
@@ -428,6 +489,7 @@ static void *status_read(void) | |||
428 | free(m); | 489 | free(m); |
429 | } | 490 | } |
430 | } | 491 | } |
492 | printf("done\n"); | ||
431 | fclose(f); | 493 | fclose(f); |
432 | return status; | 494 | return status; |
433 | } | 495 | } |
@@ -479,9 +541,9 @@ static int status_merge(void *status, package_t *pkgs) | |||
479 | } | 541 | } |
480 | if (strstr(line, "Status: ") == line && statpkg != 0) { | 542 | if (strstr(line, "Status: ") == line && statpkg != 0) { |
481 | snprintf(line, sizeof(line), "Status: %s %s %s", | 543 | snprintf(line, sizeof(line), "Status: %s %s %s", |
482 | status_words_want[statpkg->status_want - 1], | 544 | state_words_want[statpkg->state_want - 1], |
483 | status_words_flag[statpkg->status_flag - 1], | 545 | state_words_flag[statpkg->state_flag - 1], |
484 | status_words_status[statpkg->status_status - 1]); | 546 | state_words_status[statpkg->state_status - 1]); |
485 | } | 547 | } |
486 | fprintf(fout, "%s\n", line); | 548 | fprintf(fout, "%s\n", line); |
487 | } | 549 | } |
@@ -492,9 +554,9 @@ static int status_merge(void *status, package_t *pkgs) | |||
492 | // Print out packages we processed. | 554 | // Print out packages we processed. |
493 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { | 555 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { |
494 | fprintf(fout, "Package: %s\nStatus: %s %s %s\n", | 556 | fprintf(fout, "Package: %s\nStatus: %s %s %s\n", |
495 | pkg->package, status_words_want[pkg->status_want - 1], | 557 | pkg->package, state_words_want[pkg->state_want - 1], |
496 | status_words_flag[pkg->status_flag - 1], | 558 | state_words_flag[pkg->state_flag - 1], |
497 | status_words_status[pkg->status_status - 1]); | 559 | state_words_status[pkg->state_status - 1]); |
498 | 560 | ||
499 | if (pkg->depends) | 561 | if (pkg->depends) |
500 | fprintf(fout, "Depends: %s\n", pkg->depends); | 562 | fprintf(fout, "Depends: %s\n", pkg->depends); |
@@ -544,144 +606,68 @@ static int dpkg_doconfigure(package_t *pkg) | |||
544 | char buf[1024]; | 606 | char buf[1024]; |
545 | 607 | ||
546 | DPRINTF("Configuring %s\n", pkg->package); | 608 | DPRINTF("Configuring %s\n", pkg->package); |
547 | pkg->status_status = 0; | 609 | pkg->state_status = 0; |
548 | snprintf(postinst, sizeof(postinst), "%s%s.postinst", infodir, pkg->package); | 610 | snprintf(postinst, sizeof(postinst), "%s%s.postinst", infodir, pkg->package); |
549 | 611 | ||
550 | if (is_file(postinst)) { | 612 | if (is_file(postinst)) { |
551 | snprintf(buf, sizeof(buf), "%s configure", postinst); | 613 | snprintf(buf, sizeof(buf), "%s configure", postinst); |
552 | if ((r = do_system(buf)) != 0) { | 614 | if ((r = do_system(buf)) != 0) { |
553 | error_msg("postinst exited with status %d\n", r); | 615 | error_msg("postinst exited with status %d\n", r); |
554 | pkg->status_status = status_status_halfconfigured; | 616 | pkg->state_status = state_status_halfconfigured; |
555 | return 1; | 617 | return 1; |
556 | } | 618 | } |
557 | } | 619 | } |
558 | pkg->status_status = status_status_installed; | 620 | pkg->state_status = state_status_installed; |
559 | 621 | ||
560 | return 0; | 622 | return 0; |
561 | } | 623 | } |
562 | 624 | ||
563 | static int dpkg_dounpack(package_t *pkg) | 625 | static int dpkg_dounpack(package_t *pkg) |
564 | { | 626 | { |
565 | int r = 0, i; | 627 | int r = 0; |
566 | int status = TRUE; | 628 | int status = TRUE; |
567 | char *cwd = xgetcwd(0); | 629 | char *lst_path; |
568 | char *src_filename = NULL; | ||
569 | char *dst_filename = NULL; | ||
570 | // char *lst_file = NULL; | ||
571 | char *adminscripts[] = { "prerm", "postrm", "preinst", "postinst", | ||
572 | "conffiles", "md5sums", "shlibs", "templates" }; | ||
573 | 630 | ||
574 | DPRINTF("Unpacking %s\n", pkg->package); | 631 | DPRINTF("Unpacking %s\n", pkg->package); |
575 | 632 | ||
576 | if(cwd==NULL) | 633 | /* extract the data file */ |
577 | exit(EXIT_FAILURE); | 634 | deb_extract(pkg->filename, extract_extract, "/", NULL); |
578 | chdir("/"); | ||
579 | deb_extract(pkg->file, dpkg_deb_extract, "/"); | ||
580 | 635 | ||
581 | /* Installs the package scripts into the info directory */ | 636 | /* extract the control files */ |
582 | for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) { | 637 | deb_extract(pkg->filename, extract_control, infodir, pkg->package); |
583 | struct stat src_stat_buf; | ||
584 | FILE *src_file = NULL, *dst_file = NULL; | ||
585 | 638 | ||
586 | /* The full path of the current location of the admin file */ | 639 | /* Create the list file */ |
587 | src_filename = xrealloc(src_filename, strlen(dpkgcidir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); | 640 | lst_path = xmalloc(strlen(infodir) + strlen(pkg->package) + 6); |
588 | sprintf(src_filename, "%s%s/%s", dpkgcidir, pkg->package, adminscripts[i]); | 641 | strcpy(lst_path, infodir); |
642 | strcat(lst_path, pkg->package); | ||
643 | strcat(lst_path, ".list"); | ||
644 | deb_extract(pkg->filename, extract_contents_to_file, lst_path, NULL); | ||
589 | 645 | ||
590 | /* the full path of where we want the file to be copied to */ | 646 | pkg->state_want = state_want_install; |
591 | dst_filename = xrealloc(dst_filename, strlen(infodir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); | 647 | pkg->state_flag = state_flag_ok; |
592 | sprintf(dst_filename, "%s%s.%s", infodir, pkg->package, adminscripts[i]); | ||
593 | |||
594 | /* | ||
595 | * copy admin file to permanent home | ||
596 | * NOTE: Maybe merge this behaviour into libb/copy_file.c | ||
597 | */ | ||
598 | if (lstat(src_filename, &src_stat_buf) == 0) { | ||
599 | if ((src_file = wfopen(src_filename, "r")) != NULL) { | ||
600 | if ((dst_file = wfopen(dst_filename, "w")) == NULL) { | ||
601 | status = FALSE; | ||
602 | perror_msg("Opening %s", dst_filename); | ||
603 | } | ||
604 | copy_file_chunk(src_file, dst_file, src_stat_buf.st_size); | ||
605 | fclose(src_file); | ||
606 | fclose(dst_file); | ||
607 | } else { | ||
608 | status = FALSE; | ||
609 | error_msg("couldnt open [%s]\n", src_filename); | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | /* | ||
615 | * create the list file | ||
616 | * FIXME: currently this dumps the lst to stdout instead of a file | ||
617 | */ | ||
618 | /* lst_file = (char *) xmalloc(strlen(infodir) + strlen(pkg->package) + 6); | ||
619 | strcpy(lst_file, infodir); | ||
620 | strcat(lst_file, pkg->package); | ||
621 | strcat(lst_file, ".list"); | ||
622 | deb_extract(dpkg_deb_list, NULL, pkg->file); | ||
623 | */ | ||
624 | |||
625 | pkg->status_want = status_want_install; | ||
626 | pkg->status_flag = status_flag_ok; | ||
627 | 648 | ||
628 | if (status == TRUE) { | 649 | if (status == TRUE) { |
629 | pkg->status_status = status_status_unpacked; | 650 | pkg->state_status = state_status_unpacked; |
630 | } else { | 651 | } else { |
631 | pkg->status_status = status_status_halfinstalled; | 652 | pkg->state_status = state_status_halfinstalled; |
632 | } | 653 | } |
633 | 654 | ||
634 | chdir(cwd); | ||
635 | return r; | 655 | return r; |
636 | } | 656 | } |
637 | 657 | ||
638 | /* | 658 | /* |
639 | * Extract and parse the control.tar.gz from the specified package | 659 | * Extract and parse the control file from control.tar.gz |
640 | */ | 660 | */ |
641 | static int dpkg_unpackcontrol(package_t *pkg) | 661 | static int dpkg_read_control(package_t *pkg) |
642 | { | 662 | { |
643 | char *tmp_name; | 663 | FILE *pkg_file; |
644 | FILE *file; | 664 | char *control_buffer = NULL; |
645 | int length; | ||
646 | 665 | ||
647 | /* clean the temp directory (dpkgcidir) be recreating it */ | 666 | if ((pkg_file = wfopen(pkg->filename, "r")) == NULL) { |
648 | remove_dir(dpkgcidir); | ||
649 | if (create_path(dpkgcidir, S_IRWXU) == FALSE) { | ||
650 | return EXIT_FAILURE; | 667 | return EXIT_FAILURE; |
651 | } | 668 | } |
652 | 669 | control_buffer = deb_extract(pkg->filename, extract_field, NULL, NULL); | |
653 | /* | 670 | fill_package_struct(pkg, control_buffer); |
654 | * Get the package name from the file name, | ||
655 | * first remove the directories | ||
656 | */ | ||
657 | if ((tmp_name = strrchr(pkg->file, '/')) == NULL) { | ||
658 | tmp_name = pkg->file; | ||
659 | } else { | ||
660 | tmp_name++; | ||
661 | } | ||
662 | /* now remove trailing version numbers etc */ | ||
663 | length = strcspn(tmp_name, "_."); | ||
664 | pkg->package = (char *) xcalloc(1, length + 1); | ||
665 | /* store the package name */ | ||
666 | strncpy(pkg->package, tmp_name, length); | ||
667 | |||
668 | /* work out the full extraction path */ | ||
669 | tmp_name = (char *) xcalloc(1, strlen(dpkgcidir) + strlen(pkg->package) + 9); | ||
670 | strcpy(tmp_name, dpkgcidir); | ||
671 | strcat(tmp_name, pkg->package); | ||
672 | |||
673 | /* extract control.tar.gz to the full extraction path */ | ||
674 | deb_extract(pkg->file, dpkg_deb_control, tmp_name); | ||
675 | |||
676 | /* parse the extracted control file */ | ||
677 | strcat(tmp_name, "/control"); | ||
678 | if ((file = wfopen(tmp_name, "r")) == NULL) { | ||
679 | return EXIT_FAILURE; | ||
680 | } | ||
681 | if (control_read(file, pkg) == EXIT_FAILURE) { | ||
682 | return EXIT_FAILURE; | ||
683 | } | ||
684 | |||
685 | return EXIT_SUCCESS; | 671 | return EXIT_SUCCESS; |
686 | } | 672 | } |
687 | 673 | ||
@@ -691,15 +677,12 @@ static int dpkg_unpack(package_t *pkgs, void *status) | |||
691 | package_t *pkg; | 677 | package_t *pkg; |
692 | 678 | ||
693 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { | 679 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { |
694 | if (dpkg_unpackcontrol(pkg) == EXIT_FAILURE) { | 680 | dpkg_read_control(pkg); |
695 | return EXIT_FAILURE; | ||
696 | } | ||
697 | if ((r = dpkg_dounpack(pkg)) != 0 ) { | 681 | if ((r = dpkg_dounpack(pkg)) != 0 ) { |
698 | break; | 682 | break; |
699 | } | 683 | } |
700 | } | 684 | } |
701 | status_merge(status, pkgs); | 685 | status_merge(status, pkgs); |
702 | remove_dir(dpkgcidir); | ||
703 | 686 | ||
704 | return r; | 687 | return r; |
705 | } | 688 | } |
@@ -735,9 +718,7 @@ static int dpkg_install(package_t *pkgs, void *status) | |||
735 | 718 | ||
736 | /* Stage 1: parse all the control information */ | 719 | /* Stage 1: parse all the control information */ |
737 | for (p = pkgs; p != 0; p = p->next) { | 720 | for (p = pkgs; p != 0; p = p->next) { |
738 | if (dpkg_unpackcontrol(p) == EXIT_FAILURE) { | 721 | dpkg_read_control(p); |
739 | return(EXIT_FAILURE); | ||
740 | } | ||
741 | } | 722 | } |
742 | 723 | ||
743 | /* Stage 2: resolve dependencies */ | 724 | /* Stage 2: resolve dependencies */ |
@@ -749,27 +730,26 @@ static int dpkg_install(package_t *pkgs, void *status) | |||
749 | 730 | ||
750 | /* Stage 3: install */ | 731 | /* Stage 3: install */ |
751 | for (p = ordered; p != 0; p = p->next) { | 732 | for (p = ordered; p != 0; p = p->next) { |
752 | p->status_want = status_want_install; | 733 | p->state_want = state_want_install; |
753 | 734 | ||
754 | /* for now the flag is always set to ok... this is probably | 735 | /* for now the flag is always set to ok... this is probably |
755 | * not what we want | 736 | * not what we want |
756 | */ | 737 | */ |
757 | p->status_flag = status_flag_ok; | 738 | p->state_flag = state_flag_ok; |
758 | 739 | ||
759 | DPRINTF("Installing %s\n", p->package); | 740 | DPRINTF("Installing %s\n", p->package); |
760 | if (dpkg_dounpack(p) != 0) { | 741 | if (dpkg_dounpack(p) != 0) { |
761 | perror_msg(p->file); | 742 | perror_msg(p->filename); |
762 | } | 743 | } |
763 | 744 | ||
764 | if (dpkg_doconfigure(p) != 0) { | 745 | if (dpkg_doconfigure(p) != 0) { |
765 | perror_msg(p->file); | 746 | perror_msg(p->filename); |
766 | } | 747 | } |
767 | } | 748 | } |
768 | 749 | ||
769 | if (ordered != 0) { | 750 | if (ordered != 0) { |
770 | status_merge(status, pkgs); | 751 | status_merge(status, pkgs); |
771 | } | 752 | } |
772 | remove_dir(dpkgcidir); | ||
773 | 753 | ||
774 | return 0; | 754 | return 0; |
775 | } | 755 | } |
@@ -822,7 +802,7 @@ extern int dpkg_main(int argc, char **argv) | |||
822 | if (optflag & arg_configure) { | 802 | if (optflag & arg_configure) { |
823 | p->package = xstrdup(argv[optind]); | 803 | p->package = xstrdup(argv[optind]); |
824 | } else { | 804 | } else { |
825 | p->file = xstrdup(argv[optind]); | 805 | p->filename = xstrdup(argv[optind]); |
826 | } | 806 | } |
827 | p->next = packages; | 807 | p->next = packages; |
828 | packages = p; | 808 | packages = p; |
@@ -830,7 +810,6 @@ extern int dpkg_main(int argc, char **argv) | |||
830 | optind++; | 810 | optind++; |
831 | } | 811 | } |
832 | 812 | ||
833 | create_path(dpkgcidir, S_IRWXU); | ||
834 | create_path(infodir, S_IRWXU); | 813 | create_path(infodir, S_IRWXU); |
835 | 814 | ||
836 | status = status_read(); | 815 | status = status_read(); |
diff --git a/dpkg_deb.c b/dpkg_deb.c index 7c5a5de58..d08882885 100644 --- a/dpkg_deb.c +++ b/dpkg_deb.c | |||
@@ -15,12 +15,14 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <stdlib.h> | 17 | #include <stdlib.h> |
18 | #include <string.h> | ||
18 | #include <getopt.h> | 19 | #include <getopt.h> |
19 | #include "busybox.h" | 20 | #include "busybox.h" |
20 | 21 | ||
21 | extern int dpkg_deb_main(int argc, char **argv) | 22 | extern int dpkg_deb_main(int argc, char **argv) |
22 | { | 23 | { |
23 | char *argument = NULL; | 24 | char *argument = NULL; |
25 | char *output_buffer = NULL; | ||
24 | int opt = 0; | 26 | int opt = 0; |
25 | int optflag = 0; | 27 | int optflag = 0; |
26 | 28 | ||
@@ -86,7 +88,22 @@ extern int dpkg_deb_main(int argc, char **argv) | |||
86 | default: | 88 | default: |
87 | } | 89 | } |
88 | 90 | ||
89 | deb_extract(argv[optind], optflag, argument); | 91 | output_buffer = deb_extract(argv[optind], optflag, argument, NULL); |
92 | |||
93 | if (optflag & extract_field) { | ||
94 | char *field = NULL; | ||
95 | int field_length = 0; | ||
96 | int field_start = 0; | ||
97 | |||
98 | while ((field = read_package_field(&output_buffer[field_start])) != NULL) { | ||
99 | field_length = strlen(field); | ||
100 | field_start += (field_length + 1); | ||
101 | if (strstr(field, argument) == field) { | ||
102 | printf("%s\n", field + strlen(argument) + 2); | ||
103 | } | ||
104 | free(field); | ||
105 | } | ||
106 | } | ||
90 | 107 | ||
91 | return(EXIT_SUCCESS); | 108 | return(EXIT_SUCCESS); |
92 | } | 109 | } |
diff --git a/include/libbb.h b/include/libbb.h index 569ed9397..4b06ad12c 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -236,10 +236,13 @@ typedef enum extract_function_e { | |||
236 | extract_verbose_extract = 16, | 236 | extract_verbose_extract = 16, |
237 | extract_list = 32, | 237 | extract_list = 32, |
238 | extract_fsys_tarfile = 64, | 238 | extract_fsys_tarfile = 64, |
239 | extract_field = 128 | 239 | extract_field = 128, |
240 | extract_contents_to_file = 256 | ||
240 | } extract_function_t; | 241 | } extract_function_t; |
241 | extern int deb_extract(const char *package_filename, int function, char *target_dir); | 242 | extern char *deb_extract(const char *package_filename, const int function, |
242 | extern char *untar(FILE *src_tar_file, FILE *output, const int untar_function, const char *argument); | 243 | const char *argument, const char *argument2); |
244 | extern char *untar(FILE *src_tar_file, FILE *output, const int untar_function, | ||
245 | const char *argument, const char *file_prefix); | ||
243 | extern char *read_text_file_to_buffer(FILE *src_file); | 246 | extern char *read_text_file_to_buffer(FILE *src_file); |
244 | extern char *read_package_field(const char *package_buffer); | 247 | extern char *read_package_field(const char *package_buffer); |
245 | 248 | ||
diff --git a/libbb/deb_extract.c b/libbb/deb_extract.c index b95dfa4d4..36cebfa51 100644 --- a/libbb/deb_extract.c +++ b/libbb/deb_extract.c | |||
@@ -34,12 +34,13 @@ | |||
34 | * The contents of argument depend on the value of function. | 34 | * The contents of argument depend on the value of function. |
35 | * It is either a dir name or a control file or field name(see dpkg_deb.c) | 35 | * It is either a dir name or a control file or field name(see dpkg_deb.c) |
36 | */ | 36 | */ |
37 | extern int deb_extract(const char *package_filename, int function, char *argument) | 37 | extern char *deb_extract(const char *package_filename, const int function, const char *argument, const char *argument2) |
38 | { | 38 | { |
39 | 39 | ||
40 | FILE *deb_file, *uncompressed_file; | 40 | FILE *deb_file, *uncompressed_file; |
41 | ar_headers_t *headers = NULL; | 41 | ar_headers_t *headers = NULL; |
42 | char *ared_file = NULL; | 42 | char *ared_file = NULL; |
43 | char *output_buffer = NULL; | ||
43 | int gunzip_pid; | 44 | int gunzip_pid; |
44 | 45 | ||
45 | switch (function) { | 46 | switch (function) { |
@@ -61,7 +62,7 @@ extern int deb_extract(const char *package_filename, int function, char *argumen | |||
61 | /* get a linked list of all ar entries */ | 62 | /* get a linked list of all ar entries */ |
62 | if ((headers = get_ar_headers(deb_file)) == NULL) { | 63 | if ((headers = get_ar_headers(deb_file)) == NULL) { |
63 | error_msg("Couldnt get ar headers\n"); | 64 | error_msg("Couldnt get ar headers\n"); |
64 | return(EXIT_FAILURE); | 65 | return(NULL); |
65 | } | 66 | } |
66 | 67 | ||
67 | /* seek to the start of the .tar.gz file within the ar file*/ | 68 | /* seek to the start of the .tar.gz file within the ar file*/ |
@@ -75,27 +76,23 @@ extern int deb_extract(const char *package_filename, int function, char *argumen | |||
75 | if (function & extract_fsys_tarfile) { | 76 | if (function & extract_fsys_tarfile) { |
76 | copy_file_chunk(uncompressed_file, stdout, -1); | 77 | copy_file_chunk(uncompressed_file, stdout, -1); |
77 | } else { | 78 | } else { |
78 | char *output_buffer = NULL; | 79 | FILE *output; |
79 | output_buffer = untar(uncompressed_file, stdout, function, argument); | 80 | |
80 | if (function & extract_field) { | 81 | if (function & extract_contents_to_file) { |
81 | char *field = NULL; | 82 | output = wfopen(argument, "w"); |
82 | int field_length = 0; | 83 | } else { |
83 | int field_start = 0; | 84 | output = stdout; |
84 | while ((field = read_package_field(&output_buffer[field_start])) != NULL) { | ||
85 | field_length = strlen(field); | ||
86 | field_start += (field_length + 1); | ||
87 | if (strstr(field, argument) == field) { | ||
88 | printf("%s\n", field + strlen(argument) + 2); | ||
89 | } | ||
90 | free(field); | ||
91 | } | ||
92 | } | 85 | } |
93 | } | ||
94 | 86 | ||
87 | output_buffer = untar(uncompressed_file, output, function, argument, argument2); | ||
88 | if (output != stdout) { | ||
89 | fclose(output); | ||
90 | } | ||
91 | } | ||
95 | gz_close(gunzip_pid); | 92 | gz_close(gunzip_pid); |
96 | fclose(deb_file); | 93 | fclose(deb_file); |
97 | fclose(uncompressed_file); | 94 | fclose(uncompressed_file); |
98 | free(ared_file); | 95 | free(ared_file); |
99 | 96 | ||
100 | return(EXIT_SUCCESS); | 97 | return(output_buffer); |
101 | } \ No newline at end of file | 98 | } \ No newline at end of file |
diff --git a/libbb/libbb.h b/libbb/libbb.h index 569ed9397..4b06ad12c 100644 --- a/libbb/libbb.h +++ b/libbb/libbb.h | |||
@@ -236,10 +236,13 @@ typedef enum extract_function_e { | |||
236 | extract_verbose_extract = 16, | 236 | extract_verbose_extract = 16, |
237 | extract_list = 32, | 237 | extract_list = 32, |
238 | extract_fsys_tarfile = 64, | 238 | extract_fsys_tarfile = 64, |
239 | extract_field = 128 | 239 | extract_field = 128, |
240 | extract_contents_to_file = 256 | ||
240 | } extract_function_t; | 241 | } extract_function_t; |
241 | extern int deb_extract(const char *package_filename, int function, char *target_dir); | 242 | extern char *deb_extract(const char *package_filename, const int function, |
242 | extern char *untar(FILE *src_tar_file, FILE *output, const int untar_function, const char *argument); | 243 | const char *argument, const char *argument2); |
244 | extern char *untar(FILE *src_tar_file, FILE *output, const int untar_function, | ||
245 | const char *argument, const char *file_prefix); | ||
243 | extern char *read_text_file_to_buffer(FILE *src_file); | 246 | extern char *read_text_file_to_buffer(FILE *src_file); |
244 | extern char *read_package_field(const char *package_buffer); | 247 | extern char *read_package_field(const char *package_buffer); |
245 | 248 | ||
diff --git a/libbb/untar.c b/libbb/untar.c index e70032c60..a77d94f61 100644 --- a/libbb/untar.c +++ b/libbb/untar.c | |||
@@ -22,7 +22,8 @@ | |||
22 | #include <unistd.h> | 22 | #include <unistd.h> |
23 | #include "libbb.h" | 23 | #include "libbb.h" |
24 | 24 | ||
25 | extern char *untar(FILE *src_tar_file, FILE *output, const int untar_function, const char *argument) | 25 | extern char *untar(FILE *src_tar_file, FILE *output, const int untar_function, |
26 | const char *argument, const char *file_prefix) | ||
26 | { | 27 | { |
27 | typedef struct raw_tar_header { | 28 | typedef struct raw_tar_header { |
28 | char name[100]; /* 0-99 */ | 29 | char name[100]; /* 0-99 */ |
@@ -102,7 +103,21 @@ extern char *untar(FILE *src_tar_file, FILE *output, const int untar_function, c | |||
102 | next_header_offset += (512 - size % 512); | 103 | next_header_offset += (512 - size % 512); |
103 | } | 104 | } |
104 | 105 | ||
105 | if (untar_function & (extract_contents | extract_verbose_extract)) { | 106 | /* If an exclude list is specified check current file against list |
107 | if (*exclude_list != NULL) { | ||
108 | i = 0; | ||
109 | while (exclude_list[i] != 0) { | ||
110 | if (strncmp(exclude_list[i], raw_tar_header.name, strlen(raw_tar_header.name)) == 0) { | ||
111 | break; | ||
112 | } | ||
113 | i++; | ||
114 | } | ||
115 | if (exclude_list[i] != 0) { | ||
116 | continue; | ||
117 | } | ||
118 | } */ | ||
119 | |||
120 | if (untar_function & (extract_contents | extract_verbose_extract | extract_contents_to_file)) { | ||
106 | fprintf(output, "%s\n", raw_tar_header.name); | 121 | fprintf(output, "%s\n", raw_tar_header.name); |
107 | } | 122 | } |
108 | 123 | ||
@@ -123,10 +138,29 @@ extern char *untar(FILE *src_tar_file, FILE *output, const int untar_function, c | |||
123 | case (extract_extract): | 138 | case (extract_extract): |
124 | case (extract_verbose_extract): | 139 | case (extract_verbose_extract): |
125 | case (extract_control): { | 140 | case (extract_control): { |
126 | FILE *dst_file = wfopen(dir, "w"); | 141 | FILE *dst_file = NULL; |
142 | char *full_name; | ||
143 | |||
144 | if (file_prefix != NULL) { | ||
145 | char *file_name = NULL, *file_extension = NULL; | ||
146 | |||
147 | file_extension = xmalloc(strlen(raw_tar_header.name) + 1); | ||
148 | file_extension = strrchr(raw_tar_header.name, '/'); | ||
149 | file_extension++; | ||
150 | file_name = xmalloc(strlen(file_prefix) + strlen(file_extension) + 2); | ||
151 | strcpy(file_name, file_prefix); | ||
152 | strcat(file_name, "."); | ||
153 | strcat(file_name, file_extension); | ||
154 | |||
155 | full_name = concat_path_file(strndup(dir, strlen(dir) - strlen(strrchr(dir, '/'))), file_name); | ||
156 | } else { | ||
157 | full_name = xstrdup(dir); | ||
158 | } | ||
159 | dst_file = wfopen(full_name, "w"); | ||
127 | copy_file_chunk(src_tar_file, dst_file, (unsigned long long) size); | 160 | copy_file_chunk(src_tar_file, dst_file, (unsigned long long) size); |
128 | uncompressed_count += size; | 161 | uncompressed_count += size; |
129 | fclose(dst_file); | 162 | fclose(dst_file); |
163 | chmod(full_name, mode); | ||
130 | } | 164 | } |
131 | break; | 165 | break; |
132 | case (extract_info): | 166 | case (extract_info): |
@@ -136,7 +170,7 @@ extern char *untar(FILE *src_tar_file, FILE *output, const int untar_function, c | |||
136 | } | 170 | } |
137 | break; | 171 | break; |
138 | case (extract_field): | 172 | case (extract_field): |
139 | if (strstr(raw_tar_header.name, "control") != NULL) { | 173 | if (strstr(raw_tar_header.name, "./control") != NULL) { |
140 | return(read_text_file_to_buffer(src_tar_file)); | 174 | return(read_text_file_to_buffer(src_tar_file)); |
141 | } | 175 | } |
142 | break; | 176 | break; |