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 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 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 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 * 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 * 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 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 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 * 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 * 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 * 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