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
111 parse_sharetab(sa_handle_impl_t impl_handle
)
115 char *eol
, *pathname
, *resource
, *fstype
, *options
, *description
;
117 fp
= fopen(ZFS_SHARETAB
, "r");
122 while (fgets(line
, sizeof (line
), fp
) != NULL
) {
123 eol
= line
+ strlen(line
) - 1;
125 while (eol
>= line
) {
126 if (*eol
!= '\r' && *eol
!= '\n')
135 if ((resource
= strchr(pathname
, '\t')) == NULL
)
141 if ((fstype
= strchr(resource
, '\t')) == NULL
)
147 if ((options
= strchr(fstype
, '\t')) == NULL
)
153 if ((description
= strchr(fstype
, '\t')) != NULL
) {
158 if (strcmp(resource
, "-") == 0)
161 (void) process_share(impl_handle
, NULL
, pathname
, resource
,
162 fstype
, options
, description
, NULL
, B_TRUE
);
169 update_sharetab(sa_handle_impl_t impl_handle
)
171 sa_share_impl_t impl_share
;
174 char tempfile
[] = ZFS_SHARETAB
".XXXXXX";
176 const char *resource
;
178 if (mkdir("/etc/dfs", 0755) < 0 && errno
!= EEXIST
) {
182 temp_fd
= mkstemp(tempfile
);
187 temp_fp
= fdopen(temp_fd
, "w");
192 impl_share
= impl_handle
->shares
;
193 while (impl_share
!= NULL
) {
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
;
200 if (resource
== NULL
)
203 fprintf(temp_fp
, "%s\t%s\t%s\t%s\n",
204 impl_share
->sharepath
, resource
,
206 FSINFO(impl_share
, fstype
)->shareopts
);
209 fstype
= fstype
->next
;
212 impl_share
= impl_share
->next
;
219 (void) rename(tempfile
, ZFS_SHARETAB
);
222 typedef struct update_cookie_s
{
223 sa_handle_impl_t handle
;
228 update_zfs_shares_cb(zfs_handle_t
*zhp
, void *pcookie
)
230 update_cookie_t
*udata
= (update_cookie_t
*)pcookie
;
231 char mountpoint
[ZFS_MAXPROPLEN
];
232 char shareopts
[ZFS_MAXPROPLEN
];
234 zfs_type_t type
= zfs_get_type(zhp
);
236 if (type
== ZFS_TYPE_FILESYSTEM
&&
237 zfs_iter_filesystems(zhp
, update_zfs_shares_cb
, pcookie
) != 0) {
242 if (type
!= ZFS_TYPE_FILESYSTEM
) {
247 if (zfs_prop_get(zhp
, ZFS_PROP_MOUNTPOINT
, mountpoint
,
248 sizeof (mountpoint
), NULL
, NULL
, 0, B_FALSE
) != 0) {
253 dataset
= (char *)zfs_get_name(zhp
);
255 if (dataset
== NULL
) {
260 if (!zfs_is_mounted(zhp
, NULL
)) {
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
);
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
);
287 update_zfs_share(sa_share_impl_t impl_share
, const char *proto
)
289 sa_handle_impl_t impl_handle
= impl_share
->handle
;
291 update_cookie_t udata
;
293 if (impl_handle
->zfs_libhandle
== NULL
)
294 return (SA_SYSTEM_ERR
);
296 assert(impl_share
->dataset
!= NULL
);
298 zhp
= zfs_open(impl_share
->handle
->zfs_libhandle
, impl_share
->dataset
,
299 ZFS_TYPE_FILESYSTEM
);
302 return (SA_SYSTEM_ERR
);
304 udata
.handle
= impl_handle
;
306 (void) update_zfs_shares_cb(zhp
, &udata
);
312 update_zfs_shares(sa_handle_impl_t impl_handle
, const char *proto
)
314 update_cookie_t udata
;
316 if (impl_handle
->zfs_libhandle
== NULL
)
317 return (SA_SYSTEM_ERR
);
319 udata
.handle
= impl_handle
;
321 (void) zfs_iter_root(impl_handle
->zfs_libhandle
, update_zfs_shares_cb
,
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
)
335 char *resource_dup
= NULL
, *dataset_dup
= NULL
;
341 if (impl_share
== NULL
)
342 impl_share
= find_share(impl_handle
, pathname
);
344 if (impl_share
== NULL
) {
345 if (lstat(pathname
, &statbuf
) != 0 ||
346 !S_ISDIR(statbuf
.st_mode
))
347 return (SA_BAD_PATH
);
349 impl_share
= alloc_share(pathname
);
351 if (impl_share
== NULL
) {
359 if (dataset
!= NULL
) {
360 dataset_dup
= strdup(dataset
);
362 if (dataset_dup
== NULL
) {
368 free(impl_share
->dataset
);
369 impl_share
->dataset
= dataset_dup
;
371 rc
= SA_INVALID_PROTOCOL
;
374 while (fstype
!= NULL
) {
375 if (strcmp(fstype
->name
, proto
) == 0) {
376 if (resource
!= NULL
) {
377 resource_dup
= strdup(resource
);
379 if (resource_dup
== NULL
) {
385 free(FSINFO(impl_share
, fstype
)->resource
);
386 FSINFO(impl_share
, fstype
)->resource
= resource_dup
;
388 rc
= fstype
->ops
->update_shareopts(impl_share
,
391 if (rc
== SA_OK
&& from_sharetab
)
392 FSINFO(impl_share
, fstype
)->active
= B_TRUE
;
397 fstype
= fstype
->next
;
404 impl_share
->handle
= impl_handle
;
406 impl_share
->next
= impl_handle
->shares
;
407 impl_handle
->shares
= impl_share
;
414 free_share(impl_share
);
421 sa_fini(sa_handle_t handle
)
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
;
427 if (impl_handle
== NULL
)
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
435 pcurr
= &(impl_handle
->shares
);
437 while (impl_share
!= NULL
) {
438 next
= impl_share
->next
;
440 if (impl_share
->dataset
== NULL
) {
441 /* remove item from the linked list */
444 sa_disable_share(impl_share
, NULL
);
446 free_share(impl_share
);
448 pcurr
= &(impl_share
->next
);
454 update_sharetab(impl_handle
);
456 if (impl_handle
->zfs_libhandle
!= NULL
)
457 libzfs_fini(impl_handle
->zfs_libhandle
);
459 impl_share
= impl_handle
->shares
;
460 while (impl_share
!= NULL
) {
461 next
= impl_share
->next
;
462 free_share(impl_share
);
469 static sa_share_impl_t
470 find_share(sa_handle_impl_t impl_handle
, const char *sharepath
)
472 sa_share_impl_t impl_share
;
474 impl_share
= impl_handle
->shares
;
475 while (impl_share
!= NULL
) {
476 if (strcmp(impl_share
->sharepath
, sharepath
) == 0) {
480 impl_share
= impl_share
->next
;
487 sa_find_share(sa_handle_t handle
, char *sharepath
)
489 return ((sa_share_t
)find_share((sa_handle_impl_t
)handle
, sharepath
));
493 sa_enable_share(sa_share_t share
, char *protocol
)
495 sa_share_impl_t impl_share
= (sa_share_impl_t
)share
;
497 boolean_t found_protocol
= B_FALSE
;
501 while (fstype
!= NULL
) {
502 if (protocol
== NULL
|| strcmp(fstype
->name
, protocol
) == 0) {
503 update_zfs_share(impl_share
, fstype
->name
);
505 rc
= fstype
->ops
->enable_share(impl_share
);
510 FSINFO(impl_share
, fstype
)->active
= B_TRUE
;
512 found_protocol
= B_TRUE
;
515 fstype
= fstype
->next
;
518 update_sharetab(impl_share
->handle
);
520 return (found_protocol
? ret
: SA_INVALID_PROTOCOL
);
524 sa_disable_share(sa_share_t share
, char *protocol
)
526 sa_share_impl_t impl_share
= (sa_share_impl_t
)share
;
528 boolean_t found_protocol
= B_FALSE
;
532 while (fstype
!= NULL
) {
533 if (protocol
== NULL
|| strcmp(fstype
->name
, protocol
) == 0) {
534 rc
= fstype
->ops
->disable_share(impl_share
);
537 fstype
->ops
->clear_shareopts(impl_share
);
539 FSINFO(impl_share
, fstype
)->active
= B_FALSE
;
543 found_protocol
= B_TRUE
;
546 fstype
= fstype
->next
;
549 update_sharetab(impl_share
->handle
);
551 return (found_protocol
? ret
: SA_INVALID_PROTOCOL
);
557 * convert an error value to an error string
562 static char errstr
[32];
567 ret
= dgettext(TEXT_DOMAIN
, "ok");
569 case SA_NO_SUCH_PATH
:
570 ret
= dgettext(TEXT_DOMAIN
, "path doesn't exist");
573 ret
= dgettext(TEXT_DOMAIN
, "no memory");
575 case SA_DUPLICATE_NAME
:
576 ret
= dgettext(TEXT_DOMAIN
, "name in use");
579 ret
= dgettext(TEXT_DOMAIN
, "bad path");
581 case SA_NO_SUCH_GROUP
:
582 ret
= dgettext(TEXT_DOMAIN
, "no such group");
585 ret
= dgettext(TEXT_DOMAIN
, "configuration error");
588 ret
= dgettext(TEXT_DOMAIN
, "system error");
591 ret
= dgettext(TEXT_DOMAIN
, "syntax error");
593 case SA_NO_PERMISSION
:
594 ret
= dgettext(TEXT_DOMAIN
, "no permission");
597 ret
= dgettext(TEXT_DOMAIN
, "busy");
599 case SA_NO_SUCH_PROP
:
600 ret
= dgettext(TEXT_DOMAIN
, "no such property");
602 case SA_INVALID_NAME
:
603 ret
= dgettext(TEXT_DOMAIN
, "invalid name");
605 case SA_INVALID_PROTOCOL
:
606 ret
= dgettext(TEXT_DOMAIN
, "invalid protocol");
609 ret
= dgettext(TEXT_DOMAIN
, "operation not allowed");
612 ret
= dgettext(TEXT_DOMAIN
, "bad property value");
614 case SA_INVALID_SECURITY
:
615 ret
= dgettext(TEXT_DOMAIN
, "invalid security type");
617 case SA_NO_SUCH_SECURITY
:
618 ret
= dgettext(TEXT_DOMAIN
, "security type not found");
620 case SA_VALUE_CONFLICT
:
621 ret
= dgettext(TEXT_DOMAIN
, "property value conflict");
623 case SA_NOT_IMPLEMENTED
:
624 ret
= dgettext(TEXT_DOMAIN
, "not implemented");
626 case SA_INVALID_PATH
:
627 ret
= dgettext(TEXT_DOMAIN
, "invalid path");
629 case SA_NOT_SUPPORTED
:
630 ret
= dgettext(TEXT_DOMAIN
, "operation not supported");
632 case SA_PROP_SHARE_ONLY
:
633 ret
= dgettext(TEXT_DOMAIN
, "property not valid for group");
636 ret
= dgettext(TEXT_DOMAIN
, "not shared");
638 case SA_NO_SUCH_RESOURCE
:
639 ret
= dgettext(TEXT_DOMAIN
, "no such resource");
641 case SA_RESOURCE_REQUIRED
:
642 ret
= dgettext(TEXT_DOMAIN
, "resource name required");
644 case SA_MULTIPLE_ERROR
:
645 ret
= dgettext(TEXT_DOMAIN
, "errors from multiple protocols");
647 case SA_PATH_IS_SUBDIR
:
648 ret
= dgettext(TEXT_DOMAIN
, "path is a subpath of share");
650 case SA_PATH_IS_PARENTDIR
:
651 ret
= dgettext(TEXT_DOMAIN
, "path is parent of a share");
654 ret
= dgettext(TEXT_DOMAIN
, "protocol requires a section");
656 case SA_NO_PROPERTIES
:
657 ret
= dgettext(TEXT_DOMAIN
, "properties not found");
659 case SA_NO_SUCH_SECTION
:
660 ret
= dgettext(TEXT_DOMAIN
, "section not found");
662 case SA_PASSWORD_ENC
:
663 ret
= dgettext(TEXT_DOMAIN
, "passwords must be encrypted");
665 case SA_SHARE_EXISTS
:
666 ret
= dgettext(TEXT_DOMAIN
, "path or file is already shared");
669 (void) snprintf(errstr
, sizeof (errstr
),
670 dgettext(TEXT_DOMAIN
, "unknown %d"), err
);
677 sa_parse_legacy_options(sa_group_t group
, char *options
, char *proto
)
682 while (fstype
!= NULL
) {
683 if (strcmp(fstype
->name
, proto
) != 0) {
684 fstype
= fstype
->next
;
688 return (fstype
->ops
->validate_shareopts(options
));
691 return (SA_INVALID_PROTOCOL
);
695 sa_needs_refresh(sa_handle_t handle
)
701 sa_get_zfs_handle(sa_handle_t handle
)
703 sa_handle_impl_t impl_handle
= (sa_handle_impl_t
)handle
;
705 if (impl_handle
== NULL
)
708 return (impl_handle
->zfs_libhandle
);
711 static sa_share_impl_t
712 alloc_share(const char *sharepath
)
714 sa_share_impl_t impl_share
;
716 impl_share
= calloc(sizeof (struct sa_share_impl
), 1);
718 if (impl_share
== NULL
)
721 impl_share
->sharepath
= strdup(sharepath
);
723 if (impl_share
->sharepath
== NULL
) {
728 impl_share
->fsinfo
= calloc(sizeof (sa_share_fsinfo_t
), fstypes_count
);
730 if (impl_share
->fsinfo
== NULL
) {
731 free(impl_share
->sharepath
);
740 free_share(sa_share_impl_t impl_share
)
745 while (fstype
!= NULL
) {
746 fstype
->ops
->clear_shareopts(impl_share
);
748 free(FSINFO(impl_share
, fstype
)->resource
);
750 fstype
= fstype
->next
;
753 free(impl_share
->sharepath
);
754 free(impl_share
->dataset
);
755 free(impl_share
->fsinfo
);
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
)
764 sa_handle_impl_t impl_handle
= (sa_handle_impl_t
)handle
;
765 sa_share_impl_t impl_share
= (sa_share_impl_t
)share
;
767 return (process_share(impl_handle
, impl_share
, mountpoint
, NULL
,
768 proto
, shareopts
, NULL
, dataset
, B_FALSE
));
772 sa_update_sharetab_ts(sa_handle_t handle
)
774 sa_handle_impl_t impl_handle
= (sa_handle_impl_t
)handle
;
776 update_sharetab(impl_handle
);