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 */
54 * libinstzones includes
57 #include <instzones_api.h>
60 * consolidation pkg command library includes
66 * local pkg command library includes
75 * pkgrm local includes
81 * exported global variables
84 /* these globals are set by ckreturn and used by quit.c */
86 int admnflag
= 0; /* != 0 if any pkg op admin setting failure (4) */
87 int doreboot
= 0; /* != 0 if reboot required after installation */
88 int failflag
= 0; /* != 0 if fatal error has occurred (1) */
89 int intrflag
= 0; /* != 0 if user selected quit (3) */
90 int ireboot
= 0; /* != 0 if immediate reboot required */
91 int nullflag
= 0; /* != 0 if admin interaction required (5) */
92 int warnflag
= 0; /* != 0 if non-fatal error has occurred (2) */
94 /* imported by quit.c */
95 int npkgs
= 0; /* the number of packages yet to be installed */
97 /* imported by presvr4.c */
99 char *tmpdir
= NULL
; /* location to place temporary files */
101 /* imported by various (many) */
102 struct admin adm
; /* holds info about installation admin */
103 struct pkgdev pkgdev
; /* holds info about the installation device */
106 * internal global variables
109 static char *admnfile
= NULL
; /* file to use for installation admin */
110 static char *pkginst
= NULL
; /* current pkg/src instance 2 process */
111 static char *vfstab_file
= NULL
;
112 static char *zoneTempDir
= (char *)NULL
;
114 /* set by ckreturn() */
116 static int interrupted
= 0; /* last pkg op was quit (1,2,3,4,5) */
118 static int nointeract
= 0; /* non-zero - no user interaction */
119 static int pkgrmremote
= 0; /* remove pkg objs stored remotely */
120 static int pkgverbose
= 0; /* non-zero if verbose mode selected */
123 * Assume the package complies with the standards as regards user
124 * interaction during procedure scripts.
127 static int old_pkg
= 0;
128 static int old_symlinks
= 0;
129 static int no_map_client
= 0;
131 /* Set by -O nozones: do not process any zones */
133 static boolean_t noZones
= B_FALSE
;
135 /* Set by -O zonelist=<names...>: process only named zones */
137 static boolean_t usedZoneList
= B_FALSE
;
139 /* Set by -O debug: debug output is enabled? */
141 static boolean_t debugFlag
= B_FALSE
;
144 * imported (external) functions
149 extern int preremove_verify(char **a_pkgList
, zoneList_t a_zlst
,
150 char *a_zoneTempDir
);
153 extern void quitSetZonelist(zoneList_t a_zlst
);
156 * imported (external) variables
161 /* printable string - if string is null results in ??? */
163 #define PSTR(STR) (((STR) == (char *)NULL) ? "???" : (STR))
167 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
168 #define TEXT_DOMAIN "SYS_TEST"
172 * forward declarations
175 static void ckreturn(int retcode
);
176 static void create_zone_adminfile(char **r_zoneAdminFile
,
177 char *a_zoneTempDir
, char *a_admnfile
);
178 static void create_zone_tempdir(char **r_zoneTempDir
,
180 static int doRemove(int a_nodelete
, char *a_altBinDir
,
181 int a_longestPkg
, char *a_adminFile
,
182 char *a_zoneAdminFile
, zoneList_t zlst
);
183 static int pkgRemove(int a_nodelete
, char *a_altBinDir
,
185 static int pkgZoneCheckRemove(char *a_zoneName
, char *a_altBinDir
,
186 char *a_adminFile
, char *a_stdoutPath
,
187 zone_state_t a_zoneState
, boolean_t tmpzone
);
188 static int pkgZoneRemove(char *a_zoneName
, int a_nodelete
,
189 char *a_altBinDir
, char *a_adminFile
,
190 zone_state_t a_zoneState
, boolean_t tmpzone
);
191 static void resetreturn();
192 static void usage(void);
193 static boolean_t
check_applicability(char *a_packageDir
,
194 char *a_pkgInst
, char *a_rootPath
,
196 static boolean_t
check_packages(char **a_pkgList
, char *a_packageDir
);
197 static boolean_t
remove_packages(char **a_pkgList
, int a_nodelete
,
198 int a_longestPkg
, int a_repeat
,
199 char *a_altBinDir
, char *a_pkgdir
,
200 char *a_spoolDir
, boolean_t a_noZones
);
201 static boolean_t
remove_packages_from_spool_directory(char **a_pkgList
,
202 int a_nodelete
, int a_longestPkg
, int a_repeat
,
204 static boolean_t
remove_packages_in_global_no_zones(char **a_pkgList
,
205 int a_nodelete
, int a_longestPkg
, int a_repeat
,
207 static boolean_t
remove_packages_in_global_with_zones(char **a_pkgList
,
208 int a_nodelete
, int a_longestPkg
, int a_repeat
,
209 char *a_altBinDir
, char *a_pkgdir
,
211 static boolean_t
remove_packages_in_nonglobal_zone(char **a_pkgList
,
212 int a_nodelete
, int a_longestPkg
, int a_repeat
,
213 char *a_altBinDir
, char *a_pkgdir
);
214 static boolean_t
shall_we_continue(char *a_pkgInst
, int a_npkgs
);
217 * *****************************************************************************
218 * global external (public) functions
219 * *****************************************************************************
224 * Description: main entry point for pkgrm
226 * 0 Successful completion
231 * 5 Administration. Interaction is required. Do not use pkgrm -n.
232 * 10 Reboot after removal of all packages.
233 * 20 Reboot after removal of this package.
237 main(int argc
, char **argv
)
239 char **category
= NULL
;
240 char *altBinDir
= (char *)NULL
;
241 char *catg_arg
= NULL
;
243 char *prog_full_name
= NULL
;
248 int nodelete
= 0; /* dont rm files/run scripts */
251 struct sigaction nact
;
252 struct sigaction oact
;
254 /* initialize locale environment */
256 (void) setlocale(LC_ALL
, "");
257 (void) textdomain(TEXT_DOMAIN
);
259 /* initialize program name */
261 prog_full_name
= argv
[0];
262 (void) set_prog_name(argv
[0]);
264 /* tell spmi zones interface how to access package output functions */
266 z_set_output_functions(echo
, echoDebug
, progerr
);
268 /* tell quit which ckreturn function to call */
270 quitSetCkreturnFunc(&ckreturn
);
272 /* Read PKG_INSTALL_ROOT from the environment, if it's there. */
274 if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
275 progerr(ERR_ROOT_SET
);
279 if (z_running_in_global_zone() && !enable_local_fs()) {
280 progerr(ERR_CANNOT_ENABLE_LOCAL_FS
);
283 pkgserversetmode(DEFAULTMODE
);
286 * ********************************************************************
287 * parse command line options
288 * ********************************************************************
291 while ((c
= getopt(argc
, argv
, "?Aa:b:FMnO:R:s:V:vY:Z")) != EOF
) {
294 * Public interface: Allow admin to remove objects
295 * from a service area via a reference client.
296 * Remove the package files from the client's file
297 * system, absolutely. If a file is shared with other
298 * packages, the default behavior is to not remove
299 * the file from the client's file system.
306 * Public interface: Use the installation
307 * administration file, admin, in place of the
308 * default admin file. pkgrm first looks in the
309 * current working directory for the administration
310 * file. If the specified administration file is not
311 * in the current working directory, pkgrm looks in
312 * the /var/sadm/install/admin directory for the
313 * administra- tion file.
316 admnfile
= flex_device(optarg
, 0);
320 * Not a public interface: location where package executables
321 * can be found - default is /usr/sadm/install/bin.
324 if (!path_valid(optarg
)) {
325 progerr(ERR_PATH
, optarg
);
328 if (isdir(optarg
) != 0) {
330 progerr(ERR_CANNOT_USE_DIR
, optarg
, p
);
337 * Not a public interface: pass -F option to
338 * pkgremove which suppresses the removal of any
339 * files and any class action scripts, and suppresses
340 * the running of any class action scripts. The
341 * package files remain but the package looks like it
342 * is not installed. This is mainly for use by the
350 * Public interface: Instruct pkgrm not to use the
351 * $root_path/etc/vfstab file for determining the
352 * client's mount points. This option assumes the
353 * mount points are correct on the server and it
354 * behaves consistently with Solaris 2.5 and earlier
362 * Public interface: package removal occurs in
363 * non-interactive mode. Suppress output of the list of
364 * removed files. The default mode is interactive.
368 (void) echoSetFlag(B_FALSE
);
372 * Not a public interface: the -O option allows the behavior
373 * of the package tools to be modified. Recognized options:
375 * ---> enable debugging output
377 * ---> act as though in global zone with no non-global zones
378 * -> enable-hollow-package-support
379 * --> Enable hollow package support. When specified, for any
380 * --> package that has SUNW_PKG_HOLLOW=true:
381 * --> Do not calculate and verify package size against target
382 * --> Do not run any package procedure or class action scripts
383 * --> Do not create or remove any target directories
384 * --> Do not perform any script locking
385 * --> Do not install or uninstall any components of any package
386 * --> Do not output any status or database update messages
387 * -> zonelist="<names...>"
388 * ---> add package to space-separated list of zones only
392 for (p
= strtok(optarg
, ","); p
!= (char *)NULL
;
393 p
= strtok(NULL
, ",")) {
395 if (strcmp(p
, "nozones") == 0) {
401 "enable-hollow-package-support") == 0) {
402 set_depend_pkginfo_DB(B_TRUE
);
406 if (strcmp(p
, "debug") == 0) {
407 /* set debug flag/enable debug output */
409 (void) echoDebugSetFlag(debugFlag
);
411 /* debug info on arguments to pkgadd */
412 for (n
= 0; n
< argc
&& argv
[n
]; n
++) {
413 echoDebug(DBG_ARG
, n
, argv
[n
]);
419 if (strncmp(p
, "zonelist=", 9) == 0) {
420 if (z_set_zone_spec(p
+ 9) == -1)
422 usedZoneList
= B_TRUE
;
426 /* -O option not recognized - issue warning */
428 progerr(ERR_INVALID_O_OPTION
, p
);
434 * Public interface: defines the full path name of a
435 * directory to use as the root_path. All files,
436 * including package system information files, are
437 * relocated to a directory tree starting in the
438 * specified root_path.
441 if (!set_inst_root(optarg
)) {
442 progerr(ERR_ROOT_CMD
);
448 * Public interface: remove the specified package(s)
449 * from the directory spool. The default directory
450 * for spooled packages is /var/sadm/pkg.
453 spoolDir
= flex_device(optarg
, 1);
457 * Public interface: Allow admin to establish the client
458 * filesystem using a vfstab-like file of stable format.
461 vfstab_file
= flex_device(optarg
, 2);
466 * Public interface: trace all of the scripts that
467 * get executed by pkgrm, located in the
468 * pkginst/install directory. This option is used for
469 * debugging the procedural and non- procedural
477 * Public interface: remove packages based on the
478 * CATEGORY variable from the installed/spooled
482 catg_arg
= strdup(optarg
);
484 if ((category
= get_categories(catg_arg
)) == NULL
) {
485 progerr(ERR_CAT_INV
, catg_arg
);
487 } else if (is_not_valid_category(category
,
489 progerr(ERR_CAT_SYS
);
491 } else if (is_not_valid_length(category
)) {
492 progerr(ERR_CAT_LNGTH
);
499 * unrecognized option
508 * ********************************************************************
509 * validate command line options
510 * ********************************************************************
513 /* set "debug echo" flag according to setting of "-O debug" option */
515 (void) echoDebugSetFlag(debugFlag
);
517 /* output entry debugging information */
519 if (z_running_in_global_zone()) {
520 echoDebug(DBG_ENTRY_IN_GZ
, prog_full_name
);
522 echoDebug(DBG_ENTRY_IN_LZ
, prog_full_name
, getzoneid(),
526 /* -s cannot be used with several */
528 if (spoolDir
!= (char *)NULL
) {
529 if (admnfile
!= (char *)NULL
) {
530 progerr(ERR_SPOOLDIR_AND_ADMNFILE
);
535 if (pkgrmremote
!= 0) {
536 progerr(ERR_SPOOLDIR_AND_PKGRMREMOTE
);
541 if (pkgverbose
!= 0) {
542 progerr(ERR_SPOOLDIR_AND_PKGVERBOSE
);
547 if (is_an_inst_root() != 0) {
548 progerr(ERR_SPOOLDIR_AND_INST_ROOT
);
554 /* -V cannot be used with -A */
556 if (no_map_client
&& pkgrmremote
) {
557 progerr(ERR_V_USED_AND_PKGRMREMOTE
);
562 /* -n used without pkg names or category */
564 if (nointeract
&& (optind
== argc
) && (catg_arg
== NULL
)) {
565 progerr(ERR_BAD_N_PKGRM
);
570 /* Error if specified zone list isn't valid on target */
571 if (usedZoneList
&& z_verify_zone_spec() == -1)
575 * hook SIGINT and SIGHUP interrupts into quit.c's trap handler
578 /* hold SIGINT/SIGHUP interrupts */
580 (void) sighold(SIGHUP
);
581 (void) sighold(SIGINT
);
583 /* connect quit.c:trap() to SIGINT */
585 nact
.sa_handler
= quitGetTrapHandler();
586 nact
.sa_flags
= SA_RESTART
;
587 (void) sigemptyset(&nact
.sa_mask
);
589 (void) sigaction(SIGINT
, &nact
, &oact
);
591 /* connect quit.c:trap() to SIGHUP */
593 nact
.sa_handler
= quitGetTrapHandler();
594 nact
.sa_flags
= SA_RESTART
;
595 (void) sigemptyset(&nact
.sa_mask
);
597 (void) sigaction(SIGHUP
, &nact
, &oact
);
599 /* release hold on signals */
601 (void) sigrelse(SIGHUP
);
602 (void) sigrelse(SIGINT
);
604 /* establish temporary directory to use */
606 tmpdir
= getenv("TMPDIR");
607 if (tmpdir
== NULL
) {
611 echoDebug(DBG_PKGRM_TMPDIR
, tmpdir
);
613 /* initialize path parameters */
615 set_PKGpaths(get_inst_root());
618 * initialize installation admin parameters - if removing from a spool
619 * directory then the admin file is ignore.
622 if (spoolDir
== NULL
) {
623 echoDebug(DBG_PKGRM_ADMINFILE
, admnfile
? admnfile
: "");
624 setadminFile(admnfile
);
628 * if running in the global zone, and non-global zones exist, then
629 * enable hollow package support so that any packages that are marked
630 * SUNW_PKG_HOLLOW=true will be correctly removed in non-global zones
631 * when removed directly in the global zone by the global zone admin.
634 if (is_depend_pkginfo_DB()) {
635 echoDebug(DBG_PKGRM_HOLLOW_ENABLED
);
636 } else if ((z_running_in_global_zone() == B_TRUE
) &&
637 (z_non_global_zones_exist() == B_TRUE
)) {
638 echoDebug(DBG_PKGRM_ENABLING_HOLLOW
);
639 set_depend_pkginfo_DB(B_TRUE
);
643 * See if user wants this to be handled as an old style pkg.
644 * NOTE : the ``exception_pkg()'' stuff is to be used only
645 * through on495. This function comes out for on1095. See
646 * PSARC 1993-546. -- JST
648 if (getenv("NONABI_SCRIPTS") != NULL
) {
653 * See if the user wants to process symlinks consistent with
657 if (getenv("PKG_NONABI_SYMLINKS") != NULL
) {
661 if (devtype((spoolDir
? spoolDir
: get_PKGLOC()), &pkgdev
) ||
662 pkgdev
.dirname
== NULL
) {
663 progerr(ERR_BAD_DEVICE
, spoolDir
? spoolDir
: get_PKGLOC());
668 pkgdir
= pkgdev
.dirname
;
669 repeat
= ((optind
>= argc
) && pkgdev
.mount
);
672 * error if there are packages on the command line and a category
676 if (optind
< argc
&& catg_arg
!= NULL
) {
677 progerr(ERR_PKGS_AND_CAT_PKGRM
);
683 * ********************************************************************
684 * main package processing "loop"
685 * ********************************************************************
690 char **pkglist
; /* points to array of pkgs */
693 * mount the spool device if required
697 if (n
= pkgmount(&pkgdev
, NULL
, 0, 0, 1)) {
703 if (chdir(pkgdev
.dirname
)) {
704 progerr(ERR_CHDIR
, pkgdev
.dirname
);
710 * spool device mounted/available - get the list of the
714 n
= pkgGetPackageList(&pkglist
, argv
, optind
,
715 catg_arg
, category
, &pkgdev
);
718 case -1: /* no packages found */
719 echoDebug(DBG_PKGLIST_RM_NONFOUND
,
720 PSTR(pkgdev
.dirname
));
721 progerr(ERR_NOPKGS
, pkgdev
.dirname
);
725 case 0: /* packages found */
728 default: /* "quit" error */
729 echoDebug(DBG_PKGLIST_RM_ERROR
,
736 * count the number of packages to remove
737 * NOTE: npkgs is a global variable that is referenced by quit.c
738 * when error messages are generated - it is referenced directly
739 * by the other functions called below...
742 for (npkgs
= 0; pkglist
[npkgs
] != (char *)NULL
; /* void */) {
743 pkgLgth
= strlen(pkglist
[npkgs
]);
744 if (pkgLgth
> longestPkg
) {
745 longestPkg
= pkgLgth
;
747 echoDebug(DBG_PKG_SELECTED
, npkgs
, pkglist
[npkgs
]);
751 /* output number of packages to be removed */
753 echoDebug(DBG_NUM_PKGS_TO_REMOVE
, npkgs
, longestPkg
);
756 * package list generated - remove packages
759 b
= remove_packages(pkglist
, nodelete
, longestPkg
, repeat
,
760 altBinDir
, pkgdev
.dirname
, spoolDir
, noZones
);
763 * unmount the spool directory if necessary
768 if (pkgumount(&pkgdev
)) {
769 progerr(ERR_PKGUNMOUNT
, pkgdev
.bdevice
);
777 * continue with next sequence of packages if continue set
785 * not continuing - quit with 0 exit code
797 * *****************************************************************************
798 * static internal (private) functions
799 * *****************************************************************************
804 * Description: Remove a package from the global zone, and optionally from one
805 * or more non-global zones.
806 * Arguments: a_nodelete: should the files and scripts remain installed?
807 * - if != 0 pass -F flag to pkgremove - suppress
808 * the removal of any files and any class action scripts
809 * and suppress the running of any class action scripts.
810 * The package files remain but the package looks like it
811 * is not installed. This is mainly for use by upgrade.
812 * - if == 0 do not pass -F flag to pkgremove - all
813 * files and class action scripts are removed, and any
814 * appropriate class action scripts are run.
815 * a_altBinDir - pointer to string representing location of the
816 * pkgremove executable to run. If not NULL, then pass
817 * the path specified to the -b option to pkgremove.
818 * a_longestPkg - length of the longest package "name" (for
819 * output format alignment)
820 * a_adminFile - pointer to string representing the admin
821 * file to pass to pkgremove when removing a package from
822 * the global zone only. Typically the admin file used for
823 * the global zone is the admin file passed in by the user.
824 * If this is == NULL no admin file is given to pkgremove.
825 * a_zoneAdminFile - pointer to string representing the admin
826 * file to pass to pkgremove when removing the package
827 * from a non-global zone only. Typically the admin file
828 * used for non-global zones supresses all checks since
829 * the dependency checking is done for all zones first
831 * A zoneAdminFile MUST be specified if a_zlst != NULL.
832 * A zoneAdminFile must NOT be specified if a_zlst == NULL.
833 * a_zlst - list of zones to process; NULL if no zones to process.
834 * Returns: int (see ckreturn() function for details)
836 * 1 - package operation failed (fatal error)
837 * 2 - non-fatal error (warning)
838 * 3 - user selected quit (operation interrupted)
839 * 4 - admin settings prevented operation
840 * 5 - interaction required and -n (non-interactive) specified
841 * "10" will be added to indicate "immediate reboot required"
842 * "20" will be added to indicate "reboot after install required"
846 doRemove(int a_nodelete
, char *a_altBinDir
, int a_longestPkg
, char *a_adminFile
,
847 char *a_zoneAdminFile
, zoneList_t a_zlst
)
855 struct pkginfo
*pinfo
= (struct pkginfo
*)NULL
;
858 /* entry assertions */
860 if (a_zlst
!= (zoneList_t
)NULL
) {
861 /* zone list specified - zone admin file required */
862 assert(a_zoneAdminFile
!= (char *)NULL
);
863 assert(*a_zoneAdminFile
!= '\0');
865 /* no zone list specified - no zone admin file needed */
866 assert(a_zoneAdminFile
== (char *)NULL
);
869 /* NOTE: required 'pkgdir' set to spool directory or NULL */
870 b
= pkginfoIsPkgInstalled(&pinfo
, pkginst
);
872 progerr(ERR_NO_SUCH_INSTANCE
, pkginst
);
877 /* entry debugging info */
879 echoDebug(DBG_DOREMOVE_ENTRY
);
880 echoDebug(DBG_DOREMOVE_ARGS
, PSTR(pinfo
->pkginst
), PSTR(pinfo
->name
),
881 PSTR(pinfo
->arch
), PSTR(pinfo
->version
), PSTR(pinfo
->basedir
),
882 PSTR(pinfo
->catg
), pinfo
->status
);
887 /* create format based on max pkg name length */
889 (void) snprintf(fmt1
, sizeof (fmt1
), " %%-%d.%ds %%s",
890 a_longestPkg
, a_longestPkg
);
892 if (pinfo
->status
== PI_SPOOLED
) {
896 progerr(ERR_NOT_ROOT
, get_prog_name());
902 echo(fmt1
, pinfo
->pkginst
, pinfo
->name
);
904 if (pinfo
->arch
|| pinfo
->version
) {
907 /* create format based on max pkg name length */
909 (void) snprintf(fmt2
, sizeof (fmt2
), " %%%d.%ds ",
910 a_longestPkg
, a_longestPkg
);
912 /* LINTED variable format specifier to fprintf() */
913 (void) fprintf(stderr
, fmt2
, "");
916 (void) fprintf(stderr
, "(%s) ", pinfo
->arch
);
919 if (pinfo
->version
) {
920 (void) fprintf(stderr
, "%s", pinfo
->version
);
923 (void) fprintf(stderr
, "\n");
926 n
= ckyorn(ans
, NULL
, NULL
, NULL
, ASK_CONFIRM
);
932 if (strchr("yY", *ans
) == NULL
) {
938 if (pinfo
->status
== PI_SPOOLED
) {
939 /* removal from a directory */
940 echo(INFO_RMSPOOL
, pkginst
);
942 return (rrmdir(pkginst
));
945 /* exit if not root */
948 progerr(ERR_NOT_ROOT
, get_prog_name());
956 if (interrupted
!= 0) {
957 echo(MSG_DOREMOVE_INTERRUPTED_B4_Z
, pkginst
);
958 echoDebug(MSG_DOREMOVE_INTERRUPTED_B4_Z
, pkginst
);
962 echoDebug(DBG_REMOVE_FLAG_VALUES
, "before pkgZoneRemove",
963 admnflag
, doreboot
, failflag
, interrupted
,
964 intrflag
, ireboot
, nullflag
, warnflag
);
968 (zoneName
= z_zlist_get_zonename(a_zlst
, zoneIndex
)) != NULL
;
971 /* skip the zone if it is NOT running */
973 zst
= z_zlist_get_current_state(a_zlst
, zoneIndex
);
974 if (zst
!= ZONE_STATE_RUNNING
&& zst
!= ZONE_STATE_MOUNTED
) {
976 echoDebug(DBG_SKIPPING_ZONE
, zoneName
);
980 echo(MSG_REMOVE_PKG_FROM_ZONE
, pkginst
, zoneName
);
981 echoDebug(DBG_REMOVE_PKG_FROM_ZONE
, pkginst
, zoneName
);
984 * remove package from zone; use the zone admin file which
985 * suppresses all checks.
988 n
= pkgZoneRemove(z_zlist_get_scratch(a_zlst
, zoneIndex
),
989 a_nodelete
, a_altBinDir
, a_zoneAdminFile
,
992 /* set success/fail condition variables */
996 echoDebug(DBG_REMOVE_FLAG_VALUES
, "after pkgZoneRemove",
997 admnflag
, doreboot
, failflag
, interrupted
, intrflag
,
998 ireboot
, nullflag
, warnflag
);
1001 if (zonesSkipped
> 0) {
1002 echoDebug(DBG_ZONES_SKIPPED
, zonesSkipped
);
1005 (zoneName
= z_zlist_get_zonename(a_zlst
, zoneIndex
)) !=
1006 (char *)NULL
; zoneIndex
++) {
1008 /* skip the zone if it IS running */
1010 zst
= z_zlist_get_current_state(a_zlst
, zoneIndex
);
1011 if (zst
== ZONE_STATE_RUNNING
||
1012 zst
== ZONE_STATE_MOUNTED
) {
1014 echoDebug(DBG_SKIPPING_ZONE_BOOT
, zoneName
);
1018 /* skip the zone if it is NOT bootable */
1020 if (z_zlist_is_zone_runnable(a_zlst
,
1021 zoneIndex
) == B_FALSE
) {
1022 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE
, zoneName
);
1023 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE
,
1028 /* mount up the zone */
1030 echo(MSG_BOOTING_ZONE
, zoneName
);
1031 echoDebug(DBG_BOOTING_ZONE
, zoneName
);
1033 b
= z_zlist_change_zone_state(a_zlst
, zoneIndex
,
1034 ZONE_STATE_MOUNTED
);
1036 progerr(ERR_CANNOT_BOOT_ZONE
, zoneName
);
1037 /* set fatal error return condition */
1042 echo(MSG_REMOVE_PKG_FROM_ZONE
, pkginst
, zoneName
);
1045 * remove package from zone; use the zone admin file
1046 * which suppresses all checks.
1049 n
= pkgZoneRemove(z_zlist_get_scratch(a_zlst
,
1050 zoneIndex
), a_nodelete
, a_altBinDir
,
1051 a_zoneAdminFile
, ZONE_STATE_MOUNTED
, B_TRUE
);
1053 /* set success/fail condition variables */
1057 echoDebug(DBG_REMOVE_FLAG_VALUES
, "after pkgZoneRemove",
1058 admnflag
, doreboot
, failflag
, interrupted
,
1059 intrflag
, ireboot
, nullflag
, warnflag
);
1061 /* restore original state of zone */
1063 echo(MSG_RESTORE_ZONE_STATE
, zoneName
);
1064 echoDebug(DBG_RESTORE_ZONE_STATE
, zoneName
);
1066 b
= z_zlist_restore_zone_state(a_zlst
, zoneIndex
);
1071 * Process global zone if it was either the only possible
1072 * target (no list of zones specified) or it appears in the list
1074 if (a_zlst
== NULL
|| z_on_zone_spec(GLOBAL_ZONENAME
)) {
1075 /* reset interrupted flag before calling pkgremove */
1076 interrupted
= 0; /* last action was NOT quit */
1079 * call pkgremove for this package for the global zone;
1080 * use the admin file passed in by the user via -a.
1082 n
= pkgRemove(a_nodelete
, a_altBinDir
, a_adminFile
);
1084 /* set success/fail condition variables */
1092 * function to clear out any exisiting error return conditions that may have
1093 * been set by previous calls to ckreturn()
1098 admnflag
= 0; /* != 0 if any pkg op admin setting failure (4) */
1099 doreboot
= 0; /* != 0 if reboot required after installation (>= 10) */
1100 failflag
= 0; /* != 0 if fatal error has occurred (1) */
1101 intrflag
= 0; /* != 0 if user selected quit (3) */
1102 ireboot
= 0; /* != 0 if immediate reboot required (>= 20) */
1103 nullflag
= 0; /* != 0 if admin interaction required (5) */
1104 warnflag
= 0; /* != 0 if non-fatal error has occurred (2) */
1105 interrupted
= 0; /* last pkg op was quit (1,2,3,4,5) */
1109 * function which checks the indicated return value
1110 * and indicates disposition of installation
1113 ckreturn(int retcode
)
1116 * entry debugging info
1119 echoDebug(DBG_PKGRM_CKRETURN
, retcode
, PSTR(pkginst
));
1122 case 0: /* successful */
1125 break; /* empty case */
1127 case 1: /* package operation failed (fatal error) */
1134 case 2: /* non-fatal error (warning) */
1141 case 3: /* user selected quit; operation interrupted */
1148 case 4: /* admin settings prevented operation */
1155 case 5: /* administration: interaction req (no -n) */
1168 if (retcode
>= 20) {
1170 } else if (retcode
>= 10) {
1176 pkgZoneCheckRemove(char *a_zoneName
, char *a_altBinDir
, char *a_adminFile
,
1177 char *a_stdoutPath
, zone_state_t a_zoneState
, boolean_t tmpzone
)
1181 char adminfd_path
[PATH_MAX
];
1182 char path
[PATH_MAX
];
1188 /* entry assertions */
1190 assert(a_zoneName
!= (char *)NULL
);
1191 assert(*a_zoneName
!= '\0');
1193 /* entry debugging info */
1195 echoDebug(DBG_PKGZONECHECKREMOVE_ENTRY
);
1196 echoDebug(DBG_PKGZONECHECKREMOVE_ARGS
, a_zoneName
, PSTR(pkginst
),
1197 PSTR(pkgdev
.dirname
), PSTR(a_adminFile
), PSTR(a_stdoutPath
));
1199 /* generate path to pkgremove */
1201 (void) snprintf(path
, sizeof (path
), "%s/pkgremove",
1202 a_altBinDir
== (char *)NULL
? PKGBIN
: a_altBinDir
);
1204 /* start at first file descriptor */
1209 * generate argument list for call to pkgremove
1212 /* start at argument 0 */
1216 /* first argument is path to executable */
1218 arg
[nargs
++] = strdup(path
);
1220 /* second argument is always: pass -O debug to pkgremove: debug mode */
1222 if (debugFlag
== B_TRUE
) {
1223 arg
[nargs
++] = "-O";
1224 arg
[nargs
++] = "debug";
1227 /* pkgrm -b dir: pass -b to pkgremove */
1229 if (a_altBinDir
!= (char *)NULL
) {
1230 arg
[nargs
++] = "-b";
1231 arg
[nargs
++] = a_altBinDir
;
1235 * NONABI_SCRIPTS defined: pass -o to pkgremove; refers to a
1236 * pkg requiring operator interaction during a procedure script
1237 * (common before on1093)
1241 arg
[nargs
++] = "-o";
1245 * PKG_NONABI_SYMLINKS defined: pass -y to pkgremove; process
1246 * symlinks consistent with old behavior
1250 arg
[nargs
++] = "-y";
1253 /* pkgrm -M: pass -M to pkgremove: don't mount client file systems */
1255 arg
[nargs
++] = "-M";
1257 /* pkgrm -A: pass -A to pkgremove */
1260 arg
[nargs
++] = "-A";
1263 /* pkgrm -v: pass -v to pkgremove: never trace scripts */
1265 /* pass "-O enable-hollow-package-support" */
1267 if (is_depend_pkginfo_DB()) {
1268 arg
[nargs
++] = "-O";
1269 arg
[nargs
++] = "enable-hollow-package-support";
1272 /* pass -n to pkgremove: always in noninteractive mode */
1274 arg
[nargs
++] = "-n";
1276 /* pkgrm -a admin: pass -a admin to pkgremove: admin file */
1280 fd
= openLocal(a_adminFile
, O_RDONLY
, tmpdir
);
1282 progerr(ERR_CANNOT_COPY_LOCAL
, a_adminFile
,
1283 errno
, strerror(errno
));
1286 (void) snprintf(adminfd_path
, sizeof (adminfd_path
),
1287 "/proc/self/fd/%d", fd
);
1289 arg
[nargs
++] = "-a";
1290 arg
[nargs
++] = strdup(adminfd_path
);
1294 * pkgadd -R root: pass -R /a to pkgremove in mounted zone
1296 if (a_zoneState
== ZONE_STATE_MOUNTED
) {
1297 arg
[nargs
++] = "-R";
1298 arg
[nargs
++] = "/a";
1301 /* pkgrm -F: pass -F to pkgremove: always update DB only */
1303 arg
[nargs
++] = "-F";
1305 /* pass "-O preremovecheck" */
1307 arg
[nargs
++] = "-O";
1308 arg
[nargs
++] = "preremovecheck";
1310 /* add "-O addzonename" */
1312 arg
[nargs
++] = "-O";
1313 arg
[nargs
++] = "addzonename";
1316 * add parent zone info/type
1319 p
= z_get_zonename();
1320 if ((p
!= NULL
) && (*p
!= '\0')) {
1321 char zn
[MAXPATHLEN
];
1322 (void) snprintf(zn
, sizeof (zn
),
1323 "parent-zone-name=%s", p
);
1324 arg
[nargs
++] = "-O";
1325 arg
[nargs
++] = strdup(zn
);
1328 /* current zone type */
1330 arg
[nargs
++] = "-O";
1331 if (z_running_in_global_zone() == B_TRUE
) {
1332 char zn
[MAXPATHLEN
];
1333 (void) snprintf(zn
, sizeof (zn
),
1334 "parent-zone-type=%s",
1335 TAG_VALUE_GLOBAL_ZONE
);
1336 arg
[nargs
++] = strdup(zn
);
1338 char zn
[MAXPATHLEN
];
1339 (void) snprintf(zn
, sizeof (zn
),
1340 "parent-zone-type=%s",
1341 TAG_VALUE_NONGLOBAL_ZONE
);
1342 arg
[nargs
++] = strdup(zn
);
1345 /* Add arguments how to start the pkgserv */
1347 arg
[nargs
++] = "-O";
1348 arg
[nargs
++] = pkgmodeargument(tmpzone
? RUN_ONCE
: pkgservergetmode());
1350 /* pass -N to pkgremove: program name to report */
1352 arg
[nargs
++] = "-N";
1353 arg
[nargs
++] = get_prog_name();
1355 /* add package instance name */
1357 arg
[nargs
++] = pkginst
;
1359 /* terminate argument list */
1361 arg
[nargs
++] = NULL
;
1363 /* execute pkgremove command */
1365 if (debugFlag
== B_TRUE
) {
1366 echoDebug(DBG_ZONE_EXEC_ENTER
, a_zoneName
, arg
[0]);
1367 for (n
= 0; arg
[n
]; n
++) {
1368 echoDebug(DBG_ARG
, n
, arg
[n
]);
1372 /* terminate file descriptor list */
1376 /* exec command in zone */
1378 n
= z_zone_exec(a_zoneName
, path
, arg
, a_stdoutPath
, (char *)NULL
, fds
);
1380 echoDebug(DBG_ZONE_EXEC_EXIT
, a_zoneName
, arg
[0], n
,
1381 PSTR(a_stdoutPath
));
1384 * close any files that were opened for use by the
1385 * /proc/self/fd interface so they could be passed to programs
1386 * via the z_zone_exec() interface
1389 for (; maxfds
> 0; maxfds
--) {
1390 (void) close(fds
[maxfds
-1]);
1393 /* return results of pkgremove in zone execution */
1399 pkgZoneRemove(char *a_zoneName
, int a_nodelete
, char *a_altBinDir
,
1400 char *a_adminFile
, zone_state_t a_zoneState
, boolean_t tmpzone
)
1404 char adminfd_path
[PATH_MAX
];
1405 char path
[PATH_MAX
];
1411 /* entry assertions */
1413 assert(a_zoneName
!= (char *)NULL
);
1414 assert(*a_zoneName
!= '\0');
1416 /* entry debugging info */
1418 echoDebug(DBG_PKGZONEREMOVE_ENTRY
);
1419 echoDebug(DBG_PKGZONEREMOVE_ARGS
, a_zoneName
, PSTR(pkginst
),
1420 PSTR(pkgdev
.dirname
), a_nodelete
, PSTR(a_adminFile
));
1422 /* generate path to pkgremove */
1424 (void) snprintf(path
, sizeof (path
), "%s/pkgremove",
1425 a_altBinDir
== (char *)NULL
? PKGBIN
: a_altBinDir
);
1427 /* start at first file descriptor */
1432 * generate argument list for call to pkgremove
1435 /* start at argument 0 */
1439 /* first argument is path to executable */
1441 arg
[nargs
++] = strdup(path
);
1443 /* second argument is always: pass -O debug to pkgremove: debug mode */
1445 if (debugFlag
== B_TRUE
) {
1446 arg
[nargs
++] = "-O";
1447 arg
[nargs
++] = "debug";
1450 /* pkgrm -b dir: pass -b to pkgremove */
1452 if (a_altBinDir
!= (char *)NULL
) {
1453 arg
[nargs
++] = "-b";
1454 arg
[nargs
++] = a_altBinDir
;
1458 * NONABI_SCRIPTS defined: pass -o to pkgremove; refers to a
1459 * pkg requiring operator interaction during a procedure script
1460 * (common before on1093)
1464 arg
[nargs
++] = "-o";
1468 * PKG_NONABI_SYMLINKS defined: pass -y to pkgremove; process
1469 * symlinks consistent with old behavior
1473 arg
[nargs
++] = "-y";
1476 /* pkgrm -M: pass -M to pkgremove: don't mount client file systems */
1478 arg
[nargs
++] = "-M";
1480 /* pkgrm -A: pass -A to pkgremove */
1483 arg
[nargs
++] = "-A";
1486 /* pkgrm -v: pass -v to pkgremove: trace scripts */
1489 arg
[nargs
++] = "-v";
1492 /* pass "-O enable-hollow-package-support" */
1494 if (is_depend_pkginfo_DB()) {
1495 arg
[nargs
++] = "-O";
1496 arg
[nargs
++] = "enable-hollow-package-support";
1499 /* pkgrm -n: pass -n to pkgremove: noninteractive mode */
1502 arg
[nargs
++] = "-n";
1505 /* pkgrm -a admin: pass -a admin to pkgremove: admin file */
1509 fd
= openLocal(a_adminFile
, O_RDONLY
, tmpdir
);
1511 progerr(ERR_CANNOT_COPY_LOCAL
, a_adminFile
,
1512 errno
, strerror(errno
));
1515 (void) snprintf(adminfd_path
, sizeof (adminfd_path
),
1516 "/proc/self/fd/%d", fd
);
1518 arg
[nargs
++] = "-a";
1519 arg
[nargs
++] = adminfd_path
;
1523 * pkgadd -R root: pass -R /a to pkgremove in mounted zone
1525 if (a_zoneState
== ZONE_STATE_MOUNTED
) {
1526 arg
[nargs
++] = "-R";
1527 arg
[nargs
++] = "/a";
1530 /* pkgrm -F: pass -F to pkgremove: update DB only */
1533 arg
[nargs
++] = "-F";
1536 /* add "-O addzonename" */
1538 arg
[nargs
++] = "-O";
1539 arg
[nargs
++] = "addzonename";
1542 * add parent zone info/type
1545 p
= z_get_zonename();
1546 if ((p
!= NULL
) && (*p
!= '\0')) {
1547 char zn
[MAXPATHLEN
];
1548 (void) snprintf(zn
, sizeof (zn
),
1549 "parent-zone-name=%s", p
);
1550 arg
[nargs
++] = "-O";
1551 arg
[nargs
++] = strdup(zn
);
1554 /* current zone type */
1556 arg
[nargs
++] = "-O";
1557 if (z_running_in_global_zone() == B_TRUE
) {
1558 char zn
[MAXPATHLEN
];
1559 (void) snprintf(zn
, sizeof (zn
),
1560 "parent-zone-type=%s",
1561 TAG_VALUE_GLOBAL_ZONE
);
1562 arg
[nargs
++] = strdup(zn
);
1564 char zn
[MAXPATHLEN
];
1565 (void) snprintf(zn
, sizeof (zn
),
1566 "parent-zone-type=%s",
1567 TAG_VALUE_NONGLOBAL_ZONE
);
1568 arg
[nargs
++] = strdup(zn
);
1571 /* Add arguments how to start the pkgserv */
1573 arg
[nargs
++] = "-O";
1574 arg
[nargs
++] = pkgmodeargument(tmpzone
? RUN_ONCE
: pkgservergetmode());
1576 /* pass -N to pkgremove: program name to report */
1578 arg
[nargs
++] = "-N";
1579 arg
[nargs
++] = get_prog_name();
1581 /* add package instance name */
1583 arg
[nargs
++] = pkginst
;
1585 /* terminate argument list */
1587 arg
[nargs
++] = NULL
;
1589 /* execute pkgremove command */
1591 if (debugFlag
== B_TRUE
) {
1592 echoDebug(DBG_ZONE_EXEC_ENTER
, a_zoneName
, arg
[0]);
1593 for (n
= 0; arg
[n
]; n
++) {
1594 echoDebug(DBG_ARG
, n
, arg
[n
]);
1598 /* terminate file descriptor list */
1602 /* exec command in zone */
1604 n
= z_zone_exec(a_zoneName
, path
, arg
, (char *)NULL
, (char *)NULL
, fds
);
1607 * close any files that were opened for use by the
1608 * /proc/self/fd interface so they could be passed to programs
1609 * via the z_zone_exec() interface
1612 for (; maxfds
> 0; maxfds
--) {
1613 (void) close(fds
[maxfds
-1]);
1621 * Description: Invoke pkgremove in the current zone to perform a remove
1622 * of a single package from the current zone or standalone system
1623 * Arguments: a_nodelete: should the files and scripts remain installed?
1624 * - if != 0 pass -F flag to pkgremove - suppress
1625 * the removal of any files and any class action scripts
1626 * and suppress the running of any class action scripts.
1627 * The package files remain but the package looks like it
1628 * is not installed. This is mainly for use by upgrade.
1629 * - if == 0 do not pass -F flag to pkgremove - all
1630 * files and class action scripts are removed, and any
1631 * appropriate class action scripts are run.
1632 * a_altBinDir - pointer to string representing location of the
1633 * pkgremove executable to run. If not NULL, then pass
1634 * the path specified to the -b option to pkgremove.
1635 * a_adminFile - pointer to string representing the admin
1636 * file to pass to pkgremove when removing the package.
1637 * If this is == NULL no admin file is given to pkgremove.
1638 * Returns: int (see ckreturn() function for details)
1640 * 1 - package operation failed (fatal error)
1641 * 2 - non-fatal error (warning)
1642 * 3 - user selected quit (operation interrupted)
1643 * 4 - admin settings prevented operation
1644 * 5 - interaction required and -n (non-interactive) specified
1645 * "10" will be added to indicate "immediate reboot required"
1646 * "20" will be added to indicate "reboot after install required"
1650 pkgRemove(int a_nodelete
, char *a_altBinDir
, char *a_adminFile
)
1654 char path
[PATH_MAX
];
1658 /* entry debugging info */
1660 echoDebug(DBG_PKGREMOVE_ENTRY
);
1661 echoDebug(DBG_PKGREMOVE_ARGS
, PSTR(pkginst
), PSTR(pkgdev
.dirname
),
1662 a_nodelete
, PSTR(a_adminFile
));
1664 (void) snprintf(path
, sizeof (path
), "%s/pkgremove",
1665 a_altBinDir
== (char *)NULL
? PKGBIN
: a_altBinDir
);
1669 /* first argument is path to executable */
1671 arg
[nargs
++] = strdup(path
);
1673 /* second argument is always: pass -O debug to pkgremove: debug mode */
1675 if (debugFlag
== B_TRUE
) {
1676 arg
[nargs
++] = "-O";
1677 arg
[nargs
++] = "debug";
1680 /* Add arguments how to start the pkgserv */
1682 arg
[nargs
++] = "-O";
1683 arg
[nargs
++] = pkgmodeargument(pkgservergetmode());
1685 /* pkgrm -b dir: pass -b to pkgremove */
1687 if (a_altBinDir
!= (char *)NULL
) {
1688 arg
[nargs
++] = "-b";
1689 arg
[nargs
++] = a_altBinDir
;
1693 * NONABI_SCRIPTS defined: pass -o to pkgremove; refers to a
1694 * pkg requiring operator interaction during a procedure script
1695 * (common before on1093)
1699 arg
[nargs
++] = "-o";
1703 * PKG_NONABI_SYMLINKS defined: pass -y to pkgremove; process
1704 * symlinks consistent with old behavior
1708 arg
[nargs
++] = "-y";
1711 /* pkgrm -M: pass -M to pkgrm: dont mount client file systems */
1713 if (no_map_client
) {
1714 arg
[nargs
++] = "-M";
1717 /* pkgrm -A: pass -A to pkgrm */
1720 arg
[nargs
++] = "-A";
1723 /* pkgrm -v: pass -v to pkgremove: trace scripts */
1726 arg
[nargs
++] = "-v";
1729 /* pkgrm -n: pass -n to pkgremove: noninteractive mode */
1732 arg
[nargs
++] = "-n";
1735 /* pkgrm -a admin: pass -a admin to pkgremove: admin file */
1738 arg
[nargs
++] = "-a";
1739 arg
[nargs
++] = strdup(a_adminFile
);
1742 /* pkgrm -V vfstab: pass -V vfstab to pkgremove: alternate vfstab */
1745 arg
[nargs
++] = "-V";
1746 arg
[nargs
++] = vfstab_file
;
1749 /* pkgrm -R root: pass -R root to pkgremove: alternative root */
1751 if (is_an_inst_root()) {
1752 arg
[nargs
++] = "-R";
1753 arg
[nargs
++] = get_inst_root();
1756 /* pkgrm -F: pass -F to pkgremove: update DB only */
1759 arg
[nargs
++] = "-F";
1763 * add parent zone info/type
1766 p
= z_get_zonename();
1767 if ((p
!= NULL
) && (*p
!= '\0')) {
1768 char zn
[MAXPATHLEN
];
1769 (void) snprintf(zn
, sizeof (zn
),
1770 "parent-zone-name=%s", p
);
1771 arg
[nargs
++] = "-O";
1772 arg
[nargs
++] = strdup(zn
);
1775 /* current zone type */
1777 arg
[nargs
++] = "-O";
1778 if (z_running_in_global_zone() == B_TRUE
) {
1779 char zn
[MAXPATHLEN
];
1780 (void) snprintf(zn
, sizeof (zn
),
1781 "parent-zone-type=%s",
1782 TAG_VALUE_GLOBAL_ZONE
);
1783 arg
[nargs
++] = strdup(zn
);
1785 char zn
[MAXPATHLEN
];
1786 (void) snprintf(zn
, sizeof (zn
),
1787 "parent-zone-type=%s",
1788 TAG_VALUE_NONGLOBAL_ZONE
);
1789 arg
[nargs
++] = strdup(zn
);
1792 /* pass -N to pkgremove: program name to report */
1794 arg
[nargs
++] = "-N";
1795 arg
[nargs
++] = get_prog_name();
1797 /* add package instance name */
1799 arg
[nargs
++] = pkginst
;
1801 /* terminate argument list */
1803 arg
[nargs
++] = NULL
;
1806 * run the appropriate pkgremove command in the specified zone
1809 if (debugFlag
== B_TRUE
) {
1810 echoDebug(DBG_ZONE_EXEC_ENTER
, "global", arg
[0]);
1811 for (n
= 0; arg
[n
]; n
++) {
1812 echoDebug(DBG_ARG
, n
, arg
[n
]);
1816 /* execute pkgremove command */
1818 n
= pkgexecv(NULL
, NULL
, NULL
, NULL
, arg
);
1820 /* return results of pkgrm in this zone */
1828 char *prog
= get_prog_name();
1830 (void) fprintf(stderr
, ERR_USAGE_PKGRM
, prog
, prog
);
1835 * Name: remove_packages_in_global_with_zones
1836 * Description: Remove packages from the global zone and from non-global zones
1837 * when run from the global zone and when non-global zones are
1839 * Arguments: a_pkgList - pointer to array of strings, each string specifying
1840 * the name of one package to be removed.
1841 * a_nodelete: should the files and scripts remain installed?
1842 * - if != 0 pass -F flag to pkgremove - suppress
1843 * the removal of any files and any class action scripts
1844 * and suppress the running of any class action scripts.
1845 * The package files remain but the package looks like it
1846 * is not installed. This is mainly for use by upgrade.
1847 * - if == 0 do not pass -F flag to pkgremove - all
1848 * files and class action scripts are removed, and any
1849 * appropriate class action scripts are run.
1850 * a_longestPkg - length of the longest package "name" (for
1851 * output format alignment)
1852 * a_repeat - are there more packages avialable in "optind"
1853 * - B_TRUE - process packages from optind
1854 * - B_FALSE - do not process packages from optind
1855 * a_altBinDir - pointer to string representing location of the
1856 * pkgremove executable to run. If not NULL, then pass
1857 * the path specified to the -b option to pkgremove.
1858 * a_pkgdir - pointer to string representing the directory
1859 * where the packages to be removed are located.
1860 * a_zlst - list of zones to process; NULL if no zones to process.
1861 * Returns: int (see ckreturn() function for details)
1863 * 1 - package operation failed (fatal error)
1864 * 2 - non-fatal error (warning)
1865 * 3 - user selected quit (operation interrupted)
1866 * 4 - admin settings prevented operation
1867 * 5 - interaction required and -n (non-interactive) specified
1868 * "10" will be added to indicate "immediate reboot required"
1869 * "20" will be added to indicate "reboot after install required"
1873 remove_packages_in_global_with_zones(char **a_pkgList
, int a_nodelete
,
1874 int a_longestPkg
, int a_repeat
, char *a_altBinDir
, char *a_pkgdir
,
1877 static char *zoneAdminFile
= (char *)NULL
;
1882 char preremovecheckPath
[PATH_MAX
+1];
1885 int savenpkgs
= npkgs
;
1890 /* entry assertions */
1892 assert(a_zlst
!= (zoneList_t
)NULL
);
1893 assert(a_pkgList
!= (char **)NULL
);
1894 assert(a_longestPkg
> 0);
1895 assert(a_pkgdir
!= (char *)NULL
);
1896 assert(*a_pkgdir
!= '\0');
1898 /* entry debugging info */
1900 echoDebug(DBG_PKGREMPKGSGZWNGZ_ENTRY
);
1901 echoDebug(DBG_PKGREMPKGSGZWNGZ_ARGS
, a_nodelete
, a_longestPkg
,
1902 a_repeat
, PSTR(a_altBinDir
), PSTR(a_pkgdir
));
1904 /* check all packages */
1906 if (check_packages(a_pkgList
, a_pkgdir
) != B_TRUE
) {
1910 /* create temporary directory for use by zone operations */
1912 create_zone_tempdir(&zoneTempDir
, tmpdir
);
1914 /* create hands off settings admin file for use in a non-global zone */
1916 create_zone_adminfile(&zoneAdminFile
, zoneTempDir
, admnfile
);
1919 * all of the packages (as listed in the package list) are
1920 * removed one at a time from all non-global zones and then
1921 * from the global zone.
1924 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
1925 /* reset interrupted flag before calling pkgremove */
1927 interrupted
= 0; /* last action was NOT quit */
1929 /* skip package if it is "in the global zone only" */
1931 if (pkgIsPkgInGzOnly(get_inst_root(), pkginst
) == B_TRUE
) {
1936 * if operation failed in global zone do not propagate to
1942 if (interrupted
!= 0) {
1943 echo(MSG_DOREMOVE_INTERRUPTED
, pkginst
);
1944 echoDebug(DBG_DOREMOVE_INTERRUPTED
, pkginst
);
1948 echoDebug(DBG_REMOVE_FLAG_VALUES
, "before loop",
1949 admnflag
, doreboot
, failflag
, interrupted
,
1950 intrflag
, ireboot
, nullflag
, warnflag
);
1953 (zoneName
= z_zlist_get_zonename(a_zlst
, zoneIndex
)) !=
1954 (char *)NULL
; zoneIndex
++) {
1956 /* skip the zone if it is NOT running */
1958 zst
= z_zlist_get_current_state(a_zlst
, zoneIndex
);
1959 if (zst
!= ZONE_STATE_RUNNING
&&
1960 zst
!= ZONE_STATE_MOUNTED
) {
1962 echoDebug(DBG_SKIPPING_ZONE
, zoneName
);
1966 echo(MSG_CHECKREMOVE_PKG_IN_ZONE
, pkginst
, zoneName
);
1967 echoDebug(DBG_CHECKREMOVE_PKG_IN_ZONE
, pkginst
,
1970 scratchName
= z_zlist_get_scratch(a_zlst
, zoneIndex
);
1972 (void) snprintf(preremovecheckPath
,
1973 sizeof (preremovecheckPath
),
1974 "%s/%s.%s.preremovecheck.txt",
1975 zoneTempDir
, pkginst
, scratchName
);
1978 * dependency check this package this zone; use the
1979 * user supplied admin file so that the appropriate
1980 * level of dependency checking is (or is not) done.
1983 n
= pkgZoneCheckRemove(scratchName
, a_altBinDir
,
1984 admnfile
, preremovecheckPath
,
1987 /* set success/fail condition variables */
1991 echoDebug(DBG_REMOVE_FLAG_VALUES
,
1992 "after pkgzonecheckremove",
1993 admnflag
, doreboot
, failflag
, interrupted
,
1994 intrflag
, ireboot
, nullflag
, warnflag
);
1997 if (zonesSkipped
== 0) {
2001 echoDebug(DBG_ZONES_SKIPPED
, zonesSkipped
);
2004 (zoneName
= z_zlist_get_zonename(a_zlst
, zoneIndex
)) !=
2005 (char *)NULL
; zoneIndex
++) {
2007 /* skip the zone if it IS running */
2009 zst
= z_zlist_get_current_state(a_zlst
, zoneIndex
);
2010 if (zst
== ZONE_STATE_RUNNING
||
2011 zst
== ZONE_STATE_MOUNTED
) {
2013 echoDebug(DBG_SKIPPING_ZONE_BOOT
, zoneName
);
2017 /* skip the zone if it is NOT bootable */
2019 if (z_zlist_is_zone_runnable(a_zlst
,
2020 zoneIndex
) == B_FALSE
) {
2021 echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE
, zoneName
);
2022 echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE
,
2027 /* mount up the zone */
2029 echo(MSG_BOOTING_ZONE
, zoneName
);
2030 echoDebug(DBG_BOOTING_ZONE
, zoneName
);
2032 b
= z_zlist_change_zone_state(a_zlst
, zoneIndex
,
2033 ZONE_STATE_MOUNTED
);
2035 progerr(ERR_CANNOT_BOOT_ZONE
, zoneName
);
2036 /* set fatal error return condition */
2041 echo(MSG_CHECKREMOVE_PKG_IN_ZONE
, pkginst
, zoneName
);
2042 echoDebug(DBG_CHECKREMOVE_PKG_IN_ZONE
, pkginst
,
2045 scratchName
= z_zlist_get_scratch(a_zlst
, zoneIndex
);
2047 (void) snprintf(preremovecheckPath
,
2048 sizeof (preremovecheckPath
),
2049 "%s/%s.%s.preremovecheck.txt",
2050 zoneTempDir
, pkginst
, scratchName
);
2053 * dependency check this package this zone; use the
2054 * user supplied admin file so that the appropriate
2055 * level of dependency checking is (or is not) done.
2058 n
= pkgZoneCheckRemove(scratchName
, a_altBinDir
,
2059 admnfile
, preremovecheckPath
,
2060 ZONE_STATE_MOUNTED
, B_TRUE
);
2062 /* set success/fail condition variables */
2066 echoDebug(DBG_REMOVE_FLAG_VALUES
,
2067 "after pkgzonecheckremove",
2068 admnflag
, doreboot
, failflag
, interrupted
,
2069 intrflag
, ireboot
, nullflag
, warnflag
);
2071 /* restore original state of zone */
2073 echo(MSG_RESTORE_ZONE_STATE
, zoneName
);
2074 echoDebug(DBG_RESTORE_ZONE_STATE
, zoneName
);
2076 b
= z_zlist_restore_zone_state(a_zlst
, zoneIndex
);
2082 * look at all pre-remove check files
2085 i
= preremove_verify(a_pkgList
, a_zlst
, zoneTempDir
);
2093 * reset all error return condition variables that may have been
2094 * set during package removal dependency checking so that they
2095 * do not reflect on the success/failure of the actual package
2096 * removal operations
2102 * all of the packages (as listed in the package list) are
2103 * removed one at a time.
2107 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
2108 boolean_t in_gz_only
;
2111 if (shall_we_continue(pkginst
, npkgs
) == B_FALSE
) {
2115 in_gz_only
= pkgIsPkgInGzOnly(get_inst_root(), pkginst
);
2117 /* reset interrupted flag before calling pkgremove */
2122 * pkgrm invoked from within the global zone and there are
2123 * non-global zones configured:
2124 * Remove the package from the global zone.
2125 * If not removing the package from the global zone only,
2126 * then remove the package from the list of zones specified.
2130 /* global zone only */
2131 n
= doRemove(a_nodelete
, a_altBinDir
, a_longestPkg
,
2132 admnfile
, (char *)NULL
, (zoneList_t
)NULL
);
2134 /* global zone and non-global zones */
2135 n
= doRemove(a_nodelete
, a_altBinDir
, a_longestPkg
,
2136 zoneAdminFile
, zoneAdminFile
, a_zlst
);
2139 /* set success/fail condition variables */
2147 * all packages in the package list have been removed.
2148 * Continue with removal if:
2149 * -- immediate reboot is NOT required
2150 * -- there are more packages to remove
2151 * else return do NOT continue.
2154 if ((ireboot
== 0) && (a_repeat
!= 0)) {
2158 /* return 'dont continue' */
2164 * Name: remove_packages_in_nonglobal_zone
2165 * Description: Remove packages in a non-global zone when run from a
2167 * Arguments: a_pkgList - pointer to array of strings, each string specifying
2168 * the name of one package to be removed.
2169 * a_nodelete: should the files and scripts remain installed?
2170 * - if != 0 pass -F flag to pkgremove - suppress
2171 * the removal of any files and any class action scripts
2172 * and suppress the running of any class action scripts.
2173 * The package files remain but the package looks like it
2174 * is not installed. This is mainly for use by upgrade.
2175 * - if == 0 do not pass -F flag to pkgremove - all
2176 * files and class action scripts are removed, and any
2177 * appropriate class action scripts are run.
2178 * a_longestPkg - length of the longest package "name" (for
2179 * output format alignment)
2180 * a_repeat - are there more packages avialable in "optind"
2181 * - B_TRUE - process packages from optind
2182 * - B_FALSE - do not process packages from optind
2183 * a_altBinDir - pointer to string representing location of the
2184 * pkgremove executable to run. If not NULL, then pass
2185 * the path specified to the -b option to pkgremove.
2186 * a_pkgdir - pointer to string representing the directory
2187 * where the packages to be removed are located.
2188 * Returns: int (see ckreturn() function for details)
2190 * 1 - package operation failed (fatal error)
2191 * 2 - non-fatal error (warning)
2192 * 3 - user selected quit (operation interrupted)
2193 * 4 - admin settings prevented operation
2194 * 5 - interaction required and -n (non-interactive) specified
2195 * "10" will be added to indicate "immediate reboot required"
2196 * "20" will be added to indicate "reboot after install required"
2200 remove_packages_in_nonglobal_zone(char **a_pkgList
, int a_nodelete
,
2201 int a_longestPkg
, int a_repeat
, char *a_altBinDir
, char *a_pkgdir
)
2203 static char *zoneAdminFile
= (char *)NULL
;
2208 /* entry assertions */
2210 assert(a_pkgList
!= (char **)NULL
);
2211 assert(a_longestPkg
> 0);
2212 assert(a_pkgdir
!= (char *)NULL
);
2213 assert(*a_pkgdir
!= '\0');
2215 /* entry debugging info */
2217 echoDebug(DBG_PKGREMPKGSNGZ_ENTRY
);
2218 echoDebug(DBG_PKGREMPKGSNGZ_ARGS
, a_nodelete
, a_longestPkg
,
2219 a_repeat
, PSTR(a_altBinDir
), PSTR(a_pkgdir
));
2221 /* check all package */
2223 if (check_packages(a_pkgList
, a_pkgdir
) != B_TRUE
) {
2227 /* create temporary directory for use by zone operations */
2229 create_zone_tempdir(&zoneTempDir
, tmpdir
);
2231 /* create hands off settings admin file for use in a non-global zone */
2233 create_zone_adminfile(&zoneAdminFile
, zoneTempDir
, admnfile
);
2236 * all of the packages (as listed in the package list) are
2237 * removed one at a time.
2241 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
2244 if (shall_we_continue(pkginst
, npkgs
) == B_FALSE
) {
2251 * pkgrm invoked from within a non-global zone: remove
2252 * the package from the current zone only - no non-global
2253 * zones are possible.
2256 n
= doRemove(a_nodelete
, a_altBinDir
, a_longestPkg
,
2257 admnfile
, (char *)NULL
, (zoneList_t
)NULL
);
2259 /* set success/fail condition variables */
2267 * all packages in the package list have been removed.
2268 * Continue with removal if:
2269 * -- immediate reboot is NOT required
2270 * -- there are more packages to remove
2271 * else return do NOT continue.
2274 if ((ireboot
== 0) && (a_repeat
!= 0)) {
2278 /* return 'dont continue' */
2284 * Name: remove_packages_in_global_no_zones
2285 * Description: Remove packages from the global zone only when run in the
2286 * global zone and no non-global zones are installed.
2287 * Arguments: a_pkgList - pointer to array of strings, each string specifying
2288 * the name of one package to be removed.
2289 * a_nodelete: should the files and scripts remain installed?
2290 * - if != 0 pass -F flag to pkgremove - suppress
2291 * the removal of any files and any class action scripts
2292 * and suppress the running of any class action scripts.
2293 * The package files remain but the package looks like it
2294 * is not installed. This is mainly for use by upgrade.
2295 * - if == 0 do not pass -F flag to pkgremove - all
2296 * files and class action scripts are removed, and any
2297 * appropriate class action scripts are run.
2298 * a_longestPkg - length of the longest package "name" (for
2299 * output format alignment)
2300 * a_repeat - are there more packages avialable in "optind"
2301 * - B_TRUE - process packages from optind
2302 * - B_FALSE - do not process packages from optind
2303 * a_altBinDir - pointer to string representing location of the
2304 * pkgremove executable to run. If not NULL, then pass
2305 * the path specified to the -b option to pkgremove.
2306 * Returns: int (see ckreturn() function for details)
2308 * 1 - package operation failed (fatal error)
2309 * 2 - non-fatal error (warning)
2310 * 3 - user selected quit (operation interrupted)
2311 * 4 - admin settings prevented operation
2312 * 5 - interaction required and -n (non-interactive) specified
2313 * "10" will be added to indicate "immediate reboot required"
2314 * "20" will be added to indicate "reboot after install required"
2318 remove_packages_in_global_no_zones(char **a_pkgList
, int a_nodelete
,
2319 int a_longestPkg
, int a_repeat
, char *a_altBinDir
)
2324 /* entry assertions */
2326 assert(a_pkgList
!= (char **)NULL
);
2327 assert(a_longestPkg
> 0);
2329 /* entry debugging info */
2331 echoDebug(DBG_PKGREMPKGSGZNNGZ_ENTRY
);
2332 echoDebug(DBG_PKGREMPKGSGZNNGZ_ARGS
, a_nodelete
, a_longestPkg
,
2333 a_repeat
, PSTR(a_altBinDir
));
2336 * all of the packages (as listed in the package list) are
2337 * removed one at a time.
2341 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
2344 if (shall_we_continue(pkginst
, npkgs
) == B_FALSE
) {
2351 * pkgrm invoked from within the global zone and there are
2352 * NO non-global zones configured:
2353 * Remove the package from the global zone only.
2356 n
= doRemove(a_nodelete
, a_altBinDir
, a_longestPkg
,
2357 admnfile
, (char *)NULL
, (zoneList_t
)NULL
);
2359 /* set success/fail condition variables */
2367 * all packages in the package list have been removed.
2368 * Continue with removal if:
2369 * -- immediate reboot is NOT required
2370 * -- there are more packages to remove
2371 * else return do NOT continue.
2374 if ((ireboot
== 0) && (a_repeat
!= 0)) {
2378 /* return 'dont continue' */
2384 * Name: remove_packages_from_spool_directory
2385 * Description: Remove packages from a spool directory only.
2386 * Arguments: a_pkgList - pointer to array of strings, each string specifying
2387 * the name of one package to be removed.
2388 * a_nodelete: should the files and scripts remain installed?
2389 * - if != 0 pass -F flag to pkgremove - suppress
2390 * the removal of any files and any class action scripts
2391 * and suppress the running of any class action scripts.
2392 * The package files remain but the package looks like it
2393 * is not installed. This is mainly for use by upgrade.
2394 * - if == 0 do not pass -F flag to pkgremove - all
2395 * files and class action scripts are removed, and any
2396 * appropriate class action scripts are run.
2397 * a_longestPkg - length of the longest package "name" (for
2398 * output format alignment)
2399 * a_repeat - are there more packages avialable in "optind"
2400 * - B_TRUE - process packages from optind
2401 * - B_FALSE - do not process packages from optind
2402 * a_altBinDir - pointer to string representing location of the
2403 * pkgremove executable to run. If not NULL, then pass
2404 * the path specified to the -b option to pkgremove.
2405 * Returns: int (see ckreturn() function for details)
2407 * 1 - package operation failed (fatal error)
2408 * 2 - non-fatal error (warning)
2409 * 3 - user selected quit (operation interrupted)
2410 * 4 - admin settings prevented operation
2411 * 5 - interaction required and -n (non-interactive) specified
2412 * "10" will be added to indicate "immediate reboot required"
2413 * "20" will be added to indicate "reboot after install required"
2417 remove_packages_from_spool_directory(char **a_pkgList
, int a_nodelete
,
2418 int a_longestPkg
, int a_repeat
, char *a_altBinDir
)
2423 /* entry assertions */
2425 assert(a_pkgList
!= (char **)NULL
);
2426 assert(a_longestPkg
> 0);
2429 * all of the packages (as listed in the package list) are
2430 * removed one at a time.
2434 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
2437 if (shall_we_continue(pkginst
, npkgs
) == B_FALSE
) {
2444 * pkgrm invoked from any type of zone BUT the target
2445 * to be removed is a local spool directory: remove the
2446 * packages from the spool directory only.
2449 n
= doRemove(a_nodelete
, a_altBinDir
, a_longestPkg
,
2450 admnfile
, (char *)NULL
, (zoneList_t
)NULL
);
2452 /* set success/fail condition variables */
2460 * all packages in the package list have been removed.
2461 * Continue with removal if:
2462 * -- immediate reboot is NOT required
2463 * -- there are more packages to remove
2464 * else return do NOT continue.
2467 if ((ireboot
== 0) && (a_repeat
!= 0)) {
2471 /* return 'dont continue' */
2477 * Name: remove_packages
2478 * Description: Remove packages from the global zone, and optionally from one
2479 * or more non-global zones, or from a specified spool directory.
2480 * Arguments: a_pkgList - pointer to array of strings, each string specifying
2481 * the name of one package to be removed.
2482 * a_nodelete: should the files and scripts remain installed?
2483 * - if != 0 pass -F flag to pkgremove - suppress
2484 * the removal of any files and any class action scripts
2485 * and suppress the running of any class action scripts.
2486 * The package files remain but the package looks like it
2487 * is not installed. This is mainly for use by upgrade.
2488 * - if == 0 do not pass -F flag to pkgremove - all
2489 * files and class action scripts are removed, and any
2490 * appropriate class action scripts are run.
2491 * a_longestPkg - length of the longest package "name" (for
2492 * output format alignment)
2493 * a_repeat - are there more packages avialable in "optind"
2494 * - B_TRUE - process packages from optind
2495 * - B_FALSE - do not process packages from optind
2496 * a_altBinDir - pointer to string representing location of the
2497 * pkgremove executable to run. If not NULL, then pass
2498 * the path specified to the -b option to pkgremove.
2499 * a_pkgdir - pointer to string representing the directory
2500 * where the packages to be removed are located.
2501 * a_spoolDir - pointer to string specifying spool directory
2502 * to remove packages from. If != NULL then all zones
2503 * processing is bypassed and the packages are removed
2504 * from the specified spool directory only.
2505 * a_noZones - if non-global zones are configured, should the
2506 * packages be removed from the non-global zones?
2507 * - B_TRUE - do NOT remove packages from non-global zones
2508 * - B_FALSE - remove packages from non-global zones
2509 * Returns: int (see ckreturn() function for details)
2511 * 1 - package operation failed (fatal error)
2512 * 2 - non-fatal error (warning)
2513 * 3 - user selected quit (operation interrupted)
2514 * 4 - admin settings prevented operation
2515 * 5 - interaction required and -n (non-interactive) specified
2516 * "10" will be added to indicate "immediate reboot required"
2517 * "20" will be added to indicate "reboot after install required"
2521 remove_packages(char **a_pkgList
, int a_nodelete
, int a_longestPkg
,
2522 int a_repeat
, char *a_altBinDir
, char *a_pkgdir
, char *a_spoolDir
,
2523 boolean_t a_noZones
)
2528 /* entry assertions */
2530 assert(a_pkgList
!= (char **)NULL
);
2532 echoDebug(DBG_REMOVEPKGS_ENTRY
);
2533 echoDebug(DBG_REMOVEPKGS_ARGS
, npkgs
, a_nodelete
, a_longestPkg
,
2534 a_repeat
, PSTR(a_pkgdir
), PSTR(a_spoolDir
));
2537 * if removing from spool directory, bypass all zones checks
2540 if (a_spoolDir
!= (char *)NULL
) {
2541 /* in non-global zone */
2543 echoDebug(DBG_REMOVE_PKGS_FROM_SPOOL
, a_spoolDir
);
2545 b
= remove_packages_from_spool_directory(a_pkgList
, a_nodelete
,
2546 a_longestPkg
, a_repeat
, a_altBinDir
);
2551 /* exit if not root */
2554 progerr(ERR_NOT_ROOT
, get_prog_name());
2559 * if running in the global zone AND one or more non-global
2560 * zones exist, add packages in a 'zones aware' manner, else
2561 * add packages in the standard 'non-zones aware' manner.
2564 if ((a_noZones
== B_FALSE
) && (z_running_in_global_zone() == B_FALSE
)) {
2565 /* in non-global zone */
2567 echoDebug(DBG_IN_LZ
);
2569 b
= z_lock_this_zone(ZLOCKS_PKG_ADMIN
);
2571 progerr(ERR_CANNOT_LOCK_THIS_ZONE
);
2572 /* set fatal error return condition */
2577 b
= remove_packages_in_nonglobal_zone(a_pkgList
, a_nodelete
,
2578 a_longestPkg
, a_repeat
, a_altBinDir
, a_pkgdir
);
2580 (void) z_unlock_this_zone(ZLOCKS_ALL
);
2585 /* running in the global zone */
2587 b
= z_non_global_zones_exist();
2588 if ((a_noZones
== B_FALSE
) && (b
== B_TRUE
)) {
2590 echoDebug(DBG_IN_GZ_WITH_LZ
);
2592 /* get a list of all non-global zones */
2593 zlst
= z_get_nonglobal_zone_list();
2594 if (zlst
== (zoneList_t
)NULL
) {
2595 progerr(ERR_CANNOT_GET_ZONE_LIST
);
2599 /* need to lock all of the zones */
2601 quitSetZonelist(zlst
);
2602 b
= z_lock_zones(zlst
, ZLOCKS_PKG_ADMIN
);
2604 z_free_zone_list(zlst
);
2605 progerr(ERR_CANNOT_LOCK_ZONES
);
2606 /* set fatal error return condition */
2611 /* add packages to all zones */
2613 b
= remove_packages_in_global_with_zones(a_pkgList
, a_nodelete
,
2614 a_longestPkg
, a_repeat
, a_altBinDir
, a_pkgdir
, zlst
);
2616 /* unlock all zones */
2618 (void) z_unlock_zones(zlst
, ZLOCKS_ALL
);
2619 quitSetZonelist((zoneList_t
)NULL
);
2621 /* free list of all non-global zones */
2623 z_free_zone_list(zlst
);
2628 /* in global zone no non-global zones */
2630 echoDebug(DBG_IN_GZ_NO_LZ
);
2632 b
= z_lock_this_zone(ZLOCKS_PKG_ADMIN
);
2634 progerr(ERR_CANNOT_LOCK_THIS_ZONE
);
2635 /* set fatal error return condition */
2640 b
= remove_packages_in_global_no_zones(a_pkgList
, a_nodelete
,
2641 a_longestPkg
, a_repeat
, a_altBinDir
);
2643 (void) z_unlock_this_zone(ZLOCKS_ALL
);
2652 check_packages(char **a_pkgList
, char *a_packageDir
)
2654 int savenpkgs
= npkgs
;
2658 /* set flags for applicability check */
2660 if (z_running_in_global_zone() == B_TRUE
) {
2661 flags
|= CAF_IN_GLOBAL_ZONE
;
2665 * for each package to remove, verify that the package is installed
2669 for (i
= 0; (pkginst
= a_pkgList
[i
]) != NULL
; i
++) {
2670 /* check package applicability */
2671 if (check_applicability(a_packageDir
, pkginst
, get_inst_root(),
2672 flags
) == B_FALSE
) {
2673 progerr(ERR_PKG_NOT_REMOVABLE
, pkginst
);
2685 * - is this package removable from this zone?
2686 * - does the scope of remove conflict with existing installation
2690 check_applicability(char *a_packageDir
, char *a_pkgInst
,
2691 char *a_rootPath
, CAF_T a_flags
)
2694 boolean_t all_zones
; /* pkg is "all zones" only */
2695 char pkginfoPath
[PATH_MAX
];
2696 char pkgpath
[PATH_MAX
];
2699 /* entry assertions */
2701 assert(a_packageDir
!= (char *)NULL
);
2702 assert(*a_packageDir
!= '\0');
2703 assert(a_pkgInst
!= (char *)NULL
);
2704 assert(*a_pkgInst
!= '\0');
2706 /* normalize root path */
2708 if (a_rootPath
== (char *)NULL
) {
2713 * determine if this package is currently installed
2714 * if not installed return success - operation will fail
2715 * when the removal is attempted
2718 if (pkginfoIsPkgInstalled((struct pkginfo
**)NULL
, a_pkgInst
) !=
2724 * calculate paths to various objects
2727 len
= snprintf(pkgpath
, sizeof (pkgpath
), "%s/%s", a_packageDir
,
2729 if (len
> sizeof (pkgpath
)) {
2730 progerr(ERR_CREATE_PATH_2
, a_packageDir
, a_pkgInst
);
2734 /* if not installed then just return */
2736 if (isdir(pkgpath
) != 0) {
2737 progerr(ERR_NO_PKGDIR
, pkgpath
, a_pkgInst
, strerror(errno
));
2741 len
= snprintf(pkginfoPath
, sizeof (pkginfoPath
),
2742 "%s/pkginfo", pkgpath
);
2743 if (len
> sizeof (pkgpath
)) {
2744 progerr(ERR_CREATE_PATH_2
, pkgpath
, "pkginfo");
2749 * gather information from this packages pkginfo file
2752 pkginfoFP
= fopen(pkginfoPath
, "r");
2754 if (pkginfoFP
== (FILE *)NULL
) {
2755 progerr(ERR_NO_PKG_INFOFILE
, a_pkgInst
, pkginfoPath
,
2760 /* determine "ALLZONES" setting for this package */
2762 all_zones
= pkginfoParamTruth(pkginfoFP
, PKG_ALLZONES_VARIABLE
,
2765 /* close pkginfo file */
2767 (void) fclose(pkginfoFP
);
2769 /* gather information from the global zone only file */
2772 * verify package applicability based on information gathered;
2773 * the package IS currently installed....
2776 /* pkg ALLZONES=true & not running in global zone */
2778 if ((all_zones
== B_TRUE
) && (!(a_flags
& CAF_IN_GLOBAL_ZONE
))) {
2779 progerr(ERR_ALLZONES_AND_IN_LZ_PKGRM
, a_pkgInst
);
2787 * Name: shall_we_continue
2788 * Description: Called from within a loop that is installing packages,
2789 * this function examines various global variables and decides
2790 * whether or not to ask an appropriate question, and wait for
2791 * and appropriate reply.
2792 * Arguments: <<global variables>>
2793 * Returns: B_TRUE - continue processing with next package
2794 * B_FALSE - do not continue processing with next package
2798 shall_we_continue(char *a_pkgInst
, int a_npkgs
)
2800 char ans
[MAX_INPUT
];
2803 /* return FALSE if immediate reboot required */
2806 ptext(stderr
, MSG_SUSPEND_RM
, a_pkgInst
);
2810 /* return TRUE if not interrupted */
2816 /* output appropriate interrupt message */
2818 echo(a_npkgs
== 1 ? MSG_1MORETODO
: MSG_MORETODO
, a_npkgs
);
2820 /* if running with no interaction (-n) do not ask question */
2827 /* interaction possible: ask question */
2829 n
= ckyorn(ans
, NULL
, NULL
, NULL
, ASK_CONTINUE_RM
);
2835 if (strchr("yY", *ans
) == NULL
) {
2843 * Name: create_zone_adminfile
2844 * Description: Given a zone temporary directory and optionally an existing
2845 * administration file, generate an administration file that
2846 * can be used to perform "non-interactive" operations in a
2848 * Arguments: r_zoneAdminFile - pointer to handle that will contain a
2849 * string representing the path to the temporary
2850 * administration file created - this must be NULL
2851 * before the first call to this function - on
2852 * subsequent calls if the pointer is NOT null then
2853 * the existing string will NOT be overwritten.
2854 * a_zoneTempDir - pointer to string representing the path
2855 * to the zone temporary directory to create the
2856 * temporary administration file in
2857 * a_admnfile - pointer to string representing the path to
2858 * an existing "user" administration file - the
2859 * administration file created will contain the
2860 * settings contained in this file, modified as
2861 * appropriate to supress any interaction;
2862 * If this is == NULL then the administration file
2863 * created will not contain any extra settings
2865 * NOTE: Any string returned is placed in new storage for the
2866 * calling method. The caller must use 'free' to dispose
2867 * of the storage once the string is no longer needed.
2868 * NOTE: On any error this function will call 'quit(1)'
2872 create_zone_adminfile(char **r_zoneAdminFile
, char *a_zoneTempDir
,
2877 /* entry assertions */
2879 assert(r_zoneAdminFile
!= (char **)NULL
);
2880 assert(a_zoneTempDir
!= (char *)NULL
);
2881 assert(*a_zoneTempDir
!= '\0');
2883 /* entry debugging info */
2885 echoDebug(DBG_CREATE_ZONE_ADMINFILE
, a_zoneTempDir
, PSTR(a_admnfile
));
2887 /* if temporary name already exists, do not overwrite */
2889 if (*r_zoneAdminFile
!= (char *)NULL
) {
2893 /* create temporary name */
2895 *r_zoneAdminFile
= tempnam(a_zoneTempDir
, "zadmn");
2896 b
= z_create_zone_admin_file(*r_zoneAdminFile
, a_admnfile
);
2898 progerr(ERR_CREATE_TMPADMIN
, *r_zoneAdminFile
,
2904 echoDebug(DBG_CREATED_ZONE_ADMINFILE
, *r_zoneAdminFile
);
2908 * Name: create_zone_tempdir
2909 * Description: Given a system temporary directory, create a "zone" specific
2910 * temporary directory and return the path to the directory
2912 * Arguments: r_zoneTempDir - pointer to handle that will contain a
2913 * string representing the path to the temporary
2914 * directory created - this must be NULL before the
2915 * first call to this function - on subsequent calls
2916 * if the pointer is NOT null then the existing string
2917 * will NOT be overwritten.
2918 * a_zoneTempDir - pointer to string representing the path
2919 * to the system temporary directory to create the
2920 * temporary zone directory in
2922 * NOTE: Any string returned is placed in new storage for the
2923 * calling method. The caller must use 'free' to dispose
2924 * of the storage once the string is no longer needed.
2925 * NOTE: On any error this function will call 'quit(1)'
2926 * NOTE: This function calls "quitSetZoneTmpdir" on success to
2927 * register the directory created with quit() so that the
2928 * directory will be automatically deleted on exit.
2932 create_zone_tempdir(char **r_zoneTempDir
, char *a_tmpdir
)
2936 /* entry assertions */
2938 assert(r_zoneTempDir
!= (char **)NULL
);
2939 assert(a_tmpdir
!= (char *)NULL
);
2940 assert(*a_tmpdir
!= '\0');
2942 /* entry debugging info */
2944 echoDebug(DBG_CREATE_ZONE_TEMPDIR
, a_tmpdir
);
2946 /* if temporary directory already exists, do not overwrite */
2948 if (*r_zoneTempDir
!= (char *)NULL
) {
2952 /* create temporary directory */
2954 b
= setup_temporary_directory(r_zoneTempDir
, a_tmpdir
, "ztemp");
2956 progerr(ERR_ZONETEMPDIR
, a_tmpdir
, strerror(errno
));
2961 /* register with quit() to directory is removed on exit */
2963 quitSetZoneTmpdir(*r_zoneTempDir
);
2965 /* exit debugging info */
2967 echoDebug(DBG_CREATED_ZONE_TEMPDIR
, *r_zoneTempDir
);