/* * 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); } }
static char * check_db_entry(VFP_T *vfpo, struct cfextra *entry, int rmflag, char *myclass, int *dbchg) { struct pinfo *pinfo; int fs_entry; char *save_path = NULL; char *tp; /* write this entry to the contents file */ if (myclass && strcmp(myclass, entry->cf_ent.pkg_class)) { if (putcvfpfile(&entry->cf_ent, vfpo)) { progerr(gettext(ERR_WRITE)); quit(99); } return (NULL); } /* * Now scan each package instance holding this file or * directory and see if it matches the package we are * updating here. */ pinfo = entry->cf_ent.pinfo; while (pinfo) { if (strcmp(pkginst, pinfo->pkg) == 0) break; pinfo = pinfo->next; } /* * If pinfo == NULL at this point, then this file or * directory isn't part of the package of interest. * So the loop below executes only on files in the package * of interest. */ save_path = NULL; if (pinfo) { if (rmflag && (pinfo->status == RM_RDY)) { *dbchg = 1; (void) eptstat(&(entry->cf_ent), pkginst, '@'); if (entry->cf_ent.npkgs) { if (putcvfpfile(&(entry->cf_ent), vfpo)) { progerr(gettext(ERR_WRITE)); quit(99); } } return (NULL); } else if (!rmflag && (pinfo->status == INST_RDY)) { *dbchg = 1; /* tp is the server-relative path */ tp = fixpath(entry->cf_ent.path); /* save_path is the cmd line path */ save_path = entry->cf_ent.path; /* entry has the server-relative path */ entry->cf_ent.path = tp; /* * The next if statement figures out how * the contents file entry should be * annotated. * * Don't install or verify objects for * remote, read-only filesystems. We * need only verify their presence and * flag them appropriately from some * server. Otherwise, ok to do final * check. */ fs_entry = fsys(entry->cf_ent.path); if (is_remote_fs_n(fs_entry) && !is_fs_writeable_n(fs_entry)) { /* * Mark it shared whether it's present * or not. life's too funny for me * to explain. */ pinfo->status = SERVED_FILE; /* * restore for now. This may * chg soon. */ entry->cf_ent.path = save_path; } else { /* * If the object is accessible, check * the new entry for existence and * attributes. If there's a problem, * mark it NOT_FND; otherwise, * ENTRY_OK. */ if (is_mounted_n(fs_entry)) { int n; n = finalck((&entry->cf_ent), 1, 1, B_FALSE); pinfo->status = ENTRY_OK; if (n != 0) { pinfo->status = NOT_FND; } } /* * It's not remote, read-only but it * may look that way to the client. * If it does, overwrite the above * result - mark it shared. */ if (is_served_n(fs_entry)) pinfo->status = SERVED_FILE; /* restore original path */ entry->cf_ent.path = save_path; /* and clear save_path */ save_path = NULL; } } } /* Output entry to contents file. */ if (putcvfpfile(&(entry->cf_ent), vfpo)) { progerr(gettext(ERR_WRITE)); quit(99); } return (save_path); }