#include <stdio.h>
#include <time.h>
#include <wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <ulimit.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <dirent.h>
#include <string.h>
#include <signal.h>
#include <locale.h>
#include <libintl.h>
#include <pkgstrct.h>
#include <pkginfo.h>
#include <pkgdev.h>
#include <pkglocs.h>
#include <pwd.h>
#include <assert.h>
#include <instzones_api.h>
#include <pkglib.h>
#include <install.h>
#include <libinst.h>
#include <libadm.h>
#include <dryrun.h>
#include <messages.h>
#include "pkginstall.h"
extern char **environ;
extern char *pkgabrv;
extern char *pkgname;
extern char *pkgarch;
extern char *pkgvers;
extern char pkgwild[];
extern char *get_install_root(void);
extern sighdlrFunc_t *quitGetTrapHandler(void);
extern void quitSetDstreamTmpdir(char *a_dstreamTempDir);
extern void quitSetInstallStarted(boolean_t a_installStarted);
extern void quitSetPkgask(boolean_t a_pkgaskFlag);
extern void quitSetSilentExit(boolean_t a_silentExit);
extern void quitSetUpdatingExisting(boolean_t a_updatingExisting);
extern void quitSetZoneName(char *a_zoneName);
static char path[PATH_MAX];
static int ck_instbase(void);
static int cp_pkgdirs(void);
static int merg_pkginfos(struct cl_attr **pclass,
struct cl_attr ***mpclass);
static int merg_respfile(void);
static int mv_pkgdirs(void);
static int rdonly(char *p);
static void ck_w_dryrun(int (*func)(), int type);
static void copyright(void);
static void usage(void) __NORETURN;
static void do_pkgask(boolean_t a_run_request_as_root);
static void rm_icas(char *casdir);
static void set_dryrun_dir_loc(void);
static void unpack(void);
void ckreturn(int retcode, char *msg);
static char *ro_params[] = {
"PATH", "NAME", "PKG", "PKGINST",
"VERSION", "ARCH",
"INSTDATE", "CATEGORY",
NULL
};
static char *script_in = PROC_STDIN;
static char *pkgdrtarg = NULL;
static char *pkgcontsrc = NULL;
static int non_abi_scripts = 0;
static char *respfile = NULL;
static char *srcinst = NULL;
static int suppressCopyright = 0;
static int nointeract = 0;
char *msgtext;
char *pkginst = (char *)NULL;
char *rw_block_size = NULL;
char ilockfile[PATH_MAX];
char instdir[PATH_MAX];
char saveSpoolInstallDir[PATH_MAX];
char pkgbin[PATH_MAX];
char pkgloc[PATH_MAX];
char pkgloc_sav[PATH_MAX];
char pkgsav[PATH_MAX];
char rlockfile[PATH_MAX];
char savlog[PATH_MAX];
char tmpdir[PATH_MAX];
int dbchg;
int dparts = 0;
int dreboot = 0;
int failflag = 0;
static int askflag = 0;
int ireboot = 0;
int maxinst = 1;
int nocnflct;
int nosetuid;
int pkgverbose = 0;
int rprcflag;
int warnflag = 0;
struct admin adm;
struct cfextra **extlist;
struct pkgdev pkgdev;
fsblkcnt_t pkgmap_blks = 0LL;
static int update = 0;
static boolean_t debugFlag = B_FALSE;
static boolean_t globalZoneOnly = B_FALSE;
static boolean_t preinstallCheck = B_FALSE;
static char *parentZoneName = (char *)NULL;
static char *parentZoneType = (char *)NULL;
#define DEFPATH "/sbin:/usr/sbin:/usr/bin"
#define MALSIZ 4
#define LSIZE 256
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
#define PARENTZONENAME "parent-zone-name="
#define PARENTZONENAME_LEN ((sizeof (PARENTZONENAME))-1)
#define PARENTZONETYPE "parent-zone-type="
#define PARENTZONETYPE_LEN ((sizeof (PARENTZONETYPE))-1)
static char *cpio_names[] = {
"root",
"root.cpio",
"reloc",
"reloc.cpio",
"root.Z",
"root.cpio.Z",
"reloc.Z",
"reloc.cpio.Z",
0
};
int
main(int argc, char *argv[])
{
VFP_T *cfTmpVfp = NULL;
VFP_T *pkgmapVfp;
boolean_t run_request_as_root = B_FALSE;
char **np;
char *abi_comp_ptr;
char *abi_nm_ptr;
char *abi_sym_ptr;
char *admnfile = NULL;
char *device;
char *p;
char *prog_full_name = NULL;
char *pt;
char *updated = (char *)NULL;
char *vfstab_file = NULL;
char *zoneName = (char *)NULL;
char cbuf[MAX_PKG_PARAM_LENGTH];
char cmdbin[PATH_MAX];
char p_pkginfo[PATH_MAX];
char p_pkgmap[PATH_MAX];
char param[MAX_PKG_PARAM_LENGTH];
char script[PATH_MAX];
char altscript[PATH_MAX];
char *temp;
int c;
int disableAttributes = 0;
int err;
int init_install = 0;
int is_comp_arch;
int live_continue = 0;
int map_client = 1;
int n;
int nparts;
int npkgs;
int part;
int saveSpoolInstall = 0;
boolean_t cont_file_read;
struct cl_attr **pclass = NULL;
struct cl_attr **mergd_pclass = NULL;
struct pkginfo *prvinfo;
struct sigaction nact;
struct sigaction oact;
struct stat statb;
struct statvfs64 svfsb;
time_t clock;
PKGserver pkgserver = NULL;
(void) memset(path, '\0', sizeof (path));
(void) memset(cmdbin, '\0', sizeof (cmdbin));
(void) memset(script, '\0', sizeof (script));
(void) memset(cbuf, '\0', sizeof (cbuf));
(void) memset(param, '\0', sizeof (param));
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
prog_full_name = argv[0];
(void) set_prog_name(argv[0]);
z_set_output_functions(echo, echoDebug, progerr);
if (getuid()) {
progerr(ERR_NOT_ROOT, get_prog_name());
exit(1);
}
setmapmode(MAPINSTALL);
(void) umask(0022);
device = NULL;
npkgs = 0;
if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
progerr(ERR_ROOT_SET);
exit(1);
}
pkgserversetmode(DEFAULTMODE);
while ((c = getopt(argc, argv,
"?Aa:B:b:Cc:D:d:eFf:GhIiMm:N:noO:p:R:r:StV:vyz")) != EOF) {
switch (c) {
case 'A':
disableAttributes++;
break;
case 'a':
admnfile = flex_device(optarg, 0);
break;
case 'B':
rw_block_size = optarg;
break;
case 'b':
if (!path_valid(optarg)) {
progerr(ERR_PATH, optarg);
exit(1);
}
if (isdir(optarg) != 0) {
char *p = strerror(errno);
progerr(ERR_CANNOT_USE_DIR, optarg, p);
exit(1);
}
(void) strlcpy(cmdbin, optarg, sizeof (cmdbin));
break;
case 'C':
(void) checksum_off();
break;
case 'c':
pkgcontsrc = optarg;
set_continue_mode();
set_dr_info(DR_TYPE, INSTALL_TYPE);
init_contfile(pkgcontsrc);
break;
case 'D':
pkgdrtarg = optarg;
set_dryrun_mode();
set_dr_info(DR_TYPE, INSTALL_TYPE);
break;
case 'd':
device = flex_device(optarg, 1);
break;
case 'e':
(void) set_ABI_namelngth();
break;
case 'f':
pkgdev.fstyp = optarg;
break;
case 'G':
globalZoneOnly = B_TRUE;
break;
case 'h':
set_depend_pkginfo_DB(B_TRUE);
break;
case 'I':
init_install++;
break;
case 'i':
askflag++;
quitSetPkgask(B_TRUE);
break;
case 'M':
map_client = 0;
break;
case 'm':
pkgdev.mount = optarg;
pkgdev.rdonly++;
pkgdev.mntflg++;
break;
case 'N':
(void) set_prog_name(optarg);
break;
case 'n':
nointeract++;
(void) echoSetFlag(B_FALSE);
break;
case 'O':
for (p = strtok(optarg, ","); p != (char *)NULL;
p = strtok(NULL, ",")) {
if (strcmp(p, "debug") == 0) {
if (debugFlag == B_TRUE) {
smlSetVerbose(B_TRUE);
}
debugFlag = B_TRUE;
(void) echoDebugSetFlag(debugFlag);
for (n = 0; n < argc && argv[n]; n++) {
echoDebug(DBG_ARG, n, argv[n]);
}
continue;
}
if (strcmp(p,
"enable-hollow-package-support") == 0) {
set_depend_pkginfo_DB(B_TRUE);
continue;
}
if (strcmp(p, "preinstallcheck") == 0) {
preinstallCheck = B_TRUE;
nointeract++;
suppressCopyright++;
quitSetSilentExit(B_TRUE);
continue;
}
if (strcmp(p, "addzonename") == 0) {
zoneName =
getenv(PKG_ZONENAME_VARIABLE);
if ((zoneName == (char *)NULL) ||
(*zoneName == '\0')) {
zoneName = z_get_zonename();
}
if (zoneName != (char *)NULL) {
if (*zoneName != '\0') {
quitSetZoneName(
zoneName);
} else {
zoneName = (char *)NULL;
}
}
continue;
}
if (strncmp(p, PARENTZONENAME,
PARENTZONENAME_LEN) == 0) {
parentZoneName = p+PARENTZONENAME_LEN;
continue;
}
if (strncmp(p, PARENTZONETYPE,
PARENTZONETYPE_LEN) == 0) {
parentZoneType = p+PARENTZONETYPE_LEN;
continue;
}
if (strncmp(p, PKGSERV_MODE,
PKGSERV_MODE_LEN) == 0) {
pkgserversetmode(pkgparsemode(p +
PKGSERV_MODE_LEN));
continue;
}
progerr(ERR_INVALID_O_OPTION, p);
continue;
}
break;
case 'o':
non_abi_scripts++;
break;
case 'p':
dparts = ds_getinfo(optarg);
break;
case 'R':
if (!set_inst_root(optarg)) {
progerr(ERR_ROOT_CMD);
exit(1);
}
break;
case 'r':
respfile = flex_device(optarg, 2);
break;
case 'S':
suppressCopyright++;
break;
case 't':
disable_spool_create();
break;
case 'V':
vfstab_file = flex_device(optarg, 2);
map_client = 1;
break;
case 'v':
pkgverbose++;
break;
case 'y':
set_nonABI_symlinks();
break;
case 'z':
saveSpoolInstall++;
break;
default:
usage();
return (1);
}
}
(void) echoDebugSetFlag(debugFlag);
(void) log_set_verbose(debugFlag);
if (z_running_in_global_zone()) {
echoDebug(DBG_ENTRY_IN_GZ, prog_full_name);
} else {
echoDebug(DBG_ENTRY_IN_LZ, prog_full_name, getzoneid(),
z_get_zonename());
}
if (in_continue_mode() && !in_dryrun_mode()) {
progerr(ERR_LIVE_CONTINUE_NOT_SUPPORTED);
usage();
}
if (askflag && (respfile == NULL)) {
usage();
}
if (device) {
if (pkgdev.mount) {
pkgdev.bdevice = device;
} else {
pkgdev.cdevice = device;
}
}
if (pkgdev.fstyp && !pkgdev.mount) {
progerr(ERR_F_REQUIRES_M);
usage();
}
cont_file_read = B_FALSE;
if (in_continue_mode()) {
int error;
cont_file_read = read_continuation(&error);
if (error == -1) {
quit(99);
}
if (!in_dryrun_mode()) {
live_continue = 1;
}
}
if (!cont_file_read) {
if (get_mntinfo(map_client, vfstab_file)) {
quit(99);
}
}
set_PKGpaths(get_inst_root());
if (is_an_inst_root()) {
int fsys_value;
fsys_value = fsys(get_PKGLOC());
if (use_srvr_map_n(fsys_value))
set_PKGLOC(server_map(get_PKGLOC(), fsys_value));
fsys_value = fsys(get_PKGADM());
if (use_srvr_map_n(fsys_value))
set_PKGADM(server_map(get_PKGADM(), fsys_value));
}
set_infoloc(get_PKGLOC());
switch (argc-optind) {
case 0:
progerr(ERR_MISSING_DIR_AND_PKG);
usage();
case 1:
progerr(ERR_MISSING_PKG_INSTANCE);
usage();
case 2:
pkgdev.dirname = argv[optind++];
srcinst = argv[optind++];
break;
default:
progerr(ERR_TOO_MANY_CMD_ARGS);
usage();
break;
}
(void) pkgparam(NULL, NULL);
if (!askflag && !live_continue) {
echoDebug(DBG_PKGINSTALL_ADMINFILE, admnfile ? admnfile : "");
setadminFile(admnfile);
}
if (preinstallCheck == B_TRUE) {
(void) echoSetFlag(B_FALSE);
echoDebug(DBG_PKGINSTALL_PREINSCHK,
pkginst ? pkginst : (srcinst ? srcinst : ""),
zoneName ? zoneName : "global");
cksetPreinstallCheck(B_TRUE);
cksetZoneName(zoneName);
quitSetInstallStarted(B_TRUE);
}
if (ADMSET(RSCRIPTALT)) {
p = adm.RSCRIPTALT;
echoDebug(DBG_PKGINSTALL_RSCRIPT_SET_TO, RSCRIPTALT_KEYWORD, p);
if (strcasecmp(p, RSCRIPTALT_ROOT) == 0) {
run_request_as_root = B_TRUE;
} else if (strcasecmp(p, RSCRIPTALT_NOACCESS) == 0) {
run_request_as_root = B_FALSE;
} else {
logerr(WRN_RSCRIPTALT_BAD, RSCRIPTALT_KEYWORD, p,
RSCRIPTALT_ROOT, RSCRIPTALT_NOACCESS);
logerr(WRN_RSCRIPTALT_USING, RSCRIPTALT_KEYWORD,
RSCRIPTALT_NOACCESS);
run_request_as_root = B_FALSE;
}
} else {
echoDebug(DBG_PKGINSTALL_RSCRIPT_NOT_SET, RSCRIPTALT_KEYWORD);
run_request_as_root = B_FALSE;
}
echoDebug(DBG_PKGINSTALL_RSCRIPT_IS_ROOT, run_request_as_root);
(void) sighold(SIGHUP);
(void) sighold(SIGINT);
nact.sa_handler = quitGetTrapHandler();
nact.sa_flags = SA_RESTART;
(void) sigemptyset(&nact.sa_mask);
(void) sigaction(SIGINT, &nact, &oact);
nact.sa_handler = quitGetTrapHandler();
nact.sa_flags = SA_RESTART;
(void) sigemptyset(&nact.sa_mask);
(void) sigaction(SIGHUP, &nact, &oact);
(void) sigrelse(SIGHUP);
(void) sigrelse(SIGINT);
ckdirs();
tzset();
pt = getenv("TMPDIR");
(void) snprintf(tmpdir, sizeof (tmpdir), "%s/installXXXXXX",
((pt != (char *)NULL) && (*pt != '\0')) ? pt : P_tmpdir);
echoDebug(DBG_PKGINSTALL_TMPDIR, tmpdir);
if ((mktemp(tmpdir) == NULL) || mkdir(tmpdir, 0771)) {
progerr(ERR_MKDIR, tmpdir);
quit(99);
}
if ((isdir(pkgdev.dirname) != 0) &&
(pkgdev.cdevice == (char *)NULL) &&
(pkgdev.bdevice == (char *)NULL) &&
(isfile((char *)NULL, pkgdev.dirname) == 0)) {
char *idsName = (char *)NULL;
char *pkgnames[2];
char *device = pkgdev.dirname;
boolean_t b;
echoDebug(DBG_PKGINSTALL_DS_ISFILE, pkgdev.dirname);
if (devtype(device, &pkgdev)) {
progerr(ERR_BAD_DEVICE, device);
quit(99);
}
pkgnames[0] = srcinst;
pkgnames[1] = (char *)NULL;
b = open_package_datastream(1, pkgnames, (char *)NULL,
pkgdev.dirname, (int *)NULL, &idsName, tmpdir, &pkgdev,
1);
if (b == B_FALSE) {
progerr(ERR_CANNOT_OPEN_PKG_STREAM,
pkgdev.dirname ? pkgdev.dirname : "?");
quit(99);
}
quitSetDstreamTmpdir(pkgdev.dirname);
b = unpack_package_from_stream(idsName, srcinst,
pkgdev.dirname);
if (b == B_FALSE) {
progerr(ERR_CANNOT_UNPACK_PKGSTRM,
srcinst ? srcinst : "?",
idsName ? idsName : "?",
pkgdev.dirname ? pkgdev.dirname : "?");
quit(99);
}
echoDebug(DBG_CLOSING_STREAM, idsName, pkgdev.dirname);
(void) ds_close(1);
}
if (snprintf(instdir, PATH_MAX, "%s/%s", pkgdev.dirname, srcinst)
>= PATH_MAX) {
progerr(ERR_SNPRINTF, instdir);
quit(99);
}
zoneName = getenv(PKG_ZONENAME_VARIABLE);
(void) set_env_cbdir();
getuserlocale();
environ = NULL;
putConditionInfo(parentZoneName, parentZoneType);
putuserlocale();
if (init_install) {
putparam("PKG_INIT_INSTALL", "TRUE");
}
if (is_an_inst_root()) {
export_client_env(get_inst_root());
}
if (zoneName != (char *)NULL) {
putparam(PKG_ZONENAME_VARIABLE, zoneName);
}
putparam("INST_DATADIR", pkgdev.dirname);
if (non_abi_scripts) {
putparam("NONABI_SCRIPTS", "TRUE");
}
if (nonABI_symlinks()) {
putparam("PKG_NONABI_SYMLINKS", "TRUE");
}
if (get_ABI_namelngth()) {
putparam("PKG_ABI_NAMELENGTH", "TRUE");
}
if (cmdbin[0] == '\0') {
(void) strlcpy(cmdbin, PKGBIN, sizeof (cmdbin));
}
(void) snprintf(path, sizeof (path), "%s:%s", DEFPATH, cmdbin);
putparam("PATH", path);
putparam("OAMBASE", OAMBASE);
(void) snprintf(p_pkginfo, sizeof (p_pkginfo),
"%s/%s", instdir, PKGINFO);
(void) snprintf(p_pkgmap, sizeof (p_pkgmap),
"%s/%s", instdir, PKGMAP);
abi_nm_ptr = getenv("PKG_ABI_NAMELENGTH");
if (abi_nm_ptr && strncasecmp(abi_nm_ptr, "TRUE", 4) == 0) {
(void) set_ABI_namelngth();
}
if (pkgenv(srcinst, p_pkginfo, p_pkgmap)) {
quit(1);
}
echo("\n%s(%s) %s", pkgname, pkgarch, pkgvers);
if (askflag) {
do_pkgask(run_request_as_root);
}
if (vcfile() == 0) {
quit(99);
}
if (!in_dryrun_mode()) {
if (!lockinst(get_prog_name(), srcinst, "install-initial")) {
quit(99);
}
}
abi_comp_ptr = getenv("NONABI_SCRIPTS");
abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS");
if (abi_comp_ptr && strncasecmp(abi_comp_ptr, "TRUE", 4) == 0) {
script_in = PROC_XSTDIN;
non_abi_scripts = 1;
}
if (abi_sym_ptr && strncasecmp(abi_sym_ptr, "TRUE", 4) == 0) {
set_nonABI_symlinks();
}
if (pt = getenv("MAXINST")) {
maxinst = atol(pt);
}
if (is_depend_pkginfo_DB()) {
pt = getenv(PKG_HOLLOW_VARIABLE);
if ((pt != NULL) && (strncasecmp(pt, "true", 4) == 0)) {
echoDebug(DBG_PKGREMOVE_HOLLOW_ENABLED);
if (disableAttributes) {
disable_attribute_check();
}
setadminSetting("conflict", "nocheck");
setadminSetting("setuid", "nocheck");
setadminSetting("action", "nocheck");
setadminSetting("partial", "nocheck");
setadminSetting("space", "nocheck");
setadminSetting("authentication", "nocheck");
} else {
echoDebug(DBG_PKGREMOVE_HOLLOW_DISABLED);
set_depend_pkginfo_DB(B_FALSE);
}
}
if (saveSpoolInstall && (!is_depend_pkginfo_DB())) {
set_partial_inst();
} else {
saveSpoolInstall = 0;
}
if (pt = getenv("INTONLY")) {
if (askflag || nointeract) {
progerr(ERR_INTONLY, pkgabrv ? pkgabrv : "?");
quit(1);
}
}
if (!suppressCopyright && !pkgdev.cdevice) {
copyright();
}
prvinfo = (struct pkginfo *)calloc(MALSIZ, sizeof (struct pkginfo));
if (prvinfo == NULL) {
progerr(ERR_MEMORY, errno);
quit(99);
}
for (;;) {
if (pkginfo(&prvinfo[npkgs], pkgwild, NULL, NULL)) {
if ((errno == ESRCH) || (errno == ENOENT)) {
break;
}
progerr(ERR_SYSINFO, errno);
quit(99);
}
if ((++npkgs % MALSIZ) == 0) {
prvinfo = (struct pkginfo *)realloc(prvinfo,
(npkgs+MALSIZ) * sizeof (struct pkginfo));
if (prvinfo == NULL) {
progerr(ERR_MEMORY, errno);
quit(99);
}
}
}
pkginst = getinst(&update, prvinfo, npkgs, preinstallCheck);
if (update) {
setUpdate();
}
if (saveSpoolInstall != 0 && !isUpdate()) {
putparam("UPDATE", "");
}
quitSetUpdatingExisting(update ? B_TRUE : B_FALSE);
if (respfile) {
(void) set_respfile(respfile, pkginst, RESP_RO);
}
(void) snprintf(pkgloc, sizeof (pkgloc),
"%s/%s", get_PKGLOC(), pkginst);
(void) snprintf(pkgbin, sizeof (pkgbin),
"%s/install", pkgloc);
(void) snprintf(pkgsav, sizeof (pkgsav),
"%s/save", pkgloc);
if (snprintf(saveSpoolInstallDir, PATH_MAX, "%s/pspool/%s", pkgsav,
pkginst) < 0) {
progerr(ERR_SNPRINTF, saveSpoolInstallDir);
quit(99);
}
(void) snprintf(ilockfile, sizeof (ilockfile),
"%s/!I-Lock!", pkgloc);
(void) snprintf(rlockfile, sizeof (rlockfile),
"%s/!R-Lock!", pkgloc);
(void) snprintf(savlog, sizeof (savlog),
"%s/logs/%s", get_PKGADM(), pkginst);
putparam("PKGINST", pkginst);
putparam("PKGSAV", pkgsav);
put_path_params();
if (!map_client) {
putparam("PKG_NO_UNIFIED", "TRUE");
}
if (map_client && !mount_client()) {
logerr(MSG_MANMOUNT);
}
if ((preinstallCheck == B_FALSE) && (update)) {
if (is_samepkg()) {
if (n = merg_pkginfos(pclass, &mergd_pclass)) {
quit(n);
}
if (n = cp_pkgdirs()) {
quit(n);
}
} else {
if (n = ck_instbase()) {
quit(n);
}
if (n = mv_pkgdirs()) {
quit(n);
}
}
putparam("UPDATE", "yes");
}
if (in_dryrun_mode()) {
set_dryrun_dir_loc();
}
if (preinstallCheck == B_FALSE) {
ck_w_dryrun(ckpartial, PARTIAL);
ck_w_dryrun(ckrunlevel, RUNLEVEL);
} else {
int r;
r = ckpartial();
(void) fprintf(stdout, "ckpartialinstall=%d\n", r == 8 ? 1 : 0);
(void) fprintf(stdout, "ckpartialremove=%d\n", r == 9 ? 1 : 0);
r = ckrunlevel();
(void) fprintf(stdout, "ckrunlevel=%d\n", r);
}
if (pkgdev.cdevice) {
unpack();
if (!suppressCopyright) {
copyright();
}
}
lockupd("request");
if ((!rdonly_respfile()) && (preinstallCheck == B_FALSE)) {
(void) snprintf(path, sizeof (path),
"%s/%s", instdir, REQUEST_FILE);
n = reqexec(update, path, non_abi_scripts,
run_request_as_root);
if (in_dryrun_mode()) {
set_dr_info(REQUESTEXITCODE, n);
}
ckreturn(n, ERR_REQUEST);
}
if ((is_a_respfile()) && (preinstallCheck == B_FALSE)) {
if (n = merg_respfile()) {
quit(n);
}
}
lockupd("checkinstall");
(void) snprintf(script, sizeof (script), "%s/install/checkinstall",
instdir);
if (access(script, F_OK) != 0) {
echoDebug(DBG_PKGINSTALL_COC_NONE, pkginst, script,
zoneName ? zoneName : "global");
} else if (is_depend_pkginfo_DB()) {
echoDebug(DBG_PKGINSTALL_COC_DBUPD, pkginst, script,
zoneName ? zoneName : "global");
} else if (preinstallCheck == B_TRUE) {
echoDebug(DBG_PKGINSTALL_COC_NODEL, pkginst, script,
zoneName ? zoneName : "global");
} else {
if (zoneName == (char *)NULL) {
echo(MSG_PKGINSTALL_EXECOC_GZ);
echoDebug(DBG_PKGINSTALL_EXECOC_GZ, pkginst, script);
} else {
echo(MSG_PKGINSTALL_EXECOC_LZ, zoneName);
echoDebug(DBG_PKGINSTALL_EXECOC_LZ, pkginst, script,
zoneName);
}
n = chkexec(update, script);
if (in_dryrun_mode()) {
set_dr_info(CHECKEXITCODE, n);
}
if (n == 3) {
echo(WRN_CHKINSTALL);
ckreturn(4, NULL);
} else if (n == 7) {
progerr(ERR_CHKINSTALL_NOSCRIPT, script);
ckreturn(4, ERR_CHKINSTALL);
} else {
ckreturn(n, ERR_CHKINSTALL);
}
}
if (pkgdrtarg) {
init_dryrunfile(pkgdrtarg);
}
if (is_a_respfile()) {
if (n = merg_respfile()) {
quit(n);
}
}
lockupd("analysis");
if ((err = set_basedirs(isreloc(instdir), adm.basedir, pkginst,
nointeract)) != 0) {
quit(err);
}
if (!is_depend_pkginfo_DB() &&
!preinstallCheck && is_a_basedir()) {
mkbasedir(!nointeract, get_basedir());
echo(MSG_BASE_USED, get_basedir());
}
put_path_params();
if (ADM(setuid, "nochange")) {
nosetuid++;
}
if (ADM(conflict, "nochange")) {
nocnflct++;
}
svfsb.f_bsize = 8192;
svfsb.f_frsize = 1024;
if (statvfs64(get_PKGADM(), &svfsb) == -1) {
int lerrno = errno;
if (!access(get_PKGADM(), F_OK)) {
progerr(ERR_PKGINSTALL_STATVFS, get_PKGADM(),
strerror(errno));
logerr("(errno %d)", lerrno);
quit(99);
}
}
if (stat(p_pkgmap, &statb) == -1) {
progerr(ERR_PKGINSTALL_STATOF, p_pkgmap, strerror(errno));
quit(99);
}
pkgmap_blks = nblk(statb.st_size, svfsb.f_bsize, svfsb.f_frsize);
if (in_dryrun_mode()) {
if (n = set_cfdir(pkgdrtarg)) {
quit(n);
}
} else {
if (n = set_cfdir(NULL)) {
quit(n);
}
}
if (!ocfile(&pkgserver, &cfTmpVfp, pkgmap_blks)) {
quit(99);
}
for (np = cpio_names; *np != NULL; np++) {
(void) snprintf(path, sizeof (path),
"%s/%s", instdir, *np);
if (iscpio(path, &is_comp_arch)) {
is_WOS_arch();
break;
}
}
cl_sets(getenv("CLASSES"));
find_CAS(I_ONLY, pkgbin, instdir);
if (vfpOpen(&pkgmapVfp, p_pkgmap, "r", VFP_NEEDNOW) != 0) {
progerr(ERR_PKGMAP, p_pkgmap);
quit(99);
}
nparts = sortmap(&extlist, pkgmapVfp, pkgserver, cfTmpVfp, zoneName);
if ((n = files_installed()) > 0) {
if (n > 1) {
echo(MSG_INST_MANY, n);
} else {
echo(MSG_INST_ONE, n);
}
}
if (pt = getenv("ULIMIT")) {
if (assign_ulimit(pt) == -1) {
progerr(ERR_BADULIMIT, pt);
quit(99);
}
putparam("PKG_ULIMIT", "TRUE");
}
if (preinstallCheck == B_TRUE) {
lockupd("preinstallcheck");
(void) fprintf(stdout, "ckpkgfiles=%d\n", ckpkgfiles());
(void) fprintf(stdout, "ckdepend=%d\n", ckdepend());
(void) fprintf(stdout, "ckspace=%d\n", ckspace());
(void) fprintf(stdout, "ckconflict=%d\n", ckconflct());
(void) fprintf(stdout, "cksetuid=%d\n", cksetuid());
(void) fprintf(stdout, "ckpriv=%d\n", ckpriv());
(void) fprintf(stdout, "ckpkgdirs=%d\n", ckpkgdirs());
echoDebug(DBG_PKGINSTALL_PREINSCHK_OK);
quit(0);
}
ck_w_dryrun(ckpkgfiles, PKGFILES);
ck_w_dryrun(ckdepend, DEPEND);
ck_w_dryrun(ckspace, SPACE);
ck_w_dryrun(ckconflct, CONFLICT);
ck_w_dryrun(cksetuid, SETUID);
ck_w_dryrun(ckpriv, PRIV);
ck_w_dryrun(ckpkgdirs, PKGDIRS);
if (rprcflag) {
nparts = sortmap(&extlist, pkgmapVfp, pkgserver,
cfTmpVfp, zoneName);
}
(void) vfpClose(&pkgmapVfp);
if (in_dryrun_mode()) {
echo(MSG_PKGINSTALL_DRYRUN, pkgname, pkginst);
} else if (zoneName == (char *)NULL) {
echo(MSG_PKGINSTALL_INSIN_GZ, pkgname, pkginst);
} else {
echo(MSG_PKGINSTALL_INSIN_LZ, pkgname, pkginst, zoneName);
}
quitSetInstallStarted(B_TRUE);
n = swapcfile(pkgserver, &cfTmpVfp, pkginst, dbchg);
if (n == RESULT_WRN) {
warnflag++;
} else if (n == RESULT_ERR) {
quit(99);
}
if (access(ilockfile, F_OK) == 0) {
(void) remove(ilockfile);
}
if (open(ilockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644) < 0) {
progerr(ERR_LOCKFILE, ilockfile);
quit(99);
}
(void) time(&clock);
temp = setlocale(LC_TIME, NULL);
(void) setlocale(LC_TIME, "C");
(void) cftime(cbuf, "%b %d \045Y \045H:\045M", &clock);
putparam("INSTDATE", qstrdup(cbuf));
(void) setlocale(LC_TIME, temp);
merginfo(mergd_pclass, saveSpoolInstall);
if (in_dryrun_mode()) {
quit(0);
}
lockupd("preinstall");
(void) snprintf(altscript, sizeof (altscript), "%s/install/preinstall",
instdir);
(void) snprintf(script, sizeof (script), "%s/preinstall", pkgbin);
if (access(altscript, F_OK) != 0) {
echoDebug(DBG_PKGINSTALL_POCALT_NONE, pkginst, altscript,
zoneName ? zoneName : "global");
} else if (access(script, F_OK) != 0) {
echoDebug(DBG_PKGINSTALL_POC_NONE, pkginst, script,
zoneName ? zoneName : "global");
} else if (is_depend_pkginfo_DB()) {
echoDebug(DBG_PKGINSTALL_POC_DBUPD, pkginst, script,
zoneName ? zoneName : "global");
} else {
assert(preinstallCheck == B_FALSE);
set_ulimit("preinstall", ERR_PREINSTALL);
if (zoneName == (char *)NULL) {
echo(MSG_PKGINSTALL_EXEPOC_GZ);
echoDebug(DBG_PKGINSTALL_EXEPOC_GZ, pkginst, script);
} else {
echo(MSG_PKGINSTALL_EXEPOC_LZ, zoneName);
echoDebug(DBG_PKGINSTALL_EXEPOC_LZ, pkginst, script,
zoneName);
}
putparam("PKG_PROC_script", "preinstall");
if (pkgverbose) {
ckreturn(pkgexecl(script_in, PROC_STDOUT,
PROC_USER, PROC_GRP, SHELL, "-x",
script, NULL), ERR_PREINSTALL);
} else {
ckreturn(pkgexecl(script_in, PROC_STDOUT,
PROC_USER, PROC_GRP, SHELL, script,
NULL), ERR_PREINSTALL);
}
clr_ulimit();
(void) remove(script);
}
(void) snprintf(script, sizeof (script),
"%s/install/postinstall", instdir);
if (access(script, F_OK) == 0) {
(void) snprintf(script, sizeof (script),
"%s/postinstall", pkgbin);
} else {
script[0] = '\0';
}
lockupd("install");
part = 1;
while (part <= nparts) {
if ((part > 1) && pkgdev.cdevice) {
unpack();
}
instvol(extlist, srcinst, part, nparts,
pkgserver, &cfTmpVfp, &updated, zoneName);
if (part++ >= nparts) {
break;
}
}
z_destroyMountTable();
rm_icas(pkgbin);
if (globalZoneOnly) {
boolean_t b;
b = pkgAddPackageToGzonlyList(pkginst, get_inst_root());
if (b == B_FALSE) {
progerr(ERR_PKGINSTALL_GZONLY_ADD, pkginst);
ckreturn(1, NULL);
}
}
echoDebug(DBG_PKGINSTALL_INSDONE, is_depend_pkginfo_DB(),
is_depend_pkginfo_DB(), saveSpoolInstall,
updated ? updated : "",
script ? script : "",
script ? access(script, F_OK) : -1);
lockupd("postinstall");
if ((script == (char *)NULL) || (*script == '\0')) {
echoDebug(DBG_PKGINSTALL_POIS_NOPATH, pkginst,
zoneName ? zoneName : "global");
} else if (access(script, F_OK) != 0) {
echoDebug(DBG_PKGINSTALL_POIS_NONE, pkginst, script,
zoneName ? zoneName : "global");
} else if (is_depend_pkginfo_DB()) {
echoDebug(DBG_PKGINSTALL_POIS_DBUPD, pkginst, script,
zoneName ? zoneName : "global");
} else if ((saveSpoolInstall != 0) && (updated == (char *)NULL)) {
echoDebug(DBG_PKGINSTALL_POIS_NOUPDATING,
zoneName ? zoneName : "global", pkginst, script);
} else {
set_ulimit("postinstall", ERR_POSTINSTALL);
if (zoneName == (char *)NULL) {
echo(MSG_PKGINSTALL_EXEPIC_GZ);
echoDebug(DBG_PKGINSTALL_EXEPIC_GZ, pkginst, script);
} else {
echo(MSG_PKGINSTALL_EXEPIC_LZ, zoneName);
echoDebug(DBG_PKGINSTALL_EXEPIC_LZ, pkginst, script,
zoneName);
}
putparam("PKG_PROC_SCRIPT", "postinstall");
putparam("TMPDIR", tmpdir);
if (pkgverbose) {
ckreturn(pkgexecl(script_in, PROC_STDOUT,
PROC_USER, PROC_GRP, SHELL, "-x",
script, NULL), ERR_POSTINSTALL);
} else {
ckreturn(pkgexecl(script_in, PROC_STDOUT,
PROC_USER, PROC_GRP, SHELL, script,
NULL), ERR_POSTINSTALL);
}
clr_ulimit();
(void) remove(script);
}
if (!warnflag && !failflag) {
(void) remove(rlockfile);
(void) remove(ilockfile);
(void) remove(savlog);
}
(void) unlockinst();
pkgcloseserver(pkgserver);
quit(0);
}
static int
merg_respfile()
{
int retcode = 0;
char *resppath = get_respfile();
char *locbasedir;
char param[MAX_PKG_PARAM_LENGTH], *value;
FILE *fp;
if ((fp = fopen(resppath, "r")) == NULL) {
progerr(ERR_RESPONSE, resppath);
return (99);
}
param[0] = '\0';
while (value = fpkgparam(fp, param)) {
if (!isupper(param[0])) {
param[0] = '\0';
continue;
}
if (rdonly(param)) {
progerr(ERR_RDONLY, param);
param[0] = '\0';
continue;
}
if (update && strcmp("BASEDIR", param) == 0) {
locbasedir = getenv("BASEDIR");
if (locbasedir && strcmp(value, locbasedir) != 0) {
char *dotptr;
if (dotptr = strchr(srcinst, '.'))
*dotptr = '\000';
progerr(ERR_NEWBD, srcinst,
locbasedir, value);
retcode = 99;
}
}
putparam(param, value);
param[0] = '\0';
}
(void) fclose(fp);
return (retcode);
}
static int
ck_instbase(void)
{
int retcode = 0;
char param[MAX_PKG_PARAM_LENGTH], *value;
char pkginfo_path[PATH_MAX];
FILE *fp;
(void) snprintf(pkginfo_path, sizeof (pkginfo_path),
"%s/%s", pkgloc, PKGINFO);
if ((fp = fopen(pkginfo_path, "r")) == NULL) {
progerr(ERR_PKGINFO, pkginfo_path);
return (99);
}
param[0] = '\000';
while (value = fpkgparam(fp, param)) {
if (strcmp("BASEDIR", param) == 0) {
if (adm.basedir && *(adm.basedir) &&
strchr("/$", *(adm.basedir))) {
char *dotptr;
if (dotptr = strchr(srcinst, '.'))
*dotptr = '\000';
if (strcmp(value,
adm.basedir) != 0) {
progerr(ERR_ADMBD, srcinst,
value, adm.basedir);
retcode = 4;
break;
}
} else if (ADM(basedir, "ask"))
adm.basedir = "update";
putparam(param, value);
break;
}
param[0] = '\0';
}
(void) fclose(fp);
return (retcode);
}
static int
mv_pkgdirs(void)
{
if (!in_dryrun_mode() && pkgloc[0] && !access(pkgloc, F_OK)) {
(void) snprintf(pkgloc_sav, sizeof (pkgloc_sav),
"%s/.save.%s", get_PKGLOC(),
pkginst);
if (pkgloc_sav[0] && !access(pkgloc_sav, F_OK)) {
(void) rrmdir(pkgloc_sav);
}
if (rename(pkgloc, pkgloc_sav) == -1) {
progerr(ERR_PKGBINREN, pkgloc, pkgloc_sav);
return (99);
}
}
return (0);
}
static int
merg_pkginfos(struct cl_attr **pclass, struct cl_attr ***mpclass)
{
FILE *fp;
char SUNW_PKG_ALLZONES[MAX_PKG_PARAM_LENGTH] = {'\0'};
char SUNW_PKG_HOLLOW[MAX_PKG_PARAM_LENGTH] = {'\0'};
char SUNW_PKG_THISZONE[MAX_PKG_PARAM_LENGTH] = {'\0'};
char *newValue;
char *oldValue;
char *pkgName;
char *pkgVersion;
char param[MAX_PKG_PARAM_LENGTH];
char pkginfo_path[PATH_MAX];
int retcode = 0;
pkgName = getenv("PKG");
if (pkgName == NULL) {
pkgName = "*current*";
}
pkgVersion = getenv("VERSION");
if (pkgVersion == NULL) {
pkgVersion = "*current*";
}
(void) snprintf(pkginfo_path, sizeof (pkginfo_path),
"%s/%s", pkgloc, PKGINFO);
if ((fp = fopen(pkginfo_path, "r")) == NULL) {
progerr(ERR_PKGINFO, pkginfo_path);
return (99);
}
echoDebug(DBG_MERGINFOS_ENTRY, pkginfo_path);
for (param[0] = '\0'; (oldValue = fpkgparam(fp, param)) != NULL;
param[0] = '\0') {
boolean_t setZoneAttribute = B_FALSE;
echoDebug(DBG_MERGINFOS_SET_TO, param, oldValue);
if (strcmp(param, PKG_THISZONE_VARIABLE) == 0) {
setZoneAttribute = B_TRUE;
(void) strlcpy(SUNW_PKG_THISZONE, oldValue,
sizeof (SUNW_PKG_THISZONE));
} else if (strcmp(param, PKG_ALLZONES_VARIABLE) == 0) {
setZoneAttribute = B_TRUE;
(void) strlcpy(SUNW_PKG_ALLZONES, oldValue,
sizeof (SUNW_PKG_ALLZONES));
} else if (strcmp(param, PKG_HOLLOW_VARIABLE) == 0) {
setZoneAttribute = B_TRUE;
(void) strlcpy(SUNW_PKG_HOLLOW, oldValue,
sizeof (SUNW_PKG_HOLLOW));
}
if (strcmp(param, "CLASSES") == 0) {
echoDebug(DBG_MERGINFOS_SET_CLASSES, oldValue);
(void) setlist(&pclass, qstrdup(oldValue));
*mpclass = pclass;
continue;
}
if (strcmp("BASEDIR", param) == 0) {
if (adm.basedir && *(adm.basedir) &&
strchr("/$", *(adm.basedir))) {
char *dotptr;
if (dotptr = strchr(srcinst, '.')) {
*dotptr = '\000';
}
if (strcmp(oldValue, adm.basedir) != 0) {
progerr(ERR_ADMBD, srcinst,
oldValue, adm.basedir);
retcode = 4;
break;
}
} else if (ADM(basedir, "ask")) {
adm.basedir = "update";
echoDebug(DBG_MERGINFOS_ASK_BASEDIR);
}
echoDebug(DBG_MERGINFOS_SET_BASEDIR, oldValue);
putparam(param, oldValue);
continue;
}
newValue = getenv(param);
if ((newValue == NULL) &&
(setZoneAttribute == B_TRUE) &&
(strcasecmp(oldValue, "false") != 0)) {
progerr(ERR_MERGINFOS_UNSET_ZONEATTR,
pkgName, pkgVersion, param, oldValue);
retcode = 1;
break;
}
if (newValue == NULL) {
echoDebug(DBG_MERGINFOS_RETAIN_OLD, param, oldValue);
putparam(param, oldValue);
continue;
}
if (strcmp(newValue, oldValue) == 0) {
echoDebug(DBG_MERGINFOS_SET_DUPLICATE, param, oldValue);
continue;
}
if (setZoneAttribute == B_TRUE) {
progerr(ERR_MERGINFOS_CHANGE_ZONEATTR, pkgName,
pkgVersion, param, oldValue, newValue);
retcode = 1;
break;
}
echoDebug(DBG_MERGINFOS_SET_CHANGE, param,
oldValue, newValue);
}
(void) fclose(fp);
if (retcode != 0) {
echoDebug(DBG_MERGINFOS_EXIT, pkginfo_path, retcode);
return (retcode);
}
newValue = getenv(PKG_ALLZONES_VARIABLE);
if ((newValue != NULL) && (*SUNW_PKG_ALLZONES == '\0') &&
(strcasecmp(newValue, "false") != 0)) {
progerr(ERR_MERGINFOS_SET_ZONEATTR, pkgName,
pkgVersion, PKG_ALLZONES_VARIABLE, newValue);
return (1);
}
newValue = getenv(PKG_THISZONE_VARIABLE);
if ((newValue != NULL) && (*SUNW_PKG_THISZONE == '\0') &&
(strcasecmp(newValue, "false") != 0)) {
progerr(ERR_MERGINFOS_SET_ZONEATTR, pkgName,
pkgVersion, PKG_THISZONE_VARIABLE, newValue);
return (1);
}
newValue = getenv(PKG_HOLLOW_VARIABLE);
if ((newValue != NULL) && (*SUNW_PKG_HOLLOW == '\0') &&
(strcasecmp(newValue, "false") != 0)) {
progerr(ERR_MERGINFOS_SET_ZONEATTR, pkgName,
pkgVersion, PKG_HOLLOW_VARIABLE, newValue);
return (1);
}
echoDebug(DBG_MERGINFOS_EXIT, pkginfo_path, 0);
return (0);
}
static void
set_dryrun_dir_loc(void)
{
set_PKGLOC(pkgdrtarg);
(void) snprintf(pkgloc, sizeof (pkgloc),
"%s/%s", get_PKGLOC(), pkginst);
(void) snprintf(pkgbin, sizeof (pkgbin),
"%s/install", pkgloc);
(void) snprintf(pkgsav, sizeof (pkgsav),
"%s/save", pkgloc);
(void) snprintf(ilockfile, sizeof (ilockfile),
"%s/!I-Lock!", pkgloc);
(void) snprintf(rlockfile, sizeof (rlockfile),
"%s/!R-Lock!", pkgloc);
(void) snprintf(savlog, sizeof (savlog),
"%s/logs/%s", get_PKGADM(), pkginst);
}
static int
cp_pkgdirs(void)
{
if (in_dryrun_mode()) {
set_dryrun_dir_loc();
}
if (!in_dryrun_mode() && pkgloc[0] && !access(pkgloc, F_OK)) {
int status;
int r;
(void) snprintf(pkgloc_sav, sizeof (pkgloc_sav), "%s/.save.%s",
get_PKGLOC(), pkginst);
r = e_ExecCmdList(&status, (char **)NULL, (char *)NULL,
"/usr/bin/cp", "cp", "-r", pkgloc, pkgloc_sav,
(char *)NULL);
if ((r != 0) || (status == -1) || (WEXITSTATUS(status) != 0)) {
progerr(ERR_PKGBINCP, pkgloc, pkgloc_sav);
return (99);
}
}
return (0);
}
static void
do_pkgask(boolean_t a_run_request_as_root)
{
if (pkgdev.cdevice) {
unpack();
if (!suppressCopyright) {
copyright();
}
}
(void) snprintf(path, sizeof (path), "%s/%s", instdir, REQUEST_FILE);
if (access(path, F_OK)) {
progerr(ERR_NOREQUEST);
quit(1);
}
(void) set_respfile(respfile, srcinst, RESP_WR);
if (is_a_respfile()) {
ckreturn(reqexec(update, path, non_abi_scripts,
a_run_request_as_root), ERR_REQUEST);
} else {
failflag++;
}
if (warnflag || failflag) {
(void) remove(respfile);
echo("\nResponse file <%s> was not created.",
get_respfile());
} else {
echo("\nResponse file <%s> was created.",
get_respfile());
}
quit(0);
}
static void
ck_w_dryrun(int (*func)(), int type)
{
int n;
n = func();
if (in_dryrun_mode())
set_dr_info(type, !n);
if (n) {
quit(n);
}
}
static void
rm_icas(char *cas_dir)
{
DIR *pdirfp;
struct dirent *dp;
char path[PATH_MAX];
if ((pdirfp = opendir(cas_dir)) == NULL)
return;
while ((dp = readdir(pdirfp)) != NULL) {
if (dp->d_name[0] == '.')
continue;
if (dp->d_name[0] == 'i' && dp->d_name[1] == '.') {
(void) snprintf(path, sizeof (path),
"%s/%s", cas_dir, dp->d_name);
(void) remove(path);
}
}
(void) closedir(pdirfp);
}
void
ckreturn(int retcode, char *msg)
{
switch (retcode) {
case 2:
case 12:
case 22:
warnflag++;
if (msg) {
progerr("%s", msg);
}
case 10:
case 20:
if (retcode >= 10 && retcode < 20) {
dreboot++;
}
if (retcode >= 20) {
ireboot++;
}
case 0:
break;
case -1:
retcode = 99;
case 99:
case 1:
case 11:
case 21:
case 4:
case 14:
case 24:
case 5:
case 15:
case 25:
if (msg) {
progerr("%s", msg);
}
case 3:
case 13:
case 23:
quit(retcode);
default:
if (msg) {
progerr("%s", msg);
}
quit(1);
}
}
static void
copyright(void)
{
FILE *fp;
char line[LSIZE];
char path[PATH_MAX];
(void) snprintf(path, sizeof (path), "%s/%s", instdir, COPYRIGHT_FILE);
if ((fp = fopen(path, "r")) == NULL) {
if (getenv("VENDOR") != NULL)
echo(getenv("VENDOR"));
} else {
while (fgets(line, LSIZE, fp))
(void) fprintf(stdout, "%s", line);
(void) fclose(fp);
}
}
static int
rdonly(char *p)
{
int i;
for (i = 0; ro_params[i]; i++) {
if (strcmp(p, ro_params[i]) == 0)
return (1);
}
return (0);
}
static void
unpack(void)
{
if (dparts < 1) {
progerr(ERR_DSTREAMCNT);
quit(99);
}
if ((access(instdir, F_OK) == 0) && rrmdir(instdir)) {
progerr(ERR_RMDIR, instdir);
quit(99);
}
if (mkdir(instdir, 0755)) {
progerr(ERR_MKDIR, instdir);
quit(99);
}
if (chdir(instdir)) {
progerr(ERR_CHDIR, instdir);
quit(99);
}
if (!ds_fd_open()) {
dparts = ds_findpkg(pkgdev.cdevice, srcinst);
if (dparts < 1) {
progerr(ERR_DSARCH, srcinst);
quit(99);
}
}
dparts--;
if (ds_next(pkgdev.cdevice, instdir)) {
progerr(ERR_DSTREAM);
quit(99);
}
if (chdir(get_PKGADM())) {
progerr(ERR_CHDIR, get_PKGADM());
quit(99);
}
ds_close(1);
}
static void
usage(void)
{
(void) fprintf(stderr, ERR_USAGE_PKGINSTALL);
exit(1);
}