6809128 freeware packages cannot be installed in sparse non global zone with patch 119254-63
authorJan Kryl <Jan.Kryl@Sun.COM>
Thu, 24 Sep 2009 15:16:32 +0200
changeset 10638 5d19a597329d
parent 10637 f6eac4af74a8
child 10639 368f1335a058
6809128 freeware packages cannot be installed in sparse non global zone with patch 119254-63 6865412 pkgadm not communicating with dryrun pkgserv instances 6853789 pkgrm errors during zone upgrade to s10u8_01
usr/src/cmd/svr4pkg/libinst/mntinfo.c
usr/src/cmd/svr4pkg/pkgadm/main.c
usr/src/lib/libinstzones/common/zones_paths.c
--- a/usr/src/cmd/svr4pkg/libinst/mntinfo.c	Thu Sep 24 05:17:17 2009 -0700
+++ b/usr/src/cmd/svr4pkg/libinst/mntinfo.c	Thu Sep 24 15:16:32 2009 +0200
@@ -34,6 +34,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <libgen.h>
 #include <string.h>
 #include <wait.h>
 #include <signal.h>
@@ -952,7 +953,7 @@
 				 */
 				if (strcmp(vfs->vfs_mountp, "/") == 0) {
 					(void) strcpy(client_mountp,
-								install_root);
+					    install_root);
 				} else {
 					(void) snprintf(client_mountp,
 						sizeof (client_mountp), "%s%s",
@@ -1004,7 +1005,7 @@
 	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));
+		    strerror(errno));
 		return (1);
 	} else {
 		return (0);
@@ -1055,21 +1056,33 @@
 {
 	register int i;
 	char	real_path[PATH_MAX];
-	char	*path2use = NULL;
-	char	*cp = NULL;
+	char	path_copy[PATH_MAX];
+	char	*path2use;
+	char	*cp;
 	int	pathlen;
-
-	path2use = path;
-
-	real_path[0] = '\0';
+	boolean_t found = B_FALSE;
 
-	(void) realpath(path, real_path);
-
-	if (real_path[0]) {
-		cp = strstr(path, real_path);
-		if (cp != path || cp == NULL)
-			path2use = real_path;
+	/*
+	 * The loop below represents our best effort to identify real path of
+	 * a file, which doesn't need to exist. realpath() returns error for
+	 * nonexistent path, therefore we need to cut off trailing components
+	 * of path until we get path which exists and can be resolved by
+	 * realpath(). Lookup of "/dir/symlink/nonexistent-file" would fail
+	 * to resolve symlink without this.
+	 */
+	(void) strlcpy(path_copy, path, PATH_MAX);
+	for (cp = dirname(path_copy); strlen(cp) > 1; cp = dirname(cp)) {
+		if (realpath(cp, real_path) != NULL) {
+			found = B_TRUE;
+			break;
+		} else if (errno != ENOENT)
+			break;
 	}
+	if (found)
+		path2use = real_path;
+	else
+		/* fall back to original path in case of unexpected failure */
+		path2use = path;
 
 	pathlen = strlen(path2use);
 
--- a/usr/src/cmd/svr4pkg/pkgadm/main.c	Thu Sep 24 05:17:17 2009 -0700
+++ b/usr/src/cmd/svr4pkg/pkgadm/main.c	Thu Sep 24 15:16:32 2009 +0200
@@ -262,10 +262,27 @@
 {
 	int c;
 	char *root = NULL;
+	char *dryrundir = NULL;
 	boolean_t quit = B_FALSE;
 
-	while ((c = getopt(argc, argv, "R:q")) != EOF) {
+	/*
+	 * Options:
+	 *   -q: Tell pkgserv daemon to quit.
+	 *   -R: Alternate root specification.
+	 *   -D: Dryrun directory specification.
+	 *
+	 * -R and -D help pkgadm to locate IPC files used for communication
+	 * with pkgserv daemon. They should not be used together, though
+	 * nothing prevents you from doing so. If you use both at once
+	 * then IPC files will be searched in $ROOTDIR/$DRYRUNDIR directory.
+	 * So if you want to terminate dryrun pkgserv process, you should
+	 * always use only -D option.
+	 */
+	while ((c = getopt(argc, argv, "D:R:q")) != EOF) {
 		switch (c) {
+		case 'D':
+			dryrundir = optarg;
+			break;
 		case 'R':
 			root = optarg;
 			break;
@@ -277,15 +294,15 @@
 		}
 	}
 
-	if (!pkgsync_needed(root, NULL, quit))
+	if (!pkgsync_needed(root, dryrundir, quit))
 		return (0);
 
 	set_PKGpaths(root);
-	set_cfdir(NULL);
+	set_cfdir(dryrundir);
 
 	if (pkgWlock(1) == 1) {
 		/* Flush the log file */
-		(void) pkgsync(root, NULL, quit);
+		(void) pkgsync(root, dryrundir, quit);
 		(void) relslock();
 		return (0);
 	}
--- a/usr/src/lib/libinstzones/common/zones_paths.c	Thu Sep 24 05:17:17 2009 -0700
+++ b/usr/src/lib/libinstzones/common/zones_paths.c	Thu Sep 24 15:16:32 2009 +0200
@@ -34,6 +34,8 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <libgen.h>
+#include <errno.h>
 #include <string.h>
 #include <fcntl.h>
 #include <sys/types.h>
@@ -242,7 +244,11 @@
 boolean_t
 z_path_is_inherited(char *a_path, char a_ftype, char *a_rootDir)
 {
-	int		n;
+	int	n;
+	char	*cp, *path2use;
+	char	real_path[PATH_MAX];
+	char	path_copy[PATH_MAX];
+	boolean_t found = B_FALSE;
 
 	/* entry assertions */
 
@@ -263,11 +269,38 @@
 	}
 
 	/*
-	 * if a_path resides on an inherited filesystem then
+	 * The loop below represents our best effort to identify real path of
+	 * a file, which doesn't need to exist. realpath() returns error for
+	 * nonexistent path, therefore we need to cut off trailing components
+	 * of path until we get path which exists and can be resolved by
+	 * realpath(). Lookup of "/dir/symlink/nonexistent-file" would fail
+	 * to resolve symlink without this.
+	 */
+	(void) strlcpy(path_copy, a_path, PATH_MAX);
+	for (cp = dirname(path_copy); strlen(cp) > 1; cp = dirname(cp)) {
+		if (realpath(cp, real_path) != NULL) {
+			found = B_TRUE;
+			break;
+		} else if (errno != ENOENT)
+			break;
+	}
+	if (found) {
+		/*
+		 * In the loop above we always strip trailing path component,
+		 * so the type of real_path is always 'd'.
+		 */
+		a_ftype = 'd';
+		path2use = real_path;
+	} else {
+		path2use = a_path;
+	}
+
+	/*
+	 * if path resides on an inherited filesystem then
 	 * it must be read-only.
 	 */
 
-	if (z_isPathWritable(a_path) != 0) {
+	if (z_isPathWritable(path2use) != 0) {
 		return (B_FALSE);
 	}
 
@@ -286,22 +319,22 @@
 	/* advance past given root directory if path begins with it */
 
 	n = strlen(a_rootDir);
-	if (strncmp(a_rootDir, a_path, n) == 0) {
+	if (strncmp(a_rootDir, path2use, n) == 0) {
 		char	*p;
 
 		/* advance past the root path */
 
-		p = a_path + n;
+		p = path2use + n;
 
 		/* go back to the first occurance of the path separator */
 
-		while ((*p != '/') && (p > a_path)) {
+		while ((*p != '/') && (p > path2use)) {
 			p--;
 		}
 
 		/* use this location in the path to compare */
 
-		a_path = p;
+		path2use = p;
 	}
 
 	/*
@@ -326,7 +359,7 @@
 			fslen--;
 		}
 
-		if (strncmp(a_path, inheritedFileSystems[n], fslen) == 0) {
+		if (strncmp(path2use, inheritedFileSystems[n], fslen) == 0) {
 			_z_echoDebug(DBG_PATHS_IS_INHERITED, a_path,
 			    inheritedFileSystems[n]);
 			return (B_TRUE);