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