1*5c51f124SMoriah Waterland /* 2*5c51f124SMoriah Waterland * CDDL HEADER START 3*5c51f124SMoriah Waterland * 4*5c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 5*5c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 6*5c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 7*5c51f124SMoriah Waterland * 8*5c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 10*5c51f124SMoriah Waterland * See the License for the specific language governing permissions 11*5c51f124SMoriah Waterland * and limitations under the License. 12*5c51f124SMoriah Waterland * 13*5c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 14*5c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 16*5c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 17*5c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 18*5c51f124SMoriah Waterland * 19*5c51f124SMoriah Waterland * CDDL HEADER END 20*5c51f124SMoriah Waterland */ 21*5c51f124SMoriah Waterland 22*5c51f124SMoriah Waterland /* 23*5c51f124SMoriah Waterland * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*5c51f124SMoriah Waterland * Use is subject to license terms. 25*5c51f124SMoriah Waterland */ 26*5c51f124SMoriah Waterland 27*5c51f124SMoriah Waterland 28*5c51f124SMoriah Waterland /* 29*5c51f124SMoriah Waterland * System includes 30*5c51f124SMoriah Waterland */ 31*5c51f124SMoriah Waterland 32*5c51f124SMoriah Waterland #include <stdio.h> 33*5c51f124SMoriah Waterland #include <limits.h> 34*5c51f124SMoriah Waterland #include <errno.h> 35*5c51f124SMoriah Waterland #include <stdlib.h> 36*5c51f124SMoriah Waterland #include <unistd.h> 37*5c51f124SMoriah Waterland #include <string.h> 38*5c51f124SMoriah Waterland #include <wait.h> 39*5c51f124SMoriah Waterland #include <signal.h> 40*5c51f124SMoriah Waterland #include <malloc.h> 41*5c51f124SMoriah Waterland #include <sys/types.h> 42*5c51f124SMoriah Waterland #include <sys/mount.h> 43*5c51f124SMoriah Waterland #include <sys/stat.h> 44*5c51f124SMoriah Waterland #include <fcntl.h> 45*5c51f124SMoriah Waterland #include <sys/systeminfo.h> 46*5c51f124SMoriah Waterland #include <pkgstrct.h> 47*5c51f124SMoriah Waterland #include <pkginfo.h> 48*5c51f124SMoriah Waterland #include <locale.h> 49*5c51f124SMoriah Waterland #include <libintl.h> 50*5c51f124SMoriah Waterland 51*5c51f124SMoriah Waterland #include <sys/mnttab.h> 52*5c51f124SMoriah Waterland #include <sys/mntent.h> 53*5c51f124SMoriah Waterland #include <sys/vfstab.h> 54*5c51f124SMoriah Waterland 55*5c51f124SMoriah Waterland /* 56*5c51f124SMoriah Waterland * consolidation pkg command library includes 57*5c51f124SMoriah Waterland */ 58*5c51f124SMoriah Waterland 59*5c51f124SMoriah Waterland #include <pkglib.h> 60*5c51f124SMoriah Waterland 61*5c51f124SMoriah Waterland /* 62*5c51f124SMoriah Waterland * local pkg command library includes 63*5c51f124SMoriah Waterland */ 64*5c51f124SMoriah Waterland 65*5c51f124SMoriah Waterland #include "install.h" 66*5c51f124SMoriah Waterland #include "libinst.h" 67*5c51f124SMoriah Waterland #include "libadm.h" 68*5c51f124SMoriah Waterland #include "messages.h" 69*5c51f124SMoriah Waterland 70*5c51f124SMoriah Waterland extern char **environ; 71*5c51f124SMoriah Waterland 72*5c51f124SMoriah Waterland static int match_mount; /* This holds the mount of interest. */ 73*5c51f124SMoriah Waterland 74*5c51f124SMoriah Waterland int fs_tab_used = 0; 75*5c51f124SMoriah Waterland int fs_tab_alloc = 0; 76*5c51f124SMoriah Waterland static int fs_list = -1; 77*5c51f124SMoriah Waterland 78*5c51f124SMoriah Waterland struct fstable **fs_tab = NULL; 79*5c51f124SMoriah Waterland 80*5c51f124SMoriah Waterland #define PKGDBROOT "/var/sadm" 81*5c51f124SMoriah Waterland #define MOUNT "/sbin/mount" 82*5c51f124SMoriah Waterland #define UMOUNT "/sbin/umount" 83*5c51f124SMoriah Waterland 84*5c51f124SMoriah Waterland #define setmntent fopen 85*5c51f124SMoriah Waterland #define endmntent fclose 86*5c51f124SMoriah Waterland #define MOUNT_TABLE MNTTAB 87*5c51f124SMoriah Waterland 88*5c51f124SMoriah Waterland /* returned by already_mounted() */ 89*5c51f124SMoriah Waterland #define MNT_NOT 0 90*5c51f124SMoriah Waterland #define MNT_EXACT 1 91*5c51f124SMoriah Waterland #define MNT_AVAIL 2 92*5c51f124SMoriah Waterland 93*5c51f124SMoriah Waterland /* used with is_remote_src() */ 94*5c51f124SMoriah Waterland #define NOT_REMOTE 0 95*5c51f124SMoriah Waterland #define REAL_REMOTE 1 96*5c51f124SMoriah Waterland #define SELF_SERVE 2 97*5c51f124SMoriah Waterland 98*5c51f124SMoriah Waterland /* 99*5c51f124SMoriah Waterland * Due to /etc/mnttab files containing entries for multiple nfs hosts 100*5c51f124SMoriah Waterland * HOST_NM_LN needs to be accommodating. The recommended value in the sysinfo 101*5c51f124SMoriah Waterland * man page of 257 needs to be expanded. See bugid 4076513. 102*5c51f124SMoriah Waterland * 1024 chars is defined in the mnttab.h header as the max size of an entry. 103*5c51f124SMoriah Waterland */ 104*5c51f124SMoriah Waterland 105*5c51f124SMoriah Waterland #define HOST_NM_LN MNT_LINE_MAX 106*5c51f124SMoriah Waterland 107*5c51f124SMoriah Waterland /* These cachefs definitions should be in mntent.h. Maybe some day. */ 108*5c51f124SMoriah Waterland #define MNTTYPE_CFS "cachefs" 109*5c51f124SMoriah Waterland #define MNTOPT_BACKFSTYPE "backfstype" 110*5c51f124SMoriah Waterland #define MNTTYPE_AUTO "autofs" 111*5c51f124SMoriah Waterland 112*5c51f124SMoriah Waterland /* 113*5c51f124SMoriah Waterland * Utilities for getting filesystem information from the mount table. 114*5c51f124SMoriah Waterland * 115*5c51f124SMoriah Waterland * Note: vanilla SVr4 code (pkginstall/dockspace.c) used the output from 116*5c51f124SMoriah Waterland * popen() on the "/etc/mount" command. However, we need to get more 117*5c51f124SMoriah Waterland * information about mounted filesystems, so we use the C interfaces to 118*5c51f124SMoriah Waterland * the mount table, which also happens to be much faster than running 119*5c51f124SMoriah Waterland * another process. Since several of the pkg commands need access to the 120*5c51f124SMoriah Waterland * the code has been placed here, to be included in the libinst library. 121*5c51f124SMoriah Waterland */ 122*5c51f124SMoriah Waterland 123*5c51f124SMoriah Waterland #define ALLOC_CHUNK 30 124*5c51f124SMoriah Waterland 125*5c51f124SMoriah Waterland /* 126*5c51f124SMoriah Waterland * fs_tab_ent_comp - compare fstable entries first by length in reverse 127*5c51f124SMoriah Waterland * order, then alphabetically. 128*5c51f124SMoriah Waterland */ 129*5c51f124SMoriah Waterland static int 130*5c51f124SMoriah Waterland fs_tab_ent_comp(const void *e1, const void *e2) 131*5c51f124SMoriah Waterland { 132*5c51f124SMoriah Waterland struct fstable *fs1 = *((struct fstable **)e1); 133*5c51f124SMoriah Waterland struct fstable *fs2 = *((struct fstable **)e2); 134*5c51f124SMoriah Waterland 135*5c51f124SMoriah Waterland if (fs1->namlen == fs2->namlen) 136*5c51f124SMoriah Waterland return (strcmp(fs1->name, fs2->name)); 137*5c51f124SMoriah Waterland else 138*5c51f124SMoriah Waterland return (fs2->namlen - fs1->namlen); 139*5c51f124SMoriah Waterland } 140*5c51f124SMoriah Waterland 141*5c51f124SMoriah Waterland /* 142*5c51f124SMoriah Waterland * This determines if the source of the mount is from another host. If it's 143*5c51f124SMoriah Waterland * from this host, then it might be writable. This returns NOT_REMOTE if it's 144*5c51f124SMoriah Waterland * pure local, REAL_REMOTE if it's being served from another host and 145*5c51f124SMoriah Waterland * SELF_SERVE if it's being served by the current host. 146*5c51f124SMoriah Waterland */ 147*5c51f124SMoriah Waterland static int 148*5c51f124SMoriah Waterland is_remote_src(char *source) 149*5c51f124SMoriah Waterland { 150*5c51f124SMoriah Waterland static char host_name[HOST_NM_LN]; 151*5c51f124SMoriah Waterland char source_host[HOST_NM_LN], *src_ptr, *src_host_ptr; 152*5c51f124SMoriah Waterland static int hn_len; 153*5c51f124SMoriah Waterland 154*5c51f124SMoriah Waterland if (hn_len == 0) { 155*5c51f124SMoriah Waterland /* Find out what host this is. */ 156*5c51f124SMoriah Waterland (void) sysinfo(SI_HOSTNAME, host_name, HOST_NM_LN); 157*5c51f124SMoriah Waterland hn_len = strlen(host_name); 158*5c51f124SMoriah Waterland } 159*5c51f124SMoriah Waterland 160*5c51f124SMoriah Waterland if (source[0] == '/') 161*5c51f124SMoriah Waterland return (NOT_REMOTE); /* No server name, so it's local. */ 162*5c51f124SMoriah Waterland 163*5c51f124SMoriah Waterland if (strchr(source, ':') == NULL) 164*5c51f124SMoriah Waterland return (NOT_REMOTE); /* it's a floppy disk or something */ 165*5c51f124SMoriah Waterland 166*5c51f124SMoriah Waterland src_ptr = source; 167*5c51f124SMoriah Waterland src_host_ptr = source_host; 168*5c51f124SMoriah Waterland 169*5c51f124SMoriah Waterland /* Scan to the end of the hostname (find the ":"). */ 170*5c51f124SMoriah Waterland while (*src_ptr != ':') 171*5c51f124SMoriah Waterland *src_host_ptr++ = *src_ptr++; 172*5c51f124SMoriah Waterland *src_host_ptr = '\0'; 173*5c51f124SMoriah Waterland 174*5c51f124SMoriah Waterland if (strncmp(source, host_name, hn_len) == 0 && 175*5c51f124SMoriah Waterland *(source+hn_len) == ':' || is_local_host(source_host)) 176*5c51f124SMoriah Waterland return (SELF_SERVE); /* Exporting from itself, it's local. */ 177*5c51f124SMoriah Waterland 178*5c51f124SMoriah Waterland return (REAL_REMOTE); 179*5c51f124SMoriah Waterland } 180*5c51f124SMoriah Waterland 181*5c51f124SMoriah Waterland /* 182*5c51f124SMoriah Waterland * This determines if an apparently writeable filesystem is really writeable 183*5c51f124SMoriah Waterland * or if it's been shared over the network with root-restrictive options. 184*5c51f124SMoriah Waterland */ 185*5c51f124SMoriah Waterland static int 186*5c51f124SMoriah Waterland really_write(char *mountpt) 187*5c51f124SMoriah Waterland { 188*5c51f124SMoriah Waterland char testfile[PATH_MAX]; 189*5c51f124SMoriah Waterland int fd, retval = 0; 190*5c51f124SMoriah Waterland struct stat status; 191*5c51f124SMoriah Waterland 192*5c51f124SMoriah Waterland (void) snprintf(testfile, sizeof (testfile), "%s/testXXXXXX", mountpt); 193*5c51f124SMoriah Waterland 194*5c51f124SMoriah Waterland if (mktemp(testfile) == NULL) 195*5c51f124SMoriah Waterland return (0); /* may as well be read-only */ 196*5c51f124SMoriah Waterland /* LINTED do not use creat(); use open(path,... */ 197*5c51f124SMoriah Waterland else if ((fd = creat(testfile, 0777)) == -1) 198*5c51f124SMoriah Waterland return (0); /* can't write */ 199*5c51f124SMoriah Waterland else if (fstat(fd, &status) == -1) 200*5c51f124SMoriah Waterland retval = 0; /* may as well be read-only */ 201*5c51f124SMoriah Waterland else if (status.st_uid != 0) 202*5c51f124SMoriah Waterland retval = 0; /* too many restrictions */ 203*5c51f124SMoriah Waterland else 204*5c51f124SMoriah Waterland retval = 1; 205*5c51f124SMoriah Waterland 206*5c51f124SMoriah Waterland (void) close(fd); 207*5c51f124SMoriah Waterland (void) unlink(testfile); 208*5c51f124SMoriah Waterland 209*5c51f124SMoriah Waterland return (retval); 210*5c51f124SMoriah Waterland } 211*5c51f124SMoriah Waterland 212*5c51f124SMoriah Waterland /* This returns the hostname portion of a remote path. */ 213*5c51f124SMoriah Waterland char * 214*5c51f124SMoriah Waterland get_server_host(short n) 215*5c51f124SMoriah Waterland { 216*5c51f124SMoriah Waterland static char hostname[HOST_NM_LN], *host_end; 217*5c51f124SMoriah Waterland 218*5c51f124SMoriah Waterland if (fs_tab_used == 0) { 219*5c51f124SMoriah Waterland return ("unknown source"); 220*5c51f124SMoriah Waterland } 221*5c51f124SMoriah Waterland 222*5c51f124SMoriah Waterland if (n >= 0 && n < fs_tab_used) { 223*5c51f124SMoriah Waterland (void) strcpy(hostname, fs_tab[n]->remote_name); 224*5c51f124SMoriah Waterland if ((host_end = strchr(hostname, ':')) == NULL) { 225*5c51f124SMoriah Waterland if ((strcmp(fs_tab[n]->fstype, MNTTYPE_AUTO)) == NULL) 226*5c51f124SMoriah Waterland return ("automounter"); 227*5c51f124SMoriah Waterland else 228*5c51f124SMoriah Waterland return (fs_tab[n]->fstype); 229*5c51f124SMoriah Waterland } else { 230*5c51f124SMoriah Waterland *host_end = '\0'; 231*5c51f124SMoriah Waterland return (hostname); 232*5c51f124SMoriah Waterland } 233*5c51f124SMoriah Waterland } 234*5c51f124SMoriah Waterland 235*5c51f124SMoriah Waterland return ("unknown source"); 236*5c51f124SMoriah Waterland } 237*5c51f124SMoriah Waterland 238*5c51f124SMoriah Waterland /* 239*5c51f124SMoriah Waterland * This pulls the path out of a hostpath which may be of the form host:path 240*5c51f124SMoriah Waterland * where path is an absolute path. NOTE: If path turns out to be relative, 241*5c51f124SMoriah Waterland * this returns NULL. 242*5c51f124SMoriah Waterland */ 243*5c51f124SMoriah Waterland static char * 244*5c51f124SMoriah Waterland path_part(char *hostpath) 245*5c51f124SMoriah Waterland { 246*5c51f124SMoriah Waterland char *host_end; 247*5c51f124SMoriah Waterland 248*5c51f124SMoriah Waterland if ((host_end = strchr(hostpath, ':')) == NULL && hostpath[0] == '/') 249*5c51f124SMoriah Waterland return (hostpath); /* It's already legit. */ 250*5c51f124SMoriah Waterland 251*5c51f124SMoriah Waterland if (*(host_end+1) == '/') 252*5c51f124SMoriah Waterland return (host_end+1); /* Here's the path part. */ 253*5c51f124SMoriah Waterland 254*5c51f124SMoriah Waterland return (NULL); 255*5c51f124SMoriah Waterland } 256*5c51f124SMoriah Waterland 257*5c51f124SMoriah Waterland /* 258*5c51f124SMoriah Waterland * This scans the filesystems already mounted to see if this remote mount is 259*5c51f124SMoriah Waterland * already in place on the server. This scans the fs_tab for a remote_name 260*5c51f124SMoriah Waterland * exactly matching the client's. It stores the current entry number 261*5c51f124SMoriah Waterland * corresponding to this mount in the static match_mount. 262*5c51f124SMoriah Waterland * 263*5c51f124SMoriah Waterland * Returns: 264*5c51f124SMoriah Waterland * MNT_NOT Couldn't find it. 265*5c51f124SMoriah Waterland * MNT_EXACT This has actually been manually mounted for us 266*5c51f124SMoriah Waterland * MNT_AVAIL This is mounted for the server, but needs to be 267*5c51f124SMoriah Waterland * loopback mounted from the client's perspective. 268*5c51f124SMoriah Waterland */ 269*5c51f124SMoriah Waterland static int 270*5c51f124SMoriah Waterland already_mounted(struct vfstab *vfs, int is_local_host, char *client_path, 271*5c51f124SMoriah Waterland char *host_path) 272*5c51f124SMoriah Waterland { 273*5c51f124SMoriah Waterland int i; 274*5c51f124SMoriah Waterland 275*5c51f124SMoriah Waterland match_mount = -1; 276*5c51f124SMoriah Waterland 277*5c51f124SMoriah Waterland if (fs_tab_used == 0) { 278*5c51f124SMoriah Waterland return (MNT_NOT); 279*5c51f124SMoriah Waterland } 280*5c51f124SMoriah Waterland 281*5c51f124SMoriah Waterland for (i = 0; i < fs_tab_used; i++) { 282*5c51f124SMoriah Waterland /* 283*5c51f124SMoriah Waterland * Determine if this has been manually mounted exactly as we 284*5c51f124SMoriah Waterland * require. Begin by finding a mount on our current 285*5c51f124SMoriah Waterland * mountpoint. 286*5c51f124SMoriah Waterland */ 287*5c51f124SMoriah Waterland if (strcmp(fs_tab[i]->name, client_path) == 0) { 288*5c51f124SMoriah Waterland /* 289*5c51f124SMoriah Waterland * Now see if it is really the same mount. This isn't 290*5c51f124SMoriah Waterland * smart enough to find mounts on top of mounts, but 291*5c51f124SMoriah Waterland * assuming there is no conspiracy to fool this 292*5c51f124SMoriah Waterland * function, it will be good enough. 293*5c51f124SMoriah Waterland */ 294*5c51f124SMoriah Waterland if (is_local_host && 295*5c51f124SMoriah Waterland strcmp(fs_tab[i]->remote_name, host_path) == 0) { 296*5c51f124SMoriah Waterland match_mount = i; 297*5c51f124SMoriah Waterland return (MNT_EXACT); 298*5c51f124SMoriah Waterland } 299*5c51f124SMoriah Waterland } 300*5c51f124SMoriah Waterland 301*5c51f124SMoriah Waterland /* Determine if this mount is available to the server. */ 302*5c51f124SMoriah Waterland if (strcmp(fs_tab[i]->remote_name, vfs->vfs_special) == 0) { 303*5c51f124SMoriah Waterland match_mount = i; 304*5c51f124SMoriah Waterland return (MNT_AVAIL); 305*5c51f124SMoriah Waterland } 306*5c51f124SMoriah Waterland } 307*5c51f124SMoriah Waterland return (MNT_NOT); 308*5c51f124SMoriah Waterland } 309*5c51f124SMoriah Waterland 310*5c51f124SMoriah Waterland /* 311*5c51f124SMoriah Waterland * This function unmounts all of the loopback mounts created for the client. 312*5c51f124SMoriah Waterland * If no client stuff is mounted, this is completely benign, it finds that 313*5c51f124SMoriah Waterland * nothing is mounted up and returns. It returns "1" for unmounted everything 314*5c51f124SMoriah Waterland * OK and "0" for failure. 315*5c51f124SMoriah Waterland */ 316*5c51f124SMoriah Waterland int 317*5c51f124SMoriah Waterland unmount_client() 318*5c51f124SMoriah Waterland { 319*5c51f124SMoriah Waterland int errcode; 320*5c51f124SMoriah Waterland int exit_no; 321*5c51f124SMoriah Waterland int n; 322*5c51f124SMoriah Waterland int retcode = 1; 323*5c51f124SMoriah Waterland int status; 324*5c51f124SMoriah Waterland pid_t pid; 325*5c51f124SMoriah Waterland pid_t pid_return; 326*5c51f124SMoriah Waterland 327*5c51f124SMoriah Waterland if (fs_tab_used == 0) { 328*5c51f124SMoriah Waterland return (1); 329*5c51f124SMoriah Waterland } 330*5c51f124SMoriah Waterland 331*5c51f124SMoriah Waterland for (n = 0; n < fs_tab_used-1; n++) { 332*5c51f124SMoriah Waterland /* If the filesystem is mounted and this utility did it ... */ 333*5c51f124SMoriah Waterland if (fs_tab[n]->cl_mounted && fs_tab[n]->srvr_map) { 334*5c51f124SMoriah Waterland char *arg[3]; 335*5c51f124SMoriah Waterland 336*5c51f124SMoriah Waterland /* create arglist for umount command */ 337*5c51f124SMoriah Waterland 338*5c51f124SMoriah Waterland arg[0] = UMOUNT; 339*5c51f124SMoriah Waterland arg[1] = fs_tab[n]->name; 340*5c51f124SMoriah Waterland arg[2] = (char *)NULL; 341*5c51f124SMoriah Waterland 342*5c51f124SMoriah Waterland /* flush standard i/o before creating new process */ 343*5c51f124SMoriah Waterland 344*5c51f124SMoriah Waterland (void) fflush(stderr); 345*5c51f124SMoriah Waterland (void) fflush(stdout); 346*5c51f124SMoriah Waterland 347*5c51f124SMoriah Waterland /* 348*5c51f124SMoriah Waterland * create new process to execute command in; 349*5c51f124SMoriah Waterland * vfork is being used to avoid duplicating the parents 350*5c51f124SMoriah Waterland * memory space - this means that the child process may 351*5c51f124SMoriah Waterland * not modify any of the parents memory including the 352*5c51f124SMoriah Waterland * standard i/o descriptors - all the child can do is 353*5c51f124SMoriah Waterland * adjust interrupts and open files as a prelude to a 354*5c51f124SMoriah Waterland * call to exec(). 355*5c51f124SMoriah Waterland */ 356*5c51f124SMoriah Waterland 357*5c51f124SMoriah Waterland pid = vfork(); 358*5c51f124SMoriah Waterland if (pid < 0) { 359*5c51f124SMoriah Waterland /* fork failed! */ 360*5c51f124SMoriah Waterland 361*5c51f124SMoriah Waterland logerr(WRN_BAD_FORK, errno, strerror(errno)); 362*5c51f124SMoriah Waterland retcode = 0; 363*5c51f124SMoriah Waterland } else if (pid > 0) { 364*5c51f124SMoriah Waterland /* 365*5c51f124SMoriah Waterland * this is the parent process 366*5c51f124SMoriah Waterland */ 367*5c51f124SMoriah Waterland 368*5c51f124SMoriah Waterland status = 0; 369*5c51f124SMoriah Waterland pid_return = waitpid(pid, &status, 0); 370*5c51f124SMoriah Waterland 371*5c51f124SMoriah Waterland if (pid_return != pid) { 372*5c51f124SMoriah Waterland logerr(WRN_BAD_WAIT, pid, pid_return, 373*5c51f124SMoriah Waterland (unsigned long)status, errno, 374*5c51f124SMoriah Waterland strerror(errno)); 375*5c51f124SMoriah Waterland retcode = 0; 376*5c51f124SMoriah Waterland } 377*5c51f124SMoriah Waterland 378*5c51f124SMoriah Waterland /* 379*5c51f124SMoriah Waterland * If the child was stopped or killed by a 380*5c51f124SMoriah Waterland * signal or exied with any code but 0, we 381*5c51f124SMoriah Waterland * assume the mount has failed. 382*5c51f124SMoriah Waterland */ 383*5c51f124SMoriah Waterland 384*5c51f124SMoriah Waterland if (!WIFEXITED(status) || 385*5c51f124SMoriah Waterland (errcode = WEXITSTATUS(status))) { 386*5c51f124SMoriah Waterland retcode = 0; 387*5c51f124SMoriah Waterland logerr(WRN_FSTAB_UMOUNT, 388*5c51f124SMoriah Waterland fs_tab[n]->name, errcode); 389*5c51f124SMoriah Waterland } else { 390*5c51f124SMoriah Waterland fs_tab[n]->cl_mounted = 0; 391*5c51f124SMoriah Waterland } 392*5c51f124SMoriah Waterland } else { 393*5c51f124SMoriah Waterland /* 394*5c51f124SMoriah Waterland * this is the child process 395*5c51f124SMoriah Waterland */ 396*5c51f124SMoriah Waterland 397*5c51f124SMoriah Waterland int i; 398*5c51f124SMoriah Waterland 399*5c51f124SMoriah Waterland /* reset any signals to default */ 400*5c51f124SMoriah Waterland 401*5c51f124SMoriah Waterland for (i = 0; i < NSIG; i++) { 402*5c51f124SMoriah Waterland (void) sigset(i, SIG_DFL); 403*5c51f124SMoriah Waterland } 404*5c51f124SMoriah Waterland 405*5c51f124SMoriah Waterland /* 406*5c51f124SMoriah Waterland * Redirect output to /dev/null because the 407*5c51f124SMoriah Waterland * umount error message may be confusing to 408*5c51f124SMoriah Waterland * the user. 409*5c51f124SMoriah Waterland */ 410*5c51f124SMoriah Waterland 411*5c51f124SMoriah Waterland i = open("/dev/null", O_WRONLY); 412*5c51f124SMoriah Waterland if (i >= 0) { 413*5c51f124SMoriah Waterland dup2(2, STDERR_FILENO); 414*5c51f124SMoriah Waterland } 415*5c51f124SMoriah Waterland 416*5c51f124SMoriah Waterland /* close all file descriptors except stdio */ 417*5c51f124SMoriah Waterland 418*5c51f124SMoriah Waterland closefrom(3); 419*5c51f124SMoriah Waterland 420*5c51f124SMoriah Waterland exit_no = execve(arg[0], arg, environ); 421*5c51f124SMoriah Waterland _exit(exit_no); 422*5c51f124SMoriah Waterland } 423*5c51f124SMoriah Waterland } 424*5c51f124SMoriah Waterland } 425*5c51f124SMoriah Waterland 426*5c51f124SMoriah Waterland return (retcode); 427*5c51f124SMoriah Waterland } 428*5c51f124SMoriah Waterland 429*5c51f124SMoriah Waterland /* 430*5c51f124SMoriah Waterland * This function creates the necessary loopback mounts to emulate the client 431*5c51f124SMoriah Waterland * configuration with respect to the server. If this is being run on a 432*5c51f124SMoriah Waterland * standalone or the installation is actually to the local system, this call 433*5c51f124SMoriah Waterland * is benign since srvr_map won't be set anywhere. It returns "1" for mounted 434*5c51f124SMoriah Waterland * everything OK and "0" for failure. 435*5c51f124SMoriah Waterland */ 436*5c51f124SMoriah Waterland int 437*5c51f124SMoriah Waterland mount_client() 438*5c51f124SMoriah Waterland { 439*5c51f124SMoriah Waterland int errcode; 440*5c51f124SMoriah Waterland int exit_no; 441*5c51f124SMoriah Waterland int n; 442*5c51f124SMoriah Waterland int retcode = 1; 443*5c51f124SMoriah Waterland int status; 444*5c51f124SMoriah Waterland pid_t pid; 445*5c51f124SMoriah Waterland pid_t pid_return; 446*5c51f124SMoriah Waterland 447*5c51f124SMoriah Waterland if (fs_tab_used == 0) { 448*5c51f124SMoriah Waterland return (1); 449*5c51f124SMoriah Waterland } 450*5c51f124SMoriah Waterland 451*5c51f124SMoriah Waterland for (n = fs_tab_used-1; n >= 0; n--) { 452*5c51f124SMoriah Waterland /* 453*5c51f124SMoriah Waterland * If the filesystem is mounted (meaning available) and the 454*5c51f124SMoriah Waterland * apparent filesystem can be mapped to a local filesystem 455*5c51f124SMoriah Waterland * AND the local filesystem is not the same as the target 456*5c51f124SMoriah Waterland * filesystem, mount it. 457*5c51f124SMoriah Waterland */ 458*5c51f124SMoriah Waterland if (fs_tab[n]->mounted && fs_tab[n]->srvr_map) { 459*5c51f124SMoriah Waterland char *arg[6]; 460*5c51f124SMoriah Waterland 461*5c51f124SMoriah Waterland /* create arglist for mount command */ 462*5c51f124SMoriah Waterland 463*5c51f124SMoriah Waterland arg[0] = MOUNT; 464*5c51f124SMoriah Waterland arg[1] = "-F"; 465*5c51f124SMoriah Waterland arg[2] = "lofs"; 466*5c51f124SMoriah Waterland arg[3] = fs_tab[n]->remote_name; 467*5c51f124SMoriah Waterland arg[4] = fs_tab[n]->name; 468*5c51f124SMoriah Waterland arg[5] = (char *)NULL; 469*5c51f124SMoriah Waterland 470*5c51f124SMoriah Waterland /* flush standard i/o before creating new process */ 471*5c51f124SMoriah Waterland 472*5c51f124SMoriah Waterland (void) fflush(stderr); 473*5c51f124SMoriah Waterland (void) fflush(stdout); 474*5c51f124SMoriah Waterland 475*5c51f124SMoriah Waterland /* 476*5c51f124SMoriah Waterland * create new process to execute command in; 477*5c51f124SMoriah Waterland * vfork is being used to avoid duplicating the parents 478*5c51f124SMoriah Waterland * memory space - this means that the child process may 479*5c51f124SMoriah Waterland * not modify any of the parents memory including the 480*5c51f124SMoriah Waterland * standard i/o descriptors - all the child can do is 481*5c51f124SMoriah Waterland * adjust interrupts and open files as a prelude to a 482*5c51f124SMoriah Waterland * call to exec(). 483*5c51f124SMoriah Waterland */ 484*5c51f124SMoriah Waterland 485*5c51f124SMoriah Waterland pid = vfork(); 486*5c51f124SMoriah Waterland if (pid < 0) { 487*5c51f124SMoriah Waterland /* fork failed! */ 488*5c51f124SMoriah Waterland 489*5c51f124SMoriah Waterland logerr(WRN_BAD_FORK, errno, strerror(errno)); 490*5c51f124SMoriah Waterland retcode = 0; 491*5c51f124SMoriah Waterland } else if (pid > 0) { 492*5c51f124SMoriah Waterland /* 493*5c51f124SMoriah Waterland * this is the parent process 494*5c51f124SMoriah Waterland */ 495*5c51f124SMoriah Waterland 496*5c51f124SMoriah Waterland pid_return = waitpid(pid, &status, 0); 497*5c51f124SMoriah Waterland 498*5c51f124SMoriah Waterland if (pid_return != pid) { 499*5c51f124SMoriah Waterland logerr(WRN_BAD_WAIT, pid, pid_return, 500*5c51f124SMoriah Waterland (unsigned long)status, errno, 501*5c51f124SMoriah Waterland strerror(errno)); 502*5c51f124SMoriah Waterland retcode = 0; 503*5c51f124SMoriah Waterland } 504*5c51f124SMoriah Waterland 505*5c51f124SMoriah Waterland /* 506*5c51f124SMoriah Waterland * If the child was stopped or killed by a 507*5c51f124SMoriah Waterland * signal or exied with any code but 0, we 508*5c51f124SMoriah Waterland * assume the mount has failed. 509*5c51f124SMoriah Waterland */ 510*5c51f124SMoriah Waterland 511*5c51f124SMoriah Waterland if (!WIFEXITED(status) || 512*5c51f124SMoriah Waterland (errcode = WEXITSTATUS(status))) { 513*5c51f124SMoriah Waterland retcode = 0; 514*5c51f124SMoriah Waterland fs_tab[n]->mnt_failed = 1; 515*5c51f124SMoriah Waterland logerr(WRN_FSTAB_MOUNT, 516*5c51f124SMoriah Waterland fs_tab[n]->name, errcode); 517*5c51f124SMoriah Waterland } else { 518*5c51f124SMoriah Waterland fs_tab[n]->cl_mounted = 1; 519*5c51f124SMoriah Waterland } 520*5c51f124SMoriah Waterland } else { 521*5c51f124SMoriah Waterland /* 522*5c51f124SMoriah Waterland * this is the child process 523*5c51f124SMoriah Waterland */ 524*5c51f124SMoriah Waterland 525*5c51f124SMoriah Waterland int i; 526*5c51f124SMoriah Waterland 527*5c51f124SMoriah Waterland /* reset all signals to default */ 528*5c51f124SMoriah Waterland 529*5c51f124SMoriah Waterland for (i = 0; i < NSIG; i++) { 530*5c51f124SMoriah Waterland (void) sigset(i, SIG_DFL); 531*5c51f124SMoriah Waterland } 532*5c51f124SMoriah Waterland 533*5c51f124SMoriah Waterland /* 534*5c51f124SMoriah Waterland * Redirect output to /dev/null because the 535*5c51f124SMoriah Waterland * mount error message may be confusing to 536*5c51f124SMoriah Waterland * the user. 537*5c51f124SMoriah Waterland */ 538*5c51f124SMoriah Waterland 539*5c51f124SMoriah Waterland i = open("/dev/null", O_WRONLY); 540*5c51f124SMoriah Waterland if (i >= 0) { 541*5c51f124SMoriah Waterland dup2(i, STDERR_FILENO); 542*5c51f124SMoriah Waterland } 543*5c51f124SMoriah Waterland 544*5c51f124SMoriah Waterland /* close all file descriptors except stdio */ 545*5c51f124SMoriah Waterland 546*5c51f124SMoriah Waterland closefrom(3); 547*5c51f124SMoriah Waterland 548*5c51f124SMoriah Waterland exit_no = execve(arg[0], arg, environ); 549*5c51f124SMoriah Waterland _exit(exit_no); 550*5c51f124SMoriah Waterland /*NOTREACHED*/ 551*5c51f124SMoriah Waterland } 552*5c51f124SMoriah Waterland } 553*5c51f124SMoriah Waterland } 554*5c51f124SMoriah Waterland return (retcode); 555*5c51f124SMoriah Waterland } 556*5c51f124SMoriah Waterland 557*5c51f124SMoriah Waterland /* 558*5c51f124SMoriah Waterland * This function maps path, on a loopback filesystem, back to the real server 559*5c51f124SMoriah Waterland * filesystem. fsys_value is the fs_tab[] entry to which the loopback'd path is 560*5c51f124SMoriah Waterland * mapped. This returns a pointer to a static area. If the result is needed 561*5c51f124SMoriah Waterland * for further processing, it should be strdup()'d or something. 562*5c51f124SMoriah Waterland */ 563*5c51f124SMoriah Waterland char * 564*5c51f124SMoriah Waterland server_map(char *path, short fsys_value) 565*5c51f124SMoriah Waterland { 566*5c51f124SMoriah Waterland static char server_construction[PATH_MAX]; 567*5c51f124SMoriah Waterland 568*5c51f124SMoriah Waterland if (fs_tab_used == 0) { 569*5c51f124SMoriah Waterland (void) strcpy(server_construction, path); 570*5c51f124SMoriah Waterland } else if (fsys_value >= 0 && fsys_value < fs_tab_used) { 571*5c51f124SMoriah Waterland (void) snprintf(server_construction, 572*5c51f124SMoriah Waterland sizeof (server_construction), 573*5c51f124SMoriah Waterland "%s%s", fs_tab[fsys_value]->remote_name, 574*5c51f124SMoriah Waterland path+strlen(fs_tab[fsys_value]->name)); 575*5c51f124SMoriah Waterland } else { 576*5c51f124SMoriah Waterland (void) strcpy(server_construction, path); 577*5c51f124SMoriah Waterland } 578*5c51f124SMoriah Waterland 579*5c51f124SMoriah Waterland return (server_construction); 580*5c51f124SMoriah Waterland } 581*5c51f124SMoriah Waterland 582*5c51f124SMoriah Waterland /* This function sets up the standard parts of the fs_tab. */ 583*5c51f124SMoriah Waterland static struct fstable * 584*5c51f124SMoriah Waterland fs_tab_init(char *mountp, char *fstype) 585*5c51f124SMoriah Waterland { 586*5c51f124SMoriah Waterland struct fstable *nfte; 587*5c51f124SMoriah Waterland 588*5c51f124SMoriah Waterland /* Create the array if necessary. */ 589*5c51f124SMoriah Waterland if (fs_list == -1) { 590*5c51f124SMoriah Waterland fs_list = ar_create(ALLOC_CHUNK, 591*5c51f124SMoriah Waterland (unsigned)sizeof (struct fstable), 592*5c51f124SMoriah Waterland "filesystem mount data"); 593*5c51f124SMoriah Waterland if (fs_list == -1) { 594*5c51f124SMoriah Waterland progerr(ERR_MALLOC, "fs_list", errno, strerror(errno)); 595*5c51f124SMoriah Waterland return (NULL); 596*5c51f124SMoriah Waterland } 597*5c51f124SMoriah Waterland } 598*5c51f124SMoriah Waterland 599*5c51f124SMoriah Waterland /* 600*5c51f124SMoriah Waterland * Allocate an fstable entry for this mnttab entry. 601*5c51f124SMoriah Waterland */ 602*5c51f124SMoriah Waterland if ((nfte = *(struct fstable **)ar_next_avail(fs_list)) 603*5c51f124SMoriah Waterland == NULL) { 604*5c51f124SMoriah Waterland progerr(ERR_MALLOC, "nfte", errno, strerror(errno)); 605*5c51f124SMoriah Waterland return (NULL); 606*5c51f124SMoriah Waterland } 607*5c51f124SMoriah Waterland 608*5c51f124SMoriah Waterland /* 609*5c51f124SMoriah Waterland * Point fs_tab at the head of the array again, since it may have 610*5c51f124SMoriah Waterland * moved due to realloc in ar_next_avail(). If ar_next_avail() realizes 611*5c51f124SMoriah Waterland * that there is no more room to grow the array, it reallocates the 612*5c51f124SMoriah Waterland * array. Because we stored pointer to that array in fs_tab, we need 613*5c51f124SMoriah Waterland * to make sure that it is updated as well. 614*5c51f124SMoriah Waterland */ 615*5c51f124SMoriah Waterland if ((fs_tab = (struct fstable **)ar_get_head(fs_list)) == NULL) { 616*5c51f124SMoriah Waterland progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno)); 617*5c51f124SMoriah Waterland return (NULL); 618*5c51f124SMoriah Waterland } 619*5c51f124SMoriah Waterland 620*5c51f124SMoriah Waterland /* 621*5c51f124SMoriah Waterland * Get the length of the 'mount point' name. 622*5c51f124SMoriah Waterland */ 623*5c51f124SMoriah Waterland nfte->namlen = strlen(mountp); 624*5c51f124SMoriah Waterland /* 625*5c51f124SMoriah Waterland * Allocate space for the 'mount point' name. 626*5c51f124SMoriah Waterland */ 627*5c51f124SMoriah Waterland if ((nfte->name = malloc(nfte->namlen+1)) == NULL) { 628*5c51f124SMoriah Waterland progerr(ERR_MALLOC, "name", errno, strerror(errno)); 629*5c51f124SMoriah Waterland return (NULL); 630*5c51f124SMoriah Waterland } 631*5c51f124SMoriah Waterland (void) strcpy(nfte->name, mountp); 632*5c51f124SMoriah Waterland 633*5c51f124SMoriah Waterland if ((nfte->fstype = malloc(strlen(fstype)+1)) == NULL) { 634*5c51f124SMoriah Waterland progerr(ERR_MALLOC, "fstype", errno, strerror(errno)); 635*5c51f124SMoriah Waterland return (NULL); 636*5c51f124SMoriah Waterland } 637*5c51f124SMoriah Waterland (void) strcpy(nfte->fstype, fstype); 638*5c51f124SMoriah Waterland 639*5c51f124SMoriah Waterland fs_tab_used++; 640*5c51f124SMoriah Waterland 641*5c51f124SMoriah Waterland return (nfte); 642*5c51f124SMoriah Waterland } 643*5c51f124SMoriah Waterland 644*5c51f124SMoriah Waterland /* This function frees all memory associated with the filesystem table. */ 645*5c51f124SMoriah Waterland void 646*5c51f124SMoriah Waterland fs_tab_free(void) 647*5c51f124SMoriah Waterland { 648*5c51f124SMoriah Waterland int n; 649*5c51f124SMoriah Waterland 650*5c51f124SMoriah Waterland if (fs_tab_used == 0) { 651*5c51f124SMoriah Waterland return; 652*5c51f124SMoriah Waterland } 653*5c51f124SMoriah Waterland 654*5c51f124SMoriah Waterland for (n = 0; n < fs_tab_used; n++) { 655*5c51f124SMoriah Waterland free(fs_tab[n]->fstype); 656*5c51f124SMoriah Waterland free(fs_tab[n]->name); 657*5c51f124SMoriah Waterland free(fs_tab[n]->remote_name); 658*5c51f124SMoriah Waterland } 659*5c51f124SMoriah Waterland 660*5c51f124SMoriah Waterland ar_free(fs_list); 661*5c51f124SMoriah Waterland } 662*5c51f124SMoriah Waterland 663*5c51f124SMoriah Waterland /* This function scans a string of mount options for a specific keyword. */ 664*5c51f124SMoriah Waterland static int 665*5c51f124SMoriah Waterland hasopt(char *options, char *keyword) 666*5c51f124SMoriah Waterland { 667*5c51f124SMoriah Waterland char vfs_options[VFS_LINE_MAX], *optptr; 668*5c51f124SMoriah Waterland 669*5c51f124SMoriah Waterland if (!options) { 670*5c51f124SMoriah Waterland (void) strcpy(vfs_options, "ro"); 671*5c51f124SMoriah Waterland } else { 672*5c51f124SMoriah Waterland (void) strcpy(vfs_options, options); 673*5c51f124SMoriah Waterland } 674*5c51f124SMoriah Waterland 675*5c51f124SMoriah Waterland while (optptr = strrchr(vfs_options, ',')) { 676*5c51f124SMoriah Waterland *optptr++ = '\0'; 677*5c51f124SMoriah Waterland 678*5c51f124SMoriah Waterland if (strcmp(optptr, keyword) == 0) 679*5c51f124SMoriah Waterland return (1); 680*5c51f124SMoriah Waterland } 681*5c51f124SMoriah Waterland 682*5c51f124SMoriah Waterland /* Now deal with the remainder. */ 683*5c51f124SMoriah Waterland if (strcmp(vfs_options, keyword) == 0) 684*5c51f124SMoriah Waterland return (1); 685*5c51f124SMoriah Waterland 686*5c51f124SMoriah Waterland return (0); 687*5c51f124SMoriah Waterland } 688*5c51f124SMoriah Waterland 689*5c51f124SMoriah Waterland /* 690*5c51f124SMoriah Waterland * This function constructs a new filesystem table (fs_tab[]) entry based on 691*5c51f124SMoriah Waterland * an /etc/mnttab entry. When it returns, the new entry has been inserted 692*5c51f124SMoriah Waterland * into fs_tab[]. 693*5c51f124SMoriah Waterland */ 694*5c51f124SMoriah Waterland static int 695*5c51f124SMoriah Waterland construct_mt(struct mnttab *mt) 696*5c51f124SMoriah Waterland { 697*5c51f124SMoriah Waterland struct fstable *nfte; 698*5c51f124SMoriah Waterland 699*5c51f124SMoriah Waterland /* 700*5c51f124SMoriah Waterland * Initialize fstable structure and make the standard entries. 701*5c51f124SMoriah Waterland */ 702*5c51f124SMoriah Waterland if ((nfte = fs_tab_init(mt->mnt_mountp, mt->mnt_fstype)) == NULL) 703*5c51f124SMoriah Waterland return (1); 704*5c51f124SMoriah Waterland 705*5c51f124SMoriah Waterland /* See if this is served from another host. */ 706*5c51f124SMoriah Waterland if (is_remote_src(mt->mnt_special) == REAL_REMOTE || 707*5c51f124SMoriah Waterland strcmp(mt->mnt_fstype, MNTTYPE_AUTO) == 0) 708*5c51f124SMoriah Waterland nfte->remote = 1; 709*5c51f124SMoriah Waterland else 710*5c51f124SMoriah Waterland nfte->remote = 0; 711*5c51f124SMoriah Waterland 712*5c51f124SMoriah Waterland /* It's mounted now (by definition), so we don't have to remap it. */ 713*5c51f124SMoriah Waterland nfte->srvr_map = 0; 714*5c51f124SMoriah Waterland nfte->mounted = 1; 715*5c51f124SMoriah Waterland 716*5c51f124SMoriah Waterland nfte->remote_name = strdup(mt->mnt_special); 717*5c51f124SMoriah Waterland 718*5c51f124SMoriah Waterland /* 719*5c51f124SMoriah Waterland * This checks the mount commands which establish the most 720*5c51f124SMoriah Waterland * basic level of access. Later further tests may be 721*5c51f124SMoriah Waterland * necessary to fully qualify this. We set this bit 722*5c51f124SMoriah Waterland * preliminarily because we have access to the mount data 723*5c51f124SMoriah Waterland * now. 724*5c51f124SMoriah Waterland */ 725*5c51f124SMoriah Waterland nfte->writeable = 0; /* Assume read-only. */ 726*5c51f124SMoriah Waterland if (hasmntopt(mt, MNTOPT_RO) == NULL) { 727*5c51f124SMoriah Waterland nfte->writeable = 1; 728*5c51f124SMoriah Waterland if (!(nfte->remote)) 729*5c51f124SMoriah Waterland /* 730*5c51f124SMoriah Waterland * There's no network involved, so this 731*5c51f124SMoriah Waterland * assessment is confirmed. 732*5c51f124SMoriah Waterland */ 733*5c51f124SMoriah Waterland nfte->write_tested = 1; 734*5c51f124SMoriah Waterland } else 735*5c51f124SMoriah Waterland /* read-only is read-only */ 736*5c51f124SMoriah Waterland nfte->write_tested = 1; 737*5c51f124SMoriah Waterland 738*5c51f124SMoriah Waterland /* Is this coming to us from a server? */ 739*5c51f124SMoriah Waterland if (nfte->remote && !(nfte->writeable)) 740*5c51f124SMoriah Waterland nfte->served = 1; 741*5c51f124SMoriah Waterland 742*5c51f124SMoriah Waterland return (0); 743*5c51f124SMoriah Waterland } 744*5c51f124SMoriah Waterland 745*5c51f124SMoriah Waterland /* 746*5c51f124SMoriah Waterland * This function modifies an existing fs_tab[] entry. It was found mounted up 747*5c51f124SMoriah Waterland * exactly the way we would have mounted it in mount_client() only at the 748*5c51f124SMoriah Waterland * time we didn't know it was for the client. Now we do, so we're setting the 749*5c51f124SMoriah Waterland * various permissions to conform to the client view. 750*5c51f124SMoriah Waterland */ 751*5c51f124SMoriah Waterland static void 752*5c51f124SMoriah Waterland mod_existing(struct vfstab *vfsent, int fstab_entry, int is_remote) 753*5c51f124SMoriah Waterland { 754*5c51f124SMoriah Waterland /* 755*5c51f124SMoriah Waterland * Establish whether the client will see this as served. 756*5c51f124SMoriah Waterland */ 757*5c51f124SMoriah Waterland if (is_remote && hasopt(vfsent->vfs_mntopts, MNTOPT_RO)) 758*5c51f124SMoriah Waterland fs_tab[fstab_entry]->served = 1; 759*5c51f124SMoriah Waterland 760*5c51f124SMoriah Waterland fs_tab[fstab_entry]->cl_mounted = 1; 761*5c51f124SMoriah Waterland } 762*5c51f124SMoriah Waterland 763*5c51f124SMoriah Waterland /* 764*5c51f124SMoriah Waterland * This function constructs a new fs_tab[] entry based on 765*5c51f124SMoriah Waterland * an /etc/vfstab entry. When it returns, the new entry has been inserted 766*5c51f124SMoriah Waterland * into fstab[]. 767*5c51f124SMoriah Waterland */ 768*5c51f124SMoriah Waterland static int 769*5c51f124SMoriah Waterland construct_vfs(struct vfstab *vfsent, char *client_path, char *link_name, 770*5c51f124SMoriah Waterland int is_remote, int mnt_stat) 771*5c51f124SMoriah Waterland { 772*5c51f124SMoriah Waterland int use_link; 773*5c51f124SMoriah Waterland struct fstable *nfte; 774*5c51f124SMoriah Waterland 775*5c51f124SMoriah Waterland if ((nfte = fs_tab_init(client_path, vfsent->vfs_fstype)) == NULL) 776*5c51f124SMoriah Waterland return (1); 777*5c51f124SMoriah Waterland 778*5c51f124SMoriah Waterland nfte->remote = (is_remote == REAL_REMOTE); 779*5c51f124SMoriah Waterland 780*5c51f124SMoriah Waterland /* 781*5c51f124SMoriah Waterland * The file system mounted on the client may or may not be writeable. 782*5c51f124SMoriah Waterland * So we hand it over to fsys() to evaluate. This will have the same 783*5c51f124SMoriah Waterland * read/write attributes as the corresponding mounted filesystem. 784*5c51f124SMoriah Waterland */ 785*5c51f124SMoriah Waterland use_link = 0; 786*5c51f124SMoriah Waterland if (nfte->remote) { 787*5c51f124SMoriah Waterland /* 788*5c51f124SMoriah Waterland * Deal here with mount points actually on a system remote 789*5c51f124SMoriah Waterland * from the server. 790*5c51f124SMoriah Waterland */ 791*5c51f124SMoriah Waterland if (mnt_stat == MNT_NOT) { 792*5c51f124SMoriah Waterland /* 793*5c51f124SMoriah Waterland * This filesystem isn't in the current mount table 794*5c51f124SMoriah Waterland * meaning it isn't mounted, the current host can't 795*5c51f124SMoriah Waterland * write to it and there's no point to mapping it for 796*5c51f124SMoriah Waterland * the server. 797*5c51f124SMoriah Waterland */ 798*5c51f124SMoriah Waterland link_name = NULL; 799*5c51f124SMoriah Waterland nfte->mounted = 0; 800*5c51f124SMoriah Waterland nfte->srvr_map = 0; 801*5c51f124SMoriah Waterland nfte->writeable = 0; 802*5c51f124SMoriah Waterland } else { /* It's MNT_AVAIL. */ 803*5c51f124SMoriah Waterland /* 804*5c51f124SMoriah Waterland * This filesystem is associated with a current 805*5c51f124SMoriah Waterland * mountpoint. Since it's mounted, it needs to be 806*5c51f124SMoriah Waterland * remapped and it is writable if the real mounted 807*5c51f124SMoriah Waterland * filesystem is writeable. 808*5c51f124SMoriah Waterland */ 809*5c51f124SMoriah Waterland use_link = 1; 810*5c51f124SMoriah Waterland link_name = strdup(fs_tab[match_mount]->name); 811*5c51f124SMoriah Waterland nfte->mounted = 1; 812*5c51f124SMoriah Waterland nfte->srvr_map = 1; 813*5c51f124SMoriah Waterland nfte->writeable = fs_tab[match_mount]->writeable; 814*5c51f124SMoriah Waterland nfte->write_tested = fs_tab[match_mount]->write_tested; 815*5c51f124SMoriah Waterland } 816*5c51f124SMoriah Waterland } else { /* local filesystem */ 817*5c51f124SMoriah Waterland use_link = 1; 818*5c51f124SMoriah Waterland nfte->mounted = 1; 819*5c51f124SMoriah Waterland nfte->srvr_map = 1; 820*5c51f124SMoriah Waterland nfte->writeable = fs_tab[fsys(link_name)]->writeable; 821*5c51f124SMoriah Waterland nfte->write_tested = 1; 822*5c51f124SMoriah Waterland } 823*5c51f124SMoriah Waterland 824*5c51f124SMoriah Waterland /* 825*5c51f124SMoriah Waterland * Now we establish whether the client will see this as served. 826*5c51f124SMoriah Waterland */ 827*5c51f124SMoriah Waterland if (is_remote && hasopt(vfsent->vfs_mntopts, MNTOPT_RO)) 828*5c51f124SMoriah Waterland nfte->served = 1; 829*5c51f124SMoriah Waterland 830*5c51f124SMoriah Waterland if (use_link) { 831*5c51f124SMoriah Waterland nfte->remote_name = link_name; 832*5c51f124SMoriah Waterland } else { 833*5c51f124SMoriah Waterland nfte->remote_name = strdup(vfsent->vfs_special); 834*5c51f124SMoriah Waterland } 835*5c51f124SMoriah Waterland 836*5c51f124SMoriah Waterland return (0); 837*5c51f124SMoriah Waterland } 838*5c51f124SMoriah Waterland 839*5c51f124SMoriah Waterland /* 840*5c51f124SMoriah Waterland * get_mntinfo - get the mount table, now dynamically allocated. Returns 0 if 841*5c51f124SMoriah Waterland * no problem and 1 if there's a fatal error. 842*5c51f124SMoriah Waterland */ 843*5c51f124SMoriah Waterland int 844*5c51f124SMoriah Waterland get_mntinfo(int map_client, char *vfstab_file) 845*5c51f124SMoriah Waterland { 846*5c51f124SMoriah Waterland static char *rn = "/"; 847*5c51f124SMoriah Waterland FILE *pp; 848*5c51f124SMoriah Waterland struct mnttab mtbuf; 849*5c51f124SMoriah Waterland struct mnttab *mt = &mtbuf; 850*5c51f124SMoriah Waterland char *install_root; 851*5c51f124SMoriah Waterland int is_remote; 852*5c51f124SMoriah Waterland 853*5c51f124SMoriah Waterland /* 854*5c51f124SMoriah Waterland * Open the mount table for the current host and establish a global 855*5c51f124SMoriah Waterland * table that holds data about current mount status. 856*5c51f124SMoriah Waterland */ 857*5c51f124SMoriah Waterland if ((pp = setmntent(MOUNT_TABLE, "r")) == NULL) { 858*5c51f124SMoriah Waterland progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno)); 859*5c51f124SMoriah Waterland return (1); 860*5c51f124SMoriah Waterland } 861*5c51f124SMoriah Waterland 862*5c51f124SMoriah Waterland /* 863*5c51f124SMoriah Waterland * First, review the mounted filesystems on the managing host. This 864*5c51f124SMoriah Waterland * may also be the target host but we haven't decided that for sure 865*5c51f124SMoriah Waterland * yet. 866*5c51f124SMoriah Waterland */ 867*5c51f124SMoriah Waterland while (!getmntent(pp, mt)) 868*5c51f124SMoriah Waterland if (construct_mt(mt)) 869*5c51f124SMoriah Waterland return (1); 870*5c51f124SMoriah Waterland 871*5c51f124SMoriah Waterland (void) endmntent(pp); 872*5c51f124SMoriah Waterland 873*5c51f124SMoriah Waterland /* 874*5c51f124SMoriah Waterland * Now, we see if this installation is to a client. If it is, we scan 875*5c51f124SMoriah Waterland * the client's vfstab to determine what filesystems are 876*5c51f124SMoriah Waterland * inappropriate to write to. This simply adds the vfstab entries 877*5c51f124SMoriah Waterland * representing what will be remote file systems for the client. 878*5c51f124SMoriah Waterland * Everything that isn't remote to the client is already accounted 879*5c51f124SMoriah Waterland * for in the fs_tab[] so far. If the remote filesystem is really on 880*5c51f124SMoriah Waterland * this server, we will write through to the server from this client. 881*5c51f124SMoriah Waterland */ 882*5c51f124SMoriah Waterland install_root = get_inst_root(); 883*5c51f124SMoriah Waterland if (install_root && strcmp(install_root, "/") != 0 && map_client) { 884*5c51f124SMoriah Waterland /* OK, this is a legitimate remote client. */ 885*5c51f124SMoriah Waterland struct vfstab vfsbuf; 886*5c51f124SMoriah Waterland struct vfstab *vfs = &vfsbuf; 887*5c51f124SMoriah Waterland char VFS_TABLE[PATH_MAX]; 888*5c51f124SMoriah Waterland 889*5c51f124SMoriah Waterland /* 890*5c51f124SMoriah Waterland * Since we use the fsys() function later, and it depends on 891*5c51f124SMoriah Waterland * an ordered list, we have to sort the list here. 892*5c51f124SMoriah Waterland */ 893*5c51f124SMoriah Waterland qsort(fs_tab, fs_tab_used, 894*5c51f124SMoriah Waterland sizeof (struct fstable *), fs_tab_ent_comp); 895*5c51f124SMoriah Waterland 896*5c51f124SMoriah Waterland /* 897*5c51f124SMoriah Waterland * Here's where the vfstab for the target is. If we can get 898*5c51f124SMoriah Waterland * to it, we'll scan it for what the client will see as 899*5c51f124SMoriah Waterland * remote filesystems, otherwise, we'll just skip this. 900*5c51f124SMoriah Waterland */ 901*5c51f124SMoriah Waterland if (vfstab_file) { 902*5c51f124SMoriah Waterland (void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s", 903*5c51f124SMoriah Waterland vfstab_file); 904*5c51f124SMoriah Waterland } else { 905*5c51f124SMoriah Waterland (void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s%s", 906*5c51f124SMoriah Waterland install_root, VFSTAB); 907*5c51f124SMoriah Waterland } 908*5c51f124SMoriah Waterland 909*5c51f124SMoriah Waterland if (access(VFS_TABLE, R_OK) == 0) { 910*5c51f124SMoriah Waterland char *link_name; 911*5c51f124SMoriah Waterland 912*5c51f124SMoriah Waterland /* 913*5c51f124SMoriah Waterland * Open the vfs table for the target host. 914*5c51f124SMoriah Waterland */ 915*5c51f124SMoriah Waterland if ((pp = setmntent(VFS_TABLE, "r")) == NULL) { 916*5c51f124SMoriah Waterland progerr(ERR_NOTABLE, "vfs", VFS_TABLE, 917*5c51f124SMoriah Waterland strerror(errno)); 918*5c51f124SMoriah Waterland return (1); 919*5c51f124SMoriah Waterland } 920*5c51f124SMoriah Waterland 921*5c51f124SMoriah Waterland /* Do this for each entry in the vfstab. */ 922*5c51f124SMoriah Waterland while (!getvfsent(pp, vfs)) { 923*5c51f124SMoriah Waterland char client_mountp[PATH_MAX]; 924*5c51f124SMoriah Waterland int mnt_stat; 925*5c51f124SMoriah Waterland 926*5c51f124SMoriah Waterland /* 927*5c51f124SMoriah Waterland * We put it into the fs table if it's 928*5c51f124SMoriah Waterland * remote mounted (even from this server) or 929*5c51f124SMoriah Waterland * loopback mounted from the client's point 930*5c51f124SMoriah Waterland * of view. 931*5c51f124SMoriah Waterland */ 932*5c51f124SMoriah Waterland if (!(is_remote = 933*5c51f124SMoriah Waterland is_remote_src(vfs->vfs_special)) && 934*5c51f124SMoriah Waterland strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) != 935*5c51f124SMoriah Waterland 0) 936*5c51f124SMoriah Waterland continue; /* not interesting */ 937*5c51f124SMoriah Waterland 938*5c51f124SMoriah Waterland /* 939*5c51f124SMoriah Waterland * Construct client_mountp by prepending the 940*5c51f124SMoriah Waterland * install_root to the 'mount point' name. 941*5c51f124SMoriah Waterland */ 942*5c51f124SMoriah Waterland if (strcmp(vfs->vfs_mountp, "/") == 0) { 943*5c51f124SMoriah Waterland (void) strcpy(client_mountp, 944*5c51f124SMoriah Waterland install_root); 945*5c51f124SMoriah Waterland } else { 946*5c51f124SMoriah Waterland (void) snprintf(client_mountp, 947*5c51f124SMoriah Waterland sizeof (client_mountp), "%s%s", 948*5c51f124SMoriah Waterland install_root, vfs->vfs_mountp); 949*5c51f124SMoriah Waterland } 950*5c51f124SMoriah Waterland 951*5c51f124SMoriah Waterland /* 952*5c51f124SMoriah Waterland * We also skip the entry if the vfs_special 953*5c51f124SMoriah Waterland * path and the client_path are the same. 954*5c51f124SMoriah Waterland * There's no need to mount it, it's just a 955*5c51f124SMoriah Waterland * cachefs optimization that mounts a 956*5c51f124SMoriah Waterland * directory over itself from this server. 957*5c51f124SMoriah Waterland */ 958*5c51f124SMoriah Waterland if ((is_remote == SELF_SERVE) && 959*5c51f124SMoriah Waterland strcmp(path_part(vfs->vfs_special), 960*5c51f124SMoriah Waterland client_mountp) == 0) 961*5c51f124SMoriah Waterland continue; 962*5c51f124SMoriah Waterland 963*5c51f124SMoriah Waterland /* Determine if this is already mounted. */ 964*5c51f124SMoriah Waterland link_name = strdup(path_part(vfs->vfs_special)); 965*5c51f124SMoriah Waterland mnt_stat = already_mounted(vfs, 966*5c51f124SMoriah Waterland (is_remote != REAL_REMOTE), client_mountp, 967*5c51f124SMoriah Waterland link_name); 968*5c51f124SMoriah Waterland 969*5c51f124SMoriah Waterland if (mnt_stat == MNT_EXACT) { 970*5c51f124SMoriah Waterland mod_existing(vfs, match_mount, 971*5c51f124SMoriah Waterland is_remote); 972*5c51f124SMoriah Waterland } else { /* MNT_NOT */ 973*5c51f124SMoriah Waterland if (construct_vfs(vfs, client_mountp, 974*5c51f124SMoriah Waterland link_name, is_remote, mnt_stat)) 975*5c51f124SMoriah Waterland return (1); 976*5c51f124SMoriah Waterland } 977*5c51f124SMoriah Waterland } 978*5c51f124SMoriah Waterland (void) endmntent(pp); 979*5c51f124SMoriah Waterland } /* end of if(access()) */ 980*5c51f124SMoriah Waterland } /* end of if(install_root) */ 981*5c51f124SMoriah Waterland 982*5c51f124SMoriah Waterland /* This next one may look stupid, but it can really happen. */ 983*5c51f124SMoriah Waterland if (fs_tab_used <= 0) { 984*5c51f124SMoriah Waterland progerr(ERR_MNT_NOMOUNTS); 985*5c51f124SMoriah Waterland return (1); 986*5c51f124SMoriah Waterland } 987*5c51f124SMoriah Waterland 988*5c51f124SMoriah Waterland /* 989*5c51f124SMoriah Waterland * Now that we have the complete list of mounted (or virtually 990*5c51f124SMoriah Waterland * mounted) filesystems, we sort the mountpoints in reverse order 991*5c51f124SMoriah Waterland * based on the length of the 'mount point' name. 992*5c51f124SMoriah Waterland */ 993*5c51f124SMoriah Waterland qsort(fs_tab, fs_tab_used, sizeof (struct fstable *), fs_tab_ent_comp); 994*5c51f124SMoriah Waterland if (strcmp(fs_tab[fs_tab_used-1]->name, rn) != 0) { 995*5c51f124SMoriah Waterland progerr(ERR_MNT_NOROOT, fs_tab[fs_tab_used-1]->name, rn, errno, 996*5c51f124SMoriah Waterland strerror(errno)); 997*5c51f124SMoriah Waterland return (1); 998*5c51f124SMoriah Waterland } else { 999*5c51f124SMoriah Waterland return (0); 1000*5c51f124SMoriah Waterland } 1001*5c51f124SMoriah Waterland } 1002*5c51f124SMoriah Waterland 1003*5c51f124SMoriah Waterland /* 1004*5c51f124SMoriah Waterland * This function supports dryrun mode by allowing the filesystem table to be 1005*5c51f124SMoriah Waterland * directly loaded from the continuation file. 1006*5c51f124SMoriah Waterland */ 1007*5c51f124SMoriah Waterland int 1008*5c51f124SMoriah Waterland load_fsentry(struct fstable *fs_entry, char *name, char *fstype, 1009*5c51f124SMoriah Waterland char *remote_name) 1010*5c51f124SMoriah Waterland { 1011*5c51f124SMoriah Waterland struct fstable *nfte; 1012*5c51f124SMoriah Waterland 1013*5c51f124SMoriah Waterland if ((nfte = fs_tab_init(name, fstype)) == NULL) 1014*5c51f124SMoriah Waterland return (1); 1015*5c51f124SMoriah Waterland 1016*5c51f124SMoriah Waterland /* Grab the name and fstype from the new structure. */ 1017*5c51f124SMoriah Waterland fs_entry->name = nfte->name; 1018*5c51f124SMoriah Waterland fs_entry->fstype = nfte->fstype; 1019*5c51f124SMoriah Waterland 1020*5c51f124SMoriah Waterland /* Copy the basic structure into place. */ 1021*5c51f124SMoriah Waterland (void) memcpy(nfte, fs_entry, sizeof (struct fstable)); 1022*5c51f124SMoriah Waterland 1023*5c51f124SMoriah Waterland /* 1024*5c51f124SMoriah Waterland * Allocate space for the 'special' name. 1025*5c51f124SMoriah Waterland */ 1026*5c51f124SMoriah Waterland if ((nfte->remote_name = malloc(strlen(remote_name)+1)) == NULL) { 1027*5c51f124SMoriah Waterland progerr(ERR_MALLOC, "remote_name", errno, strerror(errno)); 1028*5c51f124SMoriah Waterland return (1); 1029*5c51f124SMoriah Waterland } 1030*5c51f124SMoriah Waterland 1031*5c51f124SMoriah Waterland (void) strcpy(nfte->remote_name, remote_name); 1032*5c51f124SMoriah Waterland 1033*5c51f124SMoriah Waterland return (0); 1034*5c51f124SMoriah Waterland } 1035*5c51f124SMoriah Waterland 1036*5c51f124SMoriah Waterland /* 1037*5c51f124SMoriah Waterland * Given a path, return the table index of the filesystem the file apparently 1038*5c51f124SMoriah Waterland * resides on. This doesn't put any time into resolving filesystems that 1039*5c51f124SMoriah Waterland * refer to other filesystems. It just returns the entry containing this 1040*5c51f124SMoriah Waterland * path. 1041*5c51f124SMoriah Waterland */ 1042*5c51f124SMoriah Waterland short 1043*5c51f124SMoriah Waterland fsys(char *path) 1044*5c51f124SMoriah Waterland { 1045*5c51f124SMoriah Waterland register int i; 1046*5c51f124SMoriah Waterland char real_path[PATH_MAX]; 1047*5c51f124SMoriah Waterland char *path2use = NULL; 1048*5c51f124SMoriah Waterland char *cp = NULL; 1049*5c51f124SMoriah Waterland int pathlen; 1050*5c51f124SMoriah Waterland 1051*5c51f124SMoriah Waterland path2use = path; 1052*5c51f124SMoriah Waterland 1053*5c51f124SMoriah Waterland real_path[0] = '\0'; 1054*5c51f124SMoriah Waterland 1055*5c51f124SMoriah Waterland (void) realpath(path, real_path); 1056*5c51f124SMoriah Waterland 1057*5c51f124SMoriah Waterland if (real_path[0]) { 1058*5c51f124SMoriah Waterland cp = strstr(path, real_path); 1059*5c51f124SMoriah Waterland if (cp != path || cp == NULL) 1060*5c51f124SMoriah Waterland path2use = real_path; 1061*5c51f124SMoriah Waterland } 1062*5c51f124SMoriah Waterland 1063*5c51f124SMoriah Waterland pathlen = strlen(path2use); 1064*5c51f124SMoriah Waterland 1065*5c51f124SMoriah Waterland /* 1066*5c51f124SMoriah Waterland * The following algorithm scans the list of attached file systems 1067*5c51f124SMoriah Waterland * for the one containing path. At this point the file names in 1068*5c51f124SMoriah Waterland * fs_tab[] are sorted by decreasing length to facilitate the scan. 1069*5c51f124SMoriah Waterland * The first for() scans past all the file system names too short to 1070*5c51f124SMoriah Waterland * contain path. The second for() does the actual string comparison. 1071*5c51f124SMoriah Waterland * It tests first to assure that the comparison is against a complete 1072*5c51f124SMoriah Waterland * token by assuring that the end of the filesystem name aligns with 1073*5c51f124SMoriah Waterland * the end of a token in path2use (ie: '/' or NULL) then it does a 1074*5c51f124SMoriah Waterland * string compare. -- JST 1075*5c51f124SMoriah Waterland */ 1076*5c51f124SMoriah Waterland 1077*5c51f124SMoriah Waterland if (fs_tab_used == 0) { 1078*5c51f124SMoriah Waterland return (-1); 1079*5c51f124SMoriah Waterland } 1080*5c51f124SMoriah Waterland 1081*5c51f124SMoriah Waterland for (i = 0; i < fs_tab_used; i++) 1082*5c51f124SMoriah Waterland if (fs_tab[i] == NULL) 1083*5c51f124SMoriah Waterland continue; 1084*5c51f124SMoriah Waterland else if (fs_tab[i]->namlen <= pathlen) 1085*5c51f124SMoriah Waterland break; 1086*5c51f124SMoriah Waterland for (; i < fs_tab_used; i++) { 1087*5c51f124SMoriah Waterland int fs_namelen; 1088*5c51f124SMoriah Waterland char term_char; 1089*5c51f124SMoriah Waterland 1090*5c51f124SMoriah Waterland if (fs_tab[i] == NULL) 1091*5c51f124SMoriah Waterland continue; 1092*5c51f124SMoriah Waterland 1093*5c51f124SMoriah Waterland fs_namelen = fs_tab[i]->namlen; 1094*5c51f124SMoriah Waterland term_char = path2use[fs_namelen]; 1095*5c51f124SMoriah Waterland 1096*5c51f124SMoriah Waterland /* 1097*5c51f124SMoriah Waterland * If we're putting the file "/a/kernel" into the filesystem 1098*5c51f124SMoriah Waterland * "/a", then fs_namelen == 2 and term_char == '/'. If, we're 1099*5c51f124SMoriah Waterland * putting "/etc/termcap" into "/", fs_namelen == 1 and 1100*5c51f124SMoriah Waterland * term_char (unfortunately) == 'e'. In the case of 1101*5c51f124SMoriah Waterland * fs_namelen == 1, we check to make sure the filesystem is 1102*5c51f124SMoriah Waterland * "/" and if it is, we have a guaranteed fit, otherwise we 1103*5c51f124SMoriah Waterland * do the string compare. -- JST 1104*5c51f124SMoriah Waterland */ 1105*5c51f124SMoriah Waterland if ((fs_namelen == 1 && *(fs_tab[i]->name) == '/') || 1106*5c51f124SMoriah Waterland ((term_char == '/' || term_char == NULL) && 1107*5c51f124SMoriah Waterland strncmp(fs_tab[i]->name, path2use, fs_namelen) == 0)) 1108*5c51f124SMoriah Waterland return (i); 1109*5c51f124SMoriah Waterland } 1110*5c51f124SMoriah Waterland 1111*5c51f124SMoriah Waterland /* 1112*5c51f124SMoriah Waterland * It only gets here if the root filesystem is fundamentally corrupt. 1113*5c51f124SMoriah Waterland * (This can happen!) 1114*5c51f124SMoriah Waterland */ 1115*5c51f124SMoriah Waterland progerr(ERR_FSYS_FELLOUT, path2use); 1116*5c51f124SMoriah Waterland 1117*5c51f124SMoriah Waterland return (-1); 1118*5c51f124SMoriah Waterland } 1119*5c51f124SMoriah Waterland 1120*5c51f124SMoriah Waterland /* 1121*5c51f124SMoriah Waterland * This function returns the entry in the fs_tab[] corresponding to the 1122*5c51f124SMoriah Waterland * actual filesystem of record. It won't return a loopback filesystem entry, 1123*5c51f124SMoriah Waterland * it will return the filesystem that the loopback filesystem is mounted 1124*5c51f124SMoriah Waterland * over. 1125*5c51f124SMoriah Waterland */ 1126*5c51f124SMoriah Waterland short 1127*5c51f124SMoriah Waterland resolved_fsys(char *path) 1128*5c51f124SMoriah Waterland { 1129*5c51f124SMoriah Waterland int i = -1; 1130*5c51f124SMoriah Waterland char path2use[PATH_MAX]; 1131*5c51f124SMoriah Waterland 1132*5c51f124SMoriah Waterland (void) strcpy(path2use, path); 1133*5c51f124SMoriah Waterland 1134*5c51f124SMoriah Waterland /* If this isn't a "real" filesystem, resolve the map. */ 1135*5c51f124SMoriah Waterland do { 1136*5c51f124SMoriah Waterland (void) strcpy(path2use, server_map(path2use, i)); 1137*5c51f124SMoriah Waterland i = fsys(path2use); 1138*5c51f124SMoriah Waterland } while (fs_tab[i]->srvr_map); 1139*5c51f124SMoriah Waterland 1140*5c51f124SMoriah Waterland return (i); 1141*5c51f124SMoriah Waterland } 1142*5c51f124SMoriah Waterland 1143*5c51f124SMoriah Waterland /* 1144*5c51f124SMoriah Waterland * This function returns the srvr_map status based upon the fs_tab entry 1145*5c51f124SMoriah Waterland * number. This tells us if the server path constructed from the package 1146*5c51f124SMoriah Waterland * install root is really the target filesystem. 1147*5c51f124SMoriah Waterland */ 1148*5c51f124SMoriah Waterland int 1149*5c51f124SMoriah Waterland use_srvr_map_n(short n) 1150*5c51f124SMoriah Waterland { 1151*5c51f124SMoriah Waterland return ((int)fs_tab[n]->srvr_map); 1152*5c51f124SMoriah Waterland } 1153*5c51f124SMoriah Waterland 1154*5c51f124SMoriah Waterland /* 1155*5c51f124SMoriah Waterland * This function returns the mount status based upon the fs_tab entry 1156*5c51f124SMoriah Waterland * number. This tells us if there is any hope of gaining access 1157*5c51f124SMoriah Waterland * to this file system. 1158*5c51f124SMoriah Waterland */ 1159*5c51f124SMoriah Waterland int 1160*5c51f124SMoriah Waterland is_mounted_n(short n) 1161*5c51f124SMoriah Waterland { 1162*5c51f124SMoriah Waterland return ((int)fs_tab[n]->mounted); 1163*5c51f124SMoriah Waterland } 1164*5c51f124SMoriah Waterland 1165*5c51f124SMoriah Waterland /* 1166*5c51f124SMoriah Waterland * is_fs_writeable_n - given an fstab index, return 1 1167*5c51f124SMoriah Waterland * if it's writeable, 0 if read-only. 1168*5c51f124SMoriah Waterland */ 1169*5c51f124SMoriah Waterland int 1170*5c51f124SMoriah Waterland is_fs_writeable_n(short n) 1171*5c51f124SMoriah Waterland { 1172*5c51f124SMoriah Waterland /* 1173*5c51f124SMoriah Waterland * If the write access permissions haven't been confirmed, do that 1174*5c51f124SMoriah Waterland * now. Note that the only reason we need to do the special check is 1175*5c51f124SMoriah Waterland * in the case of an NFS mount (remote) because we can't determine if 1176*5c51f124SMoriah Waterland * root has access in any other way. 1177*5c51f124SMoriah Waterland */ 1178*5c51f124SMoriah Waterland if (fs_tab[n]->remote && fs_tab[n]->mounted && 1179*5c51f124SMoriah Waterland !fs_tab[n]->write_tested) { 1180*5c51f124SMoriah Waterland if (fs_tab[n]->writeable && !really_write(fs_tab[n]->name)) 1181*5c51f124SMoriah Waterland fs_tab[n]->writeable = 0; /* not really */ 1182*5c51f124SMoriah Waterland 1183*5c51f124SMoriah Waterland fs_tab[n]->write_tested = 1; /* confirmed */ 1184*5c51f124SMoriah Waterland } 1185*5c51f124SMoriah Waterland 1186*5c51f124SMoriah Waterland return ((int)fs_tab[n]->writeable); 1187*5c51f124SMoriah Waterland } 1188*5c51f124SMoriah Waterland 1189*5c51f124SMoriah Waterland /* 1190*5c51f124SMoriah Waterland * is_remote_fs_n - given an fstab index, return 1 1191*5c51f124SMoriah Waterland * if it's a remote filesystem, 0 if local. 1192*5c51f124SMoriah Waterland * 1193*5c51f124SMoriah Waterland * Note: Upon entry, a valid fsys() is required. 1194*5c51f124SMoriah Waterland */ 1195*5c51f124SMoriah Waterland int 1196*5c51f124SMoriah Waterland is_remote_fs_n(short n) 1197*5c51f124SMoriah Waterland { 1198*5c51f124SMoriah Waterland return ((int)fs_tab[n]->remote); 1199*5c51f124SMoriah Waterland } 1200*5c51f124SMoriah Waterland 1201*5c51f124SMoriah Waterland /* index-driven is_served() */ 1202*5c51f124SMoriah Waterland int 1203*5c51f124SMoriah Waterland is_served_n(short n) 1204*5c51f124SMoriah Waterland { 1205*5c51f124SMoriah Waterland return ((int)fs_tab[n]->served); 1206*5c51f124SMoriah Waterland } 1207*5c51f124SMoriah Waterland 1208*5c51f124SMoriah Waterland /* 1209*5c51f124SMoriah Waterland * This returns the number of blocks available on the indicated filesystem. 1210*5c51f124SMoriah Waterland * 1211*5c51f124SMoriah Waterland * Note: Upon entry, a valid fsys() is required. 1212*5c51f124SMoriah Waterland */ 1213*5c51f124SMoriah Waterland fsblkcnt_t 1214*5c51f124SMoriah Waterland get_blk_free_n(short n) 1215*5c51f124SMoriah Waterland { 1216*5c51f124SMoriah Waterland return (fs_tab[n]->bfree); 1217*5c51f124SMoriah Waterland } 1218*5c51f124SMoriah Waterland 1219*5c51f124SMoriah Waterland /* 1220*5c51f124SMoriah Waterland * This returns the number of blocks being used on the indicated filesystem. 1221*5c51f124SMoriah Waterland * 1222*5c51f124SMoriah Waterland * Note: Upon entry, a valid fsys() is required. 1223*5c51f124SMoriah Waterland */ 1224*5c51f124SMoriah Waterland fsblkcnt_t 1225*5c51f124SMoriah Waterland get_blk_used_n(short n) 1226*5c51f124SMoriah Waterland { 1227*5c51f124SMoriah Waterland return (fs_tab[n]->bused); 1228*5c51f124SMoriah Waterland } 1229*5c51f124SMoriah Waterland 1230*5c51f124SMoriah Waterland /* 1231*5c51f124SMoriah Waterland * This returns the number of inodes available on the indicated filesystem. 1232*5c51f124SMoriah Waterland * 1233*5c51f124SMoriah Waterland * Note: Upon entry, a valid fsys() is required. 1234*5c51f124SMoriah Waterland */ 1235*5c51f124SMoriah Waterland fsblkcnt_t 1236*5c51f124SMoriah Waterland get_inode_free_n(short n) 1237*5c51f124SMoriah Waterland { 1238*5c51f124SMoriah Waterland return (fs_tab[n]->ffree); 1239*5c51f124SMoriah Waterland } 1240*5c51f124SMoriah Waterland 1241*5c51f124SMoriah Waterland /* 1242*5c51f124SMoriah Waterland * This returns the number of inodes being used on the indicated filesystem. 1243*5c51f124SMoriah Waterland * 1244*5c51f124SMoriah Waterland * Note: Upon entry, a valid fsys() is required. 1245*5c51f124SMoriah Waterland */ 1246*5c51f124SMoriah Waterland fsblkcnt_t 1247*5c51f124SMoriah Waterland get_inode_used_n(short n) 1248*5c51f124SMoriah Waterland { 1249*5c51f124SMoriah Waterland return (fs_tab[n]->fused); 1250*5c51f124SMoriah Waterland } 1251*5c51f124SMoriah Waterland 1252*5c51f124SMoriah Waterland /* 1253*5c51f124SMoriah Waterland * Sets the number of blocks being used on the indicated filesystem. 1254*5c51f124SMoriah Waterland * 1255*5c51f124SMoriah Waterland * Note: Upon entry, a valid fsys() is required. 1256*5c51f124SMoriah Waterland */ 1257*5c51f124SMoriah Waterland void 1258*5c51f124SMoriah Waterland set_blk_used_n(short n, fsblkcnt_t value) 1259*5c51f124SMoriah Waterland { 1260*5c51f124SMoriah Waterland fs_tab[n]->bused = value; 1261*5c51f124SMoriah Waterland } 1262*5c51f124SMoriah Waterland 1263*5c51f124SMoriah Waterland /* Get the filesystem block size. */ 1264*5c51f124SMoriah Waterland fsblkcnt_t 1265*5c51f124SMoriah Waterland get_blk_size_n(short n) 1266*5c51f124SMoriah Waterland { 1267*5c51f124SMoriah Waterland return (fs_tab[n]->bsize); 1268*5c51f124SMoriah Waterland } 1269*5c51f124SMoriah Waterland 1270*5c51f124SMoriah Waterland /* Get the filesystem fragment size. */ 1271*5c51f124SMoriah Waterland fsblkcnt_t 1272*5c51f124SMoriah Waterland get_frag_size_n(short n) 1273*5c51f124SMoriah Waterland { 1274*5c51f124SMoriah Waterland return (fs_tab[n]->bsize); 1275*5c51f124SMoriah Waterland } 1276*5c51f124SMoriah Waterland 1277*5c51f124SMoriah Waterland /* 1278*5c51f124SMoriah Waterland * This returns the name of the indicated filesystem. 1279*5c51f124SMoriah Waterland */ 1280*5c51f124SMoriah Waterland char * 1281*5c51f124SMoriah Waterland get_fs_name_n(short n) 1282*5c51f124SMoriah Waterland { 1283*5c51f124SMoriah Waterland if (fs_tab_used == 0) { 1284*5c51f124SMoriah Waterland return (NULL); 1285*5c51f124SMoriah Waterland } else if (n >= fs_tab_used) { 1286*5c51f124SMoriah Waterland return (NULL); 1287*5c51f124SMoriah Waterland } else { 1288*5c51f124SMoriah Waterland return (fs_tab[n]->name); 1289*5c51f124SMoriah Waterland } 1290*5c51f124SMoriah Waterland } 1291*5c51f124SMoriah Waterland 1292*5c51f124SMoriah Waterland /* 1293*5c51f124SMoriah Waterland * This returns the remote name of the indicated filesystem. 1294*5c51f124SMoriah Waterland * 1295*5c51f124SMoriah Waterland * Note: Upon entry, a valid fsys() is required. 1296*5c51f124SMoriah Waterland */ 1297*5c51f124SMoriah Waterland char * 1298*5c51f124SMoriah Waterland get_source_name_n(short n) 1299*5c51f124SMoriah Waterland { 1300*5c51f124SMoriah Waterland return (fs_tab[n]->remote_name); 1301*5c51f124SMoriah Waterland } 1302*5c51f124SMoriah Waterland 1303*5c51f124SMoriah Waterland /* 1304*5c51f124SMoriah Waterland * This function returns the srvr_map status based upon the path. 1305*5c51f124SMoriah Waterland */ 1306*5c51f124SMoriah Waterland int 1307*5c51f124SMoriah Waterland use_srvr_map(char *path, short *fsys_value) 1308*5c51f124SMoriah Waterland { 1309*5c51f124SMoriah Waterland if (*fsys_value == BADFSYS) 1310*5c51f124SMoriah Waterland *fsys_value = fsys(path); 1311*5c51f124SMoriah Waterland 1312*5c51f124SMoriah Waterland return (use_srvr_map_n(*fsys_value)); 1313*5c51f124SMoriah Waterland } 1314*5c51f124SMoriah Waterland 1315*5c51f124SMoriah Waterland /* 1316*5c51f124SMoriah Waterland * This function returns the mount status based upon the path. 1317*5c51f124SMoriah Waterland */ 1318*5c51f124SMoriah Waterland int 1319*5c51f124SMoriah Waterland is_mounted(char *path, short *fsys_value) 1320*5c51f124SMoriah Waterland { 1321*5c51f124SMoriah Waterland if (*fsys_value == BADFSYS) 1322*5c51f124SMoriah Waterland *fsys_value = fsys(path); 1323*5c51f124SMoriah Waterland 1324*5c51f124SMoriah Waterland return (is_mounted_n(*fsys_value)); 1325*5c51f124SMoriah Waterland } 1326*5c51f124SMoriah Waterland 1327*5c51f124SMoriah Waterland /* 1328*5c51f124SMoriah Waterland * is_fs_writeable - given a cfent entry, return 1 1329*5c51f124SMoriah Waterland * if it's writeable, 0 if read-only. 1330*5c51f124SMoriah Waterland * 1331*5c51f124SMoriah Waterland * Note: Upon exit, a valid fsys() is guaranteed. This is 1332*5c51f124SMoriah Waterland * an interface requirement. 1333*5c51f124SMoriah Waterland */ 1334*5c51f124SMoriah Waterland int 1335*5c51f124SMoriah Waterland is_fs_writeable(char *path, short *fsys_value) 1336*5c51f124SMoriah Waterland { 1337*5c51f124SMoriah Waterland if (*fsys_value == BADFSYS) 1338*5c51f124SMoriah Waterland *fsys_value = fsys(path); 1339*5c51f124SMoriah Waterland 1340*5c51f124SMoriah Waterland return (is_fs_writeable_n(*fsys_value)); 1341*5c51f124SMoriah Waterland } 1342*5c51f124SMoriah Waterland 1343*5c51f124SMoriah Waterland /* 1344*5c51f124SMoriah Waterland * is_remote_fs - given a cfent entry, return 1 1345*5c51f124SMoriah Waterland * if it's a remote filesystem, 0 if local. 1346*5c51f124SMoriah Waterland * 1347*5c51f124SMoriah Waterland * Also Note: Upon exit, a valid fsys() is guaranteed. This is 1348*5c51f124SMoriah Waterland * an interface requirement. 1349*5c51f124SMoriah Waterland */ 1350*5c51f124SMoriah Waterland int 1351*5c51f124SMoriah Waterland is_remote_fs(char *path, short *fsys_value) 1352*5c51f124SMoriah Waterland { 1353*5c51f124SMoriah Waterland if (*fsys_value == BADFSYS) 1354*5c51f124SMoriah Waterland *fsys_value = fsys(path); 1355*5c51f124SMoriah Waterland 1356*5c51f124SMoriah Waterland return (is_remote_fs_n(*fsys_value)); 1357*5c51f124SMoriah Waterland } 1358*5c51f124SMoriah Waterland 1359*5c51f124SMoriah Waterland /* 1360*5c51f124SMoriah Waterland * This function returns the served status of the filesystem. Served means a 1361*5c51f124SMoriah Waterland * client is getting this file from a server and it is not writeable by the 1362*5c51f124SMoriah Waterland * client. It has nothing to do with whether or not this particular operation 1363*5c51f124SMoriah Waterland * (eg: pkgadd or pkgrm) will be writing to it. 1364*5c51f124SMoriah Waterland */ 1365*5c51f124SMoriah Waterland int 1366*5c51f124SMoriah Waterland is_served(char *path, short *fsys_value) 1367*5c51f124SMoriah Waterland { 1368*5c51f124SMoriah Waterland if (*fsys_value == BADFSYS) 1369*5c51f124SMoriah Waterland *fsys_value = fsys(path); 1370*5c51f124SMoriah Waterland 1371*5c51f124SMoriah Waterland return (is_served_n(*fsys_value)); 1372*5c51f124SMoriah Waterland } 1373*5c51f124SMoriah Waterland 1374*5c51f124SMoriah Waterland /* 1375*5c51f124SMoriah Waterland * get_remote_path - given a filesystem table index, return the 1376*5c51f124SMoriah Waterland * path of the filesystem on the remote system. Otherwise, 1377*5c51f124SMoriah Waterland * return NULL if it's a local filesystem. 1378*5c51f124SMoriah Waterland */ 1379*5c51f124SMoriah Waterland char * 1380*5c51f124SMoriah Waterland get_remote_path(short n) 1381*5c51f124SMoriah Waterland { 1382*5c51f124SMoriah Waterland char *p; 1383*5c51f124SMoriah Waterland 1384*5c51f124SMoriah Waterland if (!is_remote_fs_n(n)) 1385*5c51f124SMoriah Waterland return (NULL); /* local */ 1386*5c51f124SMoriah Waterland p = strchr(fs_tab[n]->remote_name, ':'); 1387*5c51f124SMoriah Waterland if (!p) 1388*5c51f124SMoriah Waterland p = fs_tab[n]->remote_name; /* Loopback */ 1389*5c51f124SMoriah Waterland else 1390*5c51f124SMoriah Waterland p++; /* remote */ 1391*5c51f124SMoriah Waterland return (p); 1392*5c51f124SMoriah Waterland } 1393*5c51f124SMoriah Waterland 1394*5c51f124SMoriah Waterland /* 1395*5c51f124SMoriah Waterland * get_mount_point - given a filesystem table index, return the 1396*5c51f124SMoriah Waterland * path of the mount point. Otherwise, 1397*5c51f124SMoriah Waterland * return NULL if it's a local filesystem. 1398*5c51f124SMoriah Waterland */ 1399*5c51f124SMoriah Waterland char * 1400*5c51f124SMoriah Waterland get_mount_point(short n) 1401*5c51f124SMoriah Waterland { 1402*5c51f124SMoriah Waterland if (!is_remote_fs_n(n)) 1403*5c51f124SMoriah Waterland return (NULL); /* local */ 1404*5c51f124SMoriah Waterland return (fs_tab[n]->name); 1405*5c51f124SMoriah Waterland } 1406*5c51f124SMoriah Waterland 1407*5c51f124SMoriah Waterland struct fstable * 1408*5c51f124SMoriah Waterland get_fs_entry(short n) 1409*5c51f124SMoriah Waterland { 1410*5c51f124SMoriah Waterland if (fs_tab_used == 0) { 1411*5c51f124SMoriah Waterland return (NULL); 1412*5c51f124SMoriah Waterland } else if (n >= fs_tab_used) { 1413*5c51f124SMoriah Waterland return (NULL); 1414*5c51f124SMoriah Waterland } else { 1415*5c51f124SMoriah Waterland return (fs_tab[n]); 1416*5c51f124SMoriah Waterland } 1417*5c51f124SMoriah Waterland } 1418