1*45916cd2Sjpk /*
2*45916cd2Sjpk  * CDDL HEADER START
3*45916cd2Sjpk  *
4*45916cd2Sjpk  * The contents of this file are subject to the terms of the
5*45916cd2Sjpk  * Common Development and Distribution License (the "License").
6*45916cd2Sjpk  * You may not use this file except in compliance with the License.
7*45916cd2Sjpk  *
8*45916cd2Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*45916cd2Sjpk  * or http://www.opensolaris.org/os/licensing.
10*45916cd2Sjpk  * See the License for the specific language governing permissions
11*45916cd2Sjpk  * and limitations under the License.
12*45916cd2Sjpk  *
13*45916cd2Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
14*45916cd2Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*45916cd2Sjpk  * If applicable, add the following below this CDDL HEADER, with the
16*45916cd2Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
17*45916cd2Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
18*45916cd2Sjpk  *
19*45916cd2Sjpk  * CDDL HEADER END
20*45916cd2Sjpk  */
21*45916cd2Sjpk /*
22*45916cd2Sjpk  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*45916cd2Sjpk  * Use is subject to license terms.
24*45916cd2Sjpk  */
25*45916cd2Sjpk 
26*45916cd2Sjpk #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*45916cd2Sjpk 
28*45916cd2Sjpk 
29*45916cd2Sjpk /*
30*45916cd2Sjpk  *	Name:		getpathbylabel.c
31*45916cd2Sjpk  *
32*45916cd2Sjpk  *	Description:	Returns the global zone pathname corresponding
33*45916cd2Sjpk  *			to the specified label. The pathname does
34*45916cd2Sjpk  *			not need to match an existing file system object.
35*45916cd2Sjpk  *
36*45916cd2Sjpk  */
37*45916cd2Sjpk #include <stdio.h>
38*45916cd2Sjpk #include <string.h>
39*45916cd2Sjpk #include <unistd.h>
40*45916cd2Sjpk #include <errno.h>
41*45916cd2Sjpk #include <sys/types.h>
42*45916cd2Sjpk #include <tsol/label.h>
43*45916cd2Sjpk #include <stdlib.h>
44*45916cd2Sjpk #include <zone.h>
45*45916cd2Sjpk #include <sys/mntent.h>
46*45916cd2Sjpk #include <sys/mnttab.h>
47*45916cd2Sjpk #include <stdarg.h>
48*45916cd2Sjpk 
49*45916cd2Sjpk /*
50*45916cd2Sjpk  * This structure is used to chain mntent structures into a list
51*45916cd2Sjpk  * and to cache stat information for each member of the list.
52*45916cd2Sjpk  */
53*45916cd2Sjpk struct mntlist {
54*45916cd2Sjpk 	struct mnttab	*mntl_mnt;
55*45916cd2Sjpk 	struct mntlist	*mntl_next;
56*45916cd2Sjpk };
57*45916cd2Sjpk 
58*45916cd2Sjpk 
59*45916cd2Sjpk /*
60*45916cd2Sjpk  * Return a pointer to the trailing suffix of full that follows the prefix
61*45916cd2Sjpk  * given by pref.  If pref isn't a prefix of full, return NULL.  Apply
62*45916cd2Sjpk  * pathname semantics to the prefix test, so that pref must match at a
63*45916cd2Sjpk  * component boundary.
64*45916cd2Sjpk  */
65*45916cd2Sjpk static char *
66*45916cd2Sjpk pathsuffix(char *full, char *pref)
67*45916cd2Sjpk {
68*45916cd2Sjpk 	int preflen;
69*45916cd2Sjpk 
70*45916cd2Sjpk 	if (full == NULL || pref == NULL)
71*45916cd2Sjpk 		return (NULL);
72*45916cd2Sjpk 
73*45916cd2Sjpk 	preflen = strlen(pref);
74*45916cd2Sjpk 	if (strncmp(pref, full, preflen) != 0)
75*45916cd2Sjpk 		return (NULL);
76*45916cd2Sjpk 
77*45916cd2Sjpk 	/*
78*45916cd2Sjpk 	 * pref is a substring of full.  To be a subpath, it cannot cover a
79*45916cd2Sjpk 	 * partial component of full.  The last clause of the test handles the
80*45916cd2Sjpk 	 * special case of the root.
81*45916cd2Sjpk 	 */
82*45916cd2Sjpk 	if (full[preflen] != '\0' && full[preflen] != '/' && preflen > 1)
83*45916cd2Sjpk 		return (NULL);
84*45916cd2Sjpk 
85*45916cd2Sjpk 	if (preflen == 1 && full[0] == '/')
86*45916cd2Sjpk 		return (full);
87*45916cd2Sjpk 	else
88*45916cd2Sjpk 		return (full + preflen);
89*45916cd2Sjpk }
90*45916cd2Sjpk 
91*45916cd2Sjpk /*
92*45916cd2Sjpk  * Return zero iff the path named by sub is a leading subpath
93*45916cd2Sjpk  * of the path named by full.
94*45916cd2Sjpk  *
95*45916cd2Sjpk  * Treat null paths as matching nothing.
96*45916cd2Sjpk  */
97*45916cd2Sjpk static int
98*45916cd2Sjpk subpath(char *full, char *sub)
99*45916cd2Sjpk {
100*45916cd2Sjpk 	return (pathsuffix(full, sub) == NULL);
101*45916cd2Sjpk }
102*45916cd2Sjpk 
103*45916cd2Sjpk static void
104*45916cd2Sjpk tsol_mnt_free(struct mnttab *mnt)
105*45916cd2Sjpk {
106*45916cd2Sjpk 	if (mnt->mnt_special)
107*45916cd2Sjpk 		free(mnt->mnt_special);
108*45916cd2Sjpk 	if (mnt->mnt_mountp)
109*45916cd2Sjpk 		free(mnt->mnt_mountp);
110*45916cd2Sjpk 	if (mnt->mnt_fstype)
111*45916cd2Sjpk 		free(mnt->mnt_fstype);
112*45916cd2Sjpk 	if (mnt->mnt_mntopts)
113*45916cd2Sjpk 		free(mnt->mnt_mntopts);
114*45916cd2Sjpk 	free(mnt);
115*45916cd2Sjpk }
116*45916cd2Sjpk 
117*45916cd2Sjpk static void
118*45916cd2Sjpk tsol_mlist_free(struct mntlist *mlist)
119*45916cd2Sjpk {
120*45916cd2Sjpk 	struct mntlist *mlp;
121*45916cd2Sjpk 
122*45916cd2Sjpk 	for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
123*45916cd2Sjpk 		struct mnttab *mnt = mlp->mntl_mnt;
124*45916cd2Sjpk 
125*45916cd2Sjpk 		if (mnt)
126*45916cd2Sjpk 			tsol_mnt_free(mnt);
127*45916cd2Sjpk 		free(mlp);
128*45916cd2Sjpk 	}
129*45916cd2Sjpk }
130*45916cd2Sjpk 
131*45916cd2Sjpk static struct mnttab *
132*45916cd2Sjpk mntdup(struct mnttab *mnt)
133*45916cd2Sjpk {
134*45916cd2Sjpk 	struct mnttab *new;
135*45916cd2Sjpk 
136*45916cd2Sjpk 	new = (struct mnttab *)malloc(sizeof (*new));
137*45916cd2Sjpk 	if (new == NULL)
138*45916cd2Sjpk 		return (NULL);
139*45916cd2Sjpk 
140*45916cd2Sjpk 	new->mnt_special = NULL;
141*45916cd2Sjpk 	new->mnt_mountp = NULL;
142*45916cd2Sjpk 	new->mnt_fstype = NULL;
143*45916cd2Sjpk 	new->mnt_mntopts = NULL;
144*45916cd2Sjpk 
145*45916cd2Sjpk 	new->mnt_special = strdup(mnt->mnt_special);
146*45916cd2Sjpk 	if (new->mnt_special == NULL) {
147*45916cd2Sjpk 		tsol_mnt_free(new);
148*45916cd2Sjpk 		return (NULL);
149*45916cd2Sjpk 	}
150*45916cd2Sjpk 	new->mnt_mountp = strdup(mnt->mnt_mountp);
151*45916cd2Sjpk 	if (new->mnt_mountp == NULL) {
152*45916cd2Sjpk 		tsol_mnt_free(new);
153*45916cd2Sjpk 		return (NULL);
154*45916cd2Sjpk 	}
155*45916cd2Sjpk 	new->mnt_fstype = strdup(mnt->mnt_fstype);
156*45916cd2Sjpk 	if (new->mnt_fstype == NULL) {
157*45916cd2Sjpk 		tsol_mnt_free(new);
158*45916cd2Sjpk 		return (NULL);
159*45916cd2Sjpk 	}
160*45916cd2Sjpk 	new->mnt_mntopts = strdup(mnt->mnt_mntopts);
161*45916cd2Sjpk 	if (new->mnt_mntopts == NULL) {
162*45916cd2Sjpk 		tsol_mnt_free(new);
163*45916cd2Sjpk 		return (NULL);
164*45916cd2Sjpk 	}
165*45916cd2Sjpk 	return (new);
166*45916cd2Sjpk }
167*45916cd2Sjpk 
168*45916cd2Sjpk static struct mntlist *
169*45916cd2Sjpk tsol_mkmntlist(void)
170*45916cd2Sjpk {
171*45916cd2Sjpk 	FILE *mounted;
172*45916cd2Sjpk 	struct mntlist *mntl;
173*45916cd2Sjpk 	struct mntlist *mntst = NULL;
174*45916cd2Sjpk 	struct mnttab mnt;
175*45916cd2Sjpk 
176*45916cd2Sjpk 	if ((mounted = fopen(MNTTAB, "r")) == NULL) {
177*45916cd2Sjpk 		perror(MNTTAB);
178*45916cd2Sjpk 		return (NULL);
179*45916cd2Sjpk 	}
180*45916cd2Sjpk 	resetmnttab(mounted);
181*45916cd2Sjpk 	while (getmntent(mounted, &mnt) == NULL) {
182*45916cd2Sjpk 		mntl = (struct mntlist *)malloc(sizeof (*mntl));
183*45916cd2Sjpk 		if (mntl == NULL) {
184*45916cd2Sjpk 			tsol_mlist_free(mntst);
185*45916cd2Sjpk 			mntst = NULL;
186*45916cd2Sjpk 			break;
187*45916cd2Sjpk 		}
188*45916cd2Sjpk 		mntl->mntl_mnt = mntdup((struct mnttab *)(&mnt));
189*45916cd2Sjpk 		if (mntl->mntl_mnt == NULL) {
190*45916cd2Sjpk 			tsol_mlist_free(mntst);
191*45916cd2Sjpk 			mntst = NULL;
192*45916cd2Sjpk 			break;
193*45916cd2Sjpk 		}
194*45916cd2Sjpk 		mntl->mntl_next = mntst;
195*45916cd2Sjpk 		mntst = mntl;
196*45916cd2Sjpk 	}
197*45916cd2Sjpk 	(void) fclose(mounted);
198*45916cd2Sjpk 	return (mntst);
199*45916cd2Sjpk }
200*45916cd2Sjpk 
201*45916cd2Sjpk /*
202*45916cd2Sjpk  * This function attempts to convert local zone NFS mounted pathnames
203*45916cd2Sjpk  * into equivalent global zone NFS mounted pathnames. At present
204*45916cd2Sjpk  * it only works for automounted filesystems. It depends on the
205*45916cd2Sjpk  * assumption that both the local and global zone automounters
206*45916cd2Sjpk  * share the same nameservices. It also assumes that any automount
207*45916cd2Sjpk  * map used by a local zone is available to the global zone automounter.
208*45916cd2Sjpk  *
209*45916cd2Sjpk  * The algorithm used consists of three phases.
210*45916cd2Sjpk  *
211*45916cd2Sjpk  * 1. The local zone's mnttab is searched to find the automount map
212*45916cd2Sjpk  *    with the closest matching mountpath.
213*45916cd2Sjpk  *
214*45916cd2Sjpk  * 2. The matching autmount map name is looked up in the global zone's
215*45916cd2Sjpk  *    mnttab to determine the path where it should be mounted in the
216*45916cd2Sjpk  *    global zone.
217*45916cd2Sjpk  *
218*45916cd2Sjpk  * 3. A pathname covered by an appropiate autofs trigger mount in
219*45916cd2Sjpk  *    the global zone is generated as the resolved pathname
220*45916cd2Sjpk  *
221*45916cd2Sjpk  * Among the things that can go wrong is that global zone doesn't have
222*45916cd2Sjpk  * a matching automount map or the mount was not done via the automounter.
223*45916cd2Sjpk  * Either of these cases return a NULL path.
224*45916cd2Sjpk  */
225*45916cd2Sjpk #define	ZONE_OPT "zone="
226*45916cd2Sjpk static int
227*45916cd2Sjpk getnfspathbyautofs(struct mntlist *mlist, zoneid_t zoneid,
228*45916cd2Sjpk     struct mnttab *autofs_mnt, char *globalpath, char *zonepath, int global_len)
229*45916cd2Sjpk {
230*45916cd2Sjpk 	struct mntlist *mlp;
231*45916cd2Sjpk 	char zonematch[ZONENAME_MAX + 20];
232*45916cd2Sjpk 	char zonename[ZONENAME_MAX];
233*45916cd2Sjpk 	int  longestmatch;
234*45916cd2Sjpk 	struct	mnttab	*mountmatch;
235*45916cd2Sjpk 
236*45916cd2Sjpk 	if (autofs_mnt) {
237*45916cd2Sjpk 		mountmatch = autofs_mnt;
238*45916cd2Sjpk 		longestmatch = strlen(mountmatch->mnt_mountp);
239*45916cd2Sjpk 	} else {
240*45916cd2Sjpk 		/*
241*45916cd2Sjpk 		 * First we need to get the zonename to look for
242*45916cd2Sjpk 		 */
243*45916cd2Sjpk 		if (zone_getattr(zoneid, ZONE_ATTR_NAME, zonename,
244*45916cd2Sjpk 		    ZONENAME_MAX) == -1) {
245*45916cd2Sjpk 			return (0);
246*45916cd2Sjpk 		}
247*45916cd2Sjpk 
248*45916cd2Sjpk 		(void) strncpy(zonematch, ZONE_OPT, sizeof (zonematch));
249*45916cd2Sjpk 		(void) strlcat(zonematch, zonename, sizeof (zonematch));
250*45916cd2Sjpk 
251*45916cd2Sjpk 		/*
252*45916cd2Sjpk 		 * Find the best match for an automount map that
253*45916cd2Sjpk 		 * corresponds to the local zone's pathname
254*45916cd2Sjpk 		 */
255*45916cd2Sjpk 		longestmatch = 0;
256*45916cd2Sjpk 		for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
257*45916cd2Sjpk 			struct mnttab *mnt = mlp->mntl_mnt;
258*45916cd2Sjpk 			int	len;
259*45916cd2Sjpk 			int	matchfound;
260*45916cd2Sjpk 			char	*token;
261*45916cd2Sjpk 			char	*lasts;
262*45916cd2Sjpk 			char	mntopts[MAXPATHLEN];
263*45916cd2Sjpk 
264*45916cd2Sjpk 			if (subpath(globalpath, mnt->mnt_mountp) != 0)
265*45916cd2Sjpk 				continue;
266*45916cd2Sjpk 			if (strcmp(mnt->mnt_fstype, MNTTYPE_AUTOFS))
267*45916cd2Sjpk 				continue;
268*45916cd2Sjpk 
269*45916cd2Sjpk 			matchfound = 0;
270*45916cd2Sjpk 			(void) strncpy(mntopts, mnt->mnt_mntopts, MAXPATHLEN);
271*45916cd2Sjpk 			if ((token = strtok_r(mntopts, ",", &lasts)) != NULL) {
272*45916cd2Sjpk 				if (strcmp(token, zonematch) == 0) {
273*45916cd2Sjpk 					matchfound = 1;
274*45916cd2Sjpk 				} else while ((token = strtok_r(NULL, ",",
275*45916cd2Sjpk 				    &lasts)) != NULL) {
276*45916cd2Sjpk 					if (strcmp(token, zonematch) == 0) {
277*45916cd2Sjpk 						matchfound = 1;
278*45916cd2Sjpk 						break;
279*45916cd2Sjpk 					}
280*45916cd2Sjpk 				}
281*45916cd2Sjpk 			}
282*45916cd2Sjpk 			if (matchfound) {
283*45916cd2Sjpk 				len = strlen(mnt->mnt_mountp);
284*45916cd2Sjpk 				if (len > longestmatch) {
285*45916cd2Sjpk 					mountmatch = mnt;
286*45916cd2Sjpk 					longestmatch = len;
287*45916cd2Sjpk 				}
288*45916cd2Sjpk 			}
289*45916cd2Sjpk 		}
290*45916cd2Sjpk 	}
291*45916cd2Sjpk 	if (longestmatch == 0) {
292*45916cd2Sjpk 		return (0);
293*45916cd2Sjpk 	} else {
294*45916cd2Sjpk 		/*
295*45916cd2Sjpk 		 * Now we may have found the corresponding autofs mount
296*45916cd2Sjpk 		 * Try to find the matching global zone autofs entry
297*45916cd2Sjpk 		 */
298*45916cd2Sjpk 
299*45916cd2Sjpk 		for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
300*45916cd2Sjpk 			char p[MAXPATHLEN];
301*45916cd2Sjpk 			size_t zp_len;
302*45916cd2Sjpk 			size_t mp_len;
303*45916cd2Sjpk 
304*45916cd2Sjpk 			struct mnttab *mnt = mlp->mntl_mnt;
305*45916cd2Sjpk 
306*45916cd2Sjpk 			if (strcmp(mountmatch->mnt_special,
307*45916cd2Sjpk 			    mnt->mnt_special) != 0)
308*45916cd2Sjpk 				continue;
309*45916cd2Sjpk 			if (strcmp(mnt->mnt_fstype, MNTTYPE_AUTOFS))
310*45916cd2Sjpk 				continue;
311*45916cd2Sjpk 			if (strstr(mnt->mnt_mntopts, ZONE_OPT) != NULL)
312*45916cd2Sjpk 				continue;
313*45916cd2Sjpk 			/*
314*45916cd2Sjpk 			 * OK, we have a matching global zone automap
315*45916cd2Sjpk 			 * so adjust the path for the global zone.
316*45916cd2Sjpk 			 */
317*45916cd2Sjpk 			zp_len = strlen(zonepath);
318*45916cd2Sjpk 			mp_len = strlen(mnt->mnt_mountp);
319*45916cd2Sjpk 			(void) strncpy(p, globalpath + zp_len, MAXPATHLEN);
320*45916cd2Sjpk 			/*
321*45916cd2Sjpk 			 * If both global zone and zone-relative
322*45916cd2Sjpk 			 * mountpoint match, just use the same pathname
323*45916cd2Sjpk 			 */
324*45916cd2Sjpk 			if (strncmp(mnt->mnt_mountp, p, mp_len) == 0) {
325*45916cd2Sjpk 				(void) strncpy(globalpath, p, global_len);
326*45916cd2Sjpk 				return (1);
327*45916cd2Sjpk 			} else {
328*45916cd2Sjpk 				(void) strncpy(p, globalpath, MAXPATHLEN);
329*45916cd2Sjpk 				(void) strncpy(globalpath, mnt->mnt_mountp,
330*45916cd2Sjpk 				    global_len);
331*45916cd2Sjpk 				(void) strlcat(globalpath,
332*45916cd2Sjpk 				    p + strlen(mountmatch->mnt_mountp),
333*45916cd2Sjpk 				    global_len);
334*45916cd2Sjpk 				return (1);
335*45916cd2Sjpk 			}
336*45916cd2Sjpk 		}
337*45916cd2Sjpk 		return (0);
338*45916cd2Sjpk 	}
339*45916cd2Sjpk }
340*45916cd2Sjpk 
341*45916cd2Sjpk 	/*
342*45916cd2Sjpk 	 * Find the pathname for the entry in mlist that corresponds to the
343*45916cd2Sjpk 	 * file named by path (i.e., that names a mount table entry for the
344*45916cd2Sjpk 	 * file system in which path lies).
345*45916cd2Sjpk 	 *
346*45916cd2Sjpk 	 * Return 0 is there an error.
347*45916cd2Sjpk 	 */
348*45916cd2Sjpk 	static int
349*45916cd2Sjpk 	getglobalpath(const char *path, zoneid_t zoneid, struct mntlist *mlist,
350*45916cd2Sjpk 	    char *globalpath)
351*45916cd2Sjpk 	{
352*45916cd2Sjpk 		struct mntlist *mlp;
353*45916cd2Sjpk 		char		lofspath[MAXPATHLEN];
354*45916cd2Sjpk 		char		zonepath[MAXPATHLEN];
355*45916cd2Sjpk 		int		longestmatch;
356*45916cd2Sjpk 		struct	mnttab	*mountmatch;
357*45916cd2Sjpk 
358*45916cd2Sjpk 		if (zoneid != GLOBAL_ZONEID) {
359*45916cd2Sjpk 			char	*prefix;
360*45916cd2Sjpk 
361*45916cd2Sjpk 			if ((prefix = getzonerootbyid(zoneid)) == NULL) {
362*45916cd2Sjpk 				return (0);
363*45916cd2Sjpk 			}
364*45916cd2Sjpk 			(void) strncpy(zonepath, prefix, MAXPATHLEN);
365*45916cd2Sjpk 			(void) strlcpy(globalpath, prefix, MAXPATHLEN);
366*45916cd2Sjpk 			(void) strlcat(globalpath, path, MAXPATHLEN);
367*45916cd2Sjpk 			free(prefix);
368*45916cd2Sjpk 		} else {
369*45916cd2Sjpk 			(void) strlcpy(globalpath, path, MAXPATHLEN);
370*45916cd2Sjpk 		}
371*45916cd2Sjpk 
372*45916cd2Sjpk 		for (;;) {
373*45916cd2Sjpk 			longestmatch = 0;
374*45916cd2Sjpk 			for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
375*45916cd2Sjpk 				struct mnttab *mnt = mlp->mntl_mnt;
376*45916cd2Sjpk 				int	len;
377*45916cd2Sjpk 
378*45916cd2Sjpk 			if (subpath(globalpath, mnt->mnt_mountp) != 0)
379*45916cd2Sjpk 				continue;
380*45916cd2Sjpk 			len = strlen(mnt->mnt_mountp);
381*45916cd2Sjpk 			if (len > longestmatch) {
382*45916cd2Sjpk 				mountmatch = mnt;
383*45916cd2Sjpk 				longestmatch = len;
384*45916cd2Sjpk 			}
385*45916cd2Sjpk 		}
386*45916cd2Sjpk 		/*
387*45916cd2Sjpk 		 * Handle interesting mounts.
388*45916cd2Sjpk 		 */
389*45916cd2Sjpk 		if ((strcmp(mountmatch->mnt_fstype, MNTTYPE_NFS) == 0) ||
390*45916cd2Sjpk 		    (strcmp(mountmatch->mnt_fstype, MNTTYPE_AUTOFS) == 0)) {
391*45916cd2Sjpk 			if (zoneid > GLOBAL_ZONEID) {
392*45916cd2Sjpk 				struct mnttab *m = NULL;
393*45916cd2Sjpk 
394*45916cd2Sjpk 				if (strcmp(mountmatch->mnt_fstype,
395*45916cd2Sjpk 				    MNTTYPE_AUTOFS) == 0)
396*45916cd2Sjpk 					m = mountmatch;
397*45916cd2Sjpk 				if (getnfspathbyautofs(mlist, zoneid, m,
398*45916cd2Sjpk 				    globalpath, zonepath, MAXPATHLEN) == 0) {
399*45916cd2Sjpk 					return (0);
400*45916cd2Sjpk 				}
401*45916cd2Sjpk 			}
402*45916cd2Sjpk 			break;
403*45916cd2Sjpk 		} else if (strcmp(mountmatch->mnt_fstype, MNTTYPE_LOFS) == 0) {
404*45916cd2Sjpk 			/*
405*45916cd2Sjpk 			 * count up what's left
406*45916cd2Sjpk 			 */
407*45916cd2Sjpk 			int	remainder;
408*45916cd2Sjpk 
409*45916cd2Sjpk 			remainder = strlen(globalpath) - longestmatch;
410*45916cd2Sjpk 			if (remainder > 0) {
411*45916cd2Sjpk 				path = pathsuffix(globalpath,
412*45916cd2Sjpk 				    mountmatch->mnt_mountp);
413*45916cd2Sjpk 				(void) strlcpy(lofspath, path, MAXPATHLEN);
414*45916cd2Sjpk 			}
415*45916cd2Sjpk 			(void) strlcpy(globalpath, mountmatch->mnt_special,
416*45916cd2Sjpk 			    MAXPATHLEN);
417*45916cd2Sjpk 			if (remainder > 0) {
418*45916cd2Sjpk 				(void) strlcat(globalpath, lofspath,
419*45916cd2Sjpk 				    MAXPATHLEN);
420*45916cd2Sjpk 			}
421*45916cd2Sjpk 		} else {
422*45916cd2Sjpk 			if ((zoneid > GLOBAL_ZONEID) &&
423*45916cd2Sjpk 			    (strncmp(path, "/home/", strlen("/home/")) == 0)) {
424*45916cd2Sjpk 				char zonename[ZONENAME_MAX];
425*45916cd2Sjpk 
426*45916cd2Sjpk 				/*
427*45916cd2Sjpk 				 * If this is a cross-zone reference to
428*45916cd2Sjpk 				 * a home directory, it must be corrected.
429*45916cd2Sjpk 				 * We should only get here if the zone's
430*45916cd2Sjpk 				 * automounter hasn't yet mounted its
431*45916cd2Sjpk 				 * autofs trigger on /home.
432*45916cd2Sjpk 				 *
433*45916cd2Sjpk 				 * Since it is likely to do so in the
434*45916cd2Sjpk 				 * future, we will assume that the global
435*45916cd2Sjpk 				 * zone already has an equivalent autofs
436*45916cd2Sjpk 				 * mount established. By convention,
437*45916cd2Sjpk 				 * this should be mounted at the
438*45916cd2Sjpk 				 * /zone/<zonename>
439*45916cd2Sjpk 				 */
440*45916cd2Sjpk 
441*45916cd2Sjpk 				if (zone_getattr(zoneid, ZONE_ATTR_NAME,
442*45916cd2Sjpk 				    zonename, ZONENAME_MAX) == -1) {
443*45916cd2Sjpk 					return (0);
444*45916cd2Sjpk 				} else {
445*45916cd2Sjpk 					(void) snprintf(globalpath, MAXPATHLEN,
446*45916cd2Sjpk 					    "/zone/%s%s", zonename, path);
447*45916cd2Sjpk 				}
448*45916cd2Sjpk 			}
449*45916cd2Sjpk 			break;
450*45916cd2Sjpk 		}
451*45916cd2Sjpk 	}
452*45916cd2Sjpk 	return (1);
453*45916cd2Sjpk }
454*45916cd2Sjpk 
455*45916cd2Sjpk 
456*45916cd2Sjpk /*
457*45916cd2Sjpk  * This function is only useful for global zone callers
458*45916cd2Sjpk  * It uses the global zone mnttab to translate local zone pathnames
459*45916cd2Sjpk  * into global zone pathnames.
460*45916cd2Sjpk  */
461*45916cd2Sjpk char *
462*45916cd2Sjpk getpathbylabel(const char *path_name, char *resolved_path, size_t bufsize,
463*45916cd2Sjpk     const bslabel_t *sl) {
464*45916cd2Sjpk 	char		ret_path[MAXPATHLEN];	/* pathname to return */
465*45916cd2Sjpk 	zoneid_t	zoneid;
466*45916cd2Sjpk 	struct mntlist *mlist;
467*45916cd2Sjpk 
468*45916cd2Sjpk 	if (getzoneid() != GLOBAL_ZONEID) {
469*45916cd2Sjpk 		errno = EINVAL;
470*45916cd2Sjpk 		return (NULL);
471*45916cd2Sjpk 	}
472*45916cd2Sjpk 
473*45916cd2Sjpk 	if (path_name[0] != '/') {		/* need absolute pathname */
474*45916cd2Sjpk 		errno = EINVAL;
475*45916cd2Sjpk 		return (NULL);
476*45916cd2Sjpk 	}
477*45916cd2Sjpk 
478*45916cd2Sjpk 	if (resolved_path == NULL) {
479*45916cd2Sjpk 		errno = EINVAL;
480*45916cd2Sjpk 		return (NULL);
481*45916cd2Sjpk 	}
482*45916cd2Sjpk 
483*45916cd2Sjpk 	if ((zoneid = getzoneidbylabel(sl)) == -1)
484*45916cd2Sjpk 		return (NULL);
485*45916cd2Sjpk 
486*45916cd2Sjpk 	/*
487*45916cd2Sjpk 	 * Construct the list of mounted file systems.
488*45916cd2Sjpk 	 */
489*45916cd2Sjpk 
490*45916cd2Sjpk 	if ((mlist = tsol_mkmntlist()) == NULL) {
491*45916cd2Sjpk 		return (NULL);
492*45916cd2Sjpk 	}
493*45916cd2Sjpk 	if (getglobalpath(path_name, zoneid, mlist, ret_path) == 0) {
494*45916cd2Sjpk 		tsol_mlist_free(mlist);
495*45916cd2Sjpk 		return (NULL);
496*45916cd2Sjpk 	}
497*45916cd2Sjpk 	tsol_mlist_free(mlist);
498*45916cd2Sjpk 	if (strlen(ret_path) >= bufsize) {
499*45916cd2Sjpk 		errno = EFAULT;
500*45916cd2Sjpk 		return (NULL);
501*45916cd2Sjpk 	}
502*45916cd2Sjpk 	return (strcpy(resolved_path, ret_path));
503*45916cd2Sjpk } /* end getpathbylabel() */
504