4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2017 Peter Tribble.
27 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
30 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
43 #include <sys/types.h>
51 #include <instzones_api.h>
58 struct cfent
**eptlist
;
62 extern char **environ
;
65 extern sighdlrFunc_t
*quitGetTrapHandler(void);
66 extern void quitSetSilentExit(boolean_t a_silentExit
);
67 extern void quitSetZoneName(char *a_zoneName
);
72 extern void rcksetPreremoveCheck(boolean_t
);
73 extern void rcksetZoneName(char *);
74 extern int rckpriv(void);
75 extern int rckdepend(void);
76 extern int rckrunlevel(void);
79 extern int delmap(int flag
, char *pkginst
, PKGserver
*server
, VFP_T
**tfp
);
81 #define DEFPATH "/sbin:/usr/sbin:/usr/bin"
83 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
84 #define TEXT_DOMAIN "SYS_TEST"
87 /* This is the text for the "-O parent-zone-name=" option */
89 #define PARENTZONENAME "parent-zone-name="
90 #define PARENTZONENAME_LEN ((sizeof (PARENTZONENAME))-1)
92 /* This is the text for the "-O parent-zone-type=" option */
94 #define PARENTZONETYPE "parent-zone-type="
95 #define PARENTZONETYPE_LEN ((sizeof (PARENTZONETYPE))-1)
97 struct admin adm
; /* holds info about installation admin */
98 int dreboot
; /* non-zero if reboot required after installation */
99 int ireboot
; /* non-zero if immediate reboot required */
100 int failflag
; /* non-zero if fatal error has occurred */
101 int warnflag
; /* non-zero if non-fatal error has occurred */
102 int pkgverbose
; /* non-zero if verbose mode is selected */
104 int nocnflct
= 0; /* pkgdbmerg needs this defined */
105 int nosetuid
= 0; /* pkgdbmerg needs this defined */
107 char *pkginst
; /* current package (source) instance to process */
111 char pkgloc
[PATH_MAX
];
114 * The following variable is the name of the device to which stdin
115 * is connected during execution of a procedure script. /dev/null is
116 * correct for all ABI compliant packages. For non-ABI-compliant
117 * packages, the '-o' command line switch changes this to /dev/tty
118 * to allow user interaction during these scripts. -- JST
120 static char *script_in
= PROC_STDIN
; /* assume ABI compliance */
122 static char *client_mntdir
; /* mount point for client's basedir */
123 static char pkgbin
[PATH_MAX
],
125 *admnfile
, /* file to use for installation admin */
126 *tmpdir
; /* location to place temporary files */
128 static void ckreturn(int retcode
, char *msg
);
129 static void rmclass(char *aclass
, int rm_remote
, char *a_zoneName
);
130 static void usage(void);
133 * Set by -O debug: debug output is enabled?
135 static boolean_t debugFlag
= B_FALSE
;
138 * Set by -O preremovecheck: do remove dependency checking only
140 static boolean_t preremoveCheck
= B_FALSE
;
142 /* Set by -O parent-zone-name= */
144 static char *parentZoneName
= (char *)NULL
;
146 /* Set by -O parent-zone-type= */
148 static char *parentZoneType
= (char *)NULL
;
150 static int nointeract
; /* != 0 no interaction with user should occur */
155 main(int argc
, char *argv
[])
161 char *prog_full_name
= NULL
;
164 char *vfstab_file
= NULL
;
165 char *zoneName
= (char *)NULL
;
166 char cmdbin
[PATH_MAX
];
167 char param
[MAX_PKG_PARAM_LENGTH
];
169 char script
[PATH_MAX
];
176 int nodelete
= 0; /* do not delete file or run scripts */
177 int pkgrmremote
= 0; /* dont remove remote objects */
178 struct sigaction nact
;
179 struct sigaction oact
;
180 PKGserver pkgserver
= NULL
;
183 /* reset contents of all default paths */
185 (void) memset(cmdbin
, '\0', sizeof (cmdbin
));
187 /* initialize locale environment */
189 (void) setlocale(LC_ALL
, "");
190 (void) textdomain(TEXT_DOMAIN
);
192 /* initialize program name */
194 prog_full_name
= argv
[0];
195 (void) set_prog_name(argv
[0]);
197 /* tell spmi zones interface how to access package output functions */
199 z_set_output_functions(echo
, echoDebug
, progerr
);
201 /* exit if not root */
204 progerr(ERR_NOT_ROOT
, get_prog_name());
209 /* Read PKG_INSTALL_ROOT from the environment, if it's there. */
211 if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
212 progerr(ERR_ROOT_SET
);
216 pkgserversetmode(DEFAULTMODE
);
218 /* parse command line options */
220 while ((c
= getopt(argc
, argv
, "?Aa:b:FMN:nO:oR:V:vy")) != EOF
) {
223 * Same as pkgrm: Allow admin to remove package objects from
224 * a shared area from a reference client.
231 * Same as pkgrm: Use the installation
232 * administration file, admin, in place of the
233 * default admin file. pkgrm first looks in the
234 * current working directory for the administration
235 * file. If the specified administration file is not
236 * in the current working directory, pkgrm looks in
237 * the /var/sadm/install/admin directory for the
238 * administration file.
241 admnfile
= flex_device(optarg
, 0);
245 * Same as pkgrm: location where package executables
246 * can be found - default is /usr/sadm/install/bin.
249 if (!path_valid(optarg
)) {
250 progerr(ERR_PATH
, optarg
);
253 if (isdir(optarg
) != 0) {
254 char *p
= strerror(errno
);
255 progerr(ERR_CANNOT_USE_DIR
, optarg
, p
);
258 (void) strlcpy(cmdbin
, optarg
, sizeof (cmdbin
));
262 * Same as pkgrm: suppresses the removal of any
263 * files and any class action scripts, and suppresses
264 * the running of any class action scripts. The
265 * package files remain but the package looks like it
266 * is not installed. This is mainly for use by the
274 * Same as pkgrm: Instruct pkgrm not to use the
275 * $root_path/etc/vfstab file for determining the
276 * client's mount points. This option assumes the
277 * mount points are correct on the server and it
278 * behaves consistently with Solaris 2.5 and earlier
286 * Different from pkgrm: specify program name to use
290 (void) set_prog_name(optarg
);
294 * Same as pkgrm: package removal occurs in
295 * non-interactive mode. Suppress output of the list of
296 * removed files. The default mode is interactive.
300 (void) echoSetFlag(B_FALSE
);
304 * Almost same as pkgrm: the -O option allows the behavior
305 * of the package tools to be modified. Recognized options:
307 * ---> enable debugging output
309 * ---> perform a "pre removal" check of the specified
310 * ---> package - suppress all regular output and cause a
311 * ---> series of one or more "name=value" pair format lines
312 * ---> to be output that describes the "removability" of
313 * ---> the specified package
314 * -> enable-hollow-package-support
315 * --> Enable hollow package support. When specified, for any
316 * --> package that has SUNW_PKG_HOLLOW=true:
317 * --> Do not calculate and verify package size against target
318 * --> Do not run any package procedure or class action scripts
319 * --> Do not create or remove any target directories
320 * --> Do not perform any script locking
321 * --> Do not install or uninstall any components of any package
322 * --> Do not output any status or database update messages
325 for (p
= strtok(optarg
, ","); p
!= (char *)NULL
;
326 p
= strtok(NULL
, ",")) {
328 /* process debug option */
330 if (strcmp(p
, "debug") == 0) {
331 /* set debug flag/enable debug output */
333 (void) echoDebugSetFlag(debugFlag
);
335 /* debug info on arguments to pkgadd */
336 for (n
= 0; n
< argc
&& argv
[n
]; n
++) {
337 echoDebug(DBG_ARG
, n
, argv
[n
]);
343 /* process enable-hollow-package-support opt */
346 "enable-hollow-package-support") == 0) {
347 set_depend_pkginfo_DB(B_TRUE
);
351 /* process preremovecheck option */
353 if (strcmp(p
, "preremovecheck") == 0) {
354 preremoveCheck
= B_TRUE
;
355 nointeract
++; /* -n */
357 quitSetSilentExit(B_TRUE
);
361 /* process addzonename option */
363 if (strcmp(p
, "addzonename") == 0) {
364 zoneName
= z_get_zonename();
365 quitSetZoneName(zoneName
);
369 /* process parent-zone-name option */
371 if (strncmp(p
, PARENTZONENAME
,
372 PARENTZONENAME_LEN
) == 0) {
373 parentZoneName
= p
+PARENTZONENAME_LEN
;
377 /* process parent-zone-type option */
379 if (strncmp(p
, PARENTZONETYPE
,
380 PARENTZONETYPE_LEN
) == 0) {
381 parentZoneType
= p
+PARENTZONETYPE_LEN
;
385 if (strncmp(p
, PKGSERV_MODE
,
386 PKGSERV_MODE_LEN
) == 0) {
387 pkgserversetmode(pkgparsemode(p
+
391 /* option not recognized - issue warning */
393 progerr(ERR_INVALID_O_OPTION
, p
);
399 * Different from pkgrm: This is an old non-ABI package
403 script_in
= PROC_XSTDIN
;
407 * Same as pkgrm: defines the full path name of a
408 * directory to use as the root_path. All files,
409 * including package system information files, are
410 * relocated to a directory tree starting in the
411 * specified root_path.
414 if (!set_inst_root(optarg
)) {
415 progerr(ERR_ROOT_CMD
);
421 * Same as pkgrm: allow admin to establish the client
422 * filesystem using a vfstab-like file of stable format.
425 vfstab_file
= flex_device(optarg
, 2);
430 * Same as pkgrm: trace all of the scripts that
431 * get executed by pkgrm, located in the
432 * pkginst/install directory. This option is used for
433 * debugging the procedural and non-procedural
441 * Different from pkgrm: process this package using
442 * old non-ABI symlinks
445 set_nonABI_symlinks();
452 * Although usage() calls a noreturn function,
453 * needed to add return (1); so that main() would
454 * pass compilation checks. The statement below
455 * should never be executed.
462 * ********************************************************************
463 * validate command line options
464 * ********************************************************************
467 (void) echoDebugSetFlag(debugFlag
);
468 (void) log_set_verbose(debugFlag
);
470 if (z_running_in_global_zone()) {
471 echoDebug(DBG_ENTRY_IN_GZ
, prog_full_name
);
473 echoDebug(DBG_ENTRY_IN_LZ
, prog_full_name
, getzoneid(),
477 /* establish cmdbin path */
479 if (cmdbin
[0] == '\0') {
480 (void) strlcpy(cmdbin
, PKGBIN
, sizeof (cmdbin
));
483 /* Read the mount table */
485 if (get_mntinfo(map_client
, vfstab_file
)) {
490 * This function defines the standard /var/... directories used later
491 * to construct the paths to the various databases.
494 set_PKGpaths(get_inst_root());
497 * If this is being removed from a client whose /var filesystem is
498 * mounted in some odd way, remap the administrative paths to the
499 * real filesystem. This could be avoided by simply mounting up the
500 * client now; but we aren't yet to the point in the process where
501 * modification of the filesystem is permitted.
503 if (is_an_inst_root()) {
506 fsys_value
= fsys(get_PKGLOC());
507 if (use_srvr_map_n(fsys_value
))
508 set_PKGLOC(server_map(get_PKGLOC(), fsys_value
));
510 fsys_value
= fsys(get_PKGADM());
511 if (use_srvr_map_n(fsys_value
))
512 set_PKGADM(server_map(get_PKGADM(), fsys_value
));
514 pkgrmremote
= 0; /* Makes no sense on local host. */
518 * hook SIGINT and SIGHUP interrupts into quit.c's trap handler
521 /* hold SIGINT/SIGHUP interrupts */
523 (void) sighold(SIGHUP
);
524 (void) sighold(SIGINT
);
526 /* connect quit.c:trap() to SIGINT */
528 nact
.sa_handler
= quitGetTrapHandler();
529 nact
.sa_flags
= SA_RESTART
;
530 (void) sigemptyset(&nact
.sa_mask
);
532 (void) sigaction(SIGINT
, &nact
, &oact
);
534 /* connect quit.c:trap() to SIGHUP */
536 nact
.sa_handler
= quitGetTrapHandler();
537 nact
.sa_flags
= SA_RESTART
;
538 (void) sigemptyset(&nact
.sa_mask
);
540 (void) sigaction(SIGHUP
, &nact
, &oact
);
542 /* release hold on signals */
544 (void) sigrelse(SIGHUP
);
545 (void) sigrelse(SIGINT
);
547 pkginst
= argv
[optind
++];
548 if (optind
!= argc
) {
552 /* validate package software database (contents) file */
559 * Acquire the package lock - currently at "remove initialization"
562 if (!lockinst(get_prog_name(), pkginst
, "remove-initial")) {
566 /* establish temporary directory to use */
568 tmpdir
= getenv("TMPDIR");
569 if (tmpdir
== NULL
) {
573 echoDebug(DBG_PKGREMOVE_TMPDIR
, tmpdir
);
576 * Initialize installation admin parameters by reading
580 echoDebug(DBG_PKGREMOVE_ADMINFILE
, admnfile
? admnfile
: "");
581 setadminFile(admnfile
);
584 * about to perform first operation that could be modified by the
585 * preremove check option - if preremove check is selected (that is,
586 * only gathering dependencies), then output a debug message to
587 * indicate that the check is beginning. Also turn echo() output
588 * off and set various other flags.
591 if (preremoveCheck
== B_TRUE
) {
592 (void) echoSetFlag(B_FALSE
);
593 echoDebug(DBG_PKGREMOVE_PRERMCHK
, pkginst
? pkginst
: "",
594 zoneName
? zoneName
: "global");
595 rcksetPreremoveCheck(B_TRUE
);
596 rcksetZoneName(zoneName
);
599 (void) snprintf(pkgloc
, sizeof (pkgloc
), "%s/%s", get_PKGLOC(),
601 (void) snprintf(pkgbin
, sizeof (pkgbin
), "%s/install", pkgloc
);
602 (void) snprintf(rlockfile
, sizeof (rlockfile
), "%s/!R-Lock!", pkgloc
);
605 progerr(ERR_CHDIR
, pkgbin
);
609 echo(MSG_PREREMOVE_REMINST
, pkginst
);
612 * if a lock file is present, then a previous attempt to remove this
613 * package may have been unsuccessful.
616 if (access(rlockfile
, F_OK
) == 0) {
618 echoDebug(DBG_PKGINSTALL_HAS_LOCKFILE
, pkginst
, rlockfile
,
619 zoneName
? zoneName
: "global");
623 * Process all parameters from the pkginfo file
624 * and place them in the execution environment
627 /* Add DB retreival of the pkginfo parameters here */
628 (void) snprintf(path
, sizeof (path
), "%s/pkginfo", pkgloc
);
629 if ((fp
= fopen(path
, "r")) == NULL
) {
630 progerr(ERR_PKGINFO
, path
);
634 /* Mount up the client if necessary. */
635 if (map_client
&& !mount_client()) {
636 logerr(MSG_MANMOUNT
);
639 /* Get mount point of client */
640 client_mntdir
= getenv("CLIENT_MNTDIR");
645 * current environment has been read; clear environment out
646 * so putparam() can be used to populate the new environment
647 * to be passed to any executables/scripts.
652 if (nonABI_symlinks()) {
653 putparam("PKG_NONABI_SYMLINKS", "TRUE");
657 * read the pkginfo file and fix any PKGSAV path - the correct
658 * install_root will be prepended to the existing path.
662 while (value
= fpkgparam(fp
, param
)) {
666 /* strip out any setting of PATH */
668 if (strcmp(param
, "PATH") == 0) {
674 /* if not PKGSAV then write out unchanged */
676 if (strcmp(param
, "PKGSAV") != 0) {
677 putparam(param
, value
);
684 * PKGSAV parameter found - interpret the directory:
685 * If in host:path format or marked with the leading "//",
686 * then there is no client-relative translation - take it
687 * literally later rather than use fixpath().
690 if (strstr(value
, ":/")) {
691 /* no modification needed */
693 } else if (strstr(value
, "//") == value
) {
695 } else if (is_an_inst_root()) {
696 /* This PKGSAV needs to be made client-relative. */
697 newvalue
= fixpath(value
);
701 putparam(param
, value
+validx
);
708 /* write parent condition information to environment */
710 putConditionInfo(parentZoneName
, parentZoneType
);
715 * Now do all the various setups based on ABI compliance
718 /* Read the environment provided by the pkginfo file */
719 abi_comp_ptr
= getenv("NONABI_SCRIPTS");
721 /* if not ABI compliant set global flag */
722 abi_sym_ptr
= getenv("PKG_NONABI_SYMLINKS");
723 if (abi_sym_ptr
&& strncasecmp(abi_sym_ptr
, "TRUE", 4) == 0) {
724 set_nonABI_symlinks();
728 * If pkginfo says it's not compliant then set non_abi_scripts.
730 if (abi_comp_ptr
&& strncmp(abi_comp_ptr
, "TRUE", 4) == 0) {
731 script_in
= PROC_XSTDIN
;
735 * Since this is a removal, we can tell whether it's absolute or
736 * not from the resident pkginfo file read above.
738 if ((err
= set_basedirs((getenv("BASEDIR") != NULL
), adm
.basedir
,
739 pkginst
, nointeract
)) != 0) {
744 * See if were are removing a package that only wants to update
745 * the database or only remove files associated with CAS's. We
746 * only check the PKG_HOLLOW_VARIABLE variable if told to do so by
750 if (is_depend_pkginfo_DB()) {
751 pt
= getenv(PKG_HOLLOW_VARIABLE
);
753 if ((pt
!= NULL
) && (strncasecmp(pt
, "true", 4) == 0)) {
754 echoDebug(DBG_PKGREMOVE_HOLLOW_ENABLED
);
757 * this is a hollow package and hollow package support
758 * is enabled -- override admin settings to suppress
759 * checks that do not make sense since no scripts will
760 * be executed and no files will be removed.
763 setadminSetting("conflict", "nocheck");
764 setadminSetting("setuid", "nocheck");
765 setadminSetting("action", "nocheck");
766 setadminSetting("partial", "nocheck");
767 setadminSetting("space", "nocheck");
768 setadminSetting("authentication", "nocheck");
770 echoDebug(DBG_PKGREMOVE_HOLLOW_DISABLED
);
771 set_depend_pkginfo_DB(B_FALSE
);
777 /* If client mount point, add it to pkgremove environment */
779 if (client_mntdir
!= NULL
) {
780 putparam("CLIENT_MNTDIR", client_mntdir
);
783 /* Establish the class list and the class attributes. */
785 if ((value
= getenv("CLASSES")) != NULL
) {
786 cl_sets(qstrdup(value
));
788 progerr(ERR_CLASSES
, path
);
792 /* establish path and tmpdir */
794 if (cmdbin
[0] == '\0') {
795 (void) strlcpy(cmdbin
, PKGBIN
, sizeof (cmdbin
));
798 (void) snprintf(path
, sizeof (path
), "%s:%s", DEFPATH
, cmdbin
);
799 putparam("PATH", path
);
801 putparam("TMPDIR", tmpdir
);
804 * Check ulimit requirement (provided in pkginfo). The purpose of
805 * this limit is to terminate pathological file growth resulting from
806 * file edits in scripts. It does not apply to files in the pkgmap
807 * and it does not apply to any database files manipulated by the
808 * installation service.
810 if (value
= getenv("ULIMIT")) {
811 if (assign_ulimit(value
) == -1) {
812 progerr(ERR_BADULIMIT
, value
);
815 putparam("PKG_ULIMIT", "TRUE");
819 * If only gathering dependencies, check and output status of all
820 * remaining dependencies and exit.
823 if (preremoveCheck
== B_TRUE
) {
825 * make sure current runlevel is appropriate
828 (void) fprintf(stdout
, "rckrunlevel=%d\n", rckrunlevel());
831 * determine if any packaging scripts provided with
832 * this package will execute as a priviledged user
835 (void) fprintf(stdout
, "rckpriv=%d\n", rckpriv());
838 * verify package dependencies
841 (void) fprintf(stdout
, "rckdepend=%d\n", rckdepend());
844 * ****** preremove check done - exit ******
847 echoDebug(DBG_PKGREMOVE_PRERMCHK_OK
);
853 * Not gathering dependencies only, proceed to check dependencies
854 * and continue with the package removal operation.
858 * make sure current runlevel is appropriate
869 * determine if any packaging scripts provided with
870 * this package will execute as a priviledged user
881 * verify package dependencies
891 * *********************************************************************
892 * the actual removal of the package begins here
893 * *********************************************************************
897 * create lockfile to indicate start of removal
900 if ((fd
= open(rlockfile
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644)) < 0) {
901 progerr(ERR_LOCKFILE
, rlockfile
);
907 if (zoneName
== (char *)NULL
) {
908 echo(MSG_PKGREMOVE_PROCPKG_GZ
);
909 echoDebug(DBG_PKGREMOVE_PROCPKG_GZ
, pkginst
, rlockfile
);
911 echo(MSG_PKGREMOVE_PROCPKG_LZ
, zoneName
);
912 echoDebug(DBG_PKGREMOVE_PROCPKG_LZ
, pkginst
, rlockfile
,
915 if (delmap(0, pkginst
, &pkgserver
, &tmpfp
) != 0) {
916 progerr(ERR_DB_QUERY
, pkginst
);
921 * Run a preremove script if one is provided by the package.
922 * Don't execute preremove script if only updating the DB.
923 * Don't execute preremove script if files are not being deleted.
926 /* update the lock - at the preremove script */
927 lockupd("preremove");
929 /* execute preremove script if one is provided */
930 (void) snprintf(script
, sizeof (script
), "%s/preremove", pkgbin
);
931 if (access(script
, F_OK
) != 0) {
932 /* no script present */
933 echoDebug(DBG_PKGREMOVE_POC_NONE
, pkginst
,
934 zoneName
? zoneName
: "global");
935 } else if (nodelete
) {
936 /* not deleting files: skip preremove script */
937 echoDebug(DBG_PKGREMOVE_POC_NODEL
, pkginst
, script
,
938 zoneName
? zoneName
: "global");
939 } else if (is_depend_pkginfo_DB()) {
940 /* updating db only: skip preremove script */
941 echoDebug(DBG_PKGREMOVE_POC_DBUPD
, pkginst
, script
,
942 zoneName
? zoneName
: "global");
944 /* script present and ok to run: run the script */
945 set_ulimit("preremove", ERR_PREREMOVE
);
946 if (zoneName
== (char *)NULL
) {
947 echo(MSG_PKGREMOVE_EXEPOC_GZ
);
948 echoDebug(DBG_PKGREMOVE_EXEPOC_GZ
, pkginst
, script
);
950 echo(MSG_PKGREMOVE_EXEPOC_LZ
, zoneName
);
951 echoDebug(DBG_PKGREMOVE_EXEPOC_LZ
, pkginst
, script
,
954 putparam("PKG_PROC_SCRIPT", "preremove");
956 ckreturn(pkgexecl(script_in
, PROC_STDOUT
,
957 PROC_USER
, PROC_GRP
, SHELL
, "-x",
958 script
, NULL
), ERR_PREREMOVE
);
960 ckreturn(pkgexecl(script_in
, PROC_STDOUT
,
961 PROC_USER
, PROC_GRP
, SHELL
, script
,
962 NULL
), ERR_PREREMOVE
);
967 /* update the lock - doing removal */
972 * Ensure that the contents file is updated even if the db has
973 * been upgraded, in the case that there are relevant entries
974 * in a special_contents file. The return value is ignored
975 * since we do not want special_contents operation to prevent
976 * pkgremove from succeeding. We do report errors to stderr.
980 * Remove all components belonging to this package.
981 * Don't remove components if only updating the DB.
982 * Don't remove components if files are not being deleted.
986 echoDebug(DBG_PKGREMOVE_REM_NODEL
, pkginst
,
987 zoneName
? zoneName
: "global");
988 } else if (is_depend_pkginfo_DB()) {
989 echoDebug(DBG_PKGREMOVE_REM_DBUPD
, pkginst
,
990 zoneName
? zoneName
: "global");
992 echoDebug(DBG_PKGREMOVE_REM
, pkginst
,
993 zoneName
? zoneName
: "global");
995 * remove package one class at a time
998 /* reverse order of classes */
999 for (i
= cl_getn() - 1; i
>= 0; i
--) {
1000 rmclass(cl_nam(i
), pkgrmremote
, zoneName
);
1003 rmclass(NULL
, pkgrmremote
, zoneName
);
1006 z_destroyMountTable();
1009 * Execute postremove script, if any
1010 * Don't execute postremove script if only updating the DB.
1011 * Don't execute postremove script if files are not being deleted.
1014 /* update the lock - at the postremove script */
1015 lockupd("postremove");
1017 /* execute postremove script if one is provided */
1018 (void) snprintf(script
, sizeof (script
), "%s/postremove", pkgbin
);
1019 if (access(script
, F_OK
) != 0) {
1020 /* no script present */
1021 echoDebug(DBG_PKGREMOVE_PIC_NONE
, pkginst
,
1022 zoneName
? zoneName
: "global");
1023 } else if (nodelete
) {
1024 /* not deleting files: skip postremove script */
1025 echoDebug(DBG_PKGREMOVE_PIC_NODEL
, pkginst
, script
,
1026 zoneName
? zoneName
: "global");
1027 } else if (is_depend_pkginfo_DB()) {
1028 /* updating db only: skip postremove script */
1029 echoDebug(DBG_PKGREMOVE_PIC_DBUPD
, pkginst
, script
,
1030 zoneName
? zoneName
: "global");
1032 /* script present and ok to run: run the script */
1033 set_ulimit("postremove", ERR_POSTREMOVE
);
1034 if (zoneName
== (char *)NULL
) {
1035 echo(MSG_PKGREMOVE_EXEPIC_GZ
);
1036 echoDebug(DBG_PKGREMOVE_EXEPIC_GZ
, pkginst
, script
);
1038 echo(MSG_PKGREMOVE_EXEPIC_LZ
, zoneName
);
1039 echoDebug(DBG_PKGREMOVE_EXEPIC_LZ
, pkginst
, script
,
1042 putparam("PKG_PROC_SCRIPT", "postremove");
1043 putparam("TMPDIR", tmpdir
);
1045 ckreturn(pkgexecl(script_in
, PROC_STDOUT
, PROC_USER
,
1046 PROC_GRP
, SHELL
, "-x", script
, NULL
),
1049 ckreturn(pkgexecl(script_in
, PROC_STDOUT
, PROC_USER
,
1050 PROC_GRP
, SHELL
, script
, NULL
),
1056 if (zoneName
== (char *)NULL
) {
1057 echo(MSG_PKGREMOVE_UPDINF_GZ
);
1059 echo(MSG_PKGREMOVE_UPDINF_LZ
, zoneName
);
1062 if (delmap(1, pkginst
, &pkgserver
, &tmpfp
) != 0) {
1063 progerr(ERR_DB_QUERY
, pkginst
);
1067 if (!warnflag
&& !failflag
) {
1073 if ((z_running_in_global_zone() == B_TRUE
) &&
1074 (pkgIsPkgInGzOnly(get_inst_root(), pkginst
) == B_TRUE
)) {
1077 b
= pkgRemovePackageFromGzonlyList(get_inst_root(), pkginst
);
1079 progerr(ERR_PKGREMOVE_GZONLY_REMOVE
, pkginst
);
1084 /* release the generic package lock */
1086 (void) unlockinst();
1088 pkgcloseserver(pkgserver
);
1091 /* LINTED: no return */
1095 issymlink(char *path
)
1097 struct stat statbuf
;
1100 * Obtain status of path; if symbolic link get link's status
1103 if (lstat(path
, &statbuf
) != 0) {
1104 return (1); /* not symlink */
1108 * Status obtained - if symbolic link, return 0
1111 if ((statbuf
.st_mode
& S_IFMT
) == S_IFLNK
) {
1112 return (0); /* is a symlink */
1116 * Not a symbolic link - return 1
1119 return (1); /* not symlink */
1123 rmclass(char *aclass
, int rm_remote
, char *a_zoneName
)
1127 char tmpfile
[PATH_MAX
];
1128 char script
[PATH_MAX
];
1131 char *save_path
= NULL
;
1134 if (aclass
== NULL
) {
1135 for (i
= 0; i
< eptnum
; i
++) {
1136 if (eptlist
[i
] != NULL
) {
1137 rmclass(eptlist
[i
]->pkg_class
,
1138 rm_remote
, a_zoneName
);
1144 /* locate class action script to execute */
1145 (void) snprintf(script
, sizeof (script
), "%s/r.%s", pkgbin
, aclass
);
1146 if (access(script
, F_OK
) != 0) {
1147 (void) snprintf(script
, sizeof (script
), "%s/r.%s",
1149 if (access(script
, F_OK
) != 0)
1152 if (script
[0] != '\0') {
1155 (void) snprintf(tmpfile
, sizeof (tmpfile
), "%s/RMLISTXXXXXX",
1157 td
= mkstemp(tmpfile
);
1159 progerr(ERR_TMPFILE
);
1162 if ((fp
= fdopen(td
, "w")) == NULL
) {
1163 progerr(ERR_WTMPFILE
, tmpfile
);
1168 if (a_zoneName
== (char *)NULL
) {
1169 echo(MSG_PKGREMOVE_REMPATHCLASS_GZ
, aclass
);
1171 echo(MSG_PKGREMOVE_REMPATHCLASS_LZ
, aclass
, a_zoneName
);
1174 /* process paths in reverse order */
1179 if ((ept
== NULL
) || strcmp(aclass
, ept
->pkg_class
)) {
1183 /* save the path, and prepend the ir */
1184 if (is_an_inst_root()) {
1185 save_path
= ept
->path
;
1186 tmp_path
= fixpath(ept
->path
);
1187 ept
->path
= tmp_path
;
1190 if (!ept
->ftype
|| (ept
->ftype
== '^' && !script
[0])) {
1192 * A path owned by more than one package is marked with
1193 * a NULL ftype (seems odd, but that's how it's
1194 * done). Such files are sacro sanct. Shared editable
1195 * files are a special case, and are marked with an
1196 * ftype of '^'. These files should only be ignored if
1197 * no class action script is present. It is the CAS's
1198 * responsibility to not remove the editable object.
1200 echo(MSG_SHARED
, ept
->path
);
1201 } else if (ept
->pinfo
->status
== SERVED_FILE
&& !rm_remote
) {
1203 * If the path is provided to the client from a
1204 * server, don't remove anything unless explicitly
1205 * requested through the "-f" option.
1207 echo(MSG_SERVER
, ept
->path
);
1208 } else if (script
[0]) {
1210 * If there's a class action script, just put the
1211 * path name into the list.
1213 (void) fprintf(fp
, "%s\n", ept
->path
);
1214 } else if (strchr("dx", ept
->ftype
) != NULL
||
1215 (lstat(ept
->path
, &st
) == 0 && S_ISDIR(st
.st_mode
))) {
1216 /* Directories are rmdir()'d. */
1218 if (rmdir(ept
->path
)) {
1219 if (errno
== EBUSY
) {
1220 echo(MSG_DIRBUSY
, ept
->path
);
1221 } else if (errno
== EEXIST
) {
1222 echo(MSG_NOTEMPTY
, ept
->path
);
1223 } else if (errno
!= ENOENT
) {
1224 progerr(ERR_RMDIR
, ept
->path
);
1228 if (ept
->pinfo
->status
== SERVED_FILE
) {
1229 echo(MSG_RMSRVR
, ept
->path
);
1231 echo("%s", ept
->path
);
1237 * Before removing this object one more
1238 * check should be done to assure that a
1239 * shared object is not removed.
1240 * This can happen if the original object
1241 * was incorrectly updated with the
1242 * incorrect class identifier.
1243 * This handles pathologcal cases that
1244 * weren't handled above.
1246 if (ept
->npkgs
> 1) {
1247 echo(MSG_SHARED
, ept
->path
);
1251 /* Regular files are unlink()'d. */
1253 if (unlink(ept
->path
)) {
1254 if (errno
!= ENOENT
) {
1255 progerr(ERR_RMPATH
, ept
->path
);
1259 if (ept
->pinfo
->status
== SERVED_FILE
) {
1260 echo(MSG_RMSRVR
, ept
->path
);
1262 echo("%s", ept
->path
);
1267 /* restore the original path */
1269 if (is_an_inst_root()) {
1270 ept
->path
= save_path
;
1274 * free memory allocated for this entry memory used for
1275 * pathnames will be freed later by a call to pathdup()
1285 set_ulimit(script
, ERR_CASFAIL
);
1287 ckreturn(pkgexecl(tmpfile
, CAS_STDOUT
, CAS_USER
,
1288 CAS_GRP
, SHELL
, "-x", script
, NULL
),
1291 ckreturn(pkgexecl(tmpfile
, CAS_STDOUT
, CAS_USER
,
1292 CAS_GRP
, SHELL
, script
, NULL
),
1295 if (isfile(NULL
, tmpfile
) == 0) {
1296 if (unlink(tmpfile
) == -1)
1297 progerr(ERR_RMPATH
, tmpfile
);
1303 ckreturn(int retcode
, char *msg
)
1354 (void) fprintf(stderr
, ERR_USAGE_PKGREMOVE
);