Tue Aug 5 20:41:04 2008 UTC ()
Avoid chdir as much as possible.


(joerg)
diff -r1.23.2.7 -r1.23.2.8 pkgsrc/pkgtools/pkg_install/files/delete/perform.c

cvs diff -r1.23.2.7 -r1.23.2.8 pkgsrc/pkgtools/pkg_install/files/delete/Attic/perform.c (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkg_install/files/delete/Attic/perform.c 2008/08/05 19:37:48 1.23.2.7
+++ pkgsrc/pkgtools/pkg_install/files/delete/Attic/perform.c 2008/08/05 20:41:04 1.23.2.8
@@ -1,27 +1,27 @@ @@ -1,27 +1,27 @@
1/* $NetBSD: perform.c,v 1.23.2.7 2008/08/05 19:37:48 joerg Exp $ */ 1/* $NetBSD: perform.c,v 1.23.2.8 2008/08/05 20:41:04 joerg Exp $ */
2 2
3#if HAVE_CONFIG_H 3#if HAVE_CONFIG_H
4#include "config.h" 4#include "config.h"
5#endif 5#endif
6#include <nbcompat.h> 6#include <nbcompat.h>
7#if HAVE_SYS_CDEFS_H 7#if HAVE_SYS_CDEFS_H
8#include <sys/cdefs.h> 8#include <sys/cdefs.h>
9#endif 9#endif
10#ifndef lint 10#ifndef lint
11#if 0 11#if 0
12static const char *rcsid = "from FreeBSD Id: perform.c,v 1.15 1997/10/13 15:03:52 jkh Exp"; 12static const char *rcsid = "from FreeBSD Id: perform.c,v 1.15 1997/10/13 15:03:52 jkh Exp";
13#else 13#else
14__RCSID("$NetBSD: perform.c,v 1.23.2.7 2008/08/05 19:37:48 joerg Exp $"); 14__RCSID("$NetBSD: perform.c,v 1.23.2.8 2008/08/05 20:41:04 joerg Exp $");
15#endif 15#endif
16#endif 16#endif
17 17
18/* 18/*
19 * FreeBSD install - a package for the installation and maintainance 19 * FreeBSD install - a package for the installation and maintainance
20 * of non-core utilities. 20 * of non-core utilities.
21 * 21 *
22 * Redistribution and use in source and binary forms, with or without 22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions 23 * modification, are permitted provided that the following conditions
24 * are met: 24 * are met:
25 * 1. Redistributions of source code must retain the above copyright 25 * 1. Redistributions of source code must retain the above copyright
26 * notice, this list of conditions and the following disclaimer. 26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright 27 * 2. Redistributions in binary form must reproduce the above copyright
@@ -547,47 +547,47 @@ require_print(void) @@ -547,47 +547,47 @@ require_print(void)
547 while ((lpp = TAILQ_FIRST(&lpdelq))) { 547 while ((lpp = TAILQ_FIRST(&lpdelq))) {
548 TAILQ_REMOVE(&lpdelq, lpp, lp_link); 548 TAILQ_REMOVE(&lpdelq, lpp, lp_link);
549 fprintf(stderr, "\t%s\n", lpp->lp_name); 549 fprintf(stderr, "\t%s\n", lpp->lp_name);
550 free_lpkg(lpp); 550 free_lpkg(lpp);
551 } 551 }
552} 552}
553 553
554/* 554/*
555 * This is seriously ugly code following. Written very fast! 555 * This is seriously ugly code following. Written very fast!
556 */ 556 */
557static int 557static int
558pkg_do(char *pkg) 558pkg_do(char *pkg)
559{ 559{
 560 char *pkgdir, *fname;
560 plist_t *p; 561 plist_t *p;
561 FILE *cfile; 562 FILE *cfile;
562 FILE *fp; 563 FILE *fp;
563 char home[MaxPathSize]; 
564 char view[MaxPathSize]; 
565 int cc; 564 int cc;
566 Boolean is_depoted_pkg = FALSE; 565 Boolean is_depoted_pkg = FALSE;
567 566
568 /* Reset some state */ 567 /* Reset some state */
569 if (Plist.head) 568 if (Plist.head)
570 free_plist(&Plist); 569 free_plist(&Plist);
571 570
572 (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", 571 pkgdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(), pkg);
573 _pkgdb_getPKGDB_DIR(), pkg); 572 if (!fexists(pkgdir) || !(isdir(pkgdir) || islinktodir(pkgdir))) {
574 if (!fexists(LogDir) || !(isdir(LogDir) || islinktodir(LogDir))) { 
575 /* Check if the given package name matches something 573 /* Check if the given package name matches something
576 * with 'pkg-[0-9]*' */ 574 * with 'pkg-[0-9]*' */
577 lpkg_head_t trypkgs; 575 lpkg_head_t trypkgs;
578 lpkg_t *lpp; 576 lpkg_t *lpp;
579 int qlen = 0; 577 int qlen = 0;
580 578
 579 free(pkgdir);
 580
581 TAILQ_INIT(&trypkgs); 581 TAILQ_INIT(&trypkgs);
582 582
583 switch (add_installed_pkgs_by_basename(pkg, &trypkgs)) { 583 switch (add_installed_pkgs_by_basename(pkg, &trypkgs)) {
584 case 0: 584 case 0:
585 warnx("package '%s' not installed", pkg); 585 warnx("package '%s' not installed", pkg);
586 return 1; 586 return 1;
587 case -1: 587 case -1:
588 errx(EXIT_FAILURE, "Error during search in pkgdb for %s", pkg); 588 errx(EXIT_FAILURE, "Error during search in pkgdb for %s", pkg);
589 } 589 }
590 590
591 TAILQ_FOREACH(lpp, &trypkgs, lp_link) 591 TAILQ_FOREACH(lpp, &trypkgs, lp_link)
592 qlen++; 592 qlen++;
593 593
@@ -601,218 +601,267 @@ pkg_do(char *pkg) @@ -601,218 +601,267 @@ pkg_do(char *pkg)
601 return 1; 601 return 1;
602 } 602 }
603 603
604 /* 604 /*
605 * Append the package names we've discovered to the 605 * Append the package names we've discovered to the
606 * pkgs list after this one, and return 0 so that we 606 * pkgs list after this one, and return 0 so that we
607 * continue processing the pkgs list. 607 * continue processing the pkgs list.
608 */ 608 */
609 TAILQ_FOREACH(lpp, &trypkgs, lp_link) 609 TAILQ_FOREACH(lpp, &trypkgs, lp_link)
610 TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); 610 TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link);
611 611
612 return 0; 612 return 0;
613 } 613 }
 614 free(pkgdir);
614 setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1); 615 setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1);
615 if (!getcwd(home, MaxPathSize)) { 616 fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME);
616 cleanup(0); 617 if (!fexists(fname)) {
617 errx(2, "unable to get current working directory!"); 618 warnx("package '%s' is not installed, %s missing", pkg, fname);
618 } 619 if (!Force) {
619 if (chdir(LogDir) == FAIL) { 620 free(fname);
620 warnx("unable to change directory to %s! deinstall failed", LogDir); 
621 return 1; 
622 } 
623 if (!fexists(CONTENTS_FNAME)) { 
624 warnx("package '%s' is not installed, %s missing", pkg, CONTENTS_FNAME); 
625 if (!Force) 
626 return 1; 621 return 1;
 622 }
627 } 623 }
628 if (fexists(PRESERVE_FNAME)) { 624 free(fname);
 625
 626 fname = pkgdb_pkg_file(pkg, PRESERVE_FNAME);
 627 if (fexists(fname)) {
629 printf("Package `%s' is marked as not for deletion\n", pkg); 628 printf("Package `%s' is marked as not for deletion\n", pkg);
630 if (Force <= (NoDeleteFiles ? 0 : 1)) { 629 if (Force <= (NoDeleteFiles ? 0 : 1)) {
 630 free(fname);
631 return 1; 631 return 1;
632 } 632 }
633 printf("Deleting anyway\n"); 633 printf("Deleting anyway\n");
634 } 634 }
635 if (!isemptyfile(REQUIRED_BY_FNAME)) { 635 free(fname);
 636
 637 fname = pkgdb_pkg_file(pkg, REQUIRED_BY_FNAME);
 638 if (!isemptyfile(fname)) {
636 /* This package is required by others. Either nuke 639 /* This package is required by others. Either nuke
637 * them (-r), or stop. */ 640 * them (-r), or stop. */
638 if (!Recurse_up) 641 if (!Recurse_up)
639 warnx("package `%s' is required by other packages:", pkg); 642 warnx("package `%s' is required by other packages:", pkg);
640 else if (Verbose) 643 else if (Verbose)
641 printf("Building list of packages that require `%s'" 644 printf("Building list of packages that require `%s'"
642 " to deinstall\n", pkg); 645 " to deinstall\n", pkg);
643 if (require_find(pkg, FIND_UP)) { 646 if (require_find(pkg, FIND_UP)) {
644 if (!Force || Recurse_up) 647 if (!Force || Recurse_up) {
 648 free(fname);
645 return (1); 649 return (1);
 650 }
646 } 651 }
647 chdir(LogDir); /* CWD was changed by require_find() */ 
648 if (!Recurse_up) { 652 if (!Recurse_up) {
649 require_print(); 653 require_print();
650 if (!Force) 654 if (!Force) {
 655 free(fname);
651 return 1; 656 return 1;
 657 }
652 } else 658 } else
653 require_delete(0); 659 require_delete(0);
654 } 660 }
655 if (!isemptyfile(VIEWS_FNAME)) { 661 free(fname);
 662
 663 fname = pkgdb_pkg_file(pkg, VIEWS_FNAME);
 664 if (!isemptyfile(fname)) {
 665 char view[MaxPathSize];
 666
656 /* This package has instances in other views */ 667 /* This package has instances in other views */
657 /* Delete them from the views */ 668 /* Delete them from the views */
658 if ((fp = fopen(VIEWS_FNAME, "r")) == NULL) { 669 if ((fp = fopen(fname, "r")) == NULL) {
659 warnx("unable to open '%s' file", VIEWS_FNAME); 670 warnx("unable to open '%s' file", fname);
 671 free(fname);
660 return 1; 672 return 1;
661 } 673 }
662 while (fgets(view, sizeof(view), fp) != NULL) { 674 while (fgets(view, sizeof(view), fp) != NULL) {
663 if (view[cc = strlen(view) - 1] == '\n') { 675 if (view[cc = strlen(view) - 1] == '\n') {
664 view[cc] = 0; 676 view[cc] = 0;
665 } 677 }
666 if (Verbose) { 678 if (Verbose) {
667 printf("Deleting package %s instance from `%s' view\n", pkg, view); 679 printf("Deleting package %s instance from `%s' view\n", pkg, view);
668 } 680 }
669 if (fexec_skipempty(ProgramPath, "-K", view, 681 if (fexec_skipempty(ProgramPath, "-K", view,
670 (Force > 1) ? "-f -f " : (Force == 1) ? "-f " : "", 682 (Force > 1) ? "-f -f " : (Force == 1) ? "-f " : "",
671 pkg, NULL) != 0) { 683 pkg, NULL) != 0) {
672 warnx("unable to delete package %s from view %s", pkg, view); 684 warnx("unable to delete package %s from view %s", pkg, view);
673 (void) fclose(fp); 685 (void) fclose(fp);
 686 free(fname);
674 return 1; 687 return 1;
675 } 688 }
676 } 689 }
677 (void) fclose(fp); 690 (void) fclose(fp);
678 } 691 }
679 sanity_check(LogDir); 692 free(fname);
680 cfile = fopen(CONTENTS_FNAME, "r"); 693
681 if (!cfile) { 694 sanity_check(pkg);
682 warnx("unable to open '%s' file", CONTENTS_FNAME); 695 fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME);
 696 if ((cfile = fopen(fname, "r")) == NULL) {
 697 warnx("unable to open '%s' file", fname);
 698 free(fname);
683 return 1; 699 return 1;
684 } 700 }
 701 free(fname);
 702
685 read_plist(&Plist, cfile); 703 read_plist(&Plist, cfile);
686 fclose(cfile); 704 fclose(cfile);
687 p = find_plist(&Plist, PLIST_CWD); 705 p = find_plist(&Plist, PLIST_CWD);
688 /* If we have a prefix, replace the first @cwd. */ 706 /* If we have a prefix, replace the first @cwd. */
689 if (Prefix) { 707 if (Prefix) {
690 delete_plist(&Plist, FALSE, PLIST_CWD, NULL); 708 delete_plist(&Plist, FALSE, PLIST_CWD, NULL);
691 add_plist_top(&Plist, PLIST_CWD, Prefix); 709 add_plist_top(&Plist, PLIST_CWD, Prefix);
692 } 710 }
693 if (!p) { 711 if (!p) {
694 warnx("package '%s' doesn't have a prefix", pkg); 712 warnx("package '%s' doesn't have a prefix", pkg);
695 return 1; 713 return 1;
696 } 714 }
697 if (Destdir != NULL) 715 if (Destdir != NULL)
698 setenv(PKG_DESTDIR_VNAME, Destdir, 1); 716 setenv(PKG_DESTDIR_VNAME, Destdir, 1);
699 setenv(PKG_PREFIX_VNAME, p->name, 1); 717 setenv(PKG_PREFIX_VNAME, p->name, 1);
700 setenv(PKG_METADATA_DIR_VNAME, LogDir, 1); 718 setenv(PKG_METADATA_DIR_VNAME, LogDir, 1);
701 /* 719 /*
702 * Ensure that we don't do VIEW-DEINSTALL action for old packages 720 * Ensure that we don't do VIEW-DEINSTALL action for old packages
703 * or for the package in its depot directory. 721 * or for the package in its depot directory.
704 */ 722 */
705 if (!NoDeInstall && fexists(DEINSTALL_FNAME) && fexists(DEPOT_FNAME)) { 723 fname = pkgdb_pkg_file(pkg, DEINSTALL_FNAME);
 724 if (!NoDeInstall && fexists(fname)) {
 725 const char *target, *text;
 726 char *fname2;
 727
 728 fname2 = pkgdb_pkg_file(pkg, DEPOT_FNAME);
 729 if (fexists(fname2)) {
 730 target = "VIEW-DEINSTALL";
 731 text = "view deinstall";
 732 } else {
 733 target = "DEINSTALL";
 734 text = "deinstall";
 735 }
 736 free(fname2);
 737
706 if (Fake) { 738 if (Fake) {
707 printf("Would execute view de-install script at this point (arg: VIEW-DEINSTALL).\n"); 739 printf("Would execute %s script at this point "
 740 "(arg: %s).\n", text, target);
708 } else { 741 } else {
709 (void) fexec(CHMOD_CMD, "+x", DEINSTALL_FNAME, NULL); /* make sure */ 742 pkgdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(), pkg);
710 if (fexec("./" DEINSTALL_FNAME, pkg, "VIEW-DEINSTALL", NULL)) { 743 (void) fexec(CHMOD_CMD, "+x", fname, NULL); /* make sure */
711 warnx("view deinstall script returned error status"); 744 if (fcexec(pkgdir, fname, pkg, target, NULL)) {
 745 warnx("%s script returned error status", text);
712 if (!Force) { 746 if (!Force) {
 747 free(pkgdir);
713 return 1; 748 return 1;
714 } 749 }
715 } 750 }
 751 free(pkgdir);
716 } 752 }
717 } 753 }
718 if (!NoDeInstall && fexists(DEINSTALL_FNAME) && !fexists(DEPOT_FNAME)) { 754 free(fname);
719 if (Fake) 755
720 printf("Would execute de-install script at this point (arg: DEINSTALL).\n"); 
721 else { 
722 (void) fexec(CHMOD_CMD, "+x", DEINSTALL_FNAME, NULL); /* make sure */ 
723 if (fexec("./" DEINSTALL_FNAME, pkg, "DEINSTALL", NULL)) { 
724 warnx("deinstall script returned error status"); 
725 if (!Force) 
726 return 1; 
727 } 
728 } 
729 } 
730 if (!Fake) { 756 if (!Fake) {
731 /* Some packages aren't packed right, so we need to just ignore delete_package()'s status. Ugh! :-( */ 757 /* Some packages aren't packed right, so we need to just ignore delete_package()'s status. Ugh! :-( */
732 if (delete_package(FALSE, CleanDirs, &Plist, NoDeleteFiles, Destdir) == FAIL) 758 if (delete_package(FALSE, CleanDirs, &Plist, NoDeleteFiles, Destdir) == FAIL)
733 warnx("couldn't entirely delete package `%s'\n", pkg); 759 warnx("couldn't entirely delete package `%s'\n", pkg);
734 } 760 } else { /* Fake means Verbose */
735 else { /* Fake means Verbose */ 
736 printf("Attempting to delete package `%s'\n", pkg); 761 printf("Attempting to delete package `%s'\n", pkg);
737 } 762 }
738 if (!isemptyfile(DEPOT_FNAME)) { 763 fname = pkgdb_pkg_file(pkg, DEPOT_FNAME);
 764 if (!isemptyfile(fname)) {
739 if (Verbose) 765 if (Verbose)
740 printf("Attempting to remove the %s registration on package `%s'\n", VIEWS_FNAME, pkg); 766 printf("Attempting to remove the %s registration"
 767 " on package `%s'\n", fname, pkg);
741 if (!Fake) 768 if (!Fake)
742 (void) unview(pkg); 769 (void) unview(pkg);
743 } 770 }
744 /* 771 /*
745 * If this isn't a package in a view, then remove this package 772 * If this isn't a package in a view, then remove this package
746 * from the +REQUIRED_BY list of the packages this depends on. 773 * from the +REQUIRED_BY list of the packages this depends on.
747 */ 774 */
748 if (!fexists(DEPOT_FNAME)) { 775 if (!fexists(fname)) {
749 for (p = Plist.head; p; p = p->next) { 776 for (p = Plist.head; p; p = p->next) {
750 if (p->type != PLIST_PKGDEP) 777 if (p->type != PLIST_PKGDEP)
751 continue; 778 continue;
752 if (Verbose) 779 if (Verbose)
753 printf("Attempting to remove dependency on package `%s'\n", p->name); 780 printf("Attempting to remove dependency on package `%s'\n", p->name);
754 if (!Fake) 781 if (!Fake)
755 match_installed_pkgs(p->name, undepend, pkg); 782 match_installed_pkgs(p->name, undepend, pkg);
756 } 783 }
757 } 784 }
 785 free(fname);
758 if (Recurse_down) { 786 if (Recurse_down) {
759 /* Also remove the packages further down, now that there's 787 /* Also remove the packages further down, now that there's
760 * (most likely) nothing left which requires them. */ 788 * (most likely) nothing left which requires them. */
761 if (Verbose) 789 if (Verbose)
762 printf("Building list of packages that `%s' required\n", pkg); 790 printf("Building list of packages that `%s' required\n", pkg);
763 if (require_find(pkg, FIND_DOWN)) 791 if (require_find(pkg, FIND_DOWN))
764 return (1); 792 return (1);
765 793
766 require_delete(1); 794 require_delete(1);
767 } 795 }
768 if (!NoDeInstall && fexists(DEINSTALL_FNAME) && !fexists(DEPOT_FNAME)) { 796
769 if (Fake) 797 fname = pkgdb_pkg_file(pkg, DEINSTALL_FNAME);
770 printf("Would execute post-de-install script at this point (arg: POST-DEINSTALL).\n"); 798 if (!NoDeInstall && fexists(fname)) {
771 else { 799 char *fname2;
772 (void) fexec(CHMOD_CMD, "+x", DEINSTALL_FNAME, NULL); /* make sure */ 800
773 if (fexec("./" DEINSTALL_FNAME, pkg, "POST-DEINSTALL", NULL)) { 801 fname2 = pkgdb_pkg_file(pkg, DEPOT_FNAME);
774 warnx("post-deinstall script returned error status"); 802 if (!fexists(fname2)) {
775 if (!Force) 803 if (Fake)
776 return 1; 804 printf("Would execute post-de-install script at this point (arg: POST-DEINSTALL).\n");
 805 else {
 806 pkgdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(), pkg);
 807 (void) fexec(CHMOD_CMD, "+x", fname, NULL); /* make sure */
 808 if (fcexec(pkgdir, fname, pkg, "POST-DEINSTALL", NULL)) {
 809 warnx("post-deinstall script returned error status");
 810 if (!Force) {
 811 free(pkgdir);
 812 free(fname);
 813 free(fname2);
 814 return 1;
 815 }
 816 }
 817 free(pkgdir);
777 } 818 }
778 } 819 }
 820 free(fname2);
779 } 821 }
780 if (fexists(VIEWS_FNAME)) 822 free(fname);
 823
 824 fname = pkgdb_pkg_file(pkg, VIEWS_FNAME);
 825 if (fexists(fname))
781 is_depoted_pkg = TRUE; 826 is_depoted_pkg = TRUE;
 827 free(fname);
782 828
783 /* Change out of LogDir before we remove it. 829 /* Change out of LogDir before we remove it.
784 * Do not fail here, as the package is not yet completely deleted! */ 830 * Do not fail here, as the package is not yet completely deleted! */
785 if (chdir(home) == FAIL) 
786 warnx("Oops - removed current working directory. Oh, well."); 
787 if (!Fake) { 831 if (!Fake) {
788 /* Finally nuke the +-files and the pkgdb-dir (/var/db/pkg/foo) */ 832 /* Finally nuke the +-files and the pkgdb-dir (/var/db/pkg/foo) */
789 (void) remove_files(LogDir, "+*"); 833 pkgdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(), pkg);
790 if (isemptydir(LogDir)) 834 (void) remove_files(pkgdir, "+*");
791 (void)rmdir(LogDir); 835 if (isemptydir(pkgdir))
 836 (void)rmdir(pkgdir);
792 else if (is_depoted_pkg) 837 else if (is_depoted_pkg)
793 warnx("%s is not empty", LogDir); 838 warnx("%s is not empty", pkgdir);
794 else if (Force) { 839 else if (Force) {
795 if (fexec(REMOVE_CMD, "-rf", LogDir, NULL) != 0) { 840 if (fexec(REMOVE_CMD, "-rf", pkgdir, NULL) != 0) {
796 warnx("couldn't remove log entry in %s", LogDir); 841 warnx("couldn't remove log entry in %s", pkgdir);
 842 free(pkgdir);
797 return 1; 843 return 1;
798 } else { 844 } else {
799 warnx("log entry forcefully removed in %s", LogDir); 845 warnx("log entry forcefully removed in %s", pkgdir);
 846 free(pkgdir);
800 return 0; 847 return 0;
801 } 848 }
802 } else { 849 } else {
803 warnx("couldn't remove log entry in %s", LogDir); 850 warnx("couldn't remove log entry in %s", pkgdir);
 851 free(pkgdir);
804 return 1; 852 return 1;
805 } 853 }
 854 free(pkgdir);
806 } 855 }
807 return 0; 856 return 0;
808} 857}
809 858
810int 859int
811pkg_perform(lpkg_head_t *pkghead) 860pkg_perform(lpkg_head_t *pkghead)
812{ 861{
813 int err_cnt = 0; 862 int err_cnt = 0;
814 int oldcwd; 863 int oldcwd;
815 lpkg_t *lpp; 864 lpkg_t *lpp;
816 865
817 /* save cwd */ 866 /* save cwd */
818 oldcwd = open(".", O_RDONLY, 0); 867 oldcwd = open(".", O_RDONLY, 0);