diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2001-02-12 11:33:09 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2001-02-12 11:33:09 +0000 |
commit | 3af1f88725348b15a0aa467b5734d55210bedf7c (patch) | |
tree | 25ab42966fbe05fbb4c55287bf5f3229ed565e1f | |
parent | dadf9c6dcd8106d120bd986ba6c1cf6ccb184565 (diff) | |
download | busybox-w32-3af1f88725348b15a0aa467b5734d55210bedf7c.tar.gz busybox-w32-3af1f88725348b15a0aa467b5734d55210bedf7c.tar.bz2 busybox-w32-3af1f88725348b15a0aa467b5734d55210bedf7c.zip |
Closer integration with dpkg-deb and other busybox functions.
Hopefully simplified some code (works for me).
-rw-r--r-- | archival/dpkg.c | 269 | ||||
-rw-r--r-- | dpkg.c | 269 |
2 files changed, 280 insertions, 258 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c index 7b4c74d7d..4a5c6f4da 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -11,18 +11,13 @@ | |||
11 | 11 | ||
12 | #include "busybox.h" | 12 | #include "busybox.h" |
13 | 13 | ||
14 | //#define PACKAGE "udpkg" | 14 | #define DEPENDSMAX 64 /* maximum number of depends we can handle */ |
15 | //#define VERSION "0.1" | ||
16 | 15 | ||
17 | /* | 16 | /* Should we do full dependency checking? */ |
18 | * Should we do full dependency checking? | ||
19 | */ | ||
20 | #define DODEPENDS 1 | 17 | #define DODEPENDS 1 |
21 | 18 | ||
22 | /* | 19 | /* Should we do debugging? */ |
23 | * Should we do debugging? | 20 | #define DODEBUG 1 |
24 | */ | ||
25 | #define DODEBUG 0 | ||
26 | 21 | ||
27 | #ifdef DODEBUG | 22 | #ifdef DODEBUG |
28 | #define SYSTEM(x) do_system(x) | 23 | #define SYSTEM(x) do_system(x) |
@@ -32,15 +27,20 @@ | |||
32 | #define DPRINTF(fmt,args...) /* nothing */ | 27 | #define DPRINTF(fmt,args...) /* nothing */ |
33 | #endif | 28 | #endif |
34 | 29 | ||
35 | #define BUFSIZE 4096 | 30 | /* from dpkg-deb.c */ |
36 | #define DEPENDSMAX 64 /* maximum number of depends we can handle */ | 31 | extern int deb_extract(int optflags, const char *dir_name, const char *deb_filename); |
32 | static const int dpkg_deb_contents = 1; | ||
33 | static const int dpkg_deb_control = 2; | ||
34 | // const int dpkg_deb_info = 4; | ||
35 | static const int dpkg_deb_extract = 8; | ||
36 | static const int dpkg_deb_verbose_extract = 16; | ||
37 | static const int dpkg_deb_list = 32; | ||
37 | 38 | ||
38 | static const char statusfile[] = "/var/lib/dpkg/status.udeb"; | 39 | static const char statusfile[] = "/var/lib/dpkg/status.udeb"; |
39 | static const char new_statusfile[] = "/var/lib/dpkg/status.udeb.new"; | 40 | static const char new_statusfile[] = "/var/lib/dpkg/status.udeb.new"; |
40 | static const char bak_statusfile[] = "/var/lib/dpkg/status.udeb.bak"; | 41 | static const char bak_statusfile[] = "/var/lib/dpkg/status.udeb.bak"; |
41 | 42 | ||
42 | static const char dpkgcidir[] = "/var/lib/dpkg/tmp.ci/"; | 43 | static const char dpkgcidir[] = "/var/lib/dpkg/tmp.ci/"; |
43 | static const char rm_dpkgcidir[] = "rm -rf /var/lib/dpkg/tmp.ci/"; | ||
44 | 44 | ||
45 | static const char infodir[] = "/var/lib/dpkg/info/"; | 45 | static const char infodir[] = "/var/lib/dpkg/info/"; |
46 | static const char udpkg_quiet[] = "UDPKG_QUIET"; | 46 | static const char udpkg_quiet[] = "UDPKG_QUIET"; |
@@ -115,6 +115,21 @@ static int package_compare(const void *p1, const void *p2) | |||
115 | ((package_t *)p2)->package); | 115 | ((package_t *)p2)->package); |
116 | } | 116 | } |
117 | 117 | ||
118 | static int remove_dpkgcidir() | ||
119 | { | ||
120 | char *rm_dpkgcidir = NULL; | ||
121 | |||
122 | rm_dpkgcidir = (char *) xmalloc(strlen(dpkgcidir) + 8); | ||
123 | strcpy(rm_dpkgcidir, "rm -rf "); | ||
124 | strcat(rm_dpkgcidir, dpkgcidir); | ||
125 | |||
126 | if (SYSTEM(rm_dpkgcidir) != 0) { | ||
127 | perror("mkdir "); | ||
128 | return EXIT_FAILURE; | ||
129 | } | ||
130 | return EXIT_SUCCESS; | ||
131 | } | ||
132 | |||
118 | #ifdef DODEPENDS | 133 | #ifdef DODEPENDS |
119 | #include <ctype.h> | 134 | #include <ctype.h> |
120 | 135 | ||
@@ -342,7 +357,7 @@ static const char *status_print(unsigned long flags) | |||
342 | * Read a control file (or a stanza of a status file) and parse it, | 357 | * Read a control file (or a stanza of a status file) and parse it, |
343 | * filling parsed fields into the package structure | 358 | * filling parsed fields into the package structure |
344 | */ | 359 | */ |
345 | static void control_read(FILE *file, package_t *p) | 360 | static int control_read(FILE *file, package_t *p) |
346 | { | 361 | { |
347 | char *line; | 362 | char *line; |
348 | 363 | ||
@@ -374,6 +389,7 @@ static void control_read(FILE *file, package_t *p) | |||
374 | /* TODO: localized descriptions */ | 389 | /* TODO: localized descriptions */ |
375 | } | 390 | } |
376 | free(line); | 391 | free(line); |
392 | return EXIT_SUCCESS; | ||
377 | } | 393 | } |
378 | 394 | ||
379 | static void *status_read(void) | 395 | static void *status_read(void) |
@@ -558,62 +574,52 @@ static int dpkg_doconfigure(package_t *pkg) | |||
558 | static int dpkg_dounpack(package_t *pkg) | 574 | static int dpkg_dounpack(package_t *pkg) |
559 | { | 575 | { |
560 | int r = 0, i; | 576 | int r = 0, i; |
561 | char *cwd, *p; | 577 | char *cwd; |
562 | FILE *infp, *outfp; | 578 | FILE *outfp; |
579 | char *src_file = NULL; | ||
580 | char *dst_file = NULL; | ||
581 | char *lst_file = NULL; | ||
582 | char *adminscripts[] = { "/prerm", "/postrm", "/preinst", "/postinst", | ||
583 | "/conffiles", "/md5sums", "/shlibs", "/templates" }; | ||
563 | char buf[1024], buf2[1024]; | 584 | char buf[1024], buf2[1024]; |
564 | char *adminscripts[] = { "prerm", "postrm", "preinst", "postinst", | ||
565 | "conffiles", "md5sums", "shlibs", "templates" }; | ||
566 | 585 | ||
567 | DPRINTF("Unpacking %s\n", pkg->package); | 586 | DPRINTF("Unpacking %s\n", pkg->package); |
568 | 587 | ||
569 | cwd = getcwd(0, 0); | 588 | cwd = getcwd(0, 0); |
570 | chdir("/"); | 589 | chdir("/"); |
571 | snprintf(buf, sizeof(buf), "ar -p %s data.tar.gz|zcat|tar -xf -", pkg->file); | 590 | deb_extract(dpkg_deb_extract, "/", pkg->file); |
572 | if (SYSTEM(buf) != 0) { | 591 | |
573 | goto end; | ||
574 | } | ||
575 | /* Installs the package scripts into the info directory */ | 592 | /* Installs the package scripts into the info directory */ |
576 | for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) { | 593 | for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) { |
577 | snprintf(buf, sizeof(buf), "%s%s/%s", | 594 | /* The full path of the current location of the admin file */ |
578 | dpkgcidir, pkg->package, adminscripts[i]); | 595 | src_file = xrealloc(src_file, strlen(dpkgcidir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); |
579 | snprintf(buf2, sizeof(buf), "%s%s.%s", | 596 | strcpy(src_file, dpkgcidir); |
580 | infodir, pkg->package, adminscripts[i]); | 597 | strcat(src_file, pkg->package); |
581 | if (copy_file(buf, buf2, TRUE, FALSE, FALSE) < 0) { | 598 | strcat(src_file, adminscripts[i]); |
582 | fprintf(stderr, "Cannot copy %s to %s: %s\n", | 599 | |
583 | buf, buf2, strerror(errno)); | 600 | /* the full path of where we want the file to be copied to */ |
584 | r = 1; | 601 | dst_file = xrealloc(dst_file, strlen(infodir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); |
585 | break; | 602 | strcpy(dst_file, infodir); |
603 | strcat(dst_file, pkg->package); | ||
604 | strcat(dst_file, adminscripts[i]); | ||
605 | |||
606 | /* copy admin file to permanent home */ | ||
607 | if (copy_file(src_file, dst_file, TRUE, FALSE, FALSE) < 0) { | ||
608 | error_msg_and_die("Cannot copy %s to %s ", buf, buf2); | ||
586 | } | 609 | } |
587 | /* ugly hack to create the list file; should | 610 | |
588 | * probably do something more elegant | 611 | /* create the list file */ |
589 | * | 612 | lst_file = (char *) malloc(strlen(infodir) + strlen(pkg->package) + 6); |
590 | * why oh why does dpkg create the list file | 613 | strcpy(lst_file, infodir); |
591 | * so oddly... | 614 | strcat(lst_file, pkg->package); |
592 | */ | 615 | strcat(lst_file, ".list"); |
593 | snprintf(buf, sizeof(buf), "ar -p %s data.tar.gz|zcat|tar -tf -", pkg->file); | 616 | outfp = freopen(lst_file, "w", stdout); |
594 | snprintf(buf2, sizeof(buf2), "%s%s.list", infodir, pkg->package); | 617 | deb_extract(dpkg_deb_list, NULL, pkg->file); |
595 | if ((infp = popen(buf, "r")) == NULL || (outfp = fopen(buf2, "w")) == NULL) { | 618 | stdout = freopen(NULL, "w", outfp); |
596 | fprintf(stderr, "Cannot create %s\n", buf2); | 619 | |
597 | r = 1; | 620 | printf("done\n"); |
598 | break; | 621 | getchar(); |
599 | } | 622 | |
600 | while (fgets(buf, sizeof(buf), infp) && !feof(infp)) { | ||
601 | p = buf; | ||
602 | if (*p == '.') { | ||
603 | p++; | ||
604 | } | ||
605 | if ((*p == '/') && (*(p + 1) == '\n')) { | ||
606 | *(p + 1) = '.'; | ||
607 | *(p + 2) = '\n'; | ||
608 | *(p + 3) = 0; | ||
609 | } | ||
610 | if (p[strlen(p) - 2] == '/') { | ||
611 | p[strlen(p) - 2] = '\n'; | ||
612 | p[strlen(p) - 1] = 0; | ||
613 | } | ||
614 | fputs(p, outfp); | ||
615 | } | ||
616 | fclose(infp); | ||
617 | fclose(outfp); | 623 | fclose(outfp); |
618 | } | 624 | } |
619 | 625 | ||
@@ -628,80 +634,86 @@ static int dpkg_dounpack(package_t *pkg) | |||
628 | } else { | 634 | } else { |
629 | pkg->status |= status_statushalfinstalled; | 635 | pkg->status |= status_statushalfinstalled; |
630 | } | 636 | } |
631 | end: | ||
632 | chdir(cwd); | 637 | chdir(cwd); |
633 | return r; | 638 | return r; |
634 | } | 639 | } |
635 | 640 | ||
636 | static int dpkg_doinstall(package_t *pkg) | 641 | /* |
637 | { | 642 | * Extract and parse the control.tar.gz from the specified package |
638 | DPRINTF("Installing %s\n", pkg->package); | 643 | */ |
639 | return (dpkg_dounpack(pkg) || dpkg_doconfigure(pkg)); | ||
640 | } | ||
641 | |||
642 | static int dpkg_unpackcontrol(package_t *pkg) | 644 | static int dpkg_unpackcontrol(package_t *pkg) |
643 | { | 645 | { |
644 | int r = 1; | 646 | char *tmp_name; |
645 | char *cwd = 0; | 647 | FILE *file; |
646 | char *p; | 648 | int length; |
647 | char buf[1024]; | ||
648 | FILE *f; | ||
649 | 649 | ||
650 | p = strrchr(pkg->file, '/'); | 650 | /* clean the temp directory (dpkgcidir) be recreating it */ |
651 | if (p) p++; else p = pkg->file; | 651 | remove_dpkgcidir(); |
652 | p = pkg->package = strdup(p); | 652 | if (mkdir(dpkgcidir, S_IRWXU) != 0) { |
653 | while (*p != 0 && *p != '_' && *p != '.') { | 653 | perror("mkdir"); |
654 | p++; | 654 | return EXIT_FAILURE; |
655 | } | 655 | } |
656 | *p = 0; | ||
657 | 656 | ||
658 | cwd = getcwd(0, 0); | 657 | /* |
659 | snprintf(buf, sizeof(buf), "%s%s", dpkgcidir, pkg->package); | 658 | * Get the package name from the file name, |
660 | DPRINTF("dir = %s\n", buf); | 659 | * first remove the directories |
661 | 660 | */ | |
662 | if (mkdir(buf, S_IRWXU) == 0 && chdir(buf) == 0) { | 661 | if ((tmp_name = strrchr(pkg->file, '/')) == NULL) { |
663 | snprintf(buf, sizeof(buf), "ar -p %s control.tar.gz|zcat|tar -xf -", pkg->file); | 662 | tmp_name = pkg->file; |
664 | if (SYSTEM(buf) == 0) { | 663 | } else { |
665 | if ((f = fopen("control", "r")) != NULL) { | 664 | tmp_name++; |
666 | control_read(f, pkg); | ||
667 | r = 0; | ||
668 | } | ||
669 | } | ||
670 | } | 665 | } |
671 | chdir(cwd); | 666 | /* now remove trailing version numbers etc */ |
672 | free(cwd); | 667 | length = strcspn(tmp_name, "_."); |
668 | pkg->package = (char *) xmalloc(length + 1); | ||
669 | /* store the package name */ | ||
670 | strncpy(pkg->package, tmp_name, length); | ||
673 | 671 | ||
674 | return r; | 672 | /* work out the full extraction path */ |
673 | tmp_name = (char *) xmalloc(strlen(dpkgcidir) + strlen(pkg->package) + 9); | ||
674 | memset(tmp_name, 0, strlen(dpkgcidir) + strlen(pkg->package) + 9); | ||
675 | strcpy(tmp_name, dpkgcidir); | ||
676 | strcat(tmp_name, pkg->package); | ||
677 | |||
678 | /* extract control.tar.gz to the full extraction path */ | ||
679 | deb_extract(dpkg_deb_control, tmp_name, pkg->file); | ||
680 | |||
681 | /* parse the extracted control file */ | ||
682 | strcat(tmp_name, "/control"); | ||
683 | if ((file = fopen(tmp_name, "r")) == NULL) { | ||
684 | return EXIT_FAILURE; | ||
685 | } | ||
686 | if (control_read(file, pkg) == EXIT_FAILURE) { | ||
687 | return EXIT_FAILURE; | ||
688 | } | ||
689 | |||
690 | return EXIT_SUCCESS; | ||
675 | } | 691 | } |
676 | 692 | ||
677 | static int dpkg_unpack(package_t *pkgs) | 693 | static int dpkg_unpack(package_t *pkgs, void *status) |
678 | { | 694 | { |
679 | int r = 0; | 695 | int r = 0; |
680 | package_t *pkg; | 696 | package_t *pkg; |
681 | void *status = status_read(); | ||
682 | 697 | ||
683 | if (SYSTEM(rm_dpkgcidir) != 0 || | ||
684 | mkdir(dpkgcidir, S_IRWXU) != 0) { | ||
685 | perror("mkdir"); | ||
686 | return 1; | ||
687 | } | ||
688 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { | 698 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { |
689 | dpkg_unpackcontrol(pkg); | 699 | if (dpkg_unpackcontrol(pkg) == EXIT_FAILURE) { |
690 | r = dpkg_dounpack(pkg); | 700 | return EXIT_FAILURE; |
691 | if (r != 0) break; | 701 | } |
702 | if ((r = dpkg_dounpack(pkg)) != 0 ) { | ||
703 | break; | ||
704 | } | ||
692 | } | 705 | } |
693 | status_merge(status, pkgs); | 706 | status_merge(status, pkgs); |
694 | SYSTEM(rm_dpkgcidir); | 707 | remove_dpkgcidir(); |
695 | 708 | ||
696 | return r; | 709 | return r; |
697 | } | 710 | } |
698 | 711 | ||
699 | static int dpkg_configure(package_t *pkgs) | 712 | static int dpkg_configure(package_t *pkgs, void *status) |
700 | { | 713 | { |
701 | int r = 0; | 714 | int r = 0; |
702 | void *found; | 715 | void *found; |
703 | package_t *pkg; | 716 | package_t *pkg; |
704 | void *status = status_read(); | ||
705 | 717 | ||
706 | for (pkg = pkgs; pkg != 0 && r == 0; pkg = pkg->next) { | 718 | for (pkg = pkgs; pkg != 0 && r == 0; pkg = pkg->next) { |
707 | found = tfind(pkg, &status, package_compare); | 719 | found = tfind(pkg, &status, package_compare); |
@@ -722,25 +734,18 @@ static int dpkg_configure(package_t *pkgs) | |||
722 | return r; | 734 | return r; |
723 | } | 735 | } |
724 | 736 | ||
725 | static int dpkg_install(package_t *pkgs) | 737 | static int dpkg_install(package_t *pkgs, void *status) |
726 | { | 738 | { |
727 | package_t *p, *ordered = 0; | 739 | package_t *p, *ordered = 0; |
728 | void *status = status_read(); | ||
729 | 740 | ||
730 | if (SYSTEM(rm_dpkgcidir) != 0 || | ||
731 | mkdir(dpkgcidir, S_IRWXU) != 0) { | ||
732 | perror("mkdir"); | ||
733 | return 1; | ||
734 | } | ||
735 | |||
736 | /* Stage 1: parse all the control information */ | 741 | /* Stage 1: parse all the control information */ |
737 | for (p = pkgs; p != 0; p = p->next) | 742 | for (p = pkgs; p != 0; p = p->next) { |
738 | if (dpkg_unpackcontrol(p) != 0) { | 743 | if (dpkg_unpackcontrol(p) == EXIT_FAILURE) { |
739 | perror(p->file); | 744 | perror(p->file); |
740 | /* force loop break, and prevents further ops */ | 745 | return EXIT_FAILURE; |
741 | pkgs = 0; | ||
742 | } | 746 | } |
743 | 747 | } | |
748 | |||
744 | /* Stage 2: resolve dependencies */ | 749 | /* Stage 2: resolve dependencies */ |
745 | #ifdef DODEPENDS | 750 | #ifdef DODEPENDS |
746 | ordered = depends_resolve(pkgs, status); | 751 | ordered = depends_resolve(pkgs, status); |
@@ -759,7 +764,11 @@ static int dpkg_install(package_t *pkgs) | |||
759 | p->status &= status_flagmask; | 764 | p->status &= status_flagmask; |
760 | p->status |= status_flagok; | 765 | p->status |= status_flagok; |
761 | 766 | ||
762 | if (dpkg_doinstall(p) != 0) { | 767 | DPRINTF("Installing %s\n", p->package); |
768 | if (dpkg_dounpack(p) != 0) { | ||
769 | perror(p->file); | ||
770 | } | ||
771 | if (dpkg_doconfigure(p) != 0) { | ||
763 | perror(p->file); | 772 | perror(p->file); |
764 | } | 773 | } |
765 | } | 774 | } |
@@ -767,15 +776,14 @@ static int dpkg_install(package_t *pkgs) | |||
767 | if (ordered != 0) { | 776 | if (ordered != 0) { |
768 | status_merge(status, pkgs); | 777 | status_merge(status, pkgs); |
769 | } | 778 | } |
770 | SYSTEM(rm_dpkgcidir); | 779 | remove_dpkgcidir(); |
771 | 780 | ||
772 | return 0; | 781 | return 0; |
773 | } | 782 | } |
774 | 783 | ||
775 | static int dpkg_remove(package_t *pkgs) | 784 | static int dpkg_remove(package_t *pkgs, void *status) |
776 | { | 785 | { |
777 | package_t *p; | 786 | package_t *p; |
778 | void *status = status_read(); | ||
779 | 787 | ||
780 | for (p = pkgs; p != 0; p = p->next) | 788 | for (p = pkgs; p != 0; p = p->next) |
781 | { | 789 | { |
@@ -791,6 +799,7 @@ extern int dpkg_main(int argc, char **argv) | |||
791 | char *s; | 799 | char *s; |
792 | package_t *p, *packages = NULL; | 800 | package_t *p, *packages = NULL; |
793 | char *cwd = getcwd(0, 0); | 801 | char *cwd = getcwd(0, 0); |
802 | void *status = NULL; | ||
794 | 803 | ||
795 | while (*++argv) { | 804 | while (*++argv) { |
796 | if (**argv == '-') { | 805 | if (**argv == '-') { |
@@ -819,17 +828,19 @@ extern int dpkg_main(int argc, char **argv) | |||
819 | } | 828 | } |
820 | } | 829 | } |
821 | 830 | ||
831 | status = status_read(); | ||
832 | |||
822 | switch (opt) { | 833 | switch (opt) { |
823 | case 'i': | 834 | case 'i': |
824 | return dpkg_install(packages); | 835 | return dpkg_install(packages, status); |
825 | case 'r': | 836 | case 'r': |
826 | return dpkg_remove(packages); | 837 | return dpkg_remove(packages, status); |
827 | case 'u': | 838 | case 'u': |
828 | return dpkg_unpack(packages); | 839 | return dpkg_unpack(packages, status); |
829 | case 'c': | 840 | case 'c': |
830 | return dpkg_configure(packages); | 841 | return dpkg_configure(packages, status); |
831 | default : | 842 | default : |
832 | usage(dpkg_usage); | 843 | usage(dpkg_usage); |
833 | return 0; | 844 | return EXIT_FAILURE; |
834 | } | 845 | } |
835 | } \ No newline at end of file | 846 | } \ No newline at end of file |
@@ -11,18 +11,13 @@ | |||
11 | 11 | ||
12 | #include "busybox.h" | 12 | #include "busybox.h" |
13 | 13 | ||
14 | //#define PACKAGE "udpkg" | 14 | #define DEPENDSMAX 64 /* maximum number of depends we can handle */ |
15 | //#define VERSION "0.1" | ||
16 | 15 | ||
17 | /* | 16 | /* Should we do full dependency checking? */ |
18 | * Should we do full dependency checking? | ||
19 | */ | ||
20 | #define DODEPENDS 1 | 17 | #define DODEPENDS 1 |
21 | 18 | ||
22 | /* | 19 | /* Should we do debugging? */ |
23 | * Should we do debugging? | 20 | #define DODEBUG 1 |
24 | */ | ||
25 | #define DODEBUG 0 | ||
26 | 21 | ||
27 | #ifdef DODEBUG | 22 | #ifdef DODEBUG |
28 | #define SYSTEM(x) do_system(x) | 23 | #define SYSTEM(x) do_system(x) |
@@ -32,15 +27,20 @@ | |||
32 | #define DPRINTF(fmt,args...) /* nothing */ | 27 | #define DPRINTF(fmt,args...) /* nothing */ |
33 | #endif | 28 | #endif |
34 | 29 | ||
35 | #define BUFSIZE 4096 | 30 | /* from dpkg-deb.c */ |
36 | #define DEPENDSMAX 64 /* maximum number of depends we can handle */ | 31 | extern int deb_extract(int optflags, const char *dir_name, const char *deb_filename); |
32 | static const int dpkg_deb_contents = 1; | ||
33 | static const int dpkg_deb_control = 2; | ||
34 | // const int dpkg_deb_info = 4; | ||
35 | static const int dpkg_deb_extract = 8; | ||
36 | static const int dpkg_deb_verbose_extract = 16; | ||
37 | static const int dpkg_deb_list = 32; | ||
37 | 38 | ||
38 | static const char statusfile[] = "/var/lib/dpkg/status.udeb"; | 39 | static const char statusfile[] = "/var/lib/dpkg/status.udeb"; |
39 | static const char new_statusfile[] = "/var/lib/dpkg/status.udeb.new"; | 40 | static const char new_statusfile[] = "/var/lib/dpkg/status.udeb.new"; |
40 | static const char bak_statusfile[] = "/var/lib/dpkg/status.udeb.bak"; | 41 | static const char bak_statusfile[] = "/var/lib/dpkg/status.udeb.bak"; |
41 | 42 | ||
42 | static const char dpkgcidir[] = "/var/lib/dpkg/tmp.ci/"; | 43 | static const char dpkgcidir[] = "/var/lib/dpkg/tmp.ci/"; |
43 | static const char rm_dpkgcidir[] = "rm -rf /var/lib/dpkg/tmp.ci/"; | ||
44 | 44 | ||
45 | static const char infodir[] = "/var/lib/dpkg/info/"; | 45 | static const char infodir[] = "/var/lib/dpkg/info/"; |
46 | static const char udpkg_quiet[] = "UDPKG_QUIET"; | 46 | static const char udpkg_quiet[] = "UDPKG_QUIET"; |
@@ -115,6 +115,21 @@ static int package_compare(const void *p1, const void *p2) | |||
115 | ((package_t *)p2)->package); | 115 | ((package_t *)p2)->package); |
116 | } | 116 | } |
117 | 117 | ||
118 | static int remove_dpkgcidir() | ||
119 | { | ||
120 | char *rm_dpkgcidir = NULL; | ||
121 | |||
122 | rm_dpkgcidir = (char *) xmalloc(strlen(dpkgcidir) + 8); | ||
123 | strcpy(rm_dpkgcidir, "rm -rf "); | ||
124 | strcat(rm_dpkgcidir, dpkgcidir); | ||
125 | |||
126 | if (SYSTEM(rm_dpkgcidir) != 0) { | ||
127 | perror("mkdir "); | ||
128 | return EXIT_FAILURE; | ||
129 | } | ||
130 | return EXIT_SUCCESS; | ||
131 | } | ||
132 | |||
118 | #ifdef DODEPENDS | 133 | #ifdef DODEPENDS |
119 | #include <ctype.h> | 134 | #include <ctype.h> |
120 | 135 | ||
@@ -342,7 +357,7 @@ static const char *status_print(unsigned long flags) | |||
342 | * Read a control file (or a stanza of a status file) and parse it, | 357 | * Read a control file (or a stanza of a status file) and parse it, |
343 | * filling parsed fields into the package structure | 358 | * filling parsed fields into the package structure |
344 | */ | 359 | */ |
345 | static void control_read(FILE *file, package_t *p) | 360 | static int control_read(FILE *file, package_t *p) |
346 | { | 361 | { |
347 | char *line; | 362 | char *line; |
348 | 363 | ||
@@ -374,6 +389,7 @@ static void control_read(FILE *file, package_t *p) | |||
374 | /* TODO: localized descriptions */ | 389 | /* TODO: localized descriptions */ |
375 | } | 390 | } |
376 | free(line); | 391 | free(line); |
392 | return EXIT_SUCCESS; | ||
377 | } | 393 | } |
378 | 394 | ||
379 | static void *status_read(void) | 395 | static void *status_read(void) |
@@ -558,62 +574,52 @@ static int dpkg_doconfigure(package_t *pkg) | |||
558 | static int dpkg_dounpack(package_t *pkg) | 574 | static int dpkg_dounpack(package_t *pkg) |
559 | { | 575 | { |
560 | int r = 0, i; | 576 | int r = 0, i; |
561 | char *cwd, *p; | 577 | char *cwd; |
562 | FILE *infp, *outfp; | 578 | FILE *outfp; |
579 | char *src_file = NULL; | ||
580 | char *dst_file = NULL; | ||
581 | char *lst_file = NULL; | ||
582 | char *adminscripts[] = { "/prerm", "/postrm", "/preinst", "/postinst", | ||
583 | "/conffiles", "/md5sums", "/shlibs", "/templates" }; | ||
563 | char buf[1024], buf2[1024]; | 584 | char buf[1024], buf2[1024]; |
564 | char *adminscripts[] = { "prerm", "postrm", "preinst", "postinst", | ||
565 | "conffiles", "md5sums", "shlibs", "templates" }; | ||
566 | 585 | ||
567 | DPRINTF("Unpacking %s\n", pkg->package); | 586 | DPRINTF("Unpacking %s\n", pkg->package); |
568 | 587 | ||
569 | cwd = getcwd(0, 0); | 588 | cwd = getcwd(0, 0); |
570 | chdir("/"); | 589 | chdir("/"); |
571 | snprintf(buf, sizeof(buf), "ar -p %s data.tar.gz|zcat|tar -xf -", pkg->file); | 590 | deb_extract(dpkg_deb_extract, "/", pkg->file); |
572 | if (SYSTEM(buf) != 0) { | 591 | |
573 | goto end; | ||
574 | } | ||
575 | /* Installs the package scripts into the info directory */ | 592 | /* Installs the package scripts into the info directory */ |
576 | for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) { | 593 | for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) { |
577 | snprintf(buf, sizeof(buf), "%s%s/%s", | 594 | /* The full path of the current location of the admin file */ |
578 | dpkgcidir, pkg->package, adminscripts[i]); | 595 | src_file = xrealloc(src_file, strlen(dpkgcidir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); |
579 | snprintf(buf2, sizeof(buf), "%s%s.%s", | 596 | strcpy(src_file, dpkgcidir); |
580 | infodir, pkg->package, adminscripts[i]); | 597 | strcat(src_file, pkg->package); |
581 | if (copy_file(buf, buf2, TRUE, FALSE, FALSE) < 0) { | 598 | strcat(src_file, adminscripts[i]); |
582 | fprintf(stderr, "Cannot copy %s to %s: %s\n", | 599 | |
583 | buf, buf2, strerror(errno)); | 600 | /* the full path of where we want the file to be copied to */ |
584 | r = 1; | 601 | dst_file = xrealloc(dst_file, strlen(infodir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); |
585 | break; | 602 | strcpy(dst_file, infodir); |
603 | strcat(dst_file, pkg->package); | ||
604 | strcat(dst_file, adminscripts[i]); | ||
605 | |||
606 | /* copy admin file to permanent home */ | ||
607 | if (copy_file(src_file, dst_file, TRUE, FALSE, FALSE) < 0) { | ||
608 | error_msg_and_die("Cannot copy %s to %s ", buf, buf2); | ||
586 | } | 609 | } |
587 | /* ugly hack to create the list file; should | 610 | |
588 | * probably do something more elegant | 611 | /* create the list file */ |
589 | * | 612 | lst_file = (char *) malloc(strlen(infodir) + strlen(pkg->package) + 6); |
590 | * why oh why does dpkg create the list file | 613 | strcpy(lst_file, infodir); |
591 | * so oddly... | 614 | strcat(lst_file, pkg->package); |
592 | */ | 615 | strcat(lst_file, ".list"); |
593 | snprintf(buf, sizeof(buf), "ar -p %s data.tar.gz|zcat|tar -tf -", pkg->file); | 616 | outfp = freopen(lst_file, "w", stdout); |
594 | snprintf(buf2, sizeof(buf2), "%s%s.list", infodir, pkg->package); | 617 | deb_extract(dpkg_deb_list, NULL, pkg->file); |
595 | if ((infp = popen(buf, "r")) == NULL || (outfp = fopen(buf2, "w")) == NULL) { | 618 | stdout = freopen(NULL, "w", outfp); |
596 | fprintf(stderr, "Cannot create %s\n", buf2); | 619 | |
597 | r = 1; | 620 | printf("done\n"); |
598 | break; | 621 | getchar(); |
599 | } | 622 | |
600 | while (fgets(buf, sizeof(buf), infp) && !feof(infp)) { | ||
601 | p = buf; | ||
602 | if (*p == '.') { | ||
603 | p++; | ||
604 | } | ||
605 | if ((*p == '/') && (*(p + 1) == '\n')) { | ||
606 | *(p + 1) = '.'; | ||
607 | *(p + 2) = '\n'; | ||
608 | *(p + 3) = 0; | ||
609 | } | ||
610 | if (p[strlen(p) - 2] == '/') { | ||
611 | p[strlen(p) - 2] = '\n'; | ||
612 | p[strlen(p) - 1] = 0; | ||
613 | } | ||
614 | fputs(p, outfp); | ||
615 | } | ||
616 | fclose(infp); | ||
617 | fclose(outfp); | 623 | fclose(outfp); |
618 | } | 624 | } |
619 | 625 | ||
@@ -628,80 +634,86 @@ static int dpkg_dounpack(package_t *pkg) | |||
628 | } else { | 634 | } else { |
629 | pkg->status |= status_statushalfinstalled; | 635 | pkg->status |= status_statushalfinstalled; |
630 | } | 636 | } |
631 | end: | ||
632 | chdir(cwd); | 637 | chdir(cwd); |
633 | return r; | 638 | return r; |
634 | } | 639 | } |
635 | 640 | ||
636 | static int dpkg_doinstall(package_t *pkg) | 641 | /* |
637 | { | 642 | * Extract and parse the control.tar.gz from the specified package |
638 | DPRINTF("Installing %s\n", pkg->package); | 643 | */ |
639 | return (dpkg_dounpack(pkg) || dpkg_doconfigure(pkg)); | ||
640 | } | ||
641 | |||
642 | static int dpkg_unpackcontrol(package_t *pkg) | 644 | static int dpkg_unpackcontrol(package_t *pkg) |
643 | { | 645 | { |
644 | int r = 1; | 646 | char *tmp_name; |
645 | char *cwd = 0; | 647 | FILE *file; |
646 | char *p; | 648 | int length; |
647 | char buf[1024]; | ||
648 | FILE *f; | ||
649 | 649 | ||
650 | p = strrchr(pkg->file, '/'); | 650 | /* clean the temp directory (dpkgcidir) be recreating it */ |
651 | if (p) p++; else p = pkg->file; | 651 | remove_dpkgcidir(); |
652 | p = pkg->package = strdup(p); | 652 | if (mkdir(dpkgcidir, S_IRWXU) != 0) { |
653 | while (*p != 0 && *p != '_' && *p != '.') { | 653 | perror("mkdir"); |
654 | p++; | 654 | return EXIT_FAILURE; |
655 | } | 655 | } |
656 | *p = 0; | ||
657 | 656 | ||
658 | cwd = getcwd(0, 0); | 657 | /* |
659 | snprintf(buf, sizeof(buf), "%s%s", dpkgcidir, pkg->package); | 658 | * Get the package name from the file name, |
660 | DPRINTF("dir = %s\n", buf); | 659 | * first remove the directories |
661 | 660 | */ | |
662 | if (mkdir(buf, S_IRWXU) == 0 && chdir(buf) == 0) { | 661 | if ((tmp_name = strrchr(pkg->file, '/')) == NULL) { |
663 | snprintf(buf, sizeof(buf), "ar -p %s control.tar.gz|zcat|tar -xf -", pkg->file); | 662 | tmp_name = pkg->file; |
664 | if (SYSTEM(buf) == 0) { | 663 | } else { |
665 | if ((f = fopen("control", "r")) != NULL) { | 664 | tmp_name++; |
666 | control_read(f, pkg); | ||
667 | r = 0; | ||
668 | } | ||
669 | } | ||
670 | } | 665 | } |
671 | chdir(cwd); | 666 | /* now remove trailing version numbers etc */ |
672 | free(cwd); | 667 | length = strcspn(tmp_name, "_."); |
668 | pkg->package = (char *) xmalloc(length + 1); | ||
669 | /* store the package name */ | ||
670 | strncpy(pkg->package, tmp_name, length); | ||
673 | 671 | ||
674 | return r; | 672 | /* work out the full extraction path */ |
673 | tmp_name = (char *) xmalloc(strlen(dpkgcidir) + strlen(pkg->package) + 9); | ||
674 | memset(tmp_name, 0, strlen(dpkgcidir) + strlen(pkg->package) + 9); | ||
675 | strcpy(tmp_name, dpkgcidir); | ||
676 | strcat(tmp_name, pkg->package); | ||
677 | |||
678 | /* extract control.tar.gz to the full extraction path */ | ||
679 | deb_extract(dpkg_deb_control, tmp_name, pkg->file); | ||
680 | |||
681 | /* parse the extracted control file */ | ||
682 | strcat(tmp_name, "/control"); | ||
683 | if ((file = fopen(tmp_name, "r")) == NULL) { | ||
684 | return EXIT_FAILURE; | ||
685 | } | ||
686 | if (control_read(file, pkg) == EXIT_FAILURE) { | ||
687 | return EXIT_FAILURE; | ||
688 | } | ||
689 | |||
690 | return EXIT_SUCCESS; | ||
675 | } | 691 | } |
676 | 692 | ||
677 | static int dpkg_unpack(package_t *pkgs) | 693 | static int dpkg_unpack(package_t *pkgs, void *status) |
678 | { | 694 | { |
679 | int r = 0; | 695 | int r = 0; |
680 | package_t *pkg; | 696 | package_t *pkg; |
681 | void *status = status_read(); | ||
682 | 697 | ||
683 | if (SYSTEM(rm_dpkgcidir) != 0 || | ||
684 | mkdir(dpkgcidir, S_IRWXU) != 0) { | ||
685 | perror("mkdir"); | ||
686 | return 1; | ||
687 | } | ||
688 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { | 698 | for (pkg = pkgs; pkg != 0; pkg = pkg->next) { |
689 | dpkg_unpackcontrol(pkg); | 699 | if (dpkg_unpackcontrol(pkg) == EXIT_FAILURE) { |
690 | r = dpkg_dounpack(pkg); | 700 | return EXIT_FAILURE; |
691 | if (r != 0) break; | 701 | } |
702 | if ((r = dpkg_dounpack(pkg)) != 0 ) { | ||
703 | break; | ||
704 | } | ||
692 | } | 705 | } |
693 | status_merge(status, pkgs); | 706 | status_merge(status, pkgs); |
694 | SYSTEM(rm_dpkgcidir); | 707 | remove_dpkgcidir(); |
695 | 708 | ||
696 | return r; | 709 | return r; |
697 | } | 710 | } |
698 | 711 | ||
699 | static int dpkg_configure(package_t *pkgs) | 712 | static int dpkg_configure(package_t *pkgs, void *status) |
700 | { | 713 | { |
701 | int r = 0; | 714 | int r = 0; |
702 | void *found; | 715 | void *found; |
703 | package_t *pkg; | 716 | package_t *pkg; |
704 | void *status = status_read(); | ||
705 | 717 | ||
706 | for (pkg = pkgs; pkg != 0 && r == 0; pkg = pkg->next) { | 718 | for (pkg = pkgs; pkg != 0 && r == 0; pkg = pkg->next) { |
707 | found = tfind(pkg, &status, package_compare); | 719 | found = tfind(pkg, &status, package_compare); |
@@ -722,25 +734,18 @@ static int dpkg_configure(package_t *pkgs) | |||
722 | return r; | 734 | return r; |
723 | } | 735 | } |
724 | 736 | ||
725 | static int dpkg_install(package_t *pkgs) | 737 | static int dpkg_install(package_t *pkgs, void *status) |
726 | { | 738 | { |
727 | package_t *p, *ordered = 0; | 739 | package_t *p, *ordered = 0; |
728 | void *status = status_read(); | ||
729 | 740 | ||
730 | if (SYSTEM(rm_dpkgcidir) != 0 || | ||
731 | mkdir(dpkgcidir, S_IRWXU) != 0) { | ||
732 | perror("mkdir"); | ||
733 | return 1; | ||
734 | } | ||
735 | |||
736 | /* Stage 1: parse all the control information */ | 741 | /* Stage 1: parse all the control information */ |
737 | for (p = pkgs; p != 0; p = p->next) | 742 | for (p = pkgs; p != 0; p = p->next) { |
738 | if (dpkg_unpackcontrol(p) != 0) { | 743 | if (dpkg_unpackcontrol(p) == EXIT_FAILURE) { |
739 | perror(p->file); | 744 | perror(p->file); |
740 | /* force loop break, and prevents further ops */ | 745 | return EXIT_FAILURE; |
741 | pkgs = 0; | ||
742 | } | 746 | } |
743 | 747 | } | |
748 | |||
744 | /* Stage 2: resolve dependencies */ | 749 | /* Stage 2: resolve dependencies */ |
745 | #ifdef DODEPENDS | 750 | #ifdef DODEPENDS |
746 | ordered = depends_resolve(pkgs, status); | 751 | ordered = depends_resolve(pkgs, status); |
@@ -759,7 +764,11 @@ static int dpkg_install(package_t *pkgs) | |||
759 | p->status &= status_flagmask; | 764 | p->status &= status_flagmask; |
760 | p->status |= status_flagok; | 765 | p->status |= status_flagok; |
761 | 766 | ||
762 | if (dpkg_doinstall(p) != 0) { | 767 | DPRINTF("Installing %s\n", p->package); |
768 | if (dpkg_dounpack(p) != 0) { | ||
769 | perror(p->file); | ||
770 | } | ||
771 | if (dpkg_doconfigure(p) != 0) { | ||
763 | perror(p->file); | 772 | perror(p->file); |
764 | } | 773 | } |
765 | } | 774 | } |
@@ -767,15 +776,14 @@ static int dpkg_install(package_t *pkgs) | |||
767 | if (ordered != 0) { | 776 | if (ordered != 0) { |
768 | status_merge(status, pkgs); | 777 | status_merge(status, pkgs); |
769 | } | 778 | } |
770 | SYSTEM(rm_dpkgcidir); | 779 | remove_dpkgcidir(); |
771 | 780 | ||
772 | return 0; | 781 | return 0; |
773 | } | 782 | } |
774 | 783 | ||
775 | static int dpkg_remove(package_t *pkgs) | 784 | static int dpkg_remove(package_t *pkgs, void *status) |
776 | { | 785 | { |
777 | package_t *p; | 786 | package_t *p; |
778 | void *status = status_read(); | ||
779 | 787 | ||
780 | for (p = pkgs; p != 0; p = p->next) | 788 | for (p = pkgs; p != 0; p = p->next) |
781 | { | 789 | { |
@@ -791,6 +799,7 @@ extern int dpkg_main(int argc, char **argv) | |||
791 | char *s; | 799 | char *s; |
792 | package_t *p, *packages = NULL; | 800 | package_t *p, *packages = NULL; |
793 | char *cwd = getcwd(0, 0); | 801 | char *cwd = getcwd(0, 0); |
802 | void *status = NULL; | ||
794 | 803 | ||
795 | while (*++argv) { | 804 | while (*++argv) { |
796 | if (**argv == '-') { | 805 | if (**argv == '-') { |
@@ -819,17 +828,19 @@ extern int dpkg_main(int argc, char **argv) | |||
819 | } | 828 | } |
820 | } | 829 | } |
821 | 830 | ||
831 | status = status_read(); | ||
832 | |||
822 | switch (opt) { | 833 | switch (opt) { |
823 | case 'i': | 834 | case 'i': |
824 | return dpkg_install(packages); | 835 | return dpkg_install(packages, status); |
825 | case 'r': | 836 | case 'r': |
826 | return dpkg_remove(packages); | 837 | return dpkg_remove(packages, status); |
827 | case 'u': | 838 | case 'u': |
828 | return dpkg_unpack(packages); | 839 | return dpkg_unpack(packages, status); |
829 | case 'c': | 840 | case 'c': |
830 | return dpkg_configure(packages); | 841 | return dpkg_configure(packages, status); |
831 | default : | 842 | default : |
832 | usage(dpkg_usage); | 843 | usage(dpkg_usage); |
833 | return 0; | 844 | return EXIT_FAILURE; |
834 | } | 845 | } |
835 | } \ No newline at end of file | 846 | } \ No newline at end of file |