xref: /titanic_41/usr/src/cmd/svr4pkg/libinst/mntinfo.c (revision 44da9c13b9429d13843a807d44fdc018aa9a407c)
15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
225c51f124SMoriah Waterland /*
2362224350SCasper H.S. Dik  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245c51f124SMoriah Waterland  * Use is subject to license terms.
255c51f124SMoriah Waterland  */
265c51f124SMoriah Waterland 
275c51f124SMoriah Waterland 
285c51f124SMoriah Waterland /*
295c51f124SMoriah Waterland  * System includes
305c51f124SMoriah Waterland  */
315c51f124SMoriah Waterland 
325c51f124SMoriah Waterland #include <stdio.h>
335c51f124SMoriah Waterland #include <limits.h>
345c51f124SMoriah Waterland #include <errno.h>
355c51f124SMoriah Waterland #include <stdlib.h>
365c51f124SMoriah Waterland #include <unistd.h>
37af122237SJan Kryl #include <libgen.h>
385c51f124SMoriah Waterland #include <string.h>
395c51f124SMoriah Waterland #include <wait.h>
405c51f124SMoriah Waterland #include <signal.h>
415c51f124SMoriah Waterland #include <malloc.h>
425c51f124SMoriah Waterland #include <sys/types.h>
435c51f124SMoriah Waterland #include <sys/mount.h>
445c51f124SMoriah Waterland #include <sys/stat.h>
455c51f124SMoriah Waterland #include <fcntl.h>
465c51f124SMoriah Waterland #include <sys/systeminfo.h>
475c51f124SMoriah Waterland #include <pkgstrct.h>
485c51f124SMoriah Waterland #include <pkginfo.h>
495c51f124SMoriah Waterland #include <locale.h>
505c51f124SMoriah Waterland #include <libintl.h>
515c51f124SMoriah Waterland 
525c51f124SMoriah Waterland #include <sys/mnttab.h>
535c51f124SMoriah Waterland #include <sys/mntent.h>
545c51f124SMoriah Waterland #include <sys/vfstab.h>
555c51f124SMoriah Waterland 
565c51f124SMoriah Waterland /*
575c51f124SMoriah Waterland  * consolidation pkg command library includes
585c51f124SMoriah Waterland  */
595c51f124SMoriah Waterland 
605c51f124SMoriah Waterland #include <pkglib.h>
615c51f124SMoriah Waterland 
625c51f124SMoriah Waterland /*
635c51f124SMoriah Waterland  * local pkg command library includes
645c51f124SMoriah Waterland  */
655c51f124SMoriah Waterland 
665c51f124SMoriah Waterland #include "install.h"
675c51f124SMoriah Waterland #include "libinst.h"
685c51f124SMoriah Waterland #include "libadm.h"
695c51f124SMoriah Waterland #include "messages.h"
705c51f124SMoriah Waterland 
715c51f124SMoriah Waterland extern char **environ;
725c51f124SMoriah Waterland 
735c51f124SMoriah Waterland static int match_mount;		/* This holds the mount of interest. */
745c51f124SMoriah Waterland 
755c51f124SMoriah Waterland int	fs_tab_used  = 0;
765c51f124SMoriah Waterland int	fs_tab_alloc = 0;
775c51f124SMoriah Waterland static int	fs_list = -1;
785c51f124SMoriah Waterland 
795c51f124SMoriah Waterland struct	fstable	**fs_tab = NULL;
805c51f124SMoriah Waterland 
815c51f124SMoriah Waterland #define	PKGDBROOT	"/var/sadm"
825c51f124SMoriah Waterland #define	MOUNT		"/sbin/mount"
835c51f124SMoriah Waterland #define	UMOUNT		"/sbin/umount"
845c51f124SMoriah Waterland 
855c51f124SMoriah Waterland #define	setmntent	fopen
865c51f124SMoriah Waterland #define	endmntent	fclose
875c51f124SMoriah Waterland #define	MOUNT_TABLE	MNTTAB
885c51f124SMoriah Waterland 
895c51f124SMoriah Waterland /* returned by already_mounted() */
905c51f124SMoriah Waterland #define	MNT_NOT		0
915c51f124SMoriah Waterland #define	MNT_EXACT	1
925c51f124SMoriah Waterland #define	MNT_AVAIL	2
935c51f124SMoriah Waterland 
945c51f124SMoriah Waterland /* used with is_remote_src() */
955c51f124SMoriah Waterland #define	NOT_REMOTE	0
965c51f124SMoriah Waterland #define	REAL_REMOTE	1
975c51f124SMoriah Waterland #define	SELF_SERVE	2
985c51f124SMoriah Waterland 
995c51f124SMoriah Waterland /*
1005c51f124SMoriah Waterland  * Due to /etc/mnttab files containing entries for multiple nfs hosts
1015c51f124SMoriah Waterland  * HOST_NM_LN needs to be accommodating. The recommended value in the sysinfo
1025c51f124SMoriah Waterland  * man page of 257 needs to be expanded. See bugid 4076513.
1035c51f124SMoriah Waterland  * 1024 chars is defined in the mnttab.h header as the max size of an entry.
1045c51f124SMoriah Waterland  */
1055c51f124SMoriah Waterland 
1065c51f124SMoriah Waterland #define	HOST_NM_LN	MNT_LINE_MAX
1075c51f124SMoriah Waterland 
1085c51f124SMoriah Waterland /* These cachefs definitions should be in mntent.h. Maybe some day. */
1095c51f124SMoriah Waterland #define	MNTTYPE_CFS		"cachefs"
1105c51f124SMoriah Waterland #define	MNTOPT_BACKFSTYPE	"backfstype"
1115c51f124SMoriah Waterland #define	MNTTYPE_AUTO		"autofs"
1125c51f124SMoriah Waterland 
1135c51f124SMoriah Waterland /*
1145c51f124SMoriah Waterland  * Utilities for getting filesystem information from the mount table.
1155c51f124SMoriah Waterland  *
1165c51f124SMoriah Waterland  * Note: vanilla SVr4 code (pkginstall/dockspace.c) used the output from
1175c51f124SMoriah Waterland  * popen() on the "/etc/mount" command.  However, we need to get more
1185c51f124SMoriah Waterland  * information about mounted filesystems, so we use the C interfaces to
1195c51f124SMoriah Waterland  * the mount table, which also happens to be much faster than running
1205c51f124SMoriah Waterland  * another process.  Since several of the pkg commands need access to the
1215c51f124SMoriah Waterland  * the code has been placed here, to be included in the libinst library.
1225c51f124SMoriah Waterland  */
1235c51f124SMoriah Waterland 
1245c51f124SMoriah Waterland #define	ALLOC_CHUNK	30
1255c51f124SMoriah Waterland 
1265c51f124SMoriah Waterland /*
1275c51f124SMoriah Waterland  * fs_tab_ent_comp -	compare fstable entries first by length in reverse
1285c51f124SMoriah Waterland  *			order, then alphabetically.
1295c51f124SMoriah Waterland  */
1305c51f124SMoriah Waterland static int
fs_tab_ent_comp(const void * e1,const void * e2)1315c51f124SMoriah Waterland fs_tab_ent_comp(const void *e1, const void *e2)
1325c51f124SMoriah Waterland {
1335c51f124SMoriah Waterland 	struct fstable	*fs1 = *((struct fstable **)e1);
1345c51f124SMoriah Waterland 	struct fstable	*fs2 = *((struct fstable **)e2);
1355c51f124SMoriah Waterland 
1365c51f124SMoriah Waterland 	if (fs1->namlen == fs2->namlen)
1375c51f124SMoriah Waterland 		return (strcmp(fs1->name, fs2->name));
1385c51f124SMoriah Waterland 	else
1395c51f124SMoriah Waterland 		return (fs2->namlen - fs1->namlen);
1405c51f124SMoriah Waterland }
1415c51f124SMoriah Waterland 
1425c51f124SMoriah Waterland /*
1435c51f124SMoriah Waterland  * This determines if the source of the mount is from another host. If it's
1445c51f124SMoriah Waterland  * from this host, then it might be writable. This returns NOT_REMOTE if it's
1455c51f124SMoriah Waterland  * pure local, REAL_REMOTE if it's being served from another host and
1465c51f124SMoriah Waterland  * SELF_SERVE if it's being served by the current host.
1475c51f124SMoriah Waterland  */
1485c51f124SMoriah Waterland static int
is_remote_src(char * source)1495c51f124SMoriah Waterland is_remote_src(char *source)
1505c51f124SMoriah Waterland {
1515c51f124SMoriah Waterland 	static char host_name[HOST_NM_LN];
1525c51f124SMoriah Waterland 	char source_host[HOST_NM_LN], *src_ptr, *src_host_ptr;
1535c51f124SMoriah Waterland 	static int hn_len;
1545c51f124SMoriah Waterland 
1555c51f124SMoriah Waterland 	if (hn_len == 0) {
1565c51f124SMoriah Waterland 		/* Find out what host this is. */
1575c51f124SMoriah Waterland 		(void) sysinfo(SI_HOSTNAME, host_name, HOST_NM_LN);
1585c51f124SMoriah Waterland 		hn_len = strlen(host_name);
1595c51f124SMoriah Waterland 	}
1605c51f124SMoriah Waterland 
1615c51f124SMoriah Waterland 	if (source[0] == '/')
1625c51f124SMoriah Waterland 		return (NOT_REMOTE);	/* No server name, so it's local. */
1635c51f124SMoriah Waterland 
1645c51f124SMoriah Waterland 	if (strchr(source, ':') == NULL)
1655c51f124SMoriah Waterland 		return (NOT_REMOTE);	/* it's a floppy disk or something */
1665c51f124SMoriah Waterland 
1675c51f124SMoriah Waterland 	src_ptr = source;
1685c51f124SMoriah Waterland 	src_host_ptr = source_host;
1695c51f124SMoriah Waterland 
1705c51f124SMoriah Waterland 	/* Scan to the end of the hostname (find the ":"). */
1715c51f124SMoriah Waterland 	while (*src_ptr != ':')
1725c51f124SMoriah Waterland 		*src_host_ptr++ = *src_ptr++;
1735c51f124SMoriah Waterland 	*src_host_ptr = '\0';
1745c51f124SMoriah Waterland 
17562224350SCasper H.S. Dik 	/* Multiple hosts: failover with multiple servers; this is remote. */
17662224350SCasper H.S. Dik 	if (strchr(source_host, ',') != NULL)
17762224350SCasper H.S. Dik 		return (REAL_REMOTE);
17862224350SCasper H.S. Dik 
1795c51f124SMoriah Waterland 	if (strncmp(source, host_name, hn_len) == 0 &&
1805c51f124SMoriah Waterland 	    *(source+hn_len) == ':' || is_local_host(source_host))
1815c51f124SMoriah Waterland 		return (SELF_SERVE);	/* Exporting from itself, it's local. */
1825c51f124SMoriah Waterland 
1835c51f124SMoriah Waterland 	return (REAL_REMOTE);
1845c51f124SMoriah Waterland }
1855c51f124SMoriah Waterland 
1865c51f124SMoriah Waterland /*
1875c51f124SMoriah Waterland  * This determines if an apparently writeable filesystem is really writeable
1885c51f124SMoriah Waterland  * or if it's been shared over the network with root-restrictive options.
1895c51f124SMoriah Waterland  */
1905c51f124SMoriah Waterland static int
really_write(char * mountpt)1915c51f124SMoriah Waterland really_write(char *mountpt)
1925c51f124SMoriah Waterland {
1935c51f124SMoriah Waterland 	char testfile[PATH_MAX];
1945c51f124SMoriah Waterland 	int fd, retval = 0;
1955c51f124SMoriah Waterland 	struct stat status;
1965c51f124SMoriah Waterland 
1975c51f124SMoriah Waterland 	(void) snprintf(testfile, sizeof (testfile), "%s/testXXXXXX", mountpt);
1985c51f124SMoriah Waterland 
1995c51f124SMoriah Waterland 	if (mktemp(testfile) == NULL)
2005c51f124SMoriah Waterland 		return (0);	/* may as well be read-only */
2015c51f124SMoriah Waterland 	/* LINTED do not use creat(); use open(path,... */
2025c51f124SMoriah Waterland 	else if ((fd = creat(testfile, 0777)) == -1)
2035c51f124SMoriah Waterland 		return (0);	/* can't write */
2045c51f124SMoriah Waterland 	else if (fstat(fd, &status) == -1)
2055c51f124SMoriah Waterland 		retval = 0;	/* may as well be read-only */
2065c51f124SMoriah Waterland 	else if (status.st_uid != 0)
2075c51f124SMoriah Waterland 		retval = 0;	/* too many restrictions */
2085c51f124SMoriah Waterland 	else
2095c51f124SMoriah Waterland 		retval = 1;
2105c51f124SMoriah Waterland 
2115c51f124SMoriah Waterland 	(void) close(fd);
2125c51f124SMoriah Waterland 	(void) unlink(testfile);
2135c51f124SMoriah Waterland 
2145c51f124SMoriah Waterland 	return (retval);
2155c51f124SMoriah Waterland }
2165c51f124SMoriah Waterland 
2175c51f124SMoriah Waterland /* This returns the hostname portion of a remote path. */
2185c51f124SMoriah Waterland char *
get_server_host(uint32_t n)219*44da9c13SSimon Klinkert get_server_host(uint32_t n)
2205c51f124SMoriah Waterland {
2215c51f124SMoriah Waterland 	static char hostname[HOST_NM_LN], *host_end;
2225c51f124SMoriah Waterland 
2235c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
2245c51f124SMoriah Waterland 		return ("unknown source");
2255c51f124SMoriah Waterland 	}
2265c51f124SMoriah Waterland 
227*44da9c13SSimon Klinkert 	if (n < fs_tab_used) {
2285c51f124SMoriah Waterland 		(void) strcpy(hostname, fs_tab[n]->remote_name);
2295c51f124SMoriah Waterland 		if ((host_end = strchr(hostname, ':')) == NULL) {
2305c51f124SMoriah Waterland 			if ((strcmp(fs_tab[n]->fstype, MNTTYPE_AUTO)) == NULL)
2315c51f124SMoriah Waterland 				return ("automounter");
2325c51f124SMoriah Waterland 			else
2335c51f124SMoriah Waterland 				return (fs_tab[n]->fstype);
2345c51f124SMoriah Waterland 		} else {
2355c51f124SMoriah Waterland 			*host_end = '\0';
2365c51f124SMoriah Waterland 			return (hostname);
2375c51f124SMoriah Waterland 		}
2385c51f124SMoriah Waterland 	}
2395c51f124SMoriah Waterland 
2405c51f124SMoriah Waterland 	return ("unknown source");
2415c51f124SMoriah Waterland }
2425c51f124SMoriah Waterland 
2435c51f124SMoriah Waterland /*
2445c51f124SMoriah Waterland  * This pulls the path out of a hostpath which may be of the form host:path
2455c51f124SMoriah Waterland  * where path is an absolute path. NOTE: If path turns out to be relative,
2465c51f124SMoriah Waterland  * this returns NULL.
2475c51f124SMoriah Waterland  */
2485c51f124SMoriah Waterland static char *
path_part(char * hostpath)2495c51f124SMoriah Waterland path_part(char *hostpath)
2505c51f124SMoriah Waterland {
2515c51f124SMoriah Waterland 	char *host_end;
2525c51f124SMoriah Waterland 
2535c51f124SMoriah Waterland 	if ((host_end = strchr(hostpath, ':')) == NULL && hostpath[0] == '/')
2545c51f124SMoriah Waterland 		return (hostpath);	/* It's already legit. */
2555c51f124SMoriah Waterland 
2565c51f124SMoriah Waterland 	if (*(host_end+1) == '/')
2575c51f124SMoriah Waterland 		return (host_end+1);	/* Here's the path part. */
2585c51f124SMoriah Waterland 
2595c51f124SMoriah Waterland 	return (NULL);
2605c51f124SMoriah Waterland }
2615c51f124SMoriah Waterland 
2625c51f124SMoriah Waterland /*
2635c51f124SMoriah Waterland  * This scans the filesystems already mounted to see if this remote mount is
2645c51f124SMoriah Waterland  * already in place on the server. This scans the fs_tab for a remote_name
2655c51f124SMoriah Waterland  * exactly matching the client's. It stores the current entry number
2665c51f124SMoriah Waterland  * corresponding to this mount in the static match_mount.
2675c51f124SMoriah Waterland  *
2685c51f124SMoriah Waterland  * Returns:
2695c51f124SMoriah Waterland  *	MNT_NOT		Couldn't find it.
2705c51f124SMoriah Waterland  *	MNT_EXACT	This has actually been manually mounted for us
2715c51f124SMoriah Waterland  *	MNT_AVAIL	This is mounted for the server, but needs to be
2725c51f124SMoriah Waterland  *			loopback mounted from the client's perspective.
2735c51f124SMoriah Waterland  */
2745c51f124SMoriah Waterland static int
already_mounted(struct vfstab * vfs,int is_local_host,char * client_path,char * host_path)2755c51f124SMoriah Waterland already_mounted(struct vfstab *vfs, int is_local_host, char *client_path,
2765c51f124SMoriah Waterland     char *host_path)
2775c51f124SMoriah Waterland {
2785c51f124SMoriah Waterland 	int i;
2795c51f124SMoriah Waterland 
2805c51f124SMoriah Waterland 	match_mount = -1;
2815c51f124SMoriah Waterland 
2825c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
2835c51f124SMoriah Waterland 		return (MNT_NOT);
2845c51f124SMoriah Waterland 	}
2855c51f124SMoriah Waterland 
2865c51f124SMoriah Waterland 	for (i = 0; i < fs_tab_used; i++) {
2875c51f124SMoriah Waterland 		/*
2885c51f124SMoriah Waterland 		 * Determine if this has been manually mounted exactly as we
2895c51f124SMoriah Waterland 		 * require. Begin by finding a mount on our current
2905c51f124SMoriah Waterland 		 * mountpoint.
2915c51f124SMoriah Waterland 		 */
2925c51f124SMoriah Waterland 		if (strcmp(fs_tab[i]->name, client_path) == 0) {
2935c51f124SMoriah Waterland 			/*
2945c51f124SMoriah Waterland 			 * Now see if it is really the same mount. This isn't
2955c51f124SMoriah Waterland 			 * smart enough to find mounts on top of mounts, but
2965c51f124SMoriah Waterland 			 * assuming there is no conspiracy to fool this
2975c51f124SMoriah Waterland 			 * function, it will be good enough.
2985c51f124SMoriah Waterland 			 */
2995c51f124SMoriah Waterland 			if (is_local_host &&
3005c51f124SMoriah Waterland 			    strcmp(fs_tab[i]->remote_name, host_path) == 0) {
3015c51f124SMoriah Waterland 				match_mount = i;
3025c51f124SMoriah Waterland 				return (MNT_EXACT);
3035c51f124SMoriah Waterland 			}
3045c51f124SMoriah Waterland 		}
3055c51f124SMoriah Waterland 
3065c51f124SMoriah Waterland 		/* Determine if this mount is available to the server. */
3075c51f124SMoriah Waterland 		if (strcmp(fs_tab[i]->remote_name, vfs->vfs_special) == 0) {
3085c51f124SMoriah Waterland 			match_mount = i;
3095c51f124SMoriah Waterland 			return (MNT_AVAIL);
3105c51f124SMoriah Waterland 		}
3115c51f124SMoriah Waterland 	}
3125c51f124SMoriah Waterland 	return (MNT_NOT);
3135c51f124SMoriah Waterland }
3145c51f124SMoriah Waterland 
3155c51f124SMoriah Waterland /*
3165c51f124SMoriah Waterland  * This function unmounts all of the loopback mounts created for the client.
3175c51f124SMoriah Waterland  * If no client stuff is mounted, this is completely benign, it finds that
3185c51f124SMoriah Waterland  * nothing is mounted up and returns. It returns "1" for unmounted everything
3195c51f124SMoriah Waterland  * OK and "0" for failure.
3205c51f124SMoriah Waterland  */
3215c51f124SMoriah Waterland int
unmount_client()3225c51f124SMoriah Waterland unmount_client()
3235c51f124SMoriah Waterland {
3245c51f124SMoriah Waterland 	int	errcode;
3255c51f124SMoriah Waterland 	int	exit_no;
3265c51f124SMoriah Waterland 	int	n;
3275c51f124SMoriah Waterland 	int	retcode = 1;
3285c51f124SMoriah Waterland 	int	status;
3295c51f124SMoriah Waterland 	pid_t	pid;
3305c51f124SMoriah Waterland 	pid_t	pid_return;
3315c51f124SMoriah Waterland 
3325c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
3335c51f124SMoriah Waterland 		return (1);
3345c51f124SMoriah Waterland 	}
3355c51f124SMoriah Waterland 
3365c51f124SMoriah Waterland 	for (n = 0; n < fs_tab_used-1; n++) {
3375c51f124SMoriah Waterland 		/* If the filesystem is mounted and this utility did it ... */
3385c51f124SMoriah Waterland 		if (fs_tab[n]->cl_mounted && fs_tab[n]->srvr_map) {
3395c51f124SMoriah Waterland 			char	*arg[3];
3405c51f124SMoriah Waterland 
3415c51f124SMoriah Waterland 			/* create arglist for umount command */
3425c51f124SMoriah Waterland 
3435c51f124SMoriah Waterland 			arg[0] = UMOUNT;
3445c51f124SMoriah Waterland 			arg[1] = fs_tab[n]->name;
3455c51f124SMoriah Waterland 			arg[2] = (char *)NULL;
3465c51f124SMoriah Waterland 
3475c51f124SMoriah Waterland 			/* flush standard i/o before creating new process */
3485c51f124SMoriah Waterland 
3495c51f124SMoriah Waterland 			(void) fflush(stderr);
3505c51f124SMoriah Waterland 			(void) fflush(stdout);
3515c51f124SMoriah Waterland 
3525c51f124SMoriah Waterland 			/*
3535c51f124SMoriah Waterland 			 * create new process to execute command in;
3545c51f124SMoriah Waterland 			 * vfork is being used to avoid duplicating the parents
3555c51f124SMoriah Waterland 			 * memory space - this means that the child process may
3565c51f124SMoriah Waterland 			 * not modify any of the parents memory including the
3575c51f124SMoriah Waterland 			 * standard i/o descriptors - all the child can do is
3585c51f124SMoriah Waterland 			 * adjust interrupts and open files as a prelude to a
3595c51f124SMoriah Waterland 			 * call to exec().
3605c51f124SMoriah Waterland 			 */
3615c51f124SMoriah Waterland 
3625c51f124SMoriah Waterland 			pid = vfork();
3635c51f124SMoriah Waterland 			if (pid < 0) {
3645c51f124SMoriah Waterland 				/* fork failed! */
3655c51f124SMoriah Waterland 
3665c51f124SMoriah Waterland 				logerr(WRN_BAD_FORK, errno, strerror(errno));
3675c51f124SMoriah Waterland 				retcode = 0;
3685c51f124SMoriah Waterland 			} else if (pid > 0) {
3695c51f124SMoriah Waterland 				/*
3705c51f124SMoriah Waterland 				 * this is the parent process
3715c51f124SMoriah Waterland 				 */
3725c51f124SMoriah Waterland 
3735c51f124SMoriah Waterland 				status = 0;
3745c51f124SMoriah Waterland 				pid_return = waitpid(pid, &status, 0);
3755c51f124SMoriah Waterland 
3765c51f124SMoriah Waterland 				if (pid_return != pid) {
3775c51f124SMoriah Waterland 					logerr(WRN_BAD_WAIT, pid, pid_return,
3785c51f124SMoriah Waterland 					    (unsigned long)status, errno,
3795c51f124SMoriah Waterland 					    strerror(errno));
3805c51f124SMoriah Waterland 					retcode = 0;
3815c51f124SMoriah Waterland 				}
3825c51f124SMoriah Waterland 
3835c51f124SMoriah Waterland 				/*
3845c51f124SMoriah Waterland 				 * If the child was stopped or killed by a
3855c51f124SMoriah Waterland 				 * signal or exied with any code but 0, we
3865c51f124SMoriah Waterland 				 * assume the mount has failed.
3875c51f124SMoriah Waterland 				 */
3885c51f124SMoriah Waterland 
3895c51f124SMoriah Waterland 				if (!WIFEXITED(status) ||
3905c51f124SMoriah Waterland 				    (errcode = WEXITSTATUS(status))) {
3915c51f124SMoriah Waterland 					retcode = 0;
3925c51f124SMoriah Waterland 					logerr(WRN_FSTAB_UMOUNT,
3935c51f124SMoriah Waterland 					    fs_tab[n]->name, errcode);
3945c51f124SMoriah Waterland 				} else {
3955c51f124SMoriah Waterland 					fs_tab[n]->cl_mounted = 0;
3965c51f124SMoriah Waterland 				}
3975c51f124SMoriah Waterland 			} else {
3985c51f124SMoriah Waterland 				/*
3995c51f124SMoriah Waterland 				 * this is the child process
4005c51f124SMoriah Waterland 				 */
4015c51f124SMoriah Waterland 
4025c51f124SMoriah Waterland 				int	i;
4035c51f124SMoriah Waterland 
4045c51f124SMoriah Waterland 				/* reset any signals to default */
4055c51f124SMoriah Waterland 
4065c51f124SMoriah Waterland 				for (i = 0; i < NSIG; i++) {
4075c51f124SMoriah Waterland 					(void) sigset(i, SIG_DFL);
4085c51f124SMoriah Waterland 				}
4095c51f124SMoriah Waterland 
4105c51f124SMoriah Waterland 				/*
4115c51f124SMoriah Waterland 				 * Redirect output to /dev/null because the
4125c51f124SMoriah Waterland 				 * umount error message may be confusing to
4135c51f124SMoriah Waterland 				 * the user.
4145c51f124SMoriah Waterland 				 */
4155c51f124SMoriah Waterland 
4165c51f124SMoriah Waterland 				i = open("/dev/null", O_WRONLY);
4175c51f124SMoriah Waterland 				if (i >= 0) {
4185c51f124SMoriah Waterland 					dup2(2, STDERR_FILENO);
4195c51f124SMoriah Waterland 				}
4205c51f124SMoriah Waterland 
4215c51f124SMoriah Waterland 				/* close all file descriptors except stdio */
4225c51f124SMoriah Waterland 
4235c51f124SMoriah Waterland 				closefrom(3);
4245c51f124SMoriah Waterland 
4255c51f124SMoriah Waterland 				exit_no = execve(arg[0], arg, environ);
4265c51f124SMoriah Waterland 				_exit(exit_no);
4275c51f124SMoriah Waterland 			}
4285c51f124SMoriah Waterland 		}
4295c51f124SMoriah Waterland 	}
4305c51f124SMoriah Waterland 
4315c51f124SMoriah Waterland 	return (retcode);
4325c51f124SMoriah Waterland }
4335c51f124SMoriah Waterland 
4345c51f124SMoriah Waterland /*
4355c51f124SMoriah Waterland  * This function creates the necessary loopback mounts to emulate the client
4365c51f124SMoriah Waterland  * configuration with respect to the server. If this is being run on a
4375c51f124SMoriah Waterland  * standalone or the installation is actually to the local system, this call
4385c51f124SMoriah Waterland  * is benign since srvr_map won't be set anywhere. It returns "1" for mounted
4395c51f124SMoriah Waterland  * everything OK and "0" for failure.
4405c51f124SMoriah Waterland  */
4415c51f124SMoriah Waterland int
mount_client()4425c51f124SMoriah Waterland mount_client()
4435c51f124SMoriah Waterland {
4445c51f124SMoriah Waterland 	int	errcode;
4455c51f124SMoriah Waterland 	int	exit_no;
4465c51f124SMoriah Waterland 	int	n;
4475c51f124SMoriah Waterland 	int	retcode = 1;
4485c51f124SMoriah Waterland 	int	status;
4495c51f124SMoriah Waterland 	pid_t	pid;
4505c51f124SMoriah Waterland 	pid_t	pid_return;
4515c51f124SMoriah Waterland 
4525c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
4535c51f124SMoriah Waterland 		return (1);
4545c51f124SMoriah Waterland 	}
4555c51f124SMoriah Waterland 
4565c51f124SMoriah Waterland 	for (n = fs_tab_used-1; n >= 0; n--) {
4575c51f124SMoriah Waterland 		/*
4585c51f124SMoriah Waterland 		 * If the filesystem is mounted (meaning available) and the
4595c51f124SMoriah Waterland 		 * apparent filesystem can be mapped to a local filesystem
4605c51f124SMoriah Waterland 		 * AND the local filesystem is not the same as the target
4615c51f124SMoriah Waterland 		 * filesystem, mount it.
4625c51f124SMoriah Waterland 		 */
4635c51f124SMoriah Waterland 		if (fs_tab[n]->mounted && fs_tab[n]->srvr_map) {
4645c51f124SMoriah Waterland 			char	*arg[6];
4655c51f124SMoriah Waterland 
4665c51f124SMoriah Waterland 			/* create arglist for mount command */
4675c51f124SMoriah Waterland 
4685c51f124SMoriah Waterland 			arg[0] = MOUNT;
4695c51f124SMoriah Waterland 			arg[1] = "-F";
4705c51f124SMoriah Waterland 			arg[2] = "lofs";
4715c51f124SMoriah Waterland 			arg[3] = fs_tab[n]->remote_name;
4725c51f124SMoriah Waterland 			arg[4] = fs_tab[n]->name;
4735c51f124SMoriah Waterland 			arg[5] = (char *)NULL;
4745c51f124SMoriah Waterland 
4755c51f124SMoriah Waterland 			/* flush standard i/o before creating new process */
4765c51f124SMoriah Waterland 
4775c51f124SMoriah Waterland 			(void) fflush(stderr);
4785c51f124SMoriah Waterland 			(void) fflush(stdout);
4795c51f124SMoriah Waterland 
4805c51f124SMoriah Waterland 			/*
4815c51f124SMoriah Waterland 			 * create new process to execute command in;
4825c51f124SMoriah Waterland 			 * vfork is being used to avoid duplicating the parents
4835c51f124SMoriah Waterland 			 * memory space - this means that the child process may
4845c51f124SMoriah Waterland 			 * not modify any of the parents memory including the
4855c51f124SMoriah Waterland 			 * standard i/o descriptors - all the child can do is
4865c51f124SMoriah Waterland 			 * adjust interrupts and open files as a prelude to a
4875c51f124SMoriah Waterland 			 * call to exec().
4885c51f124SMoriah Waterland 			 */
4895c51f124SMoriah Waterland 
4905c51f124SMoriah Waterland 			pid = vfork();
4915c51f124SMoriah Waterland 			if (pid < 0) {
4925c51f124SMoriah Waterland 				/* fork failed! */
4935c51f124SMoriah Waterland 
4945c51f124SMoriah Waterland 				logerr(WRN_BAD_FORK, errno, strerror(errno));
4955c51f124SMoriah Waterland 				retcode = 0;
4965c51f124SMoriah Waterland 			} else if (pid > 0) {
4975c51f124SMoriah Waterland 				/*
4985c51f124SMoriah Waterland 				 * this is the parent process
4995c51f124SMoriah Waterland 				 */
5005c51f124SMoriah Waterland 
5015c51f124SMoriah Waterland 				pid_return = waitpid(pid, &status, 0);
5025c51f124SMoriah Waterland 
5035c51f124SMoriah Waterland 				if (pid_return != pid) {
5045c51f124SMoriah Waterland 					logerr(WRN_BAD_WAIT, pid, pid_return,
5055c51f124SMoriah Waterland 					    (unsigned long)status, errno,
5065c51f124SMoriah Waterland 					    strerror(errno));
5075c51f124SMoriah Waterland 					retcode = 0;
5085c51f124SMoriah Waterland 				}
5095c51f124SMoriah Waterland 
5105c51f124SMoriah Waterland 				/*
5115c51f124SMoriah Waterland 				 * If the child was stopped or killed by a
5125c51f124SMoriah Waterland 				 * signal or exied with any code but 0, we
5135c51f124SMoriah Waterland 				 * assume the mount has failed.
5145c51f124SMoriah Waterland 				 */
5155c51f124SMoriah Waterland 
5165c51f124SMoriah Waterland 				if (!WIFEXITED(status) ||
5175c51f124SMoriah Waterland 				    (errcode = WEXITSTATUS(status))) {
5185c51f124SMoriah Waterland 					retcode = 0;
5195c51f124SMoriah Waterland 					fs_tab[n]->mnt_failed = 1;
5205c51f124SMoriah Waterland 					logerr(WRN_FSTAB_MOUNT,
5215c51f124SMoriah Waterland 					    fs_tab[n]->name, errcode);
5225c51f124SMoriah Waterland 				} else {
5235c51f124SMoriah Waterland 					fs_tab[n]->cl_mounted = 1;
5245c51f124SMoriah Waterland 				}
5255c51f124SMoriah Waterland 			} else {
5265c51f124SMoriah Waterland 				/*
5275c51f124SMoriah Waterland 				 * this is the child process
5285c51f124SMoriah Waterland 				 */
5295c51f124SMoriah Waterland 
5305c51f124SMoriah Waterland 				int	i;
5315c51f124SMoriah Waterland 
5325c51f124SMoriah Waterland 				/* reset all signals to default */
5335c51f124SMoriah Waterland 
5345c51f124SMoriah Waterland 				for (i = 0; i < NSIG; i++) {
5355c51f124SMoriah Waterland 					(void) sigset(i, SIG_DFL);
5365c51f124SMoriah Waterland 				}
5375c51f124SMoriah Waterland 
5385c51f124SMoriah Waterland 				/*
5395c51f124SMoriah Waterland 				 * Redirect output to /dev/null because the
5405c51f124SMoriah Waterland 				 * mount error message may be confusing to
5415c51f124SMoriah Waterland 				 * the user.
5425c51f124SMoriah Waterland 				 */
5435c51f124SMoriah Waterland 
5445c51f124SMoriah Waterland 				i = open("/dev/null", O_WRONLY);
5455c51f124SMoriah Waterland 				if (i >= 0) {
5465c51f124SMoriah Waterland 					dup2(i, STDERR_FILENO);
5475c51f124SMoriah Waterland 				}
5485c51f124SMoriah Waterland 
5495c51f124SMoriah Waterland 				/* close all file descriptors except stdio */
5505c51f124SMoriah Waterland 
5515c51f124SMoriah Waterland 				closefrom(3);
5525c51f124SMoriah Waterland 
5535c51f124SMoriah Waterland 				exit_no = execve(arg[0], arg, environ);
5545c51f124SMoriah Waterland 				_exit(exit_no);
5555c51f124SMoriah Waterland 				/*NOTREACHED*/
5565c51f124SMoriah Waterland 			}
5575c51f124SMoriah Waterland 		}
5585c51f124SMoriah Waterland 	}
5595c51f124SMoriah Waterland 	return (retcode);
5605c51f124SMoriah Waterland }
5615c51f124SMoriah Waterland 
5625c51f124SMoriah Waterland /*
5635c51f124SMoriah Waterland  * This function maps path, on a loopback filesystem, back to the real server
5645c51f124SMoriah Waterland  * filesystem. fsys_value is the fs_tab[] entry to which the loopback'd path is
5655c51f124SMoriah Waterland  * mapped. This returns a pointer to a static area. If the result is needed
5665c51f124SMoriah Waterland  * for further processing, it should be strdup()'d or something.
5675c51f124SMoriah Waterland  */
5685c51f124SMoriah Waterland char *
server_map(char * path,uint32_t fsys_value)569*44da9c13SSimon Klinkert server_map(char *path, uint32_t fsys_value)
5705c51f124SMoriah Waterland {
5715c51f124SMoriah Waterland 	static char server_construction[PATH_MAX];
5725c51f124SMoriah Waterland 
5735c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
5745c51f124SMoriah Waterland 		(void) strcpy(server_construction, path);
575*44da9c13SSimon Klinkert 	} else if (fsys_value < fs_tab_used) {
5765c51f124SMoriah Waterland 		(void) snprintf(server_construction,
5775c51f124SMoriah Waterland 		    sizeof (server_construction),
5785c51f124SMoriah Waterland 		    "%s%s", fs_tab[fsys_value]->remote_name,
5795c51f124SMoriah Waterland 		    path+strlen(fs_tab[fsys_value]->name));
5805c51f124SMoriah Waterland 	} else {
5815c51f124SMoriah Waterland 		(void) strcpy(server_construction, path);
5825c51f124SMoriah Waterland 	}
5835c51f124SMoriah Waterland 
5845c51f124SMoriah Waterland 	return (server_construction);
5855c51f124SMoriah Waterland }
5865c51f124SMoriah Waterland 
5875c51f124SMoriah Waterland /* This function sets up the standard parts of the fs_tab. */
5885c51f124SMoriah Waterland static struct fstable *
fs_tab_init(char * mountp,char * fstype)5895c51f124SMoriah Waterland fs_tab_init(char *mountp, char *fstype)
5905c51f124SMoriah Waterland {
5915c51f124SMoriah Waterland 	struct fstable *nfte;
5925c51f124SMoriah Waterland 
5935c51f124SMoriah Waterland 	/* Create the array if necessary. */
5945c51f124SMoriah Waterland 	if (fs_list == -1) {
5955c51f124SMoriah Waterland 		fs_list = ar_create(ALLOC_CHUNK,
5965c51f124SMoriah Waterland 		    (unsigned)sizeof (struct fstable),
5975c51f124SMoriah Waterland 		    "filesystem mount data");
5985c51f124SMoriah Waterland 		if (fs_list == -1) {
5995c51f124SMoriah Waterland 			progerr(ERR_MALLOC, "fs_list", errno, strerror(errno));
6005c51f124SMoriah Waterland 			return (NULL);
6015c51f124SMoriah Waterland 		}
6025c51f124SMoriah Waterland 	}
6035c51f124SMoriah Waterland 
6045c51f124SMoriah Waterland 	/*
6055c51f124SMoriah Waterland 	 * Allocate an fstable entry for this mnttab entry.
6065c51f124SMoriah Waterland 	 */
6075c51f124SMoriah Waterland 	if ((nfte = *(struct fstable **)ar_next_avail(fs_list))
6085c51f124SMoriah Waterland 	    == NULL) {
6095c51f124SMoriah Waterland 		progerr(ERR_MALLOC, "nfte", errno, strerror(errno));
6105c51f124SMoriah Waterland 		return (NULL);
6115c51f124SMoriah Waterland 	}
6125c51f124SMoriah Waterland 
6135c51f124SMoriah Waterland 	/*
6145c51f124SMoriah Waterland 	 * Point fs_tab at the head of the array again, since it may have
6155c51f124SMoriah Waterland 	 * moved due to realloc in ar_next_avail(). If ar_next_avail() realizes
6165c51f124SMoriah Waterland 	 * that there is no more room to grow the array, it reallocates the
6175c51f124SMoriah Waterland 	 * array. Because we stored pointer to that array in fs_tab, we need
6185c51f124SMoriah Waterland 	 * to make sure that it is updated as well.
6195c51f124SMoriah Waterland 	 */
6205c51f124SMoriah Waterland 	if ((fs_tab = (struct fstable **)ar_get_head(fs_list)) == NULL) {
6215c51f124SMoriah Waterland 		progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno));
6225c51f124SMoriah Waterland 		return (NULL);
6235c51f124SMoriah Waterland 	}
6245c51f124SMoriah Waterland 
6255c51f124SMoriah Waterland 	/*
6265c51f124SMoriah Waterland 	 * Get the length of the 'mount point' name.
6275c51f124SMoriah Waterland 	 */
6285c51f124SMoriah Waterland 	nfte->namlen = strlen(mountp);
6295c51f124SMoriah Waterland 	/*
6305c51f124SMoriah Waterland 	 * Allocate space for the 'mount point' name.
6315c51f124SMoriah Waterland 	 */
6325c51f124SMoriah Waterland 	if ((nfte->name = malloc(nfte->namlen+1)) == NULL) {
6335c51f124SMoriah Waterland 		progerr(ERR_MALLOC, "name", errno, strerror(errno));
6345c51f124SMoriah Waterland 		return (NULL);
6355c51f124SMoriah Waterland 	}
6365c51f124SMoriah Waterland 	(void) strcpy(nfte->name, mountp);
6375c51f124SMoriah Waterland 
6385c51f124SMoriah Waterland 	if ((nfte->fstype = malloc(strlen(fstype)+1)) == NULL) {
6395c51f124SMoriah Waterland 		progerr(ERR_MALLOC, "fstype", errno, strerror(errno));
6405c51f124SMoriah Waterland 		return (NULL);
6415c51f124SMoriah Waterland 	}
6425c51f124SMoriah Waterland 	(void) strcpy(nfte->fstype, fstype);
6435c51f124SMoriah Waterland 
6445c51f124SMoriah Waterland 	fs_tab_used++;
6455c51f124SMoriah Waterland 
6465c51f124SMoriah Waterland 	return (nfte);
6475c51f124SMoriah Waterland }
6485c51f124SMoriah Waterland 
6495c51f124SMoriah Waterland /* This function frees all memory associated with the filesystem table. */
6505c51f124SMoriah Waterland void
fs_tab_free(void)6515c51f124SMoriah Waterland fs_tab_free(void)
6525c51f124SMoriah Waterland {
6535c51f124SMoriah Waterland 	int n;
6545c51f124SMoriah Waterland 
6555c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
6565c51f124SMoriah Waterland 		return;
6575c51f124SMoriah Waterland 	}
6585c51f124SMoriah Waterland 
6595c51f124SMoriah Waterland 	for (n = 0; n < fs_tab_used; n++) {
6605c51f124SMoriah Waterland 		free(fs_tab[n]->fstype);
6615c51f124SMoriah Waterland 		free(fs_tab[n]->name);
6625c51f124SMoriah Waterland 		free(fs_tab[n]->remote_name);
6635c51f124SMoriah Waterland 	}
6645c51f124SMoriah Waterland 
6655c51f124SMoriah Waterland 	ar_free(fs_list);
6665c51f124SMoriah Waterland }
6675c51f124SMoriah Waterland 
6685c51f124SMoriah Waterland /* This function scans a string of mount options for a specific keyword. */
6695c51f124SMoriah Waterland static int
hasopt(char * options,char * keyword)6705c51f124SMoriah Waterland hasopt(char *options, char *keyword)
6715c51f124SMoriah Waterland {
6725c51f124SMoriah Waterland 	char vfs_options[VFS_LINE_MAX], *optptr;
6735c51f124SMoriah Waterland 
6745c51f124SMoriah Waterland 	if (!options) {
6755c51f124SMoriah Waterland 		(void) strcpy(vfs_options, "ro");
6765c51f124SMoriah Waterland 	} else {
6775c51f124SMoriah Waterland 		(void) strcpy(vfs_options, options);
6785c51f124SMoriah Waterland 	}
6795c51f124SMoriah Waterland 
6805c51f124SMoriah Waterland 	while (optptr = strrchr(vfs_options, ',')) {
6815c51f124SMoriah Waterland 		*optptr++ = '\0';
6825c51f124SMoriah Waterland 
6835c51f124SMoriah Waterland 		if (strcmp(optptr, keyword) == 0)
6845c51f124SMoriah Waterland 			return (1);
6855c51f124SMoriah Waterland 	}
6865c51f124SMoriah Waterland 
6875c51f124SMoriah Waterland 	/* Now deal with the remainder. */
6885c51f124SMoriah Waterland 	if (strcmp(vfs_options, keyword) == 0)
6895c51f124SMoriah Waterland 		return (1);
6905c51f124SMoriah Waterland 
6915c51f124SMoriah Waterland 	return (0);
6925c51f124SMoriah Waterland }
6935c51f124SMoriah Waterland 
6945c51f124SMoriah Waterland /*
6955c51f124SMoriah Waterland  * This function constructs a new filesystem table (fs_tab[]) entry based on
6965c51f124SMoriah Waterland  * an /etc/mnttab entry. When it returns, the new entry has been inserted
6975c51f124SMoriah Waterland  * into fs_tab[].
6985c51f124SMoriah Waterland  */
6995c51f124SMoriah Waterland static int
construct_mt(struct mnttab * mt)7005c51f124SMoriah Waterland construct_mt(struct mnttab *mt)
7015c51f124SMoriah Waterland {
7025c51f124SMoriah Waterland 	struct	fstable	*nfte;
7035c51f124SMoriah Waterland 
7045c51f124SMoriah Waterland 	/*
7055c51f124SMoriah Waterland 	 * Initialize fstable structure and make the standard entries.
7065c51f124SMoriah Waterland 	 */
7075c51f124SMoriah Waterland 	if ((nfte = fs_tab_init(mt->mnt_mountp, mt->mnt_fstype)) == NULL)
7085c51f124SMoriah Waterland 		return (1);
7095c51f124SMoriah Waterland 
71062224350SCasper H.S. Dik 	/*
71162224350SCasper H.S. Dik 	 * See if this is served from another host.
71262224350SCasper H.S. Dik 	 * Testing the type is cheap; finding the hostname is not.
71362224350SCasper H.S. Dik 	 * At this point, we're using the REAL mnttab; since we're not
71462224350SCasper H.S. Dik 	 * allowed to mount ourself with "NFS", "NFS" must be remote.
71562224350SCasper H.S. Dik 	 * The automount will translate "nfs:self" to a lofs mount.
71662224350SCasper H.S. Dik 	 */
71762224350SCasper H.S. Dik 	if (strcmp(mt->mnt_fstype, MNTTYPE_AUTO) == 0 ||
71862224350SCasper H.S. Dik 	    strcmp(mt->mnt_fstype, MNTTYPE_NFS) == 0 ||
71962224350SCasper H.S. Dik 	    is_remote_src(mt->mnt_special) == REAL_REMOTE)
7205c51f124SMoriah Waterland 		nfte->remote = 1;
7215c51f124SMoriah Waterland 	else
7225c51f124SMoriah Waterland 		nfte->remote = 0;
7235c51f124SMoriah Waterland 
7245c51f124SMoriah Waterland 	/* It's mounted now (by definition), so we don't have to remap it. */
7255c51f124SMoriah Waterland 	nfte->srvr_map = 0;
7265c51f124SMoriah Waterland 	nfte->mounted = 1;
7275c51f124SMoriah Waterland 
7285c51f124SMoriah Waterland 	nfte->remote_name = strdup(mt->mnt_special);
7295c51f124SMoriah Waterland 
7305c51f124SMoriah Waterland 	/*
7315c51f124SMoriah Waterland 	 * This checks the mount commands which establish the most
7325c51f124SMoriah Waterland 	 * basic level of access. Later further tests may be
7335c51f124SMoriah Waterland 	 * necessary to fully qualify this. We set this bit
7345c51f124SMoriah Waterland 	 * preliminarily because we have access to the mount data
7355c51f124SMoriah Waterland 	 * now.
7365c51f124SMoriah Waterland 	 */
7375c51f124SMoriah Waterland 	nfte->writeable = 0;	/* Assume read-only. */
7385c51f124SMoriah Waterland 	if (hasmntopt(mt, MNTOPT_RO) == NULL) {
7395c51f124SMoriah Waterland 		nfte->writeable = 1;
7405c51f124SMoriah Waterland 		if (!(nfte->remote))
7415c51f124SMoriah Waterland 			/*
7425c51f124SMoriah Waterland 			 * There's no network involved, so this
7435c51f124SMoriah Waterland 			 * assessment is confirmed.
7445c51f124SMoriah Waterland 			 */
7455c51f124SMoriah Waterland 			nfte->write_tested = 1;
7465c51f124SMoriah Waterland 	} else
7475c51f124SMoriah Waterland 		/* read-only is read-only */
7485c51f124SMoriah Waterland 		nfte->write_tested = 1;
7495c51f124SMoriah Waterland 
7505c51f124SMoriah Waterland 	/* Is this coming to us from a server? */
7515c51f124SMoriah Waterland 	if (nfte->remote && !(nfte->writeable))
7525c51f124SMoriah Waterland 		nfte->served = 1;
7535c51f124SMoriah Waterland 
7545c51f124SMoriah Waterland 	return (0);
7555c51f124SMoriah Waterland }
7565c51f124SMoriah Waterland 
7575c51f124SMoriah Waterland /*
7585c51f124SMoriah Waterland  * This function modifies an existing fs_tab[] entry. It was found mounted up
7595c51f124SMoriah Waterland  * exactly the way we would have mounted it in mount_client() only at the
7605c51f124SMoriah Waterland  * time we didn't know it was for the client. Now we do, so we're setting the
7615c51f124SMoriah Waterland  * various permissions to conform to the client view.
7625c51f124SMoriah Waterland  */
7635c51f124SMoriah Waterland static void
mod_existing(struct vfstab * vfsent,int fstab_entry,int is_remote)7645c51f124SMoriah Waterland mod_existing(struct vfstab *vfsent, int fstab_entry, int is_remote)
7655c51f124SMoriah Waterland {
7665c51f124SMoriah Waterland 	/*
7675c51f124SMoriah Waterland 	 * Establish whether the client will see this as served.
7685c51f124SMoriah Waterland 	 */
7695c51f124SMoriah Waterland 	if (is_remote && hasopt(vfsent->vfs_mntopts, MNTOPT_RO))
7705c51f124SMoriah Waterland 		fs_tab[fstab_entry]->served = 1;
7715c51f124SMoriah Waterland 
7725c51f124SMoriah Waterland 	fs_tab[fstab_entry]->cl_mounted = 1;
7735c51f124SMoriah Waterland }
7745c51f124SMoriah Waterland 
7755c51f124SMoriah Waterland /*
7765c51f124SMoriah Waterland  * This function constructs a new fs_tab[] entry based on
7775c51f124SMoriah Waterland  * an /etc/vfstab entry. When it returns, the new entry has been inserted
7785c51f124SMoriah Waterland  * into fstab[].
7795c51f124SMoriah Waterland  */
7805c51f124SMoriah Waterland static int
construct_vfs(struct vfstab * vfsent,char * client_path,char * link_name,int is_remote,int mnt_stat)7815c51f124SMoriah Waterland construct_vfs(struct vfstab *vfsent, char *client_path, char *link_name,
7825c51f124SMoriah Waterland     int is_remote, int mnt_stat)
7835c51f124SMoriah Waterland {
7845c51f124SMoriah Waterland 	int use_link;
7855c51f124SMoriah Waterland 	struct	fstable	*nfte;
7865c51f124SMoriah Waterland 
7875c51f124SMoriah Waterland 	if ((nfte = fs_tab_init(client_path, vfsent->vfs_fstype)) == NULL)
7885c51f124SMoriah Waterland 		return (1);
7895c51f124SMoriah Waterland 
7905c51f124SMoriah Waterland 	nfte->remote = (is_remote == REAL_REMOTE);
7915c51f124SMoriah Waterland 
7925c51f124SMoriah Waterland 	/*
7935c51f124SMoriah Waterland 	 * The file system mounted on the client may or may not be writeable.
7945c51f124SMoriah Waterland 	 * So we hand it over to fsys() to evaluate. This will have the same
7955c51f124SMoriah Waterland 	 * read/write attributes as the corresponding mounted filesystem.
7965c51f124SMoriah Waterland 	 */
7975c51f124SMoriah Waterland 	use_link = 0;
7985c51f124SMoriah Waterland 	if (nfte->remote) {
7995c51f124SMoriah Waterland 		/*
8005c51f124SMoriah Waterland 		 * Deal here with mount points actually on a system remote
8015c51f124SMoriah Waterland 		 * from the server.
8025c51f124SMoriah Waterland 		 */
8035c51f124SMoriah Waterland 		if (mnt_stat == MNT_NOT) {
8045c51f124SMoriah Waterland 			/*
8055c51f124SMoriah Waterland 			 * This filesystem isn't in the current mount table
8065c51f124SMoriah Waterland 			 * meaning it isn't mounted, the current host can't
8075c51f124SMoriah Waterland 			 * write to it and there's no point to mapping it for
8085c51f124SMoriah Waterland 			 * the server.
8095c51f124SMoriah Waterland 			 */
8105c51f124SMoriah Waterland 			link_name = NULL;
8115c51f124SMoriah Waterland 			nfte->mounted = 0;
8125c51f124SMoriah Waterland 			nfte->srvr_map = 0;
8135c51f124SMoriah Waterland 			nfte->writeable = 0;
8145c51f124SMoriah Waterland 		} else {	/* It's MNT_AVAIL. */
8155c51f124SMoriah Waterland 			/*
8165c51f124SMoriah Waterland 			 * This filesystem is associated with a current
8175c51f124SMoriah Waterland 			 * mountpoint. Since it's mounted, it needs to be
8185c51f124SMoriah Waterland 			 * remapped and it is writable if the real mounted
8195c51f124SMoriah Waterland 			 * filesystem is writeable.
8205c51f124SMoriah Waterland 			 */
8215c51f124SMoriah Waterland 			use_link = 1;
8225c51f124SMoriah Waterland 			link_name = strdup(fs_tab[match_mount]->name);
8235c51f124SMoriah Waterland 			nfte->mounted = 1;
8245c51f124SMoriah Waterland 			nfte->srvr_map = 1;
8255c51f124SMoriah Waterland 			nfte->writeable = fs_tab[match_mount]->writeable;
8265c51f124SMoriah Waterland 			nfte->write_tested = fs_tab[match_mount]->write_tested;
8275c51f124SMoriah Waterland 		}
8285c51f124SMoriah Waterland 	} else {	/* local filesystem */
8295c51f124SMoriah Waterland 		use_link = 1;
8305c51f124SMoriah Waterland 		nfte->mounted = 1;
8315c51f124SMoriah Waterland 		nfte->srvr_map = 1;
8325c51f124SMoriah Waterland 		nfte->writeable = fs_tab[fsys(link_name)]->writeable;
8335c51f124SMoriah Waterland 		nfte->write_tested = 1;
8345c51f124SMoriah Waterland 	}
8355c51f124SMoriah Waterland 
8365c51f124SMoriah Waterland 	/*
8375c51f124SMoriah Waterland 	 * Now we establish whether the client will see this as served.
8385c51f124SMoriah Waterland 	 */
8395c51f124SMoriah Waterland 	if (is_remote && hasopt(vfsent->vfs_mntopts, MNTOPT_RO))
8405c51f124SMoriah Waterland 		nfte->served = 1;
8415c51f124SMoriah Waterland 
8425c51f124SMoriah Waterland 	if (use_link) {
8435c51f124SMoriah Waterland 		nfte->remote_name = link_name;
8445c51f124SMoriah Waterland 	} else {
8455c51f124SMoriah Waterland 		nfte->remote_name = strdup(vfsent->vfs_special);
8465c51f124SMoriah Waterland 	}
8475c51f124SMoriah Waterland 
8485c51f124SMoriah Waterland 	return (0);
8495c51f124SMoriah Waterland }
8505c51f124SMoriah Waterland 
8515c51f124SMoriah Waterland /*
8525c51f124SMoriah Waterland  * get_mntinfo - get the mount table, now dynamically allocated. Returns 0 if
8535c51f124SMoriah Waterland  * no problem and 1 if there's a fatal error.
8545c51f124SMoriah Waterland  */
8555c51f124SMoriah Waterland int
get_mntinfo(int map_client,char * vfstab_file)8565c51f124SMoriah Waterland get_mntinfo(int map_client, char *vfstab_file)
8575c51f124SMoriah Waterland {
8585c51f124SMoriah Waterland 	static 	char 	*rn = "/";
8595c51f124SMoriah Waterland 	FILE		*pp;
8605c51f124SMoriah Waterland 	struct	mnttab	mtbuf;
8615c51f124SMoriah Waterland 	struct	mnttab	*mt = &mtbuf;
8625c51f124SMoriah Waterland 	char		*install_root;
8635c51f124SMoriah Waterland 	int 		is_remote;
8645c51f124SMoriah Waterland 
8655c51f124SMoriah Waterland 	/*
8665c51f124SMoriah Waterland 	 * Open the mount table for the current host and establish a global
8675c51f124SMoriah Waterland 	 * table that holds data about current mount status.
8685c51f124SMoriah Waterland 	 */
8695c51f124SMoriah Waterland 	if ((pp = setmntent(MOUNT_TABLE, "r")) == NULL) {
8705c51f124SMoriah Waterland 		progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno));
8715c51f124SMoriah Waterland 		return (1);
8725c51f124SMoriah Waterland 	}
8735c51f124SMoriah Waterland 
8745c51f124SMoriah Waterland 	/*
8755c51f124SMoriah Waterland 	 * First, review the mounted filesystems on the managing host. This
8765c51f124SMoriah Waterland 	 * may also be the target host but we haven't decided that for sure
8775c51f124SMoriah Waterland 	 * yet.
8785c51f124SMoriah Waterland 	 */
8795c51f124SMoriah Waterland 	while (!getmntent(pp, mt))
8805c51f124SMoriah Waterland 		if (construct_mt(mt))
8815c51f124SMoriah Waterland 			return (1);
8825c51f124SMoriah Waterland 
8835c51f124SMoriah Waterland 	(void) endmntent(pp);
8845c51f124SMoriah Waterland 
8855c51f124SMoriah Waterland 	/*
8865c51f124SMoriah Waterland 	 * Now, we see if this installation is to a client. If it is, we scan
8875c51f124SMoriah Waterland 	 * the client's vfstab to determine what filesystems are
8885c51f124SMoriah Waterland 	 * inappropriate to write to. This simply adds the vfstab entries
8895c51f124SMoriah Waterland 	 * representing what will be remote file systems for the client.
8905c51f124SMoriah Waterland 	 * Everything that isn't remote to the client is already accounted
8915c51f124SMoriah Waterland 	 * for in the fs_tab[] so far. If the remote filesystem is really on
8925c51f124SMoriah Waterland 	 * this server, we will write through to the server from this client.
8935c51f124SMoriah Waterland 	 */
8945c51f124SMoriah Waterland 	install_root = get_inst_root();
8955c51f124SMoriah Waterland 	if (install_root && strcmp(install_root, "/") != 0 && map_client) {
8965c51f124SMoriah Waterland 		/* OK, this is a legitimate remote client. */
8975c51f124SMoriah Waterland 		struct	vfstab	vfsbuf;
8985c51f124SMoriah Waterland 		struct	vfstab	*vfs = &vfsbuf;
8995c51f124SMoriah Waterland 		char VFS_TABLE[PATH_MAX];
9005c51f124SMoriah Waterland 
9015c51f124SMoriah Waterland 		/*
9025c51f124SMoriah Waterland 		 * Since we use the fsys() function later, and it depends on
9035c51f124SMoriah Waterland 		 * an ordered list, we have to sort the list here.
9045c51f124SMoriah Waterland 		 */
9055c51f124SMoriah Waterland 		qsort(fs_tab, fs_tab_used,
9065c51f124SMoriah Waterland 		    sizeof (struct fstable *), fs_tab_ent_comp);
9075c51f124SMoriah Waterland 
9085c51f124SMoriah Waterland 		/*
9095c51f124SMoriah Waterland 		 * Here's where the vfstab for the target is. If we can get
9105c51f124SMoriah Waterland 		 * to it, we'll scan it for what the client will see as
9115c51f124SMoriah Waterland 		 * remote filesystems, otherwise, we'll just skip this.
9125c51f124SMoriah Waterland 		 */
9135c51f124SMoriah Waterland 		if (vfstab_file) {
9145c51f124SMoriah Waterland 			(void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s",
9155c51f124SMoriah Waterland 			    vfstab_file);
9165c51f124SMoriah Waterland 		} else {
9175c51f124SMoriah Waterland 			(void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s%s",
9185c51f124SMoriah Waterland 			    install_root, VFSTAB);
9195c51f124SMoriah Waterland 		}
9205c51f124SMoriah Waterland 
9215c51f124SMoriah Waterland 		if (access(VFS_TABLE, R_OK) == 0) {
9225c51f124SMoriah Waterland 			char *link_name;
9235c51f124SMoriah Waterland 
9245c51f124SMoriah Waterland 			/*
9255c51f124SMoriah Waterland 			 * Open the vfs table for the target host.
9265c51f124SMoriah Waterland 			 */
9275c51f124SMoriah Waterland 			if ((pp = setmntent(VFS_TABLE, "r")) == NULL) {
9285c51f124SMoriah Waterland 				progerr(ERR_NOTABLE, "vfs", VFS_TABLE,
9295c51f124SMoriah Waterland 				    strerror(errno));
9305c51f124SMoriah Waterland 				return (1);
9315c51f124SMoriah Waterland 			}
9325c51f124SMoriah Waterland 
9335c51f124SMoriah Waterland 			/* Do this for each entry in the vfstab. */
9345c51f124SMoriah Waterland 			while (!getvfsent(pp, vfs)) {
9355c51f124SMoriah Waterland 				char client_mountp[PATH_MAX];
9365c51f124SMoriah Waterland 				int mnt_stat;
9375c51f124SMoriah Waterland 
9385c51f124SMoriah Waterland 				/*
9395c51f124SMoriah Waterland 				 * We put it into the fs table if it's
9405c51f124SMoriah Waterland 				 * remote mounted (even from this server) or
9415c51f124SMoriah Waterland 				 * loopback mounted from the client's point
9425c51f124SMoriah Waterland 				 * of view.
9435c51f124SMoriah Waterland 				 */
9445c51f124SMoriah Waterland 				if (!(is_remote =
9455c51f124SMoriah Waterland 				    is_remote_src(vfs->vfs_special)) &&
9465c51f124SMoriah Waterland 				    strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) !=
9475c51f124SMoriah Waterland 				    0)
9485c51f124SMoriah Waterland 					continue;	/* not interesting */
9495c51f124SMoriah Waterland 
9505c51f124SMoriah Waterland 				/*
9515c51f124SMoriah Waterland 				 * Construct client_mountp by prepending the
9525c51f124SMoriah Waterland 				 * install_root to the 'mount point' name.
9535c51f124SMoriah Waterland 				 */
9545c51f124SMoriah Waterland 				if (strcmp(vfs->vfs_mountp, "/") == 0) {
9555c51f124SMoriah Waterland 					(void) strcpy(client_mountp,
9565c51f124SMoriah Waterland 					    install_root);
9575c51f124SMoriah Waterland 				} else {
9585c51f124SMoriah Waterland 					(void) snprintf(client_mountp,
9595c51f124SMoriah Waterland 					    sizeof (client_mountp), "%s%s",
9605c51f124SMoriah Waterland 					    install_root, vfs->vfs_mountp);
9615c51f124SMoriah Waterland 				}
9625c51f124SMoriah Waterland 
9635c51f124SMoriah Waterland 				/*
9645c51f124SMoriah Waterland 				 * We also skip the entry if the vfs_special
9655c51f124SMoriah Waterland 				 * path and the client_path are the same.
9665c51f124SMoriah Waterland 				 * There's no need to mount it, it's just a
9675c51f124SMoriah Waterland 				 * cachefs optimization that mounts a
9685c51f124SMoriah Waterland 				 * directory over itself from this server.
9695c51f124SMoriah Waterland 				 */
9705c51f124SMoriah Waterland 				if ((is_remote == SELF_SERVE) &&
9715c51f124SMoriah Waterland 				    strcmp(path_part(vfs->vfs_special),
9725c51f124SMoriah Waterland 				    client_mountp) == 0)
9735c51f124SMoriah Waterland 					continue;
9745c51f124SMoriah Waterland 
9755c51f124SMoriah Waterland 				/* Determine if this is already mounted. */
9765c51f124SMoriah Waterland 				link_name = strdup(path_part(vfs->vfs_special));
9775c51f124SMoriah Waterland 				mnt_stat = already_mounted(vfs,
9785c51f124SMoriah Waterland 				    (is_remote != REAL_REMOTE), client_mountp,
9795c51f124SMoriah Waterland 				    link_name);
9805c51f124SMoriah Waterland 
9815c51f124SMoriah Waterland 				if (mnt_stat == MNT_EXACT) {
9825c51f124SMoriah Waterland 					mod_existing(vfs, match_mount,
9835c51f124SMoriah Waterland 					    is_remote);
9845c51f124SMoriah Waterland 				} else {	/* MNT_NOT */
9855c51f124SMoriah Waterland 					if (construct_vfs(vfs, client_mountp,
986*44da9c13SSimon Klinkert 					    link_name, is_remote, mnt_stat)) {
9875c51f124SMoriah Waterland 						return (1);
9885c51f124SMoriah Waterland 					}
9895c51f124SMoriah Waterland 				}
990*44da9c13SSimon Klinkert 			}
9915c51f124SMoriah Waterland 			(void) endmntent(pp);
9925c51f124SMoriah Waterland 		}	/* end of if(access()) */
9935c51f124SMoriah Waterland 	}	/* end of if(install_root) */
9945c51f124SMoriah Waterland 
9955c51f124SMoriah Waterland 	/* This next one may look stupid, but it can really happen. */
9965c51f124SMoriah Waterland 	if (fs_tab_used <= 0) {
9975c51f124SMoriah Waterland 		progerr(ERR_MNT_NOMOUNTS);
9985c51f124SMoriah Waterland 		return (1);
9995c51f124SMoriah Waterland 	}
10005c51f124SMoriah Waterland 
10015c51f124SMoriah Waterland 	/*
10025c51f124SMoriah Waterland 	 * Now that we have the complete list of mounted (or virtually
10035c51f124SMoriah Waterland 	 * mounted) filesystems, we sort the mountpoints in reverse order
10045c51f124SMoriah Waterland 	 * based on the length of the 'mount point' name.
10055c51f124SMoriah Waterland 	 */
10065c51f124SMoriah Waterland 	qsort(fs_tab, fs_tab_used, sizeof (struct fstable *), fs_tab_ent_comp);
10075c51f124SMoriah Waterland 	if (strcmp(fs_tab[fs_tab_used-1]->name, rn) != 0) {
10085c51f124SMoriah Waterland 		progerr(ERR_MNT_NOROOT, fs_tab[fs_tab_used-1]->name, rn, errno,
10095c51f124SMoriah Waterland 		    strerror(errno));
10105c51f124SMoriah Waterland 		return (1);
10115c51f124SMoriah Waterland 	} else {
10125c51f124SMoriah Waterland 		return (0);
10135c51f124SMoriah Waterland 	}
10145c51f124SMoriah Waterland }
10155c51f124SMoriah Waterland 
10165c51f124SMoriah Waterland /*
10175c51f124SMoriah Waterland  * This function supports dryrun mode by allowing the filesystem table to be
10185c51f124SMoriah Waterland  * directly loaded from the continuation file.
10195c51f124SMoriah Waterland  */
10205c51f124SMoriah Waterland int
load_fsentry(struct fstable * fs_entry,char * name,char * fstype,char * remote_name)10215c51f124SMoriah Waterland load_fsentry(struct fstable *fs_entry, char *name, char *fstype,
10225c51f124SMoriah Waterland     char *remote_name)
10235c51f124SMoriah Waterland {
10245c51f124SMoriah Waterland 	struct fstable *nfte;
10255c51f124SMoriah Waterland 
10265c51f124SMoriah Waterland 	if ((nfte = fs_tab_init(name, fstype)) == NULL)
10275c51f124SMoriah Waterland 		return (1);
10285c51f124SMoriah Waterland 
10295c51f124SMoriah Waterland 	/* Grab the name and fstype from the new structure. */
10305c51f124SMoriah Waterland 	fs_entry->name = nfte->name;
10315c51f124SMoriah Waterland 	fs_entry->fstype = nfte->fstype;
10325c51f124SMoriah Waterland 
10335c51f124SMoriah Waterland 	/* Copy the basic structure into place. */
10345c51f124SMoriah Waterland 	(void) memcpy(nfte, fs_entry, sizeof (struct fstable));
10355c51f124SMoriah Waterland 
10365c51f124SMoriah Waterland 	/*
10375c51f124SMoriah Waterland 	 * Allocate space for the 'special' name.
10385c51f124SMoriah Waterland 	 */
10395c51f124SMoriah Waterland 	if ((nfte->remote_name = malloc(strlen(remote_name)+1)) == NULL) {
10405c51f124SMoriah Waterland 		progerr(ERR_MALLOC, "remote_name", errno, strerror(errno));
10415c51f124SMoriah Waterland 		return (1);
10425c51f124SMoriah Waterland 	}
10435c51f124SMoriah Waterland 
10445c51f124SMoriah Waterland 	(void) strcpy(nfte->remote_name, remote_name);
10455c51f124SMoriah Waterland 
10465c51f124SMoriah Waterland 	return (0);
10475c51f124SMoriah Waterland }
10485c51f124SMoriah Waterland 
10495c51f124SMoriah Waterland /*
10505c51f124SMoriah Waterland  * Given a path, return the table index of the filesystem the file apparently
10515c51f124SMoriah Waterland  * resides on. This doesn't put any time into resolving filesystems that
10525c51f124SMoriah Waterland  * refer to other filesystems. It just returns the entry containing this
10535c51f124SMoriah Waterland  * path.
10545c51f124SMoriah Waterland  */
1055*44da9c13SSimon Klinkert uint32_t
fsys(char * path)10565c51f124SMoriah Waterland fsys(char *path)
10575c51f124SMoriah Waterland {
10585c51f124SMoriah Waterland 	register int i;
10595c51f124SMoriah Waterland 	char	real_path[PATH_MAX];
1060af122237SJan Kryl 	char	path_copy[PATH_MAX];
1061af122237SJan Kryl 	char	*path2use;
1062af122237SJan Kryl 	char	*cp;
10635c51f124SMoriah Waterland 	int	pathlen;
1064af122237SJan Kryl 	boolean_t found = B_FALSE;
10655c51f124SMoriah Waterland 
1066af122237SJan Kryl 	/*
1067af122237SJan Kryl 	 * The loop below represents our best effort to identify real path of
1068af122237SJan Kryl 	 * a file, which doesn't need to exist. realpath() returns error for
1069af122237SJan Kryl 	 * nonexistent path, therefore we need to cut off trailing components
1070af122237SJan Kryl 	 * of path until we get path which exists and can be resolved by
1071af122237SJan Kryl 	 * realpath(). Lookup of "/dir/symlink/nonexistent-file" would fail
1072af122237SJan Kryl 	 * to resolve symlink without this.
1073af122237SJan Kryl 	 */
1074af122237SJan Kryl 	(void) strlcpy(path_copy, path, PATH_MAX);
1075af122237SJan Kryl 	for (cp = dirname(path_copy); strlen(cp) > 1; cp = dirname(cp)) {
1076af122237SJan Kryl 		if (realpath(cp, real_path) != NULL) {
1077af122237SJan Kryl 			found = B_TRUE;
1078af122237SJan Kryl 			break;
1079af122237SJan Kryl 		} else if (errno != ENOENT)
1080af122237SJan Kryl 			break;
10815c51f124SMoriah Waterland 	}
1082af122237SJan Kryl 	if (found)
1083af122237SJan Kryl 		path2use = real_path;
1084af122237SJan Kryl 	else
1085af122237SJan Kryl 		/* fall back to original path in case of unexpected failure */
1086af122237SJan Kryl 		path2use = path;
10875c51f124SMoriah Waterland 
10885c51f124SMoriah Waterland 	pathlen = strlen(path2use);
10895c51f124SMoriah Waterland 
10905c51f124SMoriah Waterland 	/*
10915c51f124SMoriah Waterland 	 * The following algorithm scans the list of attached file systems
10925c51f124SMoriah Waterland 	 * for the one containing path. At this point the file names in
10935c51f124SMoriah Waterland 	 * fs_tab[] are sorted by decreasing length to facilitate the scan.
10945c51f124SMoriah Waterland 	 * The first for() scans past all the file system names too short to
10955c51f124SMoriah Waterland 	 * contain path. The second for() does the actual string comparison.
10965c51f124SMoriah Waterland 	 * It tests first to assure that the comparison is against a complete
10975c51f124SMoriah Waterland 	 * token by assuring that the end of the filesystem name aligns with
10985c51f124SMoriah Waterland 	 * the end of a token in path2use (ie: '/' or NULL) then it does a
10995c51f124SMoriah Waterland 	 * string compare. -- JST
11005c51f124SMoriah Waterland 	 */
11015c51f124SMoriah Waterland 
11025c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
11035c51f124SMoriah Waterland 		return (-1);
11045c51f124SMoriah Waterland 	}
11055c51f124SMoriah Waterland 
11065c51f124SMoriah Waterland 	for (i = 0; i < fs_tab_used; i++)
11075c51f124SMoriah Waterland 		if (fs_tab[i] == NULL)
11085c51f124SMoriah Waterland 			continue;
11095c51f124SMoriah Waterland 		else if (fs_tab[i]->namlen <= pathlen)
11105c51f124SMoriah Waterland 			break;
11115c51f124SMoriah Waterland 	for (; i < fs_tab_used; i++) {
11125c51f124SMoriah Waterland 		int fs_namelen;
11135c51f124SMoriah Waterland 		char term_char;
11145c51f124SMoriah Waterland 
11155c51f124SMoriah Waterland 		if (fs_tab[i] == NULL)
11165c51f124SMoriah Waterland 			continue;
11175c51f124SMoriah Waterland 
11185c51f124SMoriah Waterland 		fs_namelen = fs_tab[i]->namlen;
11195c51f124SMoriah Waterland 		term_char = path2use[fs_namelen];
11205c51f124SMoriah Waterland 
11215c51f124SMoriah Waterland 		/*
11225c51f124SMoriah Waterland 		 * If we're putting the file "/a/kernel" into the filesystem
11235c51f124SMoriah Waterland 		 * "/a", then fs_namelen == 2 and term_char == '/'. If, we're
11245c51f124SMoriah Waterland 		 * putting "/etc/termcap" into "/", fs_namelen == 1 and
11255c51f124SMoriah Waterland 		 * term_char (unfortunately) == 'e'. In the case of
11265c51f124SMoriah Waterland 		 * fs_namelen == 1, we check to make sure the filesystem is
11275c51f124SMoriah Waterland 		 * "/" and if it is, we have a guaranteed fit, otherwise we
11285c51f124SMoriah Waterland 		 * do the string compare. -- JST
11295c51f124SMoriah Waterland 		 */
11305c51f124SMoriah Waterland 		if ((fs_namelen == 1 && *(fs_tab[i]->name) == '/') ||
11315c51f124SMoriah Waterland 		    ((term_char == '/' || term_char == NULL) &&
1132*44da9c13SSimon Klinkert 		    strncmp(fs_tab[i]->name, path2use, fs_namelen) == 0)) {
11335c51f124SMoriah Waterland 			return (i);
11345c51f124SMoriah Waterland 		}
1135*44da9c13SSimon Klinkert 	}
11365c51f124SMoriah Waterland 
11375c51f124SMoriah Waterland 	/*
11385c51f124SMoriah Waterland 	 * It only gets here if the root filesystem is fundamentally corrupt.
11395c51f124SMoriah Waterland 	 * (This can happen!)
11405c51f124SMoriah Waterland 	 */
11415c51f124SMoriah Waterland 	progerr(ERR_FSYS_FELLOUT, path2use);
11425c51f124SMoriah Waterland 
11435c51f124SMoriah Waterland 	return (-1);
11445c51f124SMoriah Waterland }
11455c51f124SMoriah Waterland 
11465c51f124SMoriah Waterland /*
11475c51f124SMoriah Waterland  * This function returns the entry in the fs_tab[] corresponding to the
11485c51f124SMoriah Waterland  * actual filesystem of record. It won't return a loopback filesystem entry,
11495c51f124SMoriah Waterland  * it will return the filesystem that the loopback filesystem is mounted
11505c51f124SMoriah Waterland  * over.
11515c51f124SMoriah Waterland  */
1152*44da9c13SSimon Klinkert uint32_t
resolved_fsys(char * path)11535c51f124SMoriah Waterland resolved_fsys(char *path)
11545c51f124SMoriah Waterland {
11555c51f124SMoriah Waterland 	int i = -1;
11565c51f124SMoriah Waterland 	char path2use[PATH_MAX];
11575c51f124SMoriah Waterland 
11585c51f124SMoriah Waterland 	(void) strcpy(path2use, path);
11595c51f124SMoriah Waterland 
11605c51f124SMoriah Waterland 	/* If this isn't a "real" filesystem, resolve the map. */
11615c51f124SMoriah Waterland 	do {
11625c51f124SMoriah Waterland 		(void) strcpy(path2use, server_map(path2use, i));
11635c51f124SMoriah Waterland 		i = fsys(path2use);
11645c51f124SMoriah Waterland 	} while (fs_tab[i]->srvr_map);
11655c51f124SMoriah Waterland 
11665c51f124SMoriah Waterland 	return (i);
11675c51f124SMoriah Waterland }
11685c51f124SMoriah Waterland 
11695c51f124SMoriah Waterland /*
11705c51f124SMoriah Waterland  * This function returns the srvr_map status based upon the fs_tab entry
11715c51f124SMoriah Waterland  * number. This tells us if the server path constructed from the package
11725c51f124SMoriah Waterland  * install root is really the target filesystem.
11735c51f124SMoriah Waterland  */
11745c51f124SMoriah Waterland int
use_srvr_map_n(uint32_t n)1175*44da9c13SSimon Klinkert use_srvr_map_n(uint32_t n)
11765c51f124SMoriah Waterland {
11775c51f124SMoriah Waterland 	return ((int)fs_tab[n]->srvr_map);
11785c51f124SMoriah Waterland }
11795c51f124SMoriah Waterland 
11805c51f124SMoriah Waterland /*
11815c51f124SMoriah Waterland  * This function returns the mount status based upon the fs_tab entry
11825c51f124SMoriah Waterland  * number. This tells us if there is any hope of gaining access
11835c51f124SMoriah Waterland  * to this file system.
11845c51f124SMoriah Waterland  */
11855c51f124SMoriah Waterland int
is_mounted_n(uint32_t n)1186*44da9c13SSimon Klinkert is_mounted_n(uint32_t n)
11875c51f124SMoriah Waterland {
11885c51f124SMoriah Waterland 	return ((int)fs_tab[n]->mounted);
11895c51f124SMoriah Waterland }
11905c51f124SMoriah Waterland 
11915c51f124SMoriah Waterland /*
11925c51f124SMoriah Waterland  * is_fs_writeable_n - given an fstab index, return 1
11935c51f124SMoriah Waterland  *	if it's writeable, 0 if read-only.
11945c51f124SMoriah Waterland  */
11955c51f124SMoriah Waterland int
is_fs_writeable_n(uint32_t n)1196*44da9c13SSimon Klinkert is_fs_writeable_n(uint32_t n)
11975c51f124SMoriah Waterland {
11985c51f124SMoriah Waterland 	/*
11995c51f124SMoriah Waterland 	 * If the write access permissions haven't been confirmed, do that
12005c51f124SMoriah Waterland 	 * now. Note that the only reason we need to do the special check is
12015c51f124SMoriah Waterland 	 * in the case of an NFS mount (remote) because we can't determine if
12025c51f124SMoriah Waterland 	 * root has access in any other way.
12035c51f124SMoriah Waterland 	 */
12045c51f124SMoriah Waterland 	if (fs_tab[n]->remote && fs_tab[n]->mounted &&
12055c51f124SMoriah Waterland 	    !fs_tab[n]->write_tested) {
12065c51f124SMoriah Waterland 		if (fs_tab[n]->writeable && !really_write(fs_tab[n]->name))
12075c51f124SMoriah Waterland 			fs_tab[n]->writeable = 0;	/* not really */
12085c51f124SMoriah Waterland 
12095c51f124SMoriah Waterland 		fs_tab[n]->write_tested = 1;	/* confirmed */
12105c51f124SMoriah Waterland 	}
12115c51f124SMoriah Waterland 
12125c51f124SMoriah Waterland 	return ((int)fs_tab[n]->writeable);
12135c51f124SMoriah Waterland }
12145c51f124SMoriah Waterland 
12155c51f124SMoriah Waterland /*
12165c51f124SMoriah Waterland  * is_remote_fs_n - given an fstab index, return 1
12175c51f124SMoriah Waterland  *	if it's a remote filesystem, 0 if local.
12185c51f124SMoriah Waterland  *
12195c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
12205c51f124SMoriah Waterland  */
12215c51f124SMoriah Waterland int
is_remote_fs_n(uint32_t n)1222*44da9c13SSimon Klinkert is_remote_fs_n(uint32_t n)
12235c51f124SMoriah Waterland {
12245c51f124SMoriah Waterland 	return ((int)fs_tab[n]->remote);
12255c51f124SMoriah Waterland }
12265c51f124SMoriah Waterland 
12275c51f124SMoriah Waterland /* index-driven is_served() */
12285c51f124SMoriah Waterland int
is_served_n(uint32_t n)1229*44da9c13SSimon Klinkert is_served_n(uint32_t n)
12305c51f124SMoriah Waterland {
12315c51f124SMoriah Waterland 	return ((int)fs_tab[n]->served);
12325c51f124SMoriah Waterland }
12335c51f124SMoriah Waterland 
12345c51f124SMoriah Waterland /*
12355c51f124SMoriah Waterland  * This returns the number of blocks available on the indicated filesystem.
12365c51f124SMoriah Waterland  *
12375c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
12385c51f124SMoriah Waterland  */
12395c51f124SMoriah Waterland fsblkcnt_t
get_blk_free_n(uint32_t n)1240*44da9c13SSimon Klinkert get_blk_free_n(uint32_t n)
12415c51f124SMoriah Waterland {
12425c51f124SMoriah Waterland 	return (fs_tab[n]->bfree);
12435c51f124SMoriah Waterland }
12445c51f124SMoriah Waterland 
12455c51f124SMoriah Waterland /*
12465c51f124SMoriah Waterland  * This returns the number of blocks being used on the indicated filesystem.
12475c51f124SMoriah Waterland  *
12485c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
12495c51f124SMoriah Waterland  */
12505c51f124SMoriah Waterland fsblkcnt_t
get_blk_used_n(uint32_t n)1251*44da9c13SSimon Klinkert get_blk_used_n(uint32_t n)
12525c51f124SMoriah Waterland {
12535c51f124SMoriah Waterland 	return (fs_tab[n]->bused);
12545c51f124SMoriah Waterland }
12555c51f124SMoriah Waterland 
12565c51f124SMoriah Waterland /*
12575c51f124SMoriah Waterland  * This returns the number of inodes available on the indicated filesystem.
12585c51f124SMoriah Waterland  *
12595c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
12605c51f124SMoriah Waterland  */
12615c51f124SMoriah Waterland fsblkcnt_t
get_inode_free_n(uint32_t n)1262*44da9c13SSimon Klinkert get_inode_free_n(uint32_t n)
12635c51f124SMoriah Waterland {
12645c51f124SMoriah Waterland 	return (fs_tab[n]->ffree);
12655c51f124SMoriah Waterland }
12665c51f124SMoriah Waterland 
12675c51f124SMoriah Waterland /*
12685c51f124SMoriah Waterland  * This returns the number of inodes being used on the indicated filesystem.
12695c51f124SMoriah Waterland  *
12705c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
12715c51f124SMoriah Waterland  */
12725c51f124SMoriah Waterland fsblkcnt_t
get_inode_used_n(uint32_t n)1273*44da9c13SSimon Klinkert get_inode_used_n(uint32_t n)
12745c51f124SMoriah Waterland {
12755c51f124SMoriah Waterland 	return (fs_tab[n]->fused);
12765c51f124SMoriah Waterland }
12775c51f124SMoriah Waterland 
12785c51f124SMoriah Waterland /*
12795c51f124SMoriah Waterland  * Sets the number of blocks being used on the indicated filesystem.
12805c51f124SMoriah Waterland  *
12815c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
12825c51f124SMoriah Waterland  */
12835c51f124SMoriah Waterland void
set_blk_used_n(uint32_t n,fsblkcnt_t value)1284*44da9c13SSimon Klinkert set_blk_used_n(uint32_t n, fsblkcnt_t value)
12855c51f124SMoriah Waterland {
12865c51f124SMoriah Waterland 	fs_tab[n]->bused = value;
12875c51f124SMoriah Waterland }
12885c51f124SMoriah Waterland 
12895c51f124SMoriah Waterland /* Get the filesystem block size. */
12905c51f124SMoriah Waterland fsblkcnt_t
get_blk_size_n(uint32_t n)1291*44da9c13SSimon Klinkert get_blk_size_n(uint32_t n)
12925c51f124SMoriah Waterland {
12935c51f124SMoriah Waterland 	return (fs_tab[n]->bsize);
12945c51f124SMoriah Waterland }
12955c51f124SMoriah Waterland 
12965c51f124SMoriah Waterland /* Get the filesystem fragment size. */
12975c51f124SMoriah Waterland fsblkcnt_t
get_frag_size_n(uint32_t n)1298*44da9c13SSimon Klinkert get_frag_size_n(uint32_t n)
12995c51f124SMoriah Waterland {
13005c51f124SMoriah Waterland 	return (fs_tab[n]->bsize);
13015c51f124SMoriah Waterland }
13025c51f124SMoriah Waterland 
13035c51f124SMoriah Waterland /*
13045c51f124SMoriah Waterland  * This returns the name of the indicated filesystem.
13055c51f124SMoriah Waterland  */
13065c51f124SMoriah Waterland char *
get_fs_name_n(uint32_t n)1307*44da9c13SSimon Klinkert get_fs_name_n(uint32_t n)
13085c51f124SMoriah Waterland {
13095c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
13105c51f124SMoriah Waterland 		return (NULL);
13115c51f124SMoriah Waterland 	} else if (n >= fs_tab_used) {
13125c51f124SMoriah Waterland 		return (NULL);
13135c51f124SMoriah Waterland 	} else {
13145c51f124SMoriah Waterland 		return (fs_tab[n]->name);
13155c51f124SMoriah Waterland 	}
13165c51f124SMoriah Waterland }
13175c51f124SMoriah Waterland 
13185c51f124SMoriah Waterland /*
13195c51f124SMoriah Waterland  * This returns the remote name of the indicated filesystem.
13205c51f124SMoriah Waterland  *
13215c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
13225c51f124SMoriah Waterland  */
13235c51f124SMoriah Waterland char *
get_source_name_n(uint32_t n)1324*44da9c13SSimon Klinkert get_source_name_n(uint32_t n)
13255c51f124SMoriah Waterland {
13265c51f124SMoriah Waterland 	return (fs_tab[n]->remote_name);
13275c51f124SMoriah Waterland }
13285c51f124SMoriah Waterland 
13295c51f124SMoriah Waterland /*
13305c51f124SMoriah Waterland  * This function returns the srvr_map status based upon the path.
13315c51f124SMoriah Waterland  */
13325c51f124SMoriah Waterland int
use_srvr_map(char * path,uint32_t * fsys_value)1333*44da9c13SSimon Klinkert use_srvr_map(char *path, uint32_t *fsys_value)
13345c51f124SMoriah Waterland {
13355c51f124SMoriah Waterland 	if (*fsys_value == BADFSYS)
13365c51f124SMoriah Waterland 		*fsys_value = fsys(path);
13375c51f124SMoriah Waterland 
13385c51f124SMoriah Waterland 	return (use_srvr_map_n(*fsys_value));
13395c51f124SMoriah Waterland }
13405c51f124SMoriah Waterland 
13415c51f124SMoriah Waterland /*
13425c51f124SMoriah Waterland  * This function returns the mount status based upon the path.
13435c51f124SMoriah Waterland  */
13445c51f124SMoriah Waterland int
is_mounted(char * path,uint32_t * fsys_value)1345*44da9c13SSimon Klinkert is_mounted(char *path, uint32_t *fsys_value)
13465c51f124SMoriah Waterland {
13475c51f124SMoriah Waterland 	if (*fsys_value == BADFSYS)
13485c51f124SMoriah Waterland 		*fsys_value = fsys(path);
13495c51f124SMoriah Waterland 
13505c51f124SMoriah Waterland 	return (is_mounted_n(*fsys_value));
13515c51f124SMoriah Waterland }
13525c51f124SMoriah Waterland 
13535c51f124SMoriah Waterland /*
13545c51f124SMoriah Waterland  * is_fs_writeable - given a cfent entry, return 1
13555c51f124SMoriah Waterland  *	if it's writeable, 0 if read-only.
13565c51f124SMoriah Waterland  *
13575c51f124SMoriah Waterland  *	Note: Upon exit, a valid fsys() is guaranteed. This is
13585c51f124SMoriah Waterland  *	an interface requirement.
13595c51f124SMoriah Waterland  */
13605c51f124SMoriah Waterland int
is_fs_writeable(char * path,uint32_t * fsys_value)1361*44da9c13SSimon Klinkert is_fs_writeable(char *path, uint32_t *fsys_value)
13625c51f124SMoriah Waterland {
13635c51f124SMoriah Waterland 	if (*fsys_value == BADFSYS)
13645c51f124SMoriah Waterland 		*fsys_value = fsys(path);
13655c51f124SMoriah Waterland 
13665c51f124SMoriah Waterland 	return (is_fs_writeable_n(*fsys_value));
13675c51f124SMoriah Waterland }
13685c51f124SMoriah Waterland 
13695c51f124SMoriah Waterland /*
13705c51f124SMoriah Waterland  * is_remote_fs - given a cfent entry, return 1
13715c51f124SMoriah Waterland  *	if it's a remote filesystem, 0 if local.
13725c51f124SMoriah Waterland  *
13735c51f124SMoriah Waterland  *	Also Note: Upon exit, a valid fsys() is guaranteed. This is
13745c51f124SMoriah Waterland  *	an interface requirement.
13755c51f124SMoriah Waterland  */
13765c51f124SMoriah Waterland int
is_remote_fs(char * path,uint32_t * fsys_value)1377*44da9c13SSimon Klinkert is_remote_fs(char *path, uint32_t *fsys_value)
13785c51f124SMoriah Waterland {
13795c51f124SMoriah Waterland 	if (*fsys_value == BADFSYS)
13805c51f124SMoriah Waterland 		*fsys_value = fsys(path);
13815c51f124SMoriah Waterland 
13825c51f124SMoriah Waterland 	return (is_remote_fs_n(*fsys_value));
13835c51f124SMoriah Waterland }
13845c51f124SMoriah Waterland 
13855c51f124SMoriah Waterland /*
13865c51f124SMoriah Waterland  * This function returns the served status of the filesystem. Served means a
13875c51f124SMoriah Waterland  * client is getting this file from a server and it is not writeable by the
13885c51f124SMoriah Waterland  * client. It has nothing to do with whether or not this particular operation
13895c51f124SMoriah Waterland  * (eg: pkgadd or pkgrm) will be writing to it.
13905c51f124SMoriah Waterland  */
13915c51f124SMoriah Waterland int
is_served(char * path,uint32_t * fsys_value)1392*44da9c13SSimon Klinkert is_served(char *path, uint32_t *fsys_value)
13935c51f124SMoriah Waterland {
13945c51f124SMoriah Waterland 	if (*fsys_value == BADFSYS)
13955c51f124SMoriah Waterland 		*fsys_value = fsys(path);
13965c51f124SMoriah Waterland 
13975c51f124SMoriah Waterland 	return (is_served_n(*fsys_value));
13985c51f124SMoriah Waterland }
13995c51f124SMoriah Waterland 
14005c51f124SMoriah Waterland /*
14015c51f124SMoriah Waterland  * get_remote_path - given a filesystem table index, return the
14025c51f124SMoriah Waterland  *	path of the filesystem on the remote system.  Otherwise,
14035c51f124SMoriah Waterland  *	return NULL if it's a local filesystem.
14045c51f124SMoriah Waterland  */
14055c51f124SMoriah Waterland char *
get_remote_path(uint32_t n)1406*44da9c13SSimon Klinkert get_remote_path(uint32_t n)
14075c51f124SMoriah Waterland {
14085c51f124SMoriah Waterland 	char	*p;
14095c51f124SMoriah Waterland 
14105c51f124SMoriah Waterland 	if (!is_remote_fs_n(n))
14115c51f124SMoriah Waterland 		return (NULL); 	/* local */
14125c51f124SMoriah Waterland 	p = strchr(fs_tab[n]->remote_name, ':');
14135c51f124SMoriah Waterland 	if (!p)
14145c51f124SMoriah Waterland 		p = fs_tab[n]->remote_name; 	/* Loopback */
14155c51f124SMoriah Waterland 	else
14165c51f124SMoriah Waterland 		p++; 	/* remote */
14175c51f124SMoriah Waterland 	return (p);
14185c51f124SMoriah Waterland }
14195c51f124SMoriah Waterland 
14205c51f124SMoriah Waterland /*
14215c51f124SMoriah Waterland  * get_mount_point - given a filesystem table index, return the
14225c51f124SMoriah Waterland  *	path of the mount point.  Otherwise,
14235c51f124SMoriah Waterland  *	return NULL if it's a local filesystem.
14245c51f124SMoriah Waterland  */
14255c51f124SMoriah Waterland char *
get_mount_point(uint32_t n)1426*44da9c13SSimon Klinkert get_mount_point(uint32_t n)
14275c51f124SMoriah Waterland {
14285c51f124SMoriah Waterland 	if (!is_remote_fs_n(n))
14295c51f124SMoriah Waterland 		return (NULL); 	/* local */
14305c51f124SMoriah Waterland 	return (fs_tab[n]->name);
14315c51f124SMoriah Waterland }
14325c51f124SMoriah Waterland 
14335c51f124SMoriah Waterland struct fstable *
get_fs_entry(uint32_t n)1434*44da9c13SSimon Klinkert get_fs_entry(uint32_t n)
14355c51f124SMoriah Waterland {
14365c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
14375c51f124SMoriah Waterland 		return (NULL);
14385c51f124SMoriah Waterland 	} else if (n >= fs_tab_used) {
14395c51f124SMoriah Waterland 		return (NULL);
14405c51f124SMoriah Waterland 	} else {
14415c51f124SMoriah Waterland 		return (fs_tab[n]);
14425c51f124SMoriah Waterland 	}
14435c51f124SMoriah Waterland }
1444