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