static int ckinfo(char *inst, char *arch, char *vers) { FILE *fp; char temp[128]; char file[PATH_MAX]; char *pt, *copy, *value, *myarch, *myvers; int errflg; (void) sprintf(file, "%s/%s/pkginfo", pkgdir, inst); if ((fp = fopen(file, "r")) == NULL) return (1); if ((arch == NULL) && (vers == NULL)) { (void) fclose(fp); return (0); } temp[0] = '\0'; myarch = myvers = NULL; while (value = fpkgparam(fp, temp)) { if (strcmp(temp, "ARCH") == 0) { /* remove all whitespace from value */ pt = copy = value; while (*pt) { if (!isspace((unsigned char)*pt)) *copy++ = *pt; pt++; } *copy = '\0'; myarch = value; if (myvers) break; } else if (strcmp(temp, "VERSION") == 0) { myvers = value; if (myarch) break; } else free(value); temp[0] = '\0'; } (void) fclose(fp); errflg = 0; if (ckinst(inst, myarch, myvers, arch, vers)) errflg++; if (myarch) free(myarch); if (myvers) free(myvers); return (errflg); }
void setadminFile(char *file) { FILE *fp; int i; char param[MAX_PKG_PARAM_LENGTH]; char *value; char path[PATH_MAX]; int mail = 0; if (file == NULL) file = "default"; else if (strcmp(file, "none") == 0) { adm.basedir = "ask"; return; } if (file[0] == '/') (void) strcpy(path, file); else { (void) snprintf(path, sizeof (path), "%s/admin/%s", get_PKGADM(), file); if (access(path, R_OK)) { (void) snprintf(path, sizeof (path), "%s/admin/%s", PKGADM, file); } } if ((fp = fopen(path, "r")) == NULL) { progerr(ERR_OPEN_ADMIN_FILE, file, strerror(errno)); quit(99); } param[0] = '\0'; while (value = fpkgparam(fp, param)) { if (strcmp(param, "mail") == 0) { mail = 1; } if (value[0] == '\0') { param[0] = '\0'; continue; /* same as not being set at all */ } for (i = 0; admlist[i].memloc; i++) { if (strcmp(param, admlist[i].tag) == 0) { *admlist[i].memloc = value; break; } } if (admlist[i].memloc == NULL) { logerr(WRN_UNKNOWN_ADM_PARAM, param); free(value); } param[0] = '\0'; } (void) fclose(fp); if (!mail) { adm.mail = DEFMAIL; /* if we don't assign anything to it */ } }
void merginfo(struct cl_attr **pclass, int install_from_pspool) { DIR *pdirfp; FILE *fp; FILE *pkginfoFP; char path[PATH_MAX]; char cmd[PATH_MAX]; char pkginfoPath[PATH_MAX]; char temp[PATH_MAX]; int i; int nc; int out; /* remove savelog from previous attempts */ (void) unlink(savlog); /* * create path to appropriate pkginfo file for the package that is * already installed - is_spool_create() will be set (!= 0) if the * -t option is presented to pkginstall - the -t option is used to * disable save spool area creation; do not spool any partial package * contents, that is, suppress the creation and population of the * package save spool area (var/sadm/pkg/PKG/save/pspool/PKG). This * option is set only when a non-global zone is being created. */ if (is_spool_create() == 0) { /* * normal package install (not a non-global zone install); * use the standard installed pkginfo file for this package: * --> /var/sadm/pkg/PKGINST/pkginfo * as the source pkginfo file to scan. */ i = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/var/sadm/pkg/%s/%s", ((get_inst_root()) && (strcmp(get_inst_root(), "/") != 0)) ? get_inst_root() : "", pkginst, PKGINFO); if (i > sizeof (pkginfoPath)) { progerr(ERR_CREATE_PATH_2, ((get_inst_root()) && (strcmp(get_inst_root(), "/") != 0)) ? get_inst_root() : "/", pkginst); quit(1); } } else { /* * non-global zone installation - use the "saved" pspool * pkginfo file in the global zone for this package: * --> /var/sadm/install/PKG/save/pspool/PKG/pkginfo * as the source pkginfo file to scan. */ i = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/%s", saveSpoolInstallDir, PKGINFO); if (i > sizeof (pkginfoPath)) { progerr(ERR_CREATE_PATH_2, saveSpoolInstallDir, PKGINFO); quit(1); } } i = snprintf(path, PATH_MAX, "%s/%s", pkgloc, PKGINFO); if (i > PATH_MAX) { progerr(ERR_CREATE_PATH_2, pkgloc, PKGINFO); quit(1); } /* entry debugging info */ echoDebug(DBG_MERGINFO_ENTRY, instdir ? instdir : "??", ((get_inst_root()) && (strcmp(get_inst_root(), "/") != 0)) ? get_inst_root() : "??", saveSpoolInstallDir ? saveSpoolInstallDir : "??", pkgloc ? pkgloc : "??", is_spool_create(), get_info_basedir() ? get_info_basedir() : "??", pkginfoPath, path); /* * open the pkginfo file: * if the source pkginfo file to check is the same as the merged one * (e.g. /var/sadm/pkg/PKGINST/pkginfo) then do not open the source * pkginfo file to "verify" */ if (strcmp(pkginfoPath, path) == 0) { pkginfoFP = (FILE *)NULL; echoDebug(DBG_MERGINFO_SAME, path); } else { echoDebug(DBG_MERGINFO_DIFFERENT, pkginfoPath, path); pkginfoFP = fopen(pkginfoPath, "r"); if (pkginfoFP == (FILE *)NULL) { echoDebug(ERR_NO_PKG_INFOFILE, pkginst, pkginfoPath, strerror(errno)); } } /* * output packaging environment to create a pkginfo file in pkgloc[] */ if ((fp = fopen(path, "w")) == NULL) { progerr(ERR_CANNOT_OPEN_FOR_WRITING, path, strerror(errno)); quit(99); } /* * output CLASSES attribute */ out = 0; (void) fputs("CLASSES=", fp); if (pclass) { (void) fputs(pclass[0]->name, fp); out++; for (i = 1; pclass[i]; i++) { (void) putc(' ', fp); (void) fputs(pclass[i]->name, fp); out++; } } nc = cl_getn(); for (i = 0; i < nc; i++) { int found = 0; if (pclass) { int j; for (j = 0; pclass[j]; ++j) { if (cl_nam(i) != NULL && strcmp(cl_nam(i), pclass[j]->name) == 0) { found++; break; } } } if (!found) { if (out > 0) { (void) putc(' ', fp); } (void) fputs(cl_nam(i), fp); out++; } } (void) putc('\n', fp); /* * NOTE : BASEDIR below is relative to the machine that * *runs* the package. If there's an install root, this * is actually the CLIENT_BASEDIR wrt the machine * doing the pkgadd'ing here. -- JST */ if (is_a_basedir()) { static char *txs1 = "BASEDIR="; (void) fputs(txs1, fp); (void) fputs(get_info_basedir(), fp); (void) putc('\n', fp); } else { (void) fputs("BASEDIR=/", fp); (void) putc('\n', fp); } /* * output all other environment attributes except those which * are relevant only to install. */ for (i = 0; environ[i] != (char *)NULL; i++) { char *ep = environ[i]; int attrPos = -1; int incr = (ATTRTBL_SIZE >> 1)+1; /* searches possible */ int pos = ATTRTBL_SIZE >> 1; /* start in middle */ NAMELIST_T *pp = (NAMELIST_T *)NULL; /* * find this attribute in the table - accept the attribute if it * is outside of the bounds of the table; otherwise, do a binary * search looking for this attribute. */ if (strncmp(ep, attrTbl[0]._nlName, attrTbl[0]._nlLen) < 0) { /* entry < first entry in attribute table */ echoDebug(DBG_MERGINFO_LESS_THAN, ep, attrTbl[0]._nlName); } else if (strncmp(ep, attrTbl[ATTRTBL_SIZE-1]._nlName, attrTbl[ATTRTBL_SIZE-1]._nlLen) > 0) { /* entry > last entry in attribute table */ echoDebug(DBG_MERGINFO_GREATER_THAN, ep, attrTbl[ATTRTBL_SIZE-1]._nlName); } else { /* first entry < entry < last entry in table: search */ echoDebug(DBG_MERGINFO_SEARCHING, ep, attrTbl[0]._nlName, attrTbl[ATTRTBL_SIZE-1]._nlName); while (incr > 0) { /* while possible to divide */ int r; pp = &attrTbl[pos]; /* compare current attr with this table entry */ r = strncmp(pp->_nlName, ep, pp->_nlLen); /* break out of loop if match */ if (r == 0) { /* save location/break if match found */ attrPos = pos; break; } /* no match search to next/prev half */ incr = incr >> 1; pos += (r < 0) ? incr : -incr; continue; } } /* handle excluded attribute found */ if ((attrPos >= 0) && (pp->_nlFlag == FLAG_EXCLUDE)) { /* attribute is excluded */ echoDebug(DBG_MERGINFO_EXCLUDING, ep); continue; } /* handle fixed attribute found */ if ((pkginfoFP != (FILE *)NULL) && (attrPos >= 0) && (pp->_nlFlag == FLAG_IDENTICAL)) { /* attribute must not change */ char *src = ep+pp->_nlLen; char *trg; char theAttr[PATH_MAX+1]; /* isolate attribute name only without '=' at end */ (void) strncpy(theAttr, pp->_nlName, pp->_nlLen-1); theAttr[pp->_nlLen-1] = '\0'; /* lookup attribute in installed package pkginfo file */ rewind(pkginfoFP); trg = fpkgparam(pkginfoFP, theAttr); echoDebug(DBG_MERGINFO_ATTRCOMP, theAttr, trg ? trg : ""); /* if target not found attribute is being added */ if (trg == (char *)NULL) { progerr(ERR_PKGINFO_ATTR_ADDED, pkginst, ep); quit(1); } /* error if two values are not the same */ if (strcmp(src, trg) != 0) { progerr(ERR_PKGINFO_ATTR_CHANGED, pkginst, theAttr, src, trg); quit(1); } } /* attribute not excluded/has not changed - process */ if ((strncmp(ep, "PKGSAV=", 7) == 0)) { (void) fputs("PKGSAV=", fp); (void) fputs(infoloc, fp); (void) putc('/', fp); (void) fputs(pkginst, fp); (void) fputs("/save\n", fp); continue; } if ((strncmp(ep, "UPDATE=", 7) == 0) && install_from_pspool != 0 && !isPatchUpdate() && !isUpdate()) { continue; } echoDebug(DBG_MERGINFO_FINAL, ep); (void) fputs(ep, fp); (void) putc('\n', fp); } (void) fclose(fp); (void) fclose(pkginfoFP); /* * copy all packaging scripts to appropriate directory */ i = snprintf(path, PATH_MAX, "%s/install", instdir); if (i > PATH_MAX) { progerr(ERR_CREATE_PATH_2, instdir, "/install"); quit(1); } if ((pdirfp = opendir(path)) != NULL) { struct dirent *dp; while ((dp = readdir(pdirfp)) != NULL) { if (dp->d_name[0] == '.') continue; i = snprintf(path, PATH_MAX, "%s/install/%s", instdir, dp->d_name); if (i > PATH_MAX) { progerr(ERR_CREATE_PATH_3, instdir, "/install/", dp->d_name); quit(1); } i = snprintf(temp, PATH_MAX, "%s/%s", pkgbin, dp->d_name); if (i > PATH_MAX) { progerr(ERR_CREATE_PATH_2, pkgbin, dp->d_name); quit(1); } if (cppath(MODE_SRC|DIR_DISPLAY, path, temp, 0644)) { progerr(ERR_CANNOT_COPY, dp->d_name, pkgbin); quit(99); } } (void) closedir(pdirfp); } /* * copy all packaging scripts to the partial spool directory */ if (!is_spool_create()) { /* packages are being spooled to ../save/pspool/.. */ i = snprintf(path, PATH_MAX, "%s/install", instdir); if (i > PATH_MAX) { progerr(ERR_CREATE_PATH_2, instdir, "/install"); quit(1); } if (((pdirfp = opendir(path)) != NULL) && !isPatchUpdate()) { struct dirent *dp; while ((dp = readdir(pdirfp)) != NULL) { if (dp->d_name[0] == '.') continue; /* * Don't copy i.none since if it exists it * contains Class Archive Format procedure * for installing archives. Only Directory * Format packages can exist * in a global spooled area. */ if (strcmp(dp->d_name, "i.none") == 0) continue; i = snprintf(path, PATH_MAX, "%s/install/%s", instdir, dp->d_name); if (i > PATH_MAX) { progerr(ERR_CREATE_PATH_3, instdir, "/install/", dp->d_name); quit(1); } i = snprintf(temp, PATH_MAX, "%s/install/%s", saveSpoolInstallDir, dp->d_name); if (i > PATH_MAX) { progerr(ERR_CREATE_PATH_3, saveSpoolInstallDir, "/install/", dp->d_name); quit(1); } if (cppath(MODE_SRC, path, temp, 0644)) { progerr(ERR_CANNOT_COPY, path, temp); (void) closedir(pdirfp); quit(99); } } (void) closedir(pdirfp); } /* * Now copy the original pkginfo and pkgmap files from the * installing package to the spooled directory. */ i = snprintf(path, sizeof (path), "%s/%s", instdir, PKGINFO); if (i > sizeof (path)) { progerr(ERR_CREATE_PATH_2, instdir, PKGINFO); quit(1); } i = snprintf(temp, sizeof (temp), "%s/%s", saveSpoolInstallDir, PKGINFO); if (i > sizeof (temp)) { progerr(ERR_CREATE_PATH_2, saveSpoolInstallDir, PKGINFO); quit(1); } if (cppath(MODE_SRC, path, temp, 0644)) { progerr(ERR_CANNOT_COPY, path, temp); quit(99); } /* * Only want to copy the FCS pkgmap if this is not a * patch installation. */ if (!isPatchUpdate()) { i = snprintf(path, sizeof (path), "%s/pkgmap", instdir); if (i > sizeof (path)) { progerr(ERR_CREATE_PATH_2, instdir, "pkgmap"); quit(1); } i = snprintf(temp, sizeof (temp), "%s/pkgmap", saveSpoolInstallDir); if (i > sizeof (path)) { progerr(ERR_CREATE_PATH_2, saveSpoolInstallDir, "pkgmap"); quit(1); } if (cppath(MODE_SRC, path, temp, 0644)) { progerr(ERR_CANNOT_COPY, path, temp); quit(99); } } } /* * If we are installing from a spool directory * copy the save directory from it, it may have * been patched. Duplicate it only if this * installation isn't an update and is not to * an alternate root. */ if (strstr(instdir, "pspool") != NULL) { struct stat status; i = snprintf(path, sizeof (path), "%s/save", instdir); if (i > sizeof (path)) { progerr(ERR_CREATE_PATH_2, instdir, "save"); quit(1); } if ((stat(path, &status) == 0) && (status.st_mode & S_IFDIR) && !isPatchUpdate()) { i = snprintf(cmd, sizeof (cmd), "cp -pr %s/* %s", path, pkgsav); if (i > sizeof (cmd)) { progerr(ERR_SNPRINTF, "cp -pr %s/* %s"); quit(1); } if (system(cmd)) { progerr(ERR_PKGBINCP, path, pkgsav); quit(99); } } } }
static int rdconfig(struct pkginfo *info, char *pkginst, char *ckvers) { FILE *fp; char temp[256]; char *value, *pt, *copy, **memloc; int count; if ((fp = pkginfopen(pkgdir, pkginst)) == NULL) { if ((errno == ENOENT) && strcmp(pkgdir, get_PKGLOC()) == 0) return (svr4info(info, pkginst, ckvers)); errno = EACCES; return (-1); } *temp = '\0'; count = 0; while (value = fpkgparam(fp, temp)) { if (strcmp(temp, "ARCH") == 0 || strcmp(temp, "CATEGORY") == 0) { /* remove all whitespace from value */ pt = copy = value; while (*pt) { if (!isspace((unsigned char)*pt)) *copy++ = *pt; pt++; } *copy = '\0'; } count++; memloc = NULL; if (strcmp(temp, "NAME") == 0) memloc = &info->name; else if (strcmp(temp, "VERSION") == 0) memloc = &info->version; else if (strcmp(temp, "ARCH") == 0) memloc = &info->arch; else if (strcmp(temp, "VENDOR") == 0) memloc = &info->vendor; else if (strcmp(temp, "BASEDIR") == 0) memloc = &info->basedir; else if (strcmp(temp, "CATEGORY") == 0) memloc = &info->catg; temp[0] = '\0'; if (memloc == NULL) continue; /* not a parameter we're looking for */ *memloc = strdup(value); if (!*memloc) { (void) fclose(fp); errno = ENOMEM; return (-1); /* malloc from strdup failed */ } } (void) fclose(fp); if (!count) { errno = ESRCH; return (-1); } info->status = (strcmp(pkgdir, get_PKGLOC()) ? PI_SPOOLED : PI_INSTALLED); if (info->status == PI_INSTALLED) { (void) sprintf(temp, "%s/%s/!I-Lock!", pkgdir, pkginst); if (access(temp, 0) == 0) info->status = PI_PARTIAL; else { (void) sprintf(temp, "%s/%s/!R-Lock!", pkgdir, pkginst); if (access(temp, 0) == 0) info->status = PI_PARTIAL; } } info->pkginst = strdup(pkginst); return (0); }
/* * This function confirms the presence of pkgmap and pkginfo and verifies * that the mandatory parameters are available in the environment. */ int pkgenv(char *pkginst, char *p_pkginfo, char *p_pkgmap) { FILE *fp; char *value, path[PATH_MAX], param[MAX_PKG_PARAM_LENGTH]; int errflg; errflg = 0; if (access(p_pkgmap, 0)) { progerr(gettext(ERR_PKGMAP), p_pkgmap); return (1); } if ((fp = fopen(p_pkginfo, "r")) == NULL) { progerr(gettext(ERR_PKGINFO), p_pkginfo); return (1); } param[0] = '\0'; while (value = fpkgparam(fp, param)) { if (strcmp("PATH", param)) putparam(param, value); free(value); param[0] = '\0'; } (void) fclose(fp); /* * verify that required parameters are now present in * the environment */ if ((pkgabrv = getenv("PKG")) == NULL) { progerr(gettext(ERR_NOPARAM), "PKG", path); errflg++; } if (pkgnmchk(pkgabrv, NULL, 0) || strchr(pkgabrv, '.')) { progerr(gettext(ERR_PKGBAD), pkgabrv); errflg++; } (void) snprintf(pkgwild, sizeof (pkgwild), "%s.*", pkgabrv); if ((pkgname = getenv("NAME")) == NULL) { progerr(gettext(ERR_NOPARAM), "NAME", path); errflg++; } if ((pkgarch = getenv("ARCH")) == NULL) { progerr(gettext(ERR_NOPARAM), "ARCH", path); errflg++; } if ((pkgvers = getenv("VERSION")) == NULL) { progerr(gettext(ERR_NOPARAM), "VERSION", path); errflg++; } if (getenv("CATEGORY") == NULL) { progerr(gettext(ERR_NOPARAM), "CATEGORY", path); errflg++; } /* * verify consistency between PKG parameter and pkginst that * was determined from the directory structure */ (void) snprintf(param, sizeof (param), "%s.*", pkgabrv); if (pkgnmchk(pkginst, param, 0)) { progerr(gettext(ERR_PKGMTCH), pkgabrv, pkginst); errflg++; } return (errflg); }
int main(int argc, char *argv[]) { FILE *fp; char *abi_comp_ptr; char *abi_sym_ptr; char *p; char *prog_full_name = NULL; char *pt; char *value; char *vfstab_file = NULL; char *zoneName = (char *)NULL; char cmdbin[PATH_MAX]; char param[MAX_PKG_PARAM_LENGTH]; char path[PATH_MAX]; char script[PATH_MAX]; int c; int err; int fd; int i; int map_client = 1; int n; int nodelete = 0; /* do not delete file or run scripts */ int pkgrmremote = 0; /* dont remove remote objects */ struct sigaction nact; struct sigaction oact; PKGserver pkgserver = NULL; VFP_T *tmpfp; /* reset contents of all default paths */ (void) memset(cmdbin, '\0', sizeof (cmdbin)); /* initialize locale environment */ (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); /* initialize program name */ prog_full_name = argv[0]; (void) set_prog_name(argv[0]); /* tell spmi zones interface how to access package output functions */ z_set_output_functions(echo, echoDebug, progerr); /* exit if not root */ if (getuid()) { progerr(ERR_NOT_ROOT, get_prog_name()); exit(1); /* NOTREACHED */ } /* Read PKG_INSTALL_ROOT from the environment, if it's there. */ if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) { progerr(ERR_ROOT_SET); exit(1); } pkgserversetmode(DEFAULTMODE); /* parse command line options */ while ((c = getopt(argc, argv, "?Aa:b:FMN:nO:oR:V:vy")) != EOF) { switch (c) { /* * Same as pkgrm: Allow admin to remove package objects from * a shared area from a reference client. */ case 'A': pkgrmremote++; break; /* * Same as pkgrm: Use the installation * administration file, admin, in place of the * default admin file. pkgrm first looks in the * current working directory for the administration * file. If the specified administration file is not * in the current working directory, pkgrm looks in * the /var/sadm/install/admin directory for the * administration file. */ case 'a': admnfile = flex_device(optarg, 0); break; /* * Same as pkgrm: location where package executables * can be found - default is /usr/sadm/install/bin. */ 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; /* * Same as pkgrm: suppresses the removal of any * files and any class action scripts, and suppresses * the running of any class action scripts. The * package files remain but the package looks like it * is not installed. This is mainly for use by the * upgrade process. */ case 'F': nodelete++; break; /* * Same as pkgrm: Instruct pkgrm not to use the * $root_path/etc/vfstab file for determining the * client's mount points. This option assumes the * mount points are correct on the server and it * behaves consistently with Solaris 2.5 and earlier * releases. */ case 'M': map_client = 0; break; /* * Different from pkgrm: specify program name to use * for messages. */ case 'N': (void) set_prog_name(optarg); break; /* * Same as pkgrm: package removal occurs in * non-interactive mode. Suppress output of the list of * removed files. The default mode is interactive. */ case 'n': nointeract++; (void) echoSetFlag(B_FALSE); break; /* * Almost same as pkgrm: the -O option allows the behavior * of the package tools to be modified. Recognized options: * -> debug * ---> enable debugging output * -> preremovecheck * ---> perform a "pre removal" check of the specified * ---> package - suppress all regular output and cause a * ---> series of one or more "name=value" pair format lines * ---> to be output that describes the "removability" of * ---> the specified package * -> enable-hollow-package-support * --> Enable hollow package support. When specified, for any * --> package that has SUNW_PKG_HOLLOW=true: * --> Do not calculate and verify package size against target * --> Do not run any package procedure or class action scripts * --> Do not create or remove any target directories * --> Do not perform any script locking * --> Do not install or uninstall any components of any package * --> Do not output any status or database update messages */ case 'O': for (p = strtok(optarg, ","); p != (char *)NULL; p = strtok(NULL, ",")) { /* process debug option */ if (strcmp(p, "debug") == 0) { /* set debug flag/enable debug output */ debugFlag = B_TRUE; (void) echoDebugSetFlag(debugFlag); /* debug info on arguments to pkgadd */ for (n = 0; n < argc && argv[n]; n++) { echoDebug(DBG_ARG, n, argv[n]); } continue; } /* process enable-hollow-package-support opt */ if (strcmp(p, "enable-hollow-package-support") == 0) { set_depend_pkginfo_DB(B_TRUE); continue; } /* process preremovecheck option */ if (strcmp(p, "preremovecheck") == 0) { preremoveCheck = B_TRUE; nointeract++; /* -n */ nodelete++; /* -F */ quitSetSilentExit(B_TRUE); continue; } /* process addzonename option */ if (strcmp(p, "addzonename") == 0) { zoneName = z_get_zonename(); quitSetZoneName(zoneName); continue; } /* process parent-zone-name option */ if (strncmp(p, PARENTZONENAME, PARENTZONENAME_LEN) == 0) { parentZoneName = p+PARENTZONENAME_LEN; continue; } /* process parent-zone-type option */ 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; } /* option not recognized - issue warning */ progerr(ERR_INVALID_O_OPTION, p); continue; } break; /* * Different from pkgrm: This is an old non-ABI package */ case 'o': script_in = PROC_XSTDIN; break; /* * Same as pkgrm: defines the full path name of a * directory to use as the root_path. All files, * including package system information files, are * relocated to a directory tree starting in the * specified root_path. */ case 'R': if (!set_inst_root(optarg)) { progerr(ERR_ROOT_CMD); exit(1); } break; /* * Same as pkgrm: allow admin to establish the client * filesystem using a vfstab-like file of stable format. */ case 'V': vfstab_file = flex_device(optarg, 2); map_client = 1; break; /* * Same as pkgrm: trace all of the scripts that * get executed by pkgrm, located in the * pkginst/install directory. This option is used for * debugging the procedural and non-procedural * scripts. */ case 'v': pkgverbose++; break; /* * Different from pkgrm: process this package using * old non-ABI symlinks */ case 'y': set_nonABI_symlinks(); break; default: usage(); /*NOTREACHED*/ /* * Although usage() calls a noreturn function, * needed to add return (1); so that main() would * pass compilation checks. The statement below * should never be executed. */ return (1); } } /* * ******************************************************************** * validate command line options * ******************************************************************** */ (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()); } /* establish cmdbin path */ if (cmdbin[0] == '\0') { (void) strlcpy(cmdbin, PKGBIN, sizeof (cmdbin)); } /* Read the mount table */ if (get_mntinfo(map_client, vfstab_file)) { quit(99); } /* * This function defines the standard /var/... directories used later * to construct the paths to the various databases. */ set_PKGpaths(get_inst_root()); /* * If this is being removed from a client whose /var filesystem is * mounted in some odd way, remap the administrative paths to the * real filesystem. This could be avoided by simply mounting up the * client now; but we aren't yet to the point in the process where * modification of the filesystem is permitted. */ 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)); } else { pkgrmremote = 0; /* Makes no sense on local host. */ } /* * hook SIGINT and SIGHUP interrupts into quit.c's trap handler */ /* hold SIGINT/SIGHUP interrupts */ (void) sighold(SIGHUP); (void) sighold(SIGINT); /* connect quit.c:trap() to SIGINT */ nact.sa_handler = quitGetTrapHandler(); nact.sa_flags = SA_RESTART; (void) sigemptyset(&nact.sa_mask); (void) sigaction(SIGINT, &nact, &oact); /* connect quit.c:trap() to SIGHUP */ nact.sa_handler = quitGetTrapHandler(); nact.sa_flags = SA_RESTART; (void) sigemptyset(&nact.sa_mask); (void) sigaction(SIGHUP, &nact, &oact); /* release hold on signals */ (void) sigrelse(SIGHUP); (void) sigrelse(SIGINT); pkginst = argv[optind++]; if (optind != argc) { usage(); } /* validate package software database (contents) file */ if (vcfile() == 0) { quit(99); } /* * Acquire the package lock - currently at "remove initialization" */ if (!lockinst(get_prog_name(), pkginst, "remove-initial")) { quit(99); } /* establish temporary directory to use */ tmpdir = getenv("TMPDIR"); if (tmpdir == NULL) { tmpdir = P_tmpdir; } echoDebug(DBG_PKGREMOVE_TMPDIR, tmpdir); /* * Initialize installation admin parameters by reading * the adminfile. */ echoDebug(DBG_PKGREMOVE_ADMINFILE, admnfile ? admnfile : ""); setadminFile(admnfile); /* * about to perform first operation that could be modified by the * preremove check option - if preremove check is selected (that is, * only gathering dependencies), then output a debug message to * indicate that the check is beginning. Also turn echo() output * off and set various other flags. */ if (preremoveCheck == B_TRUE) { (void) echoSetFlag(B_FALSE); echoDebug(DBG_PKGREMOVE_PRERMCHK, pkginst ? pkginst : "", zoneName ? zoneName : "global"); rcksetPreremoveCheck(B_TRUE); rcksetZoneName(zoneName); } (void) snprintf(pkgloc, sizeof (pkgloc), "%s/%s", get_PKGLOC(), pkginst); (void) snprintf(pkgbin, sizeof (pkgbin), "%s/install", pkgloc); (void) snprintf(rlockfile, sizeof (rlockfile), "%s/!R-Lock!", pkgloc); if (chdir(pkgbin)) { progerr(ERR_CHDIR, pkgbin); quit(99); } echo(MSG_PREREMOVE_REMINST, pkginst); /* * if a lock file is present, then a previous attempt to remove this * package may have been unsuccessful. */ if (access(rlockfile, F_OK) == 0) { echo(ERR_UNSUCC); echoDebug(DBG_PKGINSTALL_HAS_LOCKFILE, pkginst, rlockfile, zoneName ? zoneName : "global"); } /* * Process all parameters from the pkginfo file * and place them in the execution environment */ /* Add DB retreival of the pkginfo parameters here */ (void) snprintf(path, sizeof (path), "%s/pkginfo", pkgloc); if ((fp = fopen(path, "r")) == NULL) { progerr(ERR_PKGINFO, path); quit(99); } /* Mount up the client if necessary. */ if (map_client && !mount_client()) { logerr(MSG_MANMOUNT); } /* Get mount point of client */ client_mntdir = getenv("CLIENT_MNTDIR"); getuserlocale(); /* * current environment has been read; clear environment out * so putparam() can be used to populate the new environment * to be passed to any executables/scripts. */ environ = NULL; if (nonABI_symlinks()) { putparam("PKG_NONABI_SYMLINKS", "TRUE"); } /* * read the pkginfo file and fix any PKGSAV path - the correct * install_root will be prepended to the existing path. */ param[0] = '\0'; while (value = fpkgparam(fp, param)) { int validx = 0; char *newvalue; /* strip out any setting of PATH */ if (strcmp(param, "PATH") == 0) { free(value); param[0] = '\0'; continue; } /* if not PKGSAV then write out unchanged */ if (strcmp(param, "PKGSAV") != 0) { putparam(param, value); free(value); param[0] = '\0'; continue; } /* * PKGSAV parameter found - interpret the directory: * If in host:path format or marked with the leading "//", * then there is no client-relative translation - take it * literally later rather than use fixpath(). */ if (strstr(value, ":/")) { /* no modification needed */ validx = 0; } else if (strstr(value, "//") == value) { validx = 1; } else if (is_an_inst_root()) { /* This PKGSAV needs to be made client-relative. */ newvalue = fixpath(value); free(value); value = newvalue; } putparam(param, value+validx); free(value); param[0] = '\0'; } (void) fclose(fp); /* write parent condition information to environment */ putConditionInfo(parentZoneName, parentZoneType); putuserlocale(); /* * Now do all the various setups based on ABI compliance */ /* Read the environment provided by the pkginfo file */ abi_comp_ptr = getenv("NONABI_SCRIPTS"); /* if not ABI compliant set global flag */ abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS"); if (abi_sym_ptr && strncasecmp(abi_sym_ptr, "TRUE", 4) == 0) { set_nonABI_symlinks(); } /* * If pkginfo says it's not compliant then set non_abi_scripts. */ if (abi_comp_ptr && strncmp(abi_comp_ptr, "TRUE", 4) == 0) { script_in = PROC_XSTDIN; } /* * Since this is a removal, we can tell whether it's absolute or * not from the resident pkginfo file read above. */ if ((err = set_basedirs((getenv("BASEDIR") != NULL), adm.basedir, pkginst, nointeract)) != 0) { quit(err); } /* * See if were are removing a package that only wants to update * the database or only remove files associated with CAS's. We * only check the PKG_HOLLOW_VARIABLE variable if told to do so by * the caller. */ if (is_depend_pkginfo_DB()) { pt = getenv(PKG_HOLLOW_VARIABLE); if ((pt != NULL) && (strncasecmp(pt, "true", 4) == 0)) { echoDebug(DBG_PKGREMOVE_HOLLOW_ENABLED); /* * this is a hollow package and hollow package support * is enabled -- override admin settings to suppress * checks that do not make sense since no scripts will * be executed and no files will be removed. */ 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); } } put_path_params(); /* If client mount point, add it to pkgremove environment */ if (client_mntdir != NULL) { putparam("CLIENT_MNTDIR", client_mntdir); } /* Establish the class list and the class attributes. */ if ((value = getenv("CLASSES")) != NULL) { cl_sets(qstrdup(value)); } else { progerr(ERR_CLASSES, path); quit(99); } /* establish path and tmpdir */ if (cmdbin[0] == '\0') { (void) strlcpy(cmdbin, PKGBIN, sizeof (cmdbin)); } (void) snprintf(path, sizeof (path), "%s:%s", DEFPATH, cmdbin); putparam("PATH", path); putparam("TMPDIR", tmpdir); /* * Check ulimit requirement (provided in pkginfo). The purpose of * this limit is to terminate pathological file growth resulting from * file edits in scripts. It does not apply to files in the pkgmap * and it does not apply to any database files manipulated by the * installation service. */ if (value = getenv("ULIMIT")) { if (assign_ulimit(value) == -1) { progerr(ERR_BADULIMIT, value); warnflag++; } putparam("PKG_ULIMIT", "TRUE"); } /* * If only gathering dependencies, check and output status of all * remaining dependencies and exit. */ if (preremoveCheck == B_TRUE) { /* * make sure current runlevel is appropriate */ (void) fprintf(stdout, "rckrunlevel=%d\n", rckrunlevel()); /* * determine if any packaging scripts provided with * this package will execute as a priviledged user */ (void) fprintf(stdout, "rckpriv=%d\n", rckpriv()); /* * verify package dependencies */ (void) fprintf(stdout, "rckdepend=%d\n", rckdepend()); /* * ****** preremove check done - exit ****** */ echoDebug(DBG_PKGREMOVE_PRERMCHK_OK); quit(0); /*NOTREACHED*/ } /* * Not gathering dependencies only, proceed to check dependencies * and continue with the package removal operation. */ /* * make sure current runlevel is appropriate */ n = rckrunlevel(); if (n != 0) { quit(n); /* NOTREACHED */ } /* * determine if any packaging scripts provided with * this package will execute as a priviledged user */ n = rckpriv(); if (n != 0) { quit(n); /* NOTREACHED */ } /* * verify package dependencies */ n = rckdepend(); if (n != 0) { quit(n); /* NOTREACHED */ } /* * ********************************************************************* * the actual removal of the package begins here * ********************************************************************* */ /* * create lockfile to indicate start of removal */ started++; if ((fd = open(rlockfile, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) { progerr(ERR_LOCKFILE, rlockfile); quit(99); } else { (void) close(fd); } if (zoneName == (char *)NULL) { echo(MSG_PKGREMOVE_PROCPKG_GZ); echoDebug(DBG_PKGREMOVE_PROCPKG_GZ, pkginst, rlockfile); } else { echo(MSG_PKGREMOVE_PROCPKG_LZ, zoneName); echoDebug(DBG_PKGREMOVE_PROCPKG_LZ, pkginst, rlockfile, zoneName); } if (delmap(0, pkginst, &pkgserver, &tmpfp) != 0) { progerr(ERR_DB_QUERY, pkginst); quit(99); } /* * Run a preremove script if one is provided by the package. * Don't execute preremove script if only updating the DB. * Don't execute preremove script if files are not being deleted. */ /* update the lock - at the preremove script */ lockupd("preremove"); /* execute preremove script if one is provided */ (void) snprintf(script, sizeof (script), "%s/preremove", pkgbin); if (access(script, F_OK) != 0) { /* no script present */ echoDebug(DBG_PKGREMOVE_POC_NONE, pkginst, zoneName ? zoneName : "global"); } else if (nodelete) { /* not deleting files: skip preremove script */ echoDebug(DBG_PKGREMOVE_POC_NODEL, pkginst, script, zoneName ? zoneName : "global"); } else if (is_depend_pkginfo_DB()) { /* updating db only: skip preremove script */ echoDebug(DBG_PKGREMOVE_POC_DBUPD, pkginst, script, zoneName ? zoneName : "global"); } else { /* script present and ok to run: run the script */ set_ulimit("preremove", ERR_PREREMOVE); if (zoneName == (char *)NULL) { echo(MSG_PKGREMOVE_EXEPOC_GZ); echoDebug(DBG_PKGREMOVE_EXEPOC_GZ, pkginst, script); } else { echo(MSG_PKGREMOVE_EXEPOC_LZ, zoneName); echoDebug(DBG_PKGREMOVE_EXEPOC_LZ, pkginst, script, zoneName); } putparam("PKG_PROC_SCRIPT", "preremove"); if (pkgverbose) { ckreturn(pkgexecl(script_in, PROC_STDOUT, PROC_USER, PROC_GRP, SHELL, "-x", script, NULL), ERR_PREREMOVE); } else { ckreturn(pkgexecl(script_in, PROC_STDOUT, PROC_USER, PROC_GRP, SHELL, script, NULL), ERR_PREREMOVE); } clr_ulimit(); } /* update the lock - doing removal */ lockupd("remove"); /* * Remove all components belonging to this package. * Don't remove components if only updating the DB. * Don't remove components if files are not being deleted. */ if (nodelete) { echoDebug(DBG_PKGREMOVE_REM_NODEL, pkginst, zoneName ? zoneName : "global"); } else if (is_depend_pkginfo_DB()) { echoDebug(DBG_PKGREMOVE_REM_DBUPD, pkginst, zoneName ? zoneName : "global"); } else { echoDebug(DBG_PKGREMOVE_REM, pkginst, zoneName ? zoneName : "global"); /* * remove package one class at a time */ /* reverse order of classes */ for (i = cl_getn() - 1; i >= 0; i--) { rmclass(cl_nam(i), pkgrmremote, zoneName); } rmclass(NULL, pkgrmremote, zoneName); } z_destroyMountTable(); /* * Execute postremove script, if any * Don't execute postremove script if only updating the DB. * Don't execute postremove script if files are not being deleted. */ /* update the lock - at the postremove script */ lockupd("postremove"); /* execute postremove script if one is provided */ (void) snprintf(script, sizeof (script), "%s/postremove", pkgbin); if (access(script, F_OK) != 0) { /* no script present */ echoDebug(DBG_PKGREMOVE_PIC_NONE, pkginst, zoneName ? zoneName : "global"); } else if (nodelete) { /* not deleting files: skip postremove script */ echoDebug(DBG_PKGREMOVE_PIC_NODEL, pkginst, script, zoneName ? zoneName : "global"); } else if (is_depend_pkginfo_DB()) { /* updating db only: skip postremove script */ echoDebug(DBG_PKGREMOVE_PIC_DBUPD, pkginst, script, zoneName ? zoneName : "global"); } else { /* script present and ok to run: run the script */ set_ulimit("postremove", ERR_POSTREMOVE); if (zoneName == (char *)NULL) { echo(MSG_PKGREMOVE_EXEPIC_GZ); echoDebug(DBG_PKGREMOVE_EXEPIC_GZ, pkginst, script); } else { echo(MSG_PKGREMOVE_EXEPIC_LZ, zoneName); echoDebug(DBG_PKGREMOVE_EXEPIC_LZ, pkginst, script, zoneName); } putparam("PKG_PROC_SCRIPT", "postremove"); putparam("TMPDIR", tmpdir); if (pkgverbose) { ckreturn(pkgexecl(script_in, PROC_STDOUT, PROC_USER, PROC_GRP, SHELL, "-x", script, NULL), ERR_POSTREMOVE); } else { ckreturn(pkgexecl(script_in, PROC_STDOUT, PROC_USER, PROC_GRP, SHELL, script, NULL), ERR_POSTREMOVE); } clr_ulimit(); } if (zoneName == (char *)NULL) { echo(MSG_PKGREMOVE_UPDINF_GZ); } else { echo(MSG_PKGREMOVE_UPDINF_LZ, zoneName); } if (delmap(1, pkginst, &pkgserver, &tmpfp) != 0) { progerr(ERR_DB_QUERY, pkginst); quit(99); } if (!warnflag && !failflag) { (void) chdir("/"); if (rrmdir(pkgloc)) warnflag++; } if ((z_running_in_global_zone() == B_TRUE) && (pkgIsPkgInGzOnly(get_inst_root(), pkginst) == B_TRUE)) { boolean_t b; b = pkgRemovePackageFromGzonlyList(get_inst_root(), pkginst); if (b == B_FALSE) { progerr(ERR_PKGREMOVE_GZONLY_REMOVE, pkginst); ckreturn(1, NULL); } } /* release the generic package lock */ (void) unlockinst(); pkgcloseserver(pkgserver); quit(0); /* LINTED: no return */ }
int checkmap(int maptyp, int uninst, char *mapfile, char *envfile, char *pkginst, char *path, int pathtype) { FILE *fp; char *cl = NULL; char *value; char param[MAX_PKG_PARAM_LENGTH]; int count; int errflg; int n; int selected; struct pinfo *pinfo; VFP_T *vfp = (VFP_T *)NULL; PKGserver server; if (envfile != NULL) { if ((fp = fopen(envfile, "r")) == NULL) { progerr(gettext(ERR_ENVFILE), envfile); return (-1); } param[0] = '\0'; while (value = fpkgparam(fp, param)) { if (strcmp("PATH", param) != 0) { /* * If checking an uninstalled package, we * only want two parameters. If we took all * of them, including path definitions, we * wouldn't be looking in the right places in * the reloc and root directories. */ if (uninst) { if ((strncmp("PKG_SRC_NOVERIFY", param, 16) == 0) && value) { logerr(gettext(MSG_ARCHIVE)); putparam(param, value); } if ((strncmp("CLASSES", param, 7) == 0) && value) putparam(param, value); } else putparam(param, value); } free(value); param[0] = '\0'; } (void) fclose(fp); basedir = getenv("BASEDIR"); } /* * If we are using a contents file for the map, this locks the * contents file in order to freeze the database and assure it * remains synchronized with the file system against which it is * being compared. There is no practical way to lock another pkgmap * on some unknown medium so we don't bother. */ if (maptyp) { /* If this is the contents file */ if (!socfile(&server, B_FALSE) || pkgopenfilter(server, pkgcnt == 1 ? pkginst : NULL) != 0) { progerr(gettext(ERR_PKGMAP), "contents"); return (-1); } } else { if (vfpOpen(&vfp, mapfile, "r", VFP_NONE) != 0) { progerr(gettext(ERR_PKGMAP), mapfile); return (-1); } } if ((cl = getenv("CLASSES")) != NULL) cl_sets(qstrdup(cl)); errflg = count = 0; do { if ((n = NXTENTRY(&entry, vfp, server)) == 0) { break; } /* * Search for partial paths in the ext DB. */ if (pathtype) { /* LINTED warning: statement has no consequent: if */ if (is_partial_path_in_DB(entry.path, path)) { /* Check this entry */ ; } else if (entry.ftype == 's' || entry.ftype == 'l') { if (is_partial_path_in_DB( /* LINTED warning: statement has no consequen */ entry.ainfo.local, path)) { /* Check this entry */ ; } else { continue; } } else { /* Skip to next DB entry */ continue; } } if (n < 0) { char *errstr = getErrstr(); logerr(gettext("ERROR: garbled entry")); logerr(gettext("pathname: %s"), (entry.path && *entry.path) ? entry.path : "Unknown"); logerr(gettext("problem: %s"), (errstr && *errstr) ? errstr : "Unknown"); exit(99); } if (n == 0) break; /* done with file */ /* * The class list may not be complete for good reason, so * there's no complaining if this returns an index of -1. */ if (cl != NULL) entry.pkg_class_idx = cl_idx(entry.pkg_class); if (maptyp && pkginst != NULL) { /* * check to see if the entry we just read * is associated with one of the packages * we have listed on the command line */ selected = 0; pinfo = entry.pinfo; while (pinfo) { if (selpkg(pinfo->pkg)) { selected++; break; } pinfo = pinfo->next; } if (!selected) continue; /* not selected */ } /* * Check to see if the pathname associated with the entry * we just read is associated with the list of paths we * supplied on the command line */ if (!selpath(entry.path, pathtype)) continue; /* not selected */ /* * Determine if this is a package object wanting * verification. Metafiles are always checked, otherwise, we * rely on the class to discriminate. */ if (entry.ftype != 'i') /* If there's no class list... */ if (cl != NULL) /* * ... or this entry isn't in that class list * or it's in a private format, then don't * check it. */ if (entry.pkg_class_idx == -1 || cl_svfy(entry.pkg_class_idx) == NOVERIFY) continue; count++; if (ckentry((envfile ? 1 : 0), maptyp, &entry, vfp, server)) errflg++; } while (n != 0); if (maptyp) relslock(); else (void) vfpClose(&vfp); if (environ) { /* free up environment resources */ for (n = 0; environ[n]; n++) free(environ[n]); free(environ); environ = NULL; } if (maptyp) { /* * make sure each listed package was associated with * an entry from the prototype or pkgmap */ (void) selpkg(NULL); } if (!qflag && !lflag && !Lflag) { /* * make sure each listed pathname was associated with an entry * from the prototype or pkgmap */ (void) selpath(NULL, pathtype); } return (errflg); }
/* * valid_zone_attr: Validates the zone attributes specified in * pkginfo file for this package. The package * can not be created with certain combinations * of the attributes. */ static boolean_t valid_zone_attr(struct cfent **eptlist) { FILE *pkginfoFP; boolean_t all_zones; /* pkg is "all zones" only */ boolean_t is_hollow; /* pkg is "hollow" */ boolean_t this_zone; /* pkg is "this zone" only */ char pkginfoPath[PATH_MAX]; /* pkginfo file path */ char *pkgInst; int i; /* Path to pkginfo file within the package to be installed */ this_zone = B_FALSE; for (i = 0; eptlist[i]; i++) { if (eptlist[i]->ftype != 'i') continue; if (strcmp(eptlist[i]->path, "pkginfo") == 0) (void) strcpy(pkginfoPath, eptlist[i]->ainfo.local); /* * Check to see if this package has a request script. If this * package does have a request script, then mark the package * for installation in this zone only. Any package with a * request script cannot be installed outside of the zone the * pkgadd command is being run in, nor can such a package be * installed as part of a new zone install. A new zone install * must be non-interactive, which is required by all packages * integrated into the Solaris WOS. * If request file is set in prototype, then this_zone is TRUE. */ if (strcmp(eptlist[i]->path, "request") == 0) this_zone = B_TRUE; } /* Gather information from the pkginfo file */ pkginfoFP = fopen(pkginfoPath, "r"); if (pkginfoFP == NULL) { progerr(ERR_NO_PKG_INFOFILE, pkginfoPath, strerror(errno)); return (B_FALSE); } if ((pkgInst = fpkgparam(pkginfoFP, "PKG")) == NULL) { progerr(gettext(ERR_NOPARAM), "PKG", pkginfoPath); return (B_FALSE); } /* Determine "HOLLOW" setting for this package */ is_hollow = pkginfoParamTruth(pkginfoFP, PKG_HOLLOW_VARIABLE, "true", B_FALSE); /* Determine "ALLZONES" setting for this package */ all_zones = pkginfoParamTruth(pkginfoFP, PKG_ALLZONES_VARIABLE, "true", B_FALSE); /* Determine "THISZONE" setting for this package, if no request file */ if (!this_zone) this_zone = pkginfoParamTruth(pkginfoFP, PKG_THISZONE_VARIABLE, "true", B_FALSE); /* Close pkginfo file */ (void) fclose(pkginfoFP); /* * Validate zone attributes based on information gathered, * and validate the three SUNW_PKG_ options: * * -----------------------------|---------------| * <ALLZONES><HOLLOW><THISZONE> | If Allowed | * ----1------------------------|---------------| * F F F | OK | * F F T | OK | * F T * | NO | * ----2------------------------|---------------| * T F F | OK | * T T F | OK | * T * T | NO | * -----------------------------|---------------| */ /* pkg "all zones" && "this zone" (#2) */ if (all_zones && this_zone) { progerr(ERR_ALLZONES_AND_THISZONE, pkgInst, PKG_ALLZONES_VARIABLE, PKG_THISZONE_VARIABLE); return (B_FALSE); } /* pkg "!all zones" && "hollow" (#1) */ if ((!all_zones) && is_hollow) { progerr(ERR_NO_ALLZONES_AND_HOLLOW, pkgInst, PKG_ALLZONES_VARIABLE, PKG_HOLLOW_VARIABLE); return (B_FALSE); } return (B_TRUE); }
int main(int argc, char *argv[]) { struct utsname utsbuf; struct statvfs64 svfsb; struct cfent **eptlist; FILE *fp; VFP_T *vfp; int i, c, n, eptnum, found, part, nparts, npkgs, objects; char buf[MAX_PKG_PARAM_LENGTH]; char temp[MAX_PKG_PARAM_LENGTH]; char param[MAX_PKG_PARAM_LENGTH]; char *pt, *value, *pkginst, *tmpdir, *abi_sym_ptr, **cmdparam; char *pkgname; char *pkgvers; char *pkgarch; char *pkgcat; void (*func)(); time_t clock; fsblkcnt_t bsize = 0; fsblkcnt_t frsize = 0; struct cl_attr **allclass = NULL; struct cl_attr **order; /* initialize locale environment */ (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); /* initialize program name */ (void) set_prog_name(argv[0]); /* tell spmi zones interface how to access package output functions */ z_set_output_functions(echo, echoDebug, progerr); func = sigset(SIGINT, trap); if (func != SIG_DFL) func = sigset(SIGINT, func); func = sigset(SIGHUP, trap); setmapmode(MAPBUILD); /* variable binding */ if (func != SIG_DFL) func = sigset(SIGHUP, func); environ = NULL; while ((c = getopt(argc, argv, "osnp:l:r:b:d:f:a:v:?")) != EOF) { switch (c) { case 'n': nflag++; break; case 's': sflag++; break; case 'o': overwrite++; break; case 'p': putparam("PSTAMP", optarg); break; case 'l': llimit = atol(optarg); break; case 'r': pt = strtok(optarg, " \t\n, "); n = 0; do { rootlist[n++] = flex_device(pt, 0); if (n >= NROOT) { progerr(gettext(ERR_NROOT), NROOT); quit(1); } } while (pt = strtok(NULL, " \t\n, ")); rootlist[n] = NULL; break; case 'b': basedir = optarg; break; case 'f': protofile = optarg; break; case 'd': device = flex_device(optarg, 1); break; case 'a': putparam("ARCH", optarg); break; case 'v': putparam("VERSION", optarg); break; default: usage(); } } /* * Store command line variable assignments for later * incorporation into the environment. */ cmdparam = &argv[optind]; /* Skip past equates. */ while (argv[optind] && strchr(argv[optind], '=')) optind++; /* Confirm that the instance name is valid */ if ((pkginst = argv[optind]) != NULL) { if (pkgnmchk(pkginst, "all", 0)) { progerr(gettext(ERR_PKGINST), pkginst); quit(1); } argv[optind++] = NULL; } if (optind != argc) usage(); tmpdir = getenv("TMPDIR"); if (tmpdir == NULL) tmpdir = P_tmpdir; /* bug id 4244631, not ABI compliant */ abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS"); if (abi_sym_ptr && (strncasecmp(abi_sym_ptr, "TRUE", 4) == 0)) { set_nonABI_symlinks(); } if (device == NULL) { device = devattr(SPOOLDEV, "pathname"); if (device == NULL) { progerr(gettext(ERR_DEVICE), SPOOLDEV); exit(99); } } if (protofile == NULL) { if (access("prototype", 0) == 0) protofile = "prototype"; else if (access("Prototype", 0) == 0) protofile = "Prototype"; else { progerr(gettext(ERR_PROTOTYPE)); quit(1); } } if (devtype(device, &pkgdev)) { progerr(gettext(ERR_BADDEV), device); quit(1); } if (pkgdev.norewind) { /* initialize datastream */ progerr(gettext(ERR_DSTREAM), device); quit(1); } if (pkgdev.mount) { if (n = pkgmount(&pkgdev, NULL, 0, 0, 1)) quit(n); } /* * convert prototype file to a pkgmap, while locating * package objects in the current environment */ t_pkgmap = tempnam(tmpdir, "tmpmap"); if (t_pkgmap == NULL) { progerr(gettext(ERR_TEMP), errno); exit(99); } (void) fprintf(stderr, gettext(MSG_PROTOTYPE)); if (n = mkpkgmap(t_pkgmap, protofile, cmdparam)) { progerr(gettext(ERR_BUILD)); quit(1); } setmapmode(MAPNONE); /* All appropriate variables are now bound */ if (vfpOpen(&vfp, t_pkgmap, "r", VFP_NEEDNOW) != 0) { progerr(gettext(ERR_TEMP), errno); quit(99); } eptlist = procmap(vfp, 0, NULL); if (eptlist == NULL) { quit(1); } (void) vfpClose(&vfp); /* Validate the zone attributes in pkginfo, before creation */ if (!valid_zone_attr(eptlist)) { progerr(ERR_PKGINFO_INVALID_OPTION_COMB); quit(1); } (void) fprintf(stderr, gettext(MSG_PKGINFO)); pt = NULL; for (i = 0; eptlist[i]; i++) { ckmissing(eptlist[i]->path, eptlist[i]->ftype); if (eptlist[i]->ftype != 'i') continue; if (strcmp(eptlist[i]->path, "pkginfo") == 0) svept = eptlist[i]; } if (svept == NULL) { progerr(gettext(ERR_NOPKGINFO)); quit(99); } eptnum = i; /* * process all parameters from the pkginfo file * and place them in the execution environment */ if ((fp = fopen(svept->ainfo.local, "r")) == NULL) { progerr(gettext(ERR_RDPKGINFO), svept->ainfo.local); quit(99); } param[0] = '\0'; while (value = fpkgparam(fp, param)) { if (getenv(param) == NULL) putparam(param, value); free((void *)value); param[0] = '\0'; } (void) fclose(fp); /* add command line variables */ while (*cmdparam && (value = strchr(*cmdparam, '=')) != NULL) { *value = NULL; /* terminate the parameter */ value++; /* value is now the value (not '=') */ putparam(*cmdparam++, value); /* store it in environ */ } /* make sure parameters are valid */ (void) time(&clock); if (pt = getenv("PKG")) { if (pkgnmchk(pt, NULL, 0) || strchr(pt, '.')) { progerr(gettext(ERR_PKGABRV), pt); quit(1); } if (pkginst == NULL) pkginst = pt; } else { progerr(gettext(ERR_NOPARAM), "PKG", svept->path); quit(1); } /* * verify consistency between PKG parameter and pkginst */ (void) snprintf(param, sizeof (param), "%s.*", pt); if (pkgnmchk(pkginst, param, 0)) { progerr(gettext(ERR_PKGMTCH), pt, pkginst); quit(1); } /* * ********************************************************************* * this feature is removed starting with Solaris 10 - there is no built * in list of packages that should be run "the old way" * ********************************************************************* */ #ifdef ALLOW_EXCEPTION_PKG_LIST /* Until 2.9, set it from the execption list */ if (exception_pkg(pkginst, LINK)) set_nonABI_symlinks(); #endif if ((pkgname = getenv("NAME")) == NULL) { progerr(gettext(ERR_NOPARAM), "NAME", svept->path); quit(1); } if (ckparam("NAME", pkgname)) quit(1); if ((pkgvers = getenv("VERSION")) == NULL) { /* XXX - I18n */ /* LINTED do not use cftime(); use strftime instead */ (void) cftime(buf, "\045m/\045d/\045Y", &clock); (void) snprintf(temp, sizeof (temp), gettext("Dev Release %s"), buf); putparam("VERSION", temp); pkgvers = getenv("VERSION"); logerr(gettext(WRN_SETPARAM), "VERSION", temp); } if (ckparam("VERSION", pkgvers)) quit(1); if ((pkgarch = getenv("ARCH")) == NULL) { (void) uname(&utsbuf); putparam("ARCH", utsbuf.machine); pkgarch = getenv("ARCH"); logerr(gettext(WRN_SETPARAM), "ARCH", utsbuf.machine); } if (ckparam("ARCH", pkgarch)) quit(1); if (getenv("PSTAMP") == NULL) { /* use octal value of '%' to fight sccs expansion */ /* XXX - I18n */ /* LINTED do not use cftime(); use strftime instead */ (void) cftime(buf, "\045Y\045m\045d\045H\045M\045S", &clock); (void) uname(&utsbuf); (void) snprintf(temp, sizeof (temp), "%s%s", utsbuf.nodename, buf); putparam("PSTAMP", temp); logerr(gettext(WRN_SETPARAM), "PSTAMP", temp); } if ((pkgcat = getenv("CATEGORY")) == NULL) { progerr(gettext(ERR_NOPARAM), "CATEGORY", svept->path); quit(1); } if (ckparam("CATEGORY", pkgcat)) quit(1); /* * warn user of classes listed in package which do * not appear in CLASSES variable in pkginfo file */ objects = 0; for (i = 0; eptlist[i]; i++) { if (eptlist[i]->ftype != 'i') { objects++; addlist(&allclass, eptlist[i]->pkg_class); } } if ((pt = getenv("CLASSES")) == NULL) { if (allclass && *allclass) { cl_setl(allclass); cl_putl("CLASSES", allclass); logerr(gettext(WRN_SETPARAM), "CLASSES", getenv("CLASSES")); } } else { cl_sets(qstrdup(pt)); if (allclass && *allclass) { for (i = 0; allclass[i]; i++) { found = 0; if (cl_idx(allclass[i]->name) != -1) { found++; break; } if (!found) { logerr(gettext(WRN_CLASSES), (char *)allclass[i]); } } } } (void) fprintf(stderr, gettext(MSG_VOLUMIZE), objects); order = (struct cl_attr **)0; if (pt = getenv("ORDER")) { pt = qstrdup(pt); (void) setlist(&order, pt); cl_putl("ORDER", order); } /* stat the intended output filesystem to get blocking information */ if (pkgdev.dirname == NULL) { progerr(gettext(ERR_WHATVFS), device); quit(99); } if (statvfs64(pkgdev.dirname, &svfsb)) { progerr(gettext(ERR_STATVFS), pkgdev.dirname); quit(99); } if (bsize == 0) { bsize = svfsb.f_bsize; } if (frsize == 0) { frsize = svfsb.f_frsize; } if (limit == 0) /* * bavail is in terms of fragment size blocks - change * to 512 byte blocks */ limit = (((long)frsize > 0) ? howmany(frsize, DEV_BSIZE) : howmany(bsize, DEV_BSIZE)) * svfsb.f_bavail; if (ilimit == 0) { ilimit = (svfsb.f_favail > 0) ? svfsb.f_favail : svfsb.f_ffree; } nparts = splpkgmap(eptlist, eptnum, (char **)order, bsize, frsize, &limit, &ilimit, &llimit); if (nparts <= 0) { progerr(gettext(ERR_SPLIT)); quit(1); } if (nflag) { for (i = 0; eptlist[i]; i++) (void) ppkgmap(eptlist[i], stdout); exit(0); /*NOTREACHED*/ } (void) snprintf(pkgloc, sizeof (pkgloc), "%s/%s", pkgdev.dirname, pkginst); if (!isdir(pkgloc) && !overwrite) { progerr(gettext(ERR_OVERWRITE), pkgloc); quit(1); } /* output all environment install parameters */ t_pkginfo = tempnam(tmpdir, "pkginfo"); if ((fp = fopen(t_pkginfo, "w")) == NULL) { progerr(gettext(ERR_TEMP), errno); exit(99); } for (i = 0; environ[i]; i++) { if (isupper(*environ[i])) { (void) fputs(environ[i], fp); (void) fputc('\n', fp); } } (void) fclose(fp); started++; (void) rrmdir(pkgloc); if (mkdir(pkgloc, 0755)) { progerr(gettext(ERR_MKDIR), pkgloc); quit(1); } /* determine how many packages already reside on the medium */ pkgdir = pkgdev.dirname; npkgs = 0; while (pt = fpkginst("all", NULL, NULL)) npkgs++; (void) fpkginst(NULL); /* free resource usage */ if (nparts > 1) { if (pkgdev.mount && npkgs) { progerr(gettext(ERR_ONEVOL)); quit(1); } } /* * update pkgmap entry for pkginfo file, since it may * have changed due to command line or failure to * specify all neccessary parameters */ for (i = 0; eptlist[i]; i++) { if (eptlist[i]->ftype != 'i') continue; if (strcmp(eptlist[i]->path, "pkginfo") == 0) { svept = eptlist[i]; svept->ftype = '?'; svept->ainfo.local = t_pkginfo; (void) cverify(0, &svept->ftype, t_pkginfo, &svept->cinfo, 1); svept->ftype = 'i'; break; } } if (nparts > 1) (void) fprintf(stderr, gettext(MSG_PACKAGEM), nparts); else (void) fprintf(stderr, gettext(MSG_PACKAGE1)); for (part = 1; part <= nparts; part++) { if ((part > 1) && pkgdev.mount) { if (pkgumount(&pkgdev)) { progerr(gettext(ERR_UMOUNT), pkgdev.mount); quit(99); } if (n = pkgmount(&pkgdev, NULL, part, nparts, 1)) quit(n); (void) rrmdir(pkgloc); if (mkdir(pkgloc, 0555)) { progerr(gettext(ERR_MKDIR), pkgloc); quit(99); } } outvol(eptlist, eptnum, part, nparts); /* Validate (as much as possible) the control scripts. */ if (part == 1) { char inst_path[PATH_MAX]; (void) fprintf(stderr, gettext(MSG_VALSCRIPTS)); (void) snprintf(inst_path, sizeof (inst_path), "%s/install", pkgloc); checkscripts(inst_path, 0); } } quit(0); /*NOTREACHED*/ }