xref: /titanic_50/usr/src/cmd/svr4pkg/libinst/mntinfo.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland 
28*5c51f124SMoriah Waterland /*
29*5c51f124SMoriah Waterland  * System includes
30*5c51f124SMoriah Waterland  */
31*5c51f124SMoriah Waterland 
32*5c51f124SMoriah Waterland #include <stdio.h>
33*5c51f124SMoriah Waterland #include <limits.h>
34*5c51f124SMoriah Waterland #include <errno.h>
35*5c51f124SMoriah Waterland #include <stdlib.h>
36*5c51f124SMoriah Waterland #include <unistd.h>
37*5c51f124SMoriah Waterland #include <string.h>
38*5c51f124SMoriah Waterland #include <wait.h>
39*5c51f124SMoriah Waterland #include <signal.h>
40*5c51f124SMoriah Waterland #include <malloc.h>
41*5c51f124SMoriah Waterland #include <sys/types.h>
42*5c51f124SMoriah Waterland #include <sys/mount.h>
43*5c51f124SMoriah Waterland #include <sys/stat.h>
44*5c51f124SMoriah Waterland #include <fcntl.h>
45*5c51f124SMoriah Waterland #include <sys/systeminfo.h>
46*5c51f124SMoriah Waterland #include <pkgstrct.h>
47*5c51f124SMoriah Waterland #include <pkginfo.h>
48*5c51f124SMoriah Waterland #include <locale.h>
49*5c51f124SMoriah Waterland #include <libintl.h>
50*5c51f124SMoriah Waterland 
51*5c51f124SMoriah Waterland #include <sys/mnttab.h>
52*5c51f124SMoriah Waterland #include <sys/mntent.h>
53*5c51f124SMoriah Waterland #include <sys/vfstab.h>
54*5c51f124SMoriah Waterland 
55*5c51f124SMoriah Waterland /*
56*5c51f124SMoriah Waterland  * consolidation pkg command library includes
57*5c51f124SMoriah Waterland  */
58*5c51f124SMoriah Waterland 
59*5c51f124SMoriah Waterland #include <pkglib.h>
60*5c51f124SMoriah Waterland 
61*5c51f124SMoriah Waterland /*
62*5c51f124SMoriah Waterland  * local pkg command library includes
63*5c51f124SMoriah Waterland  */
64*5c51f124SMoriah Waterland 
65*5c51f124SMoriah Waterland #include "install.h"
66*5c51f124SMoriah Waterland #include "libinst.h"
67*5c51f124SMoriah Waterland #include "libadm.h"
68*5c51f124SMoriah Waterland #include "messages.h"
69*5c51f124SMoriah Waterland 
70*5c51f124SMoriah Waterland extern char **environ;
71*5c51f124SMoriah Waterland 
72*5c51f124SMoriah Waterland static int match_mount;		/* This holds the mount of interest. */
73*5c51f124SMoriah Waterland 
74*5c51f124SMoriah Waterland int	fs_tab_used  = 0;
75*5c51f124SMoriah Waterland int	fs_tab_alloc = 0;
76*5c51f124SMoriah Waterland static int	fs_list = -1;
77*5c51f124SMoriah Waterland 
78*5c51f124SMoriah Waterland struct	fstable	**fs_tab = NULL;
79*5c51f124SMoriah Waterland 
80*5c51f124SMoriah Waterland #define	PKGDBROOT	"/var/sadm"
81*5c51f124SMoriah Waterland #define	MOUNT		"/sbin/mount"
82*5c51f124SMoriah Waterland #define	UMOUNT		"/sbin/umount"
83*5c51f124SMoriah Waterland 
84*5c51f124SMoriah Waterland #define	setmntent	fopen
85*5c51f124SMoriah Waterland #define	endmntent	fclose
86*5c51f124SMoriah Waterland #define	MOUNT_TABLE	MNTTAB
87*5c51f124SMoriah Waterland 
88*5c51f124SMoriah Waterland /* returned by already_mounted() */
89*5c51f124SMoriah Waterland #define	MNT_NOT		0
90*5c51f124SMoriah Waterland #define	MNT_EXACT	1
91*5c51f124SMoriah Waterland #define	MNT_AVAIL	2
92*5c51f124SMoriah Waterland 
93*5c51f124SMoriah Waterland /* used with is_remote_src() */
94*5c51f124SMoriah Waterland #define	NOT_REMOTE	0
95*5c51f124SMoriah Waterland #define	REAL_REMOTE	1
96*5c51f124SMoriah Waterland #define	SELF_SERVE	2
97*5c51f124SMoriah Waterland 
98*5c51f124SMoriah Waterland /*
99*5c51f124SMoriah Waterland  * Due to /etc/mnttab files containing entries for multiple nfs hosts
100*5c51f124SMoriah Waterland  * HOST_NM_LN needs to be accommodating. The recommended value in the sysinfo
101*5c51f124SMoriah Waterland  * man page of 257 needs to be expanded. See bugid 4076513.
102*5c51f124SMoriah Waterland  * 1024 chars is defined in the mnttab.h header as the max size of an entry.
103*5c51f124SMoriah Waterland  */
104*5c51f124SMoriah Waterland 
105*5c51f124SMoriah Waterland #define	HOST_NM_LN	MNT_LINE_MAX
106*5c51f124SMoriah Waterland 
107*5c51f124SMoriah Waterland /* These cachefs definitions should be in mntent.h. Maybe some day. */
108*5c51f124SMoriah Waterland #define	MNTTYPE_CFS		"cachefs"
109*5c51f124SMoriah Waterland #define	MNTOPT_BACKFSTYPE	"backfstype"
110*5c51f124SMoriah Waterland #define	MNTTYPE_AUTO		"autofs"
111*5c51f124SMoriah Waterland 
112*5c51f124SMoriah Waterland /*
113*5c51f124SMoriah Waterland  * Utilities for getting filesystem information from the mount table.
114*5c51f124SMoriah Waterland  *
115*5c51f124SMoriah Waterland  * Note: vanilla SVr4 code (pkginstall/dockspace.c) used the output from
116*5c51f124SMoriah Waterland  * popen() on the "/etc/mount" command.  However, we need to get more
117*5c51f124SMoriah Waterland  * information about mounted filesystems, so we use the C interfaces to
118*5c51f124SMoriah Waterland  * the mount table, which also happens to be much faster than running
119*5c51f124SMoriah Waterland  * another process.  Since several of the pkg commands need access to the
120*5c51f124SMoriah Waterland  * the code has been placed here, to be included in the libinst library.
121*5c51f124SMoriah Waterland  */
122*5c51f124SMoriah Waterland 
123*5c51f124SMoriah Waterland #define	ALLOC_CHUNK	30
124*5c51f124SMoriah Waterland 
125*5c51f124SMoriah Waterland /*
126*5c51f124SMoriah Waterland  * fs_tab_ent_comp -	compare fstable entries first by length in reverse
127*5c51f124SMoriah Waterland  *			order, then alphabetically.
128*5c51f124SMoriah Waterland  */
129*5c51f124SMoriah Waterland static int
130*5c51f124SMoriah Waterland fs_tab_ent_comp(const void *e1, const void *e2)
131*5c51f124SMoriah Waterland {
132*5c51f124SMoriah Waterland 	struct fstable	*fs1 = *((struct fstable **)e1);
133*5c51f124SMoriah Waterland 	struct fstable	*fs2 = *((struct fstable **)e2);
134*5c51f124SMoriah Waterland 
135*5c51f124SMoriah Waterland 	if (fs1->namlen == fs2->namlen)
136*5c51f124SMoriah Waterland 		return (strcmp(fs1->name, fs2->name));
137*5c51f124SMoriah Waterland 	else
138*5c51f124SMoriah Waterland 		return (fs2->namlen - fs1->namlen);
139*5c51f124SMoriah Waterland }
140*5c51f124SMoriah Waterland 
141*5c51f124SMoriah Waterland /*
142*5c51f124SMoriah Waterland  * This determines if the source of the mount is from another host. If it's
143*5c51f124SMoriah Waterland  * from this host, then it might be writable. This returns NOT_REMOTE if it's
144*5c51f124SMoriah Waterland  * pure local, REAL_REMOTE if it's being served from another host and
145*5c51f124SMoriah Waterland  * SELF_SERVE if it's being served by the current host.
146*5c51f124SMoriah Waterland  */
147*5c51f124SMoriah Waterland static int
148*5c51f124SMoriah Waterland is_remote_src(char *source)
149*5c51f124SMoriah Waterland {
150*5c51f124SMoriah Waterland 	static char host_name[HOST_NM_LN];
151*5c51f124SMoriah Waterland 	char source_host[HOST_NM_LN], *src_ptr, *src_host_ptr;
152*5c51f124SMoriah Waterland 	static int hn_len;
153*5c51f124SMoriah Waterland 
154*5c51f124SMoriah Waterland 	if (hn_len == 0) {
155*5c51f124SMoriah Waterland 		/* Find out what host this is. */
156*5c51f124SMoriah Waterland 		(void) sysinfo(SI_HOSTNAME, host_name, HOST_NM_LN);
157*5c51f124SMoriah Waterland 		hn_len = strlen(host_name);
158*5c51f124SMoriah Waterland 	}
159*5c51f124SMoriah Waterland 
160*5c51f124SMoriah Waterland 	if (source[0] == '/')
161*5c51f124SMoriah Waterland 		return (NOT_REMOTE);	/* No server name, so it's local. */
162*5c51f124SMoriah Waterland 
163*5c51f124SMoriah Waterland 	if (strchr(source, ':') == NULL)
164*5c51f124SMoriah Waterland 		return (NOT_REMOTE);	/* it's a floppy disk or something */
165*5c51f124SMoriah Waterland 
166*5c51f124SMoriah Waterland 	src_ptr = source;
167*5c51f124SMoriah Waterland 	src_host_ptr = source_host;
168*5c51f124SMoriah Waterland 
169*5c51f124SMoriah Waterland 	/* Scan to the end of the hostname (find the ":"). */
170*5c51f124SMoriah Waterland 	while (*src_ptr != ':')
171*5c51f124SMoriah Waterland 		*src_host_ptr++ = *src_ptr++;
172*5c51f124SMoriah Waterland 	*src_host_ptr = '\0';
173*5c51f124SMoriah Waterland 
174*5c51f124SMoriah Waterland 	if (strncmp(source, host_name, hn_len) == 0 &&
175*5c51f124SMoriah Waterland 	    *(source+hn_len) == ':' || is_local_host(source_host))
176*5c51f124SMoriah Waterland 		return (SELF_SERVE);	/* Exporting from itself, it's local. */
177*5c51f124SMoriah Waterland 
178*5c51f124SMoriah Waterland 	return (REAL_REMOTE);
179*5c51f124SMoriah Waterland }
180*5c51f124SMoriah Waterland 
181*5c51f124SMoriah Waterland /*
182*5c51f124SMoriah Waterland  * This determines if an apparently writeable filesystem is really writeable
183*5c51f124SMoriah Waterland  * or if it's been shared over the network with root-restrictive options.
184*5c51f124SMoriah Waterland  */
185*5c51f124SMoriah Waterland static int
186*5c51f124SMoriah Waterland really_write(char *mountpt)
187*5c51f124SMoriah Waterland {
188*5c51f124SMoriah Waterland 	char testfile[PATH_MAX];
189*5c51f124SMoriah Waterland 	int fd, retval = 0;
190*5c51f124SMoriah Waterland 	struct stat status;
191*5c51f124SMoriah Waterland 
192*5c51f124SMoriah Waterland 	(void) snprintf(testfile, sizeof (testfile), "%s/testXXXXXX", mountpt);
193*5c51f124SMoriah Waterland 
194*5c51f124SMoriah Waterland 	if (mktemp(testfile) == NULL)
195*5c51f124SMoriah Waterland 		return (0);	/* may as well be read-only */
196*5c51f124SMoriah Waterland 	/* LINTED do not use creat(); use open(path,... */
197*5c51f124SMoriah Waterland 	else if ((fd = creat(testfile, 0777)) == -1)
198*5c51f124SMoriah Waterland 		return (0);	/* can't write */
199*5c51f124SMoriah Waterland 	else if (fstat(fd, &status) == -1)
200*5c51f124SMoriah Waterland 		retval = 0;	/* may as well be read-only */
201*5c51f124SMoriah Waterland 	else if (status.st_uid != 0)
202*5c51f124SMoriah Waterland 		retval = 0;	/* too many restrictions */
203*5c51f124SMoriah Waterland 	else
204*5c51f124SMoriah Waterland 		retval = 1;
205*5c51f124SMoriah Waterland 
206*5c51f124SMoriah Waterland 	(void) close(fd);
207*5c51f124SMoriah Waterland 	(void) unlink(testfile);
208*5c51f124SMoriah Waterland 
209*5c51f124SMoriah Waterland 	return (retval);
210*5c51f124SMoriah Waterland }
211*5c51f124SMoriah Waterland 
212*5c51f124SMoriah Waterland /* This returns the hostname portion of a remote path. */
213*5c51f124SMoriah Waterland char *
214*5c51f124SMoriah Waterland get_server_host(short n)
215*5c51f124SMoriah Waterland {
216*5c51f124SMoriah Waterland 	static char hostname[HOST_NM_LN], *host_end;
217*5c51f124SMoriah Waterland 
218*5c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
219*5c51f124SMoriah Waterland 		return ("unknown source");
220*5c51f124SMoriah Waterland 	}
221*5c51f124SMoriah Waterland 
222*5c51f124SMoriah Waterland 	if (n >= 0 && n < fs_tab_used) {
223*5c51f124SMoriah Waterland 		(void) strcpy(hostname, fs_tab[n]->remote_name);
224*5c51f124SMoriah Waterland 		if ((host_end = strchr(hostname, ':')) == NULL) {
225*5c51f124SMoriah Waterland 			if ((strcmp(fs_tab[n]->fstype, MNTTYPE_AUTO)) == NULL)
226*5c51f124SMoriah Waterland 				return ("automounter");
227*5c51f124SMoriah Waterland 			else
228*5c51f124SMoriah Waterland 				return (fs_tab[n]->fstype);
229*5c51f124SMoriah Waterland 		} else {
230*5c51f124SMoriah Waterland 			*host_end = '\0';
231*5c51f124SMoriah Waterland 			return (hostname);
232*5c51f124SMoriah Waterland 		}
233*5c51f124SMoriah Waterland 	}
234*5c51f124SMoriah Waterland 
235*5c51f124SMoriah Waterland 	return ("unknown source");
236*5c51f124SMoriah Waterland }
237*5c51f124SMoriah Waterland 
238*5c51f124SMoriah Waterland /*
239*5c51f124SMoriah Waterland  * This pulls the path out of a hostpath which may be of the form host:path
240*5c51f124SMoriah Waterland  * where path is an absolute path. NOTE: If path turns out to be relative,
241*5c51f124SMoriah Waterland  * this returns NULL.
242*5c51f124SMoriah Waterland  */
243*5c51f124SMoriah Waterland static char *
244*5c51f124SMoriah Waterland path_part(char *hostpath)
245*5c51f124SMoriah Waterland {
246*5c51f124SMoriah Waterland 	char *host_end;
247*5c51f124SMoriah Waterland 
248*5c51f124SMoriah Waterland 	if ((host_end = strchr(hostpath, ':')) == NULL && hostpath[0] == '/')
249*5c51f124SMoriah Waterland 		return (hostpath);	/* It's already legit. */
250*5c51f124SMoriah Waterland 
251*5c51f124SMoriah Waterland 	if (*(host_end+1) == '/')
252*5c51f124SMoriah Waterland 		return (host_end+1);	/* Here's the path part. */
253*5c51f124SMoriah Waterland 
254*5c51f124SMoriah Waterland 	return (NULL);
255*5c51f124SMoriah Waterland }
256*5c51f124SMoriah Waterland 
257*5c51f124SMoriah Waterland /*
258*5c51f124SMoriah Waterland  * This scans the filesystems already mounted to see if this remote mount is
259*5c51f124SMoriah Waterland  * already in place on the server. This scans the fs_tab for a remote_name
260*5c51f124SMoriah Waterland  * exactly matching the client's. It stores the current entry number
261*5c51f124SMoriah Waterland  * corresponding to this mount in the static match_mount.
262*5c51f124SMoriah Waterland  *
263*5c51f124SMoriah Waterland  * Returns:
264*5c51f124SMoriah Waterland  *	MNT_NOT		Couldn't find it.
265*5c51f124SMoriah Waterland  *	MNT_EXACT	This has actually been manually mounted for us
266*5c51f124SMoriah Waterland  *	MNT_AVAIL	This is mounted for the server, but needs to be
267*5c51f124SMoriah Waterland  *			loopback mounted from the client's perspective.
268*5c51f124SMoriah Waterland  */
269*5c51f124SMoriah Waterland static int
270*5c51f124SMoriah Waterland already_mounted(struct vfstab *vfs, int is_local_host, char *client_path,
271*5c51f124SMoriah Waterland     char *host_path)
272*5c51f124SMoriah Waterland {
273*5c51f124SMoriah Waterland 	int i;
274*5c51f124SMoriah Waterland 
275*5c51f124SMoriah Waterland 	match_mount = -1;
276*5c51f124SMoriah Waterland 
277*5c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
278*5c51f124SMoriah Waterland 		return (MNT_NOT);
279*5c51f124SMoriah Waterland 	}
280*5c51f124SMoriah Waterland 
281*5c51f124SMoriah Waterland 	for (i = 0; i < fs_tab_used; i++) {
282*5c51f124SMoriah Waterland 		/*
283*5c51f124SMoriah Waterland 		 * Determine if this has been manually mounted exactly as we
284*5c51f124SMoriah Waterland 		 * require. Begin by finding a mount on our current
285*5c51f124SMoriah Waterland 		 * mountpoint.
286*5c51f124SMoriah Waterland 		 */
287*5c51f124SMoriah Waterland 		if (strcmp(fs_tab[i]->name, client_path) == 0) {
288*5c51f124SMoriah Waterland 			/*
289*5c51f124SMoriah Waterland 			 * Now see if it is really the same mount. This isn't
290*5c51f124SMoriah Waterland 			 * smart enough to find mounts on top of mounts, but
291*5c51f124SMoriah Waterland 			 * assuming there is no conspiracy to fool this
292*5c51f124SMoriah Waterland 			 * function, it will be good enough.
293*5c51f124SMoriah Waterland 			 */
294*5c51f124SMoriah Waterland 			if (is_local_host &&
295*5c51f124SMoriah Waterland 			    strcmp(fs_tab[i]->remote_name, host_path) == 0) {
296*5c51f124SMoriah Waterland 				match_mount = i;
297*5c51f124SMoriah Waterland 				return (MNT_EXACT);
298*5c51f124SMoriah Waterland 			}
299*5c51f124SMoriah Waterland 		}
300*5c51f124SMoriah Waterland 
301*5c51f124SMoriah Waterland 		/* Determine if this mount is available to the server. */
302*5c51f124SMoriah Waterland 		if (strcmp(fs_tab[i]->remote_name, vfs->vfs_special) == 0) {
303*5c51f124SMoriah Waterland 			match_mount = i;
304*5c51f124SMoriah Waterland 			return (MNT_AVAIL);
305*5c51f124SMoriah Waterland 		}
306*5c51f124SMoriah Waterland 	}
307*5c51f124SMoriah Waterland 	return (MNT_NOT);
308*5c51f124SMoriah Waterland }
309*5c51f124SMoriah Waterland 
310*5c51f124SMoriah Waterland /*
311*5c51f124SMoriah Waterland  * This function unmounts all of the loopback mounts created for the client.
312*5c51f124SMoriah Waterland  * If no client stuff is mounted, this is completely benign, it finds that
313*5c51f124SMoriah Waterland  * nothing is mounted up and returns. It returns "1" for unmounted everything
314*5c51f124SMoriah Waterland  * OK and "0" for failure.
315*5c51f124SMoriah Waterland  */
316*5c51f124SMoriah Waterland int
317*5c51f124SMoriah Waterland unmount_client()
318*5c51f124SMoriah Waterland {
319*5c51f124SMoriah Waterland 	int	errcode;
320*5c51f124SMoriah Waterland 	int	exit_no;
321*5c51f124SMoriah Waterland 	int	n;
322*5c51f124SMoriah Waterland 	int	retcode = 1;
323*5c51f124SMoriah Waterland 	int	status;
324*5c51f124SMoriah Waterland 	pid_t	pid;
325*5c51f124SMoriah Waterland 	pid_t	pid_return;
326*5c51f124SMoriah Waterland 
327*5c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
328*5c51f124SMoriah Waterland 		return (1);
329*5c51f124SMoriah Waterland 	}
330*5c51f124SMoriah Waterland 
331*5c51f124SMoriah Waterland 	for (n = 0; n < fs_tab_used-1; n++) {
332*5c51f124SMoriah Waterland 		/* If the filesystem is mounted and this utility did it ... */
333*5c51f124SMoriah Waterland 		if (fs_tab[n]->cl_mounted && fs_tab[n]->srvr_map) {
334*5c51f124SMoriah Waterland 			char	*arg[3];
335*5c51f124SMoriah Waterland 
336*5c51f124SMoriah Waterland 			/* create arglist for umount command */
337*5c51f124SMoriah Waterland 
338*5c51f124SMoriah Waterland 			arg[0] = UMOUNT;
339*5c51f124SMoriah Waterland 			arg[1] = fs_tab[n]->name;
340*5c51f124SMoriah Waterland 			arg[2] = (char *)NULL;
341*5c51f124SMoriah Waterland 
342*5c51f124SMoriah Waterland 			/* flush standard i/o before creating new process */
343*5c51f124SMoriah Waterland 
344*5c51f124SMoriah Waterland 			(void) fflush(stderr);
345*5c51f124SMoriah Waterland 			(void) fflush(stdout);
346*5c51f124SMoriah Waterland 
347*5c51f124SMoriah Waterland 			/*
348*5c51f124SMoriah Waterland 			 * create new process to execute command in;
349*5c51f124SMoriah Waterland 			 * vfork is being used to avoid duplicating the parents
350*5c51f124SMoriah Waterland 			 * memory space - this means that the child process may
351*5c51f124SMoriah Waterland 			 * not modify any of the parents memory including the
352*5c51f124SMoriah Waterland 			 * standard i/o descriptors - all the child can do is
353*5c51f124SMoriah Waterland 			 * adjust interrupts and open files as a prelude to a
354*5c51f124SMoriah Waterland 			 * call to exec().
355*5c51f124SMoriah Waterland 			 */
356*5c51f124SMoriah Waterland 
357*5c51f124SMoriah Waterland 			pid = vfork();
358*5c51f124SMoriah Waterland 			if (pid < 0) {
359*5c51f124SMoriah Waterland 				/* fork failed! */
360*5c51f124SMoriah Waterland 
361*5c51f124SMoriah Waterland 				logerr(WRN_BAD_FORK, errno, strerror(errno));
362*5c51f124SMoriah Waterland 				retcode = 0;
363*5c51f124SMoriah Waterland 			} else if (pid > 0) {
364*5c51f124SMoriah Waterland 				/*
365*5c51f124SMoriah Waterland 				 * this is the parent process
366*5c51f124SMoriah Waterland 				 */
367*5c51f124SMoriah Waterland 
368*5c51f124SMoriah Waterland 				status = 0;
369*5c51f124SMoriah Waterland 				pid_return = waitpid(pid, &status, 0);
370*5c51f124SMoriah Waterland 
371*5c51f124SMoriah Waterland 				if (pid_return != pid) {
372*5c51f124SMoriah Waterland 					logerr(WRN_BAD_WAIT, pid, pid_return,
373*5c51f124SMoriah Waterland 						(unsigned long)status, errno,
374*5c51f124SMoriah Waterland 						strerror(errno));
375*5c51f124SMoriah Waterland 					retcode = 0;
376*5c51f124SMoriah Waterland 				}
377*5c51f124SMoriah Waterland 
378*5c51f124SMoriah Waterland 				/*
379*5c51f124SMoriah Waterland 				 * If the child was stopped or killed by a
380*5c51f124SMoriah Waterland 				 * signal or exied with any code but 0, we
381*5c51f124SMoriah Waterland 				 * assume the mount has failed.
382*5c51f124SMoriah Waterland 				 */
383*5c51f124SMoriah Waterland 
384*5c51f124SMoriah Waterland 				if (!WIFEXITED(status) ||
385*5c51f124SMoriah Waterland 				    (errcode = WEXITSTATUS(status))) {
386*5c51f124SMoriah Waterland 					retcode = 0;
387*5c51f124SMoriah Waterland 					logerr(WRN_FSTAB_UMOUNT,
388*5c51f124SMoriah Waterland 						fs_tab[n]->name, errcode);
389*5c51f124SMoriah Waterland 				} else {
390*5c51f124SMoriah Waterland 					fs_tab[n]->cl_mounted = 0;
391*5c51f124SMoriah Waterland 				}
392*5c51f124SMoriah Waterland 			} else {
393*5c51f124SMoriah Waterland 				/*
394*5c51f124SMoriah Waterland 				 * this is the child process
395*5c51f124SMoriah Waterland 				 */
396*5c51f124SMoriah Waterland 
397*5c51f124SMoriah Waterland 				int	i;
398*5c51f124SMoriah Waterland 
399*5c51f124SMoriah Waterland 				/* reset any signals to default */
400*5c51f124SMoriah Waterland 
401*5c51f124SMoriah Waterland 				for (i = 0; i < NSIG; i++) {
402*5c51f124SMoriah Waterland 					(void) sigset(i, SIG_DFL);
403*5c51f124SMoriah Waterland 				}
404*5c51f124SMoriah Waterland 
405*5c51f124SMoriah Waterland 				/*
406*5c51f124SMoriah Waterland 				 * Redirect output to /dev/null because the
407*5c51f124SMoriah Waterland 				 * umount error message may be confusing to
408*5c51f124SMoriah Waterland 				 * the user.
409*5c51f124SMoriah Waterland 				 */
410*5c51f124SMoriah Waterland 
411*5c51f124SMoriah Waterland 				i = open("/dev/null", O_WRONLY);
412*5c51f124SMoriah Waterland 				if (i >= 0) {
413*5c51f124SMoriah Waterland 					dup2(2, STDERR_FILENO);
414*5c51f124SMoriah Waterland 				}
415*5c51f124SMoriah Waterland 
416*5c51f124SMoriah Waterland 				/* close all file descriptors except stdio */
417*5c51f124SMoriah Waterland 
418*5c51f124SMoriah Waterland 				closefrom(3);
419*5c51f124SMoriah Waterland 
420*5c51f124SMoriah Waterland 				exit_no = execve(arg[0], arg, environ);
421*5c51f124SMoriah Waterland 				_exit(exit_no);
422*5c51f124SMoriah Waterland 			}
423*5c51f124SMoriah Waterland 		}
424*5c51f124SMoriah Waterland 	}
425*5c51f124SMoriah Waterland 
426*5c51f124SMoriah Waterland 	return (retcode);
427*5c51f124SMoriah Waterland }
428*5c51f124SMoriah Waterland 
429*5c51f124SMoriah Waterland /*
430*5c51f124SMoriah Waterland  * This function creates the necessary loopback mounts to emulate the client
431*5c51f124SMoriah Waterland  * configuration with respect to the server. If this is being run on a
432*5c51f124SMoriah Waterland  * standalone or the installation is actually to the local system, this call
433*5c51f124SMoriah Waterland  * is benign since srvr_map won't be set anywhere. It returns "1" for mounted
434*5c51f124SMoriah Waterland  * everything OK and "0" for failure.
435*5c51f124SMoriah Waterland  */
436*5c51f124SMoriah Waterland int
437*5c51f124SMoriah Waterland mount_client()
438*5c51f124SMoriah Waterland {
439*5c51f124SMoriah Waterland 	int	errcode;
440*5c51f124SMoriah Waterland 	int	exit_no;
441*5c51f124SMoriah Waterland 	int	n;
442*5c51f124SMoriah Waterland 	int	retcode = 1;
443*5c51f124SMoriah Waterland 	int	status;
444*5c51f124SMoriah Waterland 	pid_t	pid;
445*5c51f124SMoriah Waterland 	pid_t	pid_return;
446*5c51f124SMoriah Waterland 
447*5c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
448*5c51f124SMoriah Waterland 		return (1);
449*5c51f124SMoriah Waterland 	}
450*5c51f124SMoriah Waterland 
451*5c51f124SMoriah Waterland 	for (n = fs_tab_used-1; n >= 0; n--) {
452*5c51f124SMoriah Waterland 		/*
453*5c51f124SMoriah Waterland 		 * If the filesystem is mounted (meaning available) and the
454*5c51f124SMoriah Waterland 		 * apparent filesystem can be mapped to a local filesystem
455*5c51f124SMoriah Waterland 		 * AND the local filesystem is not the same as the target
456*5c51f124SMoriah Waterland 		 * filesystem, mount it.
457*5c51f124SMoriah Waterland 		 */
458*5c51f124SMoriah Waterland 		if (fs_tab[n]->mounted && fs_tab[n]->srvr_map) {
459*5c51f124SMoriah Waterland 			char	*arg[6];
460*5c51f124SMoriah Waterland 
461*5c51f124SMoriah Waterland 			/* create arglist for mount command */
462*5c51f124SMoriah Waterland 
463*5c51f124SMoriah Waterland 			arg[0] = MOUNT;
464*5c51f124SMoriah Waterland 			arg[1] = "-F";
465*5c51f124SMoriah Waterland 			arg[2] = "lofs";
466*5c51f124SMoriah Waterland 			arg[3] = fs_tab[n]->remote_name;
467*5c51f124SMoriah Waterland 			arg[4] = fs_tab[n]->name;
468*5c51f124SMoriah Waterland 			arg[5] = (char *)NULL;
469*5c51f124SMoriah Waterland 
470*5c51f124SMoriah Waterland 			/* flush standard i/o before creating new process */
471*5c51f124SMoriah Waterland 
472*5c51f124SMoriah Waterland 			(void) fflush(stderr);
473*5c51f124SMoriah Waterland 			(void) fflush(stdout);
474*5c51f124SMoriah Waterland 
475*5c51f124SMoriah Waterland 			/*
476*5c51f124SMoriah Waterland 			 * create new process to execute command in;
477*5c51f124SMoriah Waterland 			 * vfork is being used to avoid duplicating the parents
478*5c51f124SMoriah Waterland 			 * memory space - this means that the child process may
479*5c51f124SMoriah Waterland 			 * not modify any of the parents memory including the
480*5c51f124SMoriah Waterland 			 * standard i/o descriptors - all the child can do is
481*5c51f124SMoriah Waterland 			 * adjust interrupts and open files as a prelude to a
482*5c51f124SMoriah Waterland 			 * call to exec().
483*5c51f124SMoriah Waterland 			 */
484*5c51f124SMoriah Waterland 
485*5c51f124SMoriah Waterland 			pid = vfork();
486*5c51f124SMoriah Waterland 			if (pid < 0) {
487*5c51f124SMoriah Waterland 				/* fork failed! */
488*5c51f124SMoriah Waterland 
489*5c51f124SMoriah Waterland 				logerr(WRN_BAD_FORK, errno, strerror(errno));
490*5c51f124SMoriah Waterland 				retcode = 0;
491*5c51f124SMoriah Waterland 			} else if (pid > 0) {
492*5c51f124SMoriah Waterland 				/*
493*5c51f124SMoriah Waterland 				 * this is the parent process
494*5c51f124SMoriah Waterland 				 */
495*5c51f124SMoriah Waterland 
496*5c51f124SMoriah Waterland 				pid_return = waitpid(pid, &status, 0);
497*5c51f124SMoriah Waterland 
498*5c51f124SMoriah Waterland 				if (pid_return != pid) {
499*5c51f124SMoriah Waterland 					logerr(WRN_BAD_WAIT, pid, pid_return,
500*5c51f124SMoriah Waterland 						(unsigned long)status, errno,
501*5c51f124SMoriah Waterland 						strerror(errno));
502*5c51f124SMoriah Waterland 					retcode = 0;
503*5c51f124SMoriah Waterland 				}
504*5c51f124SMoriah Waterland 
505*5c51f124SMoriah Waterland 				/*
506*5c51f124SMoriah Waterland 				 * If the child was stopped or killed by a
507*5c51f124SMoriah Waterland 				 * signal or exied with any code but 0, we
508*5c51f124SMoriah Waterland 				 * assume the mount has failed.
509*5c51f124SMoriah Waterland 				 */
510*5c51f124SMoriah Waterland 
511*5c51f124SMoriah Waterland 				if (!WIFEXITED(status) ||
512*5c51f124SMoriah Waterland 				    (errcode = WEXITSTATUS(status))) {
513*5c51f124SMoriah Waterland 					retcode = 0;
514*5c51f124SMoriah Waterland 					fs_tab[n]->mnt_failed = 1;
515*5c51f124SMoriah Waterland 					logerr(WRN_FSTAB_MOUNT,
516*5c51f124SMoriah Waterland 					    fs_tab[n]->name, errcode);
517*5c51f124SMoriah Waterland 				} else {
518*5c51f124SMoriah Waterland 					fs_tab[n]->cl_mounted = 1;
519*5c51f124SMoriah Waterland 				}
520*5c51f124SMoriah Waterland 			} else {
521*5c51f124SMoriah Waterland 				/*
522*5c51f124SMoriah Waterland 				 * this is the child process
523*5c51f124SMoriah Waterland 				 */
524*5c51f124SMoriah Waterland 
525*5c51f124SMoriah Waterland 				int	i;
526*5c51f124SMoriah Waterland 
527*5c51f124SMoriah Waterland 				/* reset all signals to default */
528*5c51f124SMoriah Waterland 
529*5c51f124SMoriah Waterland 				for (i = 0; i < NSIG; i++) {
530*5c51f124SMoriah Waterland 					(void) sigset(i, SIG_DFL);
531*5c51f124SMoriah Waterland 				}
532*5c51f124SMoriah Waterland 
533*5c51f124SMoriah Waterland 				/*
534*5c51f124SMoriah Waterland 				 * Redirect output to /dev/null because the
535*5c51f124SMoriah Waterland 				 * mount error message may be confusing to
536*5c51f124SMoriah Waterland 				 * the user.
537*5c51f124SMoriah Waterland 				 */
538*5c51f124SMoriah Waterland 
539*5c51f124SMoriah Waterland 				i = open("/dev/null", O_WRONLY);
540*5c51f124SMoriah Waterland 				if (i >= 0) {
541*5c51f124SMoriah Waterland 					dup2(i, STDERR_FILENO);
542*5c51f124SMoriah Waterland 				}
543*5c51f124SMoriah Waterland 
544*5c51f124SMoriah Waterland 				/* close all file descriptors except stdio */
545*5c51f124SMoriah Waterland 
546*5c51f124SMoriah Waterland 				closefrom(3);
547*5c51f124SMoriah Waterland 
548*5c51f124SMoriah Waterland 				exit_no = execve(arg[0], arg, environ);
549*5c51f124SMoriah Waterland 				_exit(exit_no);
550*5c51f124SMoriah Waterland 				/*NOTREACHED*/
551*5c51f124SMoriah Waterland 			}
552*5c51f124SMoriah Waterland 		}
553*5c51f124SMoriah Waterland 	}
554*5c51f124SMoriah Waterland 	return (retcode);
555*5c51f124SMoriah Waterland }
556*5c51f124SMoriah Waterland 
557*5c51f124SMoriah Waterland /*
558*5c51f124SMoriah Waterland  * This function maps path, on a loopback filesystem, back to the real server
559*5c51f124SMoriah Waterland  * filesystem. fsys_value is the fs_tab[] entry to which the loopback'd path is
560*5c51f124SMoriah Waterland  * mapped. This returns a pointer to a static area. If the result is needed
561*5c51f124SMoriah Waterland  * for further processing, it should be strdup()'d or something.
562*5c51f124SMoriah Waterland  */
563*5c51f124SMoriah Waterland char *
564*5c51f124SMoriah Waterland server_map(char *path, short fsys_value)
565*5c51f124SMoriah Waterland {
566*5c51f124SMoriah Waterland 	static char server_construction[PATH_MAX];
567*5c51f124SMoriah Waterland 
568*5c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
569*5c51f124SMoriah Waterland 		(void) strcpy(server_construction, path);
570*5c51f124SMoriah Waterland 	} else if (fsys_value >= 0 && fsys_value < fs_tab_used) {
571*5c51f124SMoriah Waterland 		(void) snprintf(server_construction,
572*5c51f124SMoriah Waterland 			sizeof (server_construction),
573*5c51f124SMoriah Waterland 			"%s%s", fs_tab[fsys_value]->remote_name,
574*5c51f124SMoriah Waterland 			path+strlen(fs_tab[fsys_value]->name));
575*5c51f124SMoriah Waterland 	} else {
576*5c51f124SMoriah Waterland 		(void) strcpy(server_construction, path);
577*5c51f124SMoriah Waterland 	}
578*5c51f124SMoriah Waterland 
579*5c51f124SMoriah Waterland 	return (server_construction);
580*5c51f124SMoriah Waterland }
581*5c51f124SMoriah Waterland 
582*5c51f124SMoriah Waterland /* This function sets up the standard parts of the fs_tab. */
583*5c51f124SMoriah Waterland static struct fstable *
584*5c51f124SMoriah Waterland fs_tab_init(char *mountp, char *fstype)
585*5c51f124SMoriah Waterland {
586*5c51f124SMoriah Waterland 	struct fstable *nfte;
587*5c51f124SMoriah Waterland 
588*5c51f124SMoriah Waterland 	/* Create the array if necessary. */
589*5c51f124SMoriah Waterland 	if (fs_list == -1) {
590*5c51f124SMoriah Waterland 		fs_list = ar_create(ALLOC_CHUNK,
591*5c51f124SMoriah Waterland 		    (unsigned)sizeof (struct fstable),
592*5c51f124SMoriah Waterland 		    "filesystem mount data");
593*5c51f124SMoriah Waterland 		if (fs_list == -1) {
594*5c51f124SMoriah Waterland 			progerr(ERR_MALLOC, "fs_list", errno, strerror(errno));
595*5c51f124SMoriah Waterland 			return (NULL);
596*5c51f124SMoriah Waterland 		}
597*5c51f124SMoriah Waterland 	}
598*5c51f124SMoriah Waterland 
599*5c51f124SMoriah Waterland 	/*
600*5c51f124SMoriah Waterland 	 * Allocate an fstable entry for this mnttab entry.
601*5c51f124SMoriah Waterland 	 */
602*5c51f124SMoriah Waterland 	if ((nfte = *(struct fstable **)ar_next_avail(fs_list))
603*5c51f124SMoriah Waterland 	    == NULL) {
604*5c51f124SMoriah Waterland 		progerr(ERR_MALLOC, "nfte", errno, strerror(errno));
605*5c51f124SMoriah Waterland 		return (NULL);
606*5c51f124SMoriah Waterland 	}
607*5c51f124SMoriah Waterland 
608*5c51f124SMoriah Waterland 	/*
609*5c51f124SMoriah Waterland 	 * Point fs_tab at the head of the array again, since it may have
610*5c51f124SMoriah Waterland 	 * moved due to realloc in ar_next_avail(). If ar_next_avail() realizes
611*5c51f124SMoriah Waterland 	 * that there is no more room to grow the array, it reallocates the
612*5c51f124SMoriah Waterland 	 * array. Because we stored pointer to that array in fs_tab, we need
613*5c51f124SMoriah Waterland 	 * to make sure that it is updated as well.
614*5c51f124SMoriah Waterland 	 */
615*5c51f124SMoriah Waterland 	if ((fs_tab = (struct fstable **)ar_get_head(fs_list)) == NULL) {
616*5c51f124SMoriah Waterland 		progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno));
617*5c51f124SMoriah Waterland 		return (NULL);
618*5c51f124SMoriah Waterland 	}
619*5c51f124SMoriah Waterland 
620*5c51f124SMoriah Waterland 	/*
621*5c51f124SMoriah Waterland 	 * Get the length of the 'mount point' name.
622*5c51f124SMoriah Waterland 	 */
623*5c51f124SMoriah Waterland 	nfte->namlen = strlen(mountp);
624*5c51f124SMoriah Waterland 	/*
625*5c51f124SMoriah Waterland 	 * Allocate space for the 'mount point' name.
626*5c51f124SMoriah Waterland 	 */
627*5c51f124SMoriah Waterland 	if ((nfte->name = malloc(nfte->namlen+1)) == NULL) {
628*5c51f124SMoriah Waterland 		progerr(ERR_MALLOC, "name", errno, strerror(errno));
629*5c51f124SMoriah Waterland 		return (NULL);
630*5c51f124SMoriah Waterland 	}
631*5c51f124SMoriah Waterland 	(void) strcpy(nfte->name, mountp);
632*5c51f124SMoriah Waterland 
633*5c51f124SMoriah Waterland 	if ((nfte->fstype = malloc(strlen(fstype)+1)) == NULL) {
634*5c51f124SMoriah Waterland 		progerr(ERR_MALLOC, "fstype", errno, strerror(errno));
635*5c51f124SMoriah Waterland 		return (NULL);
636*5c51f124SMoriah Waterland 	}
637*5c51f124SMoriah Waterland 	(void) strcpy(nfte->fstype, fstype);
638*5c51f124SMoriah Waterland 
639*5c51f124SMoriah Waterland 	fs_tab_used++;
640*5c51f124SMoriah Waterland 
641*5c51f124SMoriah Waterland 	return (nfte);
642*5c51f124SMoriah Waterland }
643*5c51f124SMoriah Waterland 
644*5c51f124SMoriah Waterland /* This function frees all memory associated with the filesystem table. */
645*5c51f124SMoriah Waterland void
646*5c51f124SMoriah Waterland fs_tab_free(void)
647*5c51f124SMoriah Waterland {
648*5c51f124SMoriah Waterland 	int n;
649*5c51f124SMoriah Waterland 
650*5c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
651*5c51f124SMoriah Waterland 		return;
652*5c51f124SMoriah Waterland 	}
653*5c51f124SMoriah Waterland 
654*5c51f124SMoriah Waterland 	for (n = 0; n < fs_tab_used; n++) {
655*5c51f124SMoriah Waterland 		free(fs_tab[n]->fstype);
656*5c51f124SMoriah Waterland 		free(fs_tab[n]->name);
657*5c51f124SMoriah Waterland 		free(fs_tab[n]->remote_name);
658*5c51f124SMoriah Waterland 	}
659*5c51f124SMoriah Waterland 
660*5c51f124SMoriah Waterland 	ar_free(fs_list);
661*5c51f124SMoriah Waterland }
662*5c51f124SMoriah Waterland 
663*5c51f124SMoriah Waterland /* This function scans a string of mount options for a specific keyword. */
664*5c51f124SMoriah Waterland static int
665*5c51f124SMoriah Waterland hasopt(char *options, char *keyword)
666*5c51f124SMoriah Waterland {
667*5c51f124SMoriah Waterland 	char vfs_options[VFS_LINE_MAX], *optptr;
668*5c51f124SMoriah Waterland 
669*5c51f124SMoriah Waterland 	if (!options) {
670*5c51f124SMoriah Waterland 		(void) strcpy(vfs_options, "ro");
671*5c51f124SMoriah Waterland 	} else {
672*5c51f124SMoriah Waterland 		(void) strcpy(vfs_options, options);
673*5c51f124SMoriah Waterland 	}
674*5c51f124SMoriah Waterland 
675*5c51f124SMoriah Waterland 	while (optptr = strrchr(vfs_options, ',')) {
676*5c51f124SMoriah Waterland 		*optptr++ = '\0';
677*5c51f124SMoriah Waterland 
678*5c51f124SMoriah Waterland 		if (strcmp(optptr, keyword) == 0)
679*5c51f124SMoriah Waterland 			return (1);
680*5c51f124SMoriah Waterland 	}
681*5c51f124SMoriah Waterland 
682*5c51f124SMoriah Waterland 	/* Now deal with the remainder. */
683*5c51f124SMoriah Waterland 	if (strcmp(vfs_options, keyword) == 0)
684*5c51f124SMoriah Waterland 		return (1);
685*5c51f124SMoriah Waterland 
686*5c51f124SMoriah Waterland 	return (0);
687*5c51f124SMoriah Waterland }
688*5c51f124SMoriah Waterland 
689*5c51f124SMoriah Waterland /*
690*5c51f124SMoriah Waterland  * This function constructs a new filesystem table (fs_tab[]) entry based on
691*5c51f124SMoriah Waterland  * an /etc/mnttab entry. When it returns, the new entry has been inserted
692*5c51f124SMoriah Waterland  * into fs_tab[].
693*5c51f124SMoriah Waterland  */
694*5c51f124SMoriah Waterland static int
695*5c51f124SMoriah Waterland construct_mt(struct mnttab *mt)
696*5c51f124SMoriah Waterland {
697*5c51f124SMoriah Waterland 	struct	fstable	*nfte;
698*5c51f124SMoriah Waterland 
699*5c51f124SMoriah Waterland 	/*
700*5c51f124SMoriah Waterland 	 * Initialize fstable structure and make the standard entries.
701*5c51f124SMoriah Waterland 	 */
702*5c51f124SMoriah Waterland 	if ((nfte = fs_tab_init(mt->mnt_mountp, mt->mnt_fstype)) == NULL)
703*5c51f124SMoriah Waterland 		return (1);
704*5c51f124SMoriah Waterland 
705*5c51f124SMoriah Waterland 	/* See if this is served from another host. */
706*5c51f124SMoriah Waterland 	if (is_remote_src(mt->mnt_special) == REAL_REMOTE ||
707*5c51f124SMoriah Waterland 	    strcmp(mt->mnt_fstype, MNTTYPE_AUTO) == 0)
708*5c51f124SMoriah Waterland 		nfte->remote = 1;
709*5c51f124SMoriah Waterland 	else
710*5c51f124SMoriah Waterland 		nfte->remote = 0;
711*5c51f124SMoriah Waterland 
712*5c51f124SMoriah Waterland 	/* It's mounted now (by definition), so we don't have to remap it. */
713*5c51f124SMoriah Waterland 	nfte->srvr_map = 0;
714*5c51f124SMoriah Waterland 	nfte->mounted = 1;
715*5c51f124SMoriah Waterland 
716*5c51f124SMoriah Waterland 	nfte->remote_name = strdup(mt->mnt_special);
717*5c51f124SMoriah Waterland 
718*5c51f124SMoriah Waterland 	/*
719*5c51f124SMoriah Waterland 	 * This checks the mount commands which establish the most
720*5c51f124SMoriah Waterland 	 * basic level of access. Later further tests may be
721*5c51f124SMoriah Waterland 	 * necessary to fully qualify this. We set this bit
722*5c51f124SMoriah Waterland 	 * preliminarily because we have access to the mount data
723*5c51f124SMoriah Waterland 	 * now.
724*5c51f124SMoriah Waterland 	 */
725*5c51f124SMoriah Waterland 	nfte->writeable = 0;	/* Assume read-only. */
726*5c51f124SMoriah Waterland 	if (hasmntopt(mt, MNTOPT_RO) == NULL) {
727*5c51f124SMoriah Waterland 		nfte->writeable = 1;
728*5c51f124SMoriah Waterland 		if (!(nfte->remote))
729*5c51f124SMoriah Waterland 			/*
730*5c51f124SMoriah Waterland 			 * There's no network involved, so this
731*5c51f124SMoriah Waterland 			 * assessment is confirmed.
732*5c51f124SMoriah Waterland 			 */
733*5c51f124SMoriah Waterland 			nfte->write_tested = 1;
734*5c51f124SMoriah Waterland 	} else
735*5c51f124SMoriah Waterland 		/* read-only is read-only */
736*5c51f124SMoriah Waterland 		nfte->write_tested = 1;
737*5c51f124SMoriah Waterland 
738*5c51f124SMoriah Waterland 	/* Is this coming to us from a server? */
739*5c51f124SMoriah Waterland 	if (nfte->remote && !(nfte->writeable))
740*5c51f124SMoriah Waterland 		nfte->served = 1;
741*5c51f124SMoriah Waterland 
742*5c51f124SMoriah Waterland 	return (0);
743*5c51f124SMoriah Waterland }
744*5c51f124SMoriah Waterland 
745*5c51f124SMoriah Waterland /*
746*5c51f124SMoriah Waterland  * This function modifies an existing fs_tab[] entry. It was found mounted up
747*5c51f124SMoriah Waterland  * exactly the way we would have mounted it in mount_client() only at the
748*5c51f124SMoriah Waterland  * time we didn't know it was for the client. Now we do, so we're setting the
749*5c51f124SMoriah Waterland  * various permissions to conform to the client view.
750*5c51f124SMoriah Waterland  */
751*5c51f124SMoriah Waterland static void
752*5c51f124SMoriah Waterland mod_existing(struct vfstab *vfsent, int fstab_entry, int is_remote)
753*5c51f124SMoriah Waterland {
754*5c51f124SMoriah Waterland 	/*
755*5c51f124SMoriah Waterland 	 * Establish whether the client will see this as served.
756*5c51f124SMoriah Waterland 	 */
757*5c51f124SMoriah Waterland 	if (is_remote && hasopt(vfsent->vfs_mntopts, MNTOPT_RO))
758*5c51f124SMoriah Waterland 		fs_tab[fstab_entry]->served = 1;
759*5c51f124SMoriah Waterland 
760*5c51f124SMoriah Waterland 	fs_tab[fstab_entry]->cl_mounted = 1;
761*5c51f124SMoriah Waterland }
762*5c51f124SMoriah Waterland 
763*5c51f124SMoriah Waterland /*
764*5c51f124SMoriah Waterland  * This function constructs a new fs_tab[] entry based on
765*5c51f124SMoriah Waterland  * an /etc/vfstab entry. When it returns, the new entry has been inserted
766*5c51f124SMoriah Waterland  * into fstab[].
767*5c51f124SMoriah Waterland  */
768*5c51f124SMoriah Waterland static int
769*5c51f124SMoriah Waterland construct_vfs(struct vfstab *vfsent, char *client_path, char *link_name,
770*5c51f124SMoriah Waterland     int is_remote, int mnt_stat)
771*5c51f124SMoriah Waterland {
772*5c51f124SMoriah Waterland 	int use_link;
773*5c51f124SMoriah Waterland 	struct	fstable	*nfte;
774*5c51f124SMoriah Waterland 
775*5c51f124SMoriah Waterland 	if ((nfte = fs_tab_init(client_path, vfsent->vfs_fstype)) == NULL)
776*5c51f124SMoriah Waterland 		return (1);
777*5c51f124SMoriah Waterland 
778*5c51f124SMoriah Waterland 	nfte->remote = (is_remote == REAL_REMOTE);
779*5c51f124SMoriah Waterland 
780*5c51f124SMoriah Waterland 	/*
781*5c51f124SMoriah Waterland 	 * The file system mounted on the client may or may not be writeable.
782*5c51f124SMoriah Waterland 	 * So we hand it over to fsys() to evaluate. This will have the same
783*5c51f124SMoriah Waterland 	 * read/write attributes as the corresponding mounted filesystem.
784*5c51f124SMoriah Waterland 	 */
785*5c51f124SMoriah Waterland 	use_link = 0;
786*5c51f124SMoriah Waterland 	if (nfte->remote) {
787*5c51f124SMoriah Waterland 		/*
788*5c51f124SMoriah Waterland 		 * Deal here with mount points actually on a system remote
789*5c51f124SMoriah Waterland 		 * from the server.
790*5c51f124SMoriah Waterland 		 */
791*5c51f124SMoriah Waterland 		if (mnt_stat == MNT_NOT) {
792*5c51f124SMoriah Waterland 			/*
793*5c51f124SMoriah Waterland 			 * This filesystem isn't in the current mount table
794*5c51f124SMoriah Waterland 			 * meaning it isn't mounted, the current host can't
795*5c51f124SMoriah Waterland 			 * write to it and there's no point to mapping it for
796*5c51f124SMoriah Waterland 			 * the server.
797*5c51f124SMoriah Waterland 			 */
798*5c51f124SMoriah Waterland 			link_name = NULL;
799*5c51f124SMoriah Waterland 			nfte->mounted = 0;
800*5c51f124SMoriah Waterland 			nfte->srvr_map = 0;
801*5c51f124SMoriah Waterland 			nfte->writeable = 0;
802*5c51f124SMoriah Waterland 		} else {	/* It's MNT_AVAIL. */
803*5c51f124SMoriah Waterland 			/*
804*5c51f124SMoriah Waterland 			 * This filesystem is associated with a current
805*5c51f124SMoriah Waterland 			 * mountpoint. Since it's mounted, it needs to be
806*5c51f124SMoriah Waterland 			 * remapped and it is writable if the real mounted
807*5c51f124SMoriah Waterland 			 * filesystem is writeable.
808*5c51f124SMoriah Waterland 			 */
809*5c51f124SMoriah Waterland 			use_link = 1;
810*5c51f124SMoriah Waterland 			link_name = strdup(fs_tab[match_mount]->name);
811*5c51f124SMoriah Waterland 			nfte->mounted = 1;
812*5c51f124SMoriah Waterland 			nfte->srvr_map = 1;
813*5c51f124SMoriah Waterland 			nfte->writeable = fs_tab[match_mount]->writeable;
814*5c51f124SMoriah Waterland 			nfte->write_tested = fs_tab[match_mount]->write_tested;
815*5c51f124SMoriah Waterland 		}
816*5c51f124SMoriah Waterland 	} else {	/* local filesystem */
817*5c51f124SMoriah Waterland 		use_link = 1;
818*5c51f124SMoriah Waterland 		nfte->mounted = 1;
819*5c51f124SMoriah Waterland 		nfte->srvr_map = 1;
820*5c51f124SMoriah Waterland 		nfte->writeable = fs_tab[fsys(link_name)]->writeable;
821*5c51f124SMoriah Waterland 		nfte->write_tested = 1;
822*5c51f124SMoriah Waterland 	}
823*5c51f124SMoriah Waterland 
824*5c51f124SMoriah Waterland 	/*
825*5c51f124SMoriah Waterland 	 * Now we establish whether the client will see this as served.
826*5c51f124SMoriah Waterland 	 */
827*5c51f124SMoriah Waterland 	if (is_remote && hasopt(vfsent->vfs_mntopts, MNTOPT_RO))
828*5c51f124SMoriah Waterland 		nfte->served = 1;
829*5c51f124SMoriah Waterland 
830*5c51f124SMoriah Waterland 	if (use_link) {
831*5c51f124SMoriah Waterland 		nfte->remote_name = link_name;
832*5c51f124SMoriah Waterland 	} else {
833*5c51f124SMoriah Waterland 		nfte->remote_name = strdup(vfsent->vfs_special);
834*5c51f124SMoriah Waterland 	}
835*5c51f124SMoriah Waterland 
836*5c51f124SMoriah Waterland 	return (0);
837*5c51f124SMoriah Waterland }
838*5c51f124SMoriah Waterland 
839*5c51f124SMoriah Waterland /*
840*5c51f124SMoriah Waterland  * get_mntinfo - get the mount table, now dynamically allocated. Returns 0 if
841*5c51f124SMoriah Waterland  * no problem and 1 if there's a fatal error.
842*5c51f124SMoriah Waterland  */
843*5c51f124SMoriah Waterland int
844*5c51f124SMoriah Waterland get_mntinfo(int map_client, char *vfstab_file)
845*5c51f124SMoriah Waterland {
846*5c51f124SMoriah Waterland 	static 	char 	*rn = "/";
847*5c51f124SMoriah Waterland 	FILE		*pp;
848*5c51f124SMoriah Waterland 	struct	mnttab	mtbuf;
849*5c51f124SMoriah Waterland 	struct	mnttab	*mt = &mtbuf;
850*5c51f124SMoriah Waterland 	char		*install_root;
851*5c51f124SMoriah Waterland 	int 		is_remote;
852*5c51f124SMoriah Waterland 
853*5c51f124SMoriah Waterland 	/*
854*5c51f124SMoriah Waterland 	 * Open the mount table for the current host and establish a global
855*5c51f124SMoriah Waterland 	 * table that holds data about current mount status.
856*5c51f124SMoriah Waterland 	 */
857*5c51f124SMoriah Waterland 	if ((pp = setmntent(MOUNT_TABLE, "r")) == NULL) {
858*5c51f124SMoriah Waterland 		progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno));
859*5c51f124SMoriah Waterland 		return (1);
860*5c51f124SMoriah Waterland 	}
861*5c51f124SMoriah Waterland 
862*5c51f124SMoriah Waterland 	/*
863*5c51f124SMoriah Waterland 	 * First, review the mounted filesystems on the managing host. This
864*5c51f124SMoriah Waterland 	 * may also be the target host but we haven't decided that for sure
865*5c51f124SMoriah Waterland 	 * yet.
866*5c51f124SMoriah Waterland 	 */
867*5c51f124SMoriah Waterland 	while (!getmntent(pp, mt))
868*5c51f124SMoriah Waterland 		if (construct_mt(mt))
869*5c51f124SMoriah Waterland 			return (1);
870*5c51f124SMoriah Waterland 
871*5c51f124SMoriah Waterland 	(void) endmntent(pp);
872*5c51f124SMoriah Waterland 
873*5c51f124SMoriah Waterland 	/*
874*5c51f124SMoriah Waterland 	 * Now, we see if this installation is to a client. If it is, we scan
875*5c51f124SMoriah Waterland 	 * the client's vfstab to determine what filesystems are
876*5c51f124SMoriah Waterland 	 * inappropriate to write to. This simply adds the vfstab entries
877*5c51f124SMoriah Waterland 	 * representing what will be remote file systems for the client.
878*5c51f124SMoriah Waterland 	 * Everything that isn't remote to the client is already accounted
879*5c51f124SMoriah Waterland 	 * for in the fs_tab[] so far. If the remote filesystem is really on
880*5c51f124SMoriah Waterland 	 * this server, we will write through to the server from this client.
881*5c51f124SMoriah Waterland 	 */
882*5c51f124SMoriah Waterland 	install_root = get_inst_root();
883*5c51f124SMoriah Waterland 	if (install_root && strcmp(install_root, "/") != 0 && map_client) {
884*5c51f124SMoriah Waterland 		/* OK, this is a legitimate remote client. */
885*5c51f124SMoriah Waterland 		struct	vfstab	vfsbuf;
886*5c51f124SMoriah Waterland 		struct	vfstab	*vfs = &vfsbuf;
887*5c51f124SMoriah Waterland 		char VFS_TABLE[PATH_MAX];
888*5c51f124SMoriah Waterland 
889*5c51f124SMoriah Waterland 		/*
890*5c51f124SMoriah Waterland 		 * Since we use the fsys() function later, and it depends on
891*5c51f124SMoriah Waterland 		 * an ordered list, we have to sort the list here.
892*5c51f124SMoriah Waterland 		 */
893*5c51f124SMoriah Waterland 		qsort(fs_tab, fs_tab_used,
894*5c51f124SMoriah Waterland 		    sizeof (struct fstable *), fs_tab_ent_comp);
895*5c51f124SMoriah Waterland 
896*5c51f124SMoriah Waterland 		/*
897*5c51f124SMoriah Waterland 		 * Here's where the vfstab for the target is. If we can get
898*5c51f124SMoriah Waterland 		 * to it, we'll scan it for what the client will see as
899*5c51f124SMoriah Waterland 		 * remote filesystems, otherwise, we'll just skip this.
900*5c51f124SMoriah Waterland 		 */
901*5c51f124SMoriah Waterland 		if (vfstab_file) {
902*5c51f124SMoriah Waterland 			(void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s",
903*5c51f124SMoriah Waterland 				vfstab_file);
904*5c51f124SMoriah Waterland 		} else {
905*5c51f124SMoriah Waterland 			(void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s%s",
906*5c51f124SMoriah Waterland 				install_root, VFSTAB);
907*5c51f124SMoriah Waterland 		}
908*5c51f124SMoriah Waterland 
909*5c51f124SMoriah Waterland 		if (access(VFS_TABLE, R_OK) == 0) {
910*5c51f124SMoriah Waterland 			char *link_name;
911*5c51f124SMoriah Waterland 
912*5c51f124SMoriah Waterland 			/*
913*5c51f124SMoriah Waterland 			 * Open the vfs table for the target host.
914*5c51f124SMoriah Waterland 			 */
915*5c51f124SMoriah Waterland 			if ((pp = setmntent(VFS_TABLE, "r")) == NULL) {
916*5c51f124SMoriah Waterland 				progerr(ERR_NOTABLE, "vfs", VFS_TABLE,
917*5c51f124SMoriah Waterland 					strerror(errno));
918*5c51f124SMoriah Waterland 				return (1);
919*5c51f124SMoriah Waterland 			}
920*5c51f124SMoriah Waterland 
921*5c51f124SMoriah Waterland 			/* Do this for each entry in the vfstab. */
922*5c51f124SMoriah Waterland 			while (!getvfsent(pp, vfs)) {
923*5c51f124SMoriah Waterland 				char client_mountp[PATH_MAX];
924*5c51f124SMoriah Waterland 				int mnt_stat;
925*5c51f124SMoriah Waterland 
926*5c51f124SMoriah Waterland 				/*
927*5c51f124SMoriah Waterland 				 * We put it into the fs table if it's
928*5c51f124SMoriah Waterland 				 * remote mounted (even from this server) or
929*5c51f124SMoriah Waterland 				 * loopback mounted from the client's point
930*5c51f124SMoriah Waterland 				 * of view.
931*5c51f124SMoriah Waterland 				 */
932*5c51f124SMoriah Waterland 				if (!(is_remote =
933*5c51f124SMoriah Waterland 				    is_remote_src(vfs->vfs_special)) &&
934*5c51f124SMoriah Waterland 				    strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) !=
935*5c51f124SMoriah Waterland 				    0)
936*5c51f124SMoriah Waterland 					continue;	/* not interesting */
937*5c51f124SMoriah Waterland 
938*5c51f124SMoriah Waterland 				/*
939*5c51f124SMoriah Waterland 				 * Construct client_mountp by prepending the
940*5c51f124SMoriah Waterland 				 * install_root to the 'mount point' name.
941*5c51f124SMoriah Waterland 				 */
942*5c51f124SMoriah Waterland 				if (strcmp(vfs->vfs_mountp, "/") == 0) {
943*5c51f124SMoriah Waterland 					(void) strcpy(client_mountp,
944*5c51f124SMoriah Waterland 								install_root);
945*5c51f124SMoriah Waterland 				} else {
946*5c51f124SMoriah Waterland 					(void) snprintf(client_mountp,
947*5c51f124SMoriah Waterland 						sizeof (client_mountp), "%s%s",
948*5c51f124SMoriah Waterland 						install_root, vfs->vfs_mountp);
949*5c51f124SMoriah Waterland 				}
950*5c51f124SMoriah Waterland 
951*5c51f124SMoriah Waterland 				/*
952*5c51f124SMoriah Waterland 				 * We also skip the entry if the vfs_special
953*5c51f124SMoriah Waterland 				 * path and the client_path are the same.
954*5c51f124SMoriah Waterland 				 * There's no need to mount it, it's just a
955*5c51f124SMoriah Waterland 				 * cachefs optimization that mounts a
956*5c51f124SMoriah Waterland 				 * directory over itself from this server.
957*5c51f124SMoriah Waterland 				 */
958*5c51f124SMoriah Waterland 				if ((is_remote == SELF_SERVE) &&
959*5c51f124SMoriah Waterland 				    strcmp(path_part(vfs->vfs_special),
960*5c51f124SMoriah Waterland 				    client_mountp) == 0)
961*5c51f124SMoriah Waterland 					continue;
962*5c51f124SMoriah Waterland 
963*5c51f124SMoriah Waterland 				/* Determine if this is already mounted. */
964*5c51f124SMoriah Waterland 				link_name = strdup(path_part(vfs->vfs_special));
965*5c51f124SMoriah Waterland 				mnt_stat = already_mounted(vfs,
966*5c51f124SMoriah Waterland 				    (is_remote != REAL_REMOTE), client_mountp,
967*5c51f124SMoriah Waterland 				    link_name);
968*5c51f124SMoriah Waterland 
969*5c51f124SMoriah Waterland 				if (mnt_stat == MNT_EXACT) {
970*5c51f124SMoriah Waterland 					mod_existing(vfs, match_mount,
971*5c51f124SMoriah Waterland 					    is_remote);
972*5c51f124SMoriah Waterland 				} else {	/* MNT_NOT */
973*5c51f124SMoriah Waterland 					if (construct_vfs(vfs, client_mountp,
974*5c51f124SMoriah Waterland 					    link_name, is_remote, mnt_stat))
975*5c51f124SMoriah Waterland 						return (1);
976*5c51f124SMoriah Waterland 				}
977*5c51f124SMoriah Waterland 			}
978*5c51f124SMoriah Waterland 			(void) endmntent(pp);
979*5c51f124SMoriah Waterland 		}	/* end of if(access()) */
980*5c51f124SMoriah Waterland 	}	/* end of if(install_root) */
981*5c51f124SMoriah Waterland 
982*5c51f124SMoriah Waterland 	/* This next one may look stupid, but it can really happen. */
983*5c51f124SMoriah Waterland 	if (fs_tab_used <= 0) {
984*5c51f124SMoriah Waterland 		progerr(ERR_MNT_NOMOUNTS);
985*5c51f124SMoriah Waterland 		return (1);
986*5c51f124SMoriah Waterland 	}
987*5c51f124SMoriah Waterland 
988*5c51f124SMoriah Waterland 	/*
989*5c51f124SMoriah Waterland 	 * Now that we have the complete list of mounted (or virtually
990*5c51f124SMoriah Waterland 	 * mounted) filesystems, we sort the mountpoints in reverse order
991*5c51f124SMoriah Waterland 	 * based on the length of the 'mount point' name.
992*5c51f124SMoriah Waterland 	 */
993*5c51f124SMoriah Waterland 	qsort(fs_tab, fs_tab_used, sizeof (struct fstable *), fs_tab_ent_comp);
994*5c51f124SMoriah Waterland 	if (strcmp(fs_tab[fs_tab_used-1]->name, rn) != 0) {
995*5c51f124SMoriah Waterland 		progerr(ERR_MNT_NOROOT, fs_tab[fs_tab_used-1]->name, rn, errno,
996*5c51f124SMoriah Waterland 				strerror(errno));
997*5c51f124SMoriah Waterland 		return (1);
998*5c51f124SMoriah Waterland 	} else {
999*5c51f124SMoriah Waterland 		return (0);
1000*5c51f124SMoriah Waterland 	}
1001*5c51f124SMoriah Waterland }
1002*5c51f124SMoriah Waterland 
1003*5c51f124SMoriah Waterland /*
1004*5c51f124SMoriah Waterland  * This function supports dryrun mode by allowing the filesystem table to be
1005*5c51f124SMoriah Waterland  * directly loaded from the continuation file.
1006*5c51f124SMoriah Waterland  */
1007*5c51f124SMoriah Waterland int
1008*5c51f124SMoriah Waterland load_fsentry(struct fstable *fs_entry, char *name, char *fstype,
1009*5c51f124SMoriah Waterland     char *remote_name)
1010*5c51f124SMoriah Waterland {
1011*5c51f124SMoriah Waterland 	struct fstable *nfte;
1012*5c51f124SMoriah Waterland 
1013*5c51f124SMoriah Waterland 	if ((nfte = fs_tab_init(name, fstype)) == NULL)
1014*5c51f124SMoriah Waterland 		return (1);
1015*5c51f124SMoriah Waterland 
1016*5c51f124SMoriah Waterland 	/* Grab the name and fstype from the new structure. */
1017*5c51f124SMoriah Waterland 	fs_entry->name = nfte->name;
1018*5c51f124SMoriah Waterland 	fs_entry->fstype = nfte->fstype;
1019*5c51f124SMoriah Waterland 
1020*5c51f124SMoriah Waterland 	/* Copy the basic structure into place. */
1021*5c51f124SMoriah Waterland 	(void) memcpy(nfte, fs_entry, sizeof (struct fstable));
1022*5c51f124SMoriah Waterland 
1023*5c51f124SMoriah Waterland 	/*
1024*5c51f124SMoriah Waterland 	 * Allocate space for the 'special' name.
1025*5c51f124SMoriah Waterland 	 */
1026*5c51f124SMoriah Waterland 	if ((nfte->remote_name = malloc(strlen(remote_name)+1)) == NULL) {
1027*5c51f124SMoriah Waterland 		progerr(ERR_MALLOC, "remote_name", errno, strerror(errno));
1028*5c51f124SMoriah Waterland 		return (1);
1029*5c51f124SMoriah Waterland 	}
1030*5c51f124SMoriah Waterland 
1031*5c51f124SMoriah Waterland 	(void) strcpy(nfte->remote_name, remote_name);
1032*5c51f124SMoriah Waterland 
1033*5c51f124SMoriah Waterland 	return (0);
1034*5c51f124SMoriah Waterland }
1035*5c51f124SMoriah Waterland 
1036*5c51f124SMoriah Waterland /*
1037*5c51f124SMoriah Waterland  * Given a path, return the table index of the filesystem the file apparently
1038*5c51f124SMoriah Waterland  * resides on. This doesn't put any time into resolving filesystems that
1039*5c51f124SMoriah Waterland  * refer to other filesystems. It just returns the entry containing this
1040*5c51f124SMoriah Waterland  * path.
1041*5c51f124SMoriah Waterland  */
1042*5c51f124SMoriah Waterland short
1043*5c51f124SMoriah Waterland fsys(char *path)
1044*5c51f124SMoriah Waterland {
1045*5c51f124SMoriah Waterland 	register int i;
1046*5c51f124SMoriah Waterland 	char	real_path[PATH_MAX];
1047*5c51f124SMoriah Waterland 	char	*path2use = NULL;
1048*5c51f124SMoriah Waterland 	char	*cp = NULL;
1049*5c51f124SMoriah Waterland 	int	pathlen;
1050*5c51f124SMoriah Waterland 
1051*5c51f124SMoriah Waterland 	path2use = path;
1052*5c51f124SMoriah Waterland 
1053*5c51f124SMoriah Waterland 	real_path[0] = '\0';
1054*5c51f124SMoriah Waterland 
1055*5c51f124SMoriah Waterland 	(void) realpath(path, real_path);
1056*5c51f124SMoriah Waterland 
1057*5c51f124SMoriah Waterland 	if (real_path[0]) {
1058*5c51f124SMoriah Waterland 		cp = strstr(path, real_path);
1059*5c51f124SMoriah Waterland 		if (cp != path || cp == NULL)
1060*5c51f124SMoriah Waterland 			path2use = real_path;
1061*5c51f124SMoriah Waterland 	}
1062*5c51f124SMoriah Waterland 
1063*5c51f124SMoriah Waterland 	pathlen = strlen(path2use);
1064*5c51f124SMoriah Waterland 
1065*5c51f124SMoriah Waterland 	/*
1066*5c51f124SMoriah Waterland 	 * The following algorithm scans the list of attached file systems
1067*5c51f124SMoriah Waterland 	 * for the one containing path. At this point the file names in
1068*5c51f124SMoriah Waterland 	 * fs_tab[] are sorted by decreasing length to facilitate the scan.
1069*5c51f124SMoriah Waterland 	 * The first for() scans past all the file system names too short to
1070*5c51f124SMoriah Waterland 	 * contain path. The second for() does the actual string comparison.
1071*5c51f124SMoriah Waterland 	 * It tests first to assure that the comparison is against a complete
1072*5c51f124SMoriah Waterland 	 * token by assuring that the end of the filesystem name aligns with
1073*5c51f124SMoriah Waterland 	 * the end of a token in path2use (ie: '/' or NULL) then it does a
1074*5c51f124SMoriah Waterland 	 * string compare. -- JST
1075*5c51f124SMoriah Waterland 	 */
1076*5c51f124SMoriah Waterland 
1077*5c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
1078*5c51f124SMoriah Waterland 		return (-1);
1079*5c51f124SMoriah Waterland 	}
1080*5c51f124SMoriah Waterland 
1081*5c51f124SMoriah Waterland 	for (i = 0; i < fs_tab_used; i++)
1082*5c51f124SMoriah Waterland 		if (fs_tab[i] == NULL)
1083*5c51f124SMoriah Waterland 			continue;
1084*5c51f124SMoriah Waterland 		else if (fs_tab[i]->namlen <= pathlen)
1085*5c51f124SMoriah Waterland 			break;
1086*5c51f124SMoriah Waterland 	for (; i < fs_tab_used; i++) {
1087*5c51f124SMoriah Waterland 		int fs_namelen;
1088*5c51f124SMoriah Waterland 		char term_char;
1089*5c51f124SMoriah Waterland 
1090*5c51f124SMoriah Waterland 		if (fs_tab[i] == NULL)
1091*5c51f124SMoriah Waterland 			continue;
1092*5c51f124SMoriah Waterland 
1093*5c51f124SMoriah Waterland 		fs_namelen = fs_tab[i]->namlen;
1094*5c51f124SMoriah Waterland 		term_char = path2use[fs_namelen];
1095*5c51f124SMoriah Waterland 
1096*5c51f124SMoriah Waterland 		/*
1097*5c51f124SMoriah Waterland 		 * If we're putting the file "/a/kernel" into the filesystem
1098*5c51f124SMoriah Waterland 		 * "/a", then fs_namelen == 2 and term_char == '/'. If, we're
1099*5c51f124SMoriah Waterland 		 * putting "/etc/termcap" into "/", fs_namelen == 1 and
1100*5c51f124SMoriah Waterland 		 * term_char (unfortunately) == 'e'. In the case of
1101*5c51f124SMoriah Waterland 		 * fs_namelen == 1, we check to make sure the filesystem is
1102*5c51f124SMoriah Waterland 		 * "/" and if it is, we have a guaranteed fit, otherwise we
1103*5c51f124SMoriah Waterland 		 * do the string compare. -- JST
1104*5c51f124SMoriah Waterland 		 */
1105*5c51f124SMoriah Waterland 		if ((fs_namelen == 1 && *(fs_tab[i]->name) == '/') ||
1106*5c51f124SMoriah Waterland 		    ((term_char == '/' || term_char == NULL) &&
1107*5c51f124SMoriah Waterland 		    strncmp(fs_tab[i]->name, path2use, fs_namelen) == 0))
1108*5c51f124SMoriah Waterland 			return (i);
1109*5c51f124SMoriah Waterland 	}
1110*5c51f124SMoriah Waterland 
1111*5c51f124SMoriah Waterland 	/*
1112*5c51f124SMoriah Waterland 	 * It only gets here if the root filesystem is fundamentally corrupt.
1113*5c51f124SMoriah Waterland 	 * (This can happen!)
1114*5c51f124SMoriah Waterland 	 */
1115*5c51f124SMoriah Waterland 	progerr(ERR_FSYS_FELLOUT, path2use);
1116*5c51f124SMoriah Waterland 
1117*5c51f124SMoriah Waterland 	return (-1);
1118*5c51f124SMoriah Waterland }
1119*5c51f124SMoriah Waterland 
1120*5c51f124SMoriah Waterland /*
1121*5c51f124SMoriah Waterland  * This function returns the entry in the fs_tab[] corresponding to the
1122*5c51f124SMoriah Waterland  * actual filesystem of record. It won't return a loopback filesystem entry,
1123*5c51f124SMoriah Waterland  * it will return the filesystem that the loopback filesystem is mounted
1124*5c51f124SMoriah Waterland  * over.
1125*5c51f124SMoriah Waterland  */
1126*5c51f124SMoriah Waterland short
1127*5c51f124SMoriah Waterland resolved_fsys(char *path)
1128*5c51f124SMoriah Waterland {
1129*5c51f124SMoriah Waterland 	int i = -1;
1130*5c51f124SMoriah Waterland 	char path2use[PATH_MAX];
1131*5c51f124SMoriah Waterland 
1132*5c51f124SMoriah Waterland 	(void) strcpy(path2use, path);
1133*5c51f124SMoriah Waterland 
1134*5c51f124SMoriah Waterland 	/* If this isn't a "real" filesystem, resolve the map. */
1135*5c51f124SMoriah Waterland 	do {
1136*5c51f124SMoriah Waterland 		(void) strcpy(path2use, server_map(path2use, i));
1137*5c51f124SMoriah Waterland 		i = fsys(path2use);
1138*5c51f124SMoriah Waterland 	} while (fs_tab[i]->srvr_map);
1139*5c51f124SMoriah Waterland 
1140*5c51f124SMoriah Waterland 	return (i);
1141*5c51f124SMoriah Waterland }
1142*5c51f124SMoriah Waterland 
1143*5c51f124SMoriah Waterland /*
1144*5c51f124SMoriah Waterland  * This function returns the srvr_map status based upon the fs_tab entry
1145*5c51f124SMoriah Waterland  * number. This tells us if the server path constructed from the package
1146*5c51f124SMoriah Waterland  * install root is really the target filesystem.
1147*5c51f124SMoriah Waterland  */
1148*5c51f124SMoriah Waterland int
1149*5c51f124SMoriah Waterland use_srvr_map_n(short n)
1150*5c51f124SMoriah Waterland {
1151*5c51f124SMoriah Waterland 	return ((int)fs_tab[n]->srvr_map);
1152*5c51f124SMoriah Waterland }
1153*5c51f124SMoriah Waterland 
1154*5c51f124SMoriah Waterland /*
1155*5c51f124SMoriah Waterland  * This function returns the mount status based upon the fs_tab entry
1156*5c51f124SMoriah Waterland  * number. This tells us if there is any hope of gaining access
1157*5c51f124SMoriah Waterland  * to this file system.
1158*5c51f124SMoriah Waterland  */
1159*5c51f124SMoriah Waterland int
1160*5c51f124SMoriah Waterland is_mounted_n(short n)
1161*5c51f124SMoriah Waterland {
1162*5c51f124SMoriah Waterland 	return ((int)fs_tab[n]->mounted);
1163*5c51f124SMoriah Waterland }
1164*5c51f124SMoriah Waterland 
1165*5c51f124SMoriah Waterland /*
1166*5c51f124SMoriah Waterland  * is_fs_writeable_n - given an fstab index, return 1
1167*5c51f124SMoriah Waterland  *	if it's writeable, 0 if read-only.
1168*5c51f124SMoriah Waterland  */
1169*5c51f124SMoriah Waterland int
1170*5c51f124SMoriah Waterland is_fs_writeable_n(short n)
1171*5c51f124SMoriah Waterland {
1172*5c51f124SMoriah Waterland 	/*
1173*5c51f124SMoriah Waterland 	 * If the write access permissions haven't been confirmed, do that
1174*5c51f124SMoriah Waterland 	 * now. Note that the only reason we need to do the special check is
1175*5c51f124SMoriah Waterland 	 * in the case of an NFS mount (remote) because we can't determine if
1176*5c51f124SMoriah Waterland 	 * root has access in any other way.
1177*5c51f124SMoriah Waterland 	 */
1178*5c51f124SMoriah Waterland 	if (fs_tab[n]->remote && fs_tab[n]->mounted &&
1179*5c51f124SMoriah Waterland 	    !fs_tab[n]->write_tested) {
1180*5c51f124SMoriah Waterland 		if (fs_tab[n]->writeable && !really_write(fs_tab[n]->name))
1181*5c51f124SMoriah Waterland 			fs_tab[n]->writeable = 0;	/* not really */
1182*5c51f124SMoriah Waterland 
1183*5c51f124SMoriah Waterland 		fs_tab[n]->write_tested = 1;	/* confirmed */
1184*5c51f124SMoriah Waterland 	}
1185*5c51f124SMoriah Waterland 
1186*5c51f124SMoriah Waterland 	return ((int)fs_tab[n]->writeable);
1187*5c51f124SMoriah Waterland }
1188*5c51f124SMoriah Waterland 
1189*5c51f124SMoriah Waterland /*
1190*5c51f124SMoriah Waterland  * is_remote_fs_n - given an fstab index, return 1
1191*5c51f124SMoriah Waterland  *	if it's a remote filesystem, 0 if local.
1192*5c51f124SMoriah Waterland  *
1193*5c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
1194*5c51f124SMoriah Waterland  */
1195*5c51f124SMoriah Waterland int
1196*5c51f124SMoriah Waterland is_remote_fs_n(short n)
1197*5c51f124SMoriah Waterland {
1198*5c51f124SMoriah Waterland 	return ((int)fs_tab[n]->remote);
1199*5c51f124SMoriah Waterland }
1200*5c51f124SMoriah Waterland 
1201*5c51f124SMoriah Waterland /* index-driven is_served() */
1202*5c51f124SMoriah Waterland int
1203*5c51f124SMoriah Waterland is_served_n(short n)
1204*5c51f124SMoriah Waterland {
1205*5c51f124SMoriah Waterland 	return ((int)fs_tab[n]->served);
1206*5c51f124SMoriah Waterland }
1207*5c51f124SMoriah Waterland 
1208*5c51f124SMoriah Waterland /*
1209*5c51f124SMoriah Waterland  * This returns the number of blocks available on the indicated filesystem.
1210*5c51f124SMoriah Waterland  *
1211*5c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
1212*5c51f124SMoriah Waterland  */
1213*5c51f124SMoriah Waterland fsblkcnt_t
1214*5c51f124SMoriah Waterland get_blk_free_n(short n)
1215*5c51f124SMoriah Waterland {
1216*5c51f124SMoriah Waterland 	return (fs_tab[n]->bfree);
1217*5c51f124SMoriah Waterland }
1218*5c51f124SMoriah Waterland 
1219*5c51f124SMoriah Waterland /*
1220*5c51f124SMoriah Waterland  * This returns the number of blocks being used on the indicated filesystem.
1221*5c51f124SMoriah Waterland  *
1222*5c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
1223*5c51f124SMoriah Waterland  */
1224*5c51f124SMoriah Waterland fsblkcnt_t
1225*5c51f124SMoriah Waterland get_blk_used_n(short n)
1226*5c51f124SMoriah Waterland {
1227*5c51f124SMoriah Waterland 	return (fs_tab[n]->bused);
1228*5c51f124SMoriah Waterland }
1229*5c51f124SMoriah Waterland 
1230*5c51f124SMoriah Waterland /*
1231*5c51f124SMoriah Waterland  * This returns the number of inodes available on the indicated filesystem.
1232*5c51f124SMoriah Waterland  *
1233*5c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
1234*5c51f124SMoriah Waterland  */
1235*5c51f124SMoriah Waterland fsblkcnt_t
1236*5c51f124SMoriah Waterland get_inode_free_n(short n)
1237*5c51f124SMoriah Waterland {
1238*5c51f124SMoriah Waterland 	return (fs_tab[n]->ffree);
1239*5c51f124SMoriah Waterland }
1240*5c51f124SMoriah Waterland 
1241*5c51f124SMoriah Waterland /*
1242*5c51f124SMoriah Waterland  * This returns the number of inodes being used on the indicated filesystem.
1243*5c51f124SMoriah Waterland  *
1244*5c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
1245*5c51f124SMoriah Waterland  */
1246*5c51f124SMoriah Waterland fsblkcnt_t
1247*5c51f124SMoriah Waterland get_inode_used_n(short n)
1248*5c51f124SMoriah Waterland {
1249*5c51f124SMoriah Waterland 	return (fs_tab[n]->fused);
1250*5c51f124SMoriah Waterland }
1251*5c51f124SMoriah Waterland 
1252*5c51f124SMoriah Waterland /*
1253*5c51f124SMoriah Waterland  * Sets the number of blocks being used on the indicated filesystem.
1254*5c51f124SMoriah Waterland  *
1255*5c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
1256*5c51f124SMoriah Waterland  */
1257*5c51f124SMoriah Waterland void
1258*5c51f124SMoriah Waterland set_blk_used_n(short n, fsblkcnt_t value)
1259*5c51f124SMoriah Waterland {
1260*5c51f124SMoriah Waterland 	fs_tab[n]->bused = value;
1261*5c51f124SMoriah Waterland }
1262*5c51f124SMoriah Waterland 
1263*5c51f124SMoriah Waterland /* Get the filesystem block size. */
1264*5c51f124SMoriah Waterland fsblkcnt_t
1265*5c51f124SMoriah Waterland get_blk_size_n(short n)
1266*5c51f124SMoriah Waterland {
1267*5c51f124SMoriah Waterland 	return (fs_tab[n]->bsize);
1268*5c51f124SMoriah Waterland }
1269*5c51f124SMoriah Waterland 
1270*5c51f124SMoriah Waterland /* Get the filesystem fragment size. */
1271*5c51f124SMoriah Waterland fsblkcnt_t
1272*5c51f124SMoriah Waterland get_frag_size_n(short n)
1273*5c51f124SMoriah Waterland {
1274*5c51f124SMoriah Waterland 	return (fs_tab[n]->bsize);
1275*5c51f124SMoriah Waterland }
1276*5c51f124SMoriah Waterland 
1277*5c51f124SMoriah Waterland /*
1278*5c51f124SMoriah Waterland  * This returns the name of the indicated filesystem.
1279*5c51f124SMoriah Waterland  */
1280*5c51f124SMoriah Waterland char *
1281*5c51f124SMoriah Waterland get_fs_name_n(short n)
1282*5c51f124SMoriah Waterland {
1283*5c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
1284*5c51f124SMoriah Waterland 		return (NULL);
1285*5c51f124SMoriah Waterland 	} else if (n >= fs_tab_used) {
1286*5c51f124SMoriah Waterland 		return (NULL);
1287*5c51f124SMoriah Waterland 	} else {
1288*5c51f124SMoriah Waterland 		return (fs_tab[n]->name);
1289*5c51f124SMoriah Waterland 	}
1290*5c51f124SMoriah Waterland }
1291*5c51f124SMoriah Waterland 
1292*5c51f124SMoriah Waterland /*
1293*5c51f124SMoriah Waterland  * This returns the remote name of the indicated filesystem.
1294*5c51f124SMoriah Waterland  *
1295*5c51f124SMoriah Waterland  *	Note: Upon entry, a valid fsys() is required.
1296*5c51f124SMoriah Waterland  */
1297*5c51f124SMoriah Waterland char *
1298*5c51f124SMoriah Waterland get_source_name_n(short n)
1299*5c51f124SMoriah Waterland {
1300*5c51f124SMoriah Waterland 	return (fs_tab[n]->remote_name);
1301*5c51f124SMoriah Waterland }
1302*5c51f124SMoriah Waterland 
1303*5c51f124SMoriah Waterland /*
1304*5c51f124SMoriah Waterland  * This function returns the srvr_map status based upon the path.
1305*5c51f124SMoriah Waterland  */
1306*5c51f124SMoriah Waterland int
1307*5c51f124SMoriah Waterland use_srvr_map(char *path, short *fsys_value)
1308*5c51f124SMoriah Waterland {
1309*5c51f124SMoriah Waterland 	if (*fsys_value == BADFSYS)
1310*5c51f124SMoriah Waterland 		*fsys_value = fsys(path);
1311*5c51f124SMoriah Waterland 
1312*5c51f124SMoriah Waterland 	return (use_srvr_map_n(*fsys_value));
1313*5c51f124SMoriah Waterland }
1314*5c51f124SMoriah Waterland 
1315*5c51f124SMoriah Waterland /*
1316*5c51f124SMoriah Waterland  * This function returns the mount status based upon the path.
1317*5c51f124SMoriah Waterland  */
1318*5c51f124SMoriah Waterland int
1319*5c51f124SMoriah Waterland is_mounted(char *path, short *fsys_value)
1320*5c51f124SMoriah Waterland {
1321*5c51f124SMoriah Waterland 	if (*fsys_value == BADFSYS)
1322*5c51f124SMoriah Waterland 		*fsys_value = fsys(path);
1323*5c51f124SMoriah Waterland 
1324*5c51f124SMoriah Waterland 	return (is_mounted_n(*fsys_value));
1325*5c51f124SMoriah Waterland }
1326*5c51f124SMoriah Waterland 
1327*5c51f124SMoriah Waterland /*
1328*5c51f124SMoriah Waterland  * is_fs_writeable - given a cfent entry, return 1
1329*5c51f124SMoriah Waterland  *	if it's writeable, 0 if read-only.
1330*5c51f124SMoriah Waterland  *
1331*5c51f124SMoriah Waterland  *	Note: Upon exit, a valid fsys() is guaranteed. This is
1332*5c51f124SMoriah Waterland  *	an interface requirement.
1333*5c51f124SMoriah Waterland  */
1334*5c51f124SMoriah Waterland int
1335*5c51f124SMoriah Waterland is_fs_writeable(char *path, short *fsys_value)
1336*5c51f124SMoriah Waterland {
1337*5c51f124SMoriah Waterland 	if (*fsys_value == BADFSYS)
1338*5c51f124SMoriah Waterland 		*fsys_value = fsys(path);
1339*5c51f124SMoriah Waterland 
1340*5c51f124SMoriah Waterland 	return (is_fs_writeable_n(*fsys_value));
1341*5c51f124SMoriah Waterland }
1342*5c51f124SMoriah Waterland 
1343*5c51f124SMoriah Waterland /*
1344*5c51f124SMoriah Waterland  * is_remote_fs - given a cfent entry, return 1
1345*5c51f124SMoriah Waterland  *	if it's a remote filesystem, 0 if local.
1346*5c51f124SMoriah Waterland  *
1347*5c51f124SMoriah Waterland  *	Also Note: Upon exit, a valid fsys() is guaranteed. This is
1348*5c51f124SMoriah Waterland  *	an interface requirement.
1349*5c51f124SMoriah Waterland  */
1350*5c51f124SMoriah Waterland int
1351*5c51f124SMoriah Waterland is_remote_fs(char *path, short *fsys_value)
1352*5c51f124SMoriah Waterland {
1353*5c51f124SMoriah Waterland 	if (*fsys_value == BADFSYS)
1354*5c51f124SMoriah Waterland 		*fsys_value = fsys(path);
1355*5c51f124SMoriah Waterland 
1356*5c51f124SMoriah Waterland 	return (is_remote_fs_n(*fsys_value));
1357*5c51f124SMoriah Waterland }
1358*5c51f124SMoriah Waterland 
1359*5c51f124SMoriah Waterland /*
1360*5c51f124SMoriah Waterland  * This function returns the served status of the filesystem. Served means a
1361*5c51f124SMoriah Waterland  * client is getting this file from a server and it is not writeable by the
1362*5c51f124SMoriah Waterland  * client. It has nothing to do with whether or not this particular operation
1363*5c51f124SMoriah Waterland  * (eg: pkgadd or pkgrm) will be writing to it.
1364*5c51f124SMoriah Waterland  */
1365*5c51f124SMoriah Waterland int
1366*5c51f124SMoriah Waterland is_served(char *path, short *fsys_value)
1367*5c51f124SMoriah Waterland {
1368*5c51f124SMoriah Waterland 	if (*fsys_value == BADFSYS)
1369*5c51f124SMoriah Waterland 		*fsys_value = fsys(path);
1370*5c51f124SMoriah Waterland 
1371*5c51f124SMoriah Waterland 	return (is_served_n(*fsys_value));
1372*5c51f124SMoriah Waterland }
1373*5c51f124SMoriah Waterland 
1374*5c51f124SMoriah Waterland /*
1375*5c51f124SMoriah Waterland  * get_remote_path - given a filesystem table index, return the
1376*5c51f124SMoriah Waterland  *	path of the filesystem on the remote system.  Otherwise,
1377*5c51f124SMoriah Waterland  *	return NULL if it's a local filesystem.
1378*5c51f124SMoriah Waterland  */
1379*5c51f124SMoriah Waterland char *
1380*5c51f124SMoriah Waterland get_remote_path(short n)
1381*5c51f124SMoriah Waterland {
1382*5c51f124SMoriah Waterland 	char	*p;
1383*5c51f124SMoriah Waterland 
1384*5c51f124SMoriah Waterland 	if (!is_remote_fs_n(n))
1385*5c51f124SMoriah Waterland 		return (NULL); 	/* local */
1386*5c51f124SMoriah Waterland 	p = strchr(fs_tab[n]->remote_name, ':');
1387*5c51f124SMoriah Waterland 	if (!p)
1388*5c51f124SMoriah Waterland 		p = fs_tab[n]->remote_name; 	/* Loopback */
1389*5c51f124SMoriah Waterland 	else
1390*5c51f124SMoriah Waterland 		p++; 	/* remote */
1391*5c51f124SMoriah Waterland 	return (p);
1392*5c51f124SMoriah Waterland }
1393*5c51f124SMoriah Waterland 
1394*5c51f124SMoriah Waterland /*
1395*5c51f124SMoriah Waterland  * get_mount_point - given a filesystem table index, return the
1396*5c51f124SMoriah Waterland  *	path of the mount point.  Otherwise,
1397*5c51f124SMoriah Waterland  *	return NULL if it's a local filesystem.
1398*5c51f124SMoriah Waterland  */
1399*5c51f124SMoriah Waterland char *
1400*5c51f124SMoriah Waterland get_mount_point(short n)
1401*5c51f124SMoriah Waterland {
1402*5c51f124SMoriah Waterland 	if (!is_remote_fs_n(n))
1403*5c51f124SMoriah Waterland 		return (NULL); 	/* local */
1404*5c51f124SMoriah Waterland 	return (fs_tab[n]->name);
1405*5c51f124SMoriah Waterland }
1406*5c51f124SMoriah Waterland 
1407*5c51f124SMoriah Waterland struct fstable *
1408*5c51f124SMoriah Waterland get_fs_entry(short n)
1409*5c51f124SMoriah Waterland {
1410*5c51f124SMoriah Waterland 	if (fs_tab_used == 0) {
1411*5c51f124SMoriah Waterland 		return (NULL);
1412*5c51f124SMoriah Waterland 	} else if (n >= fs_tab_used) {
1413*5c51f124SMoriah Waterland 		return (NULL);
1414*5c51f124SMoriah Waterland 	} else {
1415*5c51f124SMoriah Waterland 		return (fs_tab[n]);
1416*5c51f124SMoriah Waterland 	}
1417*5c51f124SMoriah Waterland }
1418