/* * convert_contents_to_sql * * Converts the entire contents file into a set of SQL transactions which * populate the database. The reason that a single transaction is not used * is that some systems run out of memory in this case. * * Return: 0 on success, nonzero on failure */ int convert_contents_to_sql(struct dstr *pd, const char *pcroot) { VFP_T *vfp; char path[PATH_MAX]; int n; int total = 0; struct cfent entry; if (pcroot == NULL) { pcroot = "/"; } if (pcroot[strlen(pcroot) - 1] == '/') { if (snprintf(path, sizeof (path), "%svar/sadm/install/contents", pcroot) >= sizeof (path)) { return (1); } } else { if (snprintf(path, sizeof (path), "%s/var/sadm/install/contents", pcroot) >= sizeof (path)) { return (1); } } if (vfpOpen(&vfp, path, "r", VFP_NEEDNOW) != 0) { log_msg(LOG_MSG_ERR, MSG_FILE_ACCESS, path, strerror(errno)); return (1); } while ((n = srchcfile(&entry, "*", vfp, (VFP_T *)NULL)) > 0) { if (append_contents_sql(pd, &entry)) { (void) vfpClose(&vfp); return (1); } total++; } (void) vfpClose(&vfp); if (n < 0) { log_msg(LOG_MSG_ERR, MSG_CONTENTS_FORMAT); return (1); } return (0); }
static void getinfo(struct cfstat *dp) { int n; char pkgmap[MAXPATHLEN]; VFP_T *vfp; (void) snprintf(pkgmap, sizeof (pkgmap), "%s/%s/pkgmap", pkgdir, dp->pkginst); if (vfpOpen(&vfp, pkgmap, "r", VFP_NEEDNOW) != 0) { progerr(gettext("unable open \"%s\" for reading"), pkgmap); exit(1); } dp->spooled = 1; /* pkgmap counts! */ while ((n = gpkgmapvfp(&entry, vfp)) > 0) { dp->spooled++; pkgusage(dp, &entry); } if (n < 0) { char *errstr = getErrstr(); progerr(gettext("bad entry read in pkgmap file")); logerr(gettext("pathname: %s"), (entry.path && *entry.path) ? entry.path : "Unknown"); logerr(gettext("problem: %s"), (errstr && *errstr) ? errstr : "Unknown"); exit(1); } (void) vfpClose(&vfp); }
static void rdcontents(void) { VFP_T *vfp; struct cfstat *dp; struct pinfo *pinfo; int n; if (vfpOpen(&vfp, contents, "r", VFP_NEEDNOW) != 0) { progerr(gettext("unable to open \"%s\" for reading"), contents); exit(1); } /* check the contents file to look for referenced packages */ while ((n = srchcfile(&entry, "*", vfp, (VFP_T *)NULL)) > 0) { for (pinfo = entry.pinfo; pinfo; pinfo = pinfo->next) { /* see if entry is used by indicated packaged */ if (pkgcnt && (selectp(pinfo->pkg) < 0)) continue; dp = fpkg(pinfo->pkg); pkgusage(dp, &entry); if (entry.npkgs > 1) dp->shared++; /* * Only objects specifically tagged with '!' event * character are considered "partial", everything * else is considered "installed" (even server * objects). */ switch (pinfo->status) { case '!' : dp->partial++; break; default : dp->installed++; break; } } } if (n < 0) { char *errstr = getErrstr(); progerr(gettext("bad entry read in contents file")); logerr(gettext("pathname: %s"), (entry.path && *entry.path) ? entry.path : "Unknown"); logerr(gettext("problem: %s"), (errstr && *errstr) ? errstr : "Unknown"); exit(1); } (void) vfpClose(&vfp); }
int vfpCheckpointOpen(VFP_T **a_cpVfp, VFP_T **r_vfp, char *a_path, char *a_mode, VFPFLAGS_T a_flags) { FILE *fp; /* backing store */ VFP_T *cpVfp; /* local -> to a_cpVfp checkpointed VFP */ VFP_T *vfp; /* new VFP open on checkpointed backing store */ struct stat statbuf; /* stat(2) info on backing store */ /* * if no source VFP, or source VFP empty, * or no backing store, just open file */ if ((a_cpVfp == (VFP_T **)NULL) || (*a_cpVfp == (VFP_T *)NULL) || ((*a_cpVfp)->_vfpStart == (char *)NULL)) { (void) vfpClose(a_cpVfp); return (vfpOpen(r_vfp, a_path, a_mode, a_flags)); } /* localize access to checkpointed VFP_T (*a_cpVfp) */ cpVfp = *a_cpVfp; /* if no path specified, grab it from the checkpointed VFP */ if ((a_path == (char *)NULL) || (*a_path == '\0')) { a_path = cpVfp->_vfpPath; } /* return error if no path specified and no path in checkpointed VFP */ if ((a_path == (char *)NULL) && (*a_path == '\0')) { errno = EINVAL; return (-1); } /* if no backing store path, then just open file */ if (stat(a_path, &statbuf) != 0) { (void) vfpClose(a_cpVfp); return (vfpOpen(r_vfp, a_path, a_mode, a_flags)); } /* * if backing store tokens do not match checkpointed VFP, * the backing store has been updated since the VFP was checkpointed; * release the in-memory data, and open and read the backing store */ if ((statbuf.st_size != cpVfp->_vfpCkSize) || (statbuf.st_mtime != cpVfp->_vfpCkMtime) || (statbuf.st_blocks != cpVfp->_vfpCkStBlocks) || (statbuf.st_ino != cpVfp->_vfpCkIno) || (statbuf.st_dev != cpVfp->_vfpCkDev)) { (void) vfpClose(a_cpVfp); return (vfpOpen(r_vfp, a_path, a_mode, a_flags)); } /* * backing store has not been updated since the VFP was checkpointed; * use the in-memory data without re-reading the backing store; open the * backing store file (if no file already open on the checkpointed VFP) * so there is an open file associated with the in-memory data */ fp = cpVfp->_vfpFile; if (fp == (FILE *)NULL) { fp = fopen(a_path, a_mode); if (fp == (FILE *)NULL) { int lerrno; lerrno = errno; (void) vfpClose(a_cpVfp); errno = lerrno; return (-1); } } /* allocate new VFP object to return as open VFP */ vfp = (VFP_T *)malloc(sizeof (VFP_T)); if (vfp == (VFP_T *)NULL) { (void) vfpClose(a_cpVfp); return (vfpOpen(r_vfp, a_path, a_mode, a_flags)); } /* copy cached checkpointed VFP to new VFP to return */ (void) memcpy(vfp, cpVfp, sizeof (VFP_T)); /* * initialize VFP to return contents */ /* FILE -> file opened on the VFPs backing store */ vfp->_vfpFile = fp; /* release any existing path associated with the VFP */ if (vfp->_vfpPath != (char *)NULL) { (void) free(vfp->_vfpPath); } /* path associated with the backing store for this VFP */ vfp->_vfpPath = strdup(a_path); /* * data pointers associated with in memory copy of backing store * (such as _vfpHighWater, _vfpEnd, _vfpStart, etc.) * do not need to be modified because we are using the same backing * store as was checkpointed in cpVfp that is pointed to by vfp. */ /* _vfpCurr -> next byte to read */ vfp->_vfpCurr = (char *)vfp->_vfpStart; /* free checkpointed VFP as it is now open on "vfp" */ (void) free(cpVfp); /* reset callers -> checkpointed VFP */ (*a_cpVfp) = (VFP_T *)NULL; /* set return VFP pointer */ (*r_vfp) = vfp; /* success! */ return (0); }
int swapcfile(PKGserver server, VFP_T **a_cfTmpVfp, char *pkginst, int dbchg) { char *pe; char *pl; char *ps; char line[256]; char timeb[BUFSIZ]; int retval = RESULT_OK; struct tm *timep; time_t clock; /* normalize pkginst so its never null */ if (pkginst == (char *)NULL) { dbchg = 0; pkginst = "<unknown>"; } /* * If no changes were made to the database, checkpoint the temporary * contents file - if this fails, then just close the file which causes * the contents file to be reopened and reread if it is needed again */ if ((dbchg == 0) && (vfpGetModified(*a_cfTmpVfp) == 0)) { (void) pkgWunlock(); /* Free the database lock. */ return (retval); } /* * changes made to the current temporary contents file - * remove any trailing comment lines in the temp contents file, then * append updated modification info records to temp contents file */ pe = vfpGetCurrCharPtr(*a_cfTmpVfp); /* last char in contents file */ ps = vfpGetFirstCharPtr(*a_cfTmpVfp); /* 1st char in contents file */ pl = pe; /* last match is last char in contents file */ /* skip past all trailing newlines and null bytes */ while ((pe > ps) && ((*pe == '\n') || (*pe == '\0'))) { pe--; } /* remove trailing comments as long as there are lines in the file */ while (pe > ps) { if (*pe != '\n') { /* curr char is not newline: backup one byte */ pl = pe--; } else if (*pl != '#') { /* curr char is newline next char not comment break */ break; } else { /* curr char is newline next char is comment - remove */ *pl = '\0'; vfpSetLastCharPtr(*a_cfTmpVfp, pl); pe--; } } /* create two update comment lines */ (void) time(&clock); timep = localtime(&clock); (void) strftime(timeb, sizeof (timeb), "%c\n", timep); (void) snprintf(line, sizeof (line), gettext("# Last modified by %s for %s package\n# %s"), get_prog_name(), pkginst, timeb); vfpPuts(*a_cfTmpVfp, line); /* commit temporary contents file bytes to storage */ if (pkgservercommitfile(*a_cfTmpVfp, server) != 0) { int lerrno = errno; logerr(gettext(ERR_COMMIT)); vfpClose(a_cfTmpVfp); pkgcloseserver(server); (void) pkgWunlock(); /* Free the database lock. */ return (RESULT_ERR); } return (relslock() == 0 ? RESULT_ERR : retval); }
/* * This function installs the database lock, opens the contents file for * reading and creates and opens the temporary contents file for read/write. * It returns 1 if successful, 0 otherwise. */ int ocfile(PKGserver *server, VFP_T **r_tmpvfp, fsblkcnt_t map_blks) { struct stat64 statb, statl; struct statvfs64 svfsb; fsblkcnt_t free_blocks; fsblkcnt_t need_blocks; fsblkcnt_t log_blocks; VFP_T *tmpvfp = (VFP_T *)NULL; char contents[PATH_MAX]; char logfile[PATH_MAX]; int n; off_t cdiff_alloc; PKGserver newserver; /* establish package administration contents directory location */ if (pkgadm_dir == NULL) { if (set_cfdir(NULL) != 0) { progerr(gettext(ERR_CFDIR)); return (0); } } /* Lock the file for exclusive access */ if (!pkgWlock(1)) { progerr(gettext(ERR_NOLOCK)); return (0); } if (*server != NULL) { vfpTruncate(*r_tmpvfp); (void) vfpClearModified(*r_tmpvfp); return (1); } newserver = pkgopenserver(NULL, pkgadm_dir, B_FALSE); /* The error has been reported. */ if (newserver == NULL) return (0); /* reset return VFP/FILE pointers */ (*r_tmpvfp) = (VFP_T *)NULL; /* determine path to the primary contents file */ (void) snprintf(contents, sizeof (contents), "%s/contents", pkgadm_dir); /* * Check and see if there is enough space for the packaging commands * to back up the contents file, if there is not, then do not allow * execution to continue by failing the ocfile() call. */ /* Get the contents file size */ if (stat64(contents, &statb) == -1) { int lerrno = errno; progerr(gettext(ERR_NOCFILE), contents); logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); pkgcloseserver(newserver); return (0); } /* Get the filesystem space */ if (statvfs64(contents, &svfsb) == -1) { int lerrno = errno; progerr(gettext(ERR_NOSTATV), contents); logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); pkgcloseserver(newserver); return (0); } free_blocks = (((fsblkcnt_t)svfsb.f_frsize > 0) ? howmany(svfsb.f_frsize, DEV_BSIZE) : howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bfree; /* determine blocks used by the logfile */ (void) snprintf(logfile, sizeof (logfile), "%s/" PKGLOG, pkgadm_dir); if (stat64(logfile, &statl) == -1) log_blocks = 0; else log_blocks = nblk(statl.st_size, svfsb.f_bsize, svfsb.f_frsize); /* * Calculate the number of blocks we need to be able to operate on * the contents file and the log file. * When adding a package (map_blks > 0), we add the size of the * pkgmap file times 1.5 as the pkgmap is a bit smaller then the * lines added to the contents file. That data is written both to * the new contents file and the log file (2 * 1.5 * map_blks). * The new contents file is limited by the size of the current * contents file and the increased log file. * If we're removing a package, then the log might grow to the size * of the full contents file but then the new contents file would * be zero and so we only need to add the size of the contents file. */ need_blocks = map_blks * 3 + /* Current log file */ log_blocks + /* Current contents file */ nblk(statb.st_size, svfsb.f_bsize, svfsb.f_frsize); if ((need_blocks + 10) > free_blocks) { progerr(gettext(ERR_CFBACK), contents); progerr(gettext(ERR_CFBACK1), need_blocks, free_blocks, DEV_BSIZE); pkgcloseserver(newserver); return (0); } /* * open the temporary contents file without a path name - this causes * the "vfp" to be opened on in-memory storage only, the size of which * is set following a successful return - this causes the temporary * contents file to be maintained in memory only - if no changes are * made as the primary contents file is processed, the in memory data * is discarded and not written to the disk. */ if (vfpOpen(&tmpvfp, (char *)NULL, "w", VFP_NONE) != 0) { int lerrno = errno; progerr(gettext(ERR_NOTMPOPEN)); logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); pkgcloseserver(newserver); return (0); } /* * set size of allocation for temporary contents file - this sets the * size of the in-memory buffer associated with the open vfp. * We only store the new and changed entries. * We allocate memory depending on the size of the pkgmap; it's not * completely right but <some value + * 1.5 * map_blks * DEV_BSIZE> * seems fine (an install adds the size if the name of the package.) */ cdiff_alloc = map_blks * DEV_BSIZE; cdiff_alloc += cdiff_alloc/2; if (cdiff_alloc < 1000000) cdiff_alloc += 1000000; if (vfpSetSize(tmpvfp, cdiff_alloc) != 0) { int lerrno = errno; progerr(gettext(ERR_NOTMPOPEN)); logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno)); (void) vfpClose(&tmpvfp); pkgcloseserver(newserver); return (0); } /* set return ->s to open server/vfps */ (*r_tmpvfp) = tmpvfp; *server = newserver; return (1); /* All OK */ }
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); }
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*/ }