aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2001-04-08 05:27:18 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2001-04-08 05:27:18 +0000
commit0e757a2f3f120abbd6186561399fc8180d7a9376 (patch)
tree36d093b220f59af56c8b5b8bc81e41997e360382
parentf608da428835cb7a6f921451d6f6bdc196fb5603 (diff)
downloadbusybox-w32-0e757a2f3f120abbd6186561399fc8180d7a9376.tar.gz
busybox-w32-0e757a2f3f120abbd6186561399fc8180d7a9376.tar.bz2
busybox-w32-0e757a2f3f120abbd6186561399fc8180d7a9376.zip
Some fixes, but still broken... (cont)
Make better use of some libbb functions New remove dir code to avoid depending on the rm applet dont use copy_file() it doesnt fail elegantly Use getopt. Generate correct /var/lib/dpkg/info/ files Status file is broken, working on it now
-rw-r--r--archival/dpkg.c298
-rw-r--r--dpkg.c298
2 files changed, 324 insertions, 272 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c
index af200e11e..d05198cbf 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -1,3 +1,5 @@
1#include <dirent.h>
2#include <getopt.h>
1#include <stdio.h> 3#include <stdio.h>
2#include <string.h> 4#include <string.h>
3#include <stdlib.h> 5#include <stdlib.h>
@@ -116,18 +118,34 @@ static int package_compare(const void *p1, const void *p2)
116 ((package_t *)p2)->package); 118 ((package_t *)p2)->package);
117} 119}
118 120
119static int remove_dpkgcidir() 121/*
122 * NOTE: this was handled by a "rm -rf" shell command
123 * Maybe theis behaviour should be integrated into the rm applet
124 * (i dont appreciate the rm applets recursive action fn)-bug1
125 */
126static int remove_dir(const char *dirname)
120{ 127{
121 char *rm_dpkgcidir = NULL; 128 struct dirent *fp;
122 129 DIR *dp = opendir(dirname);
123 rm_dpkgcidir = (char *) xmalloc(strlen(dpkgcidir) + 8); 130 while ((fp = readdir(dp)) != NULL) {
124 strcpy(rm_dpkgcidir, "rm -rf "); 131 struct stat statbuf;
125 strcat(rm_dpkgcidir, dpkgcidir); 132 char *filename;
126 133
127 if (SYSTEM(rm_dpkgcidir) != 0) { 134 filename = (char *) xcalloc(1, strlen(dirname) + strlen(fp->d_name) + 2);
128 perror("mkdir "); 135 strcpy(filename, dirname);
129 return EXIT_FAILURE; 136 strcat(filename, fp->d_name);
137 lstat(filename, &statbuf);
138
139 if ((strcmp(fp->d_name, ".") != 0) && (strcmp(fp->d_name, "..") != 0)) {
140 if (S_ISDIR(statbuf.st_mode)) {
141 remove_dir(strcat(filename, "/"));
142 }
143 else if (remove(filename) == -1) {
144 perror_msg(filename);
145 }
146 }
130 } 147 }
148 remove(dirname);
131 return EXIT_SUCCESS; 149 return EXIT_SUCCESS;
132} 150}
133 151
@@ -145,7 +163,7 @@ static char **depends_split(const char *dependsstr)
145 goto end; 163 goto end;
146 } 164 }
147 165
148 p = strdup(dependsstr); 166 p = xstrdup(dependsstr);
149 while (*p != 0 && *p != '\n') { 167 while (*p != 0 && *p != '\n') {
150 if (*p != ' ') { 168 if (*p != ' ') {
151 if (*p == ',') { 169 if (*p == ',') {
@@ -363,25 +381,25 @@ static int control_read(FILE *file, package_t *p)
363 char *line; 381 char *line;
364 382
365 while ((line = get_line_from_file(file)) != NULL) { 383 while ((line = get_line_from_file(file)) != NULL) {
366 line[strlen(line)] = 0; 384 line[strlen(line) - 1] = '\0';
367 385
368 if (strlen(line) == 0) { 386 if (strlen(line) == 0) {
369 break; 387 break;
370 } else 388 } else
371 if (strstr(line, "Package: ") == line) { 389 if (strstr(line, "Package: ") == line) {
372 p->package = strdup(line + 9); 390 p->package = xstrdup(line + 9);
373 } else 391 } else
374 if (strstr(line, "Status: ") == line) { 392 if (strstr(line, "Status: ") == line) {
375 p->status = status_parse(line + 8); 393 p->status = status_parse(line + 8);
376 } else 394 } else
377 if (strstr(line, "Depends: ") == line) { 395 if (strstr(line, "Depends: ") == line) {
378 p->depends = strdup(line + 9); 396 p->depends = xstrdup(line + 9);
379 } else 397 } else
380 if (strstr(line, "Provides: ") == line) { 398 if (strstr(line, "Provides: ") == line) {
381 p->provides = strdup(line + 10); 399 p->provides = xstrdup(line + 10);
382 } else 400 } else
383 if (strstr(line, "Description: ") == line) { 401 if (strstr(line, "Description: ") == line) {
384 p->description = strdup(line + 13); 402 p->description = xstrdup(line + 13);
385 /* This is specific to the Debian Installer. Ifdef? */ 403 /* This is specific to the Debian Installer. Ifdef? */
386 } else 404 } else
387 if (strstr(line, "installer-menu-item: ") == line) { 405 if (strstr(line, "installer-menu-item: ") == line) {
@@ -400,7 +418,7 @@ static void *status_read(void)
400 package_t *m = 0, *p = 0, *t = 0; 418 package_t *m = 0, *p = 0, *t = 0;
401 419
402 if ((f = fopen(statusfile, "r")) == NULL) { 420 if ((f = fopen(statusfile, "r")) == NULL) {
403 perror(statusfile); 421 perror_msg(statusfile);
404 return 0; 422 return 0;
405 } 423 }
406 424
@@ -409,8 +427,7 @@ static void *status_read(void)
409 } 427 }
410 428
411 while (!feof(f)) { 429 while (!feof(f)) {
412 m = (package_t *)xmalloc(sizeof(package_t)); 430 m = (package_t *)xcalloc(1, sizeof(package_t));
413 memset(m, 0, sizeof(package_t));
414 control_read(f, m); 431 control_read(f, m);
415 if (m->package) { 432 if (m->package) {
416 /* 433 /*
@@ -426,9 +443,8 @@ static void *status_read(void)
426 * of a pseudo package into the status 443 * of a pseudo package into the status
427 * binary-tree. 444 * binary-tree.
428 */ 445 */
429 p = (package_t *)xmalloc(sizeof(package_t)); 446 p = (package_t *)xcalloc(1, sizeof(package_t));
430 memset(p, 0, sizeof(package_t)); 447 p->package = xstrdup(m->provides);
431 p->package = strdup(m->provides);
432 448
433 t = *(package_t **)tsearch(p, &status, package_compare); 449 t = *(package_t **)tsearch(p, &status, package_compare);
434 if (t != p) { 450 if (t != p) {
@@ -459,57 +475,52 @@ static void *status_read(void)
459static int status_merge(void *status, package_t *pkgs) 475static int status_merge(void *status, package_t *pkgs)
460{ 476{
461 FILE *fin, *fout; 477 FILE *fin, *fout;
462 char *line; 478 char *line = NULL;
463 package_t *pkg = 0, *statpkg = 0; 479 package_t *pkg = 0, *statpkg = 0;
464 package_t locpkg; 480 package_t locpkg;
465 int r = 0; 481 int r = 0;
466 482
467 if ((fin = fopen(statusfile, "r")) == NULL) { 483 if ((fout = wfopen(new_statusfile, "w")) == NULL) {
468 perror(statusfile);
469 return 0;
470 }
471 if ((fout = fopen(new_statusfile, "w")) == NULL) {
472 perror(new_statusfile);
473 return 0; 484 return 0;
474 } 485 }
475 if (getenv(udpkg_quiet) == NULL) { 486 if (getenv(udpkg_quiet) == NULL) {
476 printf("(Updating database...)\n"); 487 printf("(Updating database...)\n");
477 } 488 }
489 if ((fin = wfopen(statusfile, "r")) != NULL) {
490 while (((line = get_line_from_file(fin)) != NULL) && !feof(fin)) {
491 line[strlen(line) - 1] = '\0'; /* trim newline */
492 /* If we see a package header, find out if it's a package
493 * that we have processed. if so, we skip that block for
494 * now (write it at the end).
495 *
496 * we also look at packages in the status cache and update
497 * their status fields
498 */
499 if (strstr(line, "Package: ") == line) {
500 for (pkg = pkgs; pkg != 0 && strcmp(line + 9,
501 pkg->package) != 0; pkg = pkg->next) ;
478 502
479 while (((line = get_line_from_file(fin)) != NULL) && !feof(fin)) { 503 locpkg.package = line + 9;
480 line[strlen(line)] = 0; /* trim newline */ 504 statpkg = tfind(&locpkg, &status, package_compare);
481 /* If we see a package header, find out if it's a package
482 * that we have processed. if so, we skip that block for
483 * now (write it at the end).
484 *
485 * we also look at packages in the status cache and update
486 * their status fields
487 */
488 if (strstr(line, "Package: ") == line) {
489 for (pkg = pkgs; pkg != 0 && strncmp(line + 9,
490 pkg->package, strlen(line) - 9) != 0;
491 pkg = pkg->next) ;
492
493 locpkg.package = line + 9;
494 statpkg = tfind(&locpkg, &status, package_compare);
495 505
496 /* note: statpkg should be non-zero, unless the status 506 /* note: statpkg should be non-zero, unless the status
497 * file was changed while we are processing (no locking 507 * file was changed while we are processing (no locking
498 * is currently done... 508 * is currently done...
499 */ 509 */
500 if (statpkg != 0) { 510 if (statpkg != 0) {
501 statpkg = *(package_t **)statpkg; 511 statpkg = *(package_t **)statpkg;
512 }
502 } 513 }
514 if (pkg != 0) {
515 continue;
516 }
517 if (strstr(line, "Status: ") == line && statpkg != 0) {
518 snprintf(line, sizeof(line), "Status: %s",
519 status_print(statpkg->status));
520 }
521 fputs(line, fout);
522 fputc('\n', fout);
503 } 523 }
504 if (pkg != 0) {
505 continue;
506 }
507 if (strstr(line, "Status: ") == line && statpkg != 0) {
508 snprintf(line, sizeof(line), "Status: %s",
509 status_print(statpkg->status));
510 }
511 fputs(line, fout);
512 fputc('\n', fout);
513 } 524 }
514 free(line); 525 free(line);
515 526
@@ -576,13 +587,11 @@ static int dpkg_dounpack(package_t *pkg)
576{ 587{
577 int r = 0, i; 588 int r = 0, i;
578 char *cwd; 589 char *cwd;
579 FILE *outfp;
580 char *src_file = NULL; 590 char *src_file = NULL;
581 char *dst_file = NULL; 591 char *dst_file = NULL;
582 char *lst_file = NULL; 592// char *lst_file = NULL;
583 char *adminscripts[] = { "/prerm", "/postrm", "/preinst", "/postinst", 593 char *adminscripts[] = { "prerm", "postrm", "preinst", "postinst",
584 "/conffiles", "/md5sums", "/shlibs", "/templates" }; 594 "conffiles", "md5sums", "shlibs", "templates" };
585 char buf[1024], buf2[1024];
586 595
587 DPRINTF("Unpacking %s\n", pkg->package); 596 DPRINTF("Unpacking %s\n", pkg->package);
588 597
@@ -592,36 +601,46 @@ static int dpkg_dounpack(package_t *pkg)
592 601
593 /* Installs the package scripts into the info directory */ 602 /* Installs the package scripts into the info directory */
594 for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) { 603 for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) {
604 struct stat src_stat_buf;
605 int src_fd = 0, dst_fd = 0;
606
595 /* The full path of the current location of the admin file */ 607 /* The full path of the current location of the admin file */
596 src_file = xrealloc(src_file, strlen(dpkgcidir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); 608 src_file = xrealloc(src_file, strlen(dpkgcidir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1);
597 strcpy(src_file, dpkgcidir); 609 sprintf(src_file, "%s%s/%s", dpkgcidir, pkg->package, adminscripts[i]);
598 strcat(src_file, pkg->package);
599 strcat(src_file, adminscripts[i]);
600 610
601 /* the full path of where we want the file to be copied to */ 611 /* the full path of where we want the file to be copied to */
602 dst_file = xrealloc(dst_file, strlen(infodir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); 612 dst_file = xrealloc(dst_file, strlen(infodir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1);
603 strcpy(dst_file, infodir); 613 sprintf(dst_file, "%s%s.%s", infodir, pkg->package, adminscripts[i]);
604 strcat(dst_file, pkg->package);
605 strcat(dst_file, adminscripts[i]);
606 614
607 /* copy admin file to permanent home */ 615 /*
608 if (copy_file(src_file, dst_file, TRUE, FALSE, FALSE) < 0) { 616 * copy admin file to permanent home
609 error_msg_and_die("Cannot copy %s to %s ", buf, buf2); 617 * NOTE: Maybe merge this behaviour into libb/copy_file.c
618 */
619 if (lstat(src_file, &src_stat_buf) == 0) {
620 if ((src_fd = open(src_file, O_RDONLY)) != -1) {
621 if ((dst_fd = open(dst_file, O_WRONLY | O_CREAT, 0644)) == -1) {
622 perror_msg("Opening %s", dst_file);
623 }
624 copy_file_chunk(src_fd, dst_fd, src_stat_buf.st_size);
625 close(src_fd);
626 close(dst_fd);
627 } else {
628 error_msg("couldnt open [%s]\n", src_file);
629 }
610 } 630 }
611
612 /* create the list file */
613 lst_file = (char *) xmalloc(strlen(infodir) + strlen(pkg->package) + 6);
614 strcpy(lst_file, infodir);
615 strcat(lst_file, pkg->package);
616 strcat(lst_file, ".list");
617 deb_extract(dpkg_deb_list, NULL, pkg->file);
618
619 printf("done\n");
620 getchar();
621
622 fclose(outfp);
623 } 631 }
624 632
633 /*
634 * create the list file
635 * FIXME: currently this dumps the lst to stdout instead of a file
636 */
637/* lst_file = (char *) xmalloc(strlen(infodir) + strlen(pkg->package) + 6);
638 strcpy(lst_file, infodir);
639 strcat(lst_file, pkg->package);
640 strcat(lst_file, ".list");
641 deb_extract(dpkg_deb_list, NULL, pkg->file);
642*/
643
625 pkg->status &= status_wantmask; 644 pkg->status &= status_wantmask;
626 pkg->status |= status_wantinstall; 645 pkg->status |= status_wantinstall;
627 pkg->status &= status_flagmask; 646 pkg->status &= status_flagmask;
@@ -647,7 +666,7 @@ static int dpkg_unpackcontrol(package_t *pkg)
647 int length; 666 int length;
648 667
649 /* clean the temp directory (dpkgcidir) be recreating it */ 668 /* clean the temp directory (dpkgcidir) be recreating it */
650 remove_dpkgcidir(); 669 remove_dir(dpkgcidir);
651 if (mkdir(dpkgcidir, S_IRWXU) != 0) { 670 if (mkdir(dpkgcidir, S_IRWXU) != 0) {
652 perror("mkdir"); 671 perror("mkdir");
653 return EXIT_FAILURE; 672 return EXIT_FAILURE;
@@ -664,13 +683,12 @@ static int dpkg_unpackcontrol(package_t *pkg)
664 } 683 }
665 /* now remove trailing version numbers etc */ 684 /* now remove trailing version numbers etc */
666 length = strcspn(tmp_name, "_."); 685 length = strcspn(tmp_name, "_.");
667 pkg->package = (char *) xmalloc(length + 1); 686 pkg->package = (char *) xcalloc(1, length + 1);
668 /* store the package name */ 687 /* store the package name */
669 strncpy(pkg->package, tmp_name, length); 688 strncpy(pkg->package, tmp_name, length);
670 689
671 /* work out the full extraction path */ 690 /* work out the full extraction path */
672 tmp_name = (char *) xmalloc(strlen(dpkgcidir) + strlen(pkg->package) + 9); 691 tmp_name = (char *) xcalloc(1, strlen(dpkgcidir) + strlen(pkg->package) + 9);
673 memset(tmp_name, 0, strlen(dpkgcidir) + strlen(pkg->package) + 9);
674 strcpy(tmp_name, dpkgcidir); 692 strcpy(tmp_name, dpkgcidir);
675 strcat(tmp_name, pkg->package); 693 strcat(tmp_name, pkg->package);
676 694
@@ -679,7 +697,7 @@ static int dpkg_unpackcontrol(package_t *pkg)
679 697
680 /* parse the extracted control file */ 698 /* parse the extracted control file */
681 strcat(tmp_name, "/control"); 699 strcat(tmp_name, "/control");
682 if ((file = fopen(tmp_name, "r")) == NULL) { 700 if ((file = wfopen(tmp_name, "r")) == NULL) {
683 return EXIT_FAILURE; 701 return EXIT_FAILURE;
684 } 702 }
685 if (control_read(file, pkg) == EXIT_FAILURE) { 703 if (control_read(file, pkg) == EXIT_FAILURE) {
@@ -703,7 +721,7 @@ static int dpkg_unpack(package_t *pkgs, void *status)
703 } 721 }
704 } 722 }
705 status_merge(status, pkgs); 723 status_merge(status, pkgs);
706 remove_dpkgcidir(); 724 remove_dir(dpkgcidir);
707 725
708 return r; 726 return r;
709} 727}
@@ -740,8 +758,7 @@ static int dpkg_install(package_t *pkgs, void *status)
740 /* Stage 1: parse all the control information */ 758 /* Stage 1: parse all the control information */
741 for (p = pkgs; p != 0; p = p->next) { 759 for (p = pkgs; p != 0; p = p->next) {
742 if (dpkg_unpackcontrol(p) == EXIT_FAILURE) { 760 if (dpkg_unpackcontrol(p) == EXIT_FAILURE) {
743 perror(p->file); 761 return(EXIT_FAILURE);
744 return EXIT_FAILURE;
745 } 762 }
746 } 763 }
747 764
@@ -765,21 +782,24 @@ static int dpkg_install(package_t *pkgs, void *status)
765 782
766 DPRINTF("Installing %s\n", p->package); 783 DPRINTF("Installing %s\n", p->package);
767 if (dpkg_dounpack(p) != 0) { 784 if (dpkg_dounpack(p) != 0) {
768 perror(p->file); 785 perror_msg(p->file);
769 } 786 }
770 if (dpkg_doconfigure(p) != 0) { 787 if (dpkg_doconfigure(p) != 0) {
771 perror(p->file); 788 perror_msg(p->file);
772 } 789 }
773 } 790 }
774 791
775 if (ordered != 0) { 792 if (ordered != 0) {
776 status_merge(status, pkgs); 793 status_merge(status, pkgs);
777 } 794 }
778 remove_dpkgcidir(); 795 remove_dir(dpkgcidir);
779 796
780 return 0; 797 return 0;
781} 798}
782 799
800/*
801 * Not implemented yet
802 *
783static int dpkg_remove(package_t *pkgs, void *status) 803static int dpkg_remove(package_t *pkgs, void *status)
784{ 804{
785 package_t *p; 805 package_t *p;
@@ -791,55 +811,61 @@ static int dpkg_remove(package_t *pkgs, void *status)
791 811
792 return 0; 812 return 0;
793} 813}
814*/
794 815
795extern int dpkg_main(int argc, char **argv) 816extern int dpkg_main(int argc, char **argv)
796{ 817{
797 char opt = 0; 818 const int arg_install = 1;
798 char *s; 819 const int arg_unpack = 2;
820 const int arg_configure = 4;
821
799 package_t *p, *packages = NULL; 822 package_t *p, *packages = NULL;
800 char *cwd = getcwd(0, 0);
801 void *status = NULL; 823 void *status = NULL;
824 char opt = 0;
825 int optflag = 0;
802 826
803 while (*++argv) { 827 while ((opt = getopt(argc, argv, "iruc")) != -1) {
804 if (**argv == '-') { 828 switch (opt) {
805 /* Nasty little hack to "parse" long options. */ 829 case 'i':
806 s = *argv; 830 optflag |= arg_install;
807 while (*s == '-') { 831 break;
808 s++; 832 case 'u':
809 } 833 optflag |= arg_unpack;
810 opt=s[0]; 834 break;
835 case 'c':
836 optflag |= arg_configure;
837 break;
838 default:
839 show_usage();
840 }
841 }
842
843 while (optind < argc) {
844 p = (package_t *) xcalloc(1, sizeof(package_t));
845 if (optflag & arg_configure) {
846 p->package = xstrdup(argv[optind]);
811 } else { 847 } else {
812 p = (package_t *)xmalloc(sizeof(package_t)); 848 p->file = xstrdup(argv[optind]);
813 memset(p, 0, sizeof(package_t)); 849 }
814 850 p->next = packages;
815 if (**argv == '/') { 851 packages = p;
816 p->file = *argv;
817 } else
818 if (opt != 'c') {
819 p->file = xmalloc(strlen(cwd) + strlen(*argv) + 2);
820 sprintf(p->file, "%s/%s", cwd, *argv);
821 } else {
822 p->package = strdup(*argv);
823 }
824 852
825 p->next = packages; 853 optind++;
826 packages = p;
827 }
828 } 854 }
829 855
856 create_path(dpkgcidir, 0755);
857 create_path(infodir, 0755);
858
830 status = status_read(); 859 status = status_read();
831 860
832 switch (opt) { 861 if (optflag & arg_install) {
833 case 'i': 862 return dpkg_install(packages, status);
834 return dpkg_install(packages, status); 863 }
835 case 'r': 864 else if (optflag & arg_unpack) {
836 return dpkg_remove(packages, status); 865 return dpkg_unpack(packages, status);
837 case 'u': 866 }
838 return dpkg_unpack(packages, status); 867 else if (optflag & arg_configure) {
839 case 'c': 868 return dpkg_configure(packages, status);
840 return dpkg_configure(packages, status);
841 default :
842 show_usage();
843 return EXIT_FAILURE;
844 } 869 }
870 return(EXIT_FAILURE);
845} 871}
diff --git a/dpkg.c b/dpkg.c
index af200e11e..d05198cbf 100644
--- a/dpkg.c
+++ b/dpkg.c
@@ -1,3 +1,5 @@
1#include <dirent.h>
2#include <getopt.h>
1#include <stdio.h> 3#include <stdio.h>
2#include <string.h> 4#include <string.h>
3#include <stdlib.h> 5#include <stdlib.h>
@@ -116,18 +118,34 @@ static int package_compare(const void *p1, const void *p2)
116 ((package_t *)p2)->package); 118 ((package_t *)p2)->package);
117} 119}
118 120
119static int remove_dpkgcidir() 121/*
122 * NOTE: this was handled by a "rm -rf" shell command
123 * Maybe theis behaviour should be integrated into the rm applet
124 * (i dont appreciate the rm applets recursive action fn)-bug1
125 */
126static int remove_dir(const char *dirname)
120{ 127{
121 char *rm_dpkgcidir = NULL; 128 struct dirent *fp;
122 129 DIR *dp = opendir(dirname);
123 rm_dpkgcidir = (char *) xmalloc(strlen(dpkgcidir) + 8); 130 while ((fp = readdir(dp)) != NULL) {
124 strcpy(rm_dpkgcidir, "rm -rf "); 131 struct stat statbuf;
125 strcat(rm_dpkgcidir, dpkgcidir); 132 char *filename;
126 133
127 if (SYSTEM(rm_dpkgcidir) != 0) { 134 filename = (char *) xcalloc(1, strlen(dirname) + strlen(fp->d_name) + 2);
128 perror("mkdir "); 135 strcpy(filename, dirname);
129 return EXIT_FAILURE; 136 strcat(filename, fp->d_name);
137 lstat(filename, &statbuf);
138
139 if ((strcmp(fp->d_name, ".") != 0) && (strcmp(fp->d_name, "..") != 0)) {
140 if (S_ISDIR(statbuf.st_mode)) {
141 remove_dir(strcat(filename, "/"));
142 }
143 else if (remove(filename) == -1) {
144 perror_msg(filename);
145 }
146 }
130 } 147 }
148 remove(dirname);
131 return EXIT_SUCCESS; 149 return EXIT_SUCCESS;
132} 150}
133 151
@@ -145,7 +163,7 @@ static char **depends_split(const char *dependsstr)
145 goto end; 163 goto end;
146 } 164 }
147 165
148 p = strdup(dependsstr); 166 p = xstrdup(dependsstr);
149 while (*p != 0 && *p != '\n') { 167 while (*p != 0 && *p != '\n') {
150 if (*p != ' ') { 168 if (*p != ' ') {
151 if (*p == ',') { 169 if (*p == ',') {
@@ -363,25 +381,25 @@ static int control_read(FILE *file, package_t *p)
363 char *line; 381 char *line;
364 382
365 while ((line = get_line_from_file(file)) != NULL) { 383 while ((line = get_line_from_file(file)) != NULL) {
366 line[strlen(line)] = 0; 384 line[strlen(line) - 1] = '\0';
367 385
368 if (strlen(line) == 0) { 386 if (strlen(line) == 0) {
369 break; 387 break;
370 } else 388 } else
371 if (strstr(line, "Package: ") == line) { 389 if (strstr(line, "Package: ") == line) {
372 p->package = strdup(line + 9); 390 p->package = xstrdup(line + 9);
373 } else 391 } else
374 if (strstr(line, "Status: ") == line) { 392 if (strstr(line, "Status: ") == line) {
375 p->status = status_parse(line + 8); 393 p->status = status_parse(line + 8);
376 } else 394 } else
377 if (strstr(line, "Depends: ") == line) { 395 if (strstr(line, "Depends: ") == line) {
378 p->depends = strdup(line + 9); 396 p->depends = xstrdup(line + 9);
379 } else 397 } else
380 if (strstr(line, "Provides: ") == line) { 398 if (strstr(line, "Provides: ") == line) {
381 p->provides = strdup(line + 10); 399 p->provides = xstrdup(line + 10);
382 } else 400 } else
383 if (strstr(line, "Description: ") == line) { 401 if (strstr(line, "Description: ") == line) {
384 p->description = strdup(line + 13); 402 p->description = xstrdup(line + 13);
385 /* This is specific to the Debian Installer. Ifdef? */ 403 /* This is specific to the Debian Installer. Ifdef? */
386 } else 404 } else
387 if (strstr(line, "installer-menu-item: ") == line) { 405 if (strstr(line, "installer-menu-item: ") == line) {
@@ -400,7 +418,7 @@ static void *status_read(void)
400 package_t *m = 0, *p = 0, *t = 0; 418 package_t *m = 0, *p = 0, *t = 0;
401 419
402 if ((f = fopen(statusfile, "r")) == NULL) { 420 if ((f = fopen(statusfile, "r")) == NULL) {
403 perror(statusfile); 421 perror_msg(statusfile);
404 return 0; 422 return 0;
405 } 423 }
406 424
@@ -409,8 +427,7 @@ static void *status_read(void)
409 } 427 }
410 428
411 while (!feof(f)) { 429 while (!feof(f)) {
412 m = (package_t *)xmalloc(sizeof(package_t)); 430 m = (package_t *)xcalloc(1, sizeof(package_t));
413 memset(m, 0, sizeof(package_t));
414 control_read(f, m); 431 control_read(f, m);
415 if (m->package) { 432 if (m->package) {
416 /* 433 /*
@@ -426,9 +443,8 @@ static void *status_read(void)
426 * of a pseudo package into the status 443 * of a pseudo package into the status
427 * binary-tree. 444 * binary-tree.
428 */ 445 */
429 p = (package_t *)xmalloc(sizeof(package_t)); 446 p = (package_t *)xcalloc(1, sizeof(package_t));
430 memset(p, 0, sizeof(package_t)); 447 p->package = xstrdup(m->provides);
431 p->package = strdup(m->provides);
432 448
433 t = *(package_t **)tsearch(p, &status, package_compare); 449 t = *(package_t **)tsearch(p, &status, package_compare);
434 if (t != p) { 450 if (t != p) {
@@ -459,57 +475,52 @@ static void *status_read(void)
459static int status_merge(void *status, package_t *pkgs) 475static int status_merge(void *status, package_t *pkgs)
460{ 476{
461 FILE *fin, *fout; 477 FILE *fin, *fout;
462 char *line; 478 char *line = NULL;
463 package_t *pkg = 0, *statpkg = 0; 479 package_t *pkg = 0, *statpkg = 0;
464 package_t locpkg; 480 package_t locpkg;
465 int r = 0; 481 int r = 0;
466 482
467 if ((fin = fopen(statusfile, "r")) == NULL) { 483 if ((fout = wfopen(new_statusfile, "w")) == NULL) {
468 perror(statusfile);
469 return 0;
470 }
471 if ((fout = fopen(new_statusfile, "w")) == NULL) {
472 perror(new_statusfile);
473 return 0; 484 return 0;
474 } 485 }
475 if (getenv(udpkg_quiet) == NULL) { 486 if (getenv(udpkg_quiet) == NULL) {
476 printf("(Updating database...)\n"); 487 printf("(Updating database...)\n");
477 } 488 }
489 if ((fin = wfopen(statusfile, "r")) != NULL) {
490 while (((line = get_line_from_file(fin)) != NULL) && !feof(fin)) {
491 line[strlen(line) - 1] = '\0'; /* trim newline */
492 /* If we see a package header, find out if it's a package
493 * that we have processed. if so, we skip that block for
494 * now (write it at the end).
495 *
496 * we also look at packages in the status cache and update
497 * their status fields
498 */
499 if (strstr(line, "Package: ") == line) {
500 for (pkg = pkgs; pkg != 0 && strcmp(line + 9,
501 pkg->package) != 0; pkg = pkg->next) ;
478 502
479 while (((line = get_line_from_file(fin)) != NULL) && !feof(fin)) { 503 locpkg.package = line + 9;
480 line[strlen(line)] = 0; /* trim newline */ 504 statpkg = tfind(&locpkg, &status, package_compare);
481 /* If we see a package header, find out if it's a package
482 * that we have processed. if so, we skip that block for
483 * now (write it at the end).
484 *
485 * we also look at packages in the status cache and update
486 * their status fields
487 */
488 if (strstr(line, "Package: ") == line) {
489 for (pkg = pkgs; pkg != 0 && strncmp(line + 9,
490 pkg->package, strlen(line) - 9) != 0;
491 pkg = pkg->next) ;
492
493 locpkg.package = line + 9;
494 statpkg = tfind(&locpkg, &status, package_compare);
495 505
496 /* note: statpkg should be non-zero, unless the status 506 /* note: statpkg should be non-zero, unless the status
497 * file was changed while we are processing (no locking 507 * file was changed while we are processing (no locking
498 * is currently done... 508 * is currently done...
499 */ 509 */
500 if (statpkg != 0) { 510 if (statpkg != 0) {
501 statpkg = *(package_t **)statpkg; 511 statpkg = *(package_t **)statpkg;
512 }
502 } 513 }
514 if (pkg != 0) {
515 continue;
516 }
517 if (strstr(line, "Status: ") == line && statpkg != 0) {
518 snprintf(line, sizeof(line), "Status: %s",
519 status_print(statpkg->status));
520 }
521 fputs(line, fout);
522 fputc('\n', fout);
503 } 523 }
504 if (pkg != 0) {
505 continue;
506 }
507 if (strstr(line, "Status: ") == line && statpkg != 0) {
508 snprintf(line, sizeof(line), "Status: %s",
509 status_print(statpkg->status));
510 }
511 fputs(line, fout);
512 fputc('\n', fout);
513 } 524 }
514 free(line); 525 free(line);
515 526
@@ -576,13 +587,11 @@ static int dpkg_dounpack(package_t *pkg)
576{ 587{
577 int r = 0, i; 588 int r = 0, i;
578 char *cwd; 589 char *cwd;
579 FILE *outfp;
580 char *src_file = NULL; 590 char *src_file = NULL;
581 char *dst_file = NULL; 591 char *dst_file = NULL;
582 char *lst_file = NULL; 592// char *lst_file = NULL;
583 char *adminscripts[] = { "/prerm", "/postrm", "/preinst", "/postinst", 593 char *adminscripts[] = { "prerm", "postrm", "preinst", "postinst",
584 "/conffiles", "/md5sums", "/shlibs", "/templates" }; 594 "conffiles", "md5sums", "shlibs", "templates" };
585 char buf[1024], buf2[1024];
586 595
587 DPRINTF("Unpacking %s\n", pkg->package); 596 DPRINTF("Unpacking %s\n", pkg->package);
588 597
@@ -592,36 +601,46 @@ static int dpkg_dounpack(package_t *pkg)
592 601
593 /* Installs the package scripts into the info directory */ 602 /* Installs the package scripts into the info directory */
594 for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) { 603 for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) {
604 struct stat src_stat_buf;
605 int src_fd = 0, dst_fd = 0;
606
595 /* The full path of the current location of the admin file */ 607 /* The full path of the current location of the admin file */
596 src_file = xrealloc(src_file, strlen(dpkgcidir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); 608 src_file = xrealloc(src_file, strlen(dpkgcidir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1);
597 strcpy(src_file, dpkgcidir); 609 sprintf(src_file, "%s%s/%s", dpkgcidir, pkg->package, adminscripts[i]);
598 strcat(src_file, pkg->package);
599 strcat(src_file, adminscripts[i]);
600 610
601 /* the full path of where we want the file to be copied to */ 611 /* the full path of where we want the file to be copied to */
602 dst_file = xrealloc(dst_file, strlen(infodir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1); 612 dst_file = xrealloc(dst_file, strlen(infodir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1);
603 strcpy(dst_file, infodir); 613 sprintf(dst_file, "%s%s.%s", infodir, pkg->package, adminscripts[i]);
604 strcat(dst_file, pkg->package);
605 strcat(dst_file, adminscripts[i]);
606 614
607 /* copy admin file to permanent home */ 615 /*
608 if (copy_file(src_file, dst_file, TRUE, FALSE, FALSE) < 0) { 616 * copy admin file to permanent home
609 error_msg_and_die("Cannot copy %s to %s ", buf, buf2); 617 * NOTE: Maybe merge this behaviour into libb/copy_file.c
618 */
619 if (lstat(src_file, &src_stat_buf) == 0) {
620 if ((src_fd = open(src_file, O_RDONLY)) != -1) {
621 if ((dst_fd = open(dst_file, O_WRONLY | O_CREAT, 0644)) == -1) {
622 perror_msg("Opening %s", dst_file);
623 }
624 copy_file_chunk(src_fd, dst_fd, src_stat_buf.st_size);
625 close(src_fd);
626 close(dst_fd);
627 } else {
628 error_msg("couldnt open [%s]\n", src_file);
629 }
610 } 630 }
611
612 /* create the list file */
613 lst_file = (char *) xmalloc(strlen(infodir) + strlen(pkg->package) + 6);
614 strcpy(lst_file, infodir);
615 strcat(lst_file, pkg->package);
616 strcat(lst_file, ".list");
617 deb_extract(dpkg_deb_list, NULL, pkg->file);
618
619 printf("done\n");
620 getchar();
621
622 fclose(outfp);
623 } 631 }
624 632
633 /*
634 * create the list file
635 * FIXME: currently this dumps the lst to stdout instead of a file
636 */
637/* lst_file = (char *) xmalloc(strlen(infodir) + strlen(pkg->package) + 6);
638 strcpy(lst_file, infodir);
639 strcat(lst_file, pkg->package);
640 strcat(lst_file, ".list");
641 deb_extract(dpkg_deb_list, NULL, pkg->file);
642*/
643
625 pkg->status &= status_wantmask; 644 pkg->status &= status_wantmask;
626 pkg->status |= status_wantinstall; 645 pkg->status |= status_wantinstall;
627 pkg->status &= status_flagmask; 646 pkg->status &= status_flagmask;
@@ -647,7 +666,7 @@ static int dpkg_unpackcontrol(package_t *pkg)
647 int length; 666 int length;
648 667
649 /* clean the temp directory (dpkgcidir) be recreating it */ 668 /* clean the temp directory (dpkgcidir) be recreating it */
650 remove_dpkgcidir(); 669 remove_dir(dpkgcidir);
651 if (mkdir(dpkgcidir, S_IRWXU) != 0) { 670 if (mkdir(dpkgcidir, S_IRWXU) != 0) {
652 perror("mkdir"); 671 perror("mkdir");
653 return EXIT_FAILURE; 672 return EXIT_FAILURE;
@@ -664,13 +683,12 @@ static int dpkg_unpackcontrol(package_t *pkg)
664 } 683 }
665 /* now remove trailing version numbers etc */ 684 /* now remove trailing version numbers etc */
666 length = strcspn(tmp_name, "_."); 685 length = strcspn(tmp_name, "_.");
667 pkg->package = (char *) xmalloc(length + 1); 686 pkg->package = (char *) xcalloc(1, length + 1);
668 /* store the package name */ 687 /* store the package name */
669 strncpy(pkg->package, tmp_name, length); 688 strncpy(pkg->package, tmp_name, length);
670 689
671 /* work out the full extraction path */ 690 /* work out the full extraction path */
672 tmp_name = (char *) xmalloc(strlen(dpkgcidir) + strlen(pkg->package) + 9); 691 tmp_name = (char *) xcalloc(1, strlen(dpkgcidir) + strlen(pkg->package) + 9);
673 memset(tmp_name, 0, strlen(dpkgcidir) + strlen(pkg->package) + 9);
674 strcpy(tmp_name, dpkgcidir); 692 strcpy(tmp_name, dpkgcidir);
675 strcat(tmp_name, pkg->package); 693 strcat(tmp_name, pkg->package);
676 694
@@ -679,7 +697,7 @@ static int dpkg_unpackcontrol(package_t *pkg)
679 697
680 /* parse the extracted control file */ 698 /* parse the extracted control file */
681 strcat(tmp_name, "/control"); 699 strcat(tmp_name, "/control");
682 if ((file = fopen(tmp_name, "r")) == NULL) { 700 if ((file = wfopen(tmp_name, "r")) == NULL) {
683 return EXIT_FAILURE; 701 return EXIT_FAILURE;
684 } 702 }
685 if (control_read(file, pkg) == EXIT_FAILURE) { 703 if (control_read(file, pkg) == EXIT_FAILURE) {
@@ -703,7 +721,7 @@ static int dpkg_unpack(package_t *pkgs, void *status)
703 } 721 }
704 } 722 }
705 status_merge(status, pkgs); 723 status_merge(status, pkgs);
706 remove_dpkgcidir(); 724 remove_dir(dpkgcidir);
707 725
708 return r; 726 return r;
709} 727}
@@ -740,8 +758,7 @@ static int dpkg_install(package_t *pkgs, void *status)
740 /* Stage 1: parse all the control information */ 758 /* Stage 1: parse all the control information */
741 for (p = pkgs; p != 0; p = p->next) { 759 for (p = pkgs; p != 0; p = p->next) {
742 if (dpkg_unpackcontrol(p) == EXIT_FAILURE) { 760 if (dpkg_unpackcontrol(p) == EXIT_FAILURE) {
743 perror(p->file); 761 return(EXIT_FAILURE);
744 return EXIT_FAILURE;
745 } 762 }
746 } 763 }
747 764
@@ -765,21 +782,24 @@ static int dpkg_install(package_t *pkgs, void *status)
765 782
766 DPRINTF("Installing %s\n", p->package); 783 DPRINTF("Installing %s\n", p->package);
767 if (dpkg_dounpack(p) != 0) { 784 if (dpkg_dounpack(p) != 0) {
768 perror(p->file); 785 perror_msg(p->file);
769 } 786 }
770 if (dpkg_doconfigure(p) != 0) { 787 if (dpkg_doconfigure(p) != 0) {
771 perror(p->file); 788 perror_msg(p->file);
772 } 789 }
773 } 790 }
774 791
775 if (ordered != 0) { 792 if (ordered != 0) {
776 status_merge(status, pkgs); 793 status_merge(status, pkgs);
777 } 794 }
778 remove_dpkgcidir(); 795 remove_dir(dpkgcidir);
779 796
780 return 0; 797 return 0;
781} 798}
782 799
800/*
801 * Not implemented yet
802 *
783static int dpkg_remove(package_t *pkgs, void *status) 803static int dpkg_remove(package_t *pkgs, void *status)
784{ 804{
785 package_t *p; 805 package_t *p;
@@ -791,55 +811,61 @@ static int dpkg_remove(package_t *pkgs, void *status)
791 811
792 return 0; 812 return 0;
793} 813}
814*/
794 815
795extern int dpkg_main(int argc, char **argv) 816extern int dpkg_main(int argc, char **argv)
796{ 817{
797 char opt = 0; 818 const int arg_install = 1;
798 char *s; 819 const int arg_unpack = 2;
820 const int arg_configure = 4;
821
799 package_t *p, *packages = NULL; 822 package_t *p, *packages = NULL;
800 char *cwd = getcwd(0, 0);
801 void *status = NULL; 823 void *status = NULL;
824 char opt = 0;
825 int optflag = 0;
802 826
803 while (*++argv) { 827 while ((opt = getopt(argc, argv, "iruc")) != -1) {
804 if (**argv == '-') { 828 switch (opt) {
805 /* Nasty little hack to "parse" long options. */ 829 case 'i':
806 s = *argv; 830 optflag |= arg_install;
807 while (*s == '-') { 831 break;
808 s++; 832 case 'u':
809 } 833 optflag |= arg_unpack;
810 opt=s[0]; 834 break;
835 case 'c':
836 optflag |= arg_configure;
837 break;
838 default:
839 show_usage();
840 }
841 }
842
843 while (optind < argc) {
844 p = (package_t *) xcalloc(1, sizeof(package_t));
845 if (optflag & arg_configure) {
846 p->package = xstrdup(argv[optind]);
811 } else { 847 } else {
812 p = (package_t *)xmalloc(sizeof(package_t)); 848 p->file = xstrdup(argv[optind]);
813 memset(p, 0, sizeof(package_t)); 849 }
814 850 p->next = packages;
815 if (**argv == '/') { 851 packages = p;
816 p->file = *argv;
817 } else
818 if (opt != 'c') {
819 p->file = xmalloc(strlen(cwd) + strlen(*argv) + 2);
820 sprintf(p->file, "%s/%s", cwd, *argv);
821 } else {
822 p->package = strdup(*argv);
823 }
824 852
825 p->next = packages; 853 optind++;
826 packages = p;
827 }
828 } 854 }
829 855
856 create_path(dpkgcidir, 0755);
857 create_path(infodir, 0755);
858
830 status = status_read(); 859 status = status_read();
831 860
832 switch (opt) { 861 if (optflag & arg_install) {
833 case 'i': 862 return dpkg_install(packages, status);
834 return dpkg_install(packages, status); 863 }
835 case 'r': 864 else if (optflag & arg_unpack) {
836 return dpkg_remove(packages, status); 865 return dpkg_unpack(packages, status);
837 case 'u': 866 }
838 return dpkg_unpack(packages, status); 867 else if (optflag & arg_configure) {
839 case 'c': 868 return dpkg_configure(packages, status);
840 return dpkg_configure(packages, status);
841 default :
842 show_usage();
843 return EXIT_FAILURE;
844 } 869 }
870 return(EXIT_FAILURE);
845} 871}