Esempio n. 1
0
/*
 * 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);
	}
}
Esempio n. 2
0
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);
}