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