1*eda14cbcSMatt Macy /* 2*eda14cbcSMatt Macy * CDDL HEADER START 3*eda14cbcSMatt Macy * 4*eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5*eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6*eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7*eda14cbcSMatt Macy * 8*eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 10*eda14cbcSMatt Macy * See the License for the specific language governing permissions 11*eda14cbcSMatt Macy * and limitations under the License. 12*eda14cbcSMatt Macy * 13*eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14*eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16*eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17*eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18*eda14cbcSMatt Macy * 19*eda14cbcSMatt Macy * CDDL HEADER END 20*eda14cbcSMatt Macy */ 21*eda14cbcSMatt Macy 22*eda14cbcSMatt Macy /* 23*eda14cbcSMatt Macy * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 24*eda14cbcSMatt Macy * Copyright (c) 2011,2012 Turbo Fredriksson <turbo@bayour.com>, based on nfs.c 25*eda14cbcSMatt Macy * by Gunnar Beutner 26*eda14cbcSMatt Macy * Copyright (c) 2019, 2020 by Delphix. All rights reserved. 27*eda14cbcSMatt Macy * 28*eda14cbcSMatt Macy * This is an addition to the zfs device driver to add, modify and remove SMB 29*eda14cbcSMatt Macy * shares using the 'net share' command that comes with Samba. 30*eda14cbcSMatt Macy * 31*eda14cbcSMatt Macy * TESTING 32*eda14cbcSMatt Macy * Make sure that samba listens to 'localhost' (127.0.0.1) and that the options 33*eda14cbcSMatt Macy * 'usershare max shares' and 'usershare owner only' have been reviewed/set 34*eda14cbcSMatt Macy * accordingly (see zfs(8) for information). 35*eda14cbcSMatt Macy * 36*eda14cbcSMatt Macy * Once configuration in samba have been done, test that this 37*eda14cbcSMatt Macy * works with the following three commands (in this case, my ZFS 38*eda14cbcSMatt Macy * filesystem is called 'share/Test1'): 39*eda14cbcSMatt Macy * 40*eda14cbcSMatt Macy * (root)# net -U root -S 127.0.0.1 usershare add Test1 /share/Test1 \ 41*eda14cbcSMatt Macy * "Comment: /share/Test1" "Everyone:F" 42*eda14cbcSMatt Macy * (root)# net usershare list | grep -i test 43*eda14cbcSMatt Macy * (root)# net -U root -S 127.0.0.1 usershare delete Test1 44*eda14cbcSMatt Macy * 45*eda14cbcSMatt Macy * The first command will create a user share that gives everyone full access. 46*eda14cbcSMatt Macy * To limit the access below that, use normal UNIX commands (chmod, chown etc). 47*eda14cbcSMatt Macy */ 48*eda14cbcSMatt Macy 49*eda14cbcSMatt Macy #include <time.h> 50*eda14cbcSMatt Macy #include <stdlib.h> 51*eda14cbcSMatt Macy #include <stdio.h> 52*eda14cbcSMatt Macy #include <string.h> 53*eda14cbcSMatt Macy #include <strings.h> 54*eda14cbcSMatt Macy #include <fcntl.h> 55*eda14cbcSMatt Macy #include <sys/wait.h> 56*eda14cbcSMatt Macy #include <unistd.h> 57*eda14cbcSMatt Macy #include <dirent.h> 58*eda14cbcSMatt Macy #include <sys/types.h> 59*eda14cbcSMatt Macy #include <sys/stat.h> 60*eda14cbcSMatt Macy #include <libzfs.h> 61*eda14cbcSMatt Macy #include <libshare.h> 62*eda14cbcSMatt Macy #include "libshare_impl.h" 63*eda14cbcSMatt Macy #include "smb.h" 64*eda14cbcSMatt Macy 65*eda14cbcSMatt Macy static boolean_t smb_available(void); 66*eda14cbcSMatt Macy 67*eda14cbcSMatt Macy static sa_fstype_t *smb_fstype; 68*eda14cbcSMatt Macy 69*eda14cbcSMatt Macy smb_share_t *smb_shares; 70*eda14cbcSMatt Macy static int smb_disable_share(sa_share_impl_t impl_share); 71*eda14cbcSMatt Macy static boolean_t smb_is_share_active(sa_share_impl_t impl_share); 72*eda14cbcSMatt Macy 73*eda14cbcSMatt Macy /* 74*eda14cbcSMatt Macy * Retrieve the list of SMB shares. 75*eda14cbcSMatt Macy */ 76*eda14cbcSMatt Macy static int 77*eda14cbcSMatt Macy smb_retrieve_shares(void) 78*eda14cbcSMatt Macy { 79*eda14cbcSMatt Macy int rc = SA_OK; 80*eda14cbcSMatt Macy char file_path[PATH_MAX], line[512], *token, *key, *value; 81*eda14cbcSMatt Macy char *dup_value = NULL, *path = NULL, *comment = NULL, *name = NULL; 82*eda14cbcSMatt Macy char *guest_ok = NULL; 83*eda14cbcSMatt Macy DIR *shares_dir; 84*eda14cbcSMatt Macy FILE *share_file_fp = NULL; 85*eda14cbcSMatt Macy struct dirent *directory; 86*eda14cbcSMatt Macy struct stat eStat; 87*eda14cbcSMatt Macy smb_share_t *shares, *new_shares = NULL; 88*eda14cbcSMatt Macy 89*eda14cbcSMatt Macy /* opendir(), stat() */ 90*eda14cbcSMatt Macy shares_dir = opendir(SHARE_DIR); 91*eda14cbcSMatt Macy if (shares_dir == NULL) 92*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 93*eda14cbcSMatt Macy 94*eda14cbcSMatt Macy /* Go through the directory, looking for shares */ 95*eda14cbcSMatt Macy while ((directory = readdir(shares_dir))) { 96*eda14cbcSMatt Macy if (directory->d_name[0] == '.') 97*eda14cbcSMatt Macy continue; 98*eda14cbcSMatt Macy 99*eda14cbcSMatt Macy snprintf(file_path, sizeof (file_path), 100*eda14cbcSMatt Macy "%s/%s", SHARE_DIR, directory->d_name); 101*eda14cbcSMatt Macy 102*eda14cbcSMatt Macy if (stat(file_path, &eStat) == -1) { 103*eda14cbcSMatt Macy rc = SA_SYSTEM_ERR; 104*eda14cbcSMatt Macy goto out; 105*eda14cbcSMatt Macy } 106*eda14cbcSMatt Macy 107*eda14cbcSMatt Macy if (!S_ISREG(eStat.st_mode)) 108*eda14cbcSMatt Macy continue; 109*eda14cbcSMatt Macy 110*eda14cbcSMatt Macy if ((share_file_fp = fopen(file_path, "r")) == NULL) { 111*eda14cbcSMatt Macy rc = SA_SYSTEM_ERR; 112*eda14cbcSMatt Macy goto out; 113*eda14cbcSMatt Macy } 114*eda14cbcSMatt Macy 115*eda14cbcSMatt Macy name = strdup(directory->d_name); 116*eda14cbcSMatt Macy if (name == NULL) { 117*eda14cbcSMatt Macy rc = SA_NO_MEMORY; 118*eda14cbcSMatt Macy goto out; 119*eda14cbcSMatt Macy } 120*eda14cbcSMatt Macy 121*eda14cbcSMatt Macy while (fgets(line, sizeof (line), share_file_fp)) { 122*eda14cbcSMatt Macy if (line[0] == '#') 123*eda14cbcSMatt Macy continue; 124*eda14cbcSMatt Macy 125*eda14cbcSMatt Macy /* Trim trailing new-line character(s). */ 126*eda14cbcSMatt Macy while (line[strlen(line) - 1] == '\r' || 127*eda14cbcSMatt Macy line[strlen(line) - 1] == '\n') 128*eda14cbcSMatt Macy line[strlen(line) - 1] = '\0'; 129*eda14cbcSMatt Macy 130*eda14cbcSMatt Macy /* Split the line in two, separated by '=' */ 131*eda14cbcSMatt Macy token = strchr(line, '='); 132*eda14cbcSMatt Macy if (token == NULL) 133*eda14cbcSMatt Macy continue; 134*eda14cbcSMatt Macy 135*eda14cbcSMatt Macy key = line; 136*eda14cbcSMatt Macy value = token + 1; 137*eda14cbcSMatt Macy *token = '\0'; 138*eda14cbcSMatt Macy 139*eda14cbcSMatt Macy dup_value = strdup(value); 140*eda14cbcSMatt Macy if (dup_value == NULL) { 141*eda14cbcSMatt Macy rc = SA_NO_MEMORY; 142*eda14cbcSMatt Macy goto out; 143*eda14cbcSMatt Macy } 144*eda14cbcSMatt Macy 145*eda14cbcSMatt Macy if (strcmp(key, "path") == 0) { 146*eda14cbcSMatt Macy free(path); 147*eda14cbcSMatt Macy path = dup_value; 148*eda14cbcSMatt Macy } else if (strcmp(key, "comment") == 0) { 149*eda14cbcSMatt Macy free(comment); 150*eda14cbcSMatt Macy comment = dup_value; 151*eda14cbcSMatt Macy } else if (strcmp(key, "guest_ok") == 0) { 152*eda14cbcSMatt Macy free(guest_ok); 153*eda14cbcSMatt Macy guest_ok = dup_value; 154*eda14cbcSMatt Macy } else 155*eda14cbcSMatt Macy free(dup_value); 156*eda14cbcSMatt Macy 157*eda14cbcSMatt Macy dup_value = NULL; 158*eda14cbcSMatt Macy 159*eda14cbcSMatt Macy if (path == NULL || comment == NULL || guest_ok == NULL) 160*eda14cbcSMatt Macy continue; /* Incomplete share definition */ 161*eda14cbcSMatt Macy else { 162*eda14cbcSMatt Macy shares = (smb_share_t *) 163*eda14cbcSMatt Macy malloc(sizeof (smb_share_t)); 164*eda14cbcSMatt Macy if (shares == NULL) { 165*eda14cbcSMatt Macy rc = SA_NO_MEMORY; 166*eda14cbcSMatt Macy goto out; 167*eda14cbcSMatt Macy } 168*eda14cbcSMatt Macy 169*eda14cbcSMatt Macy (void) strlcpy(shares->name, name, 170*eda14cbcSMatt Macy sizeof (shares->name)); 171*eda14cbcSMatt Macy 172*eda14cbcSMatt Macy (void) strlcpy(shares->path, path, 173*eda14cbcSMatt Macy sizeof (shares->path)); 174*eda14cbcSMatt Macy 175*eda14cbcSMatt Macy (void) strlcpy(shares->comment, comment, 176*eda14cbcSMatt Macy sizeof (shares->comment)); 177*eda14cbcSMatt Macy 178*eda14cbcSMatt Macy shares->guest_ok = atoi(guest_ok); 179*eda14cbcSMatt Macy 180*eda14cbcSMatt Macy shares->next = new_shares; 181*eda14cbcSMatt Macy new_shares = shares; 182*eda14cbcSMatt Macy 183*eda14cbcSMatt Macy free(path); 184*eda14cbcSMatt Macy free(comment); 185*eda14cbcSMatt Macy free(guest_ok); 186*eda14cbcSMatt Macy 187*eda14cbcSMatt Macy path = NULL; 188*eda14cbcSMatt Macy comment = NULL; 189*eda14cbcSMatt Macy guest_ok = NULL; 190*eda14cbcSMatt Macy } 191*eda14cbcSMatt Macy } 192*eda14cbcSMatt Macy 193*eda14cbcSMatt Macy out: 194*eda14cbcSMatt Macy if (share_file_fp != NULL) { 195*eda14cbcSMatt Macy fclose(share_file_fp); 196*eda14cbcSMatt Macy share_file_fp = NULL; 197*eda14cbcSMatt Macy } 198*eda14cbcSMatt Macy 199*eda14cbcSMatt Macy free(name); 200*eda14cbcSMatt Macy free(path); 201*eda14cbcSMatt Macy free(comment); 202*eda14cbcSMatt Macy free(guest_ok); 203*eda14cbcSMatt Macy 204*eda14cbcSMatt Macy name = NULL; 205*eda14cbcSMatt Macy path = NULL; 206*eda14cbcSMatt Macy comment = NULL; 207*eda14cbcSMatt Macy guest_ok = NULL; 208*eda14cbcSMatt Macy } 209*eda14cbcSMatt Macy closedir(shares_dir); 210*eda14cbcSMatt Macy 211*eda14cbcSMatt Macy smb_shares = new_shares; 212*eda14cbcSMatt Macy 213*eda14cbcSMatt Macy return (rc); 214*eda14cbcSMatt Macy } 215*eda14cbcSMatt Macy 216*eda14cbcSMatt Macy /* 217*eda14cbcSMatt Macy * Used internally by smb_enable_share to enable sharing for a single host. 218*eda14cbcSMatt Macy */ 219*eda14cbcSMatt Macy static int 220*eda14cbcSMatt Macy smb_enable_share_one(const char *sharename, const char *sharepath) 221*eda14cbcSMatt Macy { 222*eda14cbcSMatt Macy char *argv[10], *pos; 223*eda14cbcSMatt Macy char name[SMB_NAME_MAX], comment[SMB_COMMENT_MAX]; 224*eda14cbcSMatt Macy int rc; 225*eda14cbcSMatt Macy 226*eda14cbcSMatt Macy /* Support ZFS share name regexp '[[:alnum:]_-.: ]' */ 227*eda14cbcSMatt Macy strlcpy(name, sharename, sizeof (name)); 228*eda14cbcSMatt Macy name [sizeof (name)-1] = '\0'; 229*eda14cbcSMatt Macy 230*eda14cbcSMatt Macy pos = name; 231*eda14cbcSMatt Macy while (*pos != '\0') { 232*eda14cbcSMatt Macy switch (*pos) { 233*eda14cbcSMatt Macy case '/': 234*eda14cbcSMatt Macy case '-': 235*eda14cbcSMatt Macy case ':': 236*eda14cbcSMatt Macy case ' ': 237*eda14cbcSMatt Macy *pos = '_'; 238*eda14cbcSMatt Macy } 239*eda14cbcSMatt Macy 240*eda14cbcSMatt Macy ++pos; 241*eda14cbcSMatt Macy } 242*eda14cbcSMatt Macy 243*eda14cbcSMatt Macy /* 244*eda14cbcSMatt Macy * CMD: net -S NET_CMD_ARG_HOST usershare add Test1 /share/Test1 \ 245*eda14cbcSMatt Macy * "Comment" "Everyone:F" 246*eda14cbcSMatt Macy */ 247*eda14cbcSMatt Macy snprintf(comment, sizeof (comment), "Comment: %s", sharepath); 248*eda14cbcSMatt Macy 249*eda14cbcSMatt Macy argv[0] = NET_CMD_PATH; 250*eda14cbcSMatt Macy argv[1] = (char *)"-S"; 251*eda14cbcSMatt Macy argv[2] = NET_CMD_ARG_HOST; 252*eda14cbcSMatt Macy argv[3] = (char *)"usershare"; 253*eda14cbcSMatt Macy argv[4] = (char *)"add"; 254*eda14cbcSMatt Macy argv[5] = (char *)name; 255*eda14cbcSMatt Macy argv[6] = (char *)sharepath; 256*eda14cbcSMatt Macy argv[7] = (char *)comment; 257*eda14cbcSMatt Macy argv[8] = "Everyone:F"; 258*eda14cbcSMatt Macy argv[9] = NULL; 259*eda14cbcSMatt Macy 260*eda14cbcSMatt Macy rc = libzfs_run_process(argv[0], argv, 0); 261*eda14cbcSMatt Macy if (rc < 0) 262*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 263*eda14cbcSMatt Macy 264*eda14cbcSMatt Macy /* Reload the share file */ 265*eda14cbcSMatt Macy (void) smb_retrieve_shares(); 266*eda14cbcSMatt Macy 267*eda14cbcSMatt Macy return (SA_OK); 268*eda14cbcSMatt Macy } 269*eda14cbcSMatt Macy 270*eda14cbcSMatt Macy /* 271*eda14cbcSMatt Macy * Enables SMB sharing for the specified share. 272*eda14cbcSMatt Macy */ 273*eda14cbcSMatt Macy static int 274*eda14cbcSMatt Macy smb_enable_share(sa_share_impl_t impl_share) 275*eda14cbcSMatt Macy { 276*eda14cbcSMatt Macy char *shareopts; 277*eda14cbcSMatt Macy 278*eda14cbcSMatt Macy if (!smb_available()) 279*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 280*eda14cbcSMatt Macy 281*eda14cbcSMatt Macy if (smb_is_share_active(impl_share)) 282*eda14cbcSMatt Macy smb_disable_share(impl_share); 283*eda14cbcSMatt Macy 284*eda14cbcSMatt Macy shareopts = FSINFO(impl_share, smb_fstype)->shareopts; 285*eda14cbcSMatt Macy if (shareopts == NULL) /* on/off */ 286*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 287*eda14cbcSMatt Macy 288*eda14cbcSMatt Macy if (strcmp(shareopts, "off") == 0) 289*eda14cbcSMatt Macy return (SA_OK); 290*eda14cbcSMatt Macy 291*eda14cbcSMatt Macy /* Magic: Enable (i.e., 'create new') share */ 292*eda14cbcSMatt Macy return (smb_enable_share_one(impl_share->sa_zfsname, 293*eda14cbcSMatt Macy impl_share->sa_mountpoint)); 294*eda14cbcSMatt Macy } 295*eda14cbcSMatt Macy 296*eda14cbcSMatt Macy /* 297*eda14cbcSMatt Macy * Used internally by smb_disable_share to disable sharing for a single host. 298*eda14cbcSMatt Macy */ 299*eda14cbcSMatt Macy static int 300*eda14cbcSMatt Macy smb_disable_share_one(const char *sharename) 301*eda14cbcSMatt Macy { 302*eda14cbcSMatt Macy int rc; 303*eda14cbcSMatt Macy char *argv[7]; 304*eda14cbcSMatt Macy 305*eda14cbcSMatt Macy /* CMD: net -S NET_CMD_ARG_HOST usershare delete Test1 */ 306*eda14cbcSMatt Macy argv[0] = NET_CMD_PATH; 307*eda14cbcSMatt Macy argv[1] = (char *)"-S"; 308*eda14cbcSMatt Macy argv[2] = NET_CMD_ARG_HOST; 309*eda14cbcSMatt Macy argv[3] = (char *)"usershare"; 310*eda14cbcSMatt Macy argv[4] = (char *)"delete"; 311*eda14cbcSMatt Macy argv[5] = strdup(sharename); 312*eda14cbcSMatt Macy argv[6] = NULL; 313*eda14cbcSMatt Macy 314*eda14cbcSMatt Macy rc = libzfs_run_process(argv[0], argv, 0); 315*eda14cbcSMatt Macy if (rc < 0) 316*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 317*eda14cbcSMatt Macy else 318*eda14cbcSMatt Macy return (SA_OK); 319*eda14cbcSMatt Macy } 320*eda14cbcSMatt Macy 321*eda14cbcSMatt Macy /* 322*eda14cbcSMatt Macy * Disables SMB sharing for the specified share. 323*eda14cbcSMatt Macy */ 324*eda14cbcSMatt Macy static int 325*eda14cbcSMatt Macy smb_disable_share(sa_share_impl_t impl_share) 326*eda14cbcSMatt Macy { 327*eda14cbcSMatt Macy smb_share_t *shares = smb_shares; 328*eda14cbcSMatt Macy 329*eda14cbcSMatt Macy if (!smb_available()) { 330*eda14cbcSMatt Macy /* 331*eda14cbcSMatt Macy * The share can't possibly be active, so nothing 332*eda14cbcSMatt Macy * needs to be done to disable it. 333*eda14cbcSMatt Macy */ 334*eda14cbcSMatt Macy return (SA_OK); 335*eda14cbcSMatt Macy } 336*eda14cbcSMatt Macy 337*eda14cbcSMatt Macy while (shares != NULL) { 338*eda14cbcSMatt Macy if (strcmp(impl_share->sa_mountpoint, shares->path) == 0) 339*eda14cbcSMatt Macy return (smb_disable_share_one(shares->name)); 340*eda14cbcSMatt Macy 341*eda14cbcSMatt Macy shares = shares->next; 342*eda14cbcSMatt Macy } 343*eda14cbcSMatt Macy 344*eda14cbcSMatt Macy return (SA_OK); 345*eda14cbcSMatt Macy } 346*eda14cbcSMatt Macy 347*eda14cbcSMatt Macy /* 348*eda14cbcSMatt Macy * Checks whether the specified SMB share options are syntactically correct. 349*eda14cbcSMatt Macy */ 350*eda14cbcSMatt Macy static int 351*eda14cbcSMatt Macy smb_validate_shareopts(const char *shareopts) 352*eda14cbcSMatt Macy { 353*eda14cbcSMatt Macy /* TODO: Accept 'name' and sec/acl (?) */ 354*eda14cbcSMatt Macy if ((strcmp(shareopts, "off") == 0) || (strcmp(shareopts, "on") == 0)) 355*eda14cbcSMatt Macy return (SA_OK); 356*eda14cbcSMatt Macy 357*eda14cbcSMatt Macy return (SA_SYNTAX_ERR); 358*eda14cbcSMatt Macy } 359*eda14cbcSMatt Macy 360*eda14cbcSMatt Macy /* 361*eda14cbcSMatt Macy * Checks whether a share is currently active. 362*eda14cbcSMatt Macy */ 363*eda14cbcSMatt Macy static boolean_t 364*eda14cbcSMatt Macy smb_is_share_active(sa_share_impl_t impl_share) 365*eda14cbcSMatt Macy { 366*eda14cbcSMatt Macy smb_share_t *iter = smb_shares; 367*eda14cbcSMatt Macy 368*eda14cbcSMatt Macy if (!smb_available()) 369*eda14cbcSMatt Macy return (B_FALSE); 370*eda14cbcSMatt Macy 371*eda14cbcSMatt Macy /* Retrieve the list of (possible) active shares */ 372*eda14cbcSMatt Macy smb_retrieve_shares(); 373*eda14cbcSMatt Macy 374*eda14cbcSMatt Macy while (iter != NULL) { 375*eda14cbcSMatt Macy if (strcmp(impl_share->sa_mountpoint, iter->path) == 0) 376*eda14cbcSMatt Macy return (B_TRUE); 377*eda14cbcSMatt Macy 378*eda14cbcSMatt Macy iter = iter->next; 379*eda14cbcSMatt Macy } 380*eda14cbcSMatt Macy 381*eda14cbcSMatt Macy return (B_FALSE); 382*eda14cbcSMatt Macy } 383*eda14cbcSMatt Macy 384*eda14cbcSMatt Macy /* 385*eda14cbcSMatt Macy * Called to update a share's options. A share's options might be out of 386*eda14cbcSMatt Macy * date if the share was loaded from disk and the "sharesmb" dataset 387*eda14cbcSMatt Macy * property has changed in the meantime. This function also takes care 388*eda14cbcSMatt Macy * of re-enabling the share if necessary. 389*eda14cbcSMatt Macy */ 390*eda14cbcSMatt Macy static int 391*eda14cbcSMatt Macy smb_update_shareopts(sa_share_impl_t impl_share, const char *shareopts) 392*eda14cbcSMatt Macy { 393*eda14cbcSMatt Macy if (!impl_share) 394*eda14cbcSMatt Macy return (SA_SYSTEM_ERR); 395*eda14cbcSMatt Macy 396*eda14cbcSMatt Macy FSINFO(impl_share, smb_fstype)->shareopts = (char *)shareopts; 397*eda14cbcSMatt Macy return (SA_OK); 398*eda14cbcSMatt Macy } 399*eda14cbcSMatt Macy 400*eda14cbcSMatt Macy static int 401*eda14cbcSMatt Macy smb_update_shares(void) 402*eda14cbcSMatt Macy { 403*eda14cbcSMatt Macy /* Not implemented */ 404*eda14cbcSMatt Macy return (0); 405*eda14cbcSMatt Macy } 406*eda14cbcSMatt Macy 407*eda14cbcSMatt Macy /* 408*eda14cbcSMatt Macy * Clears a share's SMB options. Used by libshare to 409*eda14cbcSMatt Macy * clean up shares that are about to be free()'d. 410*eda14cbcSMatt Macy */ 411*eda14cbcSMatt Macy static void 412*eda14cbcSMatt Macy smb_clear_shareopts(sa_share_impl_t impl_share) 413*eda14cbcSMatt Macy { 414*eda14cbcSMatt Macy FSINFO(impl_share, smb_fstype)->shareopts = NULL; 415*eda14cbcSMatt Macy } 416*eda14cbcSMatt Macy 417*eda14cbcSMatt Macy static const sa_share_ops_t smb_shareops = { 418*eda14cbcSMatt Macy .enable_share = smb_enable_share, 419*eda14cbcSMatt Macy .disable_share = smb_disable_share, 420*eda14cbcSMatt Macy .is_shared = smb_is_share_active, 421*eda14cbcSMatt Macy 422*eda14cbcSMatt Macy .validate_shareopts = smb_validate_shareopts, 423*eda14cbcSMatt Macy .update_shareopts = smb_update_shareopts, 424*eda14cbcSMatt Macy .clear_shareopts = smb_clear_shareopts, 425*eda14cbcSMatt Macy .commit_shares = smb_update_shares, 426*eda14cbcSMatt Macy }; 427*eda14cbcSMatt Macy 428*eda14cbcSMatt Macy /* 429*eda14cbcSMatt Macy * Provides a convenient wrapper for determining SMB availability 430*eda14cbcSMatt Macy */ 431*eda14cbcSMatt Macy static boolean_t 432*eda14cbcSMatt Macy smb_available(void) 433*eda14cbcSMatt Macy { 434*eda14cbcSMatt Macy struct stat statbuf; 435*eda14cbcSMatt Macy 436*eda14cbcSMatt Macy if (lstat(SHARE_DIR, &statbuf) != 0 || 437*eda14cbcSMatt Macy !S_ISDIR(statbuf.st_mode)) 438*eda14cbcSMatt Macy return (B_FALSE); 439*eda14cbcSMatt Macy 440*eda14cbcSMatt Macy if (access(NET_CMD_PATH, F_OK) != 0) 441*eda14cbcSMatt Macy return (B_FALSE); 442*eda14cbcSMatt Macy 443*eda14cbcSMatt Macy return (B_TRUE); 444*eda14cbcSMatt Macy } 445*eda14cbcSMatt Macy 446*eda14cbcSMatt Macy /* 447*eda14cbcSMatt Macy * Initializes the SMB functionality of libshare. 448*eda14cbcSMatt Macy */ 449*eda14cbcSMatt Macy void 450*eda14cbcSMatt Macy libshare_smb_init(void) 451*eda14cbcSMatt Macy { 452*eda14cbcSMatt Macy smb_fstype = register_fstype("smb", &smb_shareops); 453*eda14cbcSMatt Macy } 454