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.
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.
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]
23 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011 Gunnar Beutner
32 #include <sys/types.h>
37 #include "libshare_impl.h"
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
);
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
);
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
);
56 static int fstypes_count
;
57 static sa_fstype_t
*fstypes
;
60 register_fstype(const char *name
, const sa_share_ops_t
*ops
)
64 fstype
= calloc(sizeof (sa_fstype_t
), 1);
71 fstype
->fsinfo_index
= fstypes_count
;
75 fstype
->next
= fstypes
;
82 sa_init(int init_service
)
84 sa_handle_impl_t impl_handle
;
86 impl_handle
= calloc(sizeof (struct sa_handle_impl
), 1);
88 if (impl_handle
== NULL
)
91 impl_handle
->zfs_libhandle
= libzfs_init();
93 if (impl_handle
->zfs_libhandle
!= NULL
) {
94 libzfs_print_on_error(impl_handle
->zfs_libhandle
, B_TRUE
);
97 parse_sharetab(impl_handle
);
98 update_zfs_shares(impl_handle
, NULL
);
100 return ((sa_handle_t
)impl_handle
);
103 __attribute__((constructor
)) static void
110 * This bit causes /etc/dfs/sharetab to be updated before libzfs gets a
111 * chance to read that file; this is necessary because the sharetab file
112 * might be out of sync with the NFS kernel exports (e.g. due to reboots
113 * or users manually removing shares)
119 parse_sharetab(sa_handle_impl_t impl_handle
) {
122 char *eol
, *pathname
, *resource
, *fstype
, *options
, *description
;
124 fp
= fopen("/etc/dfs/sharetab", "r");
129 while (fgets(line
, sizeof (line
), fp
) != NULL
) {
130 eol
= line
+ strlen(line
) - 1;
132 while (eol
>= line
) {
133 if (*eol
!= '\r' && *eol
!= '\n')
142 if ((resource
= strchr(pathname
, '\t')) == NULL
)
148 if ((fstype
= strchr(resource
, '\t')) == NULL
)
154 if ((options
= strchr(fstype
, '\t')) == NULL
)
160 if ((description
= strchr(fstype
, '\t')) != NULL
) {
165 if (strcmp(resource
, "-") == 0)
168 (void) process_share(impl_handle
, NULL
, pathname
, resource
,
169 fstype
, options
, description
, NULL
, B_TRUE
);
176 update_sharetab(sa_handle_impl_t impl_handle
)
178 sa_share_impl_t impl_share
;
181 char tempfile
[] = "/etc/dfs/sharetab.XXXXXX";
183 const char *resource
;
185 if (mkdir("/etc/dfs", 0755) < 0 && errno
!= EEXIST
) {
189 temp_fd
= mkstemp(tempfile
);
194 temp_fp
= fdopen(temp_fd
, "w");
199 impl_share
= impl_handle
->shares
;
200 while (impl_share
!= NULL
) {
202 while (fstype
!= NULL
) {
203 if (FSINFO(impl_share
, fstype
)->active
&&
204 FSINFO(impl_share
, fstype
)->shareopts
!= NULL
) {
205 resource
= FSINFO(impl_share
, fstype
)->resource
;
207 if (resource
== NULL
)
210 fprintf(temp_fp
, "%s\t%s\t%s\t%s\n",
211 impl_share
->sharepath
, resource
,
213 FSINFO(impl_share
, fstype
)->shareopts
);
216 fstype
= fstype
->next
;
219 impl_share
= impl_share
->next
;
226 rename(tempfile
, "/etc/dfs/sharetab");
229 typedef struct update_cookie_s
{
230 sa_handle_impl_t handle
;
235 update_zfs_shares_cb(zfs_handle_t
*zhp
, void *pcookie
)
237 update_cookie_t
*udata
= (update_cookie_t
*)pcookie
;
238 char mountpoint
[ZFS_MAXPROPLEN
];
239 char shareopts
[ZFS_MAXPROPLEN
];
241 zfs_type_t type
= zfs_get_type(zhp
);
243 if (type
== ZFS_TYPE_FILESYSTEM
&&
244 zfs_iter_filesystems(zhp
, update_zfs_shares_cb
, pcookie
) != 0) {
249 if (type
!= ZFS_TYPE_FILESYSTEM
) {
254 if (zfs_prop_get(zhp
, ZFS_PROP_MOUNTPOINT
, mountpoint
,
255 sizeof (mountpoint
), NULL
, NULL
, 0, B_FALSE
) != 0) {
260 dataset
= (char *)zfs_get_name(zhp
);
262 if (dataset
== NULL
) {
267 if (!zfs_is_mounted(zhp
, NULL
)) {
272 if ((udata
->proto
== NULL
|| strcmp(udata
->proto
, "nfs") == 0) &&
273 zfs_prop_get(zhp
, ZFS_PROP_SHARENFS
, shareopts
,
274 sizeof (shareopts
), NULL
, NULL
, 0, B_FALSE
) == 0 &&
275 strcmp(shareopts
, "off") != 0) {
276 (void) process_share(udata
->handle
, NULL
, mountpoint
, NULL
,
277 "nfs", shareopts
, NULL
, dataset
, B_FALSE
);
280 if ((udata
->proto
== NULL
|| strcmp(udata
->proto
, "smb") == 0) &&
281 zfs_prop_get(zhp
, ZFS_PROP_SHARESMB
, shareopts
,
282 sizeof (shareopts
), NULL
, NULL
, 0, B_FALSE
) == 0 &&
283 strcmp(shareopts
, "off") != 0) {
284 (void) process_share(udata
->handle
, NULL
, mountpoint
, NULL
,
285 "smb", shareopts
, NULL
, dataset
, B_FALSE
);
294 update_zfs_share(sa_share_impl_t impl_share
, const char *proto
)
296 sa_handle_impl_t impl_handle
= impl_share
->handle
;
298 update_cookie_t udata
;
300 if (impl_handle
->zfs_libhandle
== NULL
)
301 return SA_SYSTEM_ERR
;
303 assert(impl_share
->dataset
!= NULL
);
305 zhp
= zfs_open(impl_share
->handle
->zfs_libhandle
, impl_share
->dataset
,
306 ZFS_TYPE_FILESYSTEM
);
309 return SA_SYSTEM_ERR
;
311 udata
.handle
= impl_handle
;
313 (void) update_zfs_shares_cb(zhp
, &udata
);
319 update_zfs_shares(sa_handle_impl_t impl_handle
, const char *proto
)
321 update_cookie_t udata
;
323 if (impl_handle
->zfs_libhandle
== NULL
)
324 return SA_SYSTEM_ERR
;
326 udata
.handle
= impl_handle
;
328 (void) zfs_iter_root(impl_handle
->zfs_libhandle
, update_zfs_shares_cb
,
335 process_share(sa_handle_impl_t impl_handle
, sa_share_impl_t impl_share
,
336 char *pathname
, char *resource
, char *proto
,
337 char *options
, char *description
, char *dataset
,
338 boolean_t from_sharetab
)
342 char *resource_dup
= NULL
, *dataset_dup
= NULL
;
348 if (impl_share
== NULL
)
349 impl_share
= find_share(impl_handle
, pathname
);
351 if (impl_share
== NULL
) {
352 if (lstat(pathname
, &statbuf
) != 0 ||
353 !S_ISDIR(statbuf
.st_mode
))
356 impl_share
= alloc_share(pathname
);
358 if (impl_share
== NULL
) {
366 if (dataset
!= NULL
) {
367 dataset_dup
= strdup(dataset
);
369 if (dataset_dup
== NULL
) {
375 free(impl_share
->dataset
);
376 impl_share
->dataset
= dataset_dup
;
378 rc
= SA_INVALID_PROTOCOL
;
381 while (fstype
!= NULL
) {
382 if (strcmp(fstype
->name
, proto
) == 0) {
383 if (resource
!= NULL
) {
384 resource_dup
= strdup(resource
);
386 if (resource_dup
== NULL
) {
392 free(FSINFO(impl_share
, fstype
)->resource
);
393 FSINFO(impl_share
, fstype
)->resource
= resource_dup
;
395 rc
= fstype
->ops
->update_shareopts(impl_share
,
398 if (rc
== SA_OK
&& from_sharetab
)
399 FSINFO(impl_share
, fstype
)->active
= B_TRUE
;
404 fstype
= fstype
->next
;
411 impl_share
->handle
= impl_handle
;
413 impl_share
->next
= impl_handle
->shares
;
414 impl_handle
->shares
= impl_share
;
421 free_share(impl_share
);
428 sa_fini(sa_handle_t handle
)
430 sa_handle_impl_t impl_handle
= (sa_handle_impl_t
)handle
;
431 sa_share_impl_t impl_share
, next
;
432 sa_share_impl_t
*pcurr
;
434 if (impl_handle
== NULL
)
438 * clean up shares which don't have a non-NULL dataset property,
439 * which means they're in sharetab but we couldn't find their
442 pcurr
= &(impl_handle
->shares
);
444 while (impl_share
!= NULL
) {
445 next
= impl_share
->next
;
447 if (impl_share
->dataset
== NULL
) {
448 /* remove item from the linked list */
451 sa_disable_share(impl_share
, NULL
);
453 free_share(impl_share
);
455 pcurr
= &(impl_share
->next
);
461 update_sharetab(impl_handle
);
463 if (impl_handle
->zfs_libhandle
!= NULL
)
464 libzfs_fini(impl_handle
->zfs_libhandle
);
466 impl_share
= impl_handle
->shares
;
467 while (impl_share
!= NULL
) {
468 next
= impl_share
->next
;
469 free_share(impl_share
);
476 static sa_share_impl_t
477 find_share(sa_handle_impl_t impl_handle
, const char *sharepath
)
479 sa_share_impl_t impl_share
;
481 impl_share
= impl_handle
->shares
;
482 while (impl_share
!= NULL
) {
483 if (strcmp(impl_share
->sharepath
, sharepath
) == 0) {
487 impl_share
= impl_share
->next
;
494 sa_find_share(sa_handle_t handle
, char *sharepath
)
496 return (sa_share_t
)find_share((sa_handle_impl_t
)handle
, sharepath
);
500 sa_enable_share(sa_share_t share
, char *protocol
)
502 sa_share_impl_t impl_share
= (sa_share_impl_t
)share
;
504 boolean_t found_protocol
;
508 fprintf(stderr
, "sa_enable_share: share->sharepath=%s, protocol=%s\n",
509 impl_share
->sharepath
, protocol
);
512 assert(impl_share
->handle
!= NULL
);
515 found_protocol
= B_FALSE
;
518 while (fstype
!= NULL
) {
519 if (protocol
== NULL
|| strcmp(fstype
->name
, protocol
) == 0) {
520 update_zfs_share(impl_share
, fstype
->name
);
522 rc
= fstype
->ops
->enable_share(impl_share
);
527 FSINFO(impl_share
, fstype
)->active
= B_TRUE
;
529 found_protocol
= B_TRUE
;
532 fstype
= fstype
->next
;
535 update_sharetab(impl_share
->handle
);
537 return (found_protocol
? ret
: SA_INVALID_PROTOCOL
);
541 sa_disable_share(sa_share_t share
, char *protocol
)
543 sa_share_impl_t impl_share
= (sa_share_impl_t
)share
;
545 boolean_t found_protocol
;
549 fprintf(stderr
, "sa_disable_share: share->sharepath=%s, protocol=%s\n",
550 impl_share
->sharepath
, protocol
);
554 found_protocol
= B_FALSE
;
557 while (fstype
!= NULL
) {
558 if (protocol
== NULL
|| strcmp(fstype
->name
, protocol
) == 0) {
559 rc
= fstype
->ops
->disable_share(impl_share
);
562 fstype
->ops
->clear_shareopts(impl_share
);
564 FSINFO(impl_share
, fstype
)->active
= B_FALSE
;
568 found_protocol
= B_TRUE
;
571 fstype
= fstype
->next
;
574 update_sharetab(impl_share
->handle
);
576 return (found_protocol
? ret
: SA_INVALID_PROTOCOL
);
582 * convert an error value to an error string
587 static char errstr
[32];
592 ret
= dgettext(TEXT_DOMAIN
, "ok");
594 case SA_NO_SUCH_PATH
:
595 ret
= dgettext(TEXT_DOMAIN
, "path doesn't exist");
598 ret
= dgettext(TEXT_DOMAIN
, "no memory");
600 case SA_DUPLICATE_NAME
:
601 ret
= dgettext(TEXT_DOMAIN
, "name in use");
604 ret
= dgettext(TEXT_DOMAIN
, "bad path");
606 case SA_NO_SUCH_GROUP
:
607 ret
= dgettext(TEXT_DOMAIN
, "no such group");
610 ret
= dgettext(TEXT_DOMAIN
, "configuration error");
613 ret
= dgettext(TEXT_DOMAIN
, "system error");
616 ret
= dgettext(TEXT_DOMAIN
, "syntax error");
618 case SA_NO_PERMISSION
:
619 ret
= dgettext(TEXT_DOMAIN
, "no permission");
622 ret
= dgettext(TEXT_DOMAIN
, "busy");
624 case SA_NO_SUCH_PROP
:
625 ret
= dgettext(TEXT_DOMAIN
, "no such property");
627 case SA_INVALID_NAME
:
628 ret
= dgettext(TEXT_DOMAIN
, "invalid name");
630 case SA_INVALID_PROTOCOL
:
631 ret
= dgettext(TEXT_DOMAIN
, "invalid protocol");
634 ret
= dgettext(TEXT_DOMAIN
, "operation not allowed");
637 ret
= dgettext(TEXT_DOMAIN
, "bad property value");
639 case SA_INVALID_SECURITY
:
640 ret
= dgettext(TEXT_DOMAIN
, "invalid security type");
642 case SA_NO_SUCH_SECURITY
:
643 ret
= dgettext(TEXT_DOMAIN
, "security type not found");
645 case SA_VALUE_CONFLICT
:
646 ret
= dgettext(TEXT_DOMAIN
, "property value conflict");
648 case SA_NOT_IMPLEMENTED
:
649 ret
= dgettext(TEXT_DOMAIN
, "not implemented");
651 case SA_INVALID_PATH
:
652 ret
= dgettext(TEXT_DOMAIN
, "invalid path");
654 case SA_NOT_SUPPORTED
:
655 ret
= dgettext(TEXT_DOMAIN
, "operation not supported");
657 case SA_PROP_SHARE_ONLY
:
658 ret
= dgettext(TEXT_DOMAIN
, "property not valid for group");
661 ret
= dgettext(TEXT_DOMAIN
, "not shared");
663 case SA_NO_SUCH_RESOURCE
:
664 ret
= dgettext(TEXT_DOMAIN
, "no such resource");
666 case SA_RESOURCE_REQUIRED
:
667 ret
= dgettext(TEXT_DOMAIN
, "resource name required");
669 case SA_MULTIPLE_ERROR
:
670 ret
= dgettext(TEXT_DOMAIN
, "errors from multiple protocols");
672 case SA_PATH_IS_SUBDIR
:
673 ret
= dgettext(TEXT_DOMAIN
, "path is a subpath of share");
675 case SA_PATH_IS_PARENTDIR
:
676 ret
= dgettext(TEXT_DOMAIN
, "path is parent of a share");
679 ret
= dgettext(TEXT_DOMAIN
, "protocol requires a section");
681 case SA_NO_PROPERTIES
:
682 ret
= dgettext(TEXT_DOMAIN
, "properties not found");
684 case SA_NO_SUCH_SECTION
:
685 ret
= dgettext(TEXT_DOMAIN
, "section not found");
687 case SA_PASSWORD_ENC
:
688 ret
= dgettext(TEXT_DOMAIN
, "passwords must be encrypted");
690 case SA_SHARE_EXISTS
:
691 ret
= dgettext(TEXT_DOMAIN
, "path or file is already shared");
694 (void) snprintf(errstr
, sizeof (errstr
),
695 dgettext(TEXT_DOMAIN
, "unknown %d"), err
);
702 sa_parse_legacy_options(sa_group_t group
, char *options
, char *proto
)
707 fprintf(stderr
, "sa_parse_legacy_options: options=%s, proto=%s\n",
712 while (fstype
!= NULL
) {
713 if (strcmp(fstype
->name
, proto
) != 0) {
714 fstype
= fstype
->next
;
718 return fstype
->ops
->validate_shareopts(options
);
721 return SA_INVALID_PROTOCOL
;
725 sa_needs_refresh(sa_handle_t handle
)
731 sa_get_zfs_handle(sa_handle_t handle
)
733 sa_handle_impl_t impl_handle
= (sa_handle_impl_t
)handle
;
735 if (impl_handle
== NULL
)
738 return impl_handle
->zfs_libhandle
;
741 static sa_share_impl_t
742 alloc_share(const char *sharepath
)
744 sa_share_impl_t impl_share
;
746 impl_share
= calloc(sizeof (struct sa_share_impl
), 1);
748 if (impl_share
== NULL
)
751 impl_share
->sharepath
= strdup(sharepath
);
753 if (impl_share
->sharepath
== NULL
) {
758 impl_share
->fsinfo
= calloc(sizeof (sa_share_fsinfo_t
), fstypes_count
);
760 if (impl_share
->fsinfo
== NULL
) {
761 free(impl_share
->sharepath
);
770 free_share(sa_share_impl_t impl_share
) {
774 while (fstype
!= NULL
) {
775 fstype
->ops
->clear_shareopts(impl_share
);
777 free(FSINFO(impl_share
, fstype
)->resource
);
779 fstype
= fstype
->next
;
782 free(impl_share
->sharepath
);
783 free(impl_share
->dataset
);
784 free(impl_share
->fsinfo
);
789 sa_zfs_process_share(sa_handle_t handle
, sa_group_t group
, sa_share_t share
,
790 char *mountpoint
, char *proto
, zprop_source_t source
, char *shareopts
,
791 char *sourcestr
, char *dataset
)
793 sa_handle_impl_t impl_handle
= (sa_handle_impl_t
)handle
;
794 sa_share_impl_t impl_share
= (sa_share_impl_t
)share
;
797 fprintf(stderr
, "sa_zfs_process_share: mountpoint=%s, proto=%s, "
798 "shareopts=%s, sourcestr=%s, dataset=%s\n", mountpoint
, proto
,
799 shareopts
, sourcestr
, dataset
);
802 return process_share(impl_handle
, impl_share
, mountpoint
, NULL
,
803 proto
, shareopts
, NULL
, dataset
, B_FALSE
);
807 sa_update_sharetab_ts(sa_handle_t handle
)
809 sa_handle_impl_t impl_handle
= (sa_handle_impl_t
)handle
;
811 update_sharetab(impl_handle
);