xref: /freebsd/sys/contrib/openzfs/lib/libzfs/libzfs_share.c (revision 8a62a2a5659d1839d8799b4274c04469d7f17c78)
1*8a62a2a5SMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2*8a62a2a5SMartin Matuska /*
3*8a62a2a5SMartin Matuska  * CDDL HEADER START
4*8a62a2a5SMartin Matuska  *
5*8a62a2a5SMartin Matuska  * The contents of this file are subject to the terms of the
6*8a62a2a5SMartin Matuska  * Common Development and Distribution License (the "License").
7*8a62a2a5SMartin Matuska  * You may not use this file except in compliance with the License.
8*8a62a2a5SMartin Matuska  *
9*8a62a2a5SMartin Matuska  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*8a62a2a5SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
11*8a62a2a5SMartin Matuska  * See the License for the specific language governing permissions
12*8a62a2a5SMartin Matuska  * and limitations under the License.
13*8a62a2a5SMartin Matuska  *
14*8a62a2a5SMartin Matuska  * When distributing Covered Code, include this CDDL HEADER in each
15*8a62a2a5SMartin Matuska  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*8a62a2a5SMartin Matuska  * If applicable, add the following below this CDDL HEADER, with the
17*8a62a2a5SMartin Matuska  * fields enclosed by brackets "[]" replaced with your own identifying
18*8a62a2a5SMartin Matuska  * information: Portions Copyright [yyyy] [name of copyright owner]
19*8a62a2a5SMartin Matuska  *
20*8a62a2a5SMartin Matuska  * CDDL HEADER END
21*8a62a2a5SMartin Matuska  */
22*8a62a2a5SMartin Matuska 
23*8a62a2a5SMartin Matuska /*
24*8a62a2a5SMartin Matuska  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
25*8a62a2a5SMartin Matuska  * Copyright (c) 2011 Gunnar Beutner
26*8a62a2a5SMartin Matuska  * Copyright (c) 2018, 2022 by Delphix. All rights reserved.
27*8a62a2a5SMartin Matuska  */
28*8a62a2a5SMartin Matuska 
29*8a62a2a5SMartin Matuska #include <stdio.h>
30*8a62a2a5SMartin Matuska #include <stdlib.h>
31*8a62a2a5SMartin Matuska #include <stddef.h>
32*8a62a2a5SMartin Matuska #include <string.h>
33*8a62a2a5SMartin Matuska #include <errno.h>
34*8a62a2a5SMartin Matuska #include <libintl.h>
35*8a62a2a5SMartin Matuska #include <sys/file.h>
36*8a62a2a5SMartin Matuska #include <sys/types.h>
37*8a62a2a5SMartin Matuska #include <sys/stat.h>
38*8a62a2a5SMartin Matuska #include <unistd.h>
39*8a62a2a5SMartin Matuska #include <libzfs.h>
40*8a62a2a5SMartin Matuska #include "libzfs_impl.h"
41*8a62a2a5SMartin Matuska 
42*8a62a2a5SMartin Matuska #define	init_share(zfsname, path, shareopts) \
43*8a62a2a5SMartin Matuska 	{ \
44*8a62a2a5SMartin Matuska 		.sa_zfsname = zfsname, \
45*8a62a2a5SMartin Matuska 		.sa_mountpoint = path, \
46*8a62a2a5SMartin Matuska 		.sa_shareopts = shareopts, \
47*8a62a2a5SMartin Matuska 	}
48*8a62a2a5SMartin Matuska 
49*8a62a2a5SMartin Matuska #define	VALIDATE_PROTOCOL(proto, ...) \
50*8a62a2a5SMartin Matuska 	if ((proto) < 0 || (proto) >= SA_PROTOCOL_COUNT) \
51*8a62a2a5SMartin Matuska 		return __VA_ARGS__
52*8a62a2a5SMartin Matuska 
53*8a62a2a5SMartin Matuska const char *const sa_protocol_names[SA_PROTOCOL_COUNT] = {
54*8a62a2a5SMartin Matuska 	[SA_PROTOCOL_NFS] = "nfs",
55*8a62a2a5SMartin Matuska 	[SA_PROTOCOL_SMB] = "smb",
56*8a62a2a5SMartin Matuska };
57*8a62a2a5SMartin Matuska 
58*8a62a2a5SMartin Matuska static const sa_fstype_t *fstypes[SA_PROTOCOL_COUNT] =
59*8a62a2a5SMartin Matuska 	{&libshare_nfs_type, &libshare_smb_type};
60*8a62a2a5SMartin Matuska 
61*8a62a2a5SMartin Matuska int
sa_enable_share(const char * zfsname,const char * mountpoint,const char * shareopts,enum sa_protocol protocol)62*8a62a2a5SMartin Matuska sa_enable_share(const char *zfsname, const char *mountpoint,
63*8a62a2a5SMartin Matuska     const char *shareopts, enum sa_protocol protocol)
64*8a62a2a5SMartin Matuska {
65*8a62a2a5SMartin Matuska 	VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL);
66*8a62a2a5SMartin Matuska 
67*8a62a2a5SMartin Matuska 	const struct sa_share_impl args =
68*8a62a2a5SMartin Matuska 	    init_share(zfsname, mountpoint, shareopts);
69*8a62a2a5SMartin Matuska 	return (fstypes[protocol]->enable_share(&args));
70*8a62a2a5SMartin Matuska }
71*8a62a2a5SMartin Matuska 
72*8a62a2a5SMartin Matuska int
sa_disable_share(const char * mountpoint,enum sa_protocol protocol)73*8a62a2a5SMartin Matuska sa_disable_share(const char *mountpoint, enum sa_protocol protocol)
74*8a62a2a5SMartin Matuska {
75*8a62a2a5SMartin Matuska 	VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL);
76*8a62a2a5SMartin Matuska 
77*8a62a2a5SMartin Matuska 	const struct sa_share_impl args = init_share(NULL, mountpoint, NULL);
78*8a62a2a5SMartin Matuska 	return (fstypes[protocol]->disable_share(&args));
79*8a62a2a5SMartin Matuska }
80*8a62a2a5SMartin Matuska 
81*8a62a2a5SMartin Matuska boolean_t
sa_is_shared(const char * mountpoint,enum sa_protocol protocol)82*8a62a2a5SMartin Matuska sa_is_shared(const char *mountpoint, enum sa_protocol protocol)
83*8a62a2a5SMartin Matuska {
84*8a62a2a5SMartin Matuska 	VALIDATE_PROTOCOL(protocol, B_FALSE);
85*8a62a2a5SMartin Matuska 
86*8a62a2a5SMartin Matuska 	const struct sa_share_impl args = init_share(NULL, mountpoint, NULL);
87*8a62a2a5SMartin Matuska 	return (fstypes[protocol]->is_shared(&args));
88*8a62a2a5SMartin Matuska }
89*8a62a2a5SMartin Matuska 
90*8a62a2a5SMartin Matuska void
sa_commit_shares(enum sa_protocol protocol)91*8a62a2a5SMartin Matuska sa_commit_shares(enum sa_protocol protocol)
92*8a62a2a5SMartin Matuska {
93*8a62a2a5SMartin Matuska 	/* CSTYLED */
94*8a62a2a5SMartin Matuska 	VALIDATE_PROTOCOL(protocol, );
95*8a62a2a5SMartin Matuska 
96*8a62a2a5SMartin Matuska 	fstypes[protocol]->commit_shares();
97*8a62a2a5SMartin Matuska }
98*8a62a2a5SMartin Matuska 
99*8a62a2a5SMartin Matuska void
sa_truncate_shares(enum sa_protocol protocol)100*8a62a2a5SMartin Matuska sa_truncate_shares(enum sa_protocol protocol)
101*8a62a2a5SMartin Matuska {
102*8a62a2a5SMartin Matuska 	/* CSTYLED */
103*8a62a2a5SMartin Matuska 	VALIDATE_PROTOCOL(protocol, );
104*8a62a2a5SMartin Matuska 
105*8a62a2a5SMartin Matuska 	if (fstypes[protocol]->truncate_shares != NULL)
106*8a62a2a5SMartin Matuska 		fstypes[protocol]->truncate_shares();
107*8a62a2a5SMartin Matuska }
108*8a62a2a5SMartin Matuska 
109*8a62a2a5SMartin Matuska int
sa_validate_shareopts(const char * options,enum sa_protocol protocol)110*8a62a2a5SMartin Matuska sa_validate_shareopts(const char *options, enum sa_protocol protocol)
111*8a62a2a5SMartin Matuska {
112*8a62a2a5SMartin Matuska 	VALIDATE_PROTOCOL(protocol, SA_INVALID_PROTOCOL);
113*8a62a2a5SMartin Matuska 
114*8a62a2a5SMartin Matuska 	return (fstypes[protocol]->validate_shareopts(options));
115*8a62a2a5SMartin Matuska }
116*8a62a2a5SMartin Matuska 
117*8a62a2a5SMartin Matuska /*
118*8a62a2a5SMartin Matuska  * sa_errorstr(err)
119*8a62a2a5SMartin Matuska  *
120*8a62a2a5SMartin Matuska  * convert an error value to an error string
121*8a62a2a5SMartin Matuska  */
122*8a62a2a5SMartin Matuska const char *
sa_errorstr(int err)123*8a62a2a5SMartin Matuska sa_errorstr(int err)
124*8a62a2a5SMartin Matuska {
125*8a62a2a5SMartin Matuska 	static char errstr[32];
126*8a62a2a5SMartin Matuska 
127*8a62a2a5SMartin Matuska 	switch (err) {
128*8a62a2a5SMartin Matuska 	case SA_OK:
129*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "ok"));
130*8a62a2a5SMartin Matuska 	case SA_NO_SUCH_PATH:
131*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "path doesn't exist"));
132*8a62a2a5SMartin Matuska 	case SA_NO_MEMORY:
133*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "no memory"));
134*8a62a2a5SMartin Matuska 	case SA_DUPLICATE_NAME:
135*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "name in use"));
136*8a62a2a5SMartin Matuska 	case SA_BAD_PATH:
137*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "bad path"));
138*8a62a2a5SMartin Matuska 	case SA_NO_SUCH_GROUP:
139*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "no such group"));
140*8a62a2a5SMartin Matuska 	case SA_CONFIG_ERR:
141*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "configuration error"));
142*8a62a2a5SMartin Matuska 	case SA_SYSTEM_ERR:
143*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "system error"));
144*8a62a2a5SMartin Matuska 	case SA_SYNTAX_ERR:
145*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "syntax error"));
146*8a62a2a5SMartin Matuska 	case SA_NO_PERMISSION:
147*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "no permission"));
148*8a62a2a5SMartin Matuska 	case SA_BUSY:
149*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "busy"));
150*8a62a2a5SMartin Matuska 	case SA_NO_SUCH_PROP:
151*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "no such property"));
152*8a62a2a5SMartin Matuska 	case SA_INVALID_NAME:
153*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "invalid name"));
154*8a62a2a5SMartin Matuska 	case SA_INVALID_PROTOCOL:
155*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "invalid protocol"));
156*8a62a2a5SMartin Matuska 	case SA_NOT_ALLOWED:
157*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "operation not allowed"));
158*8a62a2a5SMartin Matuska 	case SA_BAD_VALUE:
159*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "bad property value"));
160*8a62a2a5SMartin Matuska 	case SA_INVALID_SECURITY:
161*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "invalid security type"));
162*8a62a2a5SMartin Matuska 	case SA_NO_SUCH_SECURITY:
163*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "security type not found"));
164*8a62a2a5SMartin Matuska 	case SA_VALUE_CONFLICT:
165*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "property value conflict"));
166*8a62a2a5SMartin Matuska 	case SA_NOT_IMPLEMENTED:
167*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "not implemented"));
168*8a62a2a5SMartin Matuska 	case SA_INVALID_PATH:
169*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "invalid path"));
170*8a62a2a5SMartin Matuska 	case SA_NOT_SUPPORTED:
171*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "operation not supported"));
172*8a62a2a5SMartin Matuska 	case SA_PROP_SHARE_ONLY:
173*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "property not valid for group"));
174*8a62a2a5SMartin Matuska 	case SA_NOT_SHARED:
175*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "not shared"));
176*8a62a2a5SMartin Matuska 	case SA_NO_SUCH_RESOURCE:
177*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "no such resource"));
178*8a62a2a5SMartin Matuska 	case SA_RESOURCE_REQUIRED:
179*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "resource name required"));
180*8a62a2a5SMartin Matuska 	case SA_MULTIPLE_ERROR:
181*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN,
182*8a62a2a5SMartin Matuska 		    "errors from multiple protocols"));
183*8a62a2a5SMartin Matuska 	case SA_PATH_IS_SUBDIR:
184*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "path is a subpath of share"));
185*8a62a2a5SMartin Matuska 	case SA_PATH_IS_PARENTDIR:
186*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "path is parent of a share"));
187*8a62a2a5SMartin Matuska 	case SA_NO_SECTION:
188*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "protocol requires a section"));
189*8a62a2a5SMartin Matuska 	case SA_NO_PROPERTIES:
190*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "properties not found"));
191*8a62a2a5SMartin Matuska 	case SA_NO_SUCH_SECTION:
192*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "section not found"));
193*8a62a2a5SMartin Matuska 	case SA_PASSWORD_ENC:
194*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN, "passwords must be encrypted"));
195*8a62a2a5SMartin Matuska 	case SA_SHARE_EXISTS:
196*8a62a2a5SMartin Matuska 		return (dgettext(TEXT_DOMAIN,
197*8a62a2a5SMartin Matuska 		    "path or file is already shared"));
198*8a62a2a5SMartin Matuska 	default:
199*8a62a2a5SMartin Matuska 		(void) snprintf(errstr, sizeof (errstr),
200*8a62a2a5SMartin Matuska 		    dgettext(TEXT_DOMAIN, "unknown %d"), err);
201*8a62a2a5SMartin Matuska 		return (errstr);
202*8a62a2a5SMartin Matuska 	}
203*8a62a2a5SMartin Matuska }
204