1*eda14cbcSMatt Macy /* 2*eda14cbcSMatt Macy * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3*eda14cbcSMatt Macy * All rights reserved. 4*eda14cbcSMatt Macy * 5*eda14cbcSMatt Macy * Redistribution and use in source and binary forms, with or without 6*eda14cbcSMatt Macy * modification, are permitted provided that the following conditions 7*eda14cbcSMatt Macy * are met: 8*eda14cbcSMatt Macy * 1. Redistributions of source code must retain the above copyright 9*eda14cbcSMatt Macy * notice, this list of conditions and the following disclaimer. 10*eda14cbcSMatt Macy * 2. Redistributions in binary form must reproduce the above copyright 11*eda14cbcSMatt Macy * notice, this list of conditions and the following disclaimer in the 12*eda14cbcSMatt Macy * documentation and/or other materials provided with the distribution. 13*eda14cbcSMatt Macy * 14*eda14cbcSMatt Macy * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15*eda14cbcSMatt Macy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*eda14cbcSMatt Macy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*eda14cbcSMatt Macy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18*eda14cbcSMatt Macy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*eda14cbcSMatt Macy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*eda14cbcSMatt Macy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*eda14cbcSMatt Macy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*eda14cbcSMatt Macy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*eda14cbcSMatt Macy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*eda14cbcSMatt Macy * SUCH DAMAGE. 25*eda14cbcSMatt Macy * 26*eda14cbcSMatt Macy * Copyright (c) 2020 by Delphix. All rights reserved. 27*eda14cbcSMatt Macy */ 28*eda14cbcSMatt Macy 29*eda14cbcSMatt Macy #include <sys/cdefs.h> 30*eda14cbcSMatt Macy __FBSDID("$FreeBSD$"); 31*eda14cbcSMatt Macy 32*eda14cbcSMatt Macy #include <sys/param.h> 33*eda14cbcSMatt Macy #include <sys/vfs.h> 34*eda14cbcSMatt Macy 35*eda14cbcSMatt Macy #include <assert.h> 36*eda14cbcSMatt Macy #include <errno.h> 37*eda14cbcSMatt Macy #include <fcntl.h> 38*eda14cbcSMatt Macy #include <libutil.h> 39*eda14cbcSMatt Macy #include <signal.h> 40*eda14cbcSMatt Macy #include <stdio.h> 41*eda14cbcSMatt Macy #include <string.h> 42*eda14cbcSMatt Macy #include <unistd.h> 43*eda14cbcSMatt Macy #include <libintl.h> 44*eda14cbcSMatt Macy 45*eda14cbcSMatt Macy #include "libzfs_impl.h" 46*eda14cbcSMatt Macy #include "libshare_impl.h" 47*eda14cbcSMatt Macy #include "nfs.h" 48*eda14cbcSMatt Macy 49*eda14cbcSMatt Macy #define _PATH_MOUNTDPID "/var/run/mountd.pid" 50*eda14cbcSMatt Macy #define FILE_HEADER "# !!! DO NOT EDIT THIS FILE MANUALLY !!!\n\n" 51*eda14cbcSMatt Macy #define OPTSSIZE 1024 52*eda14cbcSMatt Macy #define MAXLINESIZE (PATH_MAX + OPTSSIZE) 53*eda14cbcSMatt Macy #define ZFS_EXPORTS_FILE "/etc/zfs/exports" 54*eda14cbcSMatt Macy #define ZFS_EXPORTS_LOCK ZFS_EXPORTS_FILE".lock" 55*eda14cbcSMatt Macy 56*eda14cbcSMatt Macy static sa_fstype_t *nfs_fstype; 57*eda14cbcSMatt Macy 58*eda14cbcSMatt Macy static int nfs_lock_fd = -1; 59*eda14cbcSMatt Macy 60*eda14cbcSMatt Macy /* 61*eda14cbcSMatt Macy * The nfs_exports_[lock|unlock] is used to guard against conconcurrent 62*eda14cbcSMatt Macy * updates to the exports file. Each protocol is responsible for 63*eda14cbcSMatt Macy * providing the necessary locking to ensure consistency. 64*eda14cbcSMatt Macy */ 65*eda14cbcSMatt Macy static int 66*eda14cbcSMatt Macy nfs_exports_lock(void) 67*eda14cbcSMatt Macy { 68*eda14cbcSMatt Macy nfs_lock_fd = open(ZFS_EXPORTS_LOCK, 69*eda14cbcSMatt Macy O_RDWR | O_CREAT, 0600); 70*eda14cbcSMatt Macy if (nfs_lock_fd == -1) { 71*eda14cbcSMatt Macy fprintf(stderr, "failed to lock %s: %s\n", 72*eda14cbcSMatt Macy ZFS_EXPORTS_LOCK, strerror(errno)); 73*eda14cbcSMatt Macy return (errno); 74*eda14cbcSMatt Macy } 75*eda14cbcSMatt Macy if (flock(nfs_lock_fd, LOCK_EX) != 0) { 76*eda14cbcSMatt Macy fprintf(stderr, "failed to lock %s: %s\n", 77*eda14cbcSMatt Macy ZFS_EXPORTS_LOCK, strerror(errno)); 78*eda14cbcSMatt Macy return (errno); 79*eda14cbcSMatt Macy } 80*eda14cbcSMatt Macy return (0); 81*eda14cbcSMatt Macy } 82*eda14cbcSMatt Macy 83*eda14cbcSMatt Macy static void 84*eda14cbcSMatt Macy nfs_exports_unlock(void) 85*eda14cbcSMatt Macy { 86*eda14cbcSMatt Macy verify(nfs_lock_fd > 0); 87*eda14cbcSMatt Macy 88*eda14cbcSMatt Macy if (flock(nfs_lock_fd, LOCK_UN) != 0) { 89*eda14cbcSMatt Macy fprintf(stderr, "failed to unlock %s: %s\n", 90*eda14cbcSMatt Macy ZFS_EXPORTS_LOCK, strerror(errno)); 91*eda14cbcSMatt Macy } 92*eda14cbcSMatt Macy close(nfs_lock_fd); 93*eda14cbcSMatt Macy nfs_lock_fd = -1; 94*eda14cbcSMatt Macy } 95*eda14cbcSMatt Macy 96*eda14cbcSMatt Macy /* 97*eda14cbcSMatt Macy * Read one line from a file. Skip comments, empty lines and a line with a 98*eda14cbcSMatt Macy * mountpoint specified in the 'skip' argument. 99*eda14cbcSMatt Macy * 100*eda14cbcSMatt Macy * NOTE: This function returns a static buffer and thus is not thread-safe. 101*eda14cbcSMatt Macy */ 102*eda14cbcSMatt Macy static char * 103*eda14cbcSMatt Macy zgetline(FILE *fd, const char *skip) 104*eda14cbcSMatt Macy { 105*eda14cbcSMatt Macy static char line[MAXLINESIZE]; 106*eda14cbcSMatt Macy size_t len, skiplen = 0; 107*eda14cbcSMatt Macy char *s, last; 108*eda14cbcSMatt Macy 109*eda14cbcSMatt Macy if (skip != NULL) 110*eda14cbcSMatt Macy skiplen = strlen(skip); 111*eda14cbcSMatt Macy for (;;) { 112*eda14cbcSMatt Macy s = fgets(line, sizeof (line), fd); 113*eda14cbcSMatt Macy if (s == NULL) 114*eda14cbcSMatt Macy return (NULL); 115*eda14cbcSMatt Macy /* Skip empty lines and comments. */ 116*eda14cbcSMatt Macy if (line[0] == '\n' || line[0] == '#') 117*eda14cbcSMatt Macy continue; 118*eda14cbcSMatt Macy len = strlen(line); 119*eda14cbcSMatt Macy if (line[len - 1] == '\n') 120*eda14cbcSMatt Macy line[len - 1] = '\0'; 121*eda14cbcSMatt Macy last = line[skiplen]; 122*eda14cbcSMatt Macy /* Skip the given mountpoint. */ 123*eda14cbcSMatt Macy if (skip != NULL && strncmp(skip, line, skiplen) == 0 && 124*eda14cbcSMatt Macy (last == '\t' || last == ' ' || last == '\0')) { 125*eda14cbcSMatt Macy continue; 126*eda14cbcSMatt Macy } 127*eda14cbcSMatt Macy break; 128*eda14cbcSMatt Macy } 129*eda14cbcSMatt Macy return (line); 130*eda14cbcSMatt Macy } 131*eda14cbcSMatt Macy 132*eda14cbcSMatt Macy /* 133*eda14cbcSMatt Macy * This function translate options to a format acceptable by exports(5), eg. 134*eda14cbcSMatt Macy * 135*eda14cbcSMatt Macy * -ro -network=192.168.0.0 -mask=255.255.255.0 -maproot=0 \ 136*eda14cbcSMatt Macy * zfs.freebsd.org 69.147.83.54 137*eda14cbcSMatt Macy * 138*eda14cbcSMatt Macy * Accepted input formats: 139*eda14cbcSMatt Macy * 140*eda14cbcSMatt Macy * ro,network=192.168.0.0,mask=255.255.255.0,maproot=0,zfs.freebsd.org 141*eda14cbcSMatt Macy * ro network=192.168.0.0 mask=255.255.255.0 maproot=0 zfs.freebsd.org 142*eda14cbcSMatt Macy * -ro,-network=192.168.0.0,-mask=255.255.255.0,-maproot=0,zfs.freebsd.org 143*eda14cbcSMatt Macy * -ro -network=192.168.0.0 -mask=255.255.255.0 -maproot=0 \ 144*eda14cbcSMatt Macy * zfs.freebsd.org 145*eda14cbcSMatt Macy * 146*eda14cbcSMatt Macy * Recognized keywords: 147*eda14cbcSMatt Macy * 148*eda14cbcSMatt Macy * ro, maproot, mapall, mask, network, sec, alldirs, public, webnfs, 149*eda14cbcSMatt Macy * index, quiet 150*eda14cbcSMatt Macy * 151*eda14cbcSMatt Macy * NOTE: This function returns a static buffer and thus is not thread-safe. 152*eda14cbcSMatt Macy */ 153*eda14cbcSMatt Macy static char * 154*eda14cbcSMatt Macy translate_opts(const char *shareopts) 155*eda14cbcSMatt Macy { 156*eda14cbcSMatt Macy static const char *known_opts[] = { "ro", "maproot", "mapall", "mask", 157*eda14cbcSMatt Macy "network", "sec", "alldirs", "public", "webnfs", "index", "quiet", 158*eda14cbcSMatt Macy NULL }; 159*eda14cbcSMatt Macy static char newopts[OPTSSIZE]; 160*eda14cbcSMatt Macy char oldopts[OPTSSIZE]; 161*eda14cbcSMatt Macy char *o, *s = NULL; 162*eda14cbcSMatt Macy unsigned int i; 163*eda14cbcSMatt Macy size_t len; 164*eda14cbcSMatt Macy 165*eda14cbcSMatt Macy strlcpy(oldopts, shareopts, sizeof (oldopts)); 166*eda14cbcSMatt Macy newopts[0] = '\0'; 167*eda14cbcSMatt Macy s = oldopts; 168*eda14cbcSMatt Macy while ((o = strsep(&s, "-, ")) != NULL) { 169*eda14cbcSMatt Macy if (o[0] == '\0') 170*eda14cbcSMatt Macy continue; 171*eda14cbcSMatt Macy for (i = 0; known_opts[i] != NULL; i++) { 172*eda14cbcSMatt Macy len = strlen(known_opts[i]); 173*eda14cbcSMatt Macy if (strncmp(known_opts[i], o, len) == 0 && 174*eda14cbcSMatt Macy (o[len] == '\0' || o[len] == '=')) { 175*eda14cbcSMatt Macy strlcat(newopts, "-", sizeof (newopts)); 176*eda14cbcSMatt Macy break; 177*eda14cbcSMatt Macy } 178*eda14cbcSMatt Macy } 179*eda14cbcSMatt Macy strlcat(newopts, o, sizeof (newopts)); 180*eda14cbcSMatt Macy strlcat(newopts, " ", sizeof (newopts)); 181*eda14cbcSMatt Macy } 182*eda14cbcSMatt Macy return (newopts); 183*eda14cbcSMatt Macy } 184*eda14cbcSMatt Macy 185*eda14cbcSMatt Macy static char * 186*eda14cbcSMatt Macy nfs_init_tmpfile(void) 187*eda14cbcSMatt Macy { 188*eda14cbcSMatt Macy char *tmpfile = NULL; 189*eda14cbcSMatt Macy 190*eda14cbcSMatt Macy if (asprintf(&tmpfile, "%s%s", ZFS_EXPORTS_FILE, ".XXXXXXXX") == -1) { 191*eda14cbcSMatt Macy fprintf(stderr, "Unable to allocate buffer for temporary " 192*eda14cbcSMatt Macy "file name\n"); 193*eda14cbcSMatt Macy return (NULL); 194*eda14cbcSMatt Macy } 195*eda14cbcSMatt Macy 196*eda14cbcSMatt Macy int fd = mkstemp(tmpfile); 197*eda14cbcSMatt Macy if (fd == -1) { 198*eda14cbcSMatt Macy fprintf(stderr, "Unable to create temporary file: %s", 199*eda14cbcSMatt Macy strerror(errno)); 200*eda14cbcSMatt Macy free(tmpfile); 201*eda14cbcSMatt Macy return (NULL); 202*eda14cbcSMatt Macy } 203*eda14cbcSMatt Macy close(fd); 204*eda14cbcSMatt Macy return (tmpfile); 205*eda14cbcSMatt Macy } 206*eda14cbcSMatt Macy 207*eda14cbcSMatt Macy static int 208*eda14cbcSMatt Macy nfs_fini_tmpfile(char *tmpfile) 209*eda14cbcSMatt Macy { 210*eda14cbcSMatt Macy if (rename(tmpfile, ZFS_EXPORTS_FILE) == -1) { 211*eda14cbcSMatt Macy fprintf(stderr, "Unable to rename %s: %s\n", tmpfile, 212*eda14cbcSMatt Macy strerror(errno)); 213*eda14cbcSMatt Macy unlink(tmpfile); 214*eda14cbcSMatt Macy free(tmpfile); 215*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 216*eda14cbcSMatt Macy } 217*eda14cbcSMatt Macy free(tmpfile); 218*eda14cbcSMatt Macy return (SA_OK); 219*eda14cbcSMatt Macy } 220*eda14cbcSMatt Macy 221*eda14cbcSMatt Macy /* 222*eda14cbcSMatt Macy * This function copies all entries from the exports file to "filename", 223*eda14cbcSMatt Macy * omitting any entries for the specified mountpoint. 224*eda14cbcSMatt Macy */ 225*eda14cbcSMatt Macy static int 226*eda14cbcSMatt Macy nfs_copy_entries(char *filename, const char *mountpoint) 227*eda14cbcSMatt Macy { 228*eda14cbcSMatt Macy int error = SA_OK; 229*eda14cbcSMatt Macy char *line; 230*eda14cbcSMatt Macy 231*eda14cbcSMatt Macy /* 232*eda14cbcSMatt Macy * If the file doesn't exist then there is nothing more 233*eda14cbcSMatt Macy * we need to do. 234*eda14cbcSMatt Macy */ 235*eda14cbcSMatt Macy FILE *oldfp = fopen(ZFS_EXPORTS_FILE, "r"); 236*eda14cbcSMatt Macy if (oldfp == NULL) 237*eda14cbcSMatt Macy return (SA_OK); 238*eda14cbcSMatt Macy 239*eda14cbcSMatt Macy FILE *newfp = fopen(filename, "w+"); 240*eda14cbcSMatt Macy fputs(FILE_HEADER, newfp); 241*eda14cbcSMatt Macy while ((line = zgetline(oldfp, mountpoint)) != NULL) 242*eda14cbcSMatt Macy fprintf(newfp, "%s\n", line); 243*eda14cbcSMatt Macy if (ferror(oldfp) != 0) { 244*eda14cbcSMatt Macy error = ferror(oldfp); 245*eda14cbcSMatt Macy } 246*eda14cbcSMatt Macy if (error == 0 && ferror(newfp) != 0) { 247*eda14cbcSMatt Macy error = ferror(newfp); 248*eda14cbcSMatt Macy } 249*eda14cbcSMatt Macy 250*eda14cbcSMatt Macy if (fclose(newfp) != 0) { 251*eda14cbcSMatt Macy fprintf(stderr, "Unable to close file %s: %s\n", 252*eda14cbcSMatt Macy filename, strerror(errno)); 253*eda14cbcSMatt Macy error = error != 0 ? error : SA_SYSTEM_ERR; 254*eda14cbcSMatt Macy } 255*eda14cbcSMatt Macy fclose(oldfp); 256*eda14cbcSMatt Macy 257*eda14cbcSMatt Macy return (error); 258*eda14cbcSMatt Macy } 259*eda14cbcSMatt Macy 260*eda14cbcSMatt Macy static int 261*eda14cbcSMatt Macy nfs_enable_share(sa_share_impl_t impl_share) 262*eda14cbcSMatt Macy { 263*eda14cbcSMatt Macy char *filename = NULL; 264*eda14cbcSMatt Macy int error; 265*eda14cbcSMatt Macy 266*eda14cbcSMatt Macy if ((filename = nfs_init_tmpfile()) == NULL) 267*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 268*eda14cbcSMatt Macy 269*eda14cbcSMatt Macy error = nfs_exports_lock(); 270*eda14cbcSMatt Macy if (error != 0) { 271*eda14cbcSMatt Macy unlink(filename); 272*eda14cbcSMatt Macy free(filename); 273*eda14cbcSMatt Macy return (error); 274*eda14cbcSMatt Macy } 275*eda14cbcSMatt Macy 276*eda14cbcSMatt Macy error = nfs_copy_entries(filename, impl_share->sa_mountpoint); 277*eda14cbcSMatt Macy if (error != SA_OK) { 278*eda14cbcSMatt Macy unlink(filename); 279*eda14cbcSMatt Macy free(filename); 280*eda14cbcSMatt Macy nfs_exports_unlock(); 281*eda14cbcSMatt Macy return (error); 282*eda14cbcSMatt Macy } 283*eda14cbcSMatt Macy 284*eda14cbcSMatt Macy FILE *fp = fopen(filename, "a+"); 285*eda14cbcSMatt Macy if (fp == NULL) { 286*eda14cbcSMatt Macy fprintf(stderr, "failed to open %s file: %s", filename, 287*eda14cbcSMatt Macy strerror(errno)); 288*eda14cbcSMatt Macy unlink(filename); 289*eda14cbcSMatt Macy free(filename); 290*eda14cbcSMatt Macy nfs_exports_unlock(); 291*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 292*eda14cbcSMatt Macy } 293*eda14cbcSMatt Macy char *shareopts = FSINFO(impl_share, nfs_fstype)->shareopts; 294*eda14cbcSMatt Macy if (strcmp(shareopts, "on") == 0) 295*eda14cbcSMatt Macy shareopts = ""; 296*eda14cbcSMatt Macy 297*eda14cbcSMatt Macy if (fprintf(fp, "%s\t%s\n", impl_share->sa_mountpoint, 298*eda14cbcSMatt Macy translate_opts(shareopts)) < 0) { 299*eda14cbcSMatt Macy fprintf(stderr, "failed to write to %s\n", filename); 300*eda14cbcSMatt Macy fclose(fp); 301*eda14cbcSMatt Macy unlink(filename); 302*eda14cbcSMatt Macy free(filename); 303*eda14cbcSMatt Macy nfs_exports_unlock(); 304*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 305*eda14cbcSMatt Macy } 306*eda14cbcSMatt Macy 307*eda14cbcSMatt Macy if (fclose(fp) != 0) { 308*eda14cbcSMatt Macy fprintf(stderr, "Unable to close file %s: %s\n", 309*eda14cbcSMatt Macy filename, strerror(errno)); 310*eda14cbcSMatt Macy unlink(filename); 311*eda14cbcSMatt Macy free(filename); 312*eda14cbcSMatt Macy nfs_exports_unlock(); 313*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 314*eda14cbcSMatt Macy } 315*eda14cbcSMatt Macy error = nfs_fini_tmpfile(filename); 316*eda14cbcSMatt Macy nfs_exports_unlock(); 317*eda14cbcSMatt Macy return (error); 318*eda14cbcSMatt Macy } 319*eda14cbcSMatt Macy 320*eda14cbcSMatt Macy static int 321*eda14cbcSMatt Macy nfs_disable_share(sa_share_impl_t impl_share) 322*eda14cbcSMatt Macy { 323*eda14cbcSMatt Macy int error; 324*eda14cbcSMatt Macy char *filename = NULL; 325*eda14cbcSMatt Macy 326*eda14cbcSMatt Macy if ((filename = nfs_init_tmpfile()) == NULL) 327*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 328*eda14cbcSMatt Macy 329*eda14cbcSMatt Macy error = nfs_exports_lock(); 330*eda14cbcSMatt Macy if (error != 0) { 331*eda14cbcSMatt Macy unlink(filename); 332*eda14cbcSMatt Macy free(filename); 333*eda14cbcSMatt Macy return (error); 334*eda14cbcSMatt Macy } 335*eda14cbcSMatt Macy 336*eda14cbcSMatt Macy error = nfs_copy_entries(filename, impl_share->sa_mountpoint); 337*eda14cbcSMatt Macy if (error != SA_OK) { 338*eda14cbcSMatt Macy unlink(filename); 339*eda14cbcSMatt Macy free(filename); 340*eda14cbcSMatt Macy nfs_exports_unlock(); 341*eda14cbcSMatt Macy return (error); 342*eda14cbcSMatt Macy } 343*eda14cbcSMatt Macy 344*eda14cbcSMatt Macy error = nfs_fini_tmpfile(filename); 345*eda14cbcSMatt Macy nfs_exports_unlock(); 346*eda14cbcSMatt Macy return (error); 347*eda14cbcSMatt Macy } 348*eda14cbcSMatt Macy 349*eda14cbcSMatt Macy /* 350*eda14cbcSMatt Macy * NOTE: This function returns a static buffer and thus is not thread-safe. 351*eda14cbcSMatt Macy */ 352*eda14cbcSMatt Macy static boolean_t 353*eda14cbcSMatt Macy nfs_is_shared(sa_share_impl_t impl_share) 354*eda14cbcSMatt Macy { 355*eda14cbcSMatt Macy static char line[MAXLINESIZE]; 356*eda14cbcSMatt Macy char *s, last; 357*eda14cbcSMatt Macy size_t len; 358*eda14cbcSMatt Macy char *mntpoint = impl_share->sa_mountpoint; 359*eda14cbcSMatt Macy size_t mntlen = strlen(mntpoint); 360*eda14cbcSMatt Macy 361*eda14cbcSMatt Macy FILE *fp = fopen(ZFS_EXPORTS_FILE, "r"); 362*eda14cbcSMatt Macy if (fp == NULL) 363*eda14cbcSMatt Macy return (B_FALSE); 364*eda14cbcSMatt Macy 365*eda14cbcSMatt Macy for (;;) { 366*eda14cbcSMatt Macy s = fgets(line, sizeof (line), fp); 367*eda14cbcSMatt Macy if (s == NULL) 368*eda14cbcSMatt Macy return (B_FALSE); 369*eda14cbcSMatt Macy /* Skip empty lines and comments. */ 370*eda14cbcSMatt Macy if (line[0] == '\n' || line[0] == '#') 371*eda14cbcSMatt Macy continue; 372*eda14cbcSMatt Macy len = strlen(line); 373*eda14cbcSMatt Macy if (line[len - 1] == '\n') 374*eda14cbcSMatt Macy line[len - 1] = '\0'; 375*eda14cbcSMatt Macy last = line[mntlen]; 376*eda14cbcSMatt Macy /* Skip the given mountpoint. */ 377*eda14cbcSMatt Macy if (strncmp(mntpoint, line, mntlen) == 0 && 378*eda14cbcSMatt Macy (last == '\t' || last == ' ' || last == '\0')) { 379*eda14cbcSMatt Macy fclose(fp); 380*eda14cbcSMatt Macy return (B_TRUE); 381*eda14cbcSMatt Macy } 382*eda14cbcSMatt Macy } 383*eda14cbcSMatt Macy fclose(fp); 384*eda14cbcSMatt Macy return (B_FALSE); 385*eda14cbcSMatt Macy } 386*eda14cbcSMatt Macy 387*eda14cbcSMatt Macy static int 388*eda14cbcSMatt Macy nfs_validate_shareopts(const char *shareopts) 389*eda14cbcSMatt Macy { 390*eda14cbcSMatt Macy return (SA_OK); 391*eda14cbcSMatt Macy } 392*eda14cbcSMatt Macy 393*eda14cbcSMatt Macy static int 394*eda14cbcSMatt Macy nfs_update_shareopts(sa_share_impl_t impl_share, const char *shareopts) 395*eda14cbcSMatt Macy { 396*eda14cbcSMatt Macy FSINFO(impl_share, nfs_fstype)->shareopts = (char *)shareopts; 397*eda14cbcSMatt Macy return (SA_OK); 398*eda14cbcSMatt Macy } 399*eda14cbcSMatt Macy 400*eda14cbcSMatt Macy static void 401*eda14cbcSMatt Macy nfs_clear_shareopts(sa_share_impl_t impl_share) 402*eda14cbcSMatt Macy { 403*eda14cbcSMatt Macy FSINFO(impl_share, nfs_fstype)->shareopts = NULL; 404*eda14cbcSMatt Macy } 405*eda14cbcSMatt Macy 406*eda14cbcSMatt Macy /* 407*eda14cbcSMatt Macy * Commit the shares by restarting mountd. 408*eda14cbcSMatt Macy */ 409*eda14cbcSMatt Macy static int 410*eda14cbcSMatt Macy nfs_commit_shares(void) 411*eda14cbcSMatt Macy { 412*eda14cbcSMatt Macy struct pidfh *pfh; 413*eda14cbcSMatt Macy pid_t mountdpid; 414*eda14cbcSMatt Macy 415*eda14cbcSMatt Macy pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &mountdpid); 416*eda14cbcSMatt Macy if (pfh != NULL) { 417*eda14cbcSMatt Macy /* Mountd is not running. */ 418*eda14cbcSMatt Macy pidfile_remove(pfh); 419*eda14cbcSMatt Macy return (SA_OK); 420*eda14cbcSMatt Macy } 421*eda14cbcSMatt Macy if (errno != EEXIST) { 422*eda14cbcSMatt Macy /* Cannot open pidfile for some reason. */ 423*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 424*eda14cbcSMatt Macy } 425*eda14cbcSMatt Macy /* We have mountd(8) PID in mountdpid variable. */ 426*eda14cbcSMatt Macy kill(mountdpid, SIGHUP); 427*eda14cbcSMatt Macy return (SA_OK); 428*eda14cbcSMatt Macy } 429*eda14cbcSMatt Macy 430*eda14cbcSMatt Macy static const sa_share_ops_t nfs_shareops = { 431*eda14cbcSMatt Macy .enable_share = nfs_enable_share, 432*eda14cbcSMatt Macy .disable_share = nfs_disable_share, 433*eda14cbcSMatt Macy .is_shared = nfs_is_shared, 434*eda14cbcSMatt Macy 435*eda14cbcSMatt Macy .validate_shareopts = nfs_validate_shareopts, 436*eda14cbcSMatt Macy .update_shareopts = nfs_update_shareopts, 437*eda14cbcSMatt Macy .clear_shareopts = nfs_clear_shareopts, 438*eda14cbcSMatt Macy .commit_shares = nfs_commit_shares, 439*eda14cbcSMatt Macy }; 440*eda14cbcSMatt Macy 441*eda14cbcSMatt Macy /* 442*eda14cbcSMatt Macy * Initializes the NFS functionality of libshare. 443*eda14cbcSMatt Macy */ 444*eda14cbcSMatt Macy void 445*eda14cbcSMatt Macy libshare_nfs_init(void) 446*eda14cbcSMatt Macy { 447*eda14cbcSMatt Macy nfs_fstype = register_fstype("nfs", &nfs_shareops); 448*eda14cbcSMatt Macy } 449