Ejemplo n.º 1
0
/*
 * This is a special fast verify which basically checks the attributes
 * and then, if all is OK, checks the size and mod time using the same
 * stat and statvfs structures.
 */
int
fverify(int fix, char *ftype, char *path, struct ainfo *ainfo,
    struct cinfo *cinfo)
{
	int retval;

	/* return success if attribute checks are disabled */

	if (get_disable_attribute_check()) {
		return (0);
	}

	if ((retval = averify(fix, ftype, path, ainfo)) == 0) {
		if (*ftype == 'f' || *ftype == 'i') {
			if (cinfo->size != status.st_size) {
				reperr(pkg_gt(WRN_QV_SIZE), path);
				retval = VE_CONT;
			}
			/* pcfs doesn't support modification times */
			if (strcmp(vfsstatus.f_basetype, "pcfs") != 0) {
				if (cinfo->modtime != status.st_mtime) {
					reperr(pkg_gt(WRN_QV_MTIME), path);
					retval = VE_CONT;
				}
			}
		}
	}

	return (retval);
}
Ejemplo n.º 2
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);
	}
}
Ejemplo n.º 3
0
static int
domerg(struct cfextra **extlist, int part, int nparts,
	int myclass, char **srcp, char **dstp,
	char **r_updated, char **r_skipped,
	char **r_anyPathLocal)
{
	boolean_t	stateFlag = B_FALSE;
	int		i;
	int		msg_ugid;
	static int	maxvol = 0;
	static int	svindx = 0;
	static int	svpart = 0;
	struct cfent	*ept = (struct cfent *)NULL;
	struct mergstat *mstat = (struct mergstat *)NULL;

	/* reset returned path pointers */

	*dstp = (char *)NULL;
	*srcp = (char *)NULL;

	/* set to start or continue based on which part being processed */

	if (part != 0) {
		maxvol = 0;
		svindx = 0;
		svpart = part;
	} else {
		i = svindx;
		part = svpart;
	}

	/*
	 * This goes through the pkgmap entries one by one testing them
	 * for inclusion in the package database as well as for validity
	 * against existing files.
	 */
	for (i = svindx; extlist[i]; i++) {
		ept = &(extlist[i]->cf_ent);
		mstat = &(extlist[i]->mstat);

		/*
		 * as paths are processed, if the "anyPathLocal" flag has not
		 * been set, if the object is not of type 'i' (package script),
		 * check to see if the object is in an area inherited from the
		 * global zone - if not, set "anyPathLocal" to the path found,
		 * indicating that at least one path is in an area that is not
		 * inherited from the global zone.
		 */

		if ((r_anyPathLocal != (char **)NULL) &&
			(*r_anyPathLocal == (char *)NULL) &&
			(ept->ftype != 'i') &&
			(z_path_is_inherited(ept->path, ept->ftype,
						get_inst_root()) == B_FALSE)) {
			echoDebug(DBG_INSTVOL_OBJ_LOCAL, ept->path);
			*r_anyPathLocal = ept->path;
		}

		/* if this isn't the class of current interest, skip it */

		if (myclass != ept->pkg_class_idx) {
			continue;
		}

		/* if the class is invalid, announce it & exit */
		if (ept->pkg_class_idx == -1) {
			progerr(ERR_CLIDX, ept->pkg_class_idx,
			    (ept->path && *ept->path) ? ept->path : "unknown");
			logerr(gettext("pathname=%s\n"),
			    (ept->path && *ept->path) ? ept->path : "unknown");
			logerr(gettext("class=<%s>\n"),
			    (ept->pkg_class && *ept->pkg_class) ?
			    ept->pkg_class : "Unknown");
			logerr(gettext("CLASSES=<%s>\n"),
			    getenv("CLASSES") ? getenv("CLASSES") : "Not Set");
			quit(99);
		}

		/*
		 * Next check to see if we are going to try to delete a
		 * populated directory in some distressing way.
		 */
		if (mstat->dir2nondir)
			if (dir_is_populated(ept->path)) {
				logerr(WRN_INSTVOL_NOTDIR, ept->path);
				warnflag++;
				mstat->denied = 1;	/* install denied! */
				continue;
			} else {	/* Replace is OK. */
				/*
				 * Remove this directory, so it won't
				 * interfere with creation of the new object.
				 */
				if (rmdir(ept->path)) {
					/*
					 * If it didn't work, there's nothing
					 * we can do. To continue would
					 * likely corrupt the filesystem
					 * which is unacceptable.
					 */
					progerr(ERR_RMDIR, ept->path);
					quit(99);
				}

				repl_permitted = 1;	/* flag it */
			}

		/* adjust the max volume number appropriately */

		if (ept->volno > maxvol) {
			maxvol = ept->volno;
		}

		/* if this part goes into another volume, skip it */

		if (part != ept->volno) {
			continue;
		}

		/*
		 * If it's a conflicting file and it's not supposed to be
		 * installed, note it and skip.
		 */
		if (nocnflct && mstat->shared && ept->ftype != 'e') {
			if (mstat->contchg || mstat->attrchg) {
				echo(MSG_SHIGN, ept->path);
			}
			continue;
		}

		/*
		 * If we want to set uid or gid but user says no, note it.
		 * Remember that the actual mode bits in the structure have
		 * already been adjusted and the mstat flag is telling us
		 * about the original mode.
		 */
		if (nosetuid && (mstat->setuid || mstat->setgid)) {
			msg_ugid = 1;	/* don't repeat attribute message. */
			if (is_fs_writeable(ept->path,
				&(extlist[i]->fsys_value))) {
				if (!(mstat->contchg) && mstat->attrchg) {
					echo(MSG_UGMOD, ept->path);
				} else {
					echo(MSG_UGID, ept->path);
				}
			}
		} else {
			msg_ugid = 0;
		}

		switch (ept->ftype) {
			case 'l':	/* hard link */
				/* links treated as object "update/skip" */
				stateFlag = B_TRUE;
				continue; /* defer to final proc */

			case 's': /* for symlink, verify without fix first */
				/* links treated as object "update/skip" */
				stateFlag = B_TRUE;

				/* Do this only for default verify */
				if (cl_dvfy(myclass) == DEFAULT) {
					if (averify(0, &ept->ftype,
						ept->path, &ept->ainfo))
						echo(MSG_SLINK, ept->path);
				}

				/*FALLTHRU*/

			case 'd':	/* directory */
			case 'x':	/* exclusive directory */
			case 'c':	/* character special device */
			case 'b':	/* block special device */
			case 'p':	/* named pipe */
				/* these NOT treated as object "update/skip" */
				stateFlag = B_FALSE;

				/*
				 * If we can't get to it for legitimate reasons,
				 * don't try to verify it.
				 */
				if ((z_path_is_inherited(ept->path, ept->ftype,
				    get_inst_root())) ||
				    is_remote_fs(ept->path,
				    &(extlist[i]->fsys_value)) &&
				    !is_fs_writeable(ept->path,
				    &(extlist[i]->fsys_value))) {
					mstat->attrchg = 0;
					mstat->contchg = 0;
					break;
				}

				if (averify(1, &ept->ftype, ept->path,
							&ept->ainfo) == 0) {
					mstat->contchg = mstat->attrchg = 0;
				} else {
					progerr(ERR_CREATE_PKGOBJ, ept->path);
					logerr(getErrbufAddr());
					warnflag++;
				}

				break;

			case 'i':	/* information file */
				/* not treated as object "update/skip" */
				stateFlag = B_FALSE;
				break;

			default:
				/* all files treated as object "update/skip" */
				stateFlag = B_TRUE;
				break;
		}

		/*
		 * Both contchg and shared flags have to be taken into
		 * account. contchg is set if the file is already present
		 * in the package database, if it does not exist or if it
		 * exists and is modified.
		 * The shared flag is set when 'e' or 'v' file is not
		 * present in the package database, exists and is not
		 * modified. It also has to be checked here.
		 * Shared flag is also set when file is present in package
		 * database and owned by more than one package, but for
		 * this case contchg has already been set.
		 */
		if (mstat->contchg || (mstat->shared &&
		    ((ept->ftype == 'e') || (ept->ftype == 'v')))) {
			*dstp = ept->path;
			if ((ept->ftype == 'f') || (ept->ftype == 'e') ||
				(ept->ftype == 'v')) {
				*srcp = ept->ainfo.local;
				if (is_partial_inst() != 0) {
					if (*srcp[0] == '~') {
						/* translate source pathname */
						*srcp = srcpath(instdir,
							extlist[i]->map_path,
							part, nparts);
					} else {
						*srcp = extlist[i]->map_path;
					}
				} else {
					if (*srcp[0] == '~') {
						/* translate source pathname */
						*srcp = srcpath(instdir,
						    &(ept->ainfo.local[1]),
						    part, nparts);
					}
				}

				echoDebug(DBG_DOMERG_NO_SUCH_FILE,
					ept->ftype, cl_nam(ept->pkg_class_idx),
					ept->path);
			} else {
				/*
				 * At this point, we're returning a non-file
				 * that couldn't be created in the standard
				 * way. If it refers to a filesystem that is
				 * not writeable by us, don't waste the
				 * calling process's time.
				 */
				if (!is_fs_writeable(ept->path,
					&(extlist[i]->fsys_value))) {
					echoDebug(DBG_DOMERG_NOT_WRITABLE,
						ept->ftype,
						cl_nam(ept->pkg_class_idx),
						ept->path);
					continue;
				}

				*srcp = NULL;
				echoDebug(DBG_DOMERG_NOT_THERE,
					ept->ftype, cl_nam(ept->pkg_class_idx),
					ept->path);
			}

			svindx = i+1;
			backup(*dstp, 1);
			return (i);
		}

		if (mstat->attrchg) {
			backup(ept->path, 0);
			if (!msg_ugid)
				echo(MSG_ATTRIB, ept->path);

			/* fix the attributes now for robustness sake */
			if (averify(1, &ept->ftype,
				ept->path,
				&ept->ainfo) == 0) {
				mstat->attrchg = 0;
			}
		}

		/*
		 * package object exists, or does not need updating: if the path
		 * is in an area inherited from the global zone, then treat
		 * the object as if it were "skipped" - if the path is not in an
		 * area inherited from the global zone, then treat the object as
		 * if it were "updated"
		 */

		/* LINTED warning: statement has no consequent: if */
		if ((stateFlag == B_FALSE) || (ept == (struct cfent *)NULL)) {
			/*
			 * the object in question is a directory or special
			 * file - the fact that this type of object already
			 * exists or does not need updating must not trigger
			 * the object updated/object skipped indication -
			 * that would cause class action scripts to be run
			 * when installing a new non-global zone - that action
			 * must only be done when a file object that is in
			 * an area inherited from the global zone is present.
			 */
		} else if (z_path_is_inherited(ept->path, ept->ftype,
						get_inst_root()) == B_TRUE) {
			if (r_skipped != (char **)NULL) {
				if (*r_skipped == (char *)NULL) {
					echoDebug(DBG_INSTVOL_OBJ_SKIPPED,
								ept->path);
					*r_skipped = ept->path;
				}
			}
		} else {
			if (r_updated != (char **)NULL) {
				if (*r_updated == (char *)NULL) {
					echoDebug(DBG_INSTVOL_OBJ_UPDATED,
								ept->path);
				}
				*r_updated = ept->path;
			}
		}
	}

	if (maxvol == part) {
		eocflag++;	/* endofclass */
	}

	return (DMRG_DONE);	/* no remaining entries on this volume */
}
Ejemplo n.º 4
0
static void
outvol(struct cfent **eptlist, int eptnum, int part, int nparts)
{
	FILE	*fp;
	char	*svpt, *path, temp[PATH_MAX];
	int	i;


	if (nparts > 1)
		(void) fprintf(stderr, gettext(" -- part %2d:\n"), part);
	if (part == 1) {
		/* re-write pkgmap, but exclude local pathnames */
		(void) snprintf(temp, sizeof (temp), "%s/pkgmap", pkgloc);
		if ((fp = fopen(temp, "w")) == NULL) {
			progerr(gettext(ERR_TEMP), errno);
			quit(99);
		}
		(void) fprintf(fp, ": %d %ld\n", nparts, limit);
		for (i = 0; eptlist[i]; i++) {
			svpt = eptlist[i]->ainfo.local;
			if (!strchr("sl", eptlist[i]->ftype))
				eptlist[i]->ainfo.local = NULL;
			if (ppkgmap(eptlist[i], fp)) {
				progerr(gettext(ERR_TEMP), errno);
				quit(99);
			}
			eptlist[i]->ainfo.local = svpt;
		}
		(void) fclose(fp);
		(void) fprintf(stderr, "%s\n", temp);
	}

	(void) snprintf(temp, sizeof (temp), "%s/pkginfo", pkgloc);
	if (copyf(svept->ainfo.local, temp, svept->cinfo.modtime))
		quit(1);
	(void) fprintf(stderr, "%s\n", temp);

	for (i = 0; i < eptnum; i++) {
		if (eptlist[i]->volno != part)
			continue;
		if (strchr("dxslcbp", eptlist[i]->ftype))
			continue;
		if (eptlist[i]->ftype == 'i') {
			if (eptlist[i] == svept)
				continue; /* don't copy pkginfo file */
			(void) snprintf(temp, sizeof (temp),
				"%s/install/%s", pkgloc,
				eptlist[i]->path);
			path = temp;
		} else
			path = srcpath(pkgloc, eptlist[i]->path, part, nparts);
		if (sflag) {
			if (slinkf(eptlist[i]->ainfo.local, path))
				quit(1);
		} else if (copyf(eptlist[i]->ainfo.local, path,
				eptlist[i]->cinfo.modtime)) {
			quit(1);
		}

		/*
		 * If the package file attributes can be sync'd up with
		 * the pkgmap, we fix the attributes here.
		 */
		if (*(eptlist[i]->ainfo.owner) != '$' &&
		    *(eptlist[i]->ainfo.group) != '$' && getuid() == 0) {
			/* Clear dangerous bits. */
			eptlist[i]->ainfo.mode=
			    (eptlist[i]->ainfo.mode & S_IAMB);
			/*
			 * Make sure it can be read by the world and written
			 * by root.
			 */
			eptlist[i]->ainfo.mode |= 0644;
			if (!strchr("in", eptlist[i]->ftype)) {
				/* Set the safe attributes. */
				averify(1, &(eptlist[i]->ftype),
				    path, &(eptlist[i]->ainfo));
			}
		}

		(void) fprintf(stderr, "%s\n", path);
	}
}