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