xref: /titanic_52/usr/src/lib/libtsol/common/getpathbylabel.c (revision 004388ebfdfe2ed7dfd2d153a876dfcc22d2c006)
145916cd2Sjpk /*
245916cd2Sjpk  * CDDL HEADER START
345916cd2Sjpk  *
445916cd2Sjpk  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
745916cd2Sjpk  *
845916cd2Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
945916cd2Sjpk  * or http://www.opensolaris.org/os/licensing.
1045916cd2Sjpk  * See the License for the specific language governing permissions
1145916cd2Sjpk  * and limitations under the License.
1245916cd2Sjpk  *
1345916cd2Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
1445916cd2Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1545916cd2Sjpk  * If applicable, add the following below this CDDL HEADER, with the
1645916cd2Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
1745916cd2Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
1845916cd2Sjpk  *
1945916cd2Sjpk  * CDDL HEADER END
2045916cd2Sjpk  */
2145916cd2Sjpk /*
2245916cd2Sjpk  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
2345916cd2Sjpk  * Use is subject to license terms.
2445916cd2Sjpk  */
2545916cd2Sjpk 
2645916cd2Sjpk #pragma ident	"%Z%%M%	%I%	%E% SMI"
2745916cd2Sjpk 
2845916cd2Sjpk 
2945916cd2Sjpk /*
3045916cd2Sjpk  *	Name:		getpathbylabel.c
3145916cd2Sjpk  *
3245916cd2Sjpk  *	Description:	Returns the global zone pathname corresponding
3345916cd2Sjpk  *			to the specified label. The pathname does
3445916cd2Sjpk  *			not need to match an existing file system object.
3545916cd2Sjpk  *
3645916cd2Sjpk  */
3745916cd2Sjpk #include <stdio.h>
3845916cd2Sjpk #include <string.h>
3945916cd2Sjpk #include <unistd.h>
4045916cd2Sjpk #include <errno.h>
4145916cd2Sjpk #include <sys/types.h>
4245916cd2Sjpk #include <tsol/label.h>
4345916cd2Sjpk #include <stdlib.h>
4445916cd2Sjpk #include <zone.h>
4545916cd2Sjpk #include <sys/mntent.h>
4645916cd2Sjpk #include <sys/mnttab.h>
4745916cd2Sjpk #include <stdarg.h>
4845916cd2Sjpk 
4945916cd2Sjpk /*
5045916cd2Sjpk  * This structure is used to chain mntent structures into a list
5145916cd2Sjpk  * and to cache stat information for each member of the list.
5245916cd2Sjpk  */
5345916cd2Sjpk struct mntlist {
5445916cd2Sjpk 	struct mnttab	*mntl_mnt;
5545916cd2Sjpk 	struct mntlist	*mntl_next;
5645916cd2Sjpk };
5745916cd2Sjpk 
5845916cd2Sjpk 
5945916cd2Sjpk /*
6045916cd2Sjpk  * Return a pointer to the trailing suffix of full that follows the prefix
6145916cd2Sjpk  * given by pref.  If pref isn't a prefix of full, return NULL.  Apply
6245916cd2Sjpk  * pathname semantics to the prefix test, so that pref must match at a
6345916cd2Sjpk  * component boundary.
6445916cd2Sjpk  */
6545916cd2Sjpk static char *
6645916cd2Sjpk pathsuffix(char *full, char *pref)
6745916cd2Sjpk {
6845916cd2Sjpk 	int preflen;
6945916cd2Sjpk 
7045916cd2Sjpk 	if (full == NULL || pref == NULL)
7145916cd2Sjpk 		return (NULL);
7245916cd2Sjpk 
7345916cd2Sjpk 	preflen = strlen(pref);
7445916cd2Sjpk 	if (strncmp(pref, full, preflen) != 0)
7545916cd2Sjpk 		return (NULL);
7645916cd2Sjpk 
7745916cd2Sjpk 	/*
7845916cd2Sjpk 	 * pref is a substring of full.  To be a subpath, it cannot cover a
7945916cd2Sjpk 	 * partial component of full.  The last clause of the test handles the
8045916cd2Sjpk 	 * special case of the root.
8145916cd2Sjpk 	 */
8245916cd2Sjpk 	if (full[preflen] != '\0' && full[preflen] != '/' && preflen > 1)
8345916cd2Sjpk 		return (NULL);
8445916cd2Sjpk 
8545916cd2Sjpk 	if (preflen == 1 && full[0] == '/')
8645916cd2Sjpk 		return (full);
8745916cd2Sjpk 	else
8845916cd2Sjpk 		return (full + preflen);
8945916cd2Sjpk }
9045916cd2Sjpk 
9145916cd2Sjpk /*
9245916cd2Sjpk  * Return zero iff the path named by sub is a leading subpath
9345916cd2Sjpk  * of the path named by full.
9445916cd2Sjpk  *
9545916cd2Sjpk  * Treat null paths as matching nothing.
9645916cd2Sjpk  */
9745916cd2Sjpk static int
9845916cd2Sjpk subpath(char *full, char *sub)
9945916cd2Sjpk {
10045916cd2Sjpk 	return (pathsuffix(full, sub) == NULL);
10145916cd2Sjpk }
10245916cd2Sjpk 
10345916cd2Sjpk static void
10445916cd2Sjpk tsol_mnt_free(struct mnttab *mnt)
10545916cd2Sjpk {
10645916cd2Sjpk 	if (mnt->mnt_special)
10745916cd2Sjpk 		free(mnt->mnt_special);
10845916cd2Sjpk 	if (mnt->mnt_mountp)
10945916cd2Sjpk 		free(mnt->mnt_mountp);
11045916cd2Sjpk 	if (mnt->mnt_fstype)
11145916cd2Sjpk 		free(mnt->mnt_fstype);
11245916cd2Sjpk 	if (mnt->mnt_mntopts)
11345916cd2Sjpk 		free(mnt->mnt_mntopts);
11445916cd2Sjpk 	free(mnt);
11545916cd2Sjpk }
11645916cd2Sjpk 
11745916cd2Sjpk static void
11845916cd2Sjpk tsol_mlist_free(struct mntlist *mlist)
11945916cd2Sjpk {
12045916cd2Sjpk 	struct mntlist *mlp;
12145916cd2Sjpk 
12245916cd2Sjpk 	for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
12345916cd2Sjpk 		struct mnttab *mnt = mlp->mntl_mnt;
12445916cd2Sjpk 
12545916cd2Sjpk 		if (mnt)
12645916cd2Sjpk 			tsol_mnt_free(mnt);
12745916cd2Sjpk 		free(mlp);
12845916cd2Sjpk 	}
12945916cd2Sjpk }
13045916cd2Sjpk 
13145916cd2Sjpk static struct mnttab *
13245916cd2Sjpk mntdup(struct mnttab *mnt)
13345916cd2Sjpk {
13445916cd2Sjpk 	struct mnttab *new;
13545916cd2Sjpk 
13645916cd2Sjpk 	new = (struct mnttab *)malloc(sizeof (*new));
13745916cd2Sjpk 	if (new == NULL)
13845916cd2Sjpk 		return (NULL);
13945916cd2Sjpk 
14045916cd2Sjpk 	new->mnt_special = NULL;
14145916cd2Sjpk 	new->mnt_mountp = NULL;
14245916cd2Sjpk 	new->mnt_fstype = NULL;
14345916cd2Sjpk 	new->mnt_mntopts = NULL;
14445916cd2Sjpk 
14545916cd2Sjpk 	new->mnt_special = strdup(mnt->mnt_special);
14645916cd2Sjpk 	if (new->mnt_special == NULL) {
14745916cd2Sjpk 		tsol_mnt_free(new);
14845916cd2Sjpk 		return (NULL);
14945916cd2Sjpk 	}
15045916cd2Sjpk 	new->mnt_mountp = strdup(mnt->mnt_mountp);
15145916cd2Sjpk 	if (new->mnt_mountp == NULL) {
15245916cd2Sjpk 		tsol_mnt_free(new);
15345916cd2Sjpk 		return (NULL);
15445916cd2Sjpk 	}
15545916cd2Sjpk 	new->mnt_fstype = strdup(mnt->mnt_fstype);
15645916cd2Sjpk 	if (new->mnt_fstype == NULL) {
15745916cd2Sjpk 		tsol_mnt_free(new);
15845916cd2Sjpk 		return (NULL);
15945916cd2Sjpk 	}
16045916cd2Sjpk 	new->mnt_mntopts = strdup(mnt->mnt_mntopts);
16145916cd2Sjpk 	if (new->mnt_mntopts == NULL) {
16245916cd2Sjpk 		tsol_mnt_free(new);
16345916cd2Sjpk 		return (NULL);
16445916cd2Sjpk 	}
16545916cd2Sjpk 	return (new);
16645916cd2Sjpk }
16745916cd2Sjpk 
16845916cd2Sjpk static struct mntlist *
16945916cd2Sjpk tsol_mkmntlist(void)
17045916cd2Sjpk {
17145916cd2Sjpk 	FILE *mounted;
17245916cd2Sjpk 	struct mntlist *mntl;
17345916cd2Sjpk 	struct mntlist *mntst = NULL;
17445916cd2Sjpk 	struct mnttab mnt;
17545916cd2Sjpk 
176*004388ebScasper 	if ((mounted = fopen(MNTTAB, "rF")) == NULL) {
17745916cd2Sjpk 		perror(MNTTAB);
17845916cd2Sjpk 		return (NULL);
17945916cd2Sjpk 	}
18045916cd2Sjpk 	resetmnttab(mounted);
18145916cd2Sjpk 	while (getmntent(mounted, &mnt) == NULL) {
18245916cd2Sjpk 		mntl = (struct mntlist *)malloc(sizeof (*mntl));
18345916cd2Sjpk 		if (mntl == NULL) {
18445916cd2Sjpk 			tsol_mlist_free(mntst);
18545916cd2Sjpk 			mntst = NULL;
18645916cd2Sjpk 			break;
18745916cd2Sjpk 		}
18845916cd2Sjpk 		mntl->mntl_mnt = mntdup((struct mnttab *)(&mnt));
18945916cd2Sjpk 		if (mntl->mntl_mnt == NULL) {
19045916cd2Sjpk 			tsol_mlist_free(mntst);
19145916cd2Sjpk 			mntst = NULL;
19245916cd2Sjpk 			break;
19345916cd2Sjpk 		}
19445916cd2Sjpk 		mntl->mntl_next = mntst;
19545916cd2Sjpk 		mntst = mntl;
19645916cd2Sjpk 	}
19745916cd2Sjpk 	(void) fclose(mounted);
19845916cd2Sjpk 	return (mntst);
19945916cd2Sjpk }
20045916cd2Sjpk 
20145916cd2Sjpk /*
20245916cd2Sjpk  * This function attempts to convert local zone NFS mounted pathnames
20345916cd2Sjpk  * into equivalent global zone NFS mounted pathnames. At present
20445916cd2Sjpk  * it only works for automounted filesystems. It depends on the
20545916cd2Sjpk  * assumption that both the local and global zone automounters
20645916cd2Sjpk  * share the same nameservices. It also assumes that any automount
20745916cd2Sjpk  * map used by a local zone is available to the global zone automounter.
20845916cd2Sjpk  *
20945916cd2Sjpk  * The algorithm used consists of three phases.
21045916cd2Sjpk  *
21145916cd2Sjpk  * 1. The local zone's mnttab is searched to find the automount map
21245916cd2Sjpk  *    with the closest matching mountpath.
21345916cd2Sjpk  *
21445916cd2Sjpk  * 2. The matching autmount map name is looked up in the global zone's
21545916cd2Sjpk  *    mnttab to determine the path where it should be mounted in the
21645916cd2Sjpk  *    global zone.
21745916cd2Sjpk  *
21845916cd2Sjpk  * 3. A pathname covered by an appropiate autofs trigger mount in
21945916cd2Sjpk  *    the global zone is generated as the resolved pathname
22045916cd2Sjpk  *
22145916cd2Sjpk  * Among the things that can go wrong is that global zone doesn't have
22245916cd2Sjpk  * a matching automount map or the mount was not done via the automounter.
22345916cd2Sjpk  * Either of these cases return a NULL path.
22445916cd2Sjpk  */
22545916cd2Sjpk #define	ZONE_OPT "zone="
22645916cd2Sjpk static int
22745916cd2Sjpk getnfspathbyautofs(struct mntlist *mlist, zoneid_t zoneid,
22845916cd2Sjpk     struct mnttab *autofs_mnt, char *globalpath, char *zonepath, int global_len)
22945916cd2Sjpk {
23045916cd2Sjpk 	struct mntlist *mlp;
23145916cd2Sjpk 	char zonematch[ZONENAME_MAX + 20];
23245916cd2Sjpk 	char zonename[ZONENAME_MAX];
23345916cd2Sjpk 	int  longestmatch;
23445916cd2Sjpk 	struct	mnttab	*mountmatch;
23545916cd2Sjpk 
23645916cd2Sjpk 	if (autofs_mnt) {
23745916cd2Sjpk 		mountmatch = autofs_mnt;
23845916cd2Sjpk 		longestmatch = strlen(mountmatch->mnt_mountp);
23945916cd2Sjpk 	} else {
24045916cd2Sjpk 		/*
24145916cd2Sjpk 		 * First we need to get the zonename to look for
24245916cd2Sjpk 		 */
24345916cd2Sjpk 		if (zone_getattr(zoneid, ZONE_ATTR_NAME, zonename,
24445916cd2Sjpk 		    ZONENAME_MAX) == -1) {
24545916cd2Sjpk 			return (0);
24645916cd2Sjpk 		}
24745916cd2Sjpk 
24845916cd2Sjpk 		(void) strncpy(zonematch, ZONE_OPT, sizeof (zonematch));
24945916cd2Sjpk 		(void) strlcat(zonematch, zonename, sizeof (zonematch));
25045916cd2Sjpk 
25145916cd2Sjpk 		/*
25245916cd2Sjpk 		 * Find the best match for an automount map that
25345916cd2Sjpk 		 * corresponds to the local zone's pathname
25445916cd2Sjpk 		 */
25545916cd2Sjpk 		longestmatch = 0;
25645916cd2Sjpk 		for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
25745916cd2Sjpk 			struct mnttab *mnt = mlp->mntl_mnt;
25845916cd2Sjpk 			int	len;
25945916cd2Sjpk 			int	matchfound;
26045916cd2Sjpk 			char	*token;
26145916cd2Sjpk 			char	*lasts;
26245916cd2Sjpk 			char	mntopts[MAXPATHLEN];
26345916cd2Sjpk 
26445916cd2Sjpk 			if (subpath(globalpath, mnt->mnt_mountp) != 0)
26545916cd2Sjpk 				continue;
26645916cd2Sjpk 			if (strcmp(mnt->mnt_fstype, MNTTYPE_AUTOFS))
26745916cd2Sjpk 				continue;
26845916cd2Sjpk 
26945916cd2Sjpk 			matchfound = 0;
27045916cd2Sjpk 			(void) strncpy(mntopts, mnt->mnt_mntopts, MAXPATHLEN);
27145916cd2Sjpk 			if ((token = strtok_r(mntopts, ",", &lasts)) != NULL) {
27245916cd2Sjpk 				if (strcmp(token, zonematch) == 0) {
27345916cd2Sjpk 					matchfound = 1;
27445916cd2Sjpk 				} else while ((token = strtok_r(NULL, ",",
27545916cd2Sjpk 				    &lasts)) != NULL) {
27645916cd2Sjpk 					if (strcmp(token, zonematch) == 0) {
27745916cd2Sjpk 						matchfound = 1;
27845916cd2Sjpk 						break;
27945916cd2Sjpk 					}
28045916cd2Sjpk 				}
28145916cd2Sjpk 			}
28245916cd2Sjpk 			if (matchfound) {
28345916cd2Sjpk 				len = strlen(mnt->mnt_mountp);
28445916cd2Sjpk 				if (len > longestmatch) {
28545916cd2Sjpk 					mountmatch = mnt;
28645916cd2Sjpk 					longestmatch = len;
28745916cd2Sjpk 				}
28845916cd2Sjpk 			}
28945916cd2Sjpk 		}
29045916cd2Sjpk 	}
29145916cd2Sjpk 	if (longestmatch == 0) {
29245916cd2Sjpk 		return (0);
29345916cd2Sjpk 	} else {
29445916cd2Sjpk 		/*
29545916cd2Sjpk 		 * Now we may have found the corresponding autofs mount
29645916cd2Sjpk 		 * Try to find the matching global zone autofs entry
29745916cd2Sjpk 		 */
29845916cd2Sjpk 
29945916cd2Sjpk 		for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
30045916cd2Sjpk 			char p[MAXPATHLEN];
30145916cd2Sjpk 			size_t zp_len;
30245916cd2Sjpk 			size_t mp_len;
30345916cd2Sjpk 
30445916cd2Sjpk 			struct mnttab *mnt = mlp->mntl_mnt;
30545916cd2Sjpk 
30645916cd2Sjpk 			if (strcmp(mountmatch->mnt_special,
30745916cd2Sjpk 			    mnt->mnt_special) != 0)
30845916cd2Sjpk 				continue;
30945916cd2Sjpk 			if (strcmp(mnt->mnt_fstype, MNTTYPE_AUTOFS))
31045916cd2Sjpk 				continue;
31145916cd2Sjpk 			if (strstr(mnt->mnt_mntopts, ZONE_OPT) != NULL)
31245916cd2Sjpk 				continue;
31345916cd2Sjpk 			/*
31445916cd2Sjpk 			 * OK, we have a matching global zone automap
31545916cd2Sjpk 			 * so adjust the path for the global zone.
31645916cd2Sjpk 			 */
31745916cd2Sjpk 			zp_len = strlen(zonepath);
31845916cd2Sjpk 			mp_len = strlen(mnt->mnt_mountp);
31945916cd2Sjpk 			(void) strncpy(p, globalpath + zp_len, MAXPATHLEN);
32045916cd2Sjpk 			/*
32145916cd2Sjpk 			 * If both global zone and zone-relative
32245916cd2Sjpk 			 * mountpoint match, just use the same pathname
32345916cd2Sjpk 			 */
32445916cd2Sjpk 			if (strncmp(mnt->mnt_mountp, p, mp_len) == 0) {
32545916cd2Sjpk 				(void) strncpy(globalpath, p, global_len);
32645916cd2Sjpk 				return (1);
32745916cd2Sjpk 			} else {
32845916cd2Sjpk 				(void) strncpy(p, globalpath, MAXPATHLEN);
32945916cd2Sjpk 				(void) strncpy(globalpath, mnt->mnt_mountp,
33045916cd2Sjpk 				    global_len);
33145916cd2Sjpk 				(void) strlcat(globalpath,
33245916cd2Sjpk 				    p + strlen(mountmatch->mnt_mountp),
33345916cd2Sjpk 				    global_len);
33445916cd2Sjpk 				return (1);
33545916cd2Sjpk 			}
33645916cd2Sjpk 		}
33745916cd2Sjpk 		return (0);
33845916cd2Sjpk 	}
33945916cd2Sjpk }
34045916cd2Sjpk 
34145916cd2Sjpk 	/*
34245916cd2Sjpk 	 * Find the pathname for the entry in mlist that corresponds to the
34345916cd2Sjpk 	 * file named by path (i.e., that names a mount table entry for the
34445916cd2Sjpk 	 * file system in which path lies).
34545916cd2Sjpk 	 *
34645916cd2Sjpk 	 * Return 0 is there an error.
34745916cd2Sjpk 	 */
34845916cd2Sjpk 	static int
34945916cd2Sjpk 	getglobalpath(const char *path, zoneid_t zoneid, struct mntlist *mlist,
35045916cd2Sjpk 	    char *globalpath)
35145916cd2Sjpk 	{
35245916cd2Sjpk 		struct mntlist *mlp;
35345916cd2Sjpk 		char		lofspath[MAXPATHLEN];
35445916cd2Sjpk 		char		zonepath[MAXPATHLEN];
35545916cd2Sjpk 		int		longestmatch;
35645916cd2Sjpk 		struct	mnttab	*mountmatch;
35745916cd2Sjpk 
35845916cd2Sjpk 		if (zoneid != GLOBAL_ZONEID) {
35945916cd2Sjpk 			char	*prefix;
36045916cd2Sjpk 
36145916cd2Sjpk 			if ((prefix = getzonerootbyid(zoneid)) == NULL) {
36245916cd2Sjpk 				return (0);
36345916cd2Sjpk 			}
36445916cd2Sjpk 			(void) strncpy(zonepath, prefix, MAXPATHLEN);
36545916cd2Sjpk 			(void) strlcpy(globalpath, prefix, MAXPATHLEN);
36645916cd2Sjpk 			(void) strlcat(globalpath, path, MAXPATHLEN);
36745916cd2Sjpk 			free(prefix);
36845916cd2Sjpk 		} else {
36945916cd2Sjpk 			(void) strlcpy(globalpath, path, MAXPATHLEN);
37045916cd2Sjpk 		}
37145916cd2Sjpk 
37245916cd2Sjpk 		for (;;) {
37345916cd2Sjpk 			longestmatch = 0;
37445916cd2Sjpk 			for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
37545916cd2Sjpk 				struct mnttab *mnt = mlp->mntl_mnt;
37645916cd2Sjpk 				int	len;
37745916cd2Sjpk 
37845916cd2Sjpk 			if (subpath(globalpath, mnt->mnt_mountp) != 0)
37945916cd2Sjpk 				continue;
38045916cd2Sjpk 			len = strlen(mnt->mnt_mountp);
38145916cd2Sjpk 			if (len > longestmatch) {
38245916cd2Sjpk 				mountmatch = mnt;
38345916cd2Sjpk 				longestmatch = len;
38445916cd2Sjpk 			}
38545916cd2Sjpk 		}
38645916cd2Sjpk 		/*
38745916cd2Sjpk 		 * Handle interesting mounts.
38845916cd2Sjpk 		 */
38945916cd2Sjpk 		if ((strcmp(mountmatch->mnt_fstype, MNTTYPE_NFS) == 0) ||
39045916cd2Sjpk 		    (strcmp(mountmatch->mnt_fstype, MNTTYPE_AUTOFS) == 0)) {
39145916cd2Sjpk 			if (zoneid > GLOBAL_ZONEID) {
39245916cd2Sjpk 				struct mnttab *m = NULL;
39345916cd2Sjpk 
39445916cd2Sjpk 				if (strcmp(mountmatch->mnt_fstype,
39545916cd2Sjpk 				    MNTTYPE_AUTOFS) == 0)
39645916cd2Sjpk 					m = mountmatch;
39745916cd2Sjpk 				if (getnfspathbyautofs(mlist, zoneid, m,
39845916cd2Sjpk 				    globalpath, zonepath, MAXPATHLEN) == 0) {
39945916cd2Sjpk 					return (0);
40045916cd2Sjpk 				}
40145916cd2Sjpk 			}
40245916cd2Sjpk 			break;
40345916cd2Sjpk 		} else if (strcmp(mountmatch->mnt_fstype, MNTTYPE_LOFS) == 0) {
40445916cd2Sjpk 			/*
40545916cd2Sjpk 			 * count up what's left
40645916cd2Sjpk 			 */
40745916cd2Sjpk 			int	remainder;
40845916cd2Sjpk 
40945916cd2Sjpk 			remainder = strlen(globalpath) - longestmatch;
41045916cd2Sjpk 			if (remainder > 0) {
41145916cd2Sjpk 				path = pathsuffix(globalpath,
41245916cd2Sjpk 				    mountmatch->mnt_mountp);
41345916cd2Sjpk 				(void) strlcpy(lofspath, path, MAXPATHLEN);
41445916cd2Sjpk 			}
41545916cd2Sjpk 			(void) strlcpy(globalpath, mountmatch->mnt_special,
41645916cd2Sjpk 			    MAXPATHLEN);
41745916cd2Sjpk 			if (remainder > 0) {
41845916cd2Sjpk 				(void) strlcat(globalpath, lofspath,
41945916cd2Sjpk 				    MAXPATHLEN);
42045916cd2Sjpk 			}
42145916cd2Sjpk 		} else {
42245916cd2Sjpk 			if ((zoneid > GLOBAL_ZONEID) &&
42345916cd2Sjpk 			    (strncmp(path, "/home/", strlen("/home/")) == 0)) {
42445916cd2Sjpk 				char zonename[ZONENAME_MAX];
42545916cd2Sjpk 
42645916cd2Sjpk 				/*
42745916cd2Sjpk 				 * If this is a cross-zone reference to
42845916cd2Sjpk 				 * a home directory, it must be corrected.
42945916cd2Sjpk 				 * We should only get here if the zone's
43045916cd2Sjpk 				 * automounter hasn't yet mounted its
43145916cd2Sjpk 				 * autofs trigger on /home.
43245916cd2Sjpk 				 *
43345916cd2Sjpk 				 * Since it is likely to do so in the
43445916cd2Sjpk 				 * future, we will assume that the global
43545916cd2Sjpk 				 * zone already has an equivalent autofs
43645916cd2Sjpk 				 * mount established. By convention,
43745916cd2Sjpk 				 * this should be mounted at the
43845916cd2Sjpk 				 * /zone/<zonename>
43945916cd2Sjpk 				 */
44045916cd2Sjpk 
44145916cd2Sjpk 				if (zone_getattr(zoneid, ZONE_ATTR_NAME,
44245916cd2Sjpk 				    zonename, ZONENAME_MAX) == -1) {
44345916cd2Sjpk 					return (0);
44445916cd2Sjpk 				} else {
44545916cd2Sjpk 					(void) snprintf(globalpath, MAXPATHLEN,
44645916cd2Sjpk 					    "/zone/%s%s", zonename, path);
44745916cd2Sjpk 				}
44845916cd2Sjpk 			}
44945916cd2Sjpk 			break;
45045916cd2Sjpk 		}
45145916cd2Sjpk 	}
45245916cd2Sjpk 	return (1);
45345916cd2Sjpk }
45445916cd2Sjpk 
45545916cd2Sjpk 
45645916cd2Sjpk /*
45745916cd2Sjpk  * This function is only useful for global zone callers
45845916cd2Sjpk  * It uses the global zone mnttab to translate local zone pathnames
45945916cd2Sjpk  * into global zone pathnames.
46045916cd2Sjpk  */
46145916cd2Sjpk char *
46245916cd2Sjpk getpathbylabel(const char *path_name, char *resolved_path, size_t bufsize,
46345916cd2Sjpk     const bslabel_t *sl) {
46445916cd2Sjpk 	char		ret_path[MAXPATHLEN];	/* pathname to return */
46545916cd2Sjpk 	zoneid_t	zoneid;
46645916cd2Sjpk 	struct mntlist *mlist;
46745916cd2Sjpk 
46845916cd2Sjpk 	if (getzoneid() != GLOBAL_ZONEID) {
46945916cd2Sjpk 		errno = EINVAL;
47045916cd2Sjpk 		return (NULL);
47145916cd2Sjpk 	}
47245916cd2Sjpk 
47345916cd2Sjpk 	if (path_name[0] != '/') {		/* need absolute pathname */
47445916cd2Sjpk 		errno = EINVAL;
47545916cd2Sjpk 		return (NULL);
47645916cd2Sjpk 	}
47745916cd2Sjpk 
47845916cd2Sjpk 	if (resolved_path == NULL) {
47945916cd2Sjpk 		errno = EINVAL;
48045916cd2Sjpk 		return (NULL);
48145916cd2Sjpk 	}
48245916cd2Sjpk 
48345916cd2Sjpk 	if ((zoneid = getzoneidbylabel(sl)) == -1)
48445916cd2Sjpk 		return (NULL);
48545916cd2Sjpk 
48645916cd2Sjpk 	/*
48745916cd2Sjpk 	 * Construct the list of mounted file systems.
48845916cd2Sjpk 	 */
48945916cd2Sjpk 
49045916cd2Sjpk 	if ((mlist = tsol_mkmntlist()) == NULL) {
49145916cd2Sjpk 		return (NULL);
49245916cd2Sjpk 	}
49345916cd2Sjpk 	if (getglobalpath(path_name, zoneid, mlist, ret_path) == 0) {
49445916cd2Sjpk 		tsol_mlist_free(mlist);
49545916cd2Sjpk 		return (NULL);
49645916cd2Sjpk 	}
49745916cd2Sjpk 	tsol_mlist_free(mlist);
49845916cd2Sjpk 	if (strlen(ret_path) >= bufsize) {
49945916cd2Sjpk 		errno = EFAULT;
50045916cd2Sjpk 		return (NULL);
50145916cd2Sjpk 	}
50245916cd2Sjpk 	return (strcpy(resolved_path, ret_path));
50345916cd2Sjpk } /* end getpathbylabel() */
504