#include <stdio.h>
#include <sys/mnttab.h>
#include <sys/mntent.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <locale.h>
#include <errno.h>
#include <sys/param.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"
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
#define LS_CMD "/usr/bin/ls"
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;
struct fsi_t {
char *fsi_mntOptions;
char *fsi_fsType;
char *fsi_mntPoint;
};
typedef struct fsi_t FSI_T;
struct globalData_t {
boolean_t gd_initialInstall;
boolean_t gd_globalZoneInstall;
boolean_t gd_nonglobalZoneInstall;
boolean_t inMountedState;
FSI_T *gd_fileSystemConfig;
long gd_fileSystemConfigLen;
char *gd_zoneName;
char *gd_parentZoneName;
char *gd_parentZoneType;
char *gd_installRoot;
char *gd_currentZoneName;
char *gd_currentZoneType;
char *gd_cmdline_path;
};
typedef struct globalData_t GLOBALDATA_T;
struct cmd_t {
char *c_name;
char *c_args;
int (*c_func)(int argc, char **argv, GLOBALDATA_T *a_gdt);
};
typedef struct cmd_t CMD_T;
static int cmd_can_add_driver(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_can_remove_driver(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_can_update_driver(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_is_alternative_root(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_is_boot_environment(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_is_diskless_client(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_is_global_zone(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_is_mounted_miniroot(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_is_netinstall_image(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_is_nonglobal_zone(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_is_path_writable(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_is_running_system(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static int cmd_is_what(int argc, char **argv,
GLOBALDATA_T *a_gdt);
static boolean_t getNegateResults(void);
static boolean_t recursionCheck(int *r_recursion, char *a_function);
static int adjustResults(int a_result);
static int calculateFileSystemConfig(GLOBALDATA_T *a_gdt);
static int getRootPath(char **r_rootPath);
static int getZoneName(char **r_zoneName);
static int mountOptionPresent(char *a_mntOptions, char *a_opt);
static int parseGlobalData(char *a_envVar, GLOBALDATA_T **a_gdt);
static int resolvePath(char **r_path);
static int setRootPath(char *a_path, char *a_envVar,
boolean_t a_mustExist);
static int testPath(TEST_TYPES a_tt, char *format, ...);
static int usage(char *a_format, ...);
static int findToken(char *path, char *token);
static char *getMountOption(char **p);
static void dumpGlobalData(GLOBALDATA_T *a_gdt);
static void removeLeadingWhitespace(char **a_str);
static void setNegateResults(boolean_t setting);
static void setVerbose(boolean_t);
static void sortedInsert(FSI_T **r_list, long *a_listSize,
char *a_mntPoint, char *a_fsType, char *a_mntOptions);
static void setCmdLinePath(char **a_path, char **args,
int num_args);
static boolean_t _negateResults = B_FALSE;
static char *_rootPath = "/";
static CMD_T cmds[] = {
{ "can_add_driver", " [path]",
cmd_can_add_driver },
{ "can_remove_driver", " [path]",
cmd_can_remove_driver },
{ "can_update_driver", " [path]",
cmd_can_update_driver },
{ "is_alternative_root", " [path]",
cmd_is_alternative_root },
{ "is_boot_environment", " [path]",
cmd_is_boot_environment },
{ "is_diskless_client", " [path]",
cmd_is_diskless_client },
{ "is_global_zone", " [path]",
cmd_is_global_zone },
{ "is_mounted_miniroot", " [path]",
cmd_is_mounted_miniroot },
{ "is_netinstall_image", " [path]",
cmd_is_netinstall_image },
{ "is_nonglobal_zone", " [path]",
cmd_is_nonglobal_zone },
{ "is_path_writable", " path",
cmd_is_path_writable },
{ "is_running_system", " [path]",
cmd_is_running_system },
{ "is_what", " [path]",
cmd_is_what },
{ NULL, NULL, NULL }
};
int
main(int argc, char **argv)
{
GLOBALDATA_T *gdt = NULL;
char **newargv;
char *p;
int cur_cmd;
int i;
int newargc;
setbuf(stdout, NULL);
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
set_prog_name(argv[0]);
z_set_output_functions(echo, echoDebug, progerr);
if (getenv(ENV_VAR_VERBOSE)) {
setVerbose(B_TRUE);
}
if (getenv(ENV_VAR_DEBUG)) {
smlSetVerbose(B_TRUE);
setVerbose(B_TRUE);
echoDebugSetFlag(B_TRUE);
}
if (argc <= 1) {
(void) usage(MSG_NO_ARGUMENTS_SPECIFIED);
return (R_USAGE);
}
while ((i = getopt(argc, argv, ":O:vn?")) != EOF) {
switch (i) {
case 'O':
for (p = strtok(optarg, ","); p != NULL;
p = strtok(NULL, ",")) {
if (strcmp(p, "debug") == 0) {
smlSetVerbose(B_TRUE);
setVerbose(B_TRUE);
echoDebugSetFlag(B_TRUE);
continue;
}
progerr(ERR_INVALID_O_OPTION, p);
return (adjustResults(R_USAGE));
}
break;
case 'v':
setVerbose(B_TRUE);
break;
case 'n':
setNegateResults(B_TRUE);
break;
case '?':
default:
(void) usage(MSG_INVALID_OPTION_SPECIFIED, optopt);
return (R_USAGE);
}
}
if ((argc-optind) <= 0) {
(void) usage(MSG_NO_ARGUMENTS_SPECIFIED);
return (R_USAGE);
}
if (parseGlobalData(PKGCOND_GLOBAL_VARIABLE, &gdt) != R_SUCCESS) {
log_msg(LOG_MSG_ERR, ERR_CANNOT_USE_GLOBAL_DATA,
PKGCOND_GLOBAL_VARIABLE);
return (R_ERROR);
}
if (setRootPath(gdt->gd_installRoot,
(strcmp(gdt->gd_installRoot, "/") == 0) ? NULL :
ENV_VAR_SET, B_TRUE) != R_SUCCESS) {
log_msg(LOG_MSG_ERR, ERR_CANNOT_SET_ROOT_PATH,
ENV_VAR_PKGROOT);
return (R_ERROR);
}
setCmdLinePath(&(gdt->gd_cmdline_path), argv, argc);
echoDebug(DBG_CMDLINE_PATH,
gdt->gd_cmdline_path == NULL ? "" : gdt->gd_cmdline_path);
if (calculateFileSystemConfig(gdt) != R_SUCCESS) {
log_msg(LOG_MSG_ERR, ERR_CANNOT_CALC_FS_CONFIG);
return (R_ERROR);
}
dumpGlobalData(gdt);
for (cur_cmd = 0; cmds[cur_cmd].c_name != NULL; cur_cmd++) {
if (ci_streq(argv[optind], cmds[cur_cmd].c_name)) {
int result;
newargc = argc - optind;
newargv = argv + optind;
opterr = optind = 1; optopt = 0;
result = cmds[cur_cmd].c_func(newargc, newargv, gdt);
result = adjustResults(result);
log_msg(LOG_MSG_DEBUG, DBG_RESULTS, result);
return (result);
}
}
log_msg(LOG_MSG_ERR, ERR_BAD_SUB, argv[optind]);
(void) usage(MSG_UNRECOGNIZED_CONDITION_SPECIFIED);
return (R_USAGE);
}
static int
cmd_is_diskless_client(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
char cmd[MAXPATHLEN+1];
int c;
int r;
int rc;
static char *cmdName = "is_diskless_client";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
r = cmd_is_nonglobal_zone(argc, argv, a_gdt);
if (r != R_SUCCESS) {
r = cmd_is_mounted_miniroot(argc, argv, a_gdt);
}
if (r != R_SUCCESS) {
r = cmd_is_netinstall_image(argc, argv, a_gdt);
}
if (r != R_SUCCESS) {
r = cmd_is_boot_environment(argc, argv, a_gdt);
}
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
if (pkgTestInstalled("SUNWdclnt", "/") != B_TRUE) {
log_msg(LOG_MSG_DEBUG, DBG_IDLC_PKG_NOT_INSTALLED,
rootPath, "SUNWdclnt", "/");
return (R_FAILURE);
}
if (strcmp(rootPath, "/") == 0) {
log_msg(LOG_MSG_DEBUG, DBG_IDLC_ROOTPATH_BAD, rootPath, "/");
return (R_FAILURE);
}
if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) != 0) {
log_msg(LOG_MSG_DEBUG, DBG_IDLC_ZONE_BAD, rootPath,
GLOBAL_ZONENAME);
return (R_FAILURE);
}
(void) snprintf(cmd, sizeof (cmd), "%s %s >/dev/null 2>&1",
LS_CMD, "/export/exec/Solaris_*/usr");
rc = system(cmd);
if (rc != 0) {
log_msg(LOG_MSG_DEBUG, DBG_IDLC_PATH_MISSING,
rootPath, "/export/exec/Solaris_*/usr");
return (R_FAILURE);
}
(void) snprintf(cmd, sizeof (cmd), "%s %s %s/%s >/dev/null 2>&1",
LS_CMD, "-1d", rootPath, "usr/*");
rc = system(cmd);
if (rc == 0) {
log_msg(LOG_MSG_DEBUG, DBG_IDLC_USR_IS_NOT_EMPTY,
rootPath);
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
"%s/%s", rootPath, "../templates");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_IDLC_NO_TEMPLATES_PATH,
rootPath, rootPath, "../templates");
return (R_FAILURE);
}
if ((a_gdt->gd_initialInstall == B_TRUE) &&
(strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_IDLC_INITIAL_INSTALL, rootPath);
return (R_FAILURE);
}
if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
(a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
log_msg(LOG_MSG_DEBUG, DBG_IDLC_ZONE_INSTALL, rootPath);
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_IDLC_PATH_IS_DISKLESS_CLIENT, rootPath);
return (R_SUCCESS);
}
static int
cmd_is_global_zone(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int r;
static char *cmdName = "is_global_zone";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
r = cmd_is_nonglobal_zone(argc, argv, a_gdt);
if (r != R_SUCCESS) {
r = cmd_is_mounted_miniroot(argc, argv, a_gdt);
}
if (r != R_SUCCESS) {
r = cmd_is_netinstall_image(argc, argv, a_gdt);
}
if (r != R_SUCCESS) {
r = cmd_is_diskless_client(argc, argv, a_gdt);
}
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
if ((a_gdt->gd_initialInstall == B_TRUE) &&
(strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_ISGZ_INITIAL_INSTALL, rootPath);
return (R_FAILURE);
}
if (a_gdt->gd_nonglobalZoneInstall == B_TRUE) {
log_msg(LOG_MSG_DEBUG, DBG_ISGZ_NGZ_ZONE_INSTALL, rootPath);
return (R_FAILURE);
}
if ((a_gdt->gd_globalZoneInstall == B_TRUE) &&
(strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_IS_GLOBAL_ZONE,
rootPath);
return (R_SUCCESS);
}
if (strcmp(rootPath, "/") == 0) {
if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) == 0) {
log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_IS_GLOBAL_ZONE,
rootPath);
return (R_SUCCESS);
}
log_msg(LOG_MSG_DEBUG, DBG_ISGZ_ZONENAME_ISNT_GLOBAL,
rootPath, a_gdt->gd_zoneName);
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
"%s/%s", rootPath, "/etc/zones");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_ISNT_DIRECTORY,
rootPath, "/etc/zones");
return (R_FAILURE);
}
r = testPath(TEST_NOT_EXISTS,
"%s/%s", rootPath, ".tmp_proto");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_EXISTS,
rootPath, "/.tmp_proto");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/var");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_IS_SYMLINK,
rootPath, "/var");
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_ISGZ_PATH_IS_GLOBAL_ZONE, rootPath);
return (R_SUCCESS);
}
static int
cmd_is_netinstall_image(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int r;
static char *cmdName = "is_netinstall_image";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
r = cmd_is_global_zone(argc, argv, a_gdt);
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) != 0) {
log_msg(LOG_MSG_DEBUG, DBG_INIM_BAD_CURRENT_ZONE,
rootPath, GLOBAL_ZONENAME);
return (R_FAILURE);
}
if (cmd_is_mounted_miniroot(argc, argv, a_gdt) == R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_IMRT_PATH_IS_MOUNTED_MINIROOT,
rootPath);
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
"%s/%s", rootPath, ".tmp_proto");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_INIM_PATH_ISNT_DIRECTORY,
rootPath, "/.tmp_proto");
return (R_FAILURE);
}
r = testPath(TEST_IS_SYMBOLIC_LINK,
"%s/%s", rootPath, "/var");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_INIM_PATH_ISNT_SYMLINK,
rootPath, "/var");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
"%s/%s", rootPath, "/tmp/kernel");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_INIM_PATH_ISNT_DIRECTORY,
rootPath, "/tmp/kernel");
return (R_FAILURE);
}
r = testPath(TEST_IS_SYMBOLIC_LINK,
"%s/%s", rootPath, "/.tmp_proto/kernel");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_INIM_PATH_ISNT_SYMLINK,
rootPath, "/.tmp_proto/kernel");
return (R_FAILURE);
}
if ((a_gdt->gd_initialInstall == B_TRUE) &&
(strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_INIM_INITIAL_INSTALL, rootPath);
return (R_FAILURE);
}
if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
(a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
log_msg(LOG_MSG_DEBUG, DBG_INIM_ZONE_INSTALL, rootPath);
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_INIM_PATH_IS_NETINSTALL_IMAGE, rootPath);
return (R_SUCCESS);
}
static int
cmd_is_mounted_miniroot(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int r;
static char *cmdName = "is_mounted_miniroot";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
recursion--;
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) != 0) {
log_msg(LOG_MSG_DEBUG, DBG_IMRT_BAD_CURRENT_ZONE,
rootPath, GLOBAL_ZONENAME);
return (R_FAILURE);
}
r = testPath(TEST_IS_SYMBOLIC_LINK,
"%s/%s", rootPath, "/tmp/kernel");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_IMRT_PATH_ISNT_SYMLINK,
rootPath, "/tmp/kernel");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
"%s/%s", rootPath, "/tmp/root/kernel");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_IMRT_PATH_ISNT_DIRECTORY,
rootPath, "/tmp/root/kernel");
return (R_FAILURE);
}
if ((a_gdt->gd_initialInstall == B_TRUE) &&
(strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_IMRT_INITIAL_INSTALL, rootPath);
return (R_FAILURE);
}
if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
(a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
log_msg(LOG_MSG_DEBUG, DBG_IMRT_ZONE_INSTALL, rootPath);
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_IMRT_PATH_IS_MOUNTED_MINIROOT, rootPath);
return (R_SUCCESS);
}
static int
cmd_is_nonglobal_zone(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int r;
static char *cmdName = "is_nonglobal_zone";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
recursion--;
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
if ((a_gdt->gd_nonglobalZoneInstall == B_TRUE) &&
(strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_INSTALL_ZONENAME_IS_NGZ,
rootPath, a_gdt->gd_zoneName);
return (R_SUCCESS);
}
if ((a_gdt->gd_initialInstall == B_TRUE) &&
(strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_INITIAL_INSTALL, rootPath);
return (R_FAILURE);
}
if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
(a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_GLOBAL_ZONE_INSTALL, rootPath);
return (R_FAILURE);
}
if (strcmp(rootPath, "/") == 0) {
if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) == 0) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_ZONENAME_ISNT_NGZ,
rootPath, a_gdt->gd_zoneName);
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_NGZN_ZONENAME_IS_NGZ,
rootPath, a_gdt->gd_zoneName);
return (R_SUCCESS);
}
r = testPath(TEST_EXISTS, "%s/%s", rootPath, "/etc/zones/index");
if (r == R_SUCCESS) {
if (testPath(TEST_GLOBAL_TOKEN_IN_FILE, "%s/%s", rootPath,
"/etc/zones/index") != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_ZONENAME_ISNT_NGZ,
rootPath, GLOBAL_ZONENAME);
return (R_FAILURE);
}
}
r = testPath(TEST_NOT_EXISTS, "%s/%s", rootPath, ".tmp_proto");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_PATH_EXISTS,
rootPath, "/.tmp_proto");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/var");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_PATH_DOES_NOT_EXIST,
rootPath, "/var");
return (R_FAILURE);
}
r = testPath(TEST_NOT_EXISTS,
"%s/%s", rootPath, "/tmp/root/kernel");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_PATH_EXISTS,
rootPath, "/tmp/root/kernel");
return (R_FAILURE);
}
if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) == 0) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_IN_GZ_IS_NONGLOBAL_ZONE,
rootPath);
return (R_SUCCESS);
}
if ((a_gdt->gd_parentZoneName != NULL) &&
(a_gdt->gd_currentZoneName != NULL) &&
(strcmp(a_gdt->gd_parentZoneName,
a_gdt->gd_currentZoneName) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_PARENT_CHILD_SAMEZONE,
rootPath, a_gdt->gd_parentZoneName);
return (R_SUCCESS);
}
if (a_gdt->inMountedState) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_IS_NONGLOBAL_ZONE, rootPath);
return (R_SUCCESS);
}
if ((a_gdt->gd_parentZoneType != NULL) &&
(strcmp(a_gdt->gd_parentZoneType, "nonglobal") == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_BAD_PARENT_ZONETYPE,
rootPath, "nonglobal");
return (R_FAILURE);
}
if ((a_gdt->gd_currentZoneType != NULL) &&
(strcmp(a_gdt->gd_currentZoneType, GLOBAL_ZONENAME) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_NGZN_BAD_CURRENT_ZONETYPE,
rootPath, GLOBAL_ZONENAME);
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_NGZN_IS_NONGLOBAL_ZONE, rootPath);
return (R_SUCCESS);
}
static int
cmd_is_running_system(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int r;
static char *cmdName = "is_running_system";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
r = cmd_is_diskless_client(argc, argv, a_gdt);
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
if (strcmp(rootPath, "/") != 0) {
log_msg(LOG_MSG_DEBUG, DBG_IRST_ROOTPATH_BAD, rootPath, "/");
return (R_FAILURE);
}
if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) != 0) {
log_msg(LOG_MSG_DEBUG, DBG_IRST_ZONE_BAD, rootPath,
GLOBAL_ZONENAME);
return (R_FAILURE);
}
if ((a_gdt->gd_initialInstall == B_TRUE) &&
(strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_IRST_INITIAL_INSTALL, rootPath);
return (R_FAILURE);
}
if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
(a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
log_msg(LOG_MSG_DEBUG, DBG_IRST_ZONE_INSTALL, rootPath);
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_IRST_PATH_IS_RUNNING_SYSTEM, rootPath);
return (R_SUCCESS);
}
static int
cmd_can_add_driver(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int r;
static char *cmdName = "can_add_driver";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
r = cmd_is_running_system(argc, argv, a_gdt);
if (r != R_SUCCESS) {
r = cmd_is_diskless_client(argc, argv, a_gdt);
}
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/etc");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_ADDV_PATH_IS_SYMLINK,
rootPath, "/etc");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/platform");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_ADDV_PATH_IS_SYMLINK,
rootPath, "/platform");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/kernel");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_ADDV_PATH_IS_SYMLINK,
rootPath, "/kernel");
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_ADDV_YES, rootPath);
return (R_SUCCESS);
}
static int
cmd_can_update_driver(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int r;
static char *cmdName = "can_update_driver";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
r = cmd_is_running_system(argc, argv, a_gdt);
if (r != R_SUCCESS) {
r = cmd_is_diskless_client(argc, argv, a_gdt);
}
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/etc");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_UPDV_PATH_IS_SYMLINK,
rootPath, "/etc");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/platform");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_UPDV_PATH_IS_SYMLINK,
rootPath, "/platform");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/kernel");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_UPDV_PATH_IS_SYMLINK,
rootPath, "/kernel");
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_UPDV_YES, rootPath);
return (R_SUCCESS);
}
static int
cmd_can_remove_driver(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int r;
static char *cmdName = "can_remove_driver";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
r = cmd_is_running_system(argc, argv, a_gdt);
if (r != R_SUCCESS) {
r = cmd_is_diskless_client(argc, argv, a_gdt);
}
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/etc");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_RMDV_PATH_IS_SYMLINK,
rootPath, "/etc");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/platform");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_RMDV_PATH_IS_SYMLINK,
rootPath, "/platform");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_NOT_SYMBOLIC_LINK,
"%s/%s", rootPath, "/kernel");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_RMDV_PATH_IS_SYMLINK,
rootPath, "/kernel");
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_RMDV_YES, rootPath);
return (R_SUCCESS);
}
static int
cmd_is_path_writable(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
FSI_T *list;
char *rootPath = NULL;
int c;
int n;
int nn;
int r;
long listSize;
long rootPathLen;
static char *cmdName = "is_path_writable";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
recursion--;
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc != 1) {
(void) usage(ERR_REQUIRED_ROOTPATH_MISSING, cmdName);
return (R_USAGE);
}
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
rootPathLen = strlen(rootPath);
list = a_gdt->gd_fileSystemConfig;
listSize = a_gdt->gd_fileSystemConfigLen;
for (nn = 0, n = 0; n < listSize; n++) {
long mplen = strlen(list[n].fsi_mntPoint);
if (rootPathLen < mplen) {
continue;
}
if (strncmp(rootPath, list[n].fsi_mntPoint, mplen) == 0) {
nn = n;
}
}
log_msg(LOG_MSG_DEBUG, DBG_PWRT_INFO,
rootPath, list[nn].fsi_mntPoint, list[nn].fsi_fsType,
list[nn].fsi_mntOptions);
r = mountOptionPresent(list[nn].fsi_mntOptions, MNTOPT_RO);
if (r == R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_PWRT_READONLY,
rootPath, list[nn].fsi_mntOptions);
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_PWRT_IS, rootPath);
return (R_SUCCESS);
}
static int
cmd_is_alternative_root(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int r;
static char *cmdName = "is_alternative_root";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
r = cmd_is_boot_environment(argc, argv, a_gdt);
if (r != R_SUCCESS) {
r = cmd_is_diskless_client(argc, argv, a_gdt);
}
if (r != R_SUCCESS) {
r = cmd_is_mounted_miniroot(argc, argv, a_gdt);
}
if (r != R_SUCCESS) {
r = cmd_is_netinstall_image(argc, argv, a_gdt);
}
if (r != R_SUCCESS) {
r = cmd_is_nonglobal_zone(argc, argv, a_gdt);
}
if (r != R_SUCCESS) {
r = cmd_is_running_system(argc, argv, a_gdt);
}
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
if ((a_gdt->gd_initialInstall == B_TRUE) &&
(strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_IALR_INITIAL_INSTALL, rootPath);
return (R_SUCCESS);
}
if (strcmp(rootPath, "/") == 0) {
log_msg(LOG_MSG_DEBUG, DBG_IALR_BAD_ROOTPATH, rootPath, "/");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS,
"%s/%s", rootPath, "/var");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_IALR_PATH_DOES_NOT_EXIST,
rootPath, "/var");
return (R_FAILURE);
}
if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
(a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
log_msg(LOG_MSG_DEBUG, DBG_IALR_ZONE_INSTALL, rootPath);
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_IALR_IS, rootPath);
return (R_SUCCESS);
}
static int
cmd_is_boot_environment(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int r;
static char *cmdName = "is_boot_environment";
static int recursion = 0;
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
if (recursionCheck(&recursion, cmdName) == B_FALSE) {
r = cmd_is_diskless_client(argc, argv, a_gdt);
if (r != R_SUCCESS) {
r = cmd_is_netinstall_image(argc, argv, a_gdt);
}
if (r != R_SUCCESS) {
r = cmd_is_mounted_miniroot(argc, argv, a_gdt);
}
recursion--;
switch (r) {
case R_SUCCESS:
return (R_FAILURE);
case R_FAILURE:
break;
case R_USAGE:
case R_ERROR:
default:
return (r);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
echoDebug(DBG_ROOTPATH_IS, rootPath);
if (strcmp(rootPath, "/") == 0) {
log_msg(LOG_MSG_DEBUG, DBG_BENV_BAD_ROOTPATH, rootPath, "/");
return (R_FAILURE);
}
if (strcmp(a_gdt->gd_zoneName, GLOBAL_ZONENAME) != 0) {
log_msg(LOG_MSG_DEBUG, DBG_BENV_BAD_ZONE, rootPath,
GLOBAL_ZONENAME);
return (R_FAILURE);
}
r = testPath(TEST_EXISTS, "%s/%s", rootPath, "/etc/lutab");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_BENV_NO_ETCLUTAB, rootPath,
"/etc/lutab");
return (R_FAILURE);
}
r = testPath(TEST_EXISTS|TEST_IS_DIRECTORY,
"%s/%s", rootPath, "/etc/lu");
if (r != R_SUCCESS) {
log_msg(LOG_MSG_DEBUG, DBG_BENV_NO_ETCLU, rootPath, "/etc/lu");
return (R_FAILURE);
}
if ((a_gdt->gd_initialInstall == B_TRUE) &&
(strcmp(a_gdt->gd_installRoot, rootPath) == 0)) {
log_msg(LOG_MSG_DEBUG, DBG_BENV_INITIAL_INSTALL, rootPath);
return (R_FAILURE);
}
if ((a_gdt->gd_globalZoneInstall == B_TRUE) ||
(a_gdt->gd_nonglobalZoneInstall == B_TRUE)) {
log_msg(LOG_MSG_DEBUG, DBG_BENV_ZONE_INSTALL, rootPath);
return (R_FAILURE);
}
log_msg(LOG_MSG_DEBUG, DBG_BENV_IS, rootPath);
return (R_SUCCESS);
}
static int
cmd_is_what(int argc, char **argv, GLOBALDATA_T *a_gdt)
{
char *rootPath = NULL;
int c;
int cur_cmd;
int r;
static char *cmdName = "is_what";
while ((c = getopt(argc, argv, ":")) != EOF) {
switch (c) {
case '\0':
break;
case '?':
default:
(void) usage(MSG_IS_INVALID_OPTION, optopt, cmdName);
return (R_USAGE);
}
}
argc -= optind;
argv += optind;
if (argc > 1) {
log_msg(LOG_MSG_ERR, ERR_UNRECOGNIZED_OPTION, argv[1]);
(void) usage(MSG_IS_INVALID_OPTION, argv[1]);
return (R_USAGE);
}
if (argc == 1) {
if (setRootPath(argv[0], "argv[0]", B_TRUE) != R_SUCCESS) {
return (R_ERROR);
}
}
r = getRootPath(&rootPath);
if (r != R_SUCCESS) {
return (r);
}
argc = 0;
argv[argc++] = strdup(get_prog_name());
argv[argc++] = strdup(rootPath);
echoDebug(DBG_ROOTPATH_IS, rootPath);
for (cur_cmd = 0; cmds[cur_cmd].c_name != NULL; cur_cmd++) {
int result;
if (cmds[cur_cmd].c_func == cmd_is_what) {
continue;
}
result = cmds[cur_cmd].c_func(argc, argv, a_gdt);
result = adjustResults(result);
log_msg(LOG_MSG_INFO, MSG_IS_WHAT_RESULT,
cmds[cur_cmd].c_name, result);
}
return (R_SUCCESS);
}
static char *
getMountOption(char **p)
{
char *cp = *p;
char *retstr;
while (*cp && isspace(*cp))
cp++;
retstr = cp;
while (*cp && *cp != ',')
cp++;
if (*cp) {
*cp = '\0';
cp++;
}
*p = cp;
return (retstr);
}
static int
mountOptionPresent(char *a_mntOptions, char *a_opt)
{
char tmpopts[MNT_LINE_MAX];
char *f, *opts = tmpopts;
if ((a_opt == NULL) || (*a_opt == '\0')) {
return (R_FAILURE);
}
if (a_mntOptions == NULL) {
return (R_FAILURE);
}
if (*a_mntOptions == '\0') {
return (R_FAILURE);
}
(void) strcpy(opts, a_mntOptions);
f = getMountOption(&opts);
for (; *f; f = getMountOption(&opts)) {
if (strncmp(a_opt, f, strlen(a_opt)) == 0) {
return (R_SUCCESS);
}
}
return (R_FAILURE);
}
static void
sortedInsert(FSI_T **r_list, long *a_listSize, char *a_mntPoint,
char *a_fsType, char *a_mntOptions)
{
int listSize;
FSI_T *list;
int n;
assert(a_listSize != (long *)NULL);
assert(a_mntPoint != NULL);
assert(a_fsType != NULL);
assert(a_mntOptions != NULL);
echoDebug(DBG_SINS_ENTRY, a_mntPoint, a_fsType, a_mntOptions);
listSize = *a_listSize;
list = *r_list;
if (listSize == 0) {
listSize++;
list = (FSI_T *)realloc(list, sizeof (FSI_T)*(listSize+1));
list[0].fsi_mntPoint = strdup(a_mntPoint);
list[0].fsi_fsType = strdup(a_fsType);
list[0].fsi_mntOptions = strdup(a_mntOptions);
list[1].fsi_mntPoint = NULL;
list[1].fsi_fsType = NULL;
list[1].fsi_mntOptions = NULL;
*a_listSize = listSize;
*r_list = list;
return;
}
for (n = 0; n < listSize; n++) {
int c;
c = strcmp(list[n].fsi_mntPoint, a_mntPoint);
if (c == 0) {
char *me;
long len;
len = strlen(list[n].fsi_mntOptions) +
strlen(a_mntOptions) + 2;
me = (char *)calloc(1, len);
(void) strlcat(me, list[n].fsi_mntOptions, len);
(void) strlcat(me, ",", len);
(void) strlcat(me, a_mntOptions, len);
free(list[n].fsi_mntOptions);
list[n].fsi_mntOptions = me;
echoDebug(DBG_SORTEDINS_SKIPPED,
n, list[n].fsi_mntPoint, a_fsType,
list[n].fsi_fsType, a_mntOptions,
list[n].fsi_mntOptions);
continue;
} else if (c < 0) {
continue;
}
listSize++;
list = (FSI_T *)realloc(list,
sizeof (FSI_T)*(listSize+1));
(void) memmove(&(list[n+1]), &(list[n]),
sizeof (FSI_T)*(listSize-n));
list[n].fsi_mntPoint = strdup(a_mntPoint);
list[n].fsi_fsType = strdup(a_fsType);
list[n].fsi_mntOptions = strdup(a_mntOptions);
*a_listSize = listSize;
*r_list = list;
return;
}
listSize++;
list = (FSI_T *)realloc(list, sizeof (FSI_T)*(listSize+1));
list[listSize-1].fsi_mntPoint = strdup(a_mntPoint);
list[listSize-1].fsi_fsType = strdup(a_fsType);
list[listSize-1].fsi_mntOptions = strdup(a_mntOptions);
*a_listSize = listSize;
*r_list = list;
}
static int
calculateFileSystemConfig(GLOBALDATA_T *a_gdt)
{
FILE *fp;
struct mnttab mntbuf;
FSI_T *list;
long listSize;
assert(a_gdt != (GLOBALDATA_T *)NULL);
list = (FSI_T *)calloc(1, sizeof (FSI_T));
list[0].fsi_mntPoint = NULL;
list[0].fsi_fsType = NULL;
list[0].fsi_mntOptions = NULL;
listSize = 0;
fp = fopen(MNTTAB, "r");
if (fp == (FILE *)NULL) {
return (R_ERROR);
}
echoDebug(DBG_CALCSCFG_MOUNTED);
while (getmntent(fp, &mntbuf) == 0) {
if (mntbuf.mnt_mountp[0] == '/') {
sortedInsert(&list, &listSize,
strdup(mntbuf.mnt_mountp),
strdup(mntbuf.mnt_fstype),
strdup(mntbuf.mnt_mntopts ?
mntbuf.mnt_mntopts : ""));
}
if (strcmp(mntbuf.mnt_mountp, "/a") == 0 &&
strcmp(mntbuf.mnt_special, "/a") == 0 &&
strcmp(mntbuf.mnt_fstype, "lofs") == 0) {
a_gdt->inMountedState = B_TRUE;
}
}
(void) fclose(fp);
a_gdt->gd_fileSystemConfig = list;
a_gdt->gd_fileSystemConfigLen = listSize;
return (R_SUCCESS);
}
static int
adjustResults(int a_result)
{
boolean_t negate = getNegateResults();
int realResult;
switch (a_result) {
case R_SUCCESS:
realResult = ((negate == B_TRUE) ? 1 : 0);
break;
case R_FAILURE:
realResult = ((negate == B_TRUE) ? 0 : 1);
break;
case R_USAGE:
realResult = 2;
break;
case R_ERROR:
default:
realResult = 3;
break;
}
log_msg(LOG_MSG_DEBUG, DBG_ADJUST_RESULTS, a_result, negate,
realResult);
return (realResult);
}
static void
setCmdLinePath(char **path, char **args, int num_args)
{
char rp[PATH_MAX] = { '\0' };
struct stat statbuf;
if (*path != NULL) {
return;
}
if (realpath(args[num_args - 1], rp) != NULL) {
if (stat(rp, &statbuf) == 0) {
if ((statbuf.st_mode & S_IFDIR)) {
*path = strdup(rp);
} else {
*path = NULL;
}
}
}
}
static int
setRootPath(char *a_path, char *a_envVar, boolean_t a_mustExist)
{
char rp[PATH_MAX] = { '\0' };
struct stat statbuf;
if ((a_path == NULL) || (*a_path == '\0')) {
echoDebug(DBG_NO_DEFAULT_ROOT_PATH_SET);
return (R_SUCCESS);
}
if (realpath(a_path, rp) == NULL) {
if (a_mustExist == B_TRUE) {
log_msg(LOG_MSG_ERR, ERR_DEFAULT_ROOT_INVALID,
a_path, strerror(errno));
return (R_ERROR);
} else {
(void) strcpy(rp, a_path);
}
}
echoDebug(DBG_DEFAULT_ROOT_PATH_SET, rp, a_envVar ? a_envVar : "");
if (a_mustExist == B_TRUE) {
if (stat(rp, &statbuf) != 0) {
log_msg(LOG_MSG_ERR, ERR_DEFAULT_ROOT_INVALID,
rp, strerror(errno));
return (R_ERROR);
}
if (!(statbuf.st_mode & S_IFDIR)) {
log_msg(LOG_MSG_ERR, ERR_DEFAULT_ROOT_NOT_DIR, rp);
return (R_ERROR);
}
}
echoDebug(DBG_SET_ROOT_PATH_TO, rp);
_rootPath = strdup(rp);
return (R_SUCCESS);
}
static int
testPath(TEST_TYPES a_tt, char *a_format, ...)
{
char *mbPath;
char bfr[1];
int r;
size_t vres = 0;
struct stat statbuf;
va_list ap;
int fd;
assert(a_format != NULL);
assert(*a_format != '\0');
va_start(ap, a_format);
vres = vsnprintf(bfr, 1, a_format, ap);
va_end(ap);
assert(vres > 0);
mbPath = (char *)calloc(1, vres+2);
assert(mbPath != NULL);
va_start(ap, a_format);
vres = vsnprintf(mbPath, vres+1, a_format, ap);
va_end(ap);
assert(vres > 0);
echoDebug(DBG_TEST_PATH, mbPath, (unsigned long)a_tt);
if (a_tt & (TEST_IS_SYMBOLIC_LINK|TEST_NOT_SYMBOLIC_LINK)) {
if (lstat(mbPath, &statbuf) != 0) {
echoDebug(DBG_CANNOT_LSTAT_PATH, mbPath,
strerror(errno));
free(mbPath);
return (R_FAILURE);
}
if (a_tt & TEST_IS_SYMBOLIC_LINK) {
if (!(statbuf.st_mode & S_IFLNK)) {
echoDebug(DBG_IS_NOT_A_SYMLINK, mbPath);
free(mbPath);
return (R_FAILURE);
}
echoDebug(DBG_SYMLINK_IS, mbPath);
}
if (a_tt & TEST_NOT_SYMBOLIC_LINK) {
if (statbuf.st_mode & S_IFLNK) {
echoDebug(DBG_IS_A_SYMLINK, mbPath);
free(mbPath);
return (R_FAILURE);
}
echoDebug(DBG_SYMLINK_NOT, mbPath);
}
if (!(a_tt &
(~(TEST_IS_SYMBOLIC_LINK|TEST_NOT_SYMBOLIC_LINK)))) {
free(mbPath);
return (R_SUCCESS);
}
}
r = resolvePath(&mbPath);
if (r != R_SUCCESS) {
echoDebug(DBG_TEST_PATH_NO_RESOLVE, mbPath);
free(mbPath);
if (a_tt & TEST_NOT_EXISTS) {
return (R_SUCCESS);
}
return (r);
}
echoDebug(DBG_TEST_PATH_RESOLVE, mbPath);
fd = open(mbPath, O_RDONLY|O_LARGEFILE, 0);
if (fd < 0) {
if (a_tt & TEST_NOT_EXISTS) {
echoDebug(DBG_CANNOT_ACCESS_PATH_OK, mbPath);
free(mbPath);
return (R_SUCCESS);
}
echoDebug(DBG_CANNOT_ACCESS_PATH_BUT_SHOULD,
mbPath, strerror(errno));
free(mbPath);
return (R_FAILURE);
}
if (a_tt & TEST_NOT_EXISTS) {
echoDebug(DBG_TEST_EXISTS_SHOULD_NOT, mbPath);
free(mbPath);
(void) close(fd);
return (R_FAILURE);
}
r = fstat(fd, &statbuf);
if (r != 0) {
echoDebug(DBG_PATH_DOES_NOT_EXIST, mbPath, strerror(errno));
(void) close(fd);
free(mbPath);
return (R_FAILURE);
}
if (a_tt & TEST_IS_DIRECTORY) {
if (!(statbuf.st_mode & S_IFDIR)) {
echoDebug(DBG_IS_NOT_A_DIRECTORY, mbPath);
free(mbPath);
return (R_FAILURE);
}
echoDebug(DBG_DIRECTORY_IS, mbPath);
}
if (a_tt & TEST_NOT_DIRECTORY) {
if (statbuf.st_mode & S_IFDIR) {
echoDebug(DBG_IS_A_DIRECTORY, mbPath);
free(mbPath);
return (R_FAILURE);
}
echoDebug(DBG_DIRECTORY_NOT, mbPath);
}
if (a_tt & TEST_IS_FILE) {
if (!(statbuf.st_mode & S_IFREG)) {
echoDebug(DBG_IS_NOT_A_FILE, mbPath);
free(mbPath);
return (R_FAILURE);
}
echoDebug(DBG_FILE_IS, mbPath);
}
if (a_tt & TEST_NOT_FILE) {
if (statbuf.st_mode & S_IFREG) {
echoDebug(DBG_IS_A_FILE, mbPath);
free(mbPath);
return (R_FAILURE);
}
echoDebug(DBG_FILE_NOT, mbPath);
}
if (a_tt & TEST_GLOBAL_TOKEN_IN_FILE) {
if (!(statbuf.st_mode & S_IFREG)) {
echoDebug(DBG_IS_NOT_A_FILE, mbPath);
free(mbPath);
return (R_FAILURE);
}
if (findToken(mbPath, GLOBAL_ZONENAME) == R_SUCCESS) {
echoDebug(DBG_TOKEN__EXISTS, GLOBAL_ZONENAME, mbPath);
free(mbPath);
return (R_FAILURE);
}
}
(void) close(fd);
echoDebug(DBG_TESTPATH_OK, mbPath);
free(mbPath);
return (R_SUCCESS);
}
static int
findToken(char *path, char *token)
{
FILE *fp;
char *cp;
char line[MAXPATHLEN];
if (path == NULL || token == NULL) {
return (R_ERROR);
}
if ((fp = fopen(path, "r")) == NULL) {
return (R_ERROR);
}
while (fgets(line, sizeof (line), fp) != NULL) {
for (cp = line; *cp && isspace(*cp); cp++)
;
if (*cp == '#') {
continue;
}
if (pkgstrContainsToken(cp, token, ":")) {
(void) fclose(fp);
return (R_SUCCESS);
}
}
(void) fclose(fp);
return (R_FAILURE);
}
static int
resolvePath(char **r_path)
{
int i;
char resolvedPath[MAXPATHLEN+1] = {'\0'};
size_t mbPathlen;
size_t wcPathlen;
wchar_t *wcPath;
wchar_t *wptr;
assert(r_path != NULL);
if (**r_path == '\0') {
return (R_FAILURE);
}
removeLeadingWhitespace(r_path);
if (realpath(*r_path, resolvedPath) != NULL) {
free(*r_path);
*r_path = strdup(resolvedPath);
}
mbPathlen = strlen(*r_path);
if ((wcPath = (wchar_t *)
calloc(1, sizeof (wchar_t)*(mbPathlen+1))) == NULL) {
return (R_FAILURE);
}
if ((wcPathlen = mbstowcs(wcPath, *r_path, mbPathlen)) == -1) {
free(wcPath);
return (R_FAILURE);
}
for (wptr = wcPath, i = 0; i < wcPathlen; i++) {
*wptr++ = wcPath[i];
if (wcPath[i] == '/') {
i++;
while (wcPath[i] == '/') {
i++;
}
i--;
}
}
*wptr = '\0';
if (wcstombs(*r_path, wcPath, mbPathlen) == -1) {
free(wcPath);
return (R_FAILURE);
}
free(wcPath);
return (R_SUCCESS);
}
static void
removeLeadingWhitespace(char **a_str)
{
char *o_str;
assert(a_str != (char **)NULL);
if (*a_str == NULL) {
return;
}
o_str = *a_str;
if (*o_str == '\0') {
free(*a_str);
*a_str = NULL;
return;
}
if (!isspace(*o_str)) {
return;
}
while ((*o_str != '\0') && (isspace(*o_str))) {
o_str++;
}
if (*o_str == '\0') {
free(*a_str);
*a_str = NULL;
return;
}
o_str = strdup(o_str);
free(*a_str);
*a_str = o_str;
}
static int
getZoneName(char **r_zoneName)
{
static char zoneName[ZONENAME_MAX] = { '\0' };
if (zoneName[0] == '\0') {
if (getzonenamebyid(getzoneid(), zoneName,
sizeof (zoneName)) < 0) {
log_msg(LOG_MSG_ERR, ERR_CANNOT_GET_ZONENAME);
return (R_ERROR);
}
}
*r_zoneName = zoneName;
return (R_SUCCESS);
}
static int
getRootPath(char **r_rootPath)
{
*r_rootPath = _rootPath;
return (R_SUCCESS);
}
static void
setVerbose(boolean_t setting)
{
log_set_verbose(setting);
echoSetFlag(setting);
}
static void
setNegateResults(boolean_t setting)
{
log_msg(LOG_MSG_DEBUG, DBG_SET_NEGATE_RESULTS,
_negateResults, setting);
_negateResults = setting;
}
static boolean_t
getNegateResults(void)
{
return (_negateResults);
}
static int
usage(char *a_format, ...)
{
int cur_cmd;
char cmdlst[LINE_MAX+1] = { '\0' };
char *message;
char bfr[1];
char *p = get_prog_name();
size_t vres = 0;
va_list ap;
assert(a_format != NULL);
assert(*a_format != '\0');
va_start(ap, a_format);
vres = vsnprintf(bfr, 1, a_format, ap);
va_end(ap);
assert(vres > 0);
message = (char *)calloc(1, vres+2);
assert(message != NULL);
va_start(ap, a_format);
vres = vsnprintf(message, vres+1, a_format, ap);
va_end(ap);
assert(vres > 0);
for (cur_cmd = 0; cmds[cur_cmd].c_name != NULL; cur_cmd++) {
(void) strlcat(cmdlst, "\t", sizeof (cmdlst));
(void) strlcat(cmdlst, cmds[cur_cmd].c_name, sizeof (cmdlst));
if (cmds[cur_cmd].c_args != NULL) {
(void) strlcat(cmdlst, cmds[cur_cmd].c_args,
sizeof (cmdlst));
}
(void) strlcat(cmdlst, "\n", sizeof (cmdlst));
}
log_msg(LOG_MSG_INFO, MSG_USAGE, message, p ? p : "pkgcond", cmdlst);
return (R_ERROR);
}
static int
parseGlobalData(char *a_envVar, GLOBALDATA_T **r_gdt)
{
int r;
char *a;
SML_TAG *tag;
SML_TAG *ntag;
assert(r_gdt != (GLOBALDATA_T **)NULL);
if (*r_gdt == (GLOBALDATA_T *)NULL) {
*r_gdt = (GLOBALDATA_T *)calloc(1, sizeof (GLOBALDATA_T));
}
a = getenv(ENV_VAR_INITIAL_INSTALL);
if ((a != NULL) && (strcasecmp(a, "true") == 0)) {
(*r_gdt)->gd_initialInstall = B_TRUE;
}
r = getZoneName(&(*r_gdt)->gd_zoneName);
if (r != R_SUCCESS) {
(*r_gdt)->gd_zoneName = "";
}
a = getenv(ENV_VAR_PKGZONENAME);
if ((a == NULL) || (*a == '\0')) {
(*r_gdt)->gd_globalZoneInstall = B_FALSE;
(*r_gdt)->gd_nonglobalZoneInstall = B_FALSE;
} else if (strcmp(a, GLOBAL_ZONENAME) == 0) {
(*r_gdt)->gd_globalZoneInstall = B_TRUE;
(*r_gdt)->gd_nonglobalZoneInstall = B_FALSE;
(*r_gdt)->gd_zoneName = a;
} else {
(*r_gdt)->gd_globalZoneInstall = B_FALSE;
(*r_gdt)->gd_nonglobalZoneInstall = B_TRUE;
(*r_gdt)->gd_zoneName = a;
}
a = getenv(ENV_VAR_PKGROOT);
if ((a != NULL) && (*a != '\0')) {
(*r_gdt)->gd_installRoot = a;
} else {
(*r_gdt)->gd_installRoot = "/";
}
a = getenv(a_envVar);
if ((a == NULL) || (*a_envVar == '\0')) {
log_msg(LOG_MSG_DEBUG, DBG_NO_GLOBAL_DATA_AVAILABLE, a_envVar);
return (R_SUCCESS);
}
log_msg(LOG_MSG_DEBUG, DBG_PARSE_GLOBAL, a);
r = smlConvertStringToTag(&tag, a);
if (r != R_SUCCESS) {
log_msg(LOG_MSG_ERR, ERR_CANNOT_PARSE_GLOBAL_DATA, a);
return (R_FAILURE);
}
smlDbgPrintTag(tag, DBG_PARSED_ENVIRONMENT, a_envVar);
ntag = smlGetTagByName(tag, 0, TAG_COND_TOPLEVEL);
if (ntag == SML_TAG__NULL) {
log_msg(LOG_MSG_WRN, WRN_PARSED_DATA_MISSING,
TAG_COND_TOPLEVEL);
return (R_FAILURE);
}
a = smlGetParamByTag(ntag, 0, TAG_COND_PARENT_ZONE, TAG_COND_ZONE_NAME);
(*r_gdt)->gd_parentZoneName = a;
a = smlGetParamByTag(ntag, 0, TAG_COND_PARENT_ZONE, TAG_COND_ZONE_TYPE);
(*r_gdt)->gd_parentZoneType = a;
a = smlGetParamByTag(ntag, 0, TAG_COND_CURRENT_ZONE,
TAG_COND_ZONE_NAME);
(*r_gdt)->gd_currentZoneName = a;
a = smlGetParamByTag(ntag, 0, TAG_COND_CURRENT_ZONE,
TAG_COND_ZONE_TYPE);
(*r_gdt)->gd_currentZoneType = a;
return (R_SUCCESS);
}
static void
dumpGlobalData(GLOBALDATA_T *a_gdt)
{
assert(a_gdt != (GLOBALDATA_T *)NULL);
echoDebug(DBG_DUMP_GLOBAL_ENTRY);
echoDebug(DBG_DUMP_GLOBAL_PARENT_ZONE,
a_gdt->gd_parentZoneName ? a_gdt->gd_parentZoneName : "",
a_gdt->gd_parentZoneType ? a_gdt->gd_parentZoneType : "");
echoDebug(DBG_DUMP_GLOBAL_CURRENT_ZONE,
a_gdt->gd_currentZoneName ? a_gdt->gd_currentZoneName : "",
a_gdt->gd_currentZoneType ? a_gdt->gd_currentZoneType : "");
}
static boolean_t
recursionCheck(int *r_recursion, char *a_function)
{
(*r_recursion)++;
if (*r_recursion > 1) {
echoDebug(DBG_RECURSION, a_function, *r_recursion);
(*r_recursion)--;
return (B_TRUE);
}
echoDebug(DBG_NO_RECURSION, a_function);
return (B_FALSE);
}
void
quit(int a_retcode)
{
if (a_retcode == 99) {
exit(0x7f);
}
exit(R_FAILURE);
}