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 /*
22*e1dfad11Sjparcel * Copyright 2007 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 *
pathsuffix(char * full,char * pref)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
subpath(char * full,char * sub)9845916cd2Sjpk subpath(char *full, char *sub)
9945916cd2Sjpk {
10045916cd2Sjpk return (pathsuffix(full, sub) == NULL);
10145916cd2Sjpk }
10245916cd2Sjpk
10345916cd2Sjpk static void
tsol_mnt_free(struct mnttab * mnt)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
tsol_mlist_free(struct mntlist * mlist)11845916cd2Sjpk tsol_mlist_free(struct mntlist *mlist)
11945916cd2Sjpk {
12045916cd2Sjpk struct mntlist *mlp;
121*e1dfad11Sjparcel struct mntlist *oldmlp;
12245916cd2Sjpk
123*e1dfad11Sjparcel mlp = mlist;
124*e1dfad11Sjparcel while (mlp) {
12545916cd2Sjpk struct mnttab *mnt = mlp->mntl_mnt;
12645916cd2Sjpk
12745916cd2Sjpk if (mnt)
12845916cd2Sjpk tsol_mnt_free(mnt);
129*e1dfad11Sjparcel oldmlp = mlp;
130*e1dfad11Sjparcel mlp = mlp->mntl_next;
131*e1dfad11Sjparcel free(oldmlp);
13245916cd2Sjpk }
13345916cd2Sjpk }
13445916cd2Sjpk
13545916cd2Sjpk static struct mnttab *
mntdup(struct mnttab * mnt)13645916cd2Sjpk mntdup(struct mnttab *mnt)
13745916cd2Sjpk {
13845916cd2Sjpk struct mnttab *new;
13945916cd2Sjpk
14045916cd2Sjpk new = (struct mnttab *)malloc(sizeof (*new));
14145916cd2Sjpk if (new == NULL)
14245916cd2Sjpk return (NULL);
14345916cd2Sjpk
14445916cd2Sjpk new->mnt_special = NULL;
14545916cd2Sjpk new->mnt_mountp = NULL;
14645916cd2Sjpk new->mnt_fstype = NULL;
14745916cd2Sjpk new->mnt_mntopts = NULL;
14845916cd2Sjpk
14945916cd2Sjpk new->mnt_special = strdup(mnt->mnt_special);
15045916cd2Sjpk if (new->mnt_special == NULL) {
15145916cd2Sjpk tsol_mnt_free(new);
15245916cd2Sjpk return (NULL);
15345916cd2Sjpk }
15445916cd2Sjpk new->mnt_mountp = strdup(mnt->mnt_mountp);
15545916cd2Sjpk if (new->mnt_mountp == NULL) {
15645916cd2Sjpk tsol_mnt_free(new);
15745916cd2Sjpk return (NULL);
15845916cd2Sjpk }
15945916cd2Sjpk new->mnt_fstype = strdup(mnt->mnt_fstype);
16045916cd2Sjpk if (new->mnt_fstype == NULL) {
16145916cd2Sjpk tsol_mnt_free(new);
16245916cd2Sjpk return (NULL);
16345916cd2Sjpk }
16445916cd2Sjpk new->mnt_mntopts = strdup(mnt->mnt_mntopts);
16545916cd2Sjpk if (new->mnt_mntopts == NULL) {
16645916cd2Sjpk tsol_mnt_free(new);
16745916cd2Sjpk return (NULL);
16845916cd2Sjpk }
16945916cd2Sjpk return (new);
17045916cd2Sjpk }
17145916cd2Sjpk
17245916cd2Sjpk static struct mntlist *
tsol_mkmntlist(void)17345916cd2Sjpk tsol_mkmntlist(void)
17445916cd2Sjpk {
17545916cd2Sjpk FILE *mounted;
17645916cd2Sjpk struct mntlist *mntl;
17745916cd2Sjpk struct mntlist *mntst = NULL;
17845916cd2Sjpk struct mnttab mnt;
17945916cd2Sjpk
180004388ebScasper if ((mounted = fopen(MNTTAB, "rF")) == NULL) {
18145916cd2Sjpk perror(MNTTAB);
18245916cd2Sjpk return (NULL);
18345916cd2Sjpk }
18445916cd2Sjpk resetmnttab(mounted);
18545916cd2Sjpk while (getmntent(mounted, &mnt) == NULL) {
18645916cd2Sjpk mntl = (struct mntlist *)malloc(sizeof (*mntl));
18745916cd2Sjpk if (mntl == NULL) {
18845916cd2Sjpk tsol_mlist_free(mntst);
18945916cd2Sjpk mntst = NULL;
19045916cd2Sjpk break;
19145916cd2Sjpk }
19245916cd2Sjpk mntl->mntl_mnt = mntdup((struct mnttab *)(&mnt));
19345916cd2Sjpk if (mntl->mntl_mnt == NULL) {
19445916cd2Sjpk tsol_mlist_free(mntst);
19545916cd2Sjpk mntst = NULL;
19645916cd2Sjpk break;
19745916cd2Sjpk }
19845916cd2Sjpk mntl->mntl_next = mntst;
19945916cd2Sjpk mntst = mntl;
20045916cd2Sjpk }
20145916cd2Sjpk (void) fclose(mounted);
20245916cd2Sjpk return (mntst);
20345916cd2Sjpk }
20445916cd2Sjpk
20545916cd2Sjpk /*
20645916cd2Sjpk * This function attempts to convert local zone NFS mounted pathnames
20745916cd2Sjpk * into equivalent global zone NFS mounted pathnames. At present
20845916cd2Sjpk * it only works for automounted filesystems. It depends on the
20945916cd2Sjpk * assumption that both the local and global zone automounters
21045916cd2Sjpk * share the same nameservices. It also assumes that any automount
21145916cd2Sjpk * map used by a local zone is available to the global zone automounter.
21245916cd2Sjpk *
21345916cd2Sjpk * The algorithm used consists of three phases.
21445916cd2Sjpk *
21545916cd2Sjpk * 1. The local zone's mnttab is searched to find the automount map
21645916cd2Sjpk * with the closest matching mountpath.
21745916cd2Sjpk *
21845916cd2Sjpk * 2. The matching autmount map name is looked up in the global zone's
21945916cd2Sjpk * mnttab to determine the path where it should be mounted in the
22045916cd2Sjpk * global zone.
22145916cd2Sjpk *
22245916cd2Sjpk * 3. A pathname covered by an appropiate autofs trigger mount in
22345916cd2Sjpk * the global zone is generated as the resolved pathname
22445916cd2Sjpk *
22545916cd2Sjpk * Among the things that can go wrong is that global zone doesn't have
22645916cd2Sjpk * a matching automount map or the mount was not done via the automounter.
22745916cd2Sjpk * Either of these cases return a NULL path.
22845916cd2Sjpk */
22945916cd2Sjpk #define ZONE_OPT "zone="
23045916cd2Sjpk static int
getnfspathbyautofs(struct mntlist * mlist,zoneid_t zoneid,struct mnttab * autofs_mnt,char * globalpath,char * zonepath,int global_len)23145916cd2Sjpk getnfspathbyautofs(struct mntlist *mlist, zoneid_t zoneid,
23245916cd2Sjpk struct mnttab *autofs_mnt, char *globalpath, char *zonepath, int global_len)
23345916cd2Sjpk {
23445916cd2Sjpk struct mntlist *mlp;
23545916cd2Sjpk char zonematch[ZONENAME_MAX + 20];
23645916cd2Sjpk char zonename[ZONENAME_MAX];
23745916cd2Sjpk int longestmatch;
23845916cd2Sjpk struct mnttab *mountmatch;
23945916cd2Sjpk
24045916cd2Sjpk if (autofs_mnt) {
24145916cd2Sjpk mountmatch = autofs_mnt;
24245916cd2Sjpk longestmatch = strlen(mountmatch->mnt_mountp);
24345916cd2Sjpk } else {
24445916cd2Sjpk /*
24545916cd2Sjpk * First we need to get the zonename to look for
24645916cd2Sjpk */
24745916cd2Sjpk if (zone_getattr(zoneid, ZONE_ATTR_NAME, zonename,
24845916cd2Sjpk ZONENAME_MAX) == -1) {
24945916cd2Sjpk return (0);
25045916cd2Sjpk }
25145916cd2Sjpk
25245916cd2Sjpk (void) strncpy(zonematch, ZONE_OPT, sizeof (zonematch));
25345916cd2Sjpk (void) strlcat(zonematch, zonename, sizeof (zonematch));
25445916cd2Sjpk
25545916cd2Sjpk /*
25645916cd2Sjpk * Find the best match for an automount map that
25745916cd2Sjpk * corresponds to the local zone's pathname
25845916cd2Sjpk */
25945916cd2Sjpk longestmatch = 0;
26045916cd2Sjpk for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
26145916cd2Sjpk struct mnttab *mnt = mlp->mntl_mnt;
26245916cd2Sjpk int len;
26345916cd2Sjpk int matchfound;
26445916cd2Sjpk char *token;
26545916cd2Sjpk char *lasts;
26645916cd2Sjpk char mntopts[MAXPATHLEN];
26745916cd2Sjpk
26845916cd2Sjpk if (subpath(globalpath, mnt->mnt_mountp) != 0)
26945916cd2Sjpk continue;
27045916cd2Sjpk if (strcmp(mnt->mnt_fstype, MNTTYPE_AUTOFS))
27145916cd2Sjpk continue;
27245916cd2Sjpk
27345916cd2Sjpk matchfound = 0;
27445916cd2Sjpk (void) strncpy(mntopts, mnt->mnt_mntopts, MAXPATHLEN);
27545916cd2Sjpk if ((token = strtok_r(mntopts, ",", &lasts)) != NULL) {
27645916cd2Sjpk if (strcmp(token, zonematch) == 0) {
27745916cd2Sjpk matchfound = 1;
27845916cd2Sjpk } else while ((token = strtok_r(NULL, ",",
27945916cd2Sjpk &lasts)) != NULL) {
28045916cd2Sjpk if (strcmp(token, zonematch) == 0) {
28145916cd2Sjpk matchfound = 1;
28245916cd2Sjpk break;
28345916cd2Sjpk }
28445916cd2Sjpk }
28545916cd2Sjpk }
28645916cd2Sjpk if (matchfound) {
28745916cd2Sjpk len = strlen(mnt->mnt_mountp);
28845916cd2Sjpk if (len > longestmatch) {
28945916cd2Sjpk mountmatch = mnt;
29045916cd2Sjpk longestmatch = len;
29145916cd2Sjpk }
29245916cd2Sjpk }
29345916cd2Sjpk }
29445916cd2Sjpk }
29545916cd2Sjpk if (longestmatch == 0) {
29645916cd2Sjpk return (0);
29745916cd2Sjpk } else {
29845916cd2Sjpk /*
29945916cd2Sjpk * Now we may have found the corresponding autofs mount
30045916cd2Sjpk * Try to find the matching global zone autofs entry
30145916cd2Sjpk */
30245916cd2Sjpk
30345916cd2Sjpk for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
30445916cd2Sjpk char p[MAXPATHLEN];
30545916cd2Sjpk size_t zp_len;
30645916cd2Sjpk size_t mp_len;
30745916cd2Sjpk
30845916cd2Sjpk struct mnttab *mnt = mlp->mntl_mnt;
30945916cd2Sjpk
31045916cd2Sjpk if (strcmp(mountmatch->mnt_special,
31145916cd2Sjpk mnt->mnt_special) != 0)
31245916cd2Sjpk continue;
31345916cd2Sjpk if (strcmp(mnt->mnt_fstype, MNTTYPE_AUTOFS))
31445916cd2Sjpk continue;
31545916cd2Sjpk if (strstr(mnt->mnt_mntopts, ZONE_OPT) != NULL)
31645916cd2Sjpk continue;
31745916cd2Sjpk /*
31845916cd2Sjpk * OK, we have a matching global zone automap
31945916cd2Sjpk * so adjust the path for the global zone.
32045916cd2Sjpk */
32145916cd2Sjpk zp_len = strlen(zonepath);
32245916cd2Sjpk mp_len = strlen(mnt->mnt_mountp);
32345916cd2Sjpk (void) strncpy(p, globalpath + zp_len, MAXPATHLEN);
32445916cd2Sjpk /*
32545916cd2Sjpk * If both global zone and zone-relative
32645916cd2Sjpk * mountpoint match, just use the same pathname
32745916cd2Sjpk */
32845916cd2Sjpk if (strncmp(mnt->mnt_mountp, p, mp_len) == 0) {
32945916cd2Sjpk (void) strncpy(globalpath, p, global_len);
33045916cd2Sjpk return (1);
33145916cd2Sjpk } else {
33245916cd2Sjpk (void) strncpy(p, globalpath, MAXPATHLEN);
33345916cd2Sjpk (void) strncpy(globalpath, mnt->mnt_mountp,
33445916cd2Sjpk global_len);
33545916cd2Sjpk (void) strlcat(globalpath,
33645916cd2Sjpk p + strlen(mountmatch->mnt_mountp),
33745916cd2Sjpk global_len);
33845916cd2Sjpk return (1);
33945916cd2Sjpk }
34045916cd2Sjpk }
34145916cd2Sjpk return (0);
34245916cd2Sjpk }
34345916cd2Sjpk }
34445916cd2Sjpk
34545916cd2Sjpk /*
34645916cd2Sjpk * Find the pathname for the entry in mlist that corresponds to the
34745916cd2Sjpk * file named by path (i.e., that names a mount table entry for the
34845916cd2Sjpk * file system in which path lies).
34945916cd2Sjpk *
35045916cd2Sjpk * Return 0 is there an error.
35145916cd2Sjpk */
35245916cd2Sjpk static int
getglobalpath(const char * path,zoneid_t zoneid,struct mntlist * mlist,char * globalpath)35345916cd2Sjpk getglobalpath(const char *path, zoneid_t zoneid, struct mntlist *mlist,
35445916cd2Sjpk char *globalpath)
35545916cd2Sjpk {
35645916cd2Sjpk struct mntlist *mlp;
35745916cd2Sjpk char lofspath[MAXPATHLEN];
35845916cd2Sjpk char zonepath[MAXPATHLEN];
35945916cd2Sjpk int longestmatch;
36045916cd2Sjpk struct mnttab *mountmatch;
36145916cd2Sjpk
36245916cd2Sjpk if (zoneid != GLOBAL_ZONEID) {
36345916cd2Sjpk char *prefix;
36445916cd2Sjpk
36545916cd2Sjpk if ((prefix = getzonerootbyid(zoneid)) == NULL) {
36645916cd2Sjpk return (0);
36745916cd2Sjpk }
36845916cd2Sjpk (void) strncpy(zonepath, prefix, MAXPATHLEN);
36945916cd2Sjpk (void) strlcpy(globalpath, prefix, MAXPATHLEN);
37045916cd2Sjpk (void) strlcat(globalpath, path, MAXPATHLEN);
37145916cd2Sjpk free(prefix);
37245916cd2Sjpk } else {
37345916cd2Sjpk (void) strlcpy(globalpath, path, MAXPATHLEN);
37445916cd2Sjpk }
37545916cd2Sjpk
37645916cd2Sjpk for (;;) {
37745916cd2Sjpk longestmatch = 0;
37845916cd2Sjpk for (mlp = mlist; mlp; mlp = mlp->mntl_next) {
37945916cd2Sjpk struct mnttab *mnt = mlp->mntl_mnt;
38045916cd2Sjpk int len;
38145916cd2Sjpk
38245916cd2Sjpk if (subpath(globalpath, mnt->mnt_mountp) != 0)
38345916cd2Sjpk continue;
38445916cd2Sjpk len = strlen(mnt->mnt_mountp);
38545916cd2Sjpk if (len > longestmatch) {
38645916cd2Sjpk mountmatch = mnt;
38745916cd2Sjpk longestmatch = len;
38845916cd2Sjpk }
38945916cd2Sjpk }
39045916cd2Sjpk /*
39145916cd2Sjpk * Handle interesting mounts.
39245916cd2Sjpk */
39345916cd2Sjpk if ((strcmp(mountmatch->mnt_fstype, MNTTYPE_NFS) == 0) ||
39445916cd2Sjpk (strcmp(mountmatch->mnt_fstype, MNTTYPE_AUTOFS) == 0)) {
39545916cd2Sjpk if (zoneid > GLOBAL_ZONEID) {
39645916cd2Sjpk struct mnttab *m = NULL;
39745916cd2Sjpk
39845916cd2Sjpk if (strcmp(mountmatch->mnt_fstype,
39945916cd2Sjpk MNTTYPE_AUTOFS) == 0)
40045916cd2Sjpk m = mountmatch;
40145916cd2Sjpk if (getnfspathbyautofs(mlist, zoneid, m,
40245916cd2Sjpk globalpath, zonepath, MAXPATHLEN) == 0) {
40345916cd2Sjpk return (0);
40445916cd2Sjpk }
40545916cd2Sjpk }
40645916cd2Sjpk break;
40745916cd2Sjpk } else if (strcmp(mountmatch->mnt_fstype, MNTTYPE_LOFS) == 0) {
40845916cd2Sjpk /*
40945916cd2Sjpk * count up what's left
41045916cd2Sjpk */
41145916cd2Sjpk int remainder;
41245916cd2Sjpk
41345916cd2Sjpk remainder = strlen(globalpath) - longestmatch;
41445916cd2Sjpk if (remainder > 0) {
41545916cd2Sjpk path = pathsuffix(globalpath,
41645916cd2Sjpk mountmatch->mnt_mountp);
41745916cd2Sjpk (void) strlcpy(lofspath, path, MAXPATHLEN);
41845916cd2Sjpk }
41945916cd2Sjpk (void) strlcpy(globalpath, mountmatch->mnt_special,
42045916cd2Sjpk MAXPATHLEN);
42145916cd2Sjpk if (remainder > 0) {
42245916cd2Sjpk (void) strlcat(globalpath, lofspath,
42345916cd2Sjpk MAXPATHLEN);
42445916cd2Sjpk }
42545916cd2Sjpk } else {
42645916cd2Sjpk if ((zoneid > GLOBAL_ZONEID) &&
42745916cd2Sjpk (strncmp(path, "/home/", strlen("/home/")) == 0)) {
42845916cd2Sjpk char zonename[ZONENAME_MAX];
42945916cd2Sjpk
43045916cd2Sjpk /*
43145916cd2Sjpk * If this is a cross-zone reference to
43245916cd2Sjpk * a home directory, it must be corrected.
43345916cd2Sjpk * We should only get here if the zone's
43445916cd2Sjpk * automounter hasn't yet mounted its
43545916cd2Sjpk * autofs trigger on /home.
43645916cd2Sjpk *
43745916cd2Sjpk * Since it is likely to do so in the
43845916cd2Sjpk * future, we will assume that the global
43945916cd2Sjpk * zone already has an equivalent autofs
44045916cd2Sjpk * mount established. By convention,
44145916cd2Sjpk * this should be mounted at the
44245916cd2Sjpk * /zone/<zonename>
44345916cd2Sjpk */
44445916cd2Sjpk
44545916cd2Sjpk if (zone_getattr(zoneid, ZONE_ATTR_NAME,
44645916cd2Sjpk zonename, ZONENAME_MAX) == -1) {
44745916cd2Sjpk return (0);
44845916cd2Sjpk } else {
44945916cd2Sjpk (void) snprintf(globalpath, MAXPATHLEN,
45045916cd2Sjpk "/zone/%s%s", zonename, path);
45145916cd2Sjpk }
45245916cd2Sjpk }
45345916cd2Sjpk break;
45445916cd2Sjpk }
45545916cd2Sjpk }
45645916cd2Sjpk return (1);
45745916cd2Sjpk }
45845916cd2Sjpk
45945916cd2Sjpk
46045916cd2Sjpk /*
46145916cd2Sjpk * This function is only useful for global zone callers
46245916cd2Sjpk * It uses the global zone mnttab to translate local zone pathnames
46345916cd2Sjpk * into global zone pathnames.
46445916cd2Sjpk */
46545916cd2Sjpk char *
getpathbylabel(const char * path_name,char * resolved_path,size_t bufsize,const bslabel_t * sl)46645916cd2Sjpk getpathbylabel(const char *path_name, char *resolved_path, size_t bufsize,
467*e1dfad11Sjparcel const bslabel_t *sl)
468*e1dfad11Sjparcel {
46945916cd2Sjpk char ret_path[MAXPATHLEN]; /* pathname to return */
47045916cd2Sjpk zoneid_t zoneid;
47145916cd2Sjpk struct mntlist *mlist;
47245916cd2Sjpk
47345916cd2Sjpk if (getzoneid() != GLOBAL_ZONEID) {
47445916cd2Sjpk errno = EINVAL;
47545916cd2Sjpk return (NULL);
47645916cd2Sjpk }
47745916cd2Sjpk
47845916cd2Sjpk if (path_name[0] != '/') { /* need absolute pathname */
47945916cd2Sjpk errno = EINVAL;
48045916cd2Sjpk return (NULL);
48145916cd2Sjpk }
48245916cd2Sjpk
48345916cd2Sjpk if (resolved_path == NULL) {
48445916cd2Sjpk errno = EINVAL;
48545916cd2Sjpk return (NULL);
48645916cd2Sjpk }
48745916cd2Sjpk
48845916cd2Sjpk if ((zoneid = getzoneidbylabel(sl)) == -1)
48945916cd2Sjpk return (NULL);
49045916cd2Sjpk
49145916cd2Sjpk /*
49245916cd2Sjpk * Construct the list of mounted file systems.
49345916cd2Sjpk */
49445916cd2Sjpk
49545916cd2Sjpk if ((mlist = tsol_mkmntlist()) == NULL) {
49645916cd2Sjpk return (NULL);
49745916cd2Sjpk }
49845916cd2Sjpk if (getglobalpath(path_name, zoneid, mlist, ret_path) == 0) {
49945916cd2Sjpk tsol_mlist_free(mlist);
50045916cd2Sjpk return (NULL);
50145916cd2Sjpk }
50245916cd2Sjpk tsol_mlist_free(mlist);
50345916cd2Sjpk if (strlen(ret_path) >= bufsize) {
50445916cd2Sjpk errno = EFAULT;
50545916cd2Sjpk return (NULL);
50645916cd2Sjpk }
50745916cd2Sjpk return (strcpy(resolved_path, ret_path));
50845916cd2Sjpk } /* end getpathbylabel() */
509