]>
Commit | Line | Data |
---|---|---|
46e18b3f GB |
1 | /* |
2 | * CDDL HEADER START | |
3 | * | |
4 | * The contents of this file are subject to the terms of the | |
5 | * Common Development and Distribution License (the "License"). | |
6 | * You may not use this file except in compliance with the License. | |
7 | * | |
8 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
9 | * or http://www.opensolaris.org/os/licensing. | |
10 | * See the License for the specific language governing permissions | |
11 | * and limitations under the License. | |
12 | * | |
13 | * When distributing Covered Code, include this CDDL HEADER in each | |
14 | * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 | * If applicable, add the following below this CDDL HEADER, with the | |
16 | * fields enclosed by brackets "[]" replaced with your own identifying | |
17 | * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 | * | |
19 | * CDDL HEADER END | |
20 | */ | |
21 | ||
22 | /* | |
23 | * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. | |
24 | * Copyright (c) 2011 Gunnar Beutner | |
25 | */ | |
26 | ||
27 | #include <stdio.h> | |
28 | #include <stdlib.h> | |
29 | #include <errno.h> | |
30 | #include <strings.h> | |
31 | #include <libintl.h> | |
32 | #include <sys/types.h> | |
33 | #include <sys/stat.h> | |
34 | #include <unistd.h> | |
35 | #include <libzfs.h> | |
36 | #include <libshare.h> | |
37 | #include "libshare_impl.h" | |
38 | #include "nfs.h" | |
645fb9cc | 39 | #include "smb.h" |
46e18b3f GB |
40 | |
41 | static sa_share_impl_t find_share(sa_handle_impl_t handle, | |
42 | const char *sharepath); | |
43 | static sa_share_impl_t alloc_share(const char *sharepath); | |
44 | static void free_share(sa_share_impl_t share); | |
45 | ||
46 | static void parse_sharetab(sa_handle_impl_t impl_handle); | |
47 | static int process_share(sa_handle_impl_t impl_handle, | |
48 | sa_share_impl_t impl_share, char *pathname, char *resource, | |
49 | char *fstype, char *options, char *description, | |
50 | char *dataset, boolean_t from_sharetab); | |
51 | static void update_sharetab(sa_handle_impl_t impl_handle); | |
52 | ||
53 | static int update_zfs_share(sa_share_impl_t impl_handle, const char *proto); | |
54 | static int update_zfs_shares(sa_handle_impl_t impl_handle, const char *proto); | |
55 | ||
56 | static int fstypes_count; | |
57 | static sa_fstype_t *fstypes; | |
58 | ||
59 | sa_fstype_t * | |
60 | register_fstype(const char *name, const sa_share_ops_t *ops) | |
61 | { | |
62 | sa_fstype_t *fstype; | |
63 | ||
64 | fstype = calloc(sizeof (sa_fstype_t), 1); | |
65 | ||
66 | if (fstype == NULL) | |
a08ee875 | 67 | return (NULL); |
46e18b3f GB |
68 | |
69 | fstype->name = name; | |
70 | fstype->ops = ops; | |
71 | fstype->fsinfo_index = fstypes_count; | |
72 | ||
73 | fstypes_count++; | |
74 | ||
75 | fstype->next = fstypes; | |
76 | fstypes = fstype; | |
77 | ||
a08ee875 | 78 | return (fstype); |
46e18b3f GB |
79 | } |
80 | ||
81 | sa_handle_t | |
82 | sa_init(int init_service) | |
83 | { | |
84 | sa_handle_impl_t impl_handle; | |
85 | ||
86 | impl_handle = calloc(sizeof (struct sa_handle_impl), 1); | |
87 | ||
88 | if (impl_handle == NULL) | |
a08ee875 | 89 | return (NULL); |
46e18b3f GB |
90 | |
91 | impl_handle->zfs_libhandle = libzfs_init(); | |
92 | ||
93 | if (impl_handle->zfs_libhandle != NULL) { | |
94 | libzfs_print_on_error(impl_handle->zfs_libhandle, B_TRUE); | |
95 | } | |
96 | ||
97 | parse_sharetab(impl_handle); | |
98 | update_zfs_shares(impl_handle, NULL); | |
99 | ||
100 | return ((sa_handle_t)impl_handle); | |
101 | } | |
102 | ||
103 | __attribute__((constructor)) static void | |
104 | libshare_init(void) | |
105 | { | |
106 | libshare_nfs_init(); | |
645fb9cc | 107 | libshare_smb_init(); |
46e18b3f GB |
108 | } |
109 | ||
110 | static void | |
cae5b340 AX |
111 | parse_sharetab(sa_handle_impl_t impl_handle) |
112 | { | |
46e18b3f GB |
113 | FILE *fp; |
114 | char line[512]; | |
115 | char *eol, *pathname, *resource, *fstype, *options, *description; | |
116 | ||
cae5b340 | 117 | fp = fopen(ZFS_SHARETAB, "r"); |
46e18b3f GB |
118 | |
119 | if (fp == NULL) | |
120 | return; | |
121 | ||
122 | while (fgets(line, sizeof (line), fp) != NULL) { | |
123 | eol = line + strlen(line) - 1; | |
124 | ||
125 | while (eol >= line) { | |
126 | if (*eol != '\r' && *eol != '\n') | |
127 | break; | |
128 | ||
129 | *eol = '\0'; | |
130 | eol--; | |
131 | } | |
132 | ||
133 | pathname = line; | |
134 | ||
135 | if ((resource = strchr(pathname, '\t')) == NULL) | |
136 | continue; | |
137 | ||
138 | *resource = '\0'; | |
139 | resource++; | |
140 | ||
141 | if ((fstype = strchr(resource, '\t')) == NULL) | |
142 | continue; | |
143 | ||
144 | *fstype = '\0'; | |
145 | fstype++; | |
146 | ||
147 | if ((options = strchr(fstype, '\t')) == NULL) | |
148 | continue; | |
149 | ||
150 | *options = '\0'; | |
151 | options++; | |
152 | ||
153 | if ((description = strchr(fstype, '\t')) != NULL) { | |
154 | *description = '\0'; | |
155 | description++; | |
156 | } | |
157 | ||
158 | if (strcmp(resource, "-") == 0) | |
159 | resource = NULL; | |
160 | ||
161 | (void) process_share(impl_handle, NULL, pathname, resource, | |
162 | fstype, options, description, NULL, B_TRUE); | |
163 | } | |
164 | ||
165 | fclose(fp); | |
166 | } | |
167 | ||
168 | static void | |
169 | update_sharetab(sa_handle_impl_t impl_handle) | |
170 | { | |
171 | sa_share_impl_t impl_share; | |
172 | int temp_fd; | |
173 | FILE *temp_fp; | |
cae5b340 | 174 | char tempfile[] = ZFS_SHARETAB".XXXXXX"; |
46e18b3f GB |
175 | sa_fstype_t *fstype; |
176 | const char *resource; | |
177 | ||
178 | if (mkdir("/etc/dfs", 0755) < 0 && errno != EEXIST) { | |
179 | return; | |
180 | } | |
181 | ||
182 | temp_fd = mkstemp(tempfile); | |
183 | ||
184 | if (temp_fd < 0) | |
185 | return; | |
186 | ||
187 | temp_fp = fdopen(temp_fd, "w"); | |
188 | ||
189 | if (temp_fp == NULL) | |
190 | return; | |
191 | ||
192 | impl_share = impl_handle->shares; | |
193 | while (impl_share != NULL) { | |
194 | fstype = fstypes; | |
195 | while (fstype != NULL) { | |
196 | if (FSINFO(impl_share, fstype)->active && | |
197 | FSINFO(impl_share, fstype)->shareopts != NULL) { | |
198 | resource = FSINFO(impl_share, fstype)->resource; | |
199 | ||
200 | if (resource == NULL) | |
201 | resource = "-"; | |
202 | ||
203 | fprintf(temp_fp, "%s\t%s\t%s\t%s\n", | |
204 | impl_share->sharepath, resource, | |
205 | fstype->name, | |
206 | FSINFO(impl_share, fstype)->shareopts); | |
207 | } | |
208 | ||
209 | fstype = fstype->next; | |
210 | } | |
211 | ||
212 | impl_share = impl_share->next; | |
213 | } | |
214 | ||
215 | fflush(temp_fp); | |
216 | fsync(temp_fd); | |
217 | fclose(temp_fp); | |
218 | ||
cae5b340 | 219 | (void) rename(tempfile, ZFS_SHARETAB); |
46e18b3f GB |
220 | } |
221 | ||
222 | typedef struct update_cookie_s { | |
223 | sa_handle_impl_t handle; | |
224 | const char *proto; | |
225 | } update_cookie_t; | |
226 | ||
227 | static int | |
228 | update_zfs_shares_cb(zfs_handle_t *zhp, void *pcookie) | |
229 | { | |
230 | update_cookie_t *udata = (update_cookie_t *)pcookie; | |
231 | char mountpoint[ZFS_MAXPROPLEN]; | |
232 | char shareopts[ZFS_MAXPROPLEN]; | |
233 | char *dataset; | |
234 | zfs_type_t type = zfs_get_type(zhp); | |
235 | ||
236 | if (type == ZFS_TYPE_FILESYSTEM && | |
237 | zfs_iter_filesystems(zhp, update_zfs_shares_cb, pcookie) != 0) { | |
238 | zfs_close(zhp); | |
a08ee875 | 239 | return (1); |
46e18b3f GB |
240 | } |
241 | ||
242 | if (type != ZFS_TYPE_FILESYSTEM) { | |
243 | zfs_close(zhp); | |
a08ee875 | 244 | return (0); |
46e18b3f GB |
245 | } |
246 | ||
247 | if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, | |
248 | sizeof (mountpoint), NULL, NULL, 0, B_FALSE) != 0) { | |
249 | zfs_close(zhp); | |
a08ee875 | 250 | return (0); |
46e18b3f GB |
251 | } |
252 | ||
253 | dataset = (char *)zfs_get_name(zhp); | |
254 | ||
255 | if (dataset == NULL) { | |
256 | zfs_close(zhp); | |
a08ee875 | 257 | return (0); |
46e18b3f GB |
258 | } |
259 | ||
260 | if (!zfs_is_mounted(zhp, NULL)) { | |
261 | zfs_close(zhp); | |
a08ee875 | 262 | return (0); |
46e18b3f GB |
263 | } |
264 | ||
265 | if ((udata->proto == NULL || strcmp(udata->proto, "nfs") == 0) && | |
266 | zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, | |
267 | sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0 && | |
268 | strcmp(shareopts, "off") != 0) { | |
269 | (void) process_share(udata->handle, NULL, mountpoint, NULL, | |
270 | "nfs", shareopts, NULL, dataset, B_FALSE); | |
271 | } | |
272 | ||
273 | if ((udata->proto == NULL || strcmp(udata->proto, "smb") == 0) && | |
274 | zfs_prop_get(zhp, ZFS_PROP_SHARESMB, shareopts, | |
275 | sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0 && | |
276 | strcmp(shareopts, "off") != 0) { | |
277 | (void) process_share(udata->handle, NULL, mountpoint, NULL, | |
278 | "smb", shareopts, NULL, dataset, B_FALSE); | |
279 | } | |
280 | ||
281 | zfs_close(zhp); | |
282 | ||
a08ee875 | 283 | return (0); |
46e18b3f GB |
284 | } |
285 | ||
286 | static int | |
287 | update_zfs_share(sa_share_impl_t impl_share, const char *proto) | |
288 | { | |
289 | sa_handle_impl_t impl_handle = impl_share->handle; | |
290 | zfs_handle_t *zhp; | |
291 | update_cookie_t udata; | |
292 | ||
293 | if (impl_handle->zfs_libhandle == NULL) | |
a08ee875 | 294 | return (SA_SYSTEM_ERR); |
46e18b3f GB |
295 | |
296 | assert(impl_share->dataset != NULL); | |
297 | ||
298 | zhp = zfs_open(impl_share->handle->zfs_libhandle, impl_share->dataset, | |
299 | ZFS_TYPE_FILESYSTEM); | |
300 | ||
301 | if (zhp == NULL) | |
a08ee875 | 302 | return (SA_SYSTEM_ERR); |
46e18b3f GB |
303 | |
304 | udata.handle = impl_handle; | |
305 | udata.proto = proto; | |
306 | (void) update_zfs_shares_cb(zhp, &udata); | |
307 | ||
a08ee875 | 308 | return (SA_OK); |
46e18b3f GB |
309 | } |
310 | ||
311 | static int | |
312 | update_zfs_shares(sa_handle_impl_t impl_handle, const char *proto) | |
313 | { | |
314 | update_cookie_t udata; | |
315 | ||
316 | if (impl_handle->zfs_libhandle == NULL) | |
a08ee875 | 317 | return (SA_SYSTEM_ERR); |
46e18b3f GB |
318 | |
319 | udata.handle = impl_handle; | |
320 | udata.proto = proto; | |
321 | (void) zfs_iter_root(impl_handle->zfs_libhandle, update_zfs_shares_cb, | |
322 | &udata); | |
323 | ||
a08ee875 | 324 | return (SA_OK); |
46e18b3f GB |
325 | } |
326 | ||
327 | static int | |
328 | process_share(sa_handle_impl_t impl_handle, sa_share_impl_t impl_share, | |
329 | char *pathname, char *resource, char *proto, | |
330 | char *options, char *description, char *dataset, | |
331 | boolean_t from_sharetab) | |
332 | { | |
333 | struct stat statbuf; | |
334 | int rc; | |
335 | char *resource_dup = NULL, *dataset_dup = NULL; | |
336 | boolean_t new_share; | |
337 | sa_fstype_t *fstype; | |
338 | ||
339 | new_share = B_FALSE; | |
340 | ||
341 | if (impl_share == NULL) | |
342 | impl_share = find_share(impl_handle, pathname); | |
343 | ||
344 | if (impl_share == NULL) { | |
345 | if (lstat(pathname, &statbuf) != 0 || | |
346 | !S_ISDIR(statbuf.st_mode)) | |
a08ee875 | 347 | return (SA_BAD_PATH); |
46e18b3f GB |
348 | |
349 | impl_share = alloc_share(pathname); | |
350 | ||
351 | if (impl_share == NULL) { | |
352 | rc = SA_NO_MEMORY; | |
353 | goto err; | |
354 | } | |
355 | ||
356 | new_share = B_TRUE; | |
357 | } | |
358 | ||
359 | if (dataset != NULL) { | |
360 | dataset_dup = strdup(dataset); | |
361 | ||
362 | if (dataset_dup == NULL) { | |
363 | rc = SA_NO_MEMORY; | |
364 | goto err; | |
365 | } | |
366 | } | |
367 | ||
368 | free(impl_share->dataset); | |
369 | impl_share->dataset = dataset_dup; | |
370 | ||
371 | rc = SA_INVALID_PROTOCOL; | |
372 | ||
373 | fstype = fstypes; | |
374 | while (fstype != NULL) { | |
375 | if (strcmp(fstype->name, proto) == 0) { | |
376 | if (resource != NULL) { | |
377 | resource_dup = strdup(resource); | |
378 | ||
379 | if (resource_dup == NULL) { | |
380 | rc = SA_NO_MEMORY; | |
381 | goto err; | |
382 | } | |
383 | } | |
384 | ||
385 | free(FSINFO(impl_share, fstype)->resource); | |
386 | FSINFO(impl_share, fstype)->resource = resource_dup; | |
387 | ||
388 | rc = fstype->ops->update_shareopts(impl_share, | |
389 | resource, options); | |
390 | ||
391 | if (rc == SA_OK && from_sharetab) | |
392 | FSINFO(impl_share, fstype)->active = B_TRUE; | |
393 | ||
394 | break; | |
395 | } | |
396 | ||
397 | fstype = fstype->next; | |
398 | } | |
399 | ||
400 | if (rc != SA_OK) | |
401 | goto err; | |
402 | ||
403 | if (new_share) { | |
404 | impl_share->handle = impl_handle; | |
405 | ||
406 | impl_share->next = impl_handle->shares; | |
407 | impl_handle->shares = impl_share; | |
408 | ||
409 | } | |
410 | ||
411 | err: | |
412 | if (rc != SA_OK) { | |
413 | if (new_share) | |
414 | free_share(impl_share); | |
415 | } | |
416 | ||
a08ee875 | 417 | return (rc); |
46e18b3f GB |
418 | } |
419 | ||
420 | void | |
421 | sa_fini(sa_handle_t handle) | |
422 | { | |
423 | sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle; | |
424 | sa_share_impl_t impl_share, next; | |
425 | sa_share_impl_t *pcurr; | |
426 | ||
427 | if (impl_handle == NULL) | |
428 | return; | |
429 | ||
430 | /* | |
431 | * clean up shares which don't have a non-NULL dataset property, | |
432 | * which means they're in sharetab but we couldn't find their | |
433 | * ZFS dataset. | |
434 | */ | |
435 | pcurr = &(impl_handle->shares); | |
436 | impl_share = *pcurr; | |
437 | while (impl_share != NULL) { | |
438 | next = impl_share->next; | |
439 | ||
440 | if (impl_share->dataset == NULL) { | |
441 | /* remove item from the linked list */ | |
442 | *pcurr = next; | |
443 | ||
444 | sa_disable_share(impl_share, NULL); | |
445 | ||
446 | free_share(impl_share); | |
447 | } else { | |
448 | pcurr = &(impl_share->next); | |
449 | } | |
450 | ||
451 | impl_share = next; | |
452 | } | |
453 | ||
454 | update_sharetab(impl_handle); | |
455 | ||
456 | if (impl_handle->zfs_libhandle != NULL) | |
457 | libzfs_fini(impl_handle->zfs_libhandle); | |
458 | ||
459 | impl_share = impl_handle->shares; | |
460 | while (impl_share != NULL) { | |
461 | next = impl_share->next; | |
462 | free_share(impl_share); | |
463 | impl_share = next; | |
464 | } | |
465 | ||
466 | free(impl_handle); | |
467 | } | |
468 | ||
469 | static sa_share_impl_t | |
470 | find_share(sa_handle_impl_t impl_handle, const char *sharepath) | |
471 | { | |
472 | sa_share_impl_t impl_share; | |
473 | ||
474 | impl_share = impl_handle->shares; | |
475 | while (impl_share != NULL) { | |
476 | if (strcmp(impl_share->sharepath, sharepath) == 0) { | |
477 | break; | |
478 | } | |
479 | ||
480 | impl_share = impl_share->next; | |
481 | } | |
482 | ||
a08ee875 | 483 | return (impl_share); |
46e18b3f GB |
484 | } |
485 | ||
486 | sa_share_t | |
487 | sa_find_share(sa_handle_t handle, char *sharepath) | |
488 | { | |
a08ee875 | 489 | return ((sa_share_t)find_share((sa_handle_impl_t)handle, sharepath)); |
46e18b3f GB |
490 | } |
491 | ||
492 | int | |
493 | sa_enable_share(sa_share_t share, char *protocol) | |
494 | { | |
495 | sa_share_impl_t impl_share = (sa_share_impl_t)share; | |
047218e2 AX |
496 | int rc, ret = SA_OK; |
497 | boolean_t found_protocol = B_FALSE; | |
46e18b3f GB |
498 | sa_fstype_t *fstype; |
499 | ||
46e18b3f GB |
500 | fstype = fstypes; |
501 | while (fstype != NULL) { | |
502 | if (protocol == NULL || strcmp(fstype->name, protocol) == 0) { | |
503 | update_zfs_share(impl_share, fstype->name); | |
504 | ||
505 | rc = fstype->ops->enable_share(impl_share); | |
506 | ||
507 | if (rc != SA_OK) | |
508 | ret = rc; | |
509 | else | |
510 | FSINFO(impl_share, fstype)->active = B_TRUE; | |
511 | ||
512 | found_protocol = B_TRUE; | |
513 | } | |
514 | ||
515 | fstype = fstype->next; | |
516 | } | |
517 | ||
518 | update_sharetab(impl_share->handle); | |
519 | ||
520 | return (found_protocol ? ret : SA_INVALID_PROTOCOL); | |
521 | } | |
522 | ||
523 | int | |
524 | sa_disable_share(sa_share_t share, char *protocol) | |
525 | { | |
526 | sa_share_impl_t impl_share = (sa_share_impl_t)share; | |
047218e2 AX |
527 | int rc, ret = SA_OK; |
528 | boolean_t found_protocol = B_FALSE; | |
46e18b3f GB |
529 | sa_fstype_t *fstype; |
530 | ||
46e18b3f GB |
531 | fstype = fstypes; |
532 | while (fstype != NULL) { | |
533 | if (protocol == NULL || strcmp(fstype->name, protocol) == 0) { | |
534 | rc = fstype->ops->disable_share(impl_share); | |
535 | ||
536 | if (rc == SA_OK) { | |
537 | fstype->ops->clear_shareopts(impl_share); | |
538 | ||
539 | FSINFO(impl_share, fstype)->active = B_FALSE; | |
540 | } else | |
541 | ret = rc; | |
542 | ||
543 | found_protocol = B_TRUE; | |
544 | } | |
545 | ||
546 | fstype = fstype->next; | |
547 | } | |
548 | ||
549 | update_sharetab(impl_share->handle); | |
550 | ||
551 | return (found_protocol ? ret : SA_INVALID_PROTOCOL); | |
552 | } | |
553 | ||
554 | /* | |
555 | * sa_errorstr(err) | |
556 | * | |
557 | * convert an error value to an error string | |
558 | */ | |
559 | char * | |
560 | sa_errorstr(int err) | |
561 | { | |
562 | static char errstr[32]; | |
563 | char *ret = NULL; | |
564 | ||
565 | switch (err) { | |
566 | case SA_OK: | |
567 | ret = dgettext(TEXT_DOMAIN, "ok"); | |
568 | break; | |
569 | case SA_NO_SUCH_PATH: | |
570 | ret = dgettext(TEXT_DOMAIN, "path doesn't exist"); | |
571 | break; | |
572 | case SA_NO_MEMORY: | |
573 | ret = dgettext(TEXT_DOMAIN, "no memory"); | |
574 | break; | |
575 | case SA_DUPLICATE_NAME: | |
576 | ret = dgettext(TEXT_DOMAIN, "name in use"); | |
577 | break; | |
578 | case SA_BAD_PATH: | |
579 | ret = dgettext(TEXT_DOMAIN, "bad path"); | |
580 | break; | |
581 | case SA_NO_SUCH_GROUP: | |
582 | ret = dgettext(TEXT_DOMAIN, "no such group"); | |
583 | break; | |
584 | case SA_CONFIG_ERR: | |
585 | ret = dgettext(TEXT_DOMAIN, "configuration error"); | |
586 | break; | |
587 | case SA_SYSTEM_ERR: | |
588 | ret = dgettext(TEXT_DOMAIN, "system error"); | |
589 | break; | |
590 | case SA_SYNTAX_ERR: | |
591 | ret = dgettext(TEXT_DOMAIN, "syntax error"); | |
592 | break; | |
593 | case SA_NO_PERMISSION: | |
594 | ret = dgettext(TEXT_DOMAIN, "no permission"); | |
595 | break; | |
596 | case SA_BUSY: | |
597 | ret = dgettext(TEXT_DOMAIN, "busy"); | |
598 | break; | |
599 | case SA_NO_SUCH_PROP: | |
600 | ret = dgettext(TEXT_DOMAIN, "no such property"); | |
601 | break; | |
602 | case SA_INVALID_NAME: | |
603 | ret = dgettext(TEXT_DOMAIN, "invalid name"); | |
604 | break; | |
605 | case SA_INVALID_PROTOCOL: | |
606 | ret = dgettext(TEXT_DOMAIN, "invalid protocol"); | |
607 | break; | |
608 | case SA_NOT_ALLOWED: | |
609 | ret = dgettext(TEXT_DOMAIN, "operation not allowed"); | |
610 | break; | |
611 | case SA_BAD_VALUE: | |
612 | ret = dgettext(TEXT_DOMAIN, "bad property value"); | |
613 | break; | |
614 | case SA_INVALID_SECURITY: | |
615 | ret = dgettext(TEXT_DOMAIN, "invalid security type"); | |
616 | break; | |
617 | case SA_NO_SUCH_SECURITY: | |
618 | ret = dgettext(TEXT_DOMAIN, "security type not found"); | |
619 | break; | |
620 | case SA_VALUE_CONFLICT: | |
621 | ret = dgettext(TEXT_DOMAIN, "property value conflict"); | |
622 | break; | |
623 | case SA_NOT_IMPLEMENTED: | |
624 | ret = dgettext(TEXT_DOMAIN, "not implemented"); | |
625 | break; | |
626 | case SA_INVALID_PATH: | |
627 | ret = dgettext(TEXT_DOMAIN, "invalid path"); | |
628 | break; | |
629 | case SA_NOT_SUPPORTED: | |
630 | ret = dgettext(TEXT_DOMAIN, "operation not supported"); | |
631 | break; | |
632 | case SA_PROP_SHARE_ONLY: | |
633 | ret = dgettext(TEXT_DOMAIN, "property not valid for group"); | |
634 | break; | |
635 | case SA_NOT_SHARED: | |
636 | ret = dgettext(TEXT_DOMAIN, "not shared"); | |
637 | break; | |
638 | case SA_NO_SUCH_RESOURCE: | |
639 | ret = dgettext(TEXT_DOMAIN, "no such resource"); | |
640 | break; | |
641 | case SA_RESOURCE_REQUIRED: | |
642 | ret = dgettext(TEXT_DOMAIN, "resource name required"); | |
643 | break; | |
644 | case SA_MULTIPLE_ERROR: | |
645 | ret = dgettext(TEXT_DOMAIN, "errors from multiple protocols"); | |
646 | break; | |
647 | case SA_PATH_IS_SUBDIR: | |
648 | ret = dgettext(TEXT_DOMAIN, "path is a subpath of share"); | |
649 | break; | |
650 | case SA_PATH_IS_PARENTDIR: | |
651 | ret = dgettext(TEXT_DOMAIN, "path is parent of a share"); | |
652 | break; | |
653 | case SA_NO_SECTION: | |
654 | ret = dgettext(TEXT_DOMAIN, "protocol requires a section"); | |
655 | break; | |
656 | case SA_NO_PROPERTIES: | |
657 | ret = dgettext(TEXT_DOMAIN, "properties not found"); | |
658 | break; | |
659 | case SA_NO_SUCH_SECTION: | |
660 | ret = dgettext(TEXT_DOMAIN, "section not found"); | |
661 | break; | |
662 | case SA_PASSWORD_ENC: | |
663 | ret = dgettext(TEXT_DOMAIN, "passwords must be encrypted"); | |
664 | break; | |
665 | case SA_SHARE_EXISTS: | |
666 | ret = dgettext(TEXT_DOMAIN, "path or file is already shared"); | |
667 | break; | |
668 | default: | |
669 | (void) snprintf(errstr, sizeof (errstr), | |
670 | dgettext(TEXT_DOMAIN, "unknown %d"), err); | |
671 | ret = errstr; | |
672 | } | |
673 | return (ret); | |
674 | } | |
675 | ||
676 | int | |
677 | sa_parse_legacy_options(sa_group_t group, char *options, char *proto) | |
678 | { | |
679 | sa_fstype_t *fstype; | |
680 | ||
46e18b3f GB |
681 | fstype = fstypes; |
682 | while (fstype != NULL) { | |
683 | if (strcmp(fstype->name, proto) != 0) { | |
684 | fstype = fstype->next; | |
685 | continue; | |
686 | } | |
687 | ||
a08ee875 | 688 | return (fstype->ops->validate_shareopts(options)); |
46e18b3f GB |
689 | } |
690 | ||
a08ee875 | 691 | return (SA_INVALID_PROTOCOL); |
46e18b3f GB |
692 | } |
693 | ||
694 | boolean_t | |
695 | sa_needs_refresh(sa_handle_t handle) | |
696 | { | |
a08ee875 | 697 | return (B_TRUE); |
46e18b3f GB |
698 | } |
699 | ||
700 | libzfs_handle_t * | |
701 | sa_get_zfs_handle(sa_handle_t handle) | |
702 | { | |
703 | sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle; | |
704 | ||
705 | if (impl_handle == NULL) | |
a08ee875 | 706 | return (NULL); |
46e18b3f | 707 | |
a08ee875 | 708 | return (impl_handle->zfs_libhandle); |
46e18b3f GB |
709 | } |
710 | ||
711 | static sa_share_impl_t | |
712 | alloc_share(const char *sharepath) | |
713 | { | |
714 | sa_share_impl_t impl_share; | |
715 | ||
716 | impl_share = calloc(sizeof (struct sa_share_impl), 1); | |
717 | ||
718 | if (impl_share == NULL) | |
a08ee875 | 719 | return (NULL); |
46e18b3f GB |
720 | |
721 | impl_share->sharepath = strdup(sharepath); | |
722 | ||
723 | if (impl_share->sharepath == NULL) { | |
724 | free(impl_share); | |
a08ee875 | 725 | return (NULL); |
46e18b3f GB |
726 | } |
727 | ||
728 | impl_share->fsinfo = calloc(sizeof (sa_share_fsinfo_t), fstypes_count); | |
729 | ||
730 | if (impl_share->fsinfo == NULL) { | |
731 | free(impl_share->sharepath); | |
732 | free(impl_share); | |
a08ee875 | 733 | return (NULL); |
46e18b3f GB |
734 | } |
735 | ||
a08ee875 | 736 | return (impl_share); |
46e18b3f GB |
737 | } |
738 | ||
739 | static void | |
cae5b340 AX |
740 | free_share(sa_share_impl_t impl_share) |
741 | { | |
46e18b3f GB |
742 | sa_fstype_t *fstype; |
743 | ||
744 | fstype = fstypes; | |
745 | while (fstype != NULL) { | |
746 | fstype->ops->clear_shareopts(impl_share); | |
747 | ||
748 | free(FSINFO(impl_share, fstype)->resource); | |
749 | ||
750 | fstype = fstype->next; | |
751 | } | |
752 | ||
753 | free(impl_share->sharepath); | |
754 | free(impl_share->dataset); | |
755 | free(impl_share->fsinfo); | |
756 | free(impl_share); | |
757 | } | |
758 | ||
759 | int | |
760 | sa_zfs_process_share(sa_handle_t handle, sa_group_t group, sa_share_t share, | |
761 | char *mountpoint, char *proto, zprop_source_t source, char *shareopts, | |
762 | char *sourcestr, char *dataset) | |
763 | { | |
764 | sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle; | |
765 | sa_share_impl_t impl_share = (sa_share_impl_t)share; | |
766 | ||
a08ee875 LG |
767 | return (process_share(impl_handle, impl_share, mountpoint, NULL, |
768 | proto, shareopts, NULL, dataset, B_FALSE)); | |
46e18b3f GB |
769 | } |
770 | ||
771 | void | |
772 | sa_update_sharetab_ts(sa_handle_t handle) | |
773 | { | |
774 | sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle; | |
775 | ||
776 | update_sharetab(impl_handle); | |
777 | } |