Example #1
0
/*
 * This function reads in the various continuation file data in order to seed
 * the internal data structures.
 */
static boolean_t
read_continue_bin(void)
{
	int n;
	int fsentry_size = sizeof (struct fstable);
	int extentry_size = sizeof (struct cfextra);
	int pinfoentry_size = sizeof (struct pinfo);

	pkgobjinit();
	if (!init_pkgobjspace())
		return (B_FALSE);

	if ((fd_cnb = open(continue_bin, O_RDONLY)) == -1) {
		progerr(gettext(ERR_NOOPEN), continue_bin);
		return (B_FALSE);
	}

	/* Read the dryrun info structure. */
	if (read(fd_cnb, &dr_info, sizeof (struct drinfo)) == -1) {
		progerr(gettext(ERR_NOREAD), continue_bin);
		return (B_FALSE);
	}

	init_drinfo();

	if (this_type != dr_info.type) {
		progerr(gettext(ERR_BADTYPE),
		    (this_type == REMOVE_TYPE) ?
		    "a remove" : "an install",
		    (dr_info.type == REMOVE_TYPE) ?
		    "a remove" : "an install");
		return (B_FALSE);
	}

	/* Read in the dryrun package records. */
	for (n = 0; n < tot_pkgs; n++) {
		char pkg_name[PKGNAMESIZE];

		if (read(fd_cnb, &pkg_name, PKGNAMESIZE) == -1) {
			progerr(gettext(ERR_NOREAD), continue_bin);
			return (B_FALSE);
		}

		add_pkg_to_list(pkg_name);
	}

	/* Read in the fstable records. */
	for (n = 0; n < dr_info.total_fs_recs; n++) {
		struct fstable fs_entry;
		char name[PATH_MAX], remote_name[PATH_MAX];
		char fstype[200];

		if (read(fd_cnb, &fs_entry, fsentry_size) == -1) {
			progerr(gettext(ERR_NOREAD), continue_bin);
			return (B_FALSE);
		}

		if (read_string(fd_cnb, &name[0]) == NULL)
			return (B_FALSE);

		if (read_string(fd_cnb, &fstype[0]) == NULL)
			return (B_FALSE);

		if (read_string(fd_cnb, &remote_name[0]) == NULL)
			return (B_FALSE);

		if (load_fsentry(&fs_entry, name, fstype, remote_name)) {
			progerr(gettext(ERR_FSFAIL));
			return (B_FALSE);
		}
	}

	/* Read in the package objects and their attributes. */
	for (n = 0; n < dr_info.total_ext_recs; n++) {
		struct cfextra ext_entry;
		struct pinfo pinfo_area, *pinfo_ptr;
		char path[PATH_MAX], local[PATH_MAX], *local_ptr;

		if (read(fd_cnb, &ext_entry, extentry_size) == -1) {
			progerr(gettext(ERR_NOREAD), continue_bin);
			return (B_FALSE);
		}

		/*
		 * If the previous dryrun replaced a directory with a
		 * non-directory and we're going into *another* dryrun, we're
		 * stacking errors and continuation should not be permitted.
		 */
		if (ext_entry.mstat.dir2nondir && dryrun_mode)
			dr_info.do_not_continue = 1;

		/*
		 * Since we just read this from a continuation file; it is,
		 * by definition, preloaded.
		 */
		ext_entry.mstat.preloaded = 1;

		if (read_string(fd_cnb, &path[0]) == NULL)
			return (B_FALSE);

		local_ptr = read_string(fd_cnb, &local[0]);

		ext_entry.cf_ent.pinfo = NULL;

		/*
		 * Now all of the entries about the various packages that own
		 * this entry.
		 */
		do {
			if (read(fd_cnb, &pinfo_area, pinfoentry_size) == -1) {
				progerr(gettext(ERR_NOREAD), continue_bin);
				return (B_FALSE);

			}

			pinfo_ptr = eptstat(&(ext_entry.cf_ent),
			    pinfo_area.pkg, CONFIRM_CONT);

			if (pinfo_ptr->next) {
				pinfo_ptr = pinfo_ptr->next;
			} else {
				pinfo_ptr = NULL;
			}

		} while (pinfo_ptr);

		seed_pkgobjmap(&ext_entry, path, local_ptr);
	}

	(void) close(fd_cnb);

	/*
	 * Return as reading is done, so pkginstall doesn't
	 * read the same info from the system.
	 */

	return (B_TRUE);
}
Example #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);
	}
}
Example #3
0
/*
 * This writes out a dryrun file.
 */
static void
write_dryrun_bin()
{
	struct fstable *fs_entry;
	struct pinfo *pkginfo;
	struct dr_pkg_entry *pkg_entry;
	int n;
	int fsentry_size = sizeof (struct fstable);
	int extentry_size = sizeof (struct cfextra);
	int pinfoentry_size = sizeof (struct pinfo);

	if ((fd_drb = open(dryrun_bin,
	    O_RDWR | O_APPEND | O_TRUNC)) == -1) {
		progerr(gettext(ERR_NOOPEN), dryrun_bin);
		return;
	}

	/* Write the dryrun info table. */
	if (write(fd_drb, &dr_info, sizeof (struct drinfo)) == -1) {
		progerr(gettext(ERR_NOWRITE), dryrun_bin);
		return;
	}

	/* Write out the package instance list. */
	pkg_entry = dr_info.packages;
	while (pkg_entry) {
		if (write(fd_drb, pkg_entry->pkginst, PKGNAMESIZE) == -1) {
			progerr(gettext(ERR_NOWRITE), dryrun_bin);
			return;
		}
		pkg_entry = pkg_entry->next;
	}

	/* Write out the fstable records. */
	for (n = 0; n < dr_info.total_fs_recs; n++) {
		fs_entry = get_fs_entry(n);

		if (write(fd_drb, fs_entry, fsentry_size) == -1) {
			progerr(gettext(ERR_NOWRITE), dryrun_bin);
			return;
		}

		if (!write_string(fd_drb, fs_entry->name))
			return;

		if (!write_string(fd_drb, fs_entry->fstype))
			return;

		if (!write_string(fd_drb, fs_entry->remote_name))
			return;
	}

	/* Write out the package objects and their attributes. */
	for (n = 0; extptr && extptr[n]; n++) {
		/* Don't save metafiles. */
		if (extptr[n]->cf_ent.ftype == 'i')
			continue;

		/*
		 * If it's a new package object (not left over from the
		 * continuation file) and it indicates no changes to the
		 * system, skip it. Only files that will change the system
		 * are stored.
		 */
		if (extptr[n]->mstat.preloaded == 0 &&
		    !(this_exitcode == 0 &&
		    (extptr[n]->mstat.contchg || extptr[n]->mstat.attrchg)))
			continue;

		if (write(fd_drb, extptr[n], extentry_size) == -1) {
			progerr(gettext(ERR_NOWRITE), dryrun_bin);
			return;
		}

		if (!write_string(fd_drb, extptr[n]->cf_ent.path))
			return;

		if (!write_string(fd_drb, extptr[n]->cf_ent.ainfo.local))
			return;

		extptr[n]->cf_ent.pinfo = eptstat(&(extptr[n]->cf_ent),
		    pkginst, CONFIRM_CONT);

		/*
		 * Now all of the entries about the various packages that own
		 * this entry.
		 */
		pkginfo = extptr[n]->cf_ent.pinfo;

		do {
			if (write(fd_drb, pkginfo,
			    pinfoentry_size) == -1) {
				progerr(gettext(ERR_NOWRITE), dryrun_bin);
				return;
			}
			pkginfo = pkginfo->next;	/* May be several */
		} while (pkginfo);
	}

	(void) close(fd_drb);
}
Example #4
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);
}