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