15c51f12Moriah Waterland/*
25c51f12Moriah Waterland * CDDL HEADER START
35c51f12Moriah Waterland *
45c51f12Moriah Waterland * The contents of this file are subject to the terms of the
55c51f12Moriah Waterland * Common Development and Distribution License (the "License").
65c51f12Moriah Waterland * You may not use this file except in compliance with the License.
75c51f12Moriah Waterland *
85c51f12Moriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f12Moriah Waterland * or http://www.opensolaris.org/os/licensing.
105c51f12Moriah Waterland * See the License for the specific language governing permissions
115c51f12Moriah Waterland * and limitations under the License.
125c51f12Moriah Waterland *
135c51f12Moriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
145c51f12Moriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f12Moriah Waterland * If applicable, add the following below this CDDL HEADER, with the
165c51f12Moriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
175c51f12Moriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f12Moriah Waterland *
195c51f12Moriah Waterland * CDDL HEADER END
205c51f12Moriah Waterland */
215c51f12Moriah Waterland
225c51f12Moriah Waterland/*
235c51f12Moriah Waterland * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245c51f12Moriah Waterland * Use is subject to license terms.
255c51f12Moriah Waterland */
265c51f12Moriah Waterland
275c51f12Moriah Waterland
285c51f12Moriah Waterland#include <stdio.h>
295c51f12Moriah Waterland#include <stdlib.h>
305c51f12Moriah Waterland#include <string.h>
315c51f12Moriah Waterland#include <unistd.h>
325c51f12Moriah Waterland#include <libintl.h>
335c51f12Moriah Waterland#include <errno.h>
345c51f12Moriah Waterland#include <assert.h>
355c51f12Moriah Waterland#include <sys/types.h>
365c51f12Moriah Waterland#include <sys/mntent.h>
375c51f12Moriah Waterland#include <sys/mnttab.h>
385c51f12Moriah Waterland#include <sys/param.h>
395c51f12Moriah Waterland#include <libzonecfg.h>
405c51f12Moriah Waterland#include "zones_strings.h"
415c51f12Moriah Waterland#include "instzones_lib.h"
425c51f12Moriah Waterland
435c51f12Moriah Waterland#define	MNTTAB	"/etc/mnttab"
445c51f12Moriah Waterland
455c51f12Moriah Waterland#define	MNTTAB_HUNK	32
465c51f12Moriah Waterland
475c51f12Moriah Waterlandstatic struct mnttab *mountTable;
485c51f12Moriah Waterlandstatic size_t mountTableSize = 0;
495c51f12Moriah Waterlandstatic boolean_t createdFlag = B_FALSE;
505c51f12Moriah Waterland
515c51f12Moriah Waterland/*
525c51f12Moriah Waterland * Name		: z_createMountTable
535c51f12Moriah Waterland * Description	: Populate the mountTable Array with mnttab entries
545c51f12Moriah Waterland * Arguments	: void
555c51f12Moriah Waterland * Returns	: int
565c51f12Moriah Waterland *		  0: The Mount Table was succesfully initialized
575c51f12Moriah Waterland *		 -1: There was an error during initialisation
585c51f12Moriah Waterland */
595c51f12Moriah Waterlandint
605c51f12Moriah Waterlandz_createMountTable(void)
615c51f12Moriah Waterland{
625c51f12Moriah Waterland	FILE *fp;
635c51f12Moriah Waterland	struct mnttab ent;
645c51f12Moriah Waterland	struct mnttab *entp;
655c51f12Moriah Waterland
665c51f12Moriah Waterland	if (createdFlag) {
675c51f12Moriah Waterland		return (0);
685c51f12Moriah Waterland	}
695c51f12Moriah Waterland
705c51f12Moriah Waterland	fp = fopen(MNTTAB, "r");
715c51f12Moriah Waterland	if (fp == NULL) {
725c51f12Moriah Waterland		_z_program_error(ERR_OPEN_READ, MNTTAB, errno,
735c51f12Moriah Waterland		    strerror(errno));
745c51f12Moriah Waterland		return (-1);
755c51f12Moriah Waterland	}
765c51f12Moriah Waterland
775c51f12Moriah Waterland	/* Put the entries into the table */
785c51f12Moriah Waterland	mountTable = NULL;
795c51f12Moriah Waterland	mountTableSize = 0;
805c51f12Moriah Waterland	createdFlag = B_TRUE;
815c51f12Moriah Waterland	while (getmntent(fp, &ent) == 0) {
825c51f12Moriah Waterland		if (mountTableSize % MNTTAB_HUNK == 0) {
835c51f12Moriah Waterland			mountTable = _z_realloc(mountTable,
845c51f12Moriah Waterland			    (mountTableSize + MNTTAB_HUNK) * sizeof (ent));
855c51f12Moriah Waterland		}
865c51f12Moriah Waterland		entp = &mountTable[mountTableSize++];
875c51f12Moriah Waterland
885c51f12Moriah Waterland		/*
895c51f12Moriah Waterland		 * Zero out any fields we're not using.
905c51f12Moriah Waterland		 */
915c51f12Moriah Waterland		(void) memset(entp, 0, sizeof (*entp));
925c51f12Moriah Waterland
935c51f12Moriah Waterland		if (ent.mnt_special != NULL)
945c51f12Moriah Waterland			entp->mnt_special = _z_strdup(ent.mnt_special);
955c51f12Moriah Waterland		if (ent.mnt_mntopts != NULL)
965c51f12Moriah Waterland			entp->mnt_mntopts = _z_strdup(ent.mnt_mntopts);
975c51f12Moriah Waterland		entp->mnt_mountp = _z_strdup(ent.mnt_mountp);
985c51f12Moriah Waterland		entp->mnt_fstype = _z_strdup(ent.mnt_fstype);
995c51f12Moriah Waterland	}
1005c51f12Moriah Waterland
1015c51f12Moriah Waterland	(void) fclose(fp);
1025c51f12Moriah Waterland	return (0);
1035c51f12Moriah Waterland}
1045c51f12Moriah Waterland
1055c51f12Moriah Waterland/*
1065c51f12Moriah Waterland * Name		: findPathRWStatus
1075c51f12Moriah Waterland * Description	: Check whether the given path is an mnttab entry
1085c51f12Moriah Waterland * Arguments	: char * - The Path to be verified
1095c51f12Moriah Waterland * Returns	: int
1105c51f12Moriah Waterland *		  -1: The Path is NOT present in the table (mnttab)
1115c51f12Moriah Waterland *		   0: The Path is present in the table and is mounted read-only
1125c51f12Moriah Waterland *		   1: The Path is present in the table and is mounted read-write
1135c51f12Moriah Waterland */
1145c51f12Moriah Waterlandstatic int
1155c51f12Moriah WaterlandfindPathRWStatus(const char *a_path)
1165c51f12Moriah Waterland{
1175c51f12Moriah Waterland	int i;
1185c51f12Moriah Waterland
1195c51f12Moriah Waterland	for (i = 0; i < mountTableSize; i++) {
1205c51f12Moriah Waterland		if (strcmp(a_path, mountTable[i].mnt_mountp) == 0) {
1215c51f12Moriah Waterland			if (hasmntopt(&mountTable[i], MNTOPT_RO) != NULL) {
1225c51f12Moriah Waterland				return (0);
1235c51f12Moriah Waterland			} else {
1245c51f12Moriah Waterland				return (1);
1255c51f12Moriah Waterland			}
1265c51f12Moriah Waterland		}
1275c51f12Moriah Waterland	}
1285c51f12Moriah Waterland
1295c51f12Moriah Waterland	return (-1);
1305c51f12Moriah Waterland}
1315c51f12Moriah Waterland
1325c51f12Moriah Waterland
1335c51f12Moriah Waterland/*
1345c51f12Moriah Waterland * Name		: z_isPathWritable
1355c51f12Moriah Waterland * Description	: Check if the given path is in a writable area
1365c51f12Moriah Waterland * Arguments	: char * - The Path to be verified
1375c51f12Moriah Waterland * Returns	: int
1385c51f12Moriah Waterland *		   0: The Path is under a read-only mount
1395c51f12Moriah Waterland *		   1: The Path is under a read-write mount
1405c51f12Moriah Waterland * NOTE		: This funcion automatically initialises
1415c51f12Moriah Waterland *		  the mountPoint table if needed.
1425c51f12Moriah Waterland */
1435c51f12Moriah Waterlandint
1445c51f12Moriah Waterlandz_isPathWritable(const char *a_str)
1455c51f12Moriah Waterland{
1465c51f12Moriah Waterland	int i, result, slen;
1475c51f12Moriah Waterland	char a_path[MAXPATHLEN];
1485c51f12Moriah Waterland
1495c51f12Moriah Waterland	if (!createdFlag) {
1505c51f12Moriah Waterland		if (z_createMountTable() != 0) {
1515c51f12Moriah Waterland			return (1);
1525c51f12Moriah Waterland		}
1535c51f12Moriah Waterland	}
1545c51f12Moriah Waterland
1555c51f12Moriah Waterland	(void) strlcpy(a_path, a_str, sizeof (a_path));
1565c51f12Moriah Waterland	slen = strlen(a_path);
1575c51f12Moriah Waterland
1585c51f12Moriah Waterland	/*
1595c51f12Moriah Waterland	 * This for loop traverses Path backwards, incrementally removing the
1605c51f12Moriah Waterland	 * basename of Path and looking for the resultant directory in the
1615c51f12Moriah Waterland	 * mnttab.  Once found, it returns the rw status of that file system.
1625c51f12Moriah Waterland	 */
1635c51f12Moriah Waterland	for (i = slen; i > 0; i--) {
1645c51f12Moriah Waterland		if ((a_path[i] == '/') || (a_path[i] == '\0')) {
1655c51f12Moriah Waterland			a_path[i] = '\0';
1665c51f12Moriah Waterland			result = findPathRWStatus(a_path);
1675c51f12Moriah Waterland			if (result != -1) {
1685c51f12Moriah Waterland				return (result);
1695c51f12Moriah Waterland			}
1705c51f12Moriah Waterland		}
1715c51f12Moriah Waterland	}
1725c51f12Moriah Waterland
1735c51f12Moriah Waterland	return (1);
1745c51f12Moriah Waterland}
1755c51f12Moriah Waterland
1765c51f12Moriah Waterland/*
1775c51f12Moriah Waterland * Name		: z_destroyMountTable
1785c51f12Moriah Waterland * Description	: Clear the entries in the mount table
1795c51f12Moriah Waterland * Arguments	: void
1805c51f12Moriah Waterland * Returns	: void
1815c51f12Moriah Waterland */
1825c51f12Moriah Waterlandvoid
1835c51f12Moriah Waterlandz_destroyMountTable(void)
1845c51f12Moriah Waterland{
1855c51f12Moriah Waterland	int i;
1865c51f12Moriah Waterland
1875c51f12Moriah Waterland	if (!createdFlag) {
1885c51f12Moriah Waterland		return;
1895c51f12Moriah Waterland	}
1905c51f12Moriah Waterland
1915c51f12Moriah Waterland	if (mountTable == NULL) {
1925c51f12Moriah Waterland		return;
1935c51f12Moriah Waterland	}
1945c51f12Moriah Waterland
1955c51f12Moriah Waterland	for (i = 0; i < mountTableSize; i++) {
1965c51f12Moriah Waterland		free(mountTable[i].mnt_mountp);
1975c51f12Moriah Waterland		free(mountTable[i].mnt_fstype);
1985c51f12Moriah Waterland		free(mountTable[i].mnt_special);
1995c51f12Moriah Waterland		free(mountTable[i].mnt_mntopts);
2005c51f12Moriah Waterland		assert(mountTable[i].mnt_time == NULL);
2015c51f12Moriah Waterland	}
2025c51f12Moriah Waterland
2035c51f12Moriah Waterland	free(mountTable);
2045c51f12Moriah Waterland	mountTable = NULL;
2055c51f12Moriah Waterland	mountTableSize = 0;
2065c51f12Moriah Waterland	createdFlag = B_FALSE;
2075c51f12Moriah Waterland}
2085c51f12Moriah Waterland
2095c51f12Moriah Waterland/*
2105c51f12Moriah Waterland * Name		: z_resolve_lofs
2115c51f12Moriah Waterland * Description	: Loop over potential loopback mounts and symlinks in a
2125c51f12Moriah Waterland *		  given path and resolve them all down to an absolute path.
2135c51f12Moriah Waterland * Arguments	: char * - path to resolve.  path is in writable storage.
2145c51f12Moriah Waterland *		  size_t - length of path storage.
2155c51f12Moriah Waterland * Returns	: void
2165c51f12Moriah Waterland */
2175c51f12Moriah Waterlandvoid
2185c51f12Moriah Waterlandz_resolve_lofs(char *path, size_t pathlen)
2195c51f12Moriah Waterland{
2205c51f12Moriah Waterland	int len, arlen, i;
2215c51f12Moriah Waterland	const char *altroot;
2225c51f12Moriah Waterland	char tmppath[MAXPATHLEN];
2235c51f12Moriah Waterland	boolean_t outside_altroot;
2245c51f12Moriah Waterland
2255c51f12Moriah Waterland	if ((len = resolvepath(path, tmppath, sizeof (tmppath))) == -1)
2265c51f12Moriah Waterland		return;
2275c51f12Moriah Waterland
2285c51f12Moriah Waterland	tmppath[len] = '\0';
2295c51f12Moriah Waterland	(void) strlcpy(path, tmppath, pathlen);
2305c51f12Moriah Waterland
2315c51f12Moriah Waterland	if (z_createMountTable() == -1)
2325c51f12Moriah Waterland		return;
2335c51f12Moriah Waterland
2345c51f12Moriah Waterland	altroot = zonecfg_get_root();
2355c51f12Moriah Waterland	arlen = strlen(altroot);
2365c51f12Moriah Waterland	outside_altroot = B_FALSE;
2375c51f12Moriah Waterland	for (;;) {
2385c51f12Moriah Waterland		struct mnttab *mnp;
2395c51f12Moriah Waterland
2405c51f12Moriah Waterland		/* Search in reverse order to find longest match */
2415c51f12Moriah Waterland		for (i = mountTableSize; i > 0; i--) {
2425c51f12Moriah Waterland			mnp = &mountTable[i - 1];
2435c51f12Moriah Waterland			if (mnp->mnt_fstype == NULL ||
2445c51f12Moriah Waterland			    mnp->mnt_mountp == NULL ||
2455c51f12Moriah Waterland			    mnp->mnt_special == NULL)
2465c51f12Moriah Waterland				continue;
2475c51f12Moriah Waterland			len = strlen(mnp->mnt_mountp);
2485c51f12Moriah Waterland			if (strncmp(mnp->mnt_mountp, path, len) == 0 &&
2495c51f12Moriah Waterland			    (path[len] == '/' || path[len] == '\0'))
2505c51f12Moriah Waterland				break;
2515c51f12Moriah Waterland		}
2525c51f12Moriah Waterland		if (i <= 0)
2535c51f12Moriah Waterland			break;
2545c51f12Moriah Waterland
2555c51f12Moriah Waterland		/* If it's not a lofs then we're done */
2565c51f12Moriah Waterland		if (strcmp(mnp->mnt_fstype, MNTTYPE_LOFS) != 0)
2575c51f12Moriah Waterland			break;
2585c51f12Moriah Waterland
2595c51f12Moriah Waterland		if (outside_altroot) {
2605c51f12Moriah Waterland			char *cp;
2615c51f12Moriah Waterland			int olen = sizeof (MNTOPT_RO) - 1;
2625c51f12Moriah Waterland
2635c51f12Moriah Waterland			/*
2645c51f12Moriah Waterland			 * If we run into a read-only mount outside of the
2655c51f12Moriah Waterland			 * alternate root environment, then the user doesn't
2665c51f12Moriah Waterland			 * want this path to be made read-write.
2675c51f12Moriah Waterland			 */
2685c51f12Moriah Waterland			if (mnp->mnt_mntopts != NULL &&
2695c51f12Moriah Waterland			    (cp = strstr(mnp->mnt_mntopts, MNTOPT_RO)) !=
2705c51f12Moriah Waterland			    NULL &&
2715c51f12Moriah Waterland			    (cp == mnp->mnt_mntopts || cp[-1] == ',') &&
2725c51f12Moriah Waterland			    (cp[olen] == '\0' || cp[olen] == ',')) {
2735c51f12Moriah Waterland				break;
2745c51f12Moriah Waterland			}
2755c51f12Moriah Waterland		} else if (arlen > 0 &&
2765c51f12Moriah Waterland		    (strncmp(mnp->mnt_special, altroot, arlen) != 0 ||
2775c51f12Moriah Waterland		    (mnp->mnt_special[arlen] != '\0' &&
2785c51f12Moriah Waterland		    mnp->mnt_special[arlen] != '/'))) {
2795c51f12Moriah Waterland			outside_altroot = B_TRUE;
2805c51f12Moriah Waterland		}
2815c51f12Moriah Waterland		/* use temporary buffer because new path might be longer */
2825c51f12Moriah Waterland		(void) snprintf(tmppath, sizeof (tmppath), "%s%s",
2835c51f12Moriah Waterland		    mnp->mnt_special, path + len);
2845c51f12Moriah Waterland		if ((len = resolvepath(tmppath, path, pathlen)) == -1)
2855c51f12Moriah Waterland			break;
2865c51f12Moriah Waterland		path[len] = '\0';
2875c51f12Moriah Waterland	}
2885c51f12Moriah Waterland}