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); }
static void rdcontents(void) { struct cfstat *dp; struct pinfo *pinfo; int n; PKGserver server; if (!socfile(&server, B_TRUE) || pkgopenfilter(server, pkgcnt == 1 ? pkg[0] : NULL) != 0) exit(1); /* check the contents file to look for referenced packages */ while ((n = srchcfile(&entry, "*", server)) > 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); } pkgcloseserver(server); }
/*ARGSUSED*/ int dofinal(VFP_T *vfp, VFP_T *vfpo, int rmflag, char *myclass, char *prog) { struct cfextra entry; int n, indx, dbchg; char *save_path = NULL; entry.cf_ent.pinfo = NULL; entry.fsys_value = BADFSYS; entry.fsys_base = BADFSYS; indx = 0; while (extlist && extlist[indx] && (extlist[indx]->cf_ent.ftype == 'i')) indx++; dbchg = 0; while (n = srchcfile(&(entry.cf_ent), "*", vfp, vfpo)) { if (n < 0) { char *errstr = getErrstr(); progerr(gettext ("bad entry read in contents file")); logerr(gettext("pathname=%s"), (entry.cf_ent.path && *(entry.cf_ent.path)) ? entry.cf_ent.path : "Unknown"); logerr(gettext("problem=%s"), (errstr && *errstr) ? errstr : "Unknown"); quit(99); } save_path = check_db_entry( vfpo, &entry, rmflag, myclass, &dbchg); /* Restore original server-relative path, if needed */ if (save_path != NULL) { entry.cf_ent.path = save_path; save_path = NULL; } } return (dbchg); }
/* * This is the function that cleans up the installation of this class. * This is where hard links get put in since the stuff they're linking * probably exists by now. */ static void endofclass(struct cfextra **extlist, int myclass, int ckflag, VFP_T **a_cfVfp, VFP_T **a_cfTmpVfp) { char *temppath; char *pspool_loc; char *relocpath = (char *)NULL; char scrpt_dst[PATH_MAX]; int flag; int idx; int n; struct cfent *ept; /* entry from the internal list */ struct cfextra entry; /* entry from the package database */ struct mergstat *mstat; /* merge status */ struct pinfo *pinfo; /* open the package database (contents) file */ if (!ocfile(a_cfVfp, a_cfTmpVfp, pkgmap_blks)) { quit(99); } echo(MSG_VERIFYING_CLASS, cl_nam(myclass)); for (idx = 0; /* void */; idx++) { /* find next package object in this class */ while (extlist[idx]) { if ((extlist[idx]->cf_ent.ftype != 'i') && extlist[idx]->cf_ent.pkg_class_idx == myclass) { break; } idx++; } if (extlist[idx] == NULL) { /* finish copying contents file and exit loop */ (void) srchcfile(&(entry.cf_ent), NULL, *a_cfVfp, *a_cfTmpVfp); break; } ept = &(extlist[idx]->cf_ent); mstat = &(extlist[idx]->mstat); temppath = extlist[idx] ? extlist[idx]->client_path : NULL; /* * At this point the only difference between the entry * in the contents file and the entry in extlist[] is * that the status indicator contains CONFIRM_CONT. * So for the new DB we use this knowledge and just * verify everything in accordance with extlist without * trying to retrieve the entry from the DB. */ n = srchcfile(&(entry.cf_ent), (ept ? temppath : NULL), *a_cfVfp, *a_cfTmpVfp); if (n == 0) { break; } else if (n < 0) { char *errstr = getErrstr(); progerr(ERR_CFBAD); logerr(gettext("pathname=%s\n"), entry.cf_ent.path && *entry.cf_ent.path ? entry.cf_ent.path : "Unknown"); logerr(gettext("problem=%s\n"), (errstr && *errstr) ? errstr : "Unknown"); quit(99); } else if (n != 1) { /* * Check if path should be in the package * database. */ if ((mstat->shared && nocnflct)) { continue; } progerr(ERR_CFMISSING, ept->path); quit(99); } /* * If merge was not appropriate for this object, now is the * time to choose one or the other. */ if (mstat->denied) { /* * If installation was denied AFTER the package * database was updated, skip this. We've already * announced the discrepancy and the verifications * that follow will make faulty decisions based on * the ftype, which may not be correct. */ progerr(ERR_COULD_NOT_INSTALL, ept->path); warnflag++; } else { if (mstat->replace) /* * This replaces the old entry with the new * one. This should never happen in the new * DB since the entries are already identical. */ repl_cfent(ept, &(entry.cf_ent)); /* * Validate this entry and change the status flag in * the package database. */ if (ept->ftype == RM_RDY) { (void) eptstat(&(entry.cf_ent), pkginst, STAT_NEXT); } else { /* check the hard link now. */ if (ept->ftype == 'l') { if (averify(0, &ept->ftype, ept->path, &ept->ainfo)) { echo(MSG_HRDLINK, ept->path); mstat->attrchg++; } } /* * Don't install or verify objects for * remote, read-only filesystems. We need * only flag them as shared from some server. * Otherwise, ok to do final check. */ if (is_remote_fs(ept->path, &(extlist[idx]->fsys_value)) && !is_fs_writeable(ept->path, &(extlist[idx]->fsys_value))) { flag = -1; } else { boolean_t inheritedFlag; inheritedFlag = z_path_is_inherited(ept->path, ept->ftype, get_inst_root()); flag = finalck(ept, mstat->attrchg, (ckflag ? mstat->contchg : (-1)), inheritedFlag); } pinfo = entry.cf_ent.pinfo; /* Find this package in the list. */ while (pinfo) { if (strcmp(pkginst, pinfo->pkg) == 0) { break; } pinfo = pinfo->next; } /* * If this package owns this file, then store * it in the database with the appropriate * status. Need to check pinfo in case it * points to NULL which could happen if * pinfo->next = NULL above. */ if (pinfo) { if (flag < 0 || is_served(ept->path, &(extlist[idx]->fsys_value))) { /* * This is provided to * clients by a server. */ pinfo->status = SERVED_FILE; } else { /* * It's either there or it's * not. */ pinfo->status = (flag ? NOT_FND : ENTRY_OK); } } } } /* * If not installing from a partially spooled package, the * "save/pspool" area, and the file contents can be * changed (type is 'e' or 'v'), and the class IS "none": * copy the installed volatile file into the appropriate * location in the packages destination "save/pspool" area. */ if ((!is_partial_inst()) && ((ept->ftype == 'e') || (ept->ftype == 'v')) && (strcmp(ept->pkg_class, "none") == 0)) { if (absolutepath(extlist[idx]->map_path) == B_TRUE && parametricpath(extlist[idx]->cf_ent.ainfo.local, &relocpath) == B_FALSE) { pspool_loc = ROOT; } else { pspool_loc = RELOC; } n = snprintf(scrpt_dst, PATH_MAX, "%s/%s/%s", saveSpoolInstallDir, pspool_loc, relocpath ? relocpath : extlist[idx]->map_path); if (n >= PATH_MAX) { progerr(ERR_CREATE_PATH_2, saveSpoolInstallDir, extlist[idx]->map_path); quit(99); } /* copy, preserve source file mode */ if (cppath(MODE_SRC, ept->path, scrpt_dst, 0644)) { warnflag++; } } /* * Now insert this potentially changed package database * entry. */ if (entry.cf_ent.npkgs) { if (putcvfpfile(&(entry.cf_ent), *a_cfTmpVfp)) { quit(99); } } } n = swapcfile(a_cfVfp, a_cfTmpVfp, pkginst, dbchg); if (n == RESULT_WRN) { warnflag++; } else if (n == RESULT_ERR) { quit(99); } }
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); }