xref: /onnv-gate/usr/src/cmd/svr4pkg/libinst/mntinfo.c (revision 10638:5d19a597329d)
19781SMoriah.Waterland@Sun.COM /*
29781SMoriah.Waterland@Sun.COM  * CDDL HEADER START
39781SMoriah.Waterland@Sun.COM  *
49781SMoriah.Waterland@Sun.COM  * The contents of this file are subject to the terms of the
59781SMoriah.Waterland@Sun.COM  * Common Development and Distribution License (the "License").
69781SMoriah.Waterland@Sun.COM  * You may not use this file except in compliance with the License.
79781SMoriah.Waterland@Sun.COM  *
89781SMoriah.Waterland@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99781SMoriah.Waterland@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109781SMoriah.Waterland@Sun.COM  * See the License for the specific language governing permissions
119781SMoriah.Waterland@Sun.COM  * and limitations under the License.
129781SMoriah.Waterland@Sun.COM  *
139781SMoriah.Waterland@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149781SMoriah.Waterland@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159781SMoriah.Waterland@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169781SMoriah.Waterland@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179781SMoriah.Waterland@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189781SMoriah.Waterland@Sun.COM  *
199781SMoriah.Waterland@Sun.COM  * CDDL HEADER END
209781SMoriah.Waterland@Sun.COM  */
219781SMoriah.Waterland@Sun.COM 
229781SMoriah.Waterland@Sun.COM /*
239869SCasper.Dik@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
249781SMoriah.Waterland@Sun.COM  * Use is subject to license terms.
259781SMoriah.Waterland@Sun.COM  */
269781SMoriah.Waterland@Sun.COM 
279781SMoriah.Waterland@Sun.COM 
289781SMoriah.Waterland@Sun.COM /*
299781SMoriah.Waterland@Sun.COM  * System includes
309781SMoriah.Waterland@Sun.COM  */
319781SMoriah.Waterland@Sun.COM 
329781SMoriah.Waterland@Sun.COM #include <stdio.h>
339781SMoriah.Waterland@Sun.COM #include <limits.h>
349781SMoriah.Waterland@Sun.COM #include <errno.h>
359781SMoriah.Waterland@Sun.COM #include <stdlib.h>
369781SMoriah.Waterland@Sun.COM #include <unistd.h>
37*10638SJan.Kryl@Sun.COM #include <libgen.h>
389781SMoriah.Waterland@Sun.COM #include <string.h>
399781SMoriah.Waterland@Sun.COM #include <wait.h>
409781SMoriah.Waterland@Sun.COM #include <signal.h>
419781SMoriah.Waterland@Sun.COM #include <malloc.h>
429781SMoriah.Waterland@Sun.COM #include <sys/types.h>
439781SMoriah.Waterland@Sun.COM #include <sys/mount.h>
449781SMoriah.Waterland@Sun.COM #include <sys/stat.h>
459781SMoriah.Waterland@Sun.COM #include <fcntl.h>
469781SMoriah.Waterland@Sun.COM #include <sys/systeminfo.h>
479781SMoriah.Waterland@Sun.COM #include <pkgstrct.h>
489781SMoriah.Waterland@Sun.COM #include <pkginfo.h>
499781SMoriah.Waterland@Sun.COM #include <locale.h>
509781SMoriah.Waterland@Sun.COM #include <libintl.h>
519781SMoriah.Waterland@Sun.COM 
529781SMoriah.Waterland@Sun.COM #include <sys/mnttab.h>
539781SMoriah.Waterland@Sun.COM #include <sys/mntent.h>
549781SMoriah.Waterland@Sun.COM #include <sys/vfstab.h>
559781SMoriah.Waterland@Sun.COM 
569781SMoriah.Waterland@Sun.COM /*
579781SMoriah.Waterland@Sun.COM  * consolidation pkg command library includes
589781SMoriah.Waterland@Sun.COM  */
599781SMoriah.Waterland@Sun.COM 
609781SMoriah.Waterland@Sun.COM #include <pkglib.h>
619781SMoriah.Waterland@Sun.COM 
629781SMoriah.Waterland@Sun.COM /*
639781SMoriah.Waterland@Sun.COM  * local pkg command library includes
649781SMoriah.Waterland@Sun.COM  */
659781SMoriah.Waterland@Sun.COM 
669781SMoriah.Waterland@Sun.COM #include "install.h"
679781SMoriah.Waterland@Sun.COM #include "libinst.h"
689781SMoriah.Waterland@Sun.COM #include "libadm.h"
699781SMoriah.Waterland@Sun.COM #include "messages.h"
709781SMoriah.Waterland@Sun.COM 
719781SMoriah.Waterland@Sun.COM extern char **environ;
729781SMoriah.Waterland@Sun.COM 
739781SMoriah.Waterland@Sun.COM static int match_mount;		/* This holds the mount of interest. */
749781SMoriah.Waterland@Sun.COM 
759781SMoriah.Waterland@Sun.COM int	fs_tab_used  = 0;
769781SMoriah.Waterland@Sun.COM int	fs_tab_alloc = 0;
779781SMoriah.Waterland@Sun.COM static int	fs_list = -1;
789781SMoriah.Waterland@Sun.COM 
799781SMoriah.Waterland@Sun.COM struct	fstable	**fs_tab = NULL;
809781SMoriah.Waterland@Sun.COM 
819781SMoriah.Waterland@Sun.COM #define	PKGDBROOT	"/var/sadm"
829781SMoriah.Waterland@Sun.COM #define	MOUNT		"/sbin/mount"
839781SMoriah.Waterland@Sun.COM #define	UMOUNT		"/sbin/umount"
849781SMoriah.Waterland@Sun.COM 
859781SMoriah.Waterland@Sun.COM #define	setmntent	fopen
869781SMoriah.Waterland@Sun.COM #define	endmntent	fclose
879781SMoriah.Waterland@Sun.COM #define	MOUNT_TABLE	MNTTAB
889781SMoriah.Waterland@Sun.COM 
899781SMoriah.Waterland@Sun.COM /* returned by already_mounted() */
909781SMoriah.Waterland@Sun.COM #define	MNT_NOT		0
919781SMoriah.Waterland@Sun.COM #define	MNT_EXACT	1
929781SMoriah.Waterland@Sun.COM #define	MNT_AVAIL	2
939781SMoriah.Waterland@Sun.COM 
949781SMoriah.Waterland@Sun.COM /* used with is_remote_src() */
959781SMoriah.Waterland@Sun.COM #define	NOT_REMOTE	0
969781SMoriah.Waterland@Sun.COM #define	REAL_REMOTE	1
979781SMoriah.Waterland@Sun.COM #define	SELF_SERVE	2
989781SMoriah.Waterland@Sun.COM 
999781SMoriah.Waterland@Sun.COM /*
1009781SMoriah.Waterland@Sun.COM  * Due to /etc/mnttab files containing entries for multiple nfs hosts
1019781SMoriah.Waterland@Sun.COM  * HOST_NM_LN needs to be accommodating. The recommended value in the sysinfo
1029781SMoriah.Waterland@Sun.COM  * man page of 257 needs to be expanded. See bugid 4076513.
1039781SMoriah.Waterland@Sun.COM  * 1024 chars is defined in the mnttab.h header as the max size of an entry.
1049781SMoriah.Waterland@Sun.COM  */
1059781SMoriah.Waterland@Sun.COM 
1069781SMoriah.Waterland@Sun.COM #define	HOST_NM_LN	MNT_LINE_MAX
1079781SMoriah.Waterland@Sun.COM 
1089781SMoriah.Waterland@Sun.COM /* These cachefs definitions should be in mntent.h. Maybe some day. */
1099781SMoriah.Waterland@Sun.COM #define	MNTTYPE_CFS		"cachefs"
1109781SMoriah.Waterland@Sun.COM #define	MNTOPT_BACKFSTYPE	"backfstype"
1119781SMoriah.Waterland@Sun.COM #define	MNTTYPE_AUTO		"autofs"
1129781SMoriah.Waterland@Sun.COM 
1139781SMoriah.Waterland@Sun.COM /*
1149781SMoriah.Waterland@Sun.COM  * Utilities for getting filesystem information from the mount table.
1159781SMoriah.Waterland@Sun.COM  *
1169781SMoriah.Waterland@Sun.COM  * Note: vanilla SVr4 code (pkginstall/dockspace.c) used the output from
1179781SMoriah.Waterland@Sun.COM  * popen() on the "/etc/mount" command.  However, we need to get more
1189781SMoriah.Waterland@Sun.COM  * information about mounted filesystems, so we use the C interfaces to
1199781SMoriah.Waterland@Sun.COM  * the mount table, which also happens to be much faster than running
1209781SMoriah.Waterland@Sun.COM  * another process.  Since several of the pkg commands need access to the
1219781SMoriah.Waterland@Sun.COM  * the code has been placed here, to be included in the libinst library.
1229781SMoriah.Waterland@Sun.COM  */
1239781SMoriah.Waterland@Sun.COM 
1249781SMoriah.Waterland@Sun.COM #define	ALLOC_CHUNK	30
1259781SMoriah.Waterland@Sun.COM 
1269781SMoriah.Waterland@Sun.COM /*
1279781SMoriah.Waterland@Sun.COM  * fs_tab_ent_comp -	compare fstable entries first by length in reverse
1289781SMoriah.Waterland@Sun.COM  *			order, then alphabetically.
1299781SMoriah.Waterland@Sun.COM  */
1309781SMoriah.Waterland@Sun.COM static int
fs_tab_ent_comp(const void * e1,const void * e2)1319781SMoriah.Waterland@Sun.COM fs_tab_ent_comp(const void *e1, const void *e2)
1329781SMoriah.Waterland@Sun.COM {
1339781SMoriah.Waterland@Sun.COM 	struct fstable	*fs1 = *((struct fstable **)e1);
1349781SMoriah.Waterland@Sun.COM 	struct fstable	*fs2 = *((struct fstable **)e2);
1359781SMoriah.Waterland@Sun.COM 
1369781SMoriah.Waterland@Sun.COM 	if (fs1->namlen == fs2->namlen)
1379781SMoriah.Waterland@Sun.COM 		return (strcmp(fs1->name, fs2->name));
1389781SMoriah.Waterland@Sun.COM 	else
1399781SMoriah.Waterland@Sun.COM 		return (fs2->namlen - fs1->namlen);
1409781SMoriah.Waterland@Sun.COM }
1419781SMoriah.Waterland@Sun.COM 
1429781SMoriah.Waterland@Sun.COM /*
1439781SMoriah.Waterland@Sun.COM  * This determines if the source of the mount is from another host. If it's
1449781SMoriah.Waterland@Sun.COM  * from this host, then it might be writable. This returns NOT_REMOTE if it's
1459781SMoriah.Waterland@Sun.COM  * pure local, REAL_REMOTE if it's being served from another host and
1469781SMoriah.Waterland@Sun.COM  * SELF_SERVE if it's being served by the current host.
1479781SMoriah.Waterland@Sun.COM  */
1489781SMoriah.Waterland@Sun.COM static int
is_remote_src(char * source)1499781SMoriah.Waterland@Sun.COM is_remote_src(char *source)
1509781SMoriah.Waterland@Sun.COM {
1519781SMoriah.Waterland@Sun.COM 	static char host_name[HOST_NM_LN];
1529781SMoriah.Waterland@Sun.COM 	char source_host[HOST_NM_LN], *src_ptr, *src_host_ptr;
1539781SMoriah.Waterland@Sun.COM 	static int hn_len;
1549781SMoriah.Waterland@Sun.COM 
1559781SMoriah.Waterland@Sun.COM 	if (hn_len == 0) {
1569781SMoriah.Waterland@Sun.COM 		/* Find out what host this is. */
1579781SMoriah.Waterland@Sun.COM 		(void) sysinfo(SI_HOSTNAME, host_name, HOST_NM_LN);
1589781SMoriah.Waterland@Sun.COM 		hn_len = strlen(host_name);
1599781SMoriah.Waterland@Sun.COM 	}
1609781SMoriah.Waterland@Sun.COM 
1619781SMoriah.Waterland@Sun.COM 	if (source[0] == '/')
1629781SMoriah.Waterland@Sun.COM 		return (NOT_REMOTE);	/* No server name, so it's local. */
1639781SMoriah.Waterland@Sun.COM 
1649781SMoriah.Waterland@Sun.COM 	if (strchr(source, ':') == NULL)
1659781SMoriah.Waterland@Sun.COM 		return (NOT_REMOTE);	/* it's a floppy disk or something */
1669781SMoriah.Waterland@Sun.COM 
1679781SMoriah.Waterland@Sun.COM 	src_ptr = source;
1689781SMoriah.Waterland@Sun.COM 	src_host_ptr = source_host;
1699781SMoriah.Waterland@Sun.COM 
1709781SMoriah.Waterland@Sun.COM 	/* Scan to the end of the hostname (find the ":"). */
1719781SMoriah.Waterland@Sun.COM 	while (*src_ptr != ':')
1729781SMoriah.Waterland@Sun.COM 		*src_host_ptr++ = *src_ptr++;
1739781SMoriah.Waterland@Sun.COM 	*src_host_ptr = '\0';
1749781SMoriah.Waterland@Sun.COM 
1759869SCasper.Dik@Sun.COM 	/* Multiple hosts: failover with multiple servers; this is remote. */
1769869SCasper.Dik@Sun.COM 	if (strchr(source_host, ',') != NULL)
1779869SCasper.Dik@Sun.COM 		return (REAL_REMOTE);
1789869SCasper.Dik@Sun.COM 
1799781SMoriah.Waterland@Sun.COM 	if (strncmp(source, host_name, hn_len) == 0 &&
1809781SMoriah.Waterland@Sun.COM 	    *(source+hn_len) == ':' || is_local_host(source_host))
1819781SMoriah.Waterland@Sun.COM 		return (SELF_SERVE);	/* Exporting from itself, it's local. */
1829781SMoriah.Waterland@Sun.COM 
1839781SMoriah.Waterland@Sun.COM 	return (REAL_REMOTE);
1849781SMoriah.Waterland@Sun.COM }
1859781SMoriah.Waterland@Sun.COM 
1869781SMoriah.Waterland@Sun.COM /*
1879781SMoriah.Waterland@Sun.COM  * This determines if an apparently writeable filesystem is really writeable
1889781SMoriah.Waterland@Sun.COM  * or if it's been shared over the network with root-restrictive options.
1899781SMoriah.Waterland@Sun.COM  */
1909781SMoriah.Waterland@Sun.COM static int
really_write(char * mountpt)1919781SMoriah.Waterland@Sun.COM really_write(char *mountpt)
1929781SMoriah.Waterland@Sun.COM {
1939781SMoriah.Waterland@Sun.COM 	char testfile[PATH_MAX];
1949781SMoriah.Waterland@Sun.COM 	int fd, retval = 0;
1959781SMoriah.Waterland@Sun.COM 	struct stat status;
1969781SMoriah.Waterland@Sun.COM 
1979781SMoriah.Waterland@Sun.COM 	(void) snprintf(testfile, sizeof (testfile), "%s/testXXXXXX", mountpt);
1989781SMoriah.Waterland@Sun.COM 
1999781SMoriah.Waterland@Sun.COM 	if (mktemp(testfile) == NULL)
2009781SMoriah.Waterland@Sun.COM 		return (0);	/* may as well be read-only */
2019781SMoriah.Waterland@Sun.COM 	/* LINTED do not use creat(); use open(path,... */
2029781SMoriah.Waterland@Sun.COM 	else if ((fd = creat(testfile, 0777)) == -1)
2039781SMoriah.Waterland@Sun.COM 		return (0);	/* can't write */
2049781SMoriah.Waterland@Sun.COM 	else if (fstat(fd, &status) == -1)
2059781SMoriah.Waterland@Sun.COM 		retval = 0;	/* may as well be read-only */
2069781SMoriah.Waterland@Sun.COM 	else if (status.st_uid != 0)
2079781SMoriah.Waterland@Sun.COM 		retval = 0;	/* too many restrictions */
2089781SMoriah.Waterland@Sun.COM 	else
2099781SMoriah.Waterland@Sun.COM 		retval = 1;
2109781SMoriah.Waterland@Sun.COM 
2119781SMoriah.Waterland@Sun.COM 	(void) close(fd);
2129781SMoriah.Waterland@Sun.COM 	(void) unlink(testfile);
2139781SMoriah.Waterland@Sun.COM 
2149781SMoriah.Waterland@Sun.COM 	return (retval);
2159781SMoriah.Waterland@Sun.COM }
2169781SMoriah.Waterland@Sun.COM 
2179781SMoriah.Waterland@Sun.COM /* This returns the hostname portion of a remote path. */
2189781SMoriah.Waterland@Sun.COM char *
get_server_host(short n)2199781SMoriah.Waterland@Sun.COM get_server_host(short n)
2209781SMoriah.Waterland@Sun.COM {
2219781SMoriah.Waterland@Sun.COM 	static char hostname[HOST_NM_LN], *host_end;
2229781SMoriah.Waterland@Sun.COM 
2239781SMoriah.Waterland@Sun.COM 	if (fs_tab_used == 0) {
2249781SMoriah.Waterland@Sun.COM 		return ("unknown source");
2259781SMoriah.Waterland@Sun.COM 	}
2269781SMoriah.Waterland@Sun.COM 
2279781SMoriah.Waterland@Sun.COM 	if (n >= 0 && n < fs_tab_used) {
2289781SMoriah.Waterland@Sun.COM 		(void) strcpy(hostname, fs_tab[n]->remote_name);
2299781SMoriah.Waterland@Sun.COM 		if ((host_end = strchr(hostname, ':')) == NULL) {
2309781SMoriah.Waterland@Sun.COM 			if ((strcmp(fs_tab[n]->fstype, MNTTYPE_AUTO)) == NULL)
2319781SMoriah.Waterland@Sun.COM 				return ("automounter");
2329781SMoriah.Waterland@Sun.COM 			else
2339781SMoriah.Waterland@Sun.COM 				return (fs_tab[n]->fstype);
2349781SMoriah.Waterland@Sun.COM 		} else {
2359781SMoriah.Waterland@Sun.COM 			*host_end = '\0';
2369781SMoriah.Waterland@Sun.COM 			return (hostname);
2379781SMoriah.Waterland@Sun.COM 		}
2389781SMoriah.Waterland@Sun.COM 	}
2399781SMoriah.Waterland@Sun.COM 
2409781SMoriah.Waterland@Sun.COM 	return ("unknown source");
2419781SMoriah.Waterland@Sun.COM }
2429781SMoriah.Waterland@Sun.COM 
2439781SMoriah.Waterland@Sun.COM /*
2449781SMoriah.Waterland@Sun.COM  * This pulls the path out of a hostpath which may be of the form host:path
2459781SMoriah.Waterland@Sun.COM  * where path is an absolute path. NOTE: If path turns out to be relative,
2469781SMoriah.Waterland@Sun.COM  * this returns NULL.
2479781SMoriah.Waterland@Sun.COM  */
2489781SMoriah.Waterland@Sun.COM static char *
path_part(char * hostpath)2499781SMoriah.Waterland@Sun.COM path_part(char *hostpath)
2509781SMoriah.Waterland@Sun.COM {
2519781SMoriah.Waterland@Sun.COM 	char *host_end;
2529781SMoriah.Waterland@Sun.COM 
2539781SMoriah.Waterland@Sun.COM 	if ((host_end = strchr(hostpath, ':')) == NULL && hostpath[0] == '/')
2549781SMoriah.Waterland@Sun.COM 		return (hostpath);	/* It's already legit. */
2559781SMoriah.Waterland@Sun.COM 
2569781SMoriah.Waterland@Sun.COM 	if (*(host_end+1) == '/')
2579781SMoriah.Waterland@Sun.COM 		return (host_end+1);	/* Here's the path part. */
2589781SMoriah.Waterland@Sun.COM 
2599781SMoriah.Waterland@Sun.COM 	return (NULL);
2609781SMoriah.Waterland@Sun.COM }
2619781SMoriah.Waterland@Sun.COM 
2629781SMoriah.Waterland@Sun.COM /*
2639781SMoriah.Waterland@Sun.COM  * This scans the filesystems already mounted to see if this remote mount is
2649781SMoriah.Waterland@Sun.COM  * already in place on the server. This scans the fs_tab for a remote_name
2659781SMoriah.Waterland@Sun.COM  * exactly matching the client's. It stores the current entry number
2669781SMoriah.Waterland@Sun.COM  * corresponding to this mount in the static match_mount.
2679781SMoriah.Waterland@Sun.COM  *
2689781SMoriah.Waterland@Sun.COM  * Returns:
2699781SMoriah.Waterland@Sun.COM  *	MNT_NOT		Couldn't find it.
2709781SMoriah.Waterland@Sun.COM  *	MNT_EXACT	This has actually been manually mounted for us
2719781SMoriah.Waterland@Sun.COM  *	MNT_AVAIL	This is mounted for the server, but needs to be
2729781SMoriah.Waterland@Sun.COM  *			loopback mounted from the client's perspective.
2739781SMoriah.Waterland@Sun.COM  */
2749781SMoriah.Waterland@Sun.COM static int
already_mounted(struct vfstab * vfs,int is_local_host,char * client_path,char * host_path)2759781SMoriah.Waterland@Sun.COM already_mounted(struct vfstab *vfs, int is_local_host, char *client_path,
2769781SMoriah.Waterland@Sun.COM     char *host_path)
2779781SMoriah.Waterland@Sun.COM {
2789781SMoriah.Waterland@Sun.COM 	int i;
2799781SMoriah.Waterland@Sun.COM 
2809781SMoriah.Waterland@Sun.COM 	match_mount = -1;
2819781SMoriah.Waterland@Sun.COM 
2829781SMoriah.Waterland@Sun.COM 	if (fs_tab_used == 0) {
2839781SMoriah.Waterland@Sun.COM 		return (MNT_NOT);
2849781SMoriah.Waterland@Sun.COM 	}
2859781SMoriah.Waterland@Sun.COM 
2869781SMoriah.Waterland@Sun.COM 	for (i = 0; i < fs_tab_used; i++) {
2879781SMoriah.Waterland@Sun.COM 		/*
2889781SMoriah.Waterland@Sun.COM 		 * Determine if this has been manually mounted exactly as we
2899781SMoriah.Waterland@Sun.COM 		 * require. Begin by finding a mount on our current
2909781SMoriah.Waterland@Sun.COM 		 * mountpoint.
2919781SMoriah.Waterland@Sun.COM 		 */
2929781SMoriah.Waterland@Sun.COM 		if (strcmp(fs_tab[i]->name, client_path) == 0) {
2939781SMoriah.Waterland@Sun.COM 			/*
2949781SMoriah.Waterland@Sun.COM 			 * Now see if it is really the same mount. This isn't
2959781SMoriah.Waterland@Sun.COM 			 * smart enough to find mounts on top of mounts, but
2969781SMoriah.Waterland@Sun.COM 			 * assuming there is no conspiracy to fool this
2979781SMoriah.Waterland@Sun.COM 			 * function, it will be good enough.
2989781SMoriah.Waterland@Sun.COM 			 */
2999781SMoriah.Waterland@Sun.COM 			if (is_local_host &&
3009781SMoriah.Waterland@Sun.COM 			    strcmp(fs_tab[i]->remote_name, host_path) == 0) {
3019781SMoriah.Waterland@Sun.COM 				match_mount = i;
3029781SMoriah.Waterland@Sun.COM 				return (MNT_EXACT);
3039781SMoriah.Waterland@Sun.COM 			}
3049781SMoriah.Waterland@Sun.COM 		}
3059781SMoriah.Waterland@Sun.COM 
3069781SMoriah.Waterland@Sun.COM 		/* Determine if this mount is available to the server. */
3079781SMoriah.Waterland@Sun.COM 		if (strcmp(fs_tab[i]->remote_name, vfs->vfs_special) == 0) {
3089781SMoriah.Waterland@Sun.COM 			match_mount = i;
3099781SMoriah.Waterland@Sun.COM 			return (MNT_AVAIL);
3109781SMoriah.Waterland@Sun.COM 		}
3119781SMoriah.Waterland@Sun.COM 	}
3129781SMoriah.Waterland@Sun.COM 	return (MNT_NOT);
3139781SMoriah.Waterland@Sun.COM }
3149781SMoriah.Waterland@Sun.COM 
3159781SMoriah.Waterland@Sun.COM /*
3169781SMoriah.Waterland@Sun.COM  * This function unmounts all of the loopback mounts created for the client.
3179781SMoriah.Waterland@Sun.COM  * If no client stuff is mounted, this is completely benign, it finds that
3189781SMoriah.Waterland@Sun.COM  * nothing is mounted up and returns. It returns "1" for unmounted everything
3199781SMoriah.Waterland@Sun.COM  * OK and "0" for failure.
3209781SMoriah.Waterland@Sun.COM  */
3219781SMoriah.Waterland@Sun.COM int
unmount_client()3229781SMoriah.Waterland@Sun.COM unmount_client()
3239781SMoriah.Waterland@Sun.COM {
3249781SMoriah.Waterland@Sun.COM 	int	errcode;
3259781SMoriah.Waterland@Sun.COM 	int	exit_no;
3269781SMoriah.Waterland@Sun.COM 	int	n;
3279781SMoriah.Waterland@Sun.COM 	int	retcode = 1;
3289781SMoriah.Waterland@Sun.COM 	int	status;
3299781SMoriah.Waterland@Sun.COM 	pid_t	pid;
3309781SMoriah.Waterland@Sun.COM 	pid_t	pid_return;
3319781SMoriah.Waterland@Sun.COM 
3329781SMoriah.Waterland@Sun.COM 	if (fs_tab_used == 0) {
3339781SMoriah.Waterland@Sun.COM 		return (1);
3349781SMoriah.Waterland@Sun.COM 	}
3359781SMoriah.Waterland@Sun.COM 
3369781SMoriah.Waterland@Sun.COM 	for (n = 0; n < fs_tab_used-1; n++) {
3379781SMoriah.Waterland@Sun.COM 		/* If the filesystem is mounted and this utility did it ... */
3389781SMoriah.Waterland@Sun.COM 		if (fs_tab[n]->cl_mounted && fs_tab[n]->srvr_map) {
3399781SMoriah.Waterland@Sun.COM 			char	*arg[3];
3409781SMoriah.Waterland@Sun.COM 
3419781SMoriah.Waterland@Sun.COM 			/* create arglist for umount command */
3429781SMoriah.Waterland@Sun.COM 
3439781SMoriah.Waterland@Sun.COM 			arg[0] = UMOUNT;
3449781SMoriah.Waterland@Sun.COM 			arg[1] = fs_tab[n]->name;
3459781SMoriah.Waterland@Sun.COM 			arg[2] = (char *)NULL;
3469781SMoriah.Waterland@Sun.COM 
3479781SMoriah.Waterland@Sun.COM 			/* flush standard i/o before creating new process */
3489781SMoriah.Waterland@Sun.COM 
3499781SMoriah.Waterland@Sun.COM 			(void) fflush(stderr);
3509781SMoriah.Waterland@Sun.COM 			(void) fflush(stdout);
3519781SMoriah.Waterland@Sun.COM 
3529781SMoriah.Waterland@Sun.COM 			/*
3539781SMoriah.Waterland@Sun.COM 			 * create new process to execute command in;
3549781SMoriah.Waterland@Sun.COM 			 * vfork is being used to avoid duplicating the parents
3559781SMoriah.Waterland@Sun.COM 			 * memory space - this means that the child process may
3569781SMoriah.Waterland@Sun.COM 			 * not modify any of the parents memory including the
3579781SMoriah.Waterland@Sun.COM 			 * standard i/o descriptors - all the child can do is
3589781SMoriah.Waterland@Sun.COM 			 * adjust interrupts and open files as a prelude to a
3599781SMoriah.Waterland@Sun.COM 			 * call to exec().
3609781SMoriah.Waterland@Sun.COM 			 */
3619781SMoriah.Waterland@Sun.COM 
3629781SMoriah.Waterland@Sun.COM 			pid = vfork();
3639781SMoriah.Waterland@Sun.COM 			if (pid < 0) {
3649781SMoriah.Waterland@Sun.COM 				/* fork failed! */
3659781SMoriah.Waterland@Sun.COM 
3669781SMoriah.Waterland@Sun.COM 				logerr(WRN_BAD_FORK, errno, strerror(errno));
3679781SMoriah.Waterland@Sun.COM 				retcode = 0;
3689781SMoriah.Waterland@Sun.COM 			} else if (pid > 0) {
3699781SMoriah.Waterland@Sun.COM 				/*
3709781SMoriah.Waterland@Sun.COM 				 * this is the parent process
3719781SMoriah.Waterland@Sun.COM 				 */
3729781SMoriah.Waterland@Sun.COM 
3739781SMoriah.Waterland@Sun.COM 				status = 0;
3749781SMoriah.Waterland@Sun.COM 				pid_return = waitpid(pid, &status, 0);
3759781SMoriah.Waterland@Sun.COM 
3769781SMoriah.Waterland@Sun.COM 				if (pid_return != pid) {
3779781SMoriah.Waterland@Sun.COM 					logerr(WRN_BAD_WAIT, pid, pid_return,
3789781SMoriah.Waterland@Sun.COM 						(unsigned long)status, errno,
3799781SMoriah.Waterland@Sun.COM 						strerror(errno));
3809781SMoriah.Waterland@Sun.COM 					retcode = 0;
3819781SMoriah.Waterland@Sun.COM 				}
3829781SMoriah.Waterland@Sun.COM 
3839781SMoriah.Waterland@Sun.COM 				/*
3849781SMoriah.Waterland@Sun.COM 				 * If the child was stopped or killed by a
3859781SMoriah.Waterland@Sun.COM 				 * signal or exied with any code but 0, we
3869781SMoriah.Waterland@Sun.COM 				 * assume the mount has failed.
3879781SMoriah.Waterland@Sun.COM 				 */
3889781SMoriah.Waterland@Sun.COM 
3899781SMoriah.Waterland@Sun.COM 				if (!WIFEXITED(status) ||
3909781SMoriah.Waterland@Sun.COM 				    (errcode = WEXITSTATUS(status))) {
3919781SMoriah.Waterland@Sun.COM 					retcode = 0;
3929781SMoriah.Waterland@Sun.COM 					logerr(WRN_FSTAB_UMOUNT,
3939781SMoriah.Waterland@Sun.COM 						fs_tab[n]->name, errcode);
3949781SMoriah.Waterland@Sun.COM 				} else {
3959781SMoriah.Waterland@Sun.COM 					fs_tab[n]->cl_mounted = 0;
3969781SMoriah.Waterland@Sun.COM 				}
3979781SMoriah.Waterland@Sun.COM 			} else {
3989781SMoriah.Waterland@Sun.COM 				/*
3999781SMoriah.Waterland@Sun.COM 				 * this is the child process
4009781SMoriah.Waterland@Sun.COM 				 */
4019781SMoriah.Waterland@Sun.COM 
4029781SMoriah.Waterland@Sun.COM 				int	i;
4039781SMoriah.Waterland@Sun.COM 
4049781SMoriah.Waterland@Sun.COM 				/* reset any signals to default */
4059781SMoriah.Waterland@Sun.COM 
4069781SMoriah.Waterland@Sun.COM 				for (i = 0; i < NSIG; i++) {
4079781SMoriah.Waterland@Sun.COM 					(void) sigset(i, SIG_DFL);
4089781SMoriah.Waterland@Sun.COM 				}
4099781SMoriah.Waterland@Sun.COM 
4109781SMoriah.Waterland@Sun.COM 				/*
4119781SMoriah.Waterland@Sun.COM 				 * Redirect output to /dev/null because the
4129781SMoriah.Waterland@Sun.COM 				 * umount error message may be confusing to
4139781SMoriah.Waterland@Sun.COM 				 * the user.
4149781SMoriah.Waterland@Sun.COM 				 */
4159781SMoriah.Waterland@Sun.COM 
4169781SMoriah.Waterland@Sun.COM 				i = open("/dev/null", O_WRONLY);
4179781SMoriah.Waterland@Sun.COM 				if (i >= 0) {
4189781SMoriah.Waterland@Sun.COM 					dup2(2, STDERR_FILENO);
4199781SMoriah.Waterland@Sun.COM 				}
4209781SMoriah.Waterland@Sun.COM 
4219781SMoriah.Waterland@Sun.COM 				/* close all file descriptors except stdio */
4229781SMoriah.Waterland@Sun.COM 
4239781SMoriah.Waterland@Sun.COM 				closefrom(3);
4249781SMoriah.Waterland@Sun.COM 
4259781SMoriah.Waterland@Sun.COM 				exit_no = execve(arg[0], arg, environ);
4269781SMoriah.Waterland@Sun.COM 				_exit(exit_no);
4279781SMoriah.Waterland@Sun.COM 			}
4289781SMoriah.Waterland@Sun.COM 		}
4299781SMoriah.Waterland@Sun.COM 	}
4309781SMoriah.Waterland@Sun.COM 
4319781SMoriah.Waterland@Sun.COM 	return (retcode);
4329781SMoriah.Waterland@Sun.COM }
4339781SMoriah.Waterland@Sun.COM 
4349781SMoriah.Waterland@Sun.COM /*
4359781SMoriah.Waterland@Sun.COM  * This function creates the necessary loopback mounts to emulate the client
4369781SMoriah.Waterland@Sun.COM  * configuration with respect to the server. If this is being run on a
4379781SMoriah.Waterland@Sun.COM  * standalone or the installation is actually to the local system, this call
4389781SMoriah.Waterland@Sun.COM  * is benign since srvr_map won't be set anywhere. It returns "1" for mounted
4399781SMoriah.Waterland@Sun.COM  * everything OK and "0" for failure.
4409781SMoriah.Waterland@Sun.COM  */
4419781SMoriah.Waterland@Sun.COM int
mount_client()4429781SMoriah.Waterland@Sun.COM mount_client()
4439781SMoriah.Waterland@Sun.COM {
4449781SMoriah.Waterland@Sun.COM 	int	errcode;
4459781SMoriah.Waterland@Sun.COM 	int	exit_no;
4469781SMoriah.Waterland@Sun.COM 	int	n;
4479781SMoriah.Waterland@Sun.COM 	int	retcode = 1;
4489781SMoriah.Waterland@Sun.COM 	int	status;
4499781SMoriah.Waterland@Sun.COM 	pid_t	pid;
4509781SMoriah.Waterland@Sun.COM 	pid_t	pid_return;
4519781SMoriah.Waterland@Sun.COM 
4529781SMoriah.Waterland@Sun.COM 	if (fs_tab_used == 0) {
4539781SMoriah.Waterland@Sun.COM 		return (1);
4549781SMoriah.Waterland@Sun.COM 	}
4559781SMoriah.Waterland@Sun.COM 
4569781SMoriah.Waterland@Sun.COM 	for (n = fs_tab_used-1; n >= 0; n--) {
4579781SMoriah.Waterland@Sun.COM 		/*
4589781SMoriah.Waterland@Sun.COM 		 * If the filesystem is mounted (meaning available) and the
4599781SMoriah.Waterland@Sun.COM 		 * apparent filesystem can be mapped to a local filesystem
4609781SMoriah.Waterland@Sun.COM 		 * AND the local filesystem is not the same as the target
4619781SMoriah.Waterland@Sun.COM 		 * filesystem, mount it.
4629781SMoriah.Waterland@Sun.COM 		 */
4639781SMoriah.Waterland@Sun.COM 		if (fs_tab[n]->mounted && fs_tab[n]->srvr_map) {
4649781SMoriah.Waterland@Sun.COM 			char	*arg[6];
4659781SMoriah.Waterland@Sun.COM 
4669781SMoriah.Waterland@Sun.COM 			/* create arglist for mount command */
4679781SMoriah.Waterland@Sun.COM 
4689781SMoriah.Waterland@Sun.COM 			arg[0] = MOUNT;
4699781SMoriah.Waterland@Sun.COM 			arg[1] = "-F";
4709781SMoriah.Waterland@Sun.COM 			arg[2] = "lofs";
4719781SMoriah.Waterland@Sun.COM 			arg[3] = fs_tab[n]->remote_name;
4729781SMoriah.Waterland@Sun.COM 			arg[4] = fs_tab[n]->name;
4739781SMoriah.Waterland@Sun.COM 			arg[5] = (char *)NULL;
4749781SMoriah.Waterland@Sun.COM 
4759781SMoriah.Waterland@Sun.COM 			/* flush standard i/o before creating new process */
4769781SMoriah.Waterland@Sun.COM 
4779781SMoriah.Waterland@Sun.COM 			(void) fflush(stderr);
4789781SMoriah.Waterland@Sun.COM 			(void) fflush(stdout);
4799781SMoriah.Waterland@Sun.COM 
4809781SMoriah.Waterland@Sun.COM 			/*
4819781SMoriah.Waterland@Sun.COM 			 * create new process to execute command in;
4829781SMoriah.Waterland@Sun.COM 			 * vfork is being used to avoid duplicating the parents
4839781SMoriah.Waterland@Sun.COM 			 * memory space - this means that the child process may
4849781SMoriah.Waterland@Sun.COM 			 * not modify any of the parents memory including the
4859781SMoriah.Waterland@Sun.COM 			 * standard i/o descriptors - all the child can do is
4869781SMoriah.Waterland@Sun.COM 			 * adjust interrupts and open files as a prelude to a
4879781SMoriah.Waterland@Sun.COM 			 * call to exec().
4889781SMoriah.Waterland@Sun.COM 			 */
4899781SMoriah.Waterland@Sun.COM 
4909781SMoriah.Waterland@Sun.COM 			pid = vfork();
4919781SMoriah.Waterland@Sun.COM 			if (pid < 0) {
4929781SMoriah.Waterland@Sun.COM 				/* fork failed! */
4939781SMoriah.Waterland@Sun.COM 
4949781SMoriah.Waterland@Sun.COM 				logerr(WRN_BAD_FORK, errno, strerror(errno));
4959781SMoriah.Waterland@Sun.COM 				retcode = 0;
4969781SMoriah.Waterland@Sun.COM 			} else if (pid > 0) {
4979781SMoriah.Waterland@Sun.COM 				/*
4989781SMoriah.Waterland@Sun.COM 				 * this is the parent process
4999781SMoriah.Waterland@Sun.COM 				 */
5009781SMoriah.Waterland@Sun.COM 
5019781SMoriah.Waterland@Sun.COM 				pid_return = waitpid(pid, &status, 0);
5029781SMoriah.Waterland@Sun.COM 
5039781SMoriah.Waterland@Sun.COM 				if (pid_return != pid) {
5049781SMoriah.Waterland@Sun.COM 					logerr(WRN_BAD_WAIT, pid, pid_return,
5059781SMoriah.Waterland@Sun.COM 						(unsigned long)status, errno,
5069781SMoriah.Waterland@Sun.COM 						strerror(errno));
5079781SMoriah.Waterland@Sun.COM 					retcode = 0;
5089781SMoriah.Waterland@Sun.COM 				}
5099781SMoriah.Waterland@Sun.COM 
5109781SMoriah.Waterland@Sun.COM 				/*
5119781SMoriah.Waterland@Sun.COM 				 * If the child was stopped or killed by a
5129781SMoriah.Waterland@Sun.COM 				 * signal or exied with any code but 0, we
5139781SMoriah.Waterland@Sun.COM 				 * assume the mount has failed.
5149781SMoriah.Waterland@Sun.COM 				 */
5159781SMoriah.Waterland@Sun.COM 
5169781SMoriah.Waterland@Sun.COM 				if (!WIFEXITED(status) ||
5179781SMoriah.Waterland@Sun.COM 				    (errcode = WEXITSTATUS(status))) {
5189781SMoriah.Waterland@Sun.COM 					retcode = 0;
5199781SMoriah.Waterland@Sun.COM 					fs_tab[n]->mnt_failed = 1;
5209781SMoriah.Waterland@Sun.COM 					logerr(WRN_FSTAB_MOUNT,
5219781SMoriah.Waterland@Sun.COM 					    fs_tab[n]->name, errcode);
5229781SMoriah.Waterland@Sun.COM 				} else {
5239781SMoriah.Waterland@Sun.COM 					fs_tab[n]->cl_mounted = 1;
5249781SMoriah.Waterland@Sun.COM 				}
5259781SMoriah.Waterland@Sun.COM 			} else {
5269781SMoriah.Waterland@Sun.COM 				/*
5279781SMoriah.Waterland@Sun.COM 				 * this is the child process
5289781SMoriah.Waterland@Sun.COM 				 */
5299781SMoriah.Waterland@Sun.COM 
5309781SMoriah.Waterland@Sun.COM 				int	i;
5319781SMoriah.Waterland@Sun.COM 
5329781SMoriah.Waterland@Sun.COM 				/* reset all signals to default */
5339781SMoriah.Waterland@Sun.COM 
5349781SMoriah.Waterland@Sun.COM 				for (i = 0; i < NSIG; i++) {
5359781SMoriah.Waterland@Sun.COM 					(void) sigset(i, SIG_DFL);
5369781SMoriah.Waterland@Sun.COM 				}
5379781SMoriah.Waterland@Sun.COM 
5389781SMoriah.Waterland@Sun.COM 				/*
5399781SMoriah.Waterland@Sun.COM 				 * Redirect output to /dev/null because the
5409781SMoriah.Waterland@Sun.COM 				 * mount error message may be confusing to
5419781SMoriah.Waterland@Sun.COM 				 * the user.
5429781SMoriah.Waterland@Sun.COM 				 */
5439781SMoriah.Waterland@Sun.COM 
5449781SMoriah.Waterland@Sun.COM 				i = open("/dev/null", O_WRONLY);
5459781SMoriah.Waterland@Sun.COM 				if (i >= 0) {
5469781SMoriah.Waterland@Sun.COM 					dup2(i, STDERR_FILENO);
5479781SMoriah.Waterland@Sun.COM 				}
5489781SMoriah.Waterland@Sun.COM 
5499781SMoriah.Waterland@Sun.COM 				/* close all file descriptors except stdio */
5509781SMoriah.Waterland@Sun.COM 
5519781SMoriah.Waterland@Sun.COM 				closefrom(3);
5529781SMoriah.Waterland@Sun.COM 
5539781SMoriah.Waterland@Sun.COM 				exit_no = execve(arg[0], arg, environ);
5549781SMoriah.Waterland@Sun.COM 				_exit(exit_no);
5559781SMoriah.Waterland@Sun.COM 				/*NOTREACHED*/
5569781SMoriah.Waterland@Sun.COM 			}
5579781SMoriah.Waterland@Sun.COM 		}
5589781SMoriah.Waterland@Sun.COM 	}
5599781SMoriah.Waterland@Sun.COM 	return (retcode);
5609781SMoriah.Waterland@Sun.COM }
5619781SMoriah.Waterland@Sun.COM 
5629781SMoriah.Waterland@Sun.COM /*
5639781SMoriah.Waterland@Sun.COM  * This function maps path, on a loopback filesystem, back to the real server
5649781SMoriah.Waterland@Sun.COM  * filesystem. fsys_value is the fs_tab[] entry to which the loopback'd path is
5659781SMoriah.Waterland@Sun.COM  * mapped. This returns a pointer to a static area. If the result is needed
5669781SMoriah.Waterland@Sun.COM  * for further processing, it should be strdup()'d or something.
5679781SMoriah.Waterland@Sun.COM  */
5689781SMoriah.Waterland@Sun.COM char *
server_map(char * path,short fsys_value)5699781SMoriah.Waterland@Sun.COM server_map(char *path, short fsys_value)
5709781SMoriah.Waterland@Sun.COM {
5719781SMoriah.Waterland@Sun.COM 	static char server_construction[PATH_MAX];
5729781SMoriah.Waterland@Sun.COM 
5739781SMoriah.Waterland@Sun.COM 	if (fs_tab_used == 0) {
5749781SMoriah.Waterland@Sun.COM 		(void) strcpy(server_construction, path);
5759781SMoriah.Waterland@Sun.COM 	} else if (fsys_value >= 0 && fsys_value < fs_tab_used) {
5769781SMoriah.Waterland@Sun.COM 		(void) snprintf(server_construction,
5779781SMoriah.Waterland@Sun.COM 			sizeof (server_construction),
5789781SMoriah.Waterland@Sun.COM 			"%s%s", fs_tab[fsys_value]->remote_name,
5799781SMoriah.Waterland@Sun.COM 			path+strlen(fs_tab[fsys_value]->name));
5809781SMoriah.Waterland@Sun.COM 	} else {
5819781SMoriah.Waterland@Sun.COM 		(void) strcpy(server_construction, path);
5829781SMoriah.Waterland@Sun.COM 	}
5839781SMoriah.Waterland@Sun.COM 
5849781SMoriah.Waterland@Sun.COM 	return (server_construction);
5859781SMoriah.Waterland@Sun.COM }
5869781SMoriah.Waterland@Sun.COM 
5879781SMoriah.Waterland@Sun.COM /* This function sets up the standard parts of the fs_tab. */
5889781SMoriah.Waterland@Sun.COM static struct fstable *
fs_tab_init(char * mountp,char * fstype)5899781SMoriah.Waterland@Sun.COM fs_tab_init(char *mountp, char *fstype)
5909781SMoriah.Waterland@Sun.COM {
5919781SMoriah.Waterland@Sun.COM 	struct fstable *nfte;
5929781SMoriah.Waterland@Sun.COM 
5939781SMoriah.Waterland@Sun.COM 	/* Create the array if necessary. */
5949781SMoriah.Waterland@Sun.COM 	if (fs_list == -1) {
5959781SMoriah.Waterland@Sun.COM 		fs_list = ar_create(ALLOC_CHUNK,
5969781SMoriah.Waterland@Sun.COM 		    (unsigned)sizeof (struct fstable),
5979781SMoriah.Waterland@Sun.COM 		    "filesystem mount data");
5989781SMoriah.Waterland@Sun.COM 		if (fs_list == -1) {
5999781SMoriah.Waterland@Sun.COM 			progerr(ERR_MALLOC, "fs_list", errno, strerror(errno));
6009781SMoriah.Waterland@Sun.COM 			return (NULL);
6019781SMoriah.Waterland@Sun.COM 		}
6029781SMoriah.Waterland@Sun.COM 	}
6039781SMoriah.Waterland@Sun.COM 
6049781SMoriah.Waterland@Sun.COM 	/*
6059781SMoriah.Waterland@Sun.COM 	 * Allocate an fstable entry for this mnttab entry.
6069781SMoriah.Waterland@Sun.COM 	 */
6079781SMoriah.Waterland@Sun.COM 	if ((nfte = *(struct fstable **)ar_next_avail(fs_list))
6089781SMoriah.Waterland@Sun.COM 	    == NULL) {
6099781SMoriah.Waterland@Sun.COM 		progerr(ERR_MALLOC, "nfte", errno, strerror(errno));
6109781SMoriah.Waterland@Sun.COM 		return (NULL);
6119781SMoriah.Waterland@Sun.COM 	}
6129781SMoriah.Waterland@Sun.COM 
6139781SMoriah.Waterland@Sun.COM 	/*
6149781SMoriah.Waterland@Sun.COM 	 * Point fs_tab at the head of the array again, since it may have
6159781SMoriah.Waterland@Sun.COM 	 * moved due to realloc in ar_next_avail(). If ar_next_avail() realizes
6169781SMoriah.Waterland@Sun.COM 	 * that there is no more room to grow the array, it reallocates the
6179781SMoriah.Waterland@Sun.COM 	 * array. Because we stored pointer to that array in fs_tab, we need
6189781SMoriah.Waterland@Sun.COM 	 * to make sure that it is updated as well.
6199781SMoriah.Waterland@Sun.COM 	 */
6209781SMoriah.Waterland@Sun.COM 	if ((fs_tab = (struct fstable **)ar_get_head(fs_list)) == NULL) {
6219781SMoriah.Waterland@Sun.COM 		progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno));
6229781SMoriah.Waterland@Sun.COM 		return (NULL);
6239781SMoriah.Waterland@Sun.COM 	}
6249781SMoriah.Waterland@Sun.COM 
6259781SMoriah.Waterland@Sun.COM 	/*
6269781SMoriah.Waterland@Sun.COM 	 * Get the length of the 'mount point' name.
6279781SMoriah.Waterland@Sun.COM 	 */
6289781SMoriah.Waterland@Sun.COM 	nfte->namlen = strlen(mountp);
6299781SMoriah.Waterland@Sun.COM 	/*
6309781SMoriah.Waterland@Sun.COM 	 * Allocate space for the 'mount point' name.
6319781SMoriah.Waterland@Sun.COM 	 */
6329781SMoriah.Waterland@Sun.COM 	if ((nfte->name = malloc(nfte->namlen+1)) == NULL) {
6339781SMoriah.Waterland@Sun.COM 		progerr(ERR_MALLOC, "name", errno, strerror(errno));
6349781SMoriah.Waterland@Sun.COM 		return (NULL);
6359781SMoriah.Waterland@Sun.COM 	}
6369781SMoriah.Waterland@Sun.COM 	(void) strcpy(nfte->name, mountp);
6379781SMoriah.Waterland@Sun.COM 
6389781SMoriah.Waterland@Sun.COM 	if ((nfte->fstype = malloc(strlen(fstype)+1)) == NULL) {
6399781SMoriah.Waterland@Sun.COM 		progerr(ERR_MALLOC, "fstype", errno, strerror(errno));
6409781SMoriah.Waterland@Sun.COM 		return (NULL);
6419781SMoriah.Waterland@Sun.COM 	}
6429781SMoriah.Waterland@Sun.COM 	(void) strcpy(nfte->fstype, fstype);
6439781SMoriah.Waterland@Sun.COM 
6449781SMoriah.Waterland@Sun.COM 	fs_tab_used++;
6459781SMoriah.Waterland@Sun.COM 
6469781SMoriah.Waterland@Sun.COM 	return (nfte);
6479781SMoriah.Waterland@Sun.COM }
6489781SMoriah.Waterland@Sun.COM 
6499781SMoriah.Waterland@Sun.COM /* This function frees all memory associated with the filesystem table. */
6509781SMoriah.Waterland@Sun.COM void
fs_tab_free(void)6519781SMoriah.Waterland@Sun.COM fs_tab_free(void)
6529781SMoriah.Waterland@Sun.COM {
6539781SMoriah.Waterland@Sun.COM 	int n;
6549781SMoriah.Waterland@Sun.COM 
6559781SMoriah.Waterland@Sun.COM 	if (fs_tab_used == 0) {
6569781SMoriah.Waterland@Sun.COM 		return;
6579781SMoriah.Waterland@Sun.COM 	}
6589781SMoriah.Waterland@Sun.COM 
6599781SMoriah.Waterland@Sun.COM 	for (n = 0; n < fs_tab_used; n++) {
6609781SMoriah.Waterland@Sun.COM 		free(fs_tab[n]->fstype);
6619781SMoriah.Waterland@Sun.COM 		free(fs_tab[n]->name);
6629781SMoriah.Waterland@Sun.COM 		free(fs_tab[n]->remote_name);
6639781SMoriah.Waterland@Sun.COM 	}
6649781SMoriah.Waterland@Sun.COM 
6659781SMoriah.Waterland@Sun.COM 	ar_free(fs_list);
6669781SMoriah.Waterland@Sun.COM }
6679781SMoriah.Waterland@Sun.COM 
6689781SMoriah.Waterland@Sun.COM /* This function scans a string of mount options for a specific keyword. */
6699781SMoriah.Waterland@Sun.COM static int
hasopt(char * options,char * keyword)6709781SMoriah.Waterland@Sun.COM hasopt(char *options, char *keyword)
6719781SMoriah.Waterland@Sun.COM {
6729781SMoriah.Waterland@Sun.COM 	char vfs_options[VFS_LINE_MAX], *optptr;
6739781SMoriah.Waterland@Sun.COM 
6749781SMoriah.Waterland@Sun.COM 	if (!options) {
6759781SMoriah.Waterland@Sun.COM 		(void) strcpy(vfs_options, "ro");
6769781SMoriah.Waterland@Sun.COM 	} else {
6779781SMoriah.Waterland@Sun.COM 		(void) strcpy(vfs_options, options);
6789781SMoriah.Waterland@Sun.COM 	}
6799781SMoriah.Waterland@Sun.COM 
6809781SMoriah.Waterland@Sun.COM 	while (optptr = strrchr(vfs_options, ',')) {
6819781SMoriah.Waterland@Sun.COM 		*optptr++ = '\0';
6829781SMoriah.Waterland@Sun.COM 
6839781SMoriah.Waterland@Sun.COM 		if (strcmp(optptr, keyword) == 0)
6849781SMoriah.Waterland@Sun.COM 			return (1);
6859781SMoriah.Waterland@Sun.COM 	}
6869781SMoriah.Waterland@Sun.COM 
6879781SMoriah.Waterland@Sun.COM 	/* Now deal with the remainder. */
6889781SMoriah.Waterland@Sun.COM 	if (strcmp(vfs_options, keyword) == 0)
6899781SMoriah.Waterland@Sun.COM 		return (1);
6909781SMoriah.Waterland@Sun.COM 
6919781SMoriah.Waterland@Sun.COM 	return (0);
6929781SMoriah.Waterland@Sun.COM }
6939781SMoriah.Waterland@Sun.COM 
6949781SMoriah.Waterland@Sun.COM /*
6959781SMoriah.Waterland@Sun.COM  * This function constructs a new filesystem table (fs_tab[]) entry based on
6969781SMoriah.Waterland@Sun.COM  * an /etc/mnttab entry. When it returns, the new entry has been inserted
6979781SMoriah.Waterland@Sun.COM  * into fs_tab[].
6989781SMoriah.Waterland@Sun.COM  */
6999781SMoriah.Waterland@Sun.COM static int
construct_mt(struct mnttab * mt)7009781SMoriah.Waterland@Sun.COM construct_mt(struct mnttab *mt)
7019781SMoriah.Waterland@Sun.COM {
7029781SMoriah.Waterland@Sun.COM 	struct	fstable	*nfte;
7039781SMoriah.Waterland@Sun.COM 
7049781SMoriah.Waterland@Sun.COM 	/*
7059781SMoriah.Waterland@Sun.COM 	 * Initialize fstable structure and make the standard entries.
7069781SMoriah.Waterland@Sun.COM 	 */
7079781SMoriah.Waterland@Sun.COM 	if ((nfte = fs_tab_init(mt->mnt_mountp, mt->mnt_fstype)) == NULL)
7089781SMoriah.Waterland@Sun.COM 		return (1);
7099781SMoriah.Waterland@Sun.COM 
7109869SCasper.Dik@Sun.COM 	/*
7119869SCasper.Dik@Sun.COM 	 * See if this is served from another host.
7129869SCasper.Dik@Sun.COM 	 * Testing the type is cheap; finding the hostname is not.
7139869SCasper.Dik@Sun.COM 	 * At this point, we're using the REAL mnttab; since we're not
7149869SCasper.Dik@Sun.COM 	 * allowed to mount ourself with "NFS", "NFS" must be remote.
7159869SCasper.Dik@Sun.COM 	 * The automount will translate "nfs:self" to a lofs mount.
7169869SCasper.Dik@Sun.COM 	 */
7179869SCasper.Dik@Sun.COM 	if (strcmp(mt->mnt_fstype, MNTTYPE_AUTO) == 0 ||
7189869SCasper.Dik@Sun.COM 	    strcmp(mt->mnt_fstype, MNTTYPE_NFS) == 0 ||
7199869SCasper.Dik@Sun.COM 	    is_remote_src(mt->mnt_special) == REAL_REMOTE)
7209781SMoriah.Waterland@Sun.COM 		nfte->remote = 1;
7219781SMoriah.Waterland@Sun.COM 	else
7229781SMoriah.Waterland@Sun.COM 		nfte->remote = 0;
7239781SMoriah.Waterland@Sun.COM 
7249781SMoriah.Waterland@Sun.COM 	/* It's mounted now (by definition), so we don't have to remap it. */
7259781SMoriah.Waterland@Sun.COM 	nfte->srvr_map = 0;
7269781SMoriah.Waterland@Sun.COM 	nfte->mounted = 1;
7279781SMoriah.Waterland@Sun.COM 
7289781SMoriah.Waterland@Sun.COM 	nfte->remote_name = strdup(mt->mnt_special);
7299781SMoriah.Waterland@Sun.COM 
7309781SMoriah.Waterland@Sun.COM 	/*
7319781SMoriah.Waterland@Sun.COM 	 * This checks the mount commands which establish the most
7329781SMoriah.Waterland@Sun.COM 	 * basic level of access. Later further tests may be
7339781SMoriah.Waterland@Sun.COM 	 * necessary to fully qualify this. We set this bit
7349781SMoriah.Waterland@Sun.COM 	 * preliminarily because we have access to the mount data
7359781SMoriah.Waterland@Sun.COM 	 * now.
7369781SMoriah.Waterland@Sun.COM 	 */
7379781SMoriah.Waterland@Sun.COM 	nfte->writeable = 0;	/* Assume read-only. */
7389781SMoriah.Waterland@Sun.COM 	if (hasmntopt(mt, MNTOPT_RO) == NULL) {
7399781SMoriah.Waterland@Sun.COM 		nfte->writeable = 1;
7409781SMoriah.Waterland@Sun.COM 		if (!(nfte->remote))
7419781SMoriah.Waterland@Sun.COM 			/*
7429781SMoriah.Waterland@Sun.COM 			 * There's no network involved, so this
7439781SMoriah.Waterland@Sun.COM 			 * assessment is confirmed.
7449781SMoriah.Waterland@Sun.COM 			 */
7459781SMoriah.Waterland@Sun.COM 			nfte->write_tested = 1;
7469781SMoriah.Waterland@Sun.COM 	} else
7479781SMoriah.Waterland@Sun.COM 		/* read-only is read-only */
7489781SMoriah.Waterland@Sun.COM 		nfte->write_tested = 1;
7499781SMoriah.Waterland@Sun.COM 
7509781SMoriah.Waterland@Sun.COM 	/* Is this coming to us from a server? */
7519781SMoriah.Waterland@Sun.COM 	if (nfte->remote && !(nfte->writeable))
7529781SMoriah.Waterland@Sun.COM 		nfte->served = 1;
7539781SMoriah.Waterland@Sun.COM 
7549781SMoriah.Waterland@Sun.COM 	return (0);
7559781SMoriah.Waterland@Sun.COM }
7569781SMoriah.Waterland@Sun.COM 
7579781SMoriah.Waterland@Sun.COM /*
7589781SMoriah.Waterland@Sun.COM  * This function modifies an existing fs_tab[] entry. It was found mounted up
7599781SMoriah.Waterland@Sun.COM  * exactly the way we would have mounted it in mount_client() only at the
7609781SMoriah.Waterland@Sun.COM  * time we didn't know it was for the client. Now we do, so we're setting the
7619781SMoriah.Waterland@Sun.COM  * various permissions to conform to the client view.
7629781SMoriah.Waterland@Sun.COM  */
7639781SMoriah.Waterland@Sun.COM static void
mod_existing(struct vfstab * vfsent,int fstab_entry,int is_remote)7649781SMoriah.Waterland@Sun.COM mod_existing(struct vfstab *vfsent, int fstab_entry, int is_remote)
7659781SMoriah.Waterland@Sun.COM {
7669781SMoriah.Waterland@Sun.COM 	/*
7679781SMoriah.Waterland@Sun.COM 	 * Establish whether the client will see this as served.
7689781SMoriah.Waterland@Sun.COM 	 */
7699781SMoriah.Waterland@Sun.COM 	if (is_remote && hasopt(vfsent->vfs_mntopts, MNTOPT_RO))
7709781SMoriah.Waterland@Sun.COM 		fs_tab[fstab_entry]->served = 1;
7719781SMoriah.Waterland@Sun.COM 
7729781SMoriah.Waterland@Sun.COM 	fs_tab[fstab_entry]->cl_mounted = 1;
7739781SMoriah.Waterland@Sun.COM }
7749781SMoriah.Waterland@Sun.COM 
7759781SMoriah.Waterland@Sun.COM /*
7769781SMoriah.Waterland@Sun.COM  * This function constructs a new fs_tab[] entry based on
7779781SMoriah.Waterland@Sun.COM  * an /etc/vfstab entry. When it returns, the new entry has been inserted
7789781SMoriah.Waterland@Sun.COM  * into fstab[].
7799781SMoriah.Waterland@Sun.COM  */
7809781SMoriah.Waterland@Sun.COM static int
construct_vfs(struct vfstab * vfsent,char * client_path,char * link_name,int is_remote,int mnt_stat)7819781SMoriah.Waterland@Sun.COM construct_vfs(struct vfstab *vfsent, char *client_path, char *link_name,
7829781SMoriah.Waterland@Sun.COM     int is_remote, int mnt_stat)
7839781SMoriah.Waterland@Sun.COM {
7849781SMoriah.Waterland@Sun.COM 	int use_link;
7859781SMoriah.Waterland@Sun.COM 	struct	fstable	*nfte;
7869781SMoriah.Waterland@Sun.COM 
7879781SMoriah.Waterland@Sun.COM 	if ((nfte = fs_tab_init(client_path, vfsent->vfs_fstype)) == NULL)
7889781SMoriah.Waterland@Sun.COM 		return (1);
7899781SMoriah.Waterland@Sun.COM 
7909781SMoriah.Waterland@Sun.COM 	nfte->remote = (is_remote == REAL_REMOTE);
7919781SMoriah.Waterland@Sun.COM 
7929781SMoriah.Waterland@Sun.COM 	/*
7939781SMoriah.Waterland@Sun.COM 	 * The file system mounted on the client may or may not be writeable.
7949781SMoriah.Waterland@Sun.COM 	 * So we hand it over to fsys() to evaluate. This will have the same
7959781SMoriah.Waterland@Sun.COM 	 * read/write attributes as the corresponding mounted filesystem.
7969781SMoriah.Waterland@Sun.COM 	 */
7979781SMoriah.Waterland@Sun.COM 	use_link = 0;
7989781SMoriah.Waterland@Sun.COM 	if (nfte->remote) {
7999781SMoriah.Waterland@Sun.COM 		/*
8009781SMoriah.Waterland@Sun.COM 		 * Deal here with mount points actually on a system remote
8019781SMoriah.Waterland@Sun.COM 		 * from the server.
8029781SMoriah.Waterland@Sun.COM 		 */
8039781SMoriah.Waterland@Sun.COM 		if (mnt_stat == MNT_NOT) {
8049781SMoriah.Waterland@Sun.COM 			/*
8059781SMoriah.Waterland@Sun.COM 			 * This filesystem isn't in the current mount table
8069781SMoriah.Waterland@Sun.COM 			 * meaning it isn't mounted, the current host can't
8079781SMoriah.Waterland@Sun.COM 			 * write to it and there's no point to mapping it for
8089781SMoriah.Waterland@Sun.COM 			 * the server.
8099781SMoriah.Waterland@Sun.COM 			 */
8109781SMoriah.Waterland@Sun.COM 			link_name = NULL;
8119781SMoriah.Waterland@Sun.COM 			nfte->mounted = 0;
8129781SMoriah.Waterland@Sun.COM 			nfte->srvr_map = 0;
8139781SMoriah.Waterland@Sun.COM 			nfte->writeable = 0;
8149781SMoriah.Waterland@Sun.COM 		} else {	/* It's MNT_AVAIL. */
8159781SMoriah.Waterland@Sun.COM 			/*
8169781SMoriah.Waterland@Sun.COM 			 * This filesystem is associated with a current
8179781SMoriah.Waterland@Sun.COM 			 * mountpoint. Since it's mounted, it needs to be
8189781SMoriah.Waterland@Sun.COM 			 * remapped and it is writable if the real mounted
8199781SMoriah.Waterland@Sun.COM 			 * filesystem is writeable.
8209781SMoriah.Waterland@Sun.COM 			 */
8219781SMoriah.Waterland@Sun.COM 			use_link = 1;
8229781SMoriah.Waterland@Sun.COM 			link_name = strdup(fs_tab[match_mount]->name);
8239781SMoriah.Waterland@Sun.COM 			nfte->mounted = 1;
8249781SMoriah.Waterland@Sun.COM 			nfte->srvr_map = 1;
8259781SMoriah.Waterland@Sun.COM 			nfte->writeable = fs_tab[match_mount]->writeable;
8269781SMoriah.Waterland@Sun.COM 			nfte->write_tested = fs_tab[match_mount]->write_tested;
8279781SMoriah.Waterland@Sun.COM 		}
8289781SMoriah.Waterland@Sun.COM 	} else {	/* local filesystem */
8299781SMoriah.Waterland@Sun.COM 		use_link = 1;
8309781SMoriah.Waterland@Sun.COM 		nfte->mounted = 1;
8319781SMoriah.Waterland@Sun.COM 		nfte->srvr_map = 1;
8329781SMoriah.Waterland@Sun.COM 		nfte->writeable = fs_tab[fsys(link_name)]->writeable;
8339781SMoriah.Waterland@Sun.COM 		nfte->write_tested = 1;
8349781SMoriah.Waterland@Sun.COM 	}
8359781SMoriah.Waterland@Sun.COM 
8369781SMoriah.Waterland@Sun.COM 	/*
8379781SMoriah.Waterland@Sun.COM 	 * Now we establish whether the client will see this as served.
8389781SMoriah.Waterland@Sun.COM 	 */
8399781SMoriah.Waterland@Sun.COM 	if (is_remote && hasopt(vfsent->vfs_mntopts, MNTOPT_RO))
8409781SMoriah.Waterland@Sun.COM 		nfte->served = 1;
8419781SMoriah.Waterland@Sun.COM 
8429781SMoriah.Waterland@Sun.COM 	if (use_link) {
8439781SMoriah.Waterland@Sun.COM 		nfte->remote_name = link_name;
8449781SMoriah.Waterland@Sun.COM 	} else {
8459781SMoriah.Waterland@Sun.COM 		nfte->remote_name = strdup(vfsent->vfs_special);
8469781SMoriah.Waterland@Sun.COM 	}
8479781SMoriah.Waterland@Sun.COM 
8489781SMoriah.Waterland@Sun.COM 	return (0);
8499781SMoriah.Waterland@Sun.COM }
8509781SMoriah.Waterland@Sun.COM 
8519781SMoriah.Waterland@Sun.COM /*
8529781SMoriah.Waterland@Sun.COM  * get_mntinfo - get the mount table, now dynamically allocated. Returns 0 if
8539781SMoriah.Waterland@Sun.COM  * no problem and 1 if there's a fatal error.
8549781SMoriah.Waterland@Sun.COM  */
8559781SMoriah.Waterland@Sun.COM int
get_mntinfo(int map_client,char * vfstab_file)8569781SMoriah.Waterland@Sun.COM get_mntinfo(int map_client, char *vfstab_file)
8579781SMoriah.Waterland@Sun.COM {
8589781SMoriah.Waterland@Sun.COM 	static 	char 	*rn = "/";
8599781SMoriah.Waterland@Sun.COM 	FILE		*pp;
8609781SMoriah.Waterland@Sun.COM 	struct	mnttab	mtbuf;
8619781SMoriah.Waterland@Sun.COM 	struct	mnttab	*mt = &mtbuf;
8629781SMoriah.Waterland@Sun.COM 	char		*install_root;
8639781SMoriah.Waterland@Sun.COM 	int 		is_remote;
8649781SMoriah.Waterland@Sun.COM 
8659781SMoriah.Waterland@Sun.COM 	/*
8669781SMoriah.Waterland@Sun.COM 	 * Open the mount table for the current host and establish a global
8679781SMoriah.Waterland@Sun.COM 	 * table that holds data about current mount status.
8689781SMoriah.Waterland@Sun.COM 	 */
8699781SMoriah.Waterland@Sun.COM 	if ((pp = setmntent(MOUNT_TABLE, "r")) == NULL) {
8709781SMoriah.Waterland@Sun.COM 		progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno));
8719781SMoriah.Waterland@Sun.COM 		return (1);
8729781SMoriah.Waterland@Sun.COM 	}
8739781SMoriah.Waterland@Sun.COM 
8749781SMoriah.Waterland@Sun.COM 	/*
8759781SMoriah.Waterland@Sun.COM 	 * First, review the mounted filesystems on the managing host. This
8769781SMoriah.Waterland@Sun.COM 	 * may also be the target host but we haven't decided that for sure
8779781SMoriah.Waterland@Sun.COM 	 * yet.
8789781SMoriah.Waterland@Sun.COM 	 */
8799781SMoriah.Waterland@Sun.COM 	while (!getmntent(pp, mt))
8809781SMoriah.Waterland@Sun.COM 		if (construct_mt(mt))
8819781SMoriah.Waterland@Sun.COM 			return (1);
8829781SMoriah.Waterland@Sun.COM 
8839781SMoriah.Waterland@Sun.COM 	(void) endmntent(pp);
8849781SMoriah.Waterland@Sun.COM 
8859781SMoriah.Waterland@Sun.COM 	/*
8869781SMoriah.Waterland@Sun.COM 	 * Now, we see if this installation is to a client. If it is, we scan
8879781SMoriah.Waterland@Sun.COM 	 * the client's vfstab to determine what filesystems are
8889781SMoriah.Waterland@Sun.COM 	 * inappropriate to write to. This simply adds the vfstab entries
8899781SMoriah.Waterland@Sun.COM 	 * representing what will be remote file systems for the client.
8909781SMoriah.Waterland@Sun.COM 	 * Everything that isn't remote to the client is already accounted
8919781SMoriah.Waterland@Sun.COM 	 * for in the fs_tab[] so far. If the remote filesystem is really on
8929781SMoriah.Waterland@Sun.COM 	 * this server, we will write through to the server from this client.
8939781SMoriah.Waterland@Sun.COM 	 */
8949781SMoriah.Waterland@Sun.COM 	install_root = get_inst_root();
8959781SMoriah.Waterland@Sun.COM 	if (install_root && strcmp(install_root, "/") != 0 && map_client) {
8969781SMoriah.Waterland@Sun.COM 		/* OK, this is a legitimate remote client. */
8979781SMoriah.Waterland@Sun.COM 		struct	vfstab	vfsbuf;
8989781SMoriah.Waterland@Sun.COM 		struct	vfstab	*vfs = &vfsbuf;
8999781SMoriah.Waterland@Sun.COM 		char VFS_TABLE[PATH_MAX];
9009781SMoriah.Waterland@Sun.COM 
9019781SMoriah.Waterland@Sun.COM 		/*
9029781SMoriah.Waterland@Sun.COM 		 * Since we use the fsys() function later, and it depends on
9039781SMoriah.Waterland@Sun.COM 		 * an ordered list, we have to sort the list here.
9049781SMoriah.Waterland@Sun.COM 		 */
9059781SMoriah.Waterland@Sun.COM 		qsort(fs_tab, fs_tab_used,
9069781SMoriah.Waterland@Sun.COM 		    sizeof (struct fstable *), fs_tab_ent_comp);
9079781SMoriah.Waterland@Sun.COM 
9089781SMoriah.Waterland@Sun.COM 		/*
9099781SMoriah.Waterland@Sun.COM 		 * Here's where the vfstab for the target is. If we can get
9109781SMoriah.Waterland@Sun.COM 		 * to it, we'll scan it for what the client will see as
9119781SMoriah.Waterland@Sun.COM 		 * remote filesystems, otherwise, we'll just skip this.
9129781SMoriah.Waterland@Sun.COM 		 */
9139781SMoriah.Waterland@Sun.COM 		if (vfstab_file) {
9149781SMoriah.Waterland@Sun.COM 			(void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s",
9159781SMoriah.Waterland@Sun.COM 				vfstab_file);
9169781SMoriah.Waterland@Sun.COM 		} else {
9179781SMoriah.Waterland@Sun.COM 			(void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s%s",
9189781SMoriah.Waterland@Sun.COM 				install_root, VFSTAB);
9199781SMoriah.Waterland@Sun.COM 		}
9209781SMoriah.Waterland@Sun.COM 
9219781SMoriah.Waterland@Sun.COM 		if (access(VFS_TABLE, R_OK) == 0) {
9229781SMoriah.Waterland@Sun.COM 			char *link_name;
9239781SMoriah.Waterland@Sun.COM 
9249781SMoriah.Waterland@Sun.COM 			/*
9259781SMoriah.Waterland@Sun.COM 			 * Open the vfs table for the target host.
9269781SMoriah.Waterland@Sun.COM 			 */
9279781SMoriah.Waterland@Sun.COM 			if ((pp = setmntent(VFS_TABLE, "r")) == NULL) {
9289781SMoriah.Waterland@Sun.COM 				progerr(ERR_NOTABLE, "vfs", VFS_TABLE,
9299781SMoriah.Waterland@Sun.COM 					strerror(errno));
9309781SMoriah.Waterland@Sun.COM 				return (1);
9319781SMoriah.Waterland@Sun.COM 			}
9329781SMoriah.Waterland@Sun.COM 
9339781SMoriah.Waterland@Sun.COM 			/* Do this for each entry in the vfstab. */
9349781SMoriah.Waterland@Sun.COM 			while (!getvfsent(pp, vfs)) {
9359781SMoriah.Waterland@Sun.COM 				char client_mountp[PATH_MAX];
9369781SMoriah.Waterland@Sun.COM 				int mnt_stat;
9379781SMoriah.Waterland@Sun.COM 
9389781SMoriah.Waterland@Sun.COM 				/*
9399781SMoriah.Waterland@Sun.COM 				 * We put it into the fs table if it's
9409781SMoriah.Waterland@Sun.COM 				 * remote mounted (even from this server) or
9419781SMoriah.Waterland@Sun.COM 				 * loopback mounted from the client's point
9429781SMoriah.Waterland@Sun.COM 				 * of view.
9439781SMoriah.Waterland@Sun.COM 				 */
9449781SMoriah.Waterland@Sun.COM 				if (!(is_remote =
9459781SMoriah.Waterland@Sun.COM 				    is_remote_src(vfs->vfs_special)) &&
9469781SMoriah.Waterland@Sun.COM 				    strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) !=
9479781SMoriah.Waterland@Sun.COM 				    0)
9489781SMoriah.Waterland@Sun.COM 					continue;	/* not interesting */
9499781SMoriah.Waterland@Sun.COM 
9509781SMoriah.Waterland@Sun.COM 				/*
9519781SMoriah.Waterland@Sun.COM 				 * Construct client_mountp by prepending the
9529781SMoriah.Waterland@Sun.COM 				 * install_root to the 'mount point' name.
9539781SMoriah.Waterland@Sun.COM 				 */
9549781SMoriah.Waterland@Sun.COM 				if (strcmp(vfs->vfs_mountp, "/") == 0) {
9559781SMoriah.Waterland@Sun.COM 					(void) strcpy(client_mountp,
956*10638SJan.Kryl@Sun.COM 					    install_root);
9579781SMoriah.Waterland@Sun.COM 				} else {
9589781SMoriah.Waterland@Sun.COM 					(void) snprintf(client_mountp,
9599781SMoriah.Waterland@Sun.COM 						sizeof (client_mountp), "%s%s",
9609781SMoriah.Waterland@Sun.COM 						install_root, vfs->vfs_mountp);
9619781SMoriah.Waterland@Sun.COM 				}
9629781SMoriah.Waterland@Sun.COM 
9639781SMoriah.Waterland@Sun.COM 				/*
9649781SMoriah.Waterland@Sun.COM 				 * We also skip the entry if the vfs_special
9659781SMoriah.Waterland@Sun.COM 				 * path and the client_path are the same.
9669781SMoriah.Waterland@Sun.COM 				 * There's no need to mount it, it's just a
9679781SMoriah.Waterland@Sun.COM 				 * cachefs optimization that mounts a
9689781SMoriah.Waterland@Sun.COM 				 * directory over itself from this server.
9699781SMoriah.Waterland@Sun.COM 				 */
9709781SMoriah.Waterland@Sun.COM 				if ((is_remote == SELF_SERVE) &&
9719781SMoriah.Waterland@Sun.COM 				    strcmp(path_part(vfs->vfs_special),
9729781SMoriah.Waterland@Sun.COM 				    client_mountp) == 0)
9739781SMoriah.Waterland@Sun.COM 					continue;
9749781SMoriah.Waterland@Sun.COM 
9759781SMoriah.Waterland@Sun.COM 				/* Determine if this is already mounted. */
9769781SMoriah.Waterland@Sun.COM 				link_name = strdup(path_part(vfs->vfs_special));
9779781SMoriah.Waterland@Sun.COM 				mnt_stat = already_mounted(vfs,
9789781SMoriah.Waterland@Sun.COM 				    (is_remote != REAL_REMOTE), client_mountp,
9799781SMoriah.Waterland@Sun.COM 				    link_name);
9809781SMoriah.Waterland@Sun.COM 
9819781SMoriah.Waterland@Sun.COM 				if (mnt_stat == MNT_EXACT) {
9829781SMoriah.Waterland@Sun.COM 					mod_existing(vfs, match_mount,
9839781SMoriah.Waterland@Sun.COM 					    is_remote);
9849781SMoriah.Waterland@Sun.COM 				} else {	/* MNT_NOT */
9859781SMoriah.Waterland@Sun.COM 					if (construct_vfs(vfs, client_mountp,
9869781SMoriah.Waterland@Sun.COM 					    link_name, is_remote, mnt_stat))
9879781SMoriah.Waterland@Sun.COM 						return (1);
9889781SMoriah.Waterland@Sun.COM 				}
9899781SMoriah.Waterland@Sun.COM 			}
9909781SMoriah.Waterland@Sun.COM 			(void) endmntent(pp);
9919781SMoriah.Waterland@Sun.COM 		}	/* end of if(access()) */
9929781SMoriah.Waterland@Sun.COM 	}	/* end of if(install_root) */
9939781SMoriah.Waterland@Sun.COM 
9949781SMoriah.Waterland@Sun.COM 	/* This next one may look stupid, but it can really happen. */
9959781SMoriah.Waterland@Sun.COM 	if (fs_tab_used <= 0) {
9969781SMoriah.Waterland@Sun.COM 		progerr(ERR_MNT_NOMOUNTS);
9979781SMoriah.Waterland@Sun.COM 		return (1);
9989781SMoriah.Waterland@Sun.COM 	}
9999781SMoriah.Waterland@Sun.COM 
10009781SMoriah.Waterland@Sun.COM 	/*
10019781SMoriah.Waterland@Sun.COM 	 * Now that we have the complete list of mounted (or virtually
10029781SMoriah.Waterland@Sun.COM 	 * mounted) filesystems, we sort the mountpoints in reverse order
10039781SMoriah.Waterland@Sun.COM 	 * based on the length of the 'mount point' name.
10049781SMoriah.Waterland@Sun.COM 	 */
10059781SMoriah.Waterland@Sun.COM 	qsort(fs_tab, fs_tab_used, sizeof (struct fstable *), fs_tab_ent_comp);
10069781SMoriah.Waterland@Sun.COM 	if (strcmp(fs_tab[fs_tab_used-1]->name, rn) != 0) {
10079781SMoriah.Waterland@Sun.COM 		progerr(ERR_MNT_NOROOT, fs_tab[fs_tab_used-1]->name, rn, errno,
1008*10638SJan.Kryl@Sun.COM 		    strerror(errno));
10099781SMoriah.Waterland@Sun.COM 		return (1);
10109781SMoriah.Waterland@Sun.COM 	} else {
10119781SMoriah.Waterland@Sun.COM 		return (0);
10129781SMoriah.Waterland@Sun.COM 	}
10139781SMoriah.Waterland@Sun.COM }
10149781SMoriah.Waterland@Sun.COM 
10159781SMoriah.Waterland@Sun.COM /*
10169781SMoriah.Waterland@Sun.COM  * This function supports dryrun mode by allowing the filesystem table to be
10179781SMoriah.Waterland@Sun.COM  * directly loaded from the continuation file.
10189781SMoriah.Waterland@Sun.COM  */
10199781SMoriah.Waterland@Sun.COM int
load_fsentry(struct fstable * fs_entry,char * name,char * fstype,char * remote_name)10209781SMoriah.Waterland@Sun.COM load_fsentry(struct fstable *fs_entry, char *name, char *fstype,
10219781SMoriah.Waterland@Sun.COM     char *remote_name)
10229781SMoriah.Waterland@Sun.COM {
10239781SMoriah.Waterland@Sun.COM 	struct fstable *nfte;
10249781SMoriah.Waterland@Sun.COM 
10259781SMoriah.Waterland@Sun.COM 	if ((nfte = fs_tab_init(name, fstype)) == NULL)
10269781SMoriah.Waterland@Sun.COM 		return (1);
10279781SMoriah.Waterland@Sun.COM 
10289781SMoriah.Waterland@Sun.COM 	/* Grab the name and fstype from the new structure. */
10299781SMoriah.Waterland@Sun.COM 	fs_entry->name = nfte->name;
10309781SMoriah.Waterland@Sun.COM 	fs_entry->fstype = nfte->fstype;
10319781SMoriah.Waterland@Sun.COM 
10329781SMoriah.Waterland@Sun.COM 	/* Copy the basic structure into place. */
10339781SMoriah.Waterland@Sun.COM 	(void) memcpy(nfte, fs_entry, sizeof (struct fstable));
10349781SMoriah.Waterland@Sun.COM 
10359781SMoriah.Waterland@Sun.COM 	/*
10369781SMoriah.Waterland@Sun.COM 	 * Allocate space for the 'special' name.
10379781SMoriah.Waterland@Sun.COM 	 */
10389781SMoriah.Waterland@Sun.COM 	if ((nfte->remote_name = malloc(strlen(remote_name)+1)) == NULL) {
10399781SMoriah.Waterland@Sun.COM 		progerr(ERR_MALLOC, "remote_name", errno, strerror(errno));
10409781SMoriah.Waterland@Sun.COM 		return (1);
10419781SMoriah.Waterland@Sun.COM 	}
10429781SMoriah.Waterland@Sun.COM 
10439781SMoriah.Waterland@Sun.COM 	(void) strcpy(nfte->remote_name, remote_name);
10449781SMoriah.Waterland@Sun.COM 
10459781SMoriah.Waterland@Sun.COM 	return (0);
10469781SMoriah.Waterland@Sun.COM }
10479781SMoriah.Waterland@Sun.COM 
10489781SMoriah.Waterland@Sun.COM /*
10499781SMoriah.Waterland@Sun.COM  * Given a path, return the table index of the filesystem the file apparently
10509781SMoriah.Waterland@Sun.COM  * resides on. This doesn't put any time into resolving filesystems that
10519781SMoriah.Waterland@Sun.COM  * refer to other filesystems. It just returns the entry containing this
10529781SMoriah.Waterland@Sun.COM  * path.
10539781SMoriah.Waterland@Sun.COM  */
10549781SMoriah.Waterland@Sun.COM short
fsys(char * path)10559781SMoriah.Waterland@Sun.COM fsys(char *path)
10569781SMoriah.Waterland@Sun.COM {
10579781SMoriah.Waterland@Sun.COM 	register int i;
10589781SMoriah.Waterland@Sun.COM 	char	real_path[PATH_MAX];
1059*10638SJan.Kryl@Sun.COM 	char	path_copy[PATH_MAX];
1060*10638SJan.Kryl@Sun.COM 	char	*path2use;
1061*10638SJan.Kryl@Sun.COM 	char	*cp;
10629781SMoriah.Waterland@Sun.COM 	int	pathlen;
1063*10638SJan.Kryl@Sun.COM 	boolean_t found = B_FALSE;
10649781SMoriah.Waterland@Sun.COM 
1065*10638SJan.Kryl@Sun.COM 	/*
1066*10638SJan.Kryl@Sun.COM 	 * The loop below represents our best effort to identify real path of
1067*10638SJan.Kryl@Sun.COM 	 * a file, which doesn't need to exist. realpath() returns error for
1068*10638SJan.Kryl@Sun.COM 	 * nonexistent path, therefore we need to cut off trailing components
1069*10638SJan.Kryl@Sun.COM 	 * of path until we get path which exists and can be resolved by
1070*10638SJan.Kryl@Sun.COM 	 * realpath(). Lookup of "/dir/symlink/nonexistent-file" would fail
1071*10638SJan.Kryl@Sun.COM 	 * to resolve symlink without this.
1072*10638SJan.Kryl@Sun.COM 	 */
1073*10638SJan.Kryl@Sun.COM 	(void) strlcpy(path_copy, path, PATH_MAX);
1074*10638SJan.Kryl@Sun.COM 	for (cp = dirname(path_copy); strlen(cp) > 1; cp = dirname(cp)) {
1075*10638SJan.Kryl@Sun.COM 		if (realpath(cp, real_path) != NULL) {
1076*10638SJan.Kryl@Sun.COM 			found = B_TRUE;
1077*10638SJan.Kryl@Sun.COM 			break;
1078*10638SJan.Kryl@Sun.COM 		} else if (errno != ENOENT)
1079*10638SJan.Kryl@Sun.COM 			break;
10809781SMoriah.Waterland@Sun.COM 	}
1081*10638SJan.Kryl@Sun.COM 	if (found)
1082*10638SJan.Kryl@Sun.COM 		path2use = real_path;
1083*10638SJan.Kryl@Sun.COM 	else
1084*10638SJan.Kryl@Sun.COM 		/* fall back to original path in case of unexpected failure */
1085*10638SJan.Kryl@Sun.COM 		path2use = path;
10869781SMoriah.Waterland@Sun.COM 
10879781SMoriah.Waterland@Sun.COM 	pathlen = strlen(path2use);
10889781SMoriah.Waterland@Sun.COM 
10899781SMoriah.Waterland@Sun.COM 	/*
10909781SMoriah.Waterland@Sun.COM 	 * The following algorithm scans the list of attached file systems
10919781SMoriah.Waterland@Sun.COM 	 * for the one containing path. At this point the file names in
10929781SMoriah.Waterland@Sun.COM 	 * fs_tab[] are sorted by decreasing length to facilitate the scan.
10939781SMoriah.Waterland@Sun.COM 	 * The first for() scans past all the file system names too short to
10949781SMoriah.Waterland@Sun.COM 	 * contain path. The second for() does the actual string comparison.
10959781SMoriah.Waterland@Sun.COM 	 * It tests first to assure that the comparison is against a complete
10969781SMoriah.Waterland@Sun.COM 	 * token by assuring that the end of the filesystem name aligns with
10979781SMoriah.Waterland@Sun.COM 	 * the end of a token in path2use (ie: '/' or NULL) then it does a
10989781SMoriah.Waterland@Sun.COM 	 * string compare. -- JST
10999781SMoriah.Waterland@Sun.COM 	 */
11009781SMoriah.Waterland@Sun.COM 
11019781SMoriah.Waterland@Sun.COM 	if (fs_tab_used == 0) {
11029781SMoriah.Waterland@Sun.COM 		return (-1);
11039781SMoriah.Waterland@Sun.COM 	}
11049781SMoriah.Waterland@Sun.COM 
11059781SMoriah.Waterland@Sun.COM 	for (i = 0; i < fs_tab_used; i++)
11069781SMoriah.Waterland@Sun.COM 		if (fs_tab[i] == NULL)
11079781SMoriah.Waterland@Sun.COM 			continue;
11089781SMoriah.Waterland@Sun.COM 		else if (fs_tab[i]->namlen <= pathlen)
11099781SMoriah.Waterland@Sun.COM 			break;
11109781SMoriah.Waterland@Sun.COM 	for (; i < fs_tab_used; i++) {
11119781SMoriah.Waterland@Sun.COM 		int fs_namelen;
11129781SMoriah.Waterland@Sun.COM 		char term_char;
11139781SMoriah.Waterland@Sun.COM 
11149781SMoriah.Waterland@Sun.COM 		if (fs_tab[i] == NULL)
11159781SMoriah.Waterland@Sun.COM 			continue;
11169781SMoriah.Waterland@Sun.COM 
11179781SMoriah.Waterland@Sun.COM 		fs_namelen = fs_tab[i]->namlen;
11189781SMoriah.Waterland@Sun.COM 		term_char = path2use[fs_namelen];
11199781SMoriah.Waterland@Sun.COM 
11209781SMoriah.Waterland@Sun.COM 		/*
11219781SMoriah.Waterland@Sun.COM 		 * If we're putting the file "/a/kernel" into the filesystem
11229781SMoriah.Waterland@Sun.COM 		 * "/a", then fs_namelen == 2 and term_char == '/'. If, we're
11239781SMoriah.Waterland@Sun.COM 		 * putting "/etc/termcap" into "/", fs_namelen == 1 and
11249781SMoriah.Waterland@Sun.COM 		 * term_char (unfortunately) == 'e'. In the case of
11259781SMoriah.Waterland@Sun.COM 		 * fs_namelen == 1, we check to make sure the filesystem is
11269781SMoriah.Waterland@Sun.COM 		 * "/" and if it is, we have a guaranteed fit, otherwise we
11279781SMoriah.Waterland@Sun.COM 		 * do the string compare. -- JST
11289781SMoriah.Waterland@Sun.COM 		 */
11299781SMoriah.Waterland@Sun.COM 		if ((fs_namelen == 1 && *(fs_tab[i]->name) == '/') ||
11309781SMoriah.Waterland@Sun.COM 		    ((term_char == '/' || term_char == NULL) &&
11319781SMoriah.Waterland@Sun.COM 		    strncmp(fs_tab[i]->name, path2use, fs_namelen) == 0))
11329781SMoriah.Waterland@Sun.COM 			return (i);
11339781SMoriah.Waterland@Sun.COM 	}
11349781SMoriah.Waterland@Sun.COM 
11359781SMoriah.Waterland@Sun.COM 	/*
11369781SMoriah.Waterland@Sun.COM 	 * It only gets here if the root filesystem is fundamentally corrupt.
11379781SMoriah.Waterland@Sun.COM 	 * (This can happen!)
11389781SMoriah.Waterland@Sun.COM 	 */
11399781SMoriah.Waterland@Sun.COM 	progerr(ERR_FSYS_FELLOUT, path2use);
11409781SMoriah.Waterland@Sun.COM 
11419781SMoriah.Waterland@Sun.COM 	return (-1);
11429781SMoriah.Waterland@Sun.COM }
11439781SMoriah.Waterland@Sun.COM 
11449781SMoriah.Waterland@Sun.COM /*
11459781SMoriah.Waterland@Sun.COM  * This function returns the entry in the fs_tab[] corresponding to the
11469781SMoriah.Waterland@Sun.COM  * actual filesystem of record. It won't return a loopback filesystem entry,
11479781SMoriah.Waterland@Sun.COM  * it will return the filesystem that the loopback filesystem is mounted
11489781SMoriah.Waterland@Sun.COM  * over.
11499781SMoriah.Waterland@Sun.COM  */
11509781SMoriah.Waterland@Sun.COM short
resolved_fsys(char * path)11519781SMoriah.Waterland@Sun.COM resolved_fsys(char *path)
11529781SMoriah.Waterland@Sun.COM {
11539781SMoriah.Waterland@Sun.COM 	int i = -1;
11549781SMoriah.Waterland@Sun.COM 	char path2use[PATH_MAX];
11559781SMoriah.Waterland@Sun.COM 
11569781SMoriah.Waterland@Sun.COM 	(void) strcpy(path2use, path);
11579781SMoriah.Waterland@Sun.COM 
11589781SMoriah.Waterland@Sun.COM 	/* If this isn't a "real" filesystem, resolve the map. */
11599781SMoriah.Waterland@Sun.COM 	do {
11609781SMoriah.Waterland@Sun.COM 		(void) strcpy(path2use, server_map(path2use, i));
11619781SMoriah.Waterland@Sun.COM 		i = fsys(path2use);
11629781SMoriah.Waterland@Sun.COM 	} while (fs_tab[i]->srvr_map);
11639781SMoriah.Waterland@Sun.COM 
11649781SMoriah.Waterland@Sun.COM 	return (i);
11659781SMoriah.Waterland@Sun.COM }
11669781SMoriah.Waterland@Sun.COM 
11679781SMoriah.Waterland@Sun.COM /*
11689781SMoriah.Waterland@Sun.COM  * This function returns the srvr_map status based upon the fs_tab entry
11699781SMoriah.Waterland@Sun.COM  * number. This tells us if the server path constructed from the package
11709781SMoriah.Waterland@Sun.COM  * install root is really the target filesystem.
11719781SMoriah.Waterland@Sun.COM  */
11729781SMoriah.Waterland@Sun.COM int
use_srvr_map_n(short n)11739781SMoriah.Waterland@Sun.COM use_srvr_map_n(short n)
11749781SMoriah.Waterland@Sun.COM {
11759781SMoriah.Waterland@Sun.COM 	return ((int)fs_tab[n]->srvr_map);
11769781SMoriah.Waterland@Sun.COM }
11779781SMoriah.Waterland@Sun.COM 
11789781SMoriah.Waterland@Sun.COM /*
11799781SMoriah.Waterland@Sun.COM  * This function returns the mount status based upon the fs_tab entry
11809781SMoriah.Waterland@Sun.COM  * number. This tells us if there is any hope of gaining access
11819781SMoriah.Waterland@Sun.COM  * to this file system.
11829781SMoriah.Waterland@Sun.COM  */
11839781SMoriah.Waterland@Sun.COM int
is_mounted_n(short n)11849781SMoriah.Waterland@Sun.COM is_mounted_n(short n)
11859781SMoriah.Waterland@Sun.COM {
11869781SMoriah.Waterland@Sun.COM 	return ((int)fs_tab[n]->mounted);
11879781SMoriah.Waterland@Sun.COM }
11889781SMoriah.Waterland@Sun.COM 
11899781SMoriah.Waterland@Sun.COM /*
11909781SMoriah.Waterland@Sun.COM  * is_fs_writeable_n - given an fstab index, return 1
11919781SMoriah.Waterland@Sun.COM  *	if it's writeable, 0 if read-only.
11929781SMoriah.Waterland@Sun.COM  */
11939781SMoriah.Waterland@Sun.COM int
is_fs_writeable_n(short n)11949781SMoriah.Waterland@Sun.COM is_fs_writeable_n(short n)
11959781SMoriah.Waterland@Sun.COM {
11969781SMoriah.Waterland@Sun.COM 	/*
11979781SMoriah.Waterland@Sun.COM 	 * If the write access permissions haven't been confirmed, do that
11989781SMoriah.Waterland@Sun.COM 	 * now. Note that the only reason we need to do the special check is
11999781SMoriah.Waterland@Sun.COM 	 * in the case of an NFS mount (remote) because we can't determine if
12009781SMoriah.Waterland@Sun.COM 	 * root has access in any other way.
12019781SMoriah.Waterland@Sun.COM 	 */
12029781SMoriah.Waterland@Sun.COM 	if (fs_tab[n]->remote && fs_tab[n]->mounted &&
12039781SMoriah.Waterland@Sun.COM 	    !fs_tab[n]->write_tested) {
12049781SMoriah.Waterland@Sun.COM 		if (fs_tab[n]->writeable && !really_write(fs_tab[n]->name))
12059781SMoriah.Waterland@Sun.COM 			fs_tab[n]->writeable = 0;	/* not really */
12069781SMoriah.Waterland@Sun.COM 
12079781SMoriah.Waterland@Sun.COM 		fs_tab[n]->write_tested = 1;	/* confirmed */
12089781SMoriah.Waterland@Sun.COM 	}
12099781SMoriah.Waterland@Sun.COM 
12109781SMoriah.Waterland@Sun.COM 	return ((int)fs_tab[n]->writeable);
12119781SMoriah.Waterland@Sun.COM }
12129781SMoriah.Waterland@Sun.COM 
12139781SMoriah.Waterland@Sun.COM /*
12149781SMoriah.Waterland@Sun.COM  * is_remote_fs_n - given an fstab index, return 1
12159781SMoriah.Waterland@Sun.COM  *	if it's a remote filesystem, 0 if local.
12169781SMoriah.Waterland@Sun.COM  *
12179781SMoriah.Waterland@Sun.COM  *	Note: Upon entry, a valid fsys() is required.
12189781SMoriah.Waterland@Sun.COM  */
12199781SMoriah.Waterland@Sun.COM int
is_remote_fs_n(short n)12209781SMoriah.Waterland@Sun.COM is_remote_fs_n(short n)
12219781SMoriah.Waterland@Sun.COM {
12229781SMoriah.Waterland@Sun.COM 	return ((int)fs_tab[n]->remote);
12239781SMoriah.Waterland@Sun.COM }
12249781SMoriah.Waterland@Sun.COM 
12259781SMoriah.Waterland@Sun.COM /* index-driven is_served() */
12269781SMoriah.Waterland@Sun.COM int
is_served_n(short n)12279781SMoriah.Waterland@Sun.COM is_served_n(short n)
12289781SMoriah.Waterland@Sun.COM {
12299781SMoriah.Waterland@Sun.COM 	return ((int)fs_tab[n]->served);
12309781SMoriah.Waterland@Sun.COM }
12319781SMoriah.Waterland@Sun.COM 
12329781SMoriah.Waterland@Sun.COM /*
12339781SMoriah.Waterland@Sun.COM  * This returns the number of blocks available on the indicated filesystem.
12349781SMoriah.Waterland@Sun.COM  *
12359781SMoriah.Waterland@Sun.COM  *	Note: Upon entry, a valid fsys() is required.
12369781SMoriah.Waterland@Sun.COM  */
12379781SMoriah.Waterland@Sun.COM fsblkcnt_t
get_blk_free_n(short n)12389781SMoriah.Waterland@Sun.COM get_blk_free_n(short n)
12399781SMoriah.Waterland@Sun.COM {
12409781SMoriah.Waterland@Sun.COM 	return (fs_tab[n]->bfree);
12419781SMoriah.Waterland@Sun.COM }
12429781SMoriah.Waterland@Sun.COM 
12439781SMoriah.Waterland@Sun.COM /*
12449781SMoriah.Waterland@Sun.COM  * This returns the number of blocks being used on the indicated filesystem.
12459781SMoriah.Waterland@Sun.COM  *
12469781SMoriah.Waterland@Sun.COM  *	Note: Upon entry, a valid fsys() is required.
12479781SMoriah.Waterland@Sun.COM  */
12489781SMoriah.Waterland@Sun.COM fsblkcnt_t
get_blk_used_n(short n)12499781SMoriah.Waterland@Sun.COM get_blk_used_n(short n)
12509781SMoriah.Waterland@Sun.COM {
12519781SMoriah.Waterland@Sun.COM 	return (fs_tab[n]->bused);
12529781SMoriah.Waterland@Sun.COM }
12539781SMoriah.Waterland@Sun.COM 
12549781SMoriah.Waterland@Sun.COM /*
12559781SMoriah.Waterland@Sun.COM  * This returns the number of inodes available on the indicated filesystem.
12569781SMoriah.Waterland@Sun.COM  *
12579781SMoriah.Waterland@Sun.COM  *	Note: Upon entry, a valid fsys() is required.
12589781SMoriah.Waterland@Sun.COM  */
12599781SMoriah.Waterland@Sun.COM fsblkcnt_t
get_inode_free_n(short n)12609781SMoriah.Waterland@Sun.COM get_inode_free_n(short n)
12619781SMoriah.Waterland@Sun.COM {
12629781SMoriah.Waterland@Sun.COM 	return (fs_tab[n]->ffree);
12639781SMoriah.Waterland@Sun.COM }
12649781SMoriah.Waterland@Sun.COM 
12659781SMoriah.Waterland@Sun.COM /*
12669781SMoriah.Waterland@Sun.COM  * This returns the number of inodes being used on the indicated filesystem.
12679781SMoriah.Waterland@Sun.COM  *
12689781SMoriah.Waterland@Sun.COM  *	Note: Upon entry, a valid fsys() is required.
12699781SMoriah.Waterland@Sun.COM  */
12709781SMoriah.Waterland@Sun.COM fsblkcnt_t
get_inode_used_n(short n)12719781SMoriah.Waterland@Sun.COM get_inode_used_n(short n)
12729781SMoriah.Waterland@Sun.COM {
12739781SMoriah.Waterland@Sun.COM 	return (fs_tab[n]->fused);
12749781SMoriah.Waterland@Sun.COM }
12759781SMoriah.Waterland@Sun.COM 
12769781SMoriah.Waterland@Sun.COM /*
12779781SMoriah.Waterland@Sun.COM  * Sets the number of blocks being used on the indicated filesystem.
12789781SMoriah.Waterland@Sun.COM  *
12799781SMoriah.Waterland@Sun.COM  *	Note: Upon entry, a valid fsys() is required.
12809781SMoriah.Waterland@Sun.COM  */
12819781SMoriah.Waterland@Sun.COM void
set_blk_used_n(short n,fsblkcnt_t value)12829781SMoriah.Waterland@Sun.COM set_blk_used_n(short n, fsblkcnt_t value)
12839781SMoriah.Waterland@Sun.COM {
12849781SMoriah.Waterland@Sun.COM 	fs_tab[n]->bused = value;
12859781SMoriah.Waterland@Sun.COM }
12869781SMoriah.Waterland@Sun.COM 
12879781SMoriah.Waterland@Sun.COM /* Get the filesystem block size. */
12889781SMoriah.Waterland@Sun.COM fsblkcnt_t
get_blk_size_n(short n)12899781SMoriah.Waterland@Sun.COM get_blk_size_n(short n)
12909781SMoriah.Waterland@Sun.COM {
12919781SMoriah.Waterland@Sun.COM 	return (fs_tab[n]->bsize);
12929781SMoriah.Waterland@Sun.COM }
12939781SMoriah.Waterland@Sun.COM 
12949781SMoriah.Waterland@Sun.COM /* Get the filesystem fragment size. */
12959781SMoriah.Waterland@Sun.COM fsblkcnt_t
get_frag_size_n(short n)12969781SMoriah.Waterland@Sun.COM get_frag_size_n(short n)
12979781SMoriah.Waterland@Sun.COM {
12989781SMoriah.Waterland@Sun.COM 	return (fs_tab[n]->bsize);
12999781SMoriah.Waterland@Sun.COM }
13009781SMoriah.Waterland@Sun.COM 
13019781SMoriah.Waterland@Sun.COM /*
13029781SMoriah.Waterland@Sun.COM  * This returns the name of the indicated filesystem.
13039781SMoriah.Waterland@Sun.COM  */
13049781SMoriah.Waterland@Sun.COM char *
get_fs_name_n(short n)13059781SMoriah.Waterland@Sun.COM get_fs_name_n(short n)
13069781SMoriah.Waterland@Sun.COM {
13079781SMoriah.Waterland@Sun.COM 	if (fs_tab_used == 0) {
13089781SMoriah.Waterland@Sun.COM 		return (NULL);
13099781SMoriah.Waterland@Sun.COM 	} else if (n >= fs_tab_used) {
13109781SMoriah.Waterland@Sun.COM 		return (NULL);
13119781SMoriah.Waterland@Sun.COM 	} else {
13129781SMoriah.Waterland@Sun.COM 		return (fs_tab[n]->name);
13139781SMoriah.Waterland@Sun.COM 	}
13149781SMoriah.Waterland@Sun.COM }
13159781SMoriah.Waterland@Sun.COM 
13169781SMoriah.Waterland@Sun.COM /*
13179781SMoriah.Waterland@Sun.COM  * This returns the remote name of the indicated filesystem.
13189781SMoriah.Waterland@Sun.COM  *
13199781SMoriah.Waterland@Sun.COM  *	Note: Upon entry, a valid fsys() is required.
13209781SMoriah.Waterland@Sun.COM  */
13219781SMoriah.Waterland@Sun.COM char *
get_source_name_n(short n)13229781SMoriah.Waterland@Sun.COM get_source_name_n(short n)
13239781SMoriah.Waterland@Sun.COM {
13249781SMoriah.Waterland@Sun.COM 	return (fs_tab[n]->remote_name);
13259781SMoriah.Waterland@Sun.COM }
13269781SMoriah.Waterland@Sun.COM 
13279781SMoriah.Waterland@Sun.COM /*
13289781SMoriah.Waterland@Sun.COM  * This function returns the srvr_map status based upon the path.
13299781SMoriah.Waterland@Sun.COM  */
13309781SMoriah.Waterland@Sun.COM int
use_srvr_map(char * path,short * fsys_value)13319781SMoriah.Waterland@Sun.COM use_srvr_map(char *path, short *fsys_value)
13329781SMoriah.Waterland@Sun.COM {
13339781SMoriah.Waterland@Sun.COM 	if (*fsys_value == BADFSYS)
13349781SMoriah.Waterland@Sun.COM 		*fsys_value = fsys(path);
13359781SMoriah.Waterland@Sun.COM 
13369781SMoriah.Waterland@Sun.COM 	return (use_srvr_map_n(*fsys_value));
13379781SMoriah.Waterland@Sun.COM }
13389781SMoriah.Waterland@Sun.COM 
13399781SMoriah.Waterland@Sun.COM /*
13409781SMoriah.Waterland@Sun.COM  * This function returns the mount status based upon the path.
13419781SMoriah.Waterland@Sun.COM  */
13429781SMoriah.Waterland@Sun.COM int
is_mounted(char * path,short * fsys_value)13439781SMoriah.Waterland@Sun.COM is_mounted(char *path, short *fsys_value)
13449781SMoriah.Waterland@Sun.COM {
13459781SMoriah.Waterland@Sun.COM 	if (*fsys_value == BADFSYS)
13469781SMoriah.Waterland@Sun.COM 		*fsys_value = fsys(path);
13479781SMoriah.Waterland@Sun.COM 
13489781SMoriah.Waterland@Sun.COM 	return (is_mounted_n(*fsys_value));
13499781SMoriah.Waterland@Sun.COM }
13509781SMoriah.Waterland@Sun.COM 
13519781SMoriah.Waterland@Sun.COM /*
13529781SMoriah.Waterland@Sun.COM  * is_fs_writeable - given a cfent entry, return 1
13539781SMoriah.Waterland@Sun.COM  *	if it's writeable, 0 if read-only.
13549781SMoriah.Waterland@Sun.COM  *
13559781SMoriah.Waterland@Sun.COM  *	Note: Upon exit, a valid fsys() is guaranteed. This is
13569781SMoriah.Waterland@Sun.COM  *	an interface requirement.
13579781SMoriah.Waterland@Sun.COM  */
13589781SMoriah.Waterland@Sun.COM int
is_fs_writeable(char * path,short * fsys_value)13599781SMoriah.Waterland@Sun.COM is_fs_writeable(char *path, short *fsys_value)
13609781SMoriah.Waterland@Sun.COM {
13619781SMoriah.Waterland@Sun.COM 	if (*fsys_value == BADFSYS)
13629781SMoriah.Waterland@Sun.COM 		*fsys_value = fsys(path);
13639781SMoriah.Waterland@Sun.COM 
13649781SMoriah.Waterland@Sun.COM 	return (is_fs_writeable_n(*fsys_value));
13659781SMoriah.Waterland@Sun.COM }
13669781SMoriah.Waterland@Sun.COM 
13679781SMoriah.Waterland@Sun.COM /*
13689781SMoriah.Waterland@Sun.COM  * is_remote_fs - given a cfent entry, return 1
13699781SMoriah.Waterland@Sun.COM  *	if it's a remote filesystem, 0 if local.
13709781SMoriah.Waterland@Sun.COM  *
13719781SMoriah.Waterland@Sun.COM  *	Also Note: Upon exit, a valid fsys() is guaranteed. This is
13729781SMoriah.Waterland@Sun.COM  *	an interface requirement.
13739781SMoriah.Waterland@Sun.COM  */
13749781SMoriah.Waterland@Sun.COM int
is_remote_fs(char * path,short * fsys_value)13759781SMoriah.Waterland@Sun.COM is_remote_fs(char *path, short *fsys_value)
13769781SMoriah.Waterland@Sun.COM {
13779781SMoriah.Waterland@Sun.COM 	if (*fsys_value == BADFSYS)
13789781SMoriah.Waterland@Sun.COM 		*fsys_value = fsys(path);
13799781SMoriah.Waterland@Sun.COM 
13809781SMoriah.Waterland@Sun.COM 	return (is_remote_fs_n(*fsys_value));
13819781SMoriah.Waterland@Sun.COM }
13829781SMoriah.Waterland@Sun.COM 
13839781SMoriah.Waterland@Sun.COM /*
13849781SMoriah.Waterland@Sun.COM  * This function returns the served status of the filesystem. Served means a
13859781SMoriah.Waterland@Sun.COM  * client is getting this file from a server and it is not writeable by the
13869781SMoriah.Waterland@Sun.COM  * client. It has nothing to do with whether or not this particular operation
13879781SMoriah.Waterland@Sun.COM  * (eg: pkgadd or pkgrm) will be writing to it.
13889781SMoriah.Waterland@Sun.COM  */
13899781SMoriah.Waterland@Sun.COM int
is_served(char * path,short * fsys_value)13909781SMoriah.Waterland@Sun.COM is_served(char *path, short *fsys_value)
13919781SMoriah.Waterland@Sun.COM {
13929781SMoriah.Waterland@Sun.COM 	if (*fsys_value == BADFSYS)
13939781SMoriah.Waterland@Sun.COM 		*fsys_value = fsys(path);
13949781SMoriah.Waterland@Sun.COM 
13959781SMoriah.Waterland@Sun.COM 	return (is_served_n(*fsys_value));
13969781SMoriah.Waterland@Sun.COM }
13979781SMoriah.Waterland@Sun.COM 
13989781SMoriah.Waterland@Sun.COM /*
13999781SMoriah.Waterland@Sun.COM  * get_remote_path - given a filesystem table index, return the
14009781SMoriah.Waterland@Sun.COM  *	path of the filesystem on the remote system.  Otherwise,
14019781SMoriah.Waterland@Sun.COM  *	return NULL if it's a local filesystem.
14029781SMoriah.Waterland@Sun.COM  */
14039781SMoriah.Waterland@Sun.COM char *
get_remote_path(short n)14049781SMoriah.Waterland@Sun.COM get_remote_path(short n)
14059781SMoriah.Waterland@Sun.COM {
14069781SMoriah.Waterland@Sun.COM 	char	*p;
14079781SMoriah.Waterland@Sun.COM 
14089781SMoriah.Waterland@Sun.COM 	if (!is_remote_fs_n(n))
14099781SMoriah.Waterland@Sun.COM 		return (NULL); 	/* local */
14109781SMoriah.Waterland@Sun.COM 	p = strchr(fs_tab[n]->remote_name, ':');
14119781SMoriah.Waterland@Sun.COM 	if (!p)
14129781SMoriah.Waterland@Sun.COM 		p = fs_tab[n]->remote_name; 	/* Loopback */
14139781SMoriah.Waterland@Sun.COM 	else
14149781SMoriah.Waterland@Sun.COM 		p++; 	/* remote */
14159781SMoriah.Waterland@Sun.COM 	return (p);
14169781SMoriah.Waterland@Sun.COM }
14179781SMoriah.Waterland@Sun.COM 
14189781SMoriah.Waterland@Sun.COM /*
14199781SMoriah.Waterland@Sun.COM  * get_mount_point - given a filesystem table index, return the
14209781SMoriah.Waterland@Sun.COM  *	path of the mount point.  Otherwise,
14219781SMoriah.Waterland@Sun.COM  *	return NULL if it's a local filesystem.
14229781SMoriah.Waterland@Sun.COM  */
14239781SMoriah.Waterland@Sun.COM char *
get_mount_point(short n)14249781SMoriah.Waterland@Sun.COM get_mount_point(short n)
14259781SMoriah.Waterland@Sun.COM {
14269781SMoriah.Waterland@Sun.COM 	if (!is_remote_fs_n(n))
14279781SMoriah.Waterland@Sun.COM 		return (NULL); 	/* local */
14289781SMoriah.Waterland@Sun.COM 	return (fs_tab[n]->name);
14299781SMoriah.Waterland@Sun.COM }
14309781SMoriah.Waterland@Sun.COM 
14319781SMoriah.Waterland@Sun.COM struct fstable *
get_fs_entry(short n)14329781SMoriah.Waterland@Sun.COM get_fs_entry(short n)
14339781SMoriah.Waterland@Sun.COM {
14349781SMoriah.Waterland@Sun.COM 	if (fs_tab_used == 0) {
14359781SMoriah.Waterland@Sun.COM 		return (NULL);
14369781SMoriah.Waterland@Sun.COM 	} else if (n >= fs_tab_used) {
14379781SMoriah.Waterland@Sun.COM 		return (NULL);
14389781SMoriah.Waterland@Sun.COM 	} else {
14399781SMoriah.Waterland@Sun.COM 		return (fs_tab[n]);
14409781SMoriah.Waterland@Sun.COM 	}
14419781SMoriah.Waterland@Sun.COM }
1442