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