main.c revision 5c51f1241dbbdf2656d0e10011981411ed0c9673
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Program: pkgcond
*
* Function: Implements the package command suite public utility pkgcond(1M)
*
* Usage: pkgcond [-nv] [-O debug] condition [ argument ]
*
* command options:
* -n - negate results of condition test
* -v - verbose output of condition testing
*
* <condition> may be any one of:
* can_add_driver [path]
* can_remove_driver [path]
* can_update_driver [path]
* is_alternative_root [path]
* is_boot_environment [path]
* is_diskless_client [path]
* is_global_zone [path]
* is_mounted_miniroot [path]
* is_netinstall_image [path]
* is_nonglobal_zone [path]
* is_path_writable path
* is_running_system [path]
* is_sparse_root_nonglobal_zone [path]
* is_what [path]
* is_whole_root_nonglobal_zone [path]
*
* <option(s)> are specific to the condition used
*
* Input: depends on command
*
* Output: depends on command
*
* Exit status: If the -n option is not specified:
* == 0 - the specified condition is true (or exists).
* == 1 - the specified condition is false (or does not exist).
* == 2 - command line usage errors (including bad keywords)
* == 3 - command failed to perform the test due to a fatal error
*
* If the -n option is specified:
* == 0 - the specified condition is false (or does not exist).
* == 1 - the specified condition is true (or exists).
* == 2 - command line usage errors (including bad keywords)
* == 3 - command failed to perform the test due to a fatal error
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <ctype.h>
#include <unistd.h>
#include <locale.h>
#include <errno.h>
#include <assert.h>
#include <instzones_api.h>
#include <pkglib.h>
#include <install.h>
#include <libinst.h>
#include <libadm.h>
#include <messages.h>
#include "pkgcond.h"
#include "pkgcond_msgs.h"
/* Should be defined by cc -D */
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
/* commands to execute */
/*
* type definition and "types" for testPath()
*/
typedef enum {
TEST_EXISTS = 0x01,
TEST_NOT_EXISTS = 0x02,
TEST_IS_DIRECTORY = 0x04,
TEST_IS_FILE = 0x08,
TEST_NOT_DIRECTORY = 0x10,
TEST_NOT_FILE = 0x20,
TEST_IS_SYMBOLIC_LINK = 0x40,
TEST_NOT_SYMBOLIC_LINK = 0x80,
TEST_GLOBAL_TOKEN_IN_FILE = 0x100
} TEST_TYPES;
/* holds file system info */
struct fsi_t {
char *fsi_mntOptions;
char *fsi_fsType;
char *fsi_mntPoint;
};
/* holds parsed global data */
struct globalData_t {
/* sparse root (are any file systems mounted read-only)? */
/* initial install: PKG_INIT_INSTALL=true */
/* global zone install: SUNW_PKG_INSTALL_ZONENAME=global */
/* non-global zone install: SUNW_PKG_INSTALL_ZONENAME!=global */
/* non-global zone is in a mounted state */
/* sorted list of all mounted file systems */
/* number of mounted file systems in list */
long gd_fileSystemConfigLen;
/* current zone name */
char *gd_zoneName;
/* version of target: PATCH_CLIENT_VERSION */
char *gd_patchClientVersion;
/* SUNW_PKGCOND_GLOBAL_DATA:parentZone:zoneName */
char *gd_parentZoneName;
/* SUNW_PKGCOND_GLOBAL_DATA:parentZone:zoneType */
char *gd_parentZoneType;
/* root path to target: PKG_INSTALL_ROOT */
char *gd_installRoot;
/* SUNW_PKGCOND_GLOBAL_DATA:currentZone:zoneName */
char *gd_currentZoneName;
/* SUNW_PKGCOND_GLOBAL_DATA:currentZone:zoneType */
char *gd_currentZoneType;
/* list of inherited file systems */
char **gd_inheritedFileSystems;
/* path provided on command line */
char *gd_cmdline_path;
};
typedef struct globalData_t GLOBALDATA_T;
/* holds subcommands and their definitions */
struct cmd_t {
char *c_name;
char *c_args;
};
/* Command function prototypes */
/* Utility function Prototypes */
static boolean_t getNegateResults(void);
static int adjustResults(int a_result);
static int getRootPath(char **r_rootPath);
static int getZoneName(char **r_zoneName);
static int resolvePath(char **r_path);
static char *getMountOption(char **p);
static void removeLeadingWhitespace(char **a_str);
static void setVerbose(boolean_t);
int num_args);
/* local static data */
static char *_rootPath = "/";
/* define subcommand data structure */
{ "can_add_driver", " [path]",
{ "can_remove_driver", " [path]",
{ "can_update_driver", " [path]",
{ "is_alternative_root", " [path]",
{ "is_boot_environment", " [path]",
{ "is_diskless_client", " [path]",
{ "is_global_zone", " [path]",
{ "is_mounted_miniroot", " [path]",
{ "is_netinstall_image", " [path]",
{ "is_nonglobal_zone", " [path]",
{ "is_path_writable", " path",
{ "is_running_system", " [path]",
{ "is_sparse_root_nonglobal_zone", " [path]",
{ "is_what", " [path]",
cmd_is_what },
{ "is_whole_root_nonglobal_zone", " [path]",
/* last one must be all NULLs */
};
/*
* *****************************************************************************
* main
* *****************************************************************************
*/
/*
* Name: main
* Description: main processing loop for pkgcond *
* Return: 0 - condition is satisfied (true)
* 1 - condition is not satisfied (false)
* 2 - command line usage errors
* 3 - failure to determine condition
*/
int
{
char **newargv;
char *p;
int cur_cmd;
int i;
int newargc;
/* make standard output non-buffered */
/* set the default text domain for messaging */
(void) textdomain(TEXT_DOMAIN);
/* remember command name */
set_prog_name(argv[0]);
/* tell spmi zones interface how to access package output functions */
/* set verbose mode if appropriate environment variable is set */
if (getenv(ENV_VAR_VERBOSE)) {
/* same as -v */
}
/* set debug mode if appropriate environment variable is set */
if (getenv(ENV_VAR_DEBUG)) {
/* same as -O debug */
/* set sml tracing (sml.c) */
/* set log and echo (interactive) message tracing */
/* enable echoDebug debugging messages */
}
/* generate usage if no options or arguments specified */
if (argc <= 1) {
(void) usage(MSG_NO_ARGUMENTS_SPECIFIED);
return (R_USAGE);
}
/*
* process any arguments that can appear before the subcommand
*/
switch (i) {
/*
* Not a public interface: the -O option allows the behavior
* of the package tools to be modified. Recognized options:
* -> debug
* ---> enable debugging output
*/
case 'O':
/* debug - enable all tracing */
if (strcmp(p, "debug") == 0) {
/* set sml tracing */
/* enable debugging messages */
continue;
}
return (adjustResults(R_USAGE));
}
break;
/*
* Public interface: enable verbose (debug) output.
*/
case 'v': /* verbose mode enabled */
/* set command tracing only */
break;
/*
* Public interface: negate output results.
*/
case 'n':
break;
/*
* unrecognized option
*/
case '?':
default:
return (R_USAGE);
}
}
/*
* done processing options that can preceed subcommand
*/
/* error if no subcommand specified */
(void) usage(MSG_NO_ARGUMENTS_SPECIFIED);
return (R_USAGE);
}
/* parse global data if environment variable set */
return (R_ERROR);
}
return (R_ERROR);
}
/* set path provided on the command line */
/* determine how file systems are layered in this zone */
return (R_ERROR);
}
/* dump global data read in (only if debugging) */
/* search for specified subcommand and execute if found */
int result;
/* make subcommand the first option */
/* process result code and exit */
return (result);
}
}
/* subcommand not found - output error message and exit with error */
return (R_USAGE);
}
/*
* *****************************************************************************
* command implementation functions
* *****************************************************************************
*/
/*
* Name: cmd_is_diskless_client
* Description: determine if target is a diskless client
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* IMPLEMENTATION:
* - must not be initial installation to the install root
* - must not be installation of a zone
* - must not be a whole root non-global zone
* - must not be a non-global zone
* - must not be a mounted mini-root
* - must not be a netinstall image
* - must not be a boot environment
* - The package "SUNWdclnt" must be installed at "/"
* - The root path must not be "/"
* - The directory "$ROOTDIR/../templates" must exist
*/
static int
{
int c;
int r;
int rc;
static char *cmdName = "is_diskless_client";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/*
* a diskless client cannot be any of the following
*/
/* cannot be whole root non-global zone */
/* cannot be nonglobal zone */
if (r != R_SUCCESS) {
}
/* cannot be mounted miniroot */
if (r != R_SUCCESS) {
}
/* cannot be a netinstall image */
if (r != R_SUCCESS) {
}
/* cannot be a boot environment */
if (r != R_SUCCESS) {
}
/* no need to guard against recursion any more */
recursion--;
/* return failure if any of the preceeding are true */
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* SUNWdclnt must be installed */
return (R_FAILURE);
}
/* - $ROOTDIR must not be "/" */
return (R_FAILURE);
}
/* - zone name must be global */
return (R_FAILURE);
}
/*
* create ls command to test:
*/
/* execute command */
/* return error if ls returns something other than "0" */
if (rc != 0) {
return (R_FAILURE);
}
/*
* /usr must be empty on a diskless client:
* create ls command to test:
*/
/* execute command */
/* return error if ls returns "0" */
if (rc == 0) {
rootPath);
return (R_FAILURE);
}
/* there must be a templates directory at ${ROOTPATH}/../templates */
if (r != R_SUCCESS) {
return (R_FAILURE);
}
/* must not be initial installation to the install root */
/* initial install: install root cannot be diskless client */
return (R_FAILURE);
}
/* must not be installation of a zone */
/* initial zone install: no path can be diskless client */
return (R_FAILURE);
}
/* the path is a diskless client */
return (R_SUCCESS);
}
/*
* Name: cmd_is_global_zone
* Description: determine if target is a global zone
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* IMPLEMENTATION:
* - must not be initial installation to the install root
* - must not be installation of a non-global zone
* - must not be a non-global zone
* - must not be a mounted mini-root
* - must not be a netinstall image
* - must not be a diskless client
* - if $ROOTDIR is "/":
* -- if zone name is "GLOBAL", then is a global zone;
* -- else not a global zone.
* - $ROOTDIR/.tmp_proto must not exist
*/
static int
{
int c;
int r;
static char *cmdName = "is_global_zone";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/*
* a global zone cannot be any of the following
*/
/* cannot be a non-global zone */
/* cannot be a mounted miniroot */
if (r != R_SUCCESS) {
}
/* cannot be a netinstall image */
if (r != R_SUCCESS) {
}
/* cannot be a diskless client */
if (r != R_SUCCESS) {
}
/* no need to guard against recursion any more */
recursion--;
/* return failure if any of the preceeding are true */
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* must not be initial installation to the install root */
/* initial install: install root cannot be global zone */
return (R_FAILURE);
}
/* must not be installation of a non-global zone */
/* initial nonglobal zone install: no path can be global zone */
return (R_FAILURE);
}
/* handle if global zone installation to the install root */
/* the path is a global zone */
rootPath);
return (R_SUCCESS);
}
/* true if current root is "/" and zone name is GLOBAL_ZONENAME */
/* the path is a global zone */
rootPath);
return (R_SUCCESS);
}
/* inside a non-global zone */
return (R_FAILURE);
}
/*
* current root is not "/" - see if target looks like a global zone
*
* - rootpath is not "/"
* - and $ROOTDIR/.tmp_proto does not exist
*/
if (r != R_SUCCESS) {
return (R_FAILURE);
}
/* .tmp_proto must not exist */
r = testPath(TEST_NOT_EXISTS,
if (r != R_SUCCESS) {
rootPath, "/.tmp_proto");
return (R_FAILURE);
}
/* /var must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/var");
return (R_FAILURE);
}
/* the path is a global zone */
return (R_SUCCESS);
}
/*
* Name: cmd_is_netinstall_image
* Description: determine if target is a net install image
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* IMPLEMENTATION:
* - must not be initial installation to the install root
* - must not be installation of a zone
* - must not be a global zone
* - must not be a mounted mini-root
* - zone name must be "global"
* - $ROOTDIR/.tmp_proto must exist and must be a directory
*/
static int
{
int c;
int r;
static char *cmdName = "is_netinstall_image";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/* a netinstall image cannot be a global zone */
/* no need to guard against recursion any more */
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* current zone name must be "global" */
return (R_FAILURE);
}
/* cannot be a mounted_miniroot */
rootPath);
return (R_FAILURE);
}
/* $ROOTDIR/.tmp_proto exists */
if (r != R_SUCCESS) {
rootPath, "/.tmp_proto");
return (R_FAILURE);
}
if (r != R_SUCCESS) {
rootPath, "/var");
return (R_FAILURE);
}
if (r != R_SUCCESS) {
return (R_FAILURE);
}
if (r != R_SUCCESS) {
return (R_FAILURE);
}
/* must not be initial installation to the install root */
/* initial install: install root cannot be netinstall image */
return (R_FAILURE);
}
/* must not be installation of a zone */
/* initial zone install: no path can be netinstall image */
return (R_FAILURE);
}
/* target is a netinstall image */
return (R_SUCCESS);
}
/*
* Name: cmd_is_mounted_miniroot
* Description: determine if target is a mounted miniroot image
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* IMPLEMENTATION:
* - must not be initial installation to the install root
* - must not be installation of a zone
* - zone name must be "global"
*/
static int
{
int c;
int r;
static char *cmdName = "is_mounted_miniroot";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
recursion--;
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* current zone name must be "global" */
return (R_FAILURE);
}
if (r != R_SUCCESS) {
return (R_FAILURE);
}
if (r != R_SUCCESS) {
return (R_FAILURE);
}
/* must not be initial installation to the install root */
/* initial install: install root cannot be mounted miniroot */
return (R_FAILURE);
}
/* must not be installation of a zone */
/* initial zone install: no path can be mounted miniroot */
return (R_FAILURE);
}
/* target is a mounted miniroot */
return (R_SUCCESS);
}
/*
* Name: cmd_is_nonglobal_zone
* Description: determine if target is a global zone
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* - must not be initial installation to the install root
* - must not be installation of a global zone
* - success if installation of a non-global zone
*/
static int
{
int c;
int r;
static char *cmdName = "is_nonglobal_zone";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
recursion--;
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* handle if non-global zone installation to the install root */
return (R_SUCCESS);
}
/* must not be initial installation to the install root */
/* initial install: install root cannot be non-global zone */
return (R_FAILURE);
}
/* must not be installation of a global zone */
/* initial global zone install: no path can be nonglobal zone */
return (R_FAILURE);
}
/*
* *********************************************************************
* if root directory is "/" then the only thing that needs to be done is
* to test the zone name directly - if the zone name is "global" then
* the target is not a non-global zone; otherwise if the zone name is
* not "global" then the target IS a non-global zone.
* *********************************************************************
*/
/* target is current running root */
/* in the global zone */
return (R_FAILURE);
}
/* in a non-global zone */
return (R_SUCCESS);
}
/*
* exists in a non-global zone after s10u4 but we can't check that
* since it is undeterministic for all releases so we only check
* for the global zone here.
*/
if (r == R_SUCCESS) {
return (R_FAILURE);
}
}
/*
* *********************************************************************
* If the root directory is "/" then you can use only the zone
* name to determine if the zone is non-global or not since the
* package is being installed or removed to the current "zone".
*
* Since the root directory being tested is not "/" then you have to
* look into the target to try and infer zone type using means other
* than the zone name only.
* *********************************************************************
*/
/* reject if any items found that cannot be in a non-global zone */
/* .tmp_proto must not exist */
if (r != R_SUCCESS) {
/* $R/.tmp_proto cannot exist in a non-global zone */
rootPath, "/.tmp_proto");
return (R_FAILURE);
}
/* /var must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/var");
return (R_FAILURE);
}
r = testPath(TEST_NOT_EXISTS,
if (r != R_SUCCESS) {
return (R_FAILURE);
}
/*
* *********************************************************************
* no items exist in $ROOTDIR that identify something other than
* a non-global zone.
*
* if in global zone no more tests possible: is a non-global zone
* *********************************************************************
*/
/* in the global zone */
rootPath);
return (R_SUCCESS);
}
/*
* *********************************************************************
* In non-global zone: interrogate zone name and type.
*
* The parent zone is the zone that the "pkgadd" or "pkgrm" command was
* run in. The child zone is the zone that the "pkginstall" or
* "pkgremove" command was run in.
* *********************************************************************
*/
/*
* If parent zone name and current zone name defined, and
* both zone names are the same, since pkgcond is running
* inside of a non-global zone, this is how the scratch
* zone is implemented, so target is a non-global zone
*/
a_gdt->gd_currentZoneName) == 0)) {
/* parent and current zone name identical: non-gz */
return (R_SUCCESS);
}
/*
* In non-global zone if inherited FS's exits
* or zone specific read only FS's exist
* or it is in a mounted state.
*/
return (R_SUCCESS);
}
/*
* the parent and current zone name are not the same;
* interrogate the zone types: the parent must be global
* and the current must be non-global, which would be set
* when a package command is run in the global zone that in
* turn runs a package command within the non-global zone.
*/
/* if defined, parent zone type must be "global" */
rootPath, "nonglobal");
return (R_FAILURE);
}
/* if defined, current zone type must be "nonglobal" */
return (R_FAILURE);
}
/*
* *********************************************************************
* no other tests possible: target is a non-global zone
* *********************************************************************
*/
return (R_SUCCESS);
}
/*
* Name: cmd_is_running_system
* Description: determine if target is a global zone
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* IMPLEMENTATION:
* - must not be initial installation to the install root
* - must not be installation of a zone
* - must not be a diskless client
* - $ROOTDIR must be "/"
* - zone name must be "global"
*/
static int
{
int c;
int r;
static char *cmdName = "is_running_system";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/* a running system cannot be a diskless client */
/* no need to guard against recursion any more */
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* if root path is "/" then check zone name */
return (R_FAILURE);
}
/* zone name must be global */
return (R_FAILURE);
}
/* must not be initial installation to the install root */
/* initial install: install root cannot be the running system */
return (R_FAILURE);
}
/* must not be installation of a zone */
/* initial zone install: no path can be running system */
return (R_FAILURE);
}
/* target is a running system */
return (R_SUCCESS);
}
/*
* Name: cmd_can_add_driver
* Description: determine if target is a global zone
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* Implementation:
* A driver can be added to the system if the components of a Solaris
* instance capable of loading drivers is present and it is not the
* currently running system.
*/
static int
{
int c;
int r;
static char *cmdName = "can_add_driver";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/* see if this is the current running system */
/* cannot be a diskless client */
if (r != R_SUCCESS) {
}
/* no need to guard against recursion any more */
recursion--;
switch (r) {
case R_SUCCESS:
/* is a running system */
return (R_FAILURE);
case R_FAILURE:
/* not a running syste */
break;
case R_USAGE:
case R_ERROR:
default:
/* cannot determine if is a running system */
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* /etc must exist and must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/etc");
return (R_FAILURE);
}
/* /platform must exist and must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/platform");
return (R_FAILURE);
}
/* /kernel must exist and must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/kernel");
return (R_FAILURE);
}
/* can add a driver */
return (R_SUCCESS);
}
/*
* Name: cmd_can_update_driver
* Description: determine if target is a global zone
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* Implementation:
* A driver can be added to the system if the components of a Solaris
* instance capable of loading drivers is present and it is not the
* currently running system.
*/
static int
{
int c;
int r;
static char *cmdName = "can_update_driver";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/* see if this is the current running system */
/* cannot be a diskless client */
if (r != R_SUCCESS) {
}
/* no need to guard against recursion any more */
recursion--;
switch (r) {
case R_SUCCESS:
/* is a running system */
return (R_FAILURE);
case R_FAILURE:
/* not a running syste */
break;
case R_USAGE:
case R_ERROR:
default:
/* cannot determine if is a running system */
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* /etc must exist and must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/etc");
return (R_FAILURE);
}
/* /platform must exist and must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/platform");
return (R_FAILURE);
}
/* /kernel must exist and must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/kernel");
return (R_FAILURE);
}
/* can update driver */
return (R_SUCCESS);
}
/*
* Name: cmd_can_remove_driver
* Description: determine if target is a global zone
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* Implementation:
* A driver can be added to the system if the components of a Solaris
* instance capable of loading drivers is present and it is not the
* currently running system.
*/
static int
{
int c;
int r;
static char *cmdName = "can_remove_driver";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/* see if this is the current running system */
/* cannot be a diskless client */
if (r != R_SUCCESS) {
}
/* no need to guard against recursion any more */
recursion--;
switch (r) {
case R_SUCCESS:
/* is a running system */
return (R_FAILURE);
case R_FAILURE:
/* not a running syste */
break;
case R_USAGE:
case R_ERROR:
default:
/* cannot determine if is a running system */
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* /etc must exist and must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/etc");
return (R_FAILURE);
}
/* /platform must exist and must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/platform");
return (R_FAILURE);
}
/* /kernel must exist and must not be a symbolic link */
if (r != R_SUCCESS) {
rootPath, "/kernel");
return (R_FAILURE);
}
/* can remove driver */
return (R_SUCCESS);
}
/*
* Name: cmd_is_path_writable
* Description: determine if target path is writable (not inherited)
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* IMPLEMENTATION:
* - path must be found in the file systems configured
* - file system type must not be "inherited"
* - mount options must not include "read only"
*/
static int
{
int c;
int n;
int nn;
int r;
long listSize;
long rootPathLen;
static char *cmdName = "is_path_writable";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
recursion--;
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc != 1) {
return (R_USAGE);
}
return (R_ERROR);
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* search file system conf for this path */
if (rootPathLen < mplen) {
/* root path is longer than target, ignore */
continue;
}
/* remember last partial match */
nn = n;
}
}
/*
* need to determine if the mount point is writeable:
* If parent mount point is "inherited" then it is not writeable
*/
return (R_FAILURE);
}
/* see if the file system is mounted with the "read only" option */
if (r == R_SUCCESS) {
return (R_FAILURE);
}
/* target path is writable */
return (R_SUCCESS);
}
/*
* Name: cmd_is_alternative_root
* Description: determine if target is an alternative root
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* Implementation:
* - success if an initial installation to the install root
* (an initial install to $PKG_INSTALL_ROOT means that $PKG_INSTALL_ROOT
* points to an alternative root that is under construction)
* - must not be installation of a zone
* - must not be a boot environment
* - must not be a diskless client
* - must not be a mounted miniroot
* - must not be a netinstall image
* - must not be a nonglobal zone
* - must not be a running system
* - $ROOTDIR must not be "/"
*/
static int
{
int c;
int r;
static char *cmdName = "is_alternative_root";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/*
* an alternative root cannot be any of the following
*/
/* cannot be a boot_environment */
/* cannot be a diskless_client */
if (r != R_SUCCESS) {
}
/* cannot be a mounted_miniroot */
if (r != R_SUCCESS) {
}
/* cannot be a netinstall_image */
if (r != R_SUCCESS) {
}
/* cannot be a nonglobal_zone */
if (r != R_SUCCESS) {
}
/* cannot be a running_system */
if (r != R_SUCCESS) {
}
/* no need to guard against recursion any more */
recursion--;
/* return failure if any of the preceeding are true */
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* return success if initial installation */
return (R_SUCCESS);
}
/* root path must not be "/" */
return (R_FAILURE);
}
/* /var must exist */
r = testPath(TEST_EXISTS,
if (r != R_SUCCESS) {
rootPath, "/var");
return (R_FAILURE);
}
/* must not be installation of a zone */
/* initial zone install: no path can be alternative root */
return (R_FAILURE);
}
/* target is an alternative root */
return (R_SUCCESS);
}
/*
* Name: cmd_is_boot_environment
* Description: determine if target is an alternative, inactive boot environment
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* IMPLEMENTATION:
* - must not be initial installation to the install root
* - must not be installation of a zone
* - must not be a diskless client
* - must not be a netinstall image
* - must not be a mounted miniroot
* - $ROOTDIR must not be "/"
*/
static int
{
int c;
int r;
static char *cmdName = "is_boot_environment";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/*
* a boot environment cannot be any of the following
*/
/* cannot be a diskless client */
/* cannot be a netinstall_image */
if (r != R_SUCCESS) {
}
/* cannot be a mounted_miniroot */
if (r != R_SUCCESS) {
}
/* no need to guard against recursion any more */
recursion--;
/* return failure if any of the preceeding are true */
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/* root path must not be "/" */
return (R_FAILURE);
}
/* zone name must be global */
return (R_FAILURE);
}
if (r != R_SUCCESS) {
return (R_FAILURE);
}
if (r != R_SUCCESS) {
return (R_FAILURE);
}
/* must not be initial installation */
return (R_FAILURE);
}
/* must not be installation of a zone */
/* initial zone install: no path can be boot environment */
return (R_FAILURE);
}
/* target is a boot environment */
return (R_SUCCESS);
}
/*
* Name: cmd_is_sparse_root_ng_zone
* Description: determine if target is a sparse non-global zone
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* IMPLEMENATION:
* - must be a non-global zone
* - read-only lofs file systems must be present
*/
static int
{
int c;
int r;
static char *cmdName = "is_sparse_root_nonglobal_zone";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/* see if this is a non-global zone */
/* no need to guard against recursion any more */
recursion--;
switch (r) {
case R_SUCCESS:
/* is a non-global zone */
break;
case R_FAILURE:
/* not a non-global zone */
return (R_FAILURE);
case R_USAGE:
case R_ERROR:
default:
/* cannot determine if non-global zone */
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/*
* in a non-global zone:
* if any file systems are inherited, or if /usr is read only,
* then the target is a sparse root non-global zone.
*/
/* no inherited file systems */
return (R_SUCCESS);
}
/* target is not a sparse root non-global zone */
return (R_FAILURE);
}
/*
* Name: cmd_is_what
* Description: determine what the target is
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
*/
static int
{
int c;
int cur_cmd;
int r;
static char *cmdName = "is_what";
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/*
* construct the command line for all of the packages
*/
argc = 0;
/* start of command debugging information */
/* search for specified subcommand and execute if found */
int result;
/* do not recursively call this function */
continue;
}
/* process result code and exit */
}
return (R_SUCCESS);
}
/*
* Name: cmd_is_whole_root_ng_zone
* Description: determine if target is a global zone
* Scope: public
* Arguments: argc,argv:
* - optional path to target to test
* Returns: int
* == 0 - success
* != 0 - failure
* IMPLEMENTATION:
* - must be a non-global zone
* - no inherited file systems may be present
* - no read-only lofs file systems may be present
*/
static int
{
int c;
int r;
static char *cmdName = "is_whole_root_nonglobal_zone";
static int recursion = 0;
/* process any command line options */
switch (c) {
case '\0': /* prevent end-of-loop not reached warning */
break;
case '?':
default:
return (R_USAGE);
}
}
/* prevent recursion */
/* see if this is a non-global zone */
/* no need to guard against recursion any more */
recursion--;
switch (r) {
case R_SUCCESS:
/* is a non-global zone */
break;
case R_FAILURE:
/* not a non-global zone */
return (R_FAILURE);
case R_USAGE:
case R_ERROR:
default:
/* cannot determine if non-global zone */
return (r);
}
}
/* error if more than one argument */
if (argc > 1) {
return (R_USAGE);
}
/* process root path if first argument present */
if (argc == 1) {
return (R_ERROR);
}
}
/* get current root path */
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
/* start of command debugging information */
/*
* in a non-global zone:
* if no file systems are inherited, and if /usr is not
* read only, then the target is a whole root non-global zone.
*/
/* no inherited file systems */
return (R_SUCCESS);
}
/* target is not a whole-root non-global zone */
return (R_FAILURE);
}
/*
* *****************************************************************************
* utility support functions
* *****************************************************************************
*/
/*
* Name: getMountOption
* Description: return next mount option in a string
* Arguments: p - pointer to string containing mount options
* Output: none
* Returns: char * - pointer to next option in string "p"
* Side Effects: advances input "p" and inserts \0 in place of the
* option separator found.
*/
static char *
getMountOption(char **p)
{
char *cp = *p;
char *retstr;
/* advance past all white space */
cp++;
/* remember start of next option */
/* advance to end of string or option separator */
cp++;
/* replace separator with '\0' if not at end of string */
if (*cp) {
*cp = '\0';
cp++;
}
/* reset caller's pointer and return pointer to option */
*p = cp;
return (retstr);
}
/*
* Name: mountOptionPresent
* Description: determine if specified mount option is present in list
* of mount point options
* Arguments: a_mntOptions - pointer to string containing list of mount
* point options to search
* a_opt - pointer to string containing option to search for
* Output: none
* Returns: R_SUCCESS - option is present in list of mount point options
* R_FAILURE - options is not present
* R_ERROR - unable to determine if option is present or not
*/
static int
{
char tmpopts[MNT_LINE_MAX];
/* return false if no mount options present */
return (R_FAILURE);
}
/* return not present if no list of options to search */
if (a_mntOptions == NULL) {
return (R_FAILURE);
}
/* return not present if list of options to search is empty */
if (*a_mntOptions == '\0') {
return (R_FAILURE);
}
/* make local copy of option list to search */
/* scan each option looking for the specified option */
f = getMountOption(&opts);
for (; *f; f = getMountOption(&opts)) {
/* return success if option matches target */
return (R_SUCCESS);
}
}
/* option not found */
return (R_FAILURE);
}
/*
* Name: sortedInsert
* Description: perform an alphabetical sorted insert into a list
* Arguments: r_list - pointer to list to insert next entry into
* a_listSize - pointer to current list size
* a_mntPoint - mount point to insert (is sort key)
* a_fsType - file system type for mount point
* a_mntOptions - file syste mount options for mount point
* Output: None
* Returns: None
*/
static void
char *a_fsType, char *a_mntOptions)
{
int listSize;
int n;
/* entry assertions */
/* entry debugging info */
/* localize references to the list and list size */
listSize = *a_listSize;
/*
* if list empty insert this entry as the first one in the list
*/
if (listSize == 0) {
/* allocate new entry for list */
listSize++;
/* first entry is data passed to this function */
/* second entry is all NULL - end of entry marker */
/* restore list and list size references to caller */
*a_listSize = listSize;
return;
}
/*
* list not empty - scan looking for largest match
*/
for (n = 0; n < listSize; n++) {
int c;
/* compare target with current list entry */
if (c == 0) {
char *me;
long len;
/* entry already in list -- merge entries */
/* merge two mount options lists into one */
/* free old list, replace with merged one */
list[n].fsi_mntOptions);
continue;
} else if (c < 0) {
/* entry before this one - skip */
continue;
}
/*
* entry after this one - insert new entry
*/
/* allocate one more entry and make space for new entry */
listSize++;
/* insert this entry into list */
/* restore list and list size references to caller */
*a_listSize = listSize;
return;
}
/*
* all entries are before this one - append to end of list
*/
/* allocate new entry at end of list */
listSize++;
/* append this entry to the end of the list */
/* restore list and list size references to caller */
*a_listSize = listSize;
}
/*
* Name: calculateFileSystemConfig
* Description: generate sorted list of all mounted file systems
* Arguments: a_gdt - global data structure to place sorted entries into
* Output: None
* Returns: R_SUCCESS - successfully generated mounted file systems list
* R_FAILURE - options is not present
* R_ERROR - unable to determine if option is present or not
*/
static int
{
long listSize;
/* entry assetions */
/* entry debugging info */
/* allocate a list that has one termination entry */
listSize = 0;
/* insert entries for all inherited file systems */
if (a_gdt->gd_inheritedFileSystems) {
int n;
/* debugging info */
/* insert all inherited file systems */
for (n = 0; ifs[n]; n++) {
}
}
/* open the mount table for reading */
return (R_ERROR);
}
/* debugging info */
/* go through all the specials looking for the device */
}
/*
* Set flag if we are in a non-global zone and it is in
* the mounted state.
*/
}
if (!readOnlyMountFound) {
}
}
/* close mount table file */
/* store list pointers in global data structure */
return (R_SUCCESS);
}
/*
* Name: checkForReadOnlyMount
* Description: given a mount point, type and options, determine if the
* mounted file system is part of a "sparse root" configuration
* by checking if the known Zone directories a ro LOFS mounted.
* Arguments: a_gdt - global data structure to place sorted entries into
* a_mntPoint - pointer to string representing mount point
* a_fsType - pointer to string representing file system type
* a_mntOptions - pointer to string representing the options
* used to mount the file system
* Returns: B_TRUE - if sparse root mount is found
* B_FLASE - if no sparse root mount's are found
* Side Effects: set:
* a_gdt->gd_srFsMountedRO = B_TRUE
* if the mounted file system is part of a 'sparse root' config
*/
static boolean_t
char *a_fsType, char *a_mntOptions)
{
/* entry assertions */
int i;
char mntPoint[MAXPATHLEN];
/* return if no read-only mount option */
return (B_FALSE);
}
/* return if file system is not read-only mounted */
return (B_FALSE);
}
/* file system is a read-only lofs mounted. */
/* Check read-only lofs mount's appended to the command line path */
zDirs[i]);
return (B_TRUE);
}
}
}
/* Check read-only lofs mount's in the mounted state */
} else if (a_gdt->inMountedState) {
sizeof (aZDirs[i])) == 0) {
a_fsType);
return (B_TRUE);
}
}
/* Check read-only lofs mount's for live system */
} else {
sizeof (zDirs[i])) == 0) {
a_fsType);
return (B_TRUE);
}
}
}
return (B_FALSE);
}
/*
* Name: adjustResults
* Description: adjust output result code before existing
* Arguments: a_result - result code to adjust
* Returns: int - adjusted result code
*/
static int
adjustResults(int a_result)
{
int realResult;
/* adjust code as appropriate */
switch (a_result) {
case R_SUCCESS: /* condition satisfied */
break;
case R_FAILURE: /* condition not satisfied */
break;
case R_USAGE: /* usage errors */
realResult = 2;
break;
case R_ERROR: /* condition could not be determined */
default:
realResult = 3;
break;
}
/* debugging output */
/* return results */
return (realResult);
}
/*
* Name: setCmdLinePath
* Description: set global command line path
* Arguments: path - path to set from the command line
* args - command line args
* num_args - number of command line args
* Returns: R_SUCCESS - root path successfully set
* R_FAILURE - root path could not be set
* R_ERROR - fatal error attempting to set root path
*/
static void
{
return;
}
/*
* If a path "pkgcond is_global_zone [path]" is provided on the
* command line it must be the last argument.
*/
/* make sure the target is a directory */
} else {
}
}
}
}
/*
* Name: setRootPath
* Description: set global root path returned by getRootPath
* Arguments: a_path - root path to set
* a_mustExist - B_TRUE if path must exist (else error)
* - B_FALSE if path may not exist
* Returns: R_SUCCESS - root path successfully set
* R_FAILURE - root path could not be set
* R_ERROR - fatal error attempting to set root path
*/
static int
{
/* if no data then issue warning and return success */
return (R_SUCCESS);
}
/* path present - resolve to absolute path */
if (a_mustExist == B_TRUE) {
/* must exist ... error */
return (R_ERROR);
} else {
/* may not exist - use path as specified */
}
}
/* debugging output */
/* validate path existence if it must exist */
if (a_mustExist == B_TRUE) {
/* get node status */
return (R_ERROR);
}
/* make sure the target is a directory */
return (R_ERROR);
}
}
/* target exists and is a directory - set */
/* store copy of resolved root path */
/* success! */
return (R_SUCCESS);
}
/*
* Name: testPath
* Description: determine if a path meets the specified conditions
* Arguments: a_tt - conditions to test path against
* a_format - format to use to generate path
* arguments following a_format - as needed for a_format
* Returns: R_SUCCESS - the path meets all of the specified conditions
* R_FAILURE - the path does not meet all of the conditions
* R_ERROR - error attempting to test path
*/
/*PRINTFLIKE2*/
static int
{
char *mbPath; /* copy for the path to be returned */
char bfr[1];
int r;
int fd;
/* entry assertions */
/* determine size of the message in bytes */
/* allocate storage to hold the message */
/* generate the results of the printf conversion */
/*
* When a path given to open(2) contains symbolic links, the
* open system call first resolves all symbolic links and then
* opens that final "resolved" path. As a result, it is not
* possible to check the result of an fstat(2) against the
* file descriptor returned by open(2) for S_IFLNK (a symbolic
* link) since all symbolic links are resolved before the
* target is opened.
*
* When testing the target as being (or not being) a symbolic
* link, first use lstat(2) against the target to determine
* whether or not the specified target itself is (or is not) a
* symbolic link.
*/
/*
* to determine the status of the target itself rather
* than what the target might finally address.
*/
return (R_FAILURE);
}
/* Is the target required to be a symbolic link? */
if (a_tt & TEST_IS_SYMBOLIC_LINK) {
/* target must be a symbolic link */
/* failure: target is not a symbolic link */
return (R_FAILURE);
}
/* success: target is a symbolic link */
}
/* Is the target required to not be a symbolic link? */
if (a_tt & TEST_NOT_SYMBOLIC_LINK) {
/* target must not be a symbolic link */
/* failure: target is a symbolic link */
return (R_FAILURE);
}
/* success: target is not a symbolic link */
}
/*
* no need to open the target: return success.
*/
if (!(a_tt &
return (R_SUCCESS);
}
}
/* resolve path and remove any whitespace */
r = resolvePath(&mbPath);
if (r != R_SUCCESS) {
if (a_tt & TEST_NOT_EXISTS) {
return (R_SUCCESS);
}
return (r);
}
/* open the file - this is the basic existence test */
/* existence test failed if file cannot be opened */
if (fd < 0) {
/*
* target could not be opened - if testing for non-existence,
* return success, otherwise return failure
*/
if (a_tt & TEST_NOT_EXISTS) {
return (R_SUCCESS);
}
return (R_FAILURE);
}
/*
* target successfully opened - if testing for non-existence,
* return failure, otherwise continue with specified tests
*/
if (a_tt & TEST_NOT_EXISTS) {
/* testing for non-existence: return failure */
return (R_FAILURE);
}
/* get the file status */
if (r != 0) {
return (R_FAILURE);
}
/* required to be a directory? */
if (a_tt & TEST_IS_DIRECTORY) {
/* is not a directory */
return (R_FAILURE);
}
/* a directory */
}
/* required to not be a directory? */
if (a_tt & TEST_NOT_DIRECTORY) {
/* is a directory */
return (R_FAILURE);
}
/* not a directory */
}
/* required to be a file? */
if (a_tt & TEST_IS_FILE) {
/* is not a regular file */
return (R_FAILURE);
}
/* a regular file */
}
/* required to not be a file? */
if (a_tt & TEST_NOT_FILE) {
/* is a regular file */
return (R_FAILURE);
}
/* not a regular file */
}
/*
* Find token (global) in file pointed to by mbPath.
* token is only compared to first word in mbPath.
*/
if (a_tt & TEST_GLOBAL_TOKEN_IN_FILE) {
/* is not a regular file */
return (R_FAILURE);
}
/* If global exists then we're not in a non-global zone */
return (R_FAILURE);
}
}
/* success! */
/* free up temp storage used to hold path to test */
return (R_SUCCESS);
}
/*
* Name: findToken
* Description: Find first token in file.
* Arguments:
* path - file to search for token
* token - string to search for
* Returns:
* R_SUCCESS - the token exists
* R_FAILURE - the token does not exist
* R_ERROR - fatal error attempting to find token
*/
static int
{
char *cp;
char line[MAXPATHLEN];
return (R_ERROR);
}
return (R_ERROR);
}
/* skip comments */
if (*cp == '#') {
continue;
}
return (R_SUCCESS);
}
}
return (R_FAILURE);
}
/*
* Name: resolvePath
* Description: fully resolve a path to an absolute real path
* Arguments: r_path - pointer to pointer to malloc()ed storage containing
* the path to resolve - this path may be reallocated
* as necessary to hold the fully resolved path
* Output: r_path - is realloc()ed as necessary
* Returns: R_SUCCESS - the path is fully resolved
* R_FAILURE - the path could not be resolved
* R_ERROR - fatal error attempting to resolve path
*/
static int
resolvePath(char **r_path)
{
int i;
/* entry assertions */
/* return error if the path is completely empty */
if (*r_path == '\0') {
return (R_FAILURE);
}
/* remove all leading whitespace */
/*
* convert to real path: an absolute pathname that names the same file,
* whose resolution does not involve ".", "..", or symbolic links.
*/
}
/*
* convert the multi-byte version of the path to a
* wide-character rendering, for doing our figuring.
*/
return (R_FAILURE);
}
/*LINTED*/
return (R_FAILURE);
}
/*
* remove duplicate slashes first ("//../" -> "/")
*/
if (wcPath[i] == '/') {
i++;
while (wcPath[i] == '/') {
i++;
}
i--;
}
}
*wptr = '\0';
/*
* now convert back to the multi-byte format.
*/
/*LINTED*/
return (R_FAILURE);
}
/* at this point have a path */
/* free up temporary storage */
return (R_SUCCESS);
}
/*
* Name: removeLeadingWhitespace
* Synopsis: Remove leading whitespace from string
* Description: Remove all leading whitespace characters from a string
* Arguments: a_str - [RO, *RW] - (char **)
* Pointer to handle to string (in allocated storage) to
* remove all leading whitespace from
* Returns: void
* The input string is modified as follows:
* == NULL:
* - input string was NULL
* - input string is all whitespace
* != NULL:
* - copy of input string with leading
* whitespace removed
* CAUTION: The input string must be allocated space (via malloc() or
* strdup()) - it must not be a static or inline character string
* NOTE: The input string a_str will be freed with 'free'
* if it is all whitespace, or if it contains any leading
* whitespace characters
* NOTE: Any string returned is placed in new storage for the
* calling method. The caller must use 'free' to dispose
* of the storage once the string is no longer needed.
* Errors: If the string cannot be created, the process exits
*/
static void
removeLeadingWhitespace(char **a_str)
{
char *o_str;
/* entry assertions */
/* if string is null, just return */
return;
}
/* if string is empty, deallocate and return NULL */
if (*o_str == '\0') {
/* free string */
return;
}
/* if first character is not a space, just return */
return;
}
/* advance past all space characters */
o_str++;
}
/* if string was all space characters, deallocate and return NULL */
if (*o_str == '\0') {
/* free string */
return;
}
}
/*
* Name: getZoneName
* Description: get the name of the zone this process is running in
* Arguments: r_zoneName - pointer to pointer to receive zone name
* Output: r_zoneName - a pointer to malloc()ed storage containing
* the zone name this process is running in is stored
* in the location pointed to by r_zoneName
* Returns: R_SUCCESS - the zone name is successfully returned
* R_FAILURE - the zone name is not successfully returned
* R_ERROR - error attempting to get the zone name
*/
static int
getZoneName(char **r_zoneName)
{
/* if zone name not already present, retrieve and cache name */
if (zoneName[0] == '\0') {
sizeof (zoneName)) < 0) {
return (R_ERROR);
}
}
/* return cached zone name */
*r_zoneName = zoneName;
return (R_SUCCESS);
}
/*
* Name: getRootPath
* Description: get the root path being tested by this process
* Arguments: r_rootPath - pointer to pointer to receive root path
* Output: r_rootPath - a pointer to malloc()ed storage containing
* the root path name this process is testing
* Returns: R_SUCCESS - the root path is successfully returned
* R_FAILURE - the root path is not successfully returned
* R_ERROR - error attempting to get the root path
*/
static int
getRootPath(char **r_rootPath)
{
*r_rootPath = _rootPath;
return (R_SUCCESS);
}
/*
* Name: setVerbose
* Description: Turns on verbose output
* Scope: public
* Arguments: verbose = B_TRUE indicates verbose mode
* Returns: none
*/
static void
{
/* set log verbose messages */
/* set interactive messages */
}
/*
* Name: negate_results
* Description: control negation of results
* Scope: public
* Arguments: setting
* == B_TRUE indicates negated results mode
* == B_FALSE indicates non-negated results mode
* Returns: none
*/
static void
{
}
/*
* Name: getNegateResults
* Description: Returns whether or not to results are negated
* Scope: public
* Arguments: none
* Returns: B_TRUE - results are negated
* B_FALSE - results are not negated
*/
static boolean_t
getNegateResults(void)
{
return (_negateResults);
}
/*
* Name: usage
* Description: output usage string
* Arguments: a_format - format to use to generate message
* arguments following a_format - as needed for a_format
* Output: Outputs the usage string to stderr.
* Returns: R_ERROR
*/
static int
{
int cur_cmd;
char *message;
char bfr[1];
char *p = get_prog_name();
/* entry assertions */
/* determine size of the message in bytes */
/* LINTED warning: variable format specifier to vsnprintf(); */
/* allocate storage to hold the message */
/* generate the results of the printf conversion */
/* LINTED warning: variable format specifier to vsnprintf(); */
/* generate list of all defined conditions */
sizeof (cmdlst));
}
}
/* output usage with conditions */
return (R_ERROR);
}
/*
* Name: parseGlobalData
* Description: parse environment global data and store in global data structure
* Arguments: a_envVar - pointer to string representing the name of the
* environment variable to get and parse
* r_gdt - pointer to pointer to global data structure to fill in
* using the parsed data from a_envVar
* Output: none
* Returns: R_SUCCESS - the global data is successfully parsed
* R_FAILURE - problem parsing global data
* R_ERROR - fatal error attempting to parse global data
*/
static int
{
int r;
int n;
char *a;
/*
* allocate space for global data structure if needed
*/
}
/*
* get initial installation indication:
* If the initial install variable is set to "true", then an initial
* installation of Solaris is underway. When this condition is true:
* - if the path being checked is the package install root, then
* the path is considered to be an 'alternative root' which is
* currently being installed.
* - if the path being checked is not the package install root, then
* the path needs to be further analyzed to determine what it may
* be referring to.
*/
}
/* get current zone name */
if (r != R_SUCCESS) {
}
/*
* get zone installation status:
* - If the package install zone name is not set, then an installation
* of a global zone, or of a non-global zone, is not underway.
* - If the package install zone name is set to "global", then an
* installation of a global zone is underway. In this case, no path
* can be a netinstall image, diskless client, mounted miniroot,
* non-global zone, the current running system, alternative root,
* or alternative boot environment.
* - If the package install zone name is set to a value other than
* "global", then an installation of a non-global zone with that name
* is underway. In this case, no path can be a netinstall image,
* diskless client, mounted miniroot, global zone, the current
* running system, alternative root, or alternative boot environment.
*/
a = getenv(ENV_VAR_PKGZONENAME);
if ((a == NULL) || (*a == '\0')) {
/* not installing a zone */
} else if (strcmp(a, GLOBAL_ZONENAME) == 0) {
/* installing a global zone */
(*r_gdt)->gd_zoneName = a;
} else {
/* installing a non-global zone by that name */
(*r_gdt)->gd_zoneName = a;
}
/*
* get package install root. If it doesn't exist check for
* patch install root (ROOTDIR)
*/
a = getenv(ENV_VAR_PKGROOT);
if ((a != NULL) && (*a != '\0')) {
(*r_gdt)->gd_installRoot = a;
} else {
a = getenv(ENV_VAR_PATCHROOT);
if ((a != NULL) && (*a != '\0')) {
(*r_gdt)->gd_installRoot = a;
} else {
}
}
/*
* get patch client version: always set if $ROOTDIR != / and
* the $ROOTDIR/var/sadm/softinfo/INST_RELEASE file exists.
*/
/* get the global data environment variable */
/* if no data then issue warning and return success */
return (R_SUCCESS);
}
/* data present - parse into SML structure */
r = smlConvertStringToTag(&tag, a);
if (r != R_SUCCESS) {
return (R_FAILURE);
}
/* fill in global data structure */
/* find the environment condition information structure */
if (ntag == SML_TAG__NULL) {
return (R_FAILURE);
}
/*
* data found - extract what we know about
*/
/* parent zone name */
(*r_gdt)->gd_parentZoneName = a;
/* parent zone type */
(*r_gdt)->gd_parentZoneType = a;
/* current zone name */
(*r_gdt)->gd_currentZoneName = a;
/* current zone type */
(*r_gdt)->gd_currentZoneType = a;
/* extract any inherited file systems */
for (n = 0; ; n++) {
char **ifs;
if (a == NULL) {
if (n > 0) {
/* LINTED warning: variable may be used */
}
break;
}
if (n == 0) {
ifs[n] = a;
} else {
ifs[n] = a;
}
}
return (R_SUCCESS);
}
/*
* Name: dumpGlobalData
* Description: dump global data structure using echoDebug
* Arguments: a_gdt - pointer to global data structure to dump
* Outputs: echoDebug is called to output global data strucutre information
* Returns: void
*/
static void
{
/* entry assertions */
/* debugging enabled, dump the global data structure */
if (a_gdt->gd_inheritedFileSystems) {
int n;
for (n = 0; ifs[n]; n++) {
}
}
}
/*
* Name: recursionCheck
* Description: prevent recursive calling of functions
* Arguments: r_recursion - pointer to int recursion counter
* a_function - pointer to name of function
* Returns: B_TRUE - function is recursively called
* B_FALSE - function not recursively called
*/
static boolean_t
{
/* prevent recursion */
(*r_recursion)++;
if (*r_recursion > 1) {
(*r_recursion)--;
return (B_TRUE);
}
return (B_FALSE);
}
/*
* Name: quit
* Description: cleanup and exit
* Arguments: a_retcode - the code to use to determine final exit status;
* if this is NOT "99" and if a "ckreturnFunc" is
* set, then that function is called with a_retcode
* to set the final exit status.
* Valid values are:
* 0 - success
* 1 - package operation failed (fatal error)
* 2 - non-fatal error (warning)
* 3 - user selected quit (operation interrupted)
* 4 - admin settings prevented operation
* 5 - interaction required and -n (non-interactive) specified
* "10" is added to indicate "immediate reboot required"
* "20" is be added to indicate "reboot after install required"
* 99 - do not interpret the code - just exit "99"
* Returns: <<this function does not return - calls exit()>>
* NOTE: This is needed because libinst functions can call "quit(99)"
* to force an error exit.
*/
void
{
/* process return code if not quit(99) */
if (a_retcode == 99) {
}
}