Ejemplo n.º 1
0
static int
readspace(char *spacefile, int *error)
{
	FILE	*fp;
	char	line[LSIZE];
	long	blocks, nodes;
	int	n;

	if (spacefile == NULL)
		return (0);

	if ((fp = fopen(spacefile, "r")) == NULL) {
		progerr(gettext("unable to open spacefile %s"), spacefile);
		return (-1);
	}

	while (fgets(line, LSIZE, fp)) {
		struct fstable *fs_tab;
		char *pt, path[PATH_MAX];

		blocks = nodes = 0;
		for (pt = line; isspace(*pt); /* void */)
			pt++;
		if (*pt == '#' || *pt == '\0')
			continue;

		(void) sscanf(line, "%s %ld %ld", path, &blocks, &nodes);
		mappath(2, path);
		basepath(path, get_basedir(), get_inst_root());
		canonize(path);

		n = resolved_fsys(path);
		if (fsys_stat(n)) {
			(*error)++;
			continue;
		}

		/*
		 * Don't accumulate space requirements on read-only
		 * remote filesystems. NOTE: For some reason, this
		 * used to check for !remote && read only. If this
		 * blows up later, then maybe that was correct -- JST
		 */
		if (is_remote_fs_n(n) && !is_fs_writeable_n(n))
			continue;

		fs_tab = get_fs_entry(n);

		fs_tab->bused += blocks;
		fs_tab->fused += nodes;
	}
	(void) fclose(fp);
	return (0);
}
Ejemplo n.º 2
0
void
merginfo(struct cl_attr **pclass, int install_from_pspool)
{
	DIR		*pdirfp;
	FILE		*fp;
	FILE		*pkginfoFP;
	char		path[PATH_MAX];
	char		cmd[PATH_MAX];
	char		pkginfoPath[PATH_MAX];
	char		temp[PATH_MAX];
	int		i;
	int		nc;
	int		out;

	/* remove savelog from previous attempts */

	(void) unlink(savlog);

	/*
	 * create path to appropriate pkginfo file for the package that is
	 * already installed - is_spool_create() will be set (!= 0) if the
	 * -t option is presented to pkginstall - the -t option is used to
	 * disable save spool area creation; do not spool any partial package
	 * contents, that is, suppress the creation and population of the
	 * package save spool area (var/sadm/pkg/PKG/save/pspool/PKG). This
	 * option is set only when a non-global zone is being created.
	 */

	if (is_spool_create() == 0) {
		/*
		 * normal package install (not a non-global zone install);
		 * use the standard installed pkginfo file for this package:
		 * --> /var/sadm/pkg/PKGINST/pkginfo
		 * as the source pkginfo file to scan.
		 */
		i = snprintf(pkginfoPath, sizeof (pkginfoPath),
			"%s/var/sadm/pkg/%s/%s",
			((get_inst_root()) &&
			(strcmp(get_inst_root(), "/") != 0)) ?
			get_inst_root() : "", pkginst,
			PKGINFO);
		if (i > sizeof (pkginfoPath)) {
			progerr(ERR_CREATE_PATH_2,
				((get_inst_root()) &&
				(strcmp(get_inst_root(), "/") != 0)) ?
				get_inst_root() : "/",
				pkginst);
			quit(1);
		}
	} else {
		/*
		 * non-global zone installation - use the "saved" pspool
		 * pkginfo file in the global zone for this package:
		 * --> /var/sadm/install/PKG/save/pspool/PKG/pkginfo
		 * as the source pkginfo file to scan.
		 */
		i = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/%s",
			saveSpoolInstallDir, PKGINFO);
		if (i > sizeof (pkginfoPath)) {
			progerr(ERR_CREATE_PATH_2,
				saveSpoolInstallDir, PKGINFO);
			quit(1);
		}
	}

	i = snprintf(path, PATH_MAX, "%s/%s", pkgloc, PKGINFO);
	if (i > PATH_MAX) {
		progerr(ERR_CREATE_PATH_2, pkgloc, PKGINFO);
		quit(1);
	}

	/* entry debugging info */

	echoDebug(DBG_MERGINFO_ENTRY,
		instdir ? instdir : "??",
		((get_inst_root()) &&
		(strcmp(get_inst_root(), "/") != 0)) ?
		get_inst_root() : "??",
		saveSpoolInstallDir ? saveSpoolInstallDir : "??",
		pkgloc ? pkgloc : "??",	is_spool_create(),
		get_info_basedir() ? get_info_basedir() : "??",
		pkginfoPath, path);

	/*
	 * open the pkginfo file:
	 * if the source pkginfo file to check is the same as the merged one
	 * (e.g. /var/sadm/pkg/PKGINST/pkginfo) then do not open the source
	 * pkginfo file to "verify"
	 */

	if (strcmp(pkginfoPath, path) == 0) {
		pkginfoFP = (FILE *)NULL;
		echoDebug(DBG_MERGINFO_SAME, path);
	} else {
		echoDebug(DBG_MERGINFO_DIFFERENT, pkginfoPath, path);
		pkginfoFP = fopen(pkginfoPath, "r");

		if (pkginfoFP == (FILE *)NULL) {
			echoDebug(ERR_NO_PKG_INFOFILE, pkginst, pkginfoPath,
				strerror(errno));
		}
	}

	/*
	 * output packaging environment to create a pkginfo file in pkgloc[]
	 */

	if ((fp = fopen(path, "w")) == NULL) {
		progerr(ERR_CANNOT_OPEN_FOR_WRITING, path, strerror(errno));
		quit(99);
	}

	/*
	 * output CLASSES attribute
	 */

	out = 0;
	(void) fputs("CLASSES=", fp);
	if (pclass) {
		(void) fputs(pclass[0]->name, fp);
		out++;
		for (i = 1; pclass[i]; i++) {
			(void) putc(' ', fp);
			(void) fputs(pclass[i]->name, fp);
			out++;
		}
	}
	nc = cl_getn();
	for (i = 0; i < nc; i++) {
		int found = 0;

		if (pclass) {
			int	j;

			for (j = 0; pclass[j]; ++j) {
				if (cl_nam(i) != NULL &&
					strcmp(cl_nam(i),
					pclass[j]->name) == 0) {
					found++;
					break;
				}
			}
		}
		if (!found) {
			if (out > 0) {
				(void) putc(' ', fp);
			}
			(void) fputs(cl_nam(i), fp);
			out++;
		}
	}
	(void) putc('\n', fp);

	/*
	 * NOTE : BASEDIR below is relative to the machine that
	 * *runs* the package. If there's an install root, this
	 * is actually the CLIENT_BASEDIR wrt the machine
	 * doing the pkgadd'ing here. -- JST
	 */

	if (is_a_basedir()) {
		static char	*txs1 = "BASEDIR=";

		(void) fputs(txs1, fp);
		(void) fputs(get_info_basedir(), fp);
		(void) putc('\n', fp);
	} else {
		(void) fputs("BASEDIR=/", fp);
		(void) putc('\n', fp);
	}

	/*
	 * output all other environment attributes except those which
	 * are relevant only to install.
	 */

	for (i = 0; environ[i] != (char *)NULL; i++) {
		char	*ep = environ[i];
		int	attrPos = -1;
		int	incr = (ATTRTBL_SIZE >> 1)+1;	/* searches possible */
		int	pos = ATTRTBL_SIZE >> 1;	/* start in middle */
		NAMELIST_T	*pp = (NAMELIST_T *)NULL;

		/*
		 * find this attribute in the table - accept the attribute if it
		 * is outside of the bounds of the table; otherwise, do a binary
		 * search looking for this attribute.
		 */

		if (strncmp(ep, attrTbl[0]._nlName, attrTbl[0]._nlLen) < 0) {

			/* entry < first entry in attribute table */

			echoDebug(DBG_MERGINFO_LESS_THAN, ep,
				attrTbl[0]._nlName);

		} else if (strncmp(ep, attrTbl[ATTRTBL_SIZE-1]._nlName,
				attrTbl[ATTRTBL_SIZE-1]._nlLen) > 0) {

			/* entry > last entry in attribute table */

			echoDebug(DBG_MERGINFO_GREATER_THAN, ep,
				attrTbl[ATTRTBL_SIZE-1]._nlName);

		} else {
			/* first entry < entry < last entry in table: search */

			echoDebug(DBG_MERGINFO_SEARCHING, ep,
				attrTbl[0]._nlName,
				attrTbl[ATTRTBL_SIZE-1]._nlName);

			while (incr > 0) {	/* while possible to divide */
				int	r;

				pp = &attrTbl[pos];

				/* compare current attr with this table entry */
				r = strncmp(pp->_nlName, ep, pp->_nlLen);

				/* break out of loop if match */
				if (r == 0) {
					/* save location/break if match found */
					attrPos = pos;
					break;
				}

				/* no match search to next/prev half */
				incr = incr >> 1;
				pos += (r < 0) ? incr : -incr;
				continue;
			}
		}

		/* handle excluded attribute found */

		if ((attrPos >= 0) && (pp->_nlFlag == FLAG_EXCLUDE)) {
			/* attribute is excluded */
			echoDebug(DBG_MERGINFO_EXCLUDING, ep);
			continue;
		}

		/* handle fixed attribute found */

		if ((pkginfoFP != (FILE *)NULL) && (attrPos >= 0) &&
			(pp->_nlFlag == FLAG_IDENTICAL)) {
			/* attribute must not change */

			char	*src = ep+pp->_nlLen;
			char	*trg;
			char	theAttr[PATH_MAX+1];

			/* isolate attribute name only without '=' at end */

			(void) strncpy(theAttr, pp->_nlName, pp->_nlLen-1);
			theAttr[pp->_nlLen-1] = '\0';

			/* lookup attribute in installed package pkginfo file */

			rewind(pkginfoFP);
			trg = fpkgparam(pkginfoFP, theAttr);

			echoDebug(DBG_MERGINFO_ATTRCOMP, theAttr,
				trg ? trg : "");

			/* if target not found attribute is being added */

			if (trg == (char *)NULL) {
				progerr(ERR_PKGINFO_ATTR_ADDED, pkginst, ep);
				quit(1);
			}

			/* error if two values are not the same */

			if (strcmp(src, trg) != 0) {
				progerr(ERR_PKGINFO_ATTR_CHANGED, pkginst,
					theAttr, src, trg);
				quit(1);
			}
		}

		/* attribute not excluded/has not changed - process */

		if ((strncmp(ep, "PKGSAV=", 7) == 0)) {
			(void) fputs("PKGSAV=", fp);
			(void) fputs(infoloc, fp);
			(void) putc('/', fp);
			(void) fputs(pkginst, fp);
			(void) fputs("/save\n", fp);
			continue;
		}

		if ((strncmp(ep, "UPDATE=", 7) == 0) &&
				install_from_pspool != 0 &&
				!isPatchUpdate() &&
				!isUpdate()) {
			continue;
		}

		echoDebug(DBG_MERGINFO_FINAL, ep);

		(void) fputs(ep, fp);
		(void) putc('\n', fp);
	}

	(void) fclose(fp);
	(void) fclose(pkginfoFP);

	/*
	 * copy all packaging scripts to appropriate directory
	 */

	i = snprintf(path, PATH_MAX, "%s/install", instdir);
	if (i > PATH_MAX) {
		progerr(ERR_CREATE_PATH_2, instdir, "/install");
		quit(1);
	}

	if ((pdirfp = opendir(path)) != NULL) {
		struct dirent	*dp;

		while ((dp = readdir(pdirfp)) != NULL) {
			if (dp->d_name[0] == '.')
				continue;

			i = snprintf(path, PATH_MAX, "%s/install/%s",
					instdir, dp->d_name);
			if (i > PATH_MAX) {
				progerr(ERR_CREATE_PATH_3, instdir, "/install/",
					dp->d_name);
				quit(1);
			}

			i = snprintf(temp, PATH_MAX, "%s/%s", pkgbin,
					dp->d_name);
			if (i > PATH_MAX) {
				progerr(ERR_CREATE_PATH_2, pkgbin, dp->d_name);
				quit(1);
			}

			if (cppath(MODE_SRC|DIR_DISPLAY, path, temp, 0644)) {
			    progerr(ERR_CANNOT_COPY, dp->d_name, pkgbin);
				quit(99);
			}
		}
		(void) closedir(pdirfp);
	}

	/*
	 * copy all packaging scripts to the partial spool directory
	 */

	if (!is_spool_create()) {
		/* packages are being spooled to ../save/pspool/.. */
		i = snprintf(path, PATH_MAX, "%s/install", instdir);
		if (i > PATH_MAX) {
			progerr(ERR_CREATE_PATH_2, instdir, "/install");
			quit(1);
		}

		if (((pdirfp = opendir(path)) != NULL) &&
			!isPatchUpdate()) {
			struct dirent	*dp;


			while ((dp = readdir(pdirfp)) != NULL) {
				if (dp->d_name[0] == '.')
					continue;
				/*
				 * Don't copy i.none since if it exists it
				 * contains Class Archive Format procedure
				 * for installing archives. Only Directory
				 * Format packages can exist
				 * in a global spooled area.
				 */
				if (strcmp(dp->d_name, "i.none") == 0)
					continue;

				i = snprintf(path, PATH_MAX, "%s/install/%s",
						instdir, dp->d_name);

				if (i > PATH_MAX) {
					progerr(ERR_CREATE_PATH_3, instdir,
						"/install/", dp->d_name);
					quit(1);
				}

				i = snprintf(temp, PATH_MAX, "%s/install/%s",
						saveSpoolInstallDir,
						dp->d_name);

				if (i > PATH_MAX) {
					progerr(ERR_CREATE_PATH_3,
						saveSpoolInstallDir,
						"/install/", dp->d_name);
					quit(1);
				}

				if (cppath(MODE_SRC, path, temp, 0644)) {
					progerr(ERR_CANNOT_COPY, path, temp);
					(void) closedir(pdirfp);
					quit(99);
				}
			}
			(void) closedir(pdirfp);
		}

		/*
		 * Now copy the original pkginfo and pkgmap files from the
		 * installing package to the spooled directory.
		 */

		i = snprintf(path, sizeof (path), "%s/%s", instdir, PKGINFO);
		if (i > sizeof (path)) {
			progerr(ERR_CREATE_PATH_2, instdir, PKGINFO);
			quit(1);
		}

		i = snprintf(temp, sizeof (temp), "%s/%s",
				saveSpoolInstallDir, PKGINFO);
		if (i > sizeof (temp)) {
			progerr(ERR_CREATE_PATH_2, saveSpoolInstallDir,
				PKGINFO);
			quit(1);
		}

		if (cppath(MODE_SRC, path, temp, 0644)) {
			progerr(ERR_CANNOT_COPY, path, temp);
			quit(99);
		}

		/*
		 * Only want to copy the FCS pkgmap if this is not a
		 * patch installation.
		 */

		if (!isPatchUpdate()) {
			i = snprintf(path, sizeof (path), "%s/pkgmap", instdir);
			if (i > sizeof (path)) {
				progerr(ERR_CREATE_PATH_2, instdir, "pkgmap");
				quit(1);
			}

			i = snprintf(temp, sizeof (temp), "%s/pkgmap",
				saveSpoolInstallDir);
			if (i > sizeof (path)) {
				progerr(ERR_CREATE_PATH_2, saveSpoolInstallDir,
					"pkgmap");
				quit(1);
			}

			if (cppath(MODE_SRC, path, temp, 0644)) {
				progerr(ERR_CANNOT_COPY, path, temp);
				quit(99);
			}
		}
	}

	/*
	 * If we are installing from a spool directory
	 * copy the save directory from it, it may have
	 * been patched. Duplicate it only if this
	 * installation isn't an update and is not to
	 * an alternate root.
	 */
	if (strstr(instdir, "pspool") != NULL) {
		struct stat status;

		i = snprintf(path, sizeof (path), "%s/save", instdir);
		if (i > sizeof (path)) {
			progerr(ERR_CREATE_PATH_2, instdir, "save");
			quit(1);
		}

		if ((stat(path, &status) == 0) &&
				(status.st_mode & S_IFDIR) &&
				!isPatchUpdate()) {
			i = snprintf(cmd, sizeof (cmd), "cp -pr %s/* %s",
					path, pkgsav);
			if (i > sizeof (cmd)) {
				progerr(ERR_SNPRINTF, "cp -pr %s/* %s");
				quit(1);
			}

			if (system(cmd)) {
				progerr(ERR_PKGBINCP, path, pkgsav);
				quit(99);
			}
		}
	}
}
Ejemplo n.º 3
0
/*
 * get_mntinfo - get the mount table, now dynamically allocated. Returns 0 if
 * no problem and 1 if there's a fatal error.
 */
int
get_mntinfo(int map_client, char *vfstab_file)
{
	static 	char 	*rn = "/";
	FILE		*pp;
	struct	mnttab	mtbuf;
	struct	mnttab	*mt = &mtbuf;
	char		*install_root;
	int 		is_remote;

	/*
	 * Open the mount table for the current host and establish a global
	 * table that holds data about current mount status.
	 */
	if ((pp = setmntent(MOUNT_TABLE, "r")) == NULL) {
		progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno));
		return (1);
	}

	/*
	 * First, review the mounted filesystems on the managing host. This
	 * may also be the target host but we haven't decided that for sure
	 * yet.
	 */
	while (!getmntent(pp, mt))
		if (construct_mt(mt))
			return (1);

	(void) endmntent(pp);

	/*
	 * Now, we see if this installation is to a client. If it is, we scan
	 * the client's vfstab to determine what filesystems are
	 * inappropriate to write to. This simply adds the vfstab entries
	 * representing what will be remote file systems for the client.
	 * Everything that isn't remote to the client is already accounted
	 * for in the fs_tab[] so far. If the remote filesystem is really on
	 * this server, we will write through to the server from this client.
	 */
	install_root = get_inst_root();
	if (install_root && strcmp(install_root, "/") != 0 && map_client) {
		/* OK, this is a legitimate remote client. */
		struct	vfstab	vfsbuf;
		struct	vfstab	*vfs = &vfsbuf;
		char VFS_TABLE[PATH_MAX];

		/*
		 * Since we use the fsys() function later, and it depends on
		 * an ordered list, we have to sort the list here.
		 */
		qsort(fs_tab, fs_tab_used,
		    sizeof (struct fstable *), fs_tab_ent_comp);

		/*
		 * Here's where the vfstab for the target is. If we can get
		 * to it, we'll scan it for what the client will see as
		 * remote filesystems, otherwise, we'll just skip this.
		 */
		if (vfstab_file) {
			(void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s",
			    vfstab_file);
		} else {
			(void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s%s",
			    install_root, VFSTAB);
		}

		if (access(VFS_TABLE, R_OK) == 0) {
			char *link_name;

			/*
			 * Open the vfs table for the target host.
			 */
			if ((pp = setmntent(VFS_TABLE, "r")) == NULL) {
				progerr(ERR_NOTABLE, "vfs", VFS_TABLE,
				    strerror(errno));
				return (1);
			}

			/* Do this for each entry in the vfstab. */
			while (!getvfsent(pp, vfs)) {
				char client_mountp[PATH_MAX];
				int mnt_stat;

				/*
				 * We put it into the fs table if it's
				 * remote mounted (even from this server) or
				 * loopback mounted from the client's point
				 * of view.
				 */
				if (!(is_remote =
				    is_remote_src(vfs->vfs_special)) &&
				    strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) !=
				    0)
					continue;	/* not interesting */

				/*
				 * Construct client_mountp by prepending the
				 * install_root to the 'mount point' name.
				 */
				if (strcmp(vfs->vfs_mountp, "/") == 0) {
					(void) strcpy(client_mountp,
					    install_root);
				} else {
					(void) snprintf(client_mountp,
					    sizeof (client_mountp), "%s%s",
					    install_root, vfs->vfs_mountp);
				}

				/*
				 * We also skip the entry if the vfs_special
				 * path and the client_path are the same.
				 * There's no need to mount it, it's just a
				 * cachefs optimization that mounts a
				 * directory over itself from this server.
				 */
				if ((is_remote == SELF_SERVE) &&
				    strcmp(path_part(vfs->vfs_special),
				    client_mountp) == 0)
					continue;

				/* Determine if this is already mounted. */
				link_name = strdup(path_part(vfs->vfs_special));
				mnt_stat = already_mounted(vfs,
				    (is_remote != REAL_REMOTE), client_mountp,
				    link_name);

				if (mnt_stat == MNT_EXACT) {
					mod_existing(vfs, match_mount,
					    is_remote);
				} else {	/* MNT_NOT */
					if (construct_vfs(vfs, client_mountp,
					    link_name, is_remote, mnt_stat)) {
						return (1);
					}
				}
			}
			(void) endmntent(pp);
		}	/* end of if(access()) */
	}	/* end of if(install_root) */

	/* This next one may look stupid, but it can really happen. */
	if (fs_tab_used <= 0) {
		progerr(ERR_MNT_NOMOUNTS);
		return (1);
	}

	/*
	 * Now that we have the complete list of mounted (or virtually
	 * mounted) filesystems, we sort the mountpoints in reverse order
	 * based on the length of the 'mount point' name.
	 */
	qsort(fs_tab, fs_tab_used, sizeof (struct fstable *), fs_tab_ent_comp);
	if (strcmp(fs_tab[fs_tab_used-1]->name, rn) != 0) {
		progerr(ERR_MNT_NOROOT, fs_tab[fs_tab_used-1]->name, rn, errno,
		    strerror(errno));
		return (1);
	} else {
		return (0);
	}
}
Ejemplo n.º 4
0
static void
write_dryrun_ascii()
{
	int n;
	char *fs_mntpt, *src_name;

	if ((fp_dra = fopen(dryrun_sumasc, "wb")) == NULL) {
		progerr(gettext(ERR_NOOPEN), dryrun_sumasc);
		return;
	}

	(void) fprintf(fp_dra, "DR_TYPE=%s\n", (dr_info.type == REMOVE_TYPE ?
	    "REMOVE" : "INSTALL"));

	(void) fprintf(fp_dra, "PKG_INSTALL_ROOT=%s\n", (((get_inst_root()) &&
	    (strcmp(get_inst_root(), "/") != 0)) ?
	    get_inst_root() : ""));

	write_pkglist_ascii();

	wr_OK(fp_dra, "CONTINUE", 1, !(dr_info.do_not_continue));

	wr_OK(fp_dra, "PARTIAL", dr_info.partial_set, dr_info.partial);

	wr_OK(fp_dra, "RUNLEVEL", dr_info.runlevel_set, dr_info.runlevel);

	(void) fprintf(fp_dra, "REQUESTEXITCODE=%d\n", dr_info.reqexit);

	(void) fprintf(fp_dra, "CHECKINSTALLEXITCODE=%d\n", dr_info.checkexit);

	wr_OK(fp_dra, "PKGFILES", dr_info.pkgfiles_set, dr_info.pkgfiles);

	wr_OK(fp_dra, "DEPEND", dr_info.depend_set, dr_info.depend);

	wr_OK(fp_dra, "SPACE", dr_info.space_set, dr_info.space);

	wr_OK(fp_dra, "CONFLICT", dr_info.conflict_set, dr_info.conflict);

	wr_OK(fp_dra, "SETUID", dr_info.setuid_set, dr_info.setuid);

	wr_OK(fp_dra, "PRIV", dr_info.priv_set, dr_info.priv);

	wr_OK(fp_dra, "PKGDIRS", dr_info.pkgdirs_set, dr_info.pkgdirs);

	(void) fprintf(fp_dra, "EXITCODE=%d\n", dr_info.exitcode);

	(void) fprintf(fp_dra, "ERRORMSG=%s\n", (exitmsg ? exitmsg : "NONE"));

	(void) fclose(fp_dra);

	if ((fp_dra = fopen(dryrun_fsasc, "wb")) == NULL) {
		progerr(gettext(ERR_NOOPEN), dryrun_fsasc);
		return;
	}

	(void) fprintf(fp_dra, "%s\nFSUSAGE=\\\n\"\\\n", HDR_FSUSAGE);

	for (n = 0; fs_mntpt = get_fs_name_n(n); n++) {
		int bfree, bused;
		bfree = get_blk_free_n(n);
		bused = get_blk_used_n(n);

		if (bfree || bused) {
			(void) fprintf(fp_dra, "%s %s %s %d %d %lu %lu \\\n",
			    fs_mntpt,
			    ((src_name = get_source_name_n(n)) ?
			    src_name : "none?"),
			    (is_fs_writeable_n(n) ? "TRUE" : "FALSE"),
			    bfree,
			    bused,
			    get_inode_free_n(n),
			    get_inode_used_n(n));
		}
	}

	dr_info.total_fs_recs = n;

	(void) fprintf(fp_dra, "\"\n");

	(void) fclose(fp_dra);

	if ((fp_dra = fopen(dryrun_poasc, "wb")) == NULL) {
		progerr(gettext(ERR_NOOPEN), dryrun_poasc);
		return;
	}

	dr_info.total_ext_recs = 0;

	(void) fprintf(fp_dra, "WOULD_INSTALL=\\\n\"\\\n");

	for (n = 0; extptr && extptr[n]; n++) {
		/*
		 * Write it out if it's a successful change or it is from the
		 * prior dryrun file (meaning it was a change back then).
		 */
		if ((this_exitcode == 0 &&
		    (extptr[n]->mstat.contchg || extptr[n]->mstat.attrchg)) ||
		    extptr[n]->mstat.preloaded) {
			(void) fprintf(fp_dra, "%c %s \\\n",
				extptr[n]->cf_ent.ftype,
				extptr[n]->client_path);

			/* Count it, if it's going into the dryrun file. */
			if (extptr[n]->cf_ent.ftype != 'i')
				dr_info.total_ext_recs++;
		}
	}

	(void) fprintf(fp_dra, "\"\n");

	(void) fclose(fp_dra);
}
Ejemplo n.º 5
0
int
main(int argc, char **argv)
{
	int	c;

	pkgdir = NULL;
	setErrstr(NULL);

	/* initialize locale mechanism */

#if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
#define	TEXT_DOMAIN "SYS_TEST"
#endif
	(void) textdomain(TEXT_DOMAIN);

	/* determine program name */

	(void) set_prog_name(argv[0]);

	/* tell spmi zones interface how to access package output functions */

	z_set_output_functions(echo, echoDebug, progerr);

	/* establish installation root directory */

	if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
		progerr(gettext(ERR_ROOT_SET));
		exit(1);
	}

	while ((c = getopt(argc, argv, "LNR:xv:a:d:qrpilc:?")) != EOF) {
		switch (c) {
		    case 'v':
			ckvers = optarg;
			break;

		    case 'a':
			ckarch = optarg;
			break;

		    case 'd':
			/* -d could specify stream or mountable device */
			device = flex_device(optarg, 1);
			break;

		    case 'q':
			qflag++;
			break;

		    case 'i':
			iflag = 1;
			if (pflag > 0)
				usage();
			pflag = 0;
			break;

		    case 'p':
			pflag = 1;
			if (iflag > 0)
				usage();
			iflag = 0;
			break;

		    case 'N':
			Nflag++;
			break;

		    case 'L':
			if (xflag || lflag || rflag) {
				progerr(gettext(ERR_INCOMP0));
				usage();
			}
			Lflag++;
			break;

		    case 'l':
			if (xflag || rflag) {
				progerr(gettext(ERR_INCOMP1));
				usage();
			}
			lflag++;
			break;

		    case 'x':
			/* bug # 1081606 */
			if (lflag || rflag) {
				progerr(gettext(ERR_INCOMP2));
				usage();
			}
			xflag++;
			break;

		    case 'r':
			if (lflag || xflag || Lflag) {
				progerr(gettext(ERR_INCOMP0));
				usage();
			}
			rflag++;
			break;

		    case 'c':
			ckcatg[ncatg++] = strtok(optarg, " \t\n, ");
			while (ckcatg[ncatg] = strtok(NULL, " \t\n, "))
				ncatg++;
			break;

		/* added for newroot functions */
		    case 'R':
			if (!set_inst_root(optarg)) {
				progerr(gettext(ERR_ROOT_CMD));
				exit(1);
			}
			break;

		    default:
			usage();
		}
	}

	/*
	 * implement the newroot option
	 */
	set_PKGpaths(get_inst_root());	/* set up /var... directories */

	/*
	 * Open the install DB, if one exists.
	 */

	pkg = &argv[optind];
	pkgcnt = (argc - optind);

	if (pkg[0] && strcmp(pkg[0], "all") == 0) {
		pkgcnt = 0;
		pkg[0] = NULL;
	}

	if (pkgdir == NULL)
		pkgdir = get_PKGLOC(); 	/* we need this later */

	/* convert device appropriately */
	if (pkghead(device))
		exit(1);

	/*
	 * If we are to inspect a spooled package we are only interested in
	 * the pkginfo file in the spooled pkg so we skip any Reg 4 DB
	 * lookups and use the old algorithm. We have a spooled pkg if
	 * device is not NULL.
	 */


	look_for_installed();

	if (lflag && strcmp(pkgdir, get_PKGLOC()) == 0) {
		/* look at contents file */
		(void) snprintf(contents, sizeof (contents),
		    "%s/contents", get_PKGADM());
		rdcontents();

	}

	/*
	 * If we are to inspect a spooled package we are only interested in
	 * the pkginfo file in the spooled pkg so we skip any Reg 4 DB
	 * lookups and use the old algorithm. We have a spooled pkg if
	 * device is not NULL.
	 */

	report();

	(void) pkghead(NULL);
	exit(errflg ? 1 : 0);
	/*NOTREACHED*/
#ifdef lint
	return (0);
#endif	/* lint */
}
Ejemplo n.º 6
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.º 7
0
Archivo: main.c Proyecto: aksr/heirloom
int
main(int argc, char *argv[])
{
	int	pkgfmt = 0;	/* Makes more sense as a pointer, but */
				/*	18N is compromised. */
	char	file[PATH_MAX+1],
		*abi_sym_ptr,
		*vfstab_file = NULL;
	char *all_pkgs[4] = {"all", NULL};
	char **category = NULL;
	char *catg_arg = NULL;
	int	c;
	int	n = 0;
	char	*prog,
		*Rvalue = NULL,
		*dvalue = NULL;
	int dbcreate = 0;
	int pathtype;

	/* initialize locale mechanism */

#if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
#define	TEXT_DOMAIN "SYS_TEST"
#endif
	(void) textdomain(TEXT_DOMAIN);

	/* determine program name */

	prog = set_prog_name(argv[0]);

	/* establish installation root directory */

	if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
		progerr(gettext(ERR_ROOT_SET));
		quit(1);
	}

	/* check if not ABI compliant mode */
	abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS");
	if (abi_sym_ptr && strncasecmp(abi_sym_ptr, "TRUE", 4) == 0) {
		set_nonABI_symlinks();
	}

	/* bugId 4012147 */
	if ((uniTmp = getenv("PKG_NO_UNIFIED")) != NULL)
		map_client = 0;

	while ((c = getopt(argc, argv, "Y:R:e:p:d:nLli:vaV:Mm:cqxfQP:?"))
			!= EOF) {
		switch (c) {
		case 'p':
			pathlist[npaths] = strtok(optarg, " , ");
			if (pathlist[npaths++] == NULL) {
				progerr(gettext(ERR_POPTION));
				quit(1);
			}
			while (pathlist[npaths] = strtok(NULL, " , ")) {
				if (npaths++ >= MAXPATHS) {
					progerr(gettext(ERR_MAXPATHS),
						MAXPATHS);
					quit(1);
				}
			}
			break;

		case 'd':
			dvalue = optarg;
			dflag = 1;
			break;

		case 'n':
			nflag++;
			break;

		case 'M':
			map_client = 0;
			break;

		/*
		 * Allow admin to establish the client filesystem using a
		 * vfstab-like file of stable format.
		 */
		case 'V':
			vfstab_file = flex_device(optarg, 2);
			map_client = 1;
			break;

		case 'f':
#if 0
			if (getuid()) {
				progerr(gettext(ERR_NOTROOT), prog);
				quit(1);
			}
#endif
			fflag++;
			break;

		case 'i':
			setpathlist(optarg);
			break;

		case 'v':
			vflag++;
			break;

		case 'l':
			lflag++;
			break;

		case 'L':
			Lflag++;
			break;

		case 'x':
			if (aflag < 0)
				aflag = 0;
			if (cflag < 0)
				cflag = 0;
			xflag++;
			break;

		case 'q':
			qflag++;
			break;

		case 'a':
			if (cflag < 0)
				cflag = 0;
			aflag = 1;
			break;

		case 'c':
			if (aflag < 0)
				aflag = 0;
			cflag = 1;
			break;

		case 'e':
			envfile = optarg;
			break;

		case 'm':
			mapfile = optarg;
			break;

		case 'R':
			Rvalue = optarg;
			Rflag = 1;
			break;

		case 'Y':
			catg_arg = strdup(optarg);

			if ((category = get_categories(catg_arg)) == NULL) {
				progerr(gettext(ERR_CAT_INV), catg_arg);
				quit(1);
			} else if (is_not_valid_length(category)) {
				progerr(gettext(ERR_CAT_LNGTH));
				quit(1);
			}
			break;

		case 'Q':
			dbcreate++;
			break;

		case 'P':
			ppathlist[npaths] = strtok(optarg, " , ");
			if ((ppathlist[npaths] == NULL) ||
			    (ppathlist[npaths][0] == '-')) {
				progerr(gettext(ERR_PARTIAL_POPTION));
				quit(1);
			}
			npaths++;
			while (ppathlist[npaths] = strtok(NULL, " , ")) {
				if (npaths++ >= MAXPATHS) {
					progerr(gettext(ERR_MAXPATHS),
						MAXPATHS);
					quit(1);
				}
			}
			break;

		default:
			usage();
		}
	}

	/* Check for incompatible options */
	if (dflag && Rflag)
		usage();

	/* Check for root dir and device dir if set */
	if (Rflag) {
		if (!set_inst_root(Rvalue)) {
			progerr(gettext(ERR_ROOT_CMD));
			quit(1);
		}
	}

	if (dflag)
		device = flex_device(dvalue, 1);

	if (lflag || Lflag) {
		/* we're only supposed to list information */
		if ((cflag >= 0) || (aflag >= 0) ||
		qflag || xflag || fflag || nflag || vflag)
			usage();
	}

	set_PKGpaths(get_inst_root());

	if (catg_arg != NULL && device == NULL) {
		if (argc - optind) {
			usage();
		}
		pkg = gpkglist(pkgdir, all_pkgs, category);
		if (pkg == NULL) {
			progerr(gettext(ERR_CAT_FND), catg_arg);
			quit(1);
		} else {
			for (pkgcnt = 0; pkg[pkgcnt] != NULL; pkgcnt++);
		}
	} else if (catg_arg != NULL && optind < argc) {
		usage();
	} else {
		pkg = &argv[optind];
		pkgcnt = (argc - optind);
	}

	environ = NULL;		/* Sever the parent environment. */

	if (vcfile() == 0) {
		quit(99);
	}

	errflg = 0;
	if (mapfile) {
		/* check for incompatible options */
		if (device || pkgcnt)
			usage();
		put_path_params();	/* Restore what's needed. */

		/* send pathtype if partial path */
		pathtype = (ppathlist[0] != NULL) ? 1 : 0;
		if (checkmap(0, (device != NULL), mapfile, envfile, NULL,
		    NULL, pathtype))
			errflg++;
	} else if (device) {
		/* check for incompatible options */
		if ((cflag >= 0) || (aflag >= 0))
			usage();
		if (qflag || xflag || nflag || envfile)
			usage();
		tmpdir = NULL;
		if ((spooldir = devattr(device, "pathname")) == NULL)
			spooldir = device;
		if (isdir(spooldir)) {
			char	template[] = "/var/tmp/spoolXXXXXX";
			close(mkstemp(template));
Ejemplo n.º 8
0
/*
 * This is the function that actually installs one volume (usually that's
 * all there is). Upon entry, the extlist is entirely correct:
 *
 *	1. It contains only those files which are to be installed
 *	   from all volumes.
 *	2. The mode bits in the ainfo structure for each file are set
 *	   correctly in accordance with administrative defaults.
 *	3. mstat.setuid/setgid reflect what the status *was* before
 *	   pkgdbmerg() processed compliance.
 */
void
instvol(struct cfextra **extlist, char *srcinst, int part,
	int nparts, VFP_T **a_cfVfp, VFP_T **a_cfTmpVfp,
	char **r_updated, char **r_skipped,
	char *a_zoneName)
{
	FILE		*listfp;
	char		*updated = (char *)NULL;
	char		*skipped = (char *)NULL;
	char		*anyPathLocal = (char *)NULL;
	char		*relocpath = (char *)NULL;
	char		*dstp;
	char		*listfile;
	char		*srcp;
	char		*pspool_loc;
	char		scrpt_dst[PATH_MAX];
	int		count;
	int		entryidx;	/* array of current package objects */
	int		n;
	int		nc = 0;
	int		pass;		/* pass count through the for loop. */
	int		tcount;
	struct cfent	*ept;
	struct cfextra	*ext;
	struct mergstat	*mstat;
	struct reg_files *rfp = NULL;

	/*
	 * r_updated and r_skipped are optional parameters that can be passed in
	 * by the caller if the caller wants to know if any objects are either
	 * updated or skipped. Do not initialize either r_updated or r_skipped;
	 * the call to instvol could be cumulative and any previous update or
	 * skipped indication must not be disturbed - these flags are only set,
	 * they must never be reset. These flags are "char *" pointers so that
	 * the object that was skipped or updated can be displayed in debugging
	 * output.
	 */

	if (part == 1) {
		pkgvolume(&pkgdev, srcinst, part, nparts);
	}

	tcount = 0;
	nc = cl_getn();

	/*
	 * For each class in this volume, install those files.
	 *
	 * NOTE : This loop index may be decremented by code below forcing a
	 * second trip through for the same class. This happens only when a
	 * class is split between an archive and the tree. Examples would be
	 * old WOS packages and the occasional class containing dynamic
	 * libraries which require special treatment.
	 */

	if (is_depend_pkginfo_DB() == B_FALSE) {
	    int		classidx;	/* the current class */

	    for (classidx = 0; classidx < nc; classidx++) {
		int pass_relative = 0;
		int rel_init = 0;

		eocflag = count = pass = 0;
		listfp = (FILE *)0;
		listfile = NULL;

		/* Now what do we pass to the class action script */

		if (cl_pthrel(classidx) == REL_2_CAS) {
			pass_relative = 1;
		}

		for (;;) {
			if (!tcount++) {
				/* first file to install */
				if (a_zoneName == (char *)NULL) {
					echo(MSG_INS_N_N, part, nparts);
				} else {
					echo(MSG_INS_N_N_LZ, part, nparts,
						a_zoneName);
				}
			}

			/*
			 * If there's an install class action script and no
			 * list file has been created yet, create that file
			 * and provide the pointer in listfp.
			 */
			if (cl_iscript(classidx) && !listfp) {
				/* create list file */
				putparam("TMPDIR", tmpdir);
				listfile = tempnam(tmpdir, "list");
				if ((listfp = fopen(listfile, "w")) == NULL) {
					progerr(ERR_WTMPFILE, listfile);
					quit(99);
				}
			}

			/*
			 * The following function goes through the package
			 * object list returning the array index of the next
			 * regular file. If it encounters a directory,
			 * symlink, named pipe or device, it just creates it.
			 */

			entryidx = domerg(extlist, (pass++ ? 0 : part), nparts,
				classidx, &srcp, &dstp, &updated, &skipped,
				&anyPathLocal);

			/* Evaluate the return code */
			if (entryidx == DMRG_DONE) {
				/*
				 * Set ept to the first entry in extlist
				 * which is guaranteed to exist so
				 * later checks against ept->ftype are
				 * not compared to NULL.
				 */
				ext = extlist[0];
				ept = &(ext->cf_ent);
				break; /* no more entries to process */
			}

			ext = extlist[entryidx];
			ept = &(ext->cf_ent);
			mstat = &(ext->mstat);

			/*
			 * 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 not
			 * "none": copy the file from the package (in pristine
			 * state with no actions performed) 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(ext->map_path) == B_TRUE &&
					parametricpath(ext->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 : ext->map_path);

				if (n >= PATH_MAX) {
					progerr(ERR_CREATE_PATH_2,
						saveSpoolInstallDir,
						ext->map_path);
					quit(99);
				}

				/* copy, preserve source file mode */

				if (cppath(MODE_SRC, srcp, scrpt_dst, 0644)) {
					warnflag++;
				}
			}

			/*
			 * If this isn't writeable anyway, it's not going
			 * into the list file. Only count it if it's going
			 * into the list file.
			 */
			if (is_fs_writeable(ext->cf_ent.path,
				&(ext->fsys_value)))
				count++;

			pkgvolume(&pkgdev, srcinst, part, nparts);

			/*
			 * If source verification is OK for this class, make
			 * sure the source we're passing to the class action
			 * script is useable.
			 */
			if (cl_svfy(classidx) != NOVERIFY) {
				if (cl_iscript(classidx) ||
					((ept->ftype == 'e') ||
					(ept->ftype == 'n'))) {
					if (ck_efile(srcp, ept)) {
						progerr(ERR_CORRUPT,
							srcp);
						logerr(getErrbufAddr());
						warnflag++;
						continue;
					}
				}
			}

			/*
			 * If there's a class action script for this class,
			 * just collect names in a temporary file
			 * that will be used as the stdin when the
			 * class action script is invoked.
			 */

			if ((cl_iscript(classidx)) &&
					((is_fs_writeable(ept->path,
						&(ext->fsys_value))))) {
				if (pass_relative) {
					if (!rel_init) {
						(void) fputs(instdir, listfp);
						(void) putc('\n', listfp);
						rel_init++;
					}
					(void) fputs(ext->map_path, listfp);
					(void) putc('\n', listfp);
				} else {
					(void) fputs(srcp ?
						srcp : "/dev/null", listfp);
					(void) putc(' ', listfp);
					(void) fputs(dstp, listfp);
					(void) putc('\n', listfp);
				}
				/*
				 * Note which entries in extlist are regular
				 * files to be installed via the class action
				 * script.
				 */
				if (regfiles_head == NULL) {
					assert(rfp == NULL);
					regfiles_head =
					    malloc(sizeof (struct reg_files));
					if (regfiles_head == NULL) {
						progerr(ERR_MEMORY, errno);
						quit(99);
					}
					regfiles_head->next = NULL;
					regfiles_head->val = entryidx;
					rfp = regfiles_head;
				} else {
					assert(rfp != NULL);
					rfp->next =
					    malloc(sizeof (struct reg_files));
					if (rfp->next == NULL) {
						progerr(ERR_MEMORY, errno);
						quit(99);
					}
					rfp = rfp->next;
					rfp->next = NULL;
					rfp->val = entryidx;
				}

				/*
				 * A warning message about unwritable targets
				 * in a class may be appropriate here.
				 */
				continue;
			}

			/*
			 * 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
			 * identifier is not "none": copy the file from the
			 * package (in pristine state with no actions performed)
			 * 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(ext->map_path) == B_TRUE &&
					parametricpath(ext->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 : ext->map_path);

				if (n >= PATH_MAX) {
					progerr(ERR_CREATE_PATH_2,
						saveSpoolInstallDir,
						ext->map_path);
					quit(99);
				}

				/* copy, preserve source file mode */

				if (cppath(MODE_SRC, srcp, scrpt_dst, 0644)) {
					warnflag++;
				}
			}

			/*
			 * There are several tests here to determine
			 * how we're going to deal with objects
			 * intended for remote read-only filesystems.
			 * We don't use is_served() because this may be
			 * a server. We're actually interested in if
			 * it's *really* remote and *really* not
			 * writeable.
			 */

			n = is_remote_fs(ept->path, &(ext->fsys_value));
			if ((n != 0) &&
				!is_fs_writeable(ept->path,
				&(ext->fsys_value))) {

				/*
				 * Don't change the file, we can't write
				 * to it anyway.
				 */

				mstat->attrchg = 0;
				mstat->contchg = 0;

				/*
				 * If it's currently mounted, we can
				 * at least test it for existence.
				 */

				if (is_mounted(ept->path, &(ext->fsys_value))) {
					if (!isfile(NULL, dstp)) {
						echo(MSG_IS_PRESENT, dstp);
					} else {
						echo(WRN_INSTVOL_NONE, dstp);
					}
				} else {
					char *server_host;

					server_host = get_server_host(
						ext->fsys_value);

					/* If not, we're just stuck. */
					echo(WRN_INSTVOL_NOVERIFY,
						dstp, server_host);
				}

				continue;
			}

			/* echo output destination name */

			echo("%s", dstp);

			/*
			 * if no source then no need to copy/verify
			 */

			if (srcp == (char *)NULL) {
				continue;
			}

			/*
			 * If doing a partial installation (creating a
			 * non-global zone), extra steps need to be taken:
			 *
			 * 1) if the file is not type 'e' and not type 'v' and
			 * the class is "none": then the file must already
			 * exist (as a result of the initial non-global zone
			 * installation which caused all non-e/v files to be
			 * copied from the global zone to the non-global
			 * zone). If this is the case, verify that the file
			 * exists and has the correct attributes.
			 *
			 * 2) if the file is not type 'e' and not type 'v'
			 * and the class is NOT "none", *OR* if the file is
			 * type 'e' or type 'v': then check to see if the
			 * file is located in an area inherited from the
			 * global zone. If so, then there is no ability to
			 * change the file since inherited file systems are
			 * "read only" - just verify that the file exists and
			 * verify attributes only if not 'e' or 'v'.
			 */

			if (is_partial_inst() != 0) {

				/*
				 * determine if the destination package is in an
				 * area inherited from the global zone
				 */

				n = pkgMatchInherited(srcp, dstp,
					get_inst_root(), ept->ainfo.mode,
					ept->cinfo.modtime, ept->ftype,
					ept->cinfo.cksum);

				echoDebug(DBG_INSTVOL_PARTIAL_INST,
					srcp ? srcp : "", dstp ? dstp: "",
					((get_inst_root()) &&
					(strcmp(get_inst_root(), "/") != 0)) ?
					get_inst_root() : "",
					ept->ainfo.mode, ept->cinfo.modtime,
					ept->ftype, ept->cinfo.cksum, n);

				/*
				 * if not type 'e|v' and class 'none', then the
				 * file must already exist.
				 */

				if ((ept->ftype != 'e') &&
					(ept->ftype != 'v') &&
					(strcmp(cl_nam(ept->pkg_class_idx),
								"none") == 0)) {

					/*
					 * if the file is in a space inherited
					 * from the global zone, and if the
					 * contents or attributes are incorrect,
					 * then generate a warning that the
					 * global zone file contents and/or file
					 * attributes have been modified and
					 * that the modifications are extended
					 * to the non-global zone (inherited
					 * from the global zone).
					 */

					if (n == 0) {
						/* is file changed? */
						n = finalck(ept, 1, 1, B_TRUE);

						/* no - ok - continue */
						if (n == 0) {
							continue;
						}

						/* output warning message */
						logerr(NOTE_INSTVOL_FINALCKFAIL,
							pkginst, ext->map_path,
							a_zoneName, ept->path);
						continue;
					} else if (!finalck(ept, 1, 1,
								B_FALSE)) {
						/*
						 * non-e/v file of class "none"
						 * not inherited from the global
						 * zone: verify file already
						 * exists:everything checks here
						 */
						mstat->attrchg = 0;
						mstat->contchg = 0;
					}
					continue;
				}

				/*
				 * non-e/v file with class action script, or
				 * e/v file: if the file is in an area inherited
				 * from the global zone, then no need (or the
				 * ability) to update just accept the file as is
				 */

				if (n == B_TRUE) {
					/*
					 * the object is in an area inherited
					 * from the global zone and the objects
					 * attributes are verified
					 */

					mstat->attrchg = 0;
					mstat->contchg = 0;

					/* NOTE: package object skipped */

					if (skipped == (char *)NULL) {
						skipped = dstp;
					echoDebug(DBG_INSTVOL_OBJ_SKIPPED,
								skipped);
					}
					continue;
				}
			}

			/*
			 * Copy from source media to target path and fix file
			 * mode and permission now in case installation halted.
			 */

			if (z_path_is_inherited(dstp, ept->ftype,
						get_inst_root()) == B_FALSE) {
				n = cppath(MODE_SET|DIR_DISPLAY, srcp, dstp,
						ept->ainfo.mode);
				if (n != 0) {
					warnflag++;
				} else if (!finalck(ept, 1, 1, B_FALSE)) {
					/*
					 * everything checks here
					 */
					mstat->attrchg = 0;
					mstat->contchg = 0;
				}
			}

			/* NOTE: a package object was updated */

			if (updated == (char *)NULL) {
				echoDebug(DBG_INSTVOL_OBJ_UPDATED, dstp);
				updated = dstp;
			}
		}

		/*
		 * We have now completed processing of all pathnames
		 * associated with this volume and class.
		 */
		if (cl_iscript(classidx)) {
			/*
			 * Execute appropriate class action script
			 * with list of source/destination pathnames
			 * as the input to the script.
			 */

			if (chdir(pkgbin)) {
				progerr(ERR_CHGDIR, pkgbin);
				quit(99);
			}

			if (listfp) {
				(void) fclose(listfp);
			}

			/*
			 * if the object associated with the class action script
			 * is in an area inherited from the global zone, then
			 * there is no need to run the class action script -
			 * assume that anything the script would do has already
			 * been done in the area shared from the global zone.
			 */

			/* nothing updated, nothing skipped */

			echoDebug(DBG_INSTVOL_CAS_INFO, is_partial_inst(),
				updated ? updated : "",
				skipped ? skipped : "",
				anyPathLocal ? anyPathLocal : "");

			if ((is_partial_inst() != 0) &&
					(updated == (char *)NULL) &&
					(anyPathLocal == (char *)NULL)) {

				/*
				 * installing in non-global zone, and no object
				 * has been updated (installed/verified in non-
				 * inherited area), and no path delivered by the
				 * package is in an area not inherited from the
				 * global zone (all paths delivered are in
				 * areas inherited from the global zone): do not
				 * run the class action script because the only
				 * affected areas are inherited (read only).
				 */

				echoDebug(DBG_INSTVOL_NOT_RUNNING_CAS,
					a_zoneName ? a_zoneName : "?",
					eocflag ? "ENDOFCLASS" :
							cl_iscript(classidx),
					cl_nam(classidx),
					cl_iscript(classidx));

				if ((r_skipped != (char **)NULL) &&
					(*r_skipped == (char *)NULL) &&
					(skipped == (char *)NULL)) {
					skipped = "postinstall";
					echoDebug(DBG_INSTVOL_OBJ_SKIPPED,
								skipped);
				}
			} else {
				/* run the class action script */

				echoDebug(DBG_INSTVOL_RUNNING_CAS,
					a_zoneName ? a_zoneName : "?",
					eocflag ? "ENDOFCLASS" :
							cl_iscript(classidx),
					cl_nam(classidx),
					cl_iscript(classidx));

				/* Use ULIMIT if supplied. */
				set_ulimit(cl_iscript(classidx), ERR_CASFAIL);

				if (eocflag) {
					/*
					 * end of class detected.
					 * Since there are no more volumes which
					 * contain pathnames associated with
					 * this class, execute class action
					 * script with the ENDOFCLASS argument;
					 * we do this even if none of the path
					 * names associated with this class and
					 * volume needed installation to
					 * guarantee the class action script is
					 * executed at least once during package
					 * installation.
					 */
					if (pkgverbose) {
						n = pkgexecl((listfp ?
							listfile : CAS_STDIN),
							CAS_STDOUT,
							CAS_USER, CAS_GRP,
							SHELL, "-x",
							cl_iscript(classidx),
							"ENDOFCLASS", NULL);
					} else {
						n = pkgexecl(
							(listfp ?
							listfile : CAS_STDIN),
							CAS_STDOUT, CAS_USER,
							CAS_GRP, SHELL,
							cl_iscript(classidx),
							"ENDOFCLASS", NULL);
					}
					ckreturn(n, ERR_CASFAIL);
				} else if (count) {
					/* execute class action script */
					if (pkgverbose) {
						n = pkgexecl(listfile,
							CAS_STDOUT, CAS_USER,
							CAS_GRP, SHELL, "-x",
							cl_iscript(classidx),
							NULL);
					} else {
						n = pkgexecl(listfile,
							CAS_STDOUT, CAS_USER,
							CAS_GRP, SHELL,
							cl_iscript(classidx),
							NULL);
					}
					ckreturn(n, ERR_CASFAIL);
				}

				/*
				 * Ensure the mod times on disk match those
				 * in the pkgmap. In this case, call cverify
				 * with checksumming disabled, since the only
				 * action that needs to be done is to verify
				 * that the attributes are correct.
				 */

				if ((rfp = regfiles_head) != NULL) {
					while (rfp != NULL) {
					    ept = &(extlist[rfp->val]->cf_ent);
					    cverify(1, &ept->ftype, ept->path,
						&ept->cinfo, 0);
					    rfp = rfp->next;
					}
					regfiles_free();
				}

				clr_ulimit();

				if ((r_updated != (char **)NULL) &&
					(*r_updated == (char *)NULL) &&
					(updated == (char *)NULL)) {
					updated = "postinstall";
					echoDebug(DBG_INSTVOL_OBJ_UPDATED,
								updated);
				}
			}
			if (listfile) {
				(void) remove(listfile);
			}
		}

		if (eocflag && (!is_partial_inst() || (is_partial_inst() &&
			strcmp(cl_nam(classidx), "none") != 0))) {
			if (cl_dvfy(classidx) == QKVERIFY && !repl_permitted) {
				/*
				 * The quick verify just fixes everything.
				 * If it returns 0, all is well. If it
				 * returns 1, then the class installation
				 * was incomplete and we retry on the
				 * stuff that failed in the conventional
				 * way (without a CAS). this is primarily
				 * to accomodate old archives such as are
				 * found in pre-2.5 WOS; but, it is also
				 * used when a critical dynamic library
				 * is not archived with its class.
				 */
				if (!fix_attributes(extlist, classidx)) {
					/*
					 * Reset the CAS pointer. If the
					 * function returns 0 then there
					 * was no script there in the first
					 * place and we'll just have to
					 * call this a miss.
					 */
					if (cl_deliscript(classidx))
						/*
						 * Decrement classidx for
						 * next pass.
						 */
						classidx--;
				}
			} else {
				/*
				 * Finalize merge. This checks to make sure
				 * file attributes are correct and any links
				 * specified are created.
				 */
				(void) endofclass(extlist, classidx,
					(cl_iscript(classidx) ? 0 : 1),
					a_cfVfp, a_cfTmpVfp);
			}
		}
	    }
	}

	/*
	 * Instead of creating links back to the GZ files the logic is
	 * to let zdo recreate the files from the GZ then invoke pkgadd to
	 * install the editable files and skip over any 'f'type files.
	 * The commented out block is to create the links which should be
	 * removed once the current code is tested to be correct.
	 */

	/*
	 * Go through extlist creating links for 'f'type files
	 * if we're in a global zone. Note that this code lies
	 * here instead of in the main loop to support CAF packages.
	 * In a CAF package the files are installed by the i.none script
	 * and don't exist until all files are done being processed, thus
	 * the additional loop through extlist.
	 */

	/*
	 * output appropriate completion message
	 */

	if (is_depend_pkginfo_DB() == B_TRUE) {
		/* updating database only (hollow package) */
		if (a_zoneName == (char *)NULL) {
			echo(MSG_DBUPD_N_N, part, nparts);
		} else {
			echo(MSG_DBUPD_N_N_LZ, part, nparts, a_zoneName);
		}
	} else if (tcount == 0) {
		/* updating package (non-hollow package) */
		if (a_zoneName == (char *)NULL) {
			echo(MSG_INST_N_N, part, nparts);
		} else {
			echo(MSG_INST_N_N_LZ, part, nparts, a_zoneName);
		}
	}

	/*
	 * if any package objects were updated (not inherited from the
	 * global zone or otherwise already in existence), set the updated
	 * flag as appropriate
	 */

	if (updated != (char *)NULL) {
		echoDebug(DBG_INSTVOL_OBJ_UPDATED, updated);
		if (r_updated != (char **)NULL) {
			*r_updated = updated;
		}
	}

	/*
	 * if any package objects were skipped (verified inherited from the
	 * global zone), set the skipped flag as appropriate
	 */

	if (skipped != (char *)NULL) {
		echoDebug(DBG_INSTVOL_OBJ_SKIPPED, skipped);
		if (r_skipped != (char **)NULL) {
			*r_skipped = skipped;
		}
	}
}
Ejemplo n.º 9
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.º 10
0
int
main(int argc, char *argv[])
{
	FILE		*fp;
	char		*abi_comp_ptr;
	char		*abi_sym_ptr;
	char		*p;
	char		*prog_full_name = NULL;
	char		*pt;
	char		*value;
	char		*vfstab_file = NULL;
	char		*zoneName = (char *)NULL;
	char		cmdbin[PATH_MAX];
	char		param[MAX_PKG_PARAM_LENGTH];
	char		path[PATH_MAX];
	char		script[PATH_MAX];
	int		c;
	int		err;
	int		fd;
	int		i;
	int		map_client = 1;
	int		n;
	int		nodelete = 0; 	/* do not delete file or run scripts */
	int		pkgrmremote = 0;	/* dont remove remote objects */
	struct sigaction	nact;
	struct sigaction	oact;
	PKGserver	pkgserver = NULL;
	VFP_T		*tmpfp;

	/* reset contents of all default paths */

	(void) memset(cmdbin, '\0', sizeof (cmdbin));

	/* initialize locale environment */

	(void) setlocale(LC_ALL, "");
	(void) textdomain(TEXT_DOMAIN);

	/* initialize program name */

	prog_full_name = argv[0];
	(void) set_prog_name(argv[0]);

	/* tell spmi zones interface how to access package output functions */

	z_set_output_functions(echo, echoDebug, progerr);

	/* exit if not root */

	if (getuid()) {
		progerr(ERR_NOT_ROOT, get_prog_name());
		exit(1);
		/* NOTREACHED */
	}

	/* Read PKG_INSTALL_ROOT from the environment, if it's there. */

	if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
		progerr(ERR_ROOT_SET);
		exit(1);
	}

	pkgserversetmode(DEFAULTMODE);

	/* parse command line options */

	while ((c = getopt(argc, argv, "?Aa:b:FMN:nO:oR:V:vy")) != EOF) {
		switch (c) {
		/*
		 * Same as pkgrm: Allow admin to remove package objects from
		 * a shared area from a reference client.
		 */
		case 'A':
			pkgrmremote++;
			break;

		/*
		 * Same as pkgrm: Use the installation
		 * administration file, admin, in place of the
		 * default admin file. pkgrm first looks in the
		 * current working directory for the administration
		 * file.  If the specified administration file is not
		 * in the current working directory, pkgrm looks in
		 * the /var/sadm/install/admin directory for the
		 * administration file.
		 */
		case 'a':
			admnfile = flex_device(optarg, 0);
			break;

		/*
		 * Same as pkgrm: location where package executables
		 * can be found - default is /usr/sadm/install/bin.
		 */
		case 'b':
			if (!path_valid(optarg)) {
				progerr(ERR_PATH, optarg);
				exit(1);
			}
			if (isdir(optarg) != 0) {
				char *p = strerror(errno);
				progerr(ERR_CANNOT_USE_DIR, optarg, p);
				exit(1);
			}
			(void) strlcpy(cmdbin, optarg, sizeof (cmdbin));
			break;

		/*
		 * Same as pkgrm: suppresses the removal of any
		 * files and any class action scripts, and suppresses
		 * the running of any class action scripts.  The
		 * package files remain but the package looks like it
		 * is not installed. This is mainly for use by the
		 * upgrade process.
		 */
		case 'F':
			nodelete++;
			break;

		/*
		 * Same as pkgrm: Instruct pkgrm not to use the
		 * $root_path/etc/vfstab file for determining the
		 * client's mount points. This option assumes the
		 * mount points are correct on the server and it
		 * behaves consistently with Solaris 2.5 and earlier
		 * releases.
		 */
		case 'M':
			map_client = 0;
			break;

		/*
		 * Different from pkgrm: specify program name to use
		 * for messages.
		 */
		case 'N':
			(void) set_prog_name(optarg);
			break;

		/*
		 * Same as pkgrm: package removal occurs in
		 * non-interactive mode.  Suppress output of the list of
		 * removed files. The default mode is interactive.
		 */
		case 'n':
			nointeract++;
			(void) echoSetFlag(B_FALSE);
			break;

		/*
		 * Almost same as pkgrm: the -O option allows the behavior
		 * of the package tools to be modified. Recognized options:
		 * -> debug
		 * ---> enable debugging output
		 * -> preremovecheck
		 * ---> perform a "pre removal" check of the specified
		 * ---> package - suppress all regular output and cause a
		 * ---> series of one or more "name=value" pair format lines
		 * ---> to be output that describes the "removability" of
		 * ---> the specified package
		 * -> enable-hollow-package-support
		 * --> Enable hollow package support. When specified, for any
		 * --> package that has SUNW_PKG_HOLLOW=true:
		 * --> Do not calculate and verify package size against target
		 * --> Do not run any package procedure or class action scripts
		 * --> Do not create or remove any target directories
		 * --> Do not perform any script locking
		 * --> Do not install or uninstall any components of any package
		 * --> Do not output any status or database update messages
		 */
		case 'O':
			for (p = strtok(optarg, ","); p != (char *)NULL;
			    p = strtok(NULL, ",")) {

				/* process debug option */

				if (strcmp(p, "debug") == 0) {
					/* set debug flag/enable debug output */
					debugFlag = B_TRUE;
					(void) echoDebugSetFlag(debugFlag);

					/* debug info on arguments to pkgadd */
					for (n = 0; n < argc && argv[n]; n++) {
						echoDebug(DBG_ARG, n, argv[n]);
					}

					continue;
				}

				/* process enable-hollow-package-support opt */

				if (strcmp(p,
				    "enable-hollow-package-support") == 0) {
					set_depend_pkginfo_DB(B_TRUE);
					continue;
				}

				/* process preremovecheck option */

				if (strcmp(p, "preremovecheck") == 0) {
					preremoveCheck = B_TRUE;
					nointeract++;	/* -n */
					nodelete++;	/* -F */
					quitSetSilentExit(B_TRUE);
					continue;
				}

				/* process addzonename option */

				if (strcmp(p, "addzonename") == 0) {
					zoneName = z_get_zonename();
					quitSetZoneName(zoneName);
					continue;
				}

				/* process parent-zone-name option */

				if (strncmp(p, PARENTZONENAME,
				    PARENTZONENAME_LEN) == 0) {
					parentZoneName = p+PARENTZONENAME_LEN;
					continue;
				}

				/* process parent-zone-type option */

				if (strncmp(p, PARENTZONETYPE,
				    PARENTZONETYPE_LEN) == 0) {
					parentZoneType = p+PARENTZONETYPE_LEN;
					continue;
				}

				if (strncmp(p, PKGSERV_MODE,
				    PKGSERV_MODE_LEN) == 0) {
					pkgserversetmode(pkgparsemode(p +
					    PKGSERV_MODE_LEN));
					continue;
				}
				/* option not recognized - issue warning */

				progerr(ERR_INVALID_O_OPTION, p);
				continue;
			}
			break;

		/*
		 * Different from pkgrm: This is an old non-ABI package
		 */

		case 'o':
			script_in = PROC_XSTDIN;
			break;

		/*
		 * Same as pkgrm: defines the full path name of a
		 * directory to use as the root_path.  All files,
		 * including package system information files, are
		 * relocated to a directory tree starting in the
		 * specified root_path.
		 */
		case 'R':
			if (!set_inst_root(optarg)) {
				progerr(ERR_ROOT_CMD);
				exit(1);
			}
			break;

		/*
		 * Same as pkgrm: allow admin to establish the client
		 * filesystem using a vfstab-like file of stable format.
		 */
		case 'V':
			vfstab_file = flex_device(optarg, 2);
			map_client = 1;
			break;

		/*
		 * Same as pkgrm: trace all of the scripts that
		 * get executed by pkgrm, located in the
		 * pkginst/install directory. This option is used for
		 * debugging the procedural and non-procedural
		 * scripts.
		 */
		case 'v':
			pkgverbose++;
			break;

		/*
		 * Different from pkgrm: process this package using
		 * old non-ABI symlinks
		 */
		case 'y':
			set_nonABI_symlinks();
			break;

		default:
			usage();
			/*NOTREACHED*/
			/*
			 * Although usage() calls a noreturn function,
			 * needed to add return (1);  so that main() would
			 * pass compilation checks. The statement below
			 * should never be executed.
			 */
			return (1);
		}
	}

	/*
	 * ********************************************************************
	 * validate command line options
	 * ********************************************************************
	 */

	(void) echoDebugSetFlag(debugFlag);
	(void) log_set_verbose(debugFlag);

	if (z_running_in_global_zone()) {
		echoDebug(DBG_ENTRY_IN_GZ, prog_full_name);
	} else {
		echoDebug(DBG_ENTRY_IN_LZ, prog_full_name, getzoneid(),
		    z_get_zonename());
	}

	/* establish cmdbin path */

	if (cmdbin[0] == '\0') {
		(void) strlcpy(cmdbin, PKGBIN, sizeof (cmdbin));
	}

	/* Read the mount table */

	if (get_mntinfo(map_client, vfstab_file)) {
		quit(99);
	}

	/*
	 * This function defines the standard /var/... directories used later
	 * to construct the paths to the various databases.
	 */

	set_PKGpaths(get_inst_root());

	/*
	 * If this is being removed from a client whose /var filesystem is
	 * mounted in some odd way, remap the administrative paths to the
	 * real filesystem. This could be avoided by simply mounting up the
	 * client now; but we aren't yet to the point in the process where
	 * modification of the filesystem is permitted.
	 */
	if (is_an_inst_root()) {
		int fsys_value;

		fsys_value = fsys(get_PKGLOC());
		if (use_srvr_map_n(fsys_value))
			set_PKGLOC(server_map(get_PKGLOC(), fsys_value));

		fsys_value = fsys(get_PKGADM());
		if (use_srvr_map_n(fsys_value))
			set_PKGADM(server_map(get_PKGADM(), fsys_value));
	} else {
		pkgrmremote = 0;	/* Makes no sense on local host. */
	}

	/*
	 * hook SIGINT and SIGHUP interrupts into quit.c's trap handler
	 */

	/* hold SIGINT/SIGHUP interrupts */

	(void) sighold(SIGHUP);
	(void) sighold(SIGINT);

	/* connect quit.c:trap() to SIGINT */

	nact.sa_handler = quitGetTrapHandler();
	nact.sa_flags = SA_RESTART;
	(void) sigemptyset(&nact.sa_mask);

	(void) sigaction(SIGINT, &nact, &oact);

	/* connect quit.c:trap() to SIGHUP */

	nact.sa_handler = quitGetTrapHandler();
	nact.sa_flags = SA_RESTART;
	(void) sigemptyset(&nact.sa_mask);

	(void) sigaction(SIGHUP, &nact, &oact);

	/* release hold on signals */

	(void) sigrelse(SIGHUP);
	(void) sigrelse(SIGINT);

	pkginst = argv[optind++];
	if (optind != argc) {
		usage();
	}

	/* validate package software database (contents) file */

	if (vcfile() == 0) {
		quit(99);
	}

	/*
	 * Acquire the package lock - currently at "remove initialization"
	 */

	if (!lockinst(get_prog_name(), pkginst, "remove-initial")) {
		quit(99);
	}

	/* establish temporary directory to use */

	tmpdir = getenv("TMPDIR");
	if (tmpdir == NULL) {
		tmpdir = P_tmpdir;
	}

	echoDebug(DBG_PKGREMOVE_TMPDIR, tmpdir);

	/*
	 * Initialize installation admin parameters by reading
	 * the adminfile.
	 */

	echoDebug(DBG_PKGREMOVE_ADMINFILE, admnfile ? admnfile : "");
	setadminFile(admnfile);

	/*
	 * about to perform first operation that could be modified by the
	 * preremove check option - if preremove check is selected (that is,
	 * only gathering dependencies), then output a debug message to
	 * indicate that the check is beginning. Also turn echo() output
	 * off and set various other flags.
	 */

	if (preremoveCheck == B_TRUE) {
		(void) echoSetFlag(B_FALSE);
		echoDebug(DBG_PKGREMOVE_PRERMCHK, pkginst ? pkginst : "",
		    zoneName ? zoneName : "global");
		rcksetPreremoveCheck(B_TRUE);
		rcksetZoneName(zoneName);
	}

	(void) snprintf(pkgloc, sizeof (pkgloc), "%s/%s", get_PKGLOC(),
	    pkginst);
	(void) snprintf(pkgbin, sizeof (pkgbin), "%s/install", pkgloc);
	(void) snprintf(rlockfile, sizeof (rlockfile), "%s/!R-Lock!", pkgloc);

	if (chdir(pkgbin)) {
		progerr(ERR_CHDIR, pkgbin);
		quit(99);
	}

	echo(MSG_PREREMOVE_REMINST, pkginst);

	/*
	 * if a lock file is present, then a previous attempt to remove this
	 * package may have been unsuccessful.
	 */

	if (access(rlockfile, F_OK) == 0) {
		echo(ERR_UNSUCC);
		echoDebug(DBG_PKGINSTALL_HAS_LOCKFILE, pkginst, rlockfile,
		    zoneName ? zoneName : "global");
	}

	/*
	 * Process all parameters from the pkginfo file
	 * and place them in the execution environment
	 */

	/* Add DB retreival of the pkginfo parameters here */
	(void) snprintf(path, sizeof (path), "%s/pkginfo", pkgloc);
	if ((fp = fopen(path, "r")) == NULL) {
		progerr(ERR_PKGINFO, path);
		quit(99);
	}

	/* Mount up the client if necessary. */
	if (map_client && !mount_client()) {
		logerr(MSG_MANMOUNT);
	}

	/* Get mount point of client */
	client_mntdir = getenv("CLIENT_MNTDIR");

	getuserlocale();

	/*
	 * current environment has been read; clear environment out
	 * so putparam() can be used to populate the new environment
	 * to be passed to any executables/scripts.
	 */

	environ = NULL;

	if (nonABI_symlinks()) {
		putparam("PKG_NONABI_SYMLINKS", "TRUE");
	}

	/*
	 * read the pkginfo file and fix any PKGSAV path - the correct
	 * install_root will be prepended to the existing path.
	 */

	param[0] = '\0';
	while (value = fpkgparam(fp, param)) {
		int validx = 0;
		char *newvalue;

		/* strip out any setting of PATH */

		if (strcmp(param, "PATH") == 0) {
			free(value);
			param[0] = '\0';
			continue;
		}

		/* if not PKGSAV then write out unchanged */

		if (strcmp(param, "PKGSAV") != 0) {
			putparam(param, value);
			free(value);
			param[0] = '\0';
			continue;
		}

		/*
		 * PKGSAV parameter found - interpret the directory:
		 * If in host:path format or marked with the leading "//",
		 * then there is no client-relative translation - take it
		 * literally later rather than use fixpath().
		 */

		if (strstr(value, ":/")) {
			/* no modification needed */
			validx = 0;
		} else if (strstr(value, "//") == value) {
			validx = 1;
		} else if (is_an_inst_root()) {
			/* This PKGSAV needs to be made client-relative. */
			newvalue = fixpath(value);
			free(value);
			value = newvalue;
		}
		putparam(param, value+validx);
		free(value);
		param[0] = '\0';
	}

	(void) fclose(fp);

	/* write parent condition information to environment */

	putConditionInfo(parentZoneName, parentZoneType);

	putuserlocale();

	/*
	 * Now do all the various setups based on ABI compliance
	 */

	/* Read the environment provided by the pkginfo file */
	abi_comp_ptr = getenv("NONABI_SCRIPTS");

	/* if not ABI compliant set global flag */
	abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS");
	if (abi_sym_ptr && strncasecmp(abi_sym_ptr, "TRUE", 4) == 0) {
		set_nonABI_symlinks();
	}

	/*
	 * If pkginfo says it's not compliant then set non_abi_scripts.
	 */
	if (abi_comp_ptr && strncmp(abi_comp_ptr, "TRUE", 4) == 0) {
		script_in = PROC_XSTDIN;
	}

	/*
	 * Since this is a removal, we can tell whether it's absolute or
	 * not from the resident pkginfo file read above.
	 */
	if ((err = set_basedirs((getenv("BASEDIR") != NULL), adm.basedir,
	    pkginst, nointeract)) != 0) {
		quit(err);
	}

	/*
	 * See if were are removing a package that only wants to update
	 * the database or only remove files associated with CAS's. We
	 * only check the PKG_HOLLOW_VARIABLE variable if told to do so by
	 * the caller.
	 */

	if (is_depend_pkginfo_DB()) {
		pt = getenv(PKG_HOLLOW_VARIABLE);

		if ((pt != NULL) && (strncasecmp(pt, "true", 4) == 0)) {
			echoDebug(DBG_PKGREMOVE_HOLLOW_ENABLED);

			/*
			 * this is a hollow package and hollow package support
			 * is enabled -- override admin settings to suppress
			 * checks that do not make sense since no scripts will
			 * be executed and no files will be removed.
			 */

			setadminSetting("conflict", "nocheck");
			setadminSetting("setuid", "nocheck");
			setadminSetting("action", "nocheck");
			setadminSetting("partial", "nocheck");
			setadminSetting("space", "nocheck");
			setadminSetting("authentication", "nocheck");
		} else {
			echoDebug(DBG_PKGREMOVE_HOLLOW_DISABLED);
			set_depend_pkginfo_DB(B_FALSE);
		}
	}

	put_path_params();

	/* If client mount point, add it to pkgremove environment */

	if (client_mntdir != NULL) {
		putparam("CLIENT_MNTDIR", client_mntdir);
	}

	/* Establish the class list and the class attributes. */

	if ((value = getenv("CLASSES")) != NULL) {
		cl_sets(qstrdup(value));
	} else {
		progerr(ERR_CLASSES, path);
		quit(99);
	}

	/* establish path and tmpdir */

	if (cmdbin[0] == '\0') {
		(void) strlcpy(cmdbin, PKGBIN, sizeof (cmdbin));
	}

	(void) snprintf(path, sizeof (path), "%s:%s", DEFPATH, cmdbin);
	putparam("PATH", path);

	putparam("TMPDIR", tmpdir);

	/*
	 * Check ulimit requirement (provided in pkginfo). The purpose of
	 * this limit is to terminate pathological file growth resulting from
	 * file edits in scripts. It does not apply to files in the pkgmap
	 * and it does not apply to any database files manipulated by the
	 * installation service.
	 */
	if (value = getenv("ULIMIT")) {
		if (assign_ulimit(value) == -1) {
			progerr(ERR_BADULIMIT, value);
			warnflag++;
		}
		putparam("PKG_ULIMIT", "TRUE");
	}

	/*
	 * If only gathering dependencies, check and output status of all
	 * remaining dependencies and exit.
	 */

	if (preremoveCheck == B_TRUE) {
		/*
		 * make sure current runlevel is appropriate
		 */

		(void) fprintf(stdout, "rckrunlevel=%d\n", rckrunlevel());

		/*
		 * determine if any packaging scripts provided with
		 * this package will execute as a priviledged user
		 */

		(void) fprintf(stdout, "rckpriv=%d\n", rckpriv());

		/*
		 * verify package dependencies
		 */

		(void) fprintf(stdout, "rckdepend=%d\n", rckdepend());

		/*
		 * ****** preremove check done - exit ******
		 */

		echoDebug(DBG_PKGREMOVE_PRERMCHK_OK);
		quit(0);
		/*NOTREACHED*/
	}

	/*
	 * Not gathering dependencies only, proceed to check dependencies
	 * and continue with the package removal operation.
	 */

	/*
	 * make sure current runlevel is appropriate
	 */

	n = rckrunlevel();

	if (n != 0) {
		quit(n);
		/* NOTREACHED */
	}

	/*
	 * determine if any packaging scripts provided with
	 * this package will execute as a priviledged user
	 */

	n = rckpriv();

	if (n != 0) {
		quit(n);
		/* NOTREACHED */
	}

	/*
	 * verify package dependencies
	 */
	n = rckdepend();

	if (n != 0) {
		quit(n);
		/* NOTREACHED */
	}

	/*
	 * *********************************************************************
	 * the actual removal of the package begins here
	 * *********************************************************************
	 */

	/*
	 * create lockfile to indicate start of removal
	 */
	started++;
	if ((fd = open(rlockfile, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
		progerr(ERR_LOCKFILE, rlockfile);
		quit(99);
	} else {
		(void) close(fd);
	}

	if (zoneName == (char *)NULL) {
		echo(MSG_PKGREMOVE_PROCPKG_GZ);
		echoDebug(DBG_PKGREMOVE_PROCPKG_GZ, pkginst, rlockfile);
	} else {
		echo(MSG_PKGREMOVE_PROCPKG_LZ, zoneName);
		echoDebug(DBG_PKGREMOVE_PROCPKG_LZ, pkginst, rlockfile,
		    zoneName);
	}
	if (delmap(0, pkginst, &pkgserver, &tmpfp) != 0) {
		progerr(ERR_DB_QUERY, pkginst);
		quit(99);
	}

	/*
	 * Run a preremove script if one is provided by the package.
	 * Don't execute preremove script if only updating the DB.
	 * Don't execute preremove script if files are not being deleted.
	 */

	/* update the lock - at the preremove script */
	lockupd("preremove");

	/* execute preremove script if one is provided */
	(void) snprintf(script, sizeof (script), "%s/preremove", pkgbin);
	if (access(script, F_OK) != 0) {
		/* no script present */
		echoDebug(DBG_PKGREMOVE_POC_NONE, pkginst,
		    zoneName ? zoneName : "global");
	} else if (nodelete) {
		/* not deleting files: skip preremove script */
		echoDebug(DBG_PKGREMOVE_POC_NODEL, pkginst, script,
		    zoneName ? zoneName : "global");
	} else if (is_depend_pkginfo_DB()) {
		/* updating db only: skip preremove script */
		echoDebug(DBG_PKGREMOVE_POC_DBUPD, pkginst, script,
		    zoneName ? zoneName : "global");
	} else {
		/* script present and ok to run: run the script */
		set_ulimit("preremove", ERR_PREREMOVE);
		if (zoneName == (char *)NULL) {
			echo(MSG_PKGREMOVE_EXEPOC_GZ);
			echoDebug(DBG_PKGREMOVE_EXEPOC_GZ, pkginst, script);
		} else {
			echo(MSG_PKGREMOVE_EXEPOC_LZ, zoneName);
			echoDebug(DBG_PKGREMOVE_EXEPOC_LZ, pkginst, script,
			    zoneName);
		}
		putparam("PKG_PROC_SCRIPT", "preremove");
		if (pkgverbose) {
			ckreturn(pkgexecl(script_in, PROC_STDOUT,
			    PROC_USER, PROC_GRP, SHELL, "-x",
			    script, NULL), ERR_PREREMOVE);
		} else {
			ckreturn(pkgexecl(script_in, PROC_STDOUT,
			    PROC_USER, PROC_GRP, SHELL, script,
			    NULL), ERR_PREREMOVE);
		}
		clr_ulimit();
	}

	/* update the lock - doing removal */

	lockupd("remove");

	/*
	 * Remove all components belonging to this package.
	 * Don't remove components if only updating the DB.
	 * Don't remove components if files are not being deleted.
	 */

	if (nodelete) {
		echoDebug(DBG_PKGREMOVE_REM_NODEL, pkginst,
		    zoneName ? zoneName : "global");
	} else if (is_depend_pkginfo_DB()) {
		echoDebug(DBG_PKGREMOVE_REM_DBUPD, pkginst,
		    zoneName ? zoneName : "global");
	} else {
		echoDebug(DBG_PKGREMOVE_REM, pkginst,
		    zoneName ? zoneName : "global");
		/*
		 * remove package one class at a time
		 */

		/* reverse order of classes */
		for (i = cl_getn() - 1; i >= 0; i--) {
			rmclass(cl_nam(i), pkgrmremote, zoneName);
		}

		rmclass(NULL, pkgrmremote, zoneName);
	}

	z_destroyMountTable();

	/*
	 * Execute postremove script, if any
	 * Don't execute postremove script if only updating the DB.
	 * Don't execute postremove script if files are not being deleted.
	 */

	/* update the lock - at the postremove script */
	lockupd("postremove");

	/* execute postremove script if one is provided */
	(void) snprintf(script, sizeof (script), "%s/postremove", pkgbin);
	if (access(script, F_OK) != 0) {
		/* no script present */
		echoDebug(DBG_PKGREMOVE_PIC_NONE, pkginst,
		    zoneName ? zoneName : "global");
	} else if (nodelete) {
		/* not deleting files: skip postremove script */
		echoDebug(DBG_PKGREMOVE_PIC_NODEL, pkginst, script,
		    zoneName ? zoneName : "global");
	} else if (is_depend_pkginfo_DB()) {
		/* updating db only: skip postremove script */
		echoDebug(DBG_PKGREMOVE_PIC_DBUPD, pkginst, script,
		    zoneName ? zoneName : "global");
	} else {
		/* script present and ok to run: run the script */
		set_ulimit("postremove", ERR_POSTREMOVE);
		if (zoneName == (char *)NULL) {
			echo(MSG_PKGREMOVE_EXEPIC_GZ);
			echoDebug(DBG_PKGREMOVE_EXEPIC_GZ, pkginst, script);
		} else {
			echo(MSG_PKGREMOVE_EXEPIC_LZ, zoneName);
			echoDebug(DBG_PKGREMOVE_EXEPIC_LZ, pkginst, script,
			    zoneName);
		}
		putparam("PKG_PROC_SCRIPT", "postremove");
		putparam("TMPDIR", tmpdir);
		if (pkgverbose) {
			ckreturn(pkgexecl(script_in, PROC_STDOUT, PROC_USER,
			    PROC_GRP, SHELL, "-x", script, NULL),
			    ERR_POSTREMOVE);
		} else {
			ckreturn(pkgexecl(script_in, PROC_STDOUT, PROC_USER,
			    PROC_GRP, SHELL, script, NULL),
			    ERR_POSTREMOVE);
		}
		clr_ulimit();
	}

	if (zoneName == (char *)NULL) {
		echo(MSG_PKGREMOVE_UPDINF_GZ);
	} else {
		echo(MSG_PKGREMOVE_UPDINF_LZ, zoneName);
	}

	if (delmap(1, pkginst, &pkgserver, &tmpfp) != 0) {
		progerr(ERR_DB_QUERY, pkginst);
		quit(99);
	}

	if (!warnflag && !failflag) {
		(void) chdir("/");
		if (rrmdir(pkgloc))
			warnflag++;
	}

	if ((z_running_in_global_zone() == B_TRUE) &&
	    (pkgIsPkgInGzOnly(get_inst_root(), pkginst) == B_TRUE)) {
		boolean_t	b;

		b = pkgRemovePackageFromGzonlyList(get_inst_root(), pkginst);
		if (b == B_FALSE) {
			progerr(ERR_PKGREMOVE_GZONLY_REMOVE, pkginst);
			ckreturn(1, NULL);
		}
	}

	/* release the generic package lock */

	(void) unlockinst();

	pkgcloseserver(pkgserver);

	quit(0);
	/* LINTED: no return */
}
Ejemplo n.º 11
0
int
selpkg(char *p)
{
	static char *selected;
	char buf[80];
	char *root;
	register int i;

	if (p == NULL) {
		if (selected == NULL) {
			if (pkgcnt) {
				for (i = 0; i < pkgcnt; ++i) {
					/* bugid 1227628 */
					root = get_inst_root();
					if (root)
						(void) snprintf(buf,
						sizeof (buf),
						"%s/var/sadm/pkg/%s/pkginfo",
						root, pkg[i]);
					else
						(void) snprintf(buf,
						sizeof (buf),
						"/var/sadm/pkg/%s/pkginfo",
						pkg[i]);

					if (access(buf, F_OK))
						logerr(gettext(WRN_NOPKG),
							pkg[i]);
					else
						logerr(gettext(EMPTY_PKG),
							pkg[i]);
				}
			}
		} else {
			for (i = 0; i < pkgcnt; ++i) {
				if (selected[i] == NULL) {
					root = get_inst_root();
					if (root)
						(void) snprintf(buf,
						sizeof (buf),
						"%s/var/sadm/pkg/%s/pkginfo",
						root, pkg[i]);
					else
						(void) snprintf(buf,
						sizeof (buf),
						"/var/sadm/pkg/%s/pkginfo",
						pkg[i]);

					if (access(buf, F_OK))
						logerr(gettext(WRN_NOPKG),
							pkg[i]);
					else
						logerr(gettext(EMPTY_PKG),
							pkg[i]);
				}
			}
		}
		return (0); /* return value not important */
	} else if (pkgcnt == 0)
		return (1);
	else if (selected == NULL) {
		selected =
		    (char *)calloc((unsigned)(pkgcnt+1), sizeof (char));
		if (selected == NULL) {
			progerr(gettext(ERR_NOMEM), errno);
			exit(99);
			/*NOTREACHED*/
		}
	}

	for (i = 0; i < pkgcnt; ++i) {
		if (pkgnmchk(p, pkg[i], 0) == 0) {
			if (selected != NULL)
				selected[i] = 'b';
			return (1);
		}
	}
	return (0);
}
Ejemplo n.º 12
0
int
rckdepend(void)
{
	int	n;
	char	ans[MAX_INPUT];
	char	**id, **name;

	if (ADM(rdepend, "nocheck")) {
		return (0);
	}

	if (zoneName == (char *)NULL) {
		echo(MSG_CHECKREMOVE_PKG_IN_GZ, pkginst);
	} else {
		echo(MSG_CHECKREMOVE_PKG_IN_ZONE, pkginst, zoneName);
	}

	if (wsreg_pkgrm_check(get_inst_root(), pkginst, &id, &name) > 0) {
		int i;

		if (ADM(rdepend, "quit")) {
			return (4);
		}

		if (echoGetFlag() == B_FALSE) {
			return (5);
		}

		msgtext = MSG_PKGREMOVE_WSDEPEND;
		echo(msgtext);

		(void) printf("%-36s  %s", MSG_PKGREMOVE_ID_STR,
		    MSG_PKGREMOVE_NAME_STR);
		(void) printf("\n------------------------------------  "
		    "--------------------------------------\n");

		for (i = 0; id[i] != NULL; i++) {
			(void) printf("%-36s  %s\n", id[i],
			    (name[i])?(name[i]):"");
			free(id[i]);
			if (name[i]) {
				free(name[i]);
			}
		}

		free(id);
		free(name);

		msgtext = NULL;

		n = ckyorn(ans, NULL, NULL, HLP_PKGREMOVE_WSDEPEND,
		    ASK_PKGREMOVE_CONTINUE);

		if (n != 0) {
			return (n);
		}

		if (strchr("yY", *ans) == NULL) {
			return (3);
		}
	}

	if (dockdeps(pkginst, 1, preremoveCheck)) {
		msgtext = MSG_PKGREMOVE_DEPEND;

		if (preremoveCheck == B_FALSE) {
			echo(msgtext);
		}

		if (ADM(rdepend, "quit")) {
			return (4);
		}

		if (echoGetFlag() == B_FALSE) {
			return (5);
		}

		msgtext = NULL;

		n = ckyorn(ans, NULL, NULL, HLP_PKGREMOVE_DEPEND,
		    ASK_PKGREMOVE_CONTINUE);

		if (n != 0) {
			return (n);
		}

		if (strchr("yY", *ans) == NULL) {
			return (3);
		}
	}

	return (0);
}