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