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 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2012 Milan Jurik. All rights reserved.
28 #include <sys/types.h>
39 #include <auth_attr.h>
41 #include <sys/param.h>
48 #include <libxml/tree.h>
55 static char *sa_get_usage(sa_usage_t
);
58 * Implementation of the common sub-commands supported by sharemgr.
59 * A number of helper functions are also included.
63 * has_protocol(group, proto)
64 * If the group has an optionset with the specified protocol,
65 * return true (1) otherwise false (0).
68 has_protocol(sa_group_t group
, char *protocol
)
70 sa_optionset_t optionset
;
73 optionset
= sa_get_optionset(group
, protocol
);
74 if (optionset
!= NULL
) {
83 * Check that name only has valid characters in it. The current valid
84 * set are the printable characters but not including:
85 * " / \ [ ] : | < > + ; , ? * = \t
86 * Note that space is included and there is a maximum length.
89 validresource(const char *name
)
98 if (len
== 0 || len
> SA_MAX_RESOURCE_NAME
)
101 if (strpbrk(name
, "\"/\\[]:|<>+;,?*=\t") != NULL
) {
105 for (cp
= name
; *cp
!= '\0'; cp
++)
113 * conv_to_utf8(input)
115 * Convert the input string to utf8 from the current locale. If the
116 * conversion fails, use the current locale, it is likely close
117 * enough. For example, the "C" locale is a subset of utf-8. The
118 * return value may be a new string or the original input string.
122 conv_to_utf8(char *input
)
126 char *output
= input
;
132 static int warned
= 0;
134 curlocale
= nl_langinfo(CODESET
);
135 if (curlocale
== NULL
)
137 cd
= iconv_open("UTF-8", curlocale
);
138 if (cd
!= NULL
&& cd
!= (iconv_t
)-1) {
139 size
= strlen(input
);
140 /* Assume worst case of characters expanding to 4 bytes. */
141 bytesleft
= size
* 4;
142 output
= calloc(bytesleft
, 1);
143 if (output
!= NULL
) {
145 /* inval can be modified on return */
146 osize
= iconv(cd
, (const char **)&inval
, &size
,
147 &outleft
, &bytesleft
);
148 if (osize
== (size_t)-1 || size
!= 0) {
153 /* Need to return something. */
156 (void) iconv_close(cd
);
159 (void) fprintf(stderr
,
160 gettext("Cannot convert to UTF-8 from %s\n"),
161 curlocale
? curlocale
: gettext("unknown"));
170 * Convert the input string from utf8 to current locale. If the
171 * conversion isn't supported, just use as is. The return value may be
172 * a new string or the original input string.
176 conv_from_utf8(char *input
)
179 char *output
= input
;
186 static int warned
= 0;
188 curlocale
= nl_langinfo(CODESET
);
189 if (curlocale
== NULL
)
191 cd
= iconv_open(curlocale
, "UTF-8");
192 if (cd
!= NULL
&& cd
!= (iconv_t
)-1) {
193 size
= strlen(input
);
194 /* Assume worst case of characters expanding to 4 bytes. */
195 bytesleft
= size
* 4;
196 output
= calloc(bytesleft
, 1);
197 if (output
!= NULL
) {
199 osize
= iconv(cd
, (const char **)&inval
, &size
,
200 &outleft
, &bytesleft
);
201 if (osize
== (size_t)-1 || size
!= 0)
204 /* Need to return something. */
207 (void) iconv_close(cd
);
210 (void) fprintf(stderr
,
211 gettext("Cannot convert to %s from UTF-8\n"),
212 curlocale
? curlocale
: gettext("unknown"));
219 * print_rsrc_desc(resource, sharedesc)
221 * Print the resource description string after converting from UTF8 to
222 * the current locale. If sharedesc is not NULL and there is no
223 * description on the resource, use sharedesc. sharedesc will already
224 * be converted to UTF8.
228 print_rsrc_desc(sa_resource_t resource
, char *sharedesc
)
233 if (resource
== NULL
)
236 description
= sa_get_resource_description(resource
);
237 if (description
!= NULL
) {
238 desc
= conv_from_utf8(description
);
239 if (desc
!= description
) {
240 sa_free_share_description(description
);
243 } else if (sharedesc
!= NULL
) {
244 description
= strdup(sharedesc
);
246 if (description
!= NULL
) {
247 (void) printf("\t\"%s\"", description
);
248 sa_free_share_description(description
);
253 * set_resource_desc(share, description)
255 * Set the share description value after converting the description
256 * string to UTF8 from the current locale.
260 set_resource_desc(sa_share_t share
, char *description
)
265 desc
= conv_to_utf8(description
);
266 ret
= sa_set_resource_description(share
, desc
);
267 if (description
!= desc
)
268 sa_free_share_description(desc
);
273 * set_share_desc(share, description)
275 * Set the resource description value after converting the description
276 * string to UTF8 from the current locale.
280 set_share_desc(sa_share_t share
, char *description
)
285 desc
= conv_to_utf8(description
);
286 ret
= sa_set_share_description(share
, desc
);
287 if (description
!= desc
)
288 sa_free_share_description(desc
);
293 * add_list(list, item, data, proto)
294 * Adds a new list member that points holds item in the list.
295 * If list is NULL, it starts a new list. The function returns
296 * the first member of the list.
299 add_list(struct list
*listp
, void *item
, void *data
, char *proto
)
301 struct list
*new, *tmp
;
303 new = malloc(sizeof (struct list
));
307 new->itemdata
= data
;
316 for (tmp
= listp
; tmp
->next
!= NULL
; tmp
= tmp
->next
) {
317 /* get to end of list */
325 * Given a list, free all the members of the list;
328 free_list(struct list
*listp
)
331 while (listp
!= NULL
) {
339 * check_authorization(instname, which)
341 * Checks to see if the specific type of authorization in which is
342 * enabled for the user in this SMF service instance.
346 check_authorization(char *instname
, int which
)
348 scf_handle_t
*handle
= NULL
;
349 scf_simple_prop_t
*prop
= NULL
;
350 char svcstring
[SA_MAX_NAME_LEN
+ sizeof (SA_SVC_FMRI_BASE
) + 1];
351 char *authstr
= NULL
;
355 struct passwd
*pw
= NULL
;
363 * Since names are restricted to SA_MAX_NAME_LEN won't
366 (void) snprintf(svcstring
, sizeof (svcstring
), "%s:%s",
367 SA_SVC_FMRI_BASE
, instname
);
368 handle
= scf_handle_create(SCF_VERSION
);
369 if (handle
!= NULL
) {
370 if (scf_handle_bind(handle
) == 0) {
373 prop
= scf_simple_prop_get(handle
,
374 svcstring
, "general",
378 prop
= scf_simple_prop_get(handle
,
379 svcstring
, "general",
386 /* make sure we have an authorization string property */
389 numauths
= scf_simple_prop_numvalues(prop
);
390 for (ret
= 0, i
= 0; i
< numauths
; i
++) {
391 authstr
= scf_simple_prop_next_astring(prop
);
392 if (authstr
!= NULL
) {
393 /* check if this user has one of the strings */
394 if (chkauthattr(authstr
, pw
->pw_name
)) {
401 scf_simple_prop_free(prop
);
403 /* no authorization string defined */
407 scf_handle_destroy(handle
);
412 * check_authorizations(instname, flags)
414 * check all the needed authorizations for the user in this service
415 * instance. Return value of 1(true) or 0(false) indicates whether
416 * there are authorizations for the user or not.
420 check_authorizations(char *instname
, int flags
)
427 ret1
= check_authorization(instname
, SVC_SET
);
428 if (flags
& SVC_ACTION
)
429 ret2
= check_authorization(instname
, SVC_ACTION
);
437 case SVC_ACTION
|SVC_SET
:
441 /* if not flags set, we assume we don't need authorizations */
448 * notify_or_enable_share(share, protocol)
450 * Since some protocols don't want an "enable" when properties change,
451 * this function will use the protocol specific notify function
452 * first. If that fails, it will then attempt to use the
453 * sa_enable_share(). "protocol" is the protocol that was specified
454 * on the command line.
457 notify_or_enable_share(sa_share_t share
, char *protocol
)
464 sa_share_t parent
= share
;
466 /* If really a resource, get parent share */
467 if (!sa_is_share(share
)) {
468 parent
= sa_get_resource_parent((sa_resource_t
)share
);
472 * Now that we've got a share in "parent", make sure it has a path.
474 path
= sa_get_share_attr(parent
, "path");
478 group
= sa_get_parent_group(parent
);
481 sa_free_attr_string(path
);
484 for (opt
= sa_get_optionset(group
, NULL
);
486 opt
= sa_get_next_optionset(opt
)) {
487 groupproto
= sa_get_optionset_attr(opt
, "type");
488 if (groupproto
== NULL
||
489 (protocol
!= NULL
&& strcmp(groupproto
, protocol
) != 0)) {
490 if (groupproto
!= NULL
)
491 sa_free_attr_string(groupproto
);
494 if (sa_is_share(share
)) {
495 if ((ret
= sa_proto_change_notify(share
,
496 groupproto
)) != SA_OK
) {
497 ret
= sa_enable_share(share
, groupproto
);
500 gettext("Could not reenable"
502 path
, sa_errorstr(ret
));
506 /* Must be a resource */
507 if ((ret
= sa_proto_notify_resource(share
,
508 groupproto
)) != SA_OK
) {
509 ret
= sa_enable_resource(share
, groupproto
);
513 "reenable resource %s: "
519 sa_free_attr_string(groupproto
);
521 sa_free_attr_string(path
);
525 * enable_group(group, updateproto, notify, proto)
527 * enable all the shares in the specified group. This is a helper for
528 * enable_all_groups in order to simplify regular and subgroup (zfs)
529 * enabling. Group has already been checked for non-NULL. If notify
530 * is non-zero, attempt to use the notify interface rather than
534 enable_group(sa_group_t group
, char *updateproto
, int notify
, char *proto
)
538 /* If the protocol isn't enabled for this group skip it */
539 if (!has_protocol(group
, proto
))
542 for (share
= sa_get_share(group
, NULL
);
544 share
= sa_get_next_share(share
)) {
545 if (updateproto
!= NULL
)
546 (void) sa_update_legacy(share
, updateproto
);
548 notify_or_enable_share(share
, proto
);
550 (void) sa_enable_share(share
, proto
);
557 * Returns B_TRUE if the group is enabled or B_FALSE if it isn't.
558 * Moved to separate function to reduce clutter in the code.
562 isenabled(sa_group_t group
)
568 state
= sa_get_group_attr(group
, "state");
571 if (strcmp(state
, "enabled") == 0)
573 sa_free_attr_string(state
);
580 * enable_all_groups(list, setstate, online, updateproto)
582 * Given a list of groups, enable each one found. If updateproto is
583 * not NULL, then update all the shares for the protocol that was
584 * passed in. If enable is non-zero, tell enable_group to try the
585 * notify interface since this is a property change.
588 enable_all_groups(sa_handle_t handle
, struct list
*work
, int setstate
,
589 int online
, char *updateproto
, int enable
)
592 char instance
[SA_MAX_NAME_LEN
+ sizeof (SA_SVC_FMRI_BASE
) + 1];
599 for (ret
= SA_OK
; work
!= NULL
; work
= work
->next
) {
600 group
= (sa_group_t
)work
->item
;
603 * If setstate == TRUE, then make sure to set
604 * enabled. This needs to be done here in order for
605 * the isenabled check to succeed on a newly enabled
608 if (setstate
== B_TRUE
) {
609 ret
= sa_set_group_attr(group
, "state", "enabled");
615 * Check to see if group is enabled. If it isn't, skip
616 * the rest. We don't want shares starting if the
617 * group is disabled. The properties may have been
618 * updated, but there won't be a change until the
621 if (!isenabled(group
))
624 /* if itemdata != NULL then a single share */
625 if (work
->itemdata
!= NULL
) {
627 if (work
->itemdata
!= NULL
)
628 notify_or_enable_share(work
->itemdata
,
633 if (sa_is_share(work
->itemdata
)) {
634 ret
= sa_enable_share(
635 (sa_share_t
)work
->itemdata
,
638 ret
= sa_enable_resource(
639 (sa_resource_t
)work
->itemdata
,
647 /* if itemdata == NULL then the whole group */
648 if (work
->itemdata
== NULL
) {
649 zfs
= sa_get_group_attr(group
, "zfs");
651 * If the share is managed by ZFS, don't
652 * update any of the protocols since ZFS is
653 * handling this. Updateproto will contain
654 * the name of the protocol that we want to
655 * update legacy files for.
657 enable_group(group
, zfs
== NULL
? updateproto
: NULL
,
658 enable
, work
->proto
);
660 sa_free_attr_string(zfs
);
662 for (subgroup
= sa_get_sub_group(group
);
664 subgroup
= sa_get_next_group(subgroup
)) {
665 /* never update legacy for ZFS subgroups */
666 enable_group(subgroup
, NULL
, enable
,
671 zfs
= sa_get_group_attr(group
, "zfs");
672 name
= sa_get_group_attr(group
, "name");
675 (void) snprintf(instance
,
676 sizeof (instance
), "%s:%s",
677 SA_SVC_FMRI_BASE
, name
);
678 state
= smf_get_state(instance
);
680 strcmp(state
, "online") != 0) {
681 (void) smf_enable_instance(
686 sa_free_attr_string(zfs
);
690 sa_free_attr_string(name
);
695 ret
= sa_update_config(handle
);
701 * chk_opt(optlistp, security, proto)
703 * Do a sanity check on the optlist provided for the protocol. This
704 * is a syntax check and verification that the property is either a
705 * general or specific to a names optionset.
709 chk_opt(struct options
*optlistp
, int security
, char *proto
)
711 struct options
*optlist
;
716 for (optlist
= optlistp
; optlist
!= NULL
; optlist
= optlist
->next
) {
719 optname
= optlist
->optname
;
721 /* extract property/value pair */
722 if (sa_is_security(optname
, proto
)) {
724 ret
= OPT_ADD_SECURITY
;
727 ret
= OPT_ADD_PROPERTY
;
729 if (ret
!= OPT_ADD_OK
) {
732 gettext("Property syntax error: "));
735 (void) printf(gettext("%ssyntax error: %s"),
739 case OPT_ADD_SECURITY
:
740 (void) printf(gettext("%s%s requires -S"),
744 case OPT_ADD_PROPERTY
:
746 gettext("%s%s not supported with -S"),
763 * Free the specified option list.
766 free_opt(struct options
*optlist
)
768 struct options
*nextopt
;
769 while (optlist
!= NULL
) {
770 nextopt
= optlist
->next
;
777 * check property list for valid properties
778 * A null value is a remove which is always valid.
781 valid_options(sa_handle_t handle
, struct options
*optlist
, char *proto
,
782 void *object
, char *sec
)
787 sa_optionset_t parent
= NULL
;
789 if (object
!= NULL
) {
791 parent
= sa_get_optionset(object
, proto
);
793 parent
= sa_get_security(object
, sec
, proto
);
796 for (cur
= optlist
; cur
!= NULL
; cur
= cur
->next
) {
797 if (cur
->optvalue
== NULL
)
799 prop
= sa_create_property(cur
->optname
, cur
->optvalue
);
803 (ret
= sa_valid_property(handle
, parent
, proto
, prop
)) !=
806 gettext("Could not add property %s: %s\n"),
807 cur
->optname
, sa_errorstr(ret
));
809 (void) sa_remove_property(prop
);
815 * add_optionset(group, optlist, protocol, *err)
816 * Add the options in optlist to an optionset and then add the optionset
819 * The return value indicates if there was a "change" while errors are
820 * returned via the *err parameters.
823 add_optionset(sa_group_t group
, struct options
*optlist
, char *proto
, int *err
)
825 sa_optionset_t optionset
;
827 int result
= B_FALSE
;
830 optionset
= sa_get_optionset(group
, proto
);
831 if (optionset
== NULL
) {
832 optionset
= sa_create_optionset(group
, proto
);
833 if (optionset
== NULL
)
835 result
= B_TRUE
; /* adding a protocol is a change */
837 if (optionset
== NULL
) {
841 handle
= sa_find_group_handle(group
);
842 if (handle
== NULL
) {
846 while (optlist
!= NULL
) {
848 prop
= sa_get_property(optionset
, optlist
->optname
);
851 * add the property, but only if it is
852 * a non-NULL or non-zero length value
854 if (optlist
->optvalue
!= NULL
) {
855 prop
= sa_create_property(optlist
->optname
,
858 ret
= sa_valid_property(handle
,
859 optionset
, proto
, prop
);
861 (void) sa_remove_property(prop
);
862 (void) printf(gettext("Could "
870 ret
= sa_add_property(optionset
, prop
);
872 (void) printf(gettext(
873 "Could not add property "
878 /* there was a change */
884 ret
= sa_update_property(prop
, optlist
->optvalue
);
885 /* should check to see if value changed */
887 (void) printf(gettext("Could not update "
888 "property %s: %s\n"), optlist
->optname
,
894 optlist
= optlist
->next
;
896 ret
= sa_commit_properties(optionset
, 0);
905 * resource_compliant(group)
907 * Go through all the shares in the group. Assume compliant, but if
908 * any share doesn't have at least one resource name, it isn't
912 resource_compliant(sa_group_t group
)
916 for (share
= sa_get_share(group
, NULL
); share
!= NULL
;
917 share
= sa_get_next_share(share
)) {
918 if (sa_get_share_resource(share
, NULL
) == NULL
) {
928 * change all illegal characters to something else. For now, all get
929 * converted to '_' and the leading '/' is stripped off. This is used
930 * to construct an resource name (SMB share name) that is valid.
931 * Caller must pass a valid path.
939 assert(path
!= NULL
);
941 /* make sure we are appropriate length */
942 cp
= path
+ 1; /* skip leading slash */
943 while (cp
!= NULL
&& strlen(cp
) > SA_MAX_RESOURCE_NAME
) {
944 cp
= strchr(cp
, '/');
948 /* two cases - cp == NULL and cp is substring of path */
950 /* just take last SA_MAX_RESOURCE_NAME chars */
951 len
= 1 + strlen(path
) - SA_MAX_RESOURCE_NAME
;
952 (void) memmove(path
, path
+ len
, SA_MAX_RESOURCE_NAME
);
953 path
[SA_MAX_RESOURCE_NAME
] = '\0';
955 len
= strlen(cp
) + 1;
956 (void) memmove(path
, cp
, len
);
960 * Don't want any of the characters that are not allowed
961 * in and SMB share name. Replace them with '_'.
989 * name_adjust(path, count)
991 * Add a ~<count> in place of last few characters. The total number of
992 * characters is dependent on count.
994 #define MAX_MANGLE_NUMBER 10000
997 name_adjust(char *path
, int count
)
1001 len
= strlen(path
) - 2;
1009 (void) sprintf(path
+ len
, "~%d", count
);
1011 return (SA_BAD_VALUE
);
1017 * make_resources(group)
1019 * Go through all the shares in the group and make them have resource
1023 make_resources(sa_group_t group
)
1029 for (share
= sa_get_share(group
, NULL
); share
!= NULL
;
1030 share
= sa_get_next_share(share
)) {
1031 /* Skip those with resources */
1032 if (sa_get_share_resource(share
, NULL
) == NULL
) {
1034 path
= sa_get_share_attr(share
, "path");
1038 count
= 0; /* reset for next resource */
1039 while (sa_add_resource(share
, path
,
1040 SA_SHARE_PERMANENT
, &err
) == NULL
&&
1041 err
== SA_DUPLICATE_NAME
) {
1043 ret
= name_adjust(path
, count
);
1046 count
>= MAX_MANGLE_NUMBER
) {
1047 (void) printf(gettext(
1048 "Cannot create resource name for"
1049 " path: %s\n"), path
);
1053 sa_free_attr_string(path
);
1059 * check_valid_group(group, protocol)
1061 * Check to see that the group should have the protocol added (if
1062 * there is one specified).
1066 check_valid_group(sa_group_t group
, char *groupname
, char *protocol
)
1069 if (protocol
!= NULL
) {
1070 if (has_protocol(group
, protocol
)) {
1071 (void) printf(gettext(
1072 "Group \"%s\" already exists"
1073 " with protocol %s\n"), groupname
,
1075 return (SA_DUPLICATE_NAME
);
1076 } else if (strcmp(groupname
, "default") == 0 &&
1077 strcmp(protocol
, "nfs") != 0) {
1078 (void) printf(gettext(
1079 "Group \"%s\" only allows protocol "
1080 "\"%s\"\n"), groupname
, "nfs");
1081 return (SA_INVALID_PROTOCOL
);
1084 /* must add new protocol */
1085 (void) printf(gettext(
1086 "Group already exists and no protocol "
1088 return (SA_DUPLICATE_NAME
);
1094 * enforce_featureset(group, protocol, dryrun, force)
1096 * Check the protocol featureset against the group and enforce any
1097 * rules that might be imposed.
1101 enforce_featureset(sa_group_t group
, char *protocol
, boolean_t dryrun
,
1106 if (protocol
== NULL
)
1110 * First check to see if specified protocol is one we want to
1111 * allow on a group. Only server protocols are allowed here.
1113 features
= sa_proto_get_featureset(protocol
);
1114 if (!(features
& SA_FEATURE_SERVER
)) {
1116 gettext("Protocol \"%s\" not supported.\n"), protocol
);
1117 return (SA_INVALID_PROTOCOL
);
1121 * Check to see if the new protocol is one that requires
1122 * resource names and make sure we are compliant before
1125 if ((features
& SA_FEATURE_RESOURCE
) &&
1126 !resource_compliant(group
)) {
1127 if (force
&& !dryrun
) {
1128 make_resources(group
);
1131 gettext("Protocol requires resource names to be "
1132 "set: %s\n"), protocol
);
1133 return (SA_RESOURCE_REQUIRED
);
1140 * set_all_protocols(group)
1142 * Get the list of all protocols and add all server protocols to the
1147 set_all_protocols(sa_group_t group
)
1152 sa_optionset_t optionset
;
1156 * Now make sure we really want to put this protocol on a
1157 * group. Only server protocols can go here.
1159 numprotos
= sa_get_protocols(&protolist
);
1160 for (i
= 0; i
< numprotos
; i
++) {
1161 features
= sa_proto_get_featureset(protolist
[i
]);
1162 if (features
& SA_FEATURE_SERVER
) {
1163 optionset
= sa_create_optionset(group
, protolist
[i
]);
1164 if (optionset
== NULL
) {
1177 * sa_create(flags, argc, argv)
1178 * create a new group
1179 * this may or may not have a protocol associated with it.
1180 * No protocol means "all" protocols in this case.
1183 sa_create(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
1188 boolean_t force
= B_FALSE
;
1189 boolean_t verbose
= B_FALSE
;
1190 boolean_t dryrun
= B_FALSE
;
1192 char *protocol
= NULL
;
1194 struct options
*optlist
= NULL
;
1197 boolean_t created
= B_FALSE
;
1199 while ((c
= getopt(argc
, argv
, "?fhvnP:p:")) != EOF
) {
1211 if (protocol
!= NULL
) {
1212 (void) printf(gettext("Specifying "
1213 "multiple protocols "
1214 "not supported: %s\n"), protocol
);
1215 return (SA_SYNTAX_ERR
);
1218 if (sa_valid_protocol(protocol
))
1220 (void) printf(gettext(
1221 "Invalid protocol specified: %s\n"), protocol
);
1222 return (SA_INVALID_PROTOCOL
);
1224 ret
= add_opt(&optlist
, optarg
, 0);
1226 case OPT_ADD_SYNTAX
:
1227 (void) printf(gettext(
1228 "Property syntax error for property: %s\n"),
1230 return (SA_SYNTAX_ERR
);
1231 case OPT_ADD_SECURITY
:
1232 (void) printf(gettext(
1233 "Security properties need "
1234 "to be set with set-security: %s\n"),
1236 return (SA_SYNTAX_ERR
);
1242 /* optopt on valid arg isn't defined */
1248 * Since a bad option gets to here, sort it
1249 * out and return a syntax error return value
1254 err
= SA_SYNTAX_ERR
;
1260 (void) printf(gettext("usage: %s\n"),
1261 sa_get_usage(USAGE_CREATE
));
1266 if (optind
>= argc
) {
1267 (void) printf(gettext("usage: %s\n"),
1268 sa_get_usage(USAGE_CREATE
));
1269 (void) printf(gettext("\tgroup must be specified.\n"));
1270 return (SA_BAD_PATH
);
1273 if ((optind
+ 1) < argc
) {
1274 (void) printf(gettext("usage: %s\n"),
1275 sa_get_usage(USAGE_CREATE
));
1276 (void) printf(gettext("\textraneous group(s) at end\n"));
1277 return (SA_SYNTAX_ERR
);
1280 if (protocol
== NULL
&& optlist
!= NULL
) {
1281 /* lookup default protocol */
1282 (void) printf(gettext("usage: %s\n"),
1283 sa_get_usage(USAGE_CREATE
));
1284 (void) printf(gettext("\tprotocol must be specified "
1285 "with properties\n"));
1286 return (SA_INVALID_PROTOCOL
);
1289 if (optlist
!= NULL
)
1290 ret
= chk_opt(optlist
, 0, protocol
);
1291 if (ret
== OPT_ADD_SECURITY
) {
1292 (void) printf(gettext("Security properties not "
1293 "supported with create\n"));
1294 return (SA_SYNTAX_ERR
);
1298 * If a group already exists, we can only add a new protocol
1299 * to it and not create a new one or add the same protocol
1303 groupname
= argv
[optind
];
1305 auth
= check_authorizations(groupname
, flags
);
1307 group
= sa_get_group(handle
, groupname
);
1308 if (group
!= NULL
) {
1309 /* group exists so must be a protocol add */
1310 ret
= check_valid_group(group
, groupname
, protocol
);
1313 * is it a valid name? Must comply with SMF instance
1314 * name restrictions.
1316 if (!sa_valid_group_name(groupname
)) {
1317 ret
= SA_INVALID_NAME
;
1318 (void) printf(gettext("Invalid group name: %s\n"),
1323 /* check protocol vs optlist */
1324 if (optlist
!= NULL
) {
1325 /* check options, if any, for validity */
1326 ret
= valid_options(handle
, optlist
, protocol
,
1330 if (ret
== SA_OK
&& !dryrun
) {
1331 if (group
== NULL
) {
1332 group
= sa_create_group(handle
, (char *)groupname
,
1336 if (group
!= NULL
) {
1337 sa_optionset_t optionset
;
1340 * Check group and protocol against featureset
1343 ret
= enforce_featureset(group
, protocol
,
1349 * So far so good. Now add the required
1350 * optionset(s) to the group.
1352 if (optlist
!= NULL
) {
1353 (void) add_optionset(group
, optlist
, protocol
,
1355 } else if (protocol
!= NULL
) {
1356 optionset
= sa_create_optionset(group
,
1358 if (optionset
== NULL
)
1360 } else if (protocol
== NULL
) {
1361 /* default group create so add all protocols */
1362 ret
= set_all_protocols(group
);
1365 * We have a group and legal additions
1369 * Commit to configuration for protocols that
1370 * need to do block updates. For NFS, this
1371 * doesn't do anything but it will be run for
1372 * all protocols that implement the
1373 * appropriate plugin.
1375 ret
= sa_update_config(handle
);
1378 (void) sa_remove_group(group
);
1382 (void) printf(gettext("Could not create group: %s\n"),
1386 if (dryrun
&& ret
== SA_OK
&& !auth
&& verbose
) {
1387 (void) printf(gettext("Command would fail: %s\n"),
1388 sa_errorstr(SA_NO_PERMISSION
));
1389 ret
= SA_NO_PERMISSION
;
1392 if (ret
!= SA_OK
&& created
)
1393 ret
= sa_remove_group(group
);
1400 * group_status(group)
1402 * return the current status (enabled/disabled) of the group.
1406 group_status(sa_group_t group
)
1411 state
= sa_get_group_attr(group
, "state");
1412 if (state
!= NULL
) {
1413 if (strcmp(state
, "enabled") == 0) {
1416 sa_free_attr_string(state
);
1418 return (enabled
? "enabled" : "disabled");
1422 * sa_delete(flags, argc, argv)
1428 sa_delete(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
1437 char *protocol
= NULL
;
1438 char *sectype
= NULL
;
1442 while ((c
= getopt(argc
, argv
, "?hvnP:fS:")) != EOF
) {
1451 if (protocol
!= NULL
) {
1452 (void) printf(gettext("Specifying "
1453 "multiple protocols "
1454 "not supported: %s\n"), protocol
);
1455 return (SA_SYNTAX_ERR
);
1458 if (!sa_valid_protocol(protocol
)) {
1459 (void) printf(gettext("Invalid protocol "
1460 "specified: %s\n"), protocol
);
1461 return (SA_INVALID_PROTOCOL
);
1465 if (sectype
!= NULL
) {
1466 (void) printf(gettext("Specifying "
1467 "multiple property "
1468 "spaces not supported: %s\n"), sectype
);
1469 return (SA_SYNTAX_ERR
);
1477 /* optopt on valid arg isn't defined */
1483 * Since a bad option gets to here, sort it
1484 * out and return a syntax error return value
1489 ret
= SA_SYNTAX_ERR
;
1495 (void) printf(gettext("usage: %s\n"),
1496 sa_get_usage(USAGE_DELETE
));
1501 if (optind
>= argc
) {
1502 (void) printf(gettext("usage: %s\n"),
1503 sa_get_usage(USAGE_DELETE
));
1504 (void) printf(gettext("\tgroup must be specified.\n"));
1505 return (SA_SYNTAX_ERR
);
1508 if ((optind
+ 1) < argc
) {
1509 (void) printf(gettext("usage: %s\n"),
1510 sa_get_usage(USAGE_DELETE
));
1511 (void) printf(gettext("\textraneous group(s) at end\n"));
1512 return (SA_SYNTAX_ERR
);
1515 if (sectype
!= NULL
&& protocol
== NULL
) {
1516 (void) printf(gettext("usage: %s\n"),
1517 sa_get_usage(USAGE_DELETE
));
1518 (void) printf(gettext("\tsecurity requires protocol to be "
1520 return (SA_SYNTAX_ERR
);
1524 * Determine if the group already exists since it must in
1525 * order to be removed.
1527 * We can delete when:
1530 * - force flag is set
1531 * - if protocol specified, only delete the protocol
1534 groupname
= argv
[optind
];
1535 group
= sa_get_group(handle
, groupname
);
1536 if (group
== NULL
) {
1537 ret
= SA_NO_SUCH_GROUP
;
1540 auth
= check_authorizations(groupname
, flags
);
1541 if (protocol
== NULL
) {
1542 share
= sa_get_share(group
, NULL
);
1545 if (share
== NULL
|| (share
!= NULL
&& force
== 1)) {
1548 while (share
!= NULL
) {
1549 sa_share_t next_share
;
1550 next_share
= sa_get_next_share(share
);
1552 * need to do the disable of
1553 * each share, but don't
1554 * actually do anything on a
1557 ret
= sa_disable_share(share
, NULL
);
1558 ret
= sa_remove_share(share
);
1561 ret
= sa_remove_group(group
);
1564 /* Commit to configuration if not a dryrun */
1565 if (!dryrun
&& ret
== SA_OK
) {
1566 ret
= sa_update_config(handle
);
1569 /* a protocol delete */
1570 sa_optionset_t optionset
;
1571 sa_security_t security
;
1572 if (sectype
!= NULL
) {
1573 /* only delete specified security */
1574 security
= sa_get_security(group
, sectype
, protocol
);
1575 if (security
!= NULL
&& !dryrun
)
1576 ret
= sa_destroy_security(security
);
1578 ret
= SA_INVALID_PROTOCOL
;
1580 optionset
= sa_get_optionset(group
, protocol
);
1581 if (optionset
!= NULL
&& !dryrun
) {
1583 * have an optionset with
1584 * protocol to delete
1586 ret
= sa_destroy_optionset(optionset
);
1588 * Now find all security sets
1589 * for the protocol and remove
1590 * them. Don't remove other
1594 sa_get_security(group
, NULL
, NULL
);
1595 ret
== SA_OK
&& security
!= NULL
;
1596 security
= sa_get_next_security(security
)) {
1598 secprot
= sa_get_security_attr(security
,
1600 if (secprot
!= NULL
&&
1601 strcmp(secprot
, protocol
) == 0)
1602 ret
= sa_destroy_security(
1604 if (secprot
!= NULL
)
1605 sa_free_attr_string(secprot
);
1609 ret
= SA_INVALID_PROTOCOL
;
1613 * With the protocol items removed, make sure that all
1614 * the shares are updated in the legacy files, if
1617 for (share
= sa_get_share(group
, NULL
);
1619 share
= sa_get_next_share(share
)) {
1620 (void) sa_delete_legacy(share
, protocol
);
1626 (void) printf(gettext("Could not delete group: %s\n"),
1628 } else if (dryrun
&& !auth
&& verbose
) {
1629 (void) printf(gettext("Command would fail: %s\n"),
1630 sa_errorstr(SA_NO_PERMISSION
));
1636 * strndupr(*buff, str, buffsize)
1638 * used with small strings to duplicate and possibly increase the
1639 * buffer size of a string.
1642 strndupr(char *buff
, char *str
, int *buffsize
)
1645 char *orig_buff
= buff
;
1648 buff
= (char *)malloc(64);
1654 limit
= strlen(buff
) + strlen(str
) + 1;
1655 if (limit
> *buffsize
) {
1656 limit
= *buffsize
= *buffsize
+ ((limit
/ 64) + 64);
1657 buff
= realloc(buff
, limit
);
1660 (void) strcat(buff
, str
);
1662 /* if it fails, fail it hard */
1669 * group_proto(group)
1671 * return a string of all the protocols (space separated) associated
1676 group_proto(sa_group_t group
)
1678 sa_optionset_t optionset
;
1684 * get the protocol list by finding the optionsets on this
1685 * group and extracting the type value. The initial call to
1686 * strndupr() initailizes buff.
1688 buff
= strndupr(buff
, "", &buffsize
);
1690 for (optionset
= sa_get_optionset(group
, NULL
);
1691 optionset
!= NULL
&& buff
!= NULL
;
1692 optionset
= sa_get_next_optionset(optionset
)) {
1694 * extract out the protocol type from this optionset
1695 * and append it to the buffer "buff". strndupr() will
1696 * reallocate space as necessay.
1698 proto
= sa_get_optionset_attr(optionset
, "type");
1699 if (proto
!= NULL
) {
1701 buff
= strndupr(buff
, " ", &buffsize
);
1702 buff
= strndupr(buff
, proto
, &buffsize
);
1703 sa_free_attr_string(proto
);
1711 * sa_list(flags, argc, argv)
1713 * implements the "list" subcommand to list groups and optionally
1714 * their state and protocols.
1718 sa_list(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
1723 char *protocol
= NULL
;
1726 while ((c
= getopt(argc
, argv
, "?hvP:")) != EOF
) {
1732 if (protocol
!= NULL
) {
1733 (void) printf(gettext(
1734 "Specifying multiple protocols "
1735 "not supported: %s\n"),
1737 return (SA_SYNTAX_ERR
);
1740 if (!sa_valid_protocol(protocol
)) {
1741 (void) printf(gettext(
1742 "Invalid protocol specified: %s\n"),
1744 return (SA_INVALID_PROTOCOL
);
1748 /* optopt on valid arg isn't defined */
1754 * Since a bad option gets to here, sort it
1755 * out and return a syntax error return value
1760 ret
= SA_SYNTAX_ERR
;
1766 (void) printf(gettext("usage: %s\n"),
1767 sa_get_usage(USAGE_LIST
));
1772 if (optind
!= argc
) {
1773 (void) printf(gettext("usage: %s\n"),
1774 sa_get_usage(USAGE_LIST
));
1775 return (SA_SYNTAX_ERR
);
1778 for (group
= sa_get_group(handle
, NULL
);
1780 group
= sa_get_next_group(group
)) {
1783 if (protocol
== NULL
|| has_protocol(group
, protocol
)) {
1784 name
= sa_get_group_attr(group
, "name");
1785 if (name
!= NULL
&& (verbose
> 1 || name
[0] != '#')) {
1786 (void) printf("%s", (char *)name
);
1789 * Need the list of protocols
1790 * and current status once
1791 * available. We do want to
1793 * enabled/disabled text here.
1795 (void) printf("\t%s", isenabled(group
) ?
1796 gettext("enabled") :
1797 gettext("disabled"));
1798 proto
= group_proto(group
);
1799 if (proto
!= NULL
) {
1800 (void) printf("\t%s",
1805 (void) printf("\n");
1808 sa_free_attr_string(name
);
1815 * out_properties(optionset, proto, sec)
1817 * Format the properties and encode the protocol and optional named
1818 * optionset into the string.
1820 * format is protocol[:name]=(property-list)
1824 out_properties(sa_optionset_t optionset
, char *proto
, char *sec
)
1832 (void) printf(" %s=(", proto
? proto
: gettext("all"));
1834 (void) printf(" %s:%s=(", proto
? proto
: gettext("all"), sec
);
1836 for (spacer
= 0, prop
= sa_get_property(optionset
, NULL
);
1838 prop
= sa_get_next_property(prop
)) {
1841 * extract the property name/value and output with
1842 * appropriate spacing. I.e. no prefixed space the
1843 * first time through but a space on subsequent
1846 type
= sa_get_property_attr(prop
, "type");
1847 value
= sa_get_property_attr(prop
, "value");
1849 (void) printf("%s%s=", spacer
? " " : "", type
);
1852 (void) printf("\"%s\"", value
);
1854 (void) printf("\"\"");
1857 sa_free_attr_string(type
);
1859 sa_free_attr_string(value
);
1865 * show_properties(group, protocol, prefix)
1867 * print the properties for a group. If protocol is NULL, do all
1868 * protocols otherwise only the specified protocol. All security
1869 * (named groups specific to the protocol) are included.
1871 * The "prefix" is always applied. The caller knows whether it wants
1872 * some type of prefix string (white space) or not. Once the prefix
1873 * has been output, it is reduced to the zero length string for the
1874 * remainder of the property output.
1878 show_properties(sa_group_t group
, char *protocol
, char *prefix
)
1880 sa_optionset_t optionset
;
1881 sa_security_t security
;
1885 if (protocol
!= NULL
) {
1886 optionset
= sa_get_optionset(group
, protocol
);
1887 if (optionset
!= NULL
) {
1888 (void) printf("%s", prefix
);
1890 out_properties(optionset
, protocol
, NULL
);
1892 security
= sa_get_security(group
, protocol
, NULL
);
1893 if (security
!= NULL
) {
1894 (void) printf("%s", prefix
);
1896 out_properties(security
, protocol
, NULL
);
1899 for (optionset
= sa_get_optionset(group
, protocol
);
1901 optionset
= sa_get_next_optionset(optionset
)) {
1903 value
= sa_get_optionset_attr(optionset
, "type");
1904 (void) printf("%s", prefix
);
1906 out_properties(optionset
, value
, 0);
1908 sa_free_attr_string(value
);
1910 for (security
= sa_get_security(group
, NULL
, protocol
);
1912 security
= sa_get_next_security(security
)) {
1914 value
= sa_get_security_attr(security
, "type");
1915 secvalue
= sa_get_security_attr(security
, "sectype");
1916 (void) printf("%s", prefix
);
1918 out_properties(security
, value
, secvalue
);
1920 sa_free_attr_string(value
);
1921 if (secvalue
!= NULL
)
1922 sa_free_attr_string(secvalue
);
1928 * get_resource(share)
1930 * Get the first resource name, if any, and fix string to be in
1931 * current locale and have quotes if it has embedded spaces. Return
1932 * an attr string that must be freed.
1936 get_resource(sa_share_t share
)
1938 sa_resource_t resource
;
1939 char *resstring
= NULL
;
1942 if ((resource
= sa_get_share_resource(share
, NULL
)) != NULL
) {
1943 resstring
= sa_get_resource_attr(resource
, "name");
1944 if (resstring
!= NULL
) {
1948 retstring
= conv_from_utf8(resstring
);
1949 if (retstring
!= resstring
) {
1950 sa_free_attr_string(resstring
);
1951 resstring
= retstring
;
1953 if (strpbrk(resstring
, " ") != NULL
) {
1954 /* account for quotes */
1955 len
= strlen(resstring
) + 3;
1956 cp
= calloc(len
, sizeof (char));
1958 (void) snprintf(cp
, len
,
1959 "\"%s\"", resstring
);
1960 sa_free_attr_string(resstring
);
1963 sa_free_attr_string(resstring
);
1973 * has_resource_with_opt(share)
1975 * Check to see if the share has any resource names with optionsets
1976 * set. Also indicate if multiple resource names since the syntax
1977 * would be about the same.
1980 has_resource_with_opt(sa_share_t share
)
1982 sa_resource_t resource
;
1985 for (resource
= sa_get_share_resource(share
, NULL
);
1987 resource
= sa_get_next_resource(resource
)) {
1989 if (sa_get_optionset(resource
, NULL
) != NULL
) {
1998 * has_multiple_resource(share)
2000 * Check to see if the share has multiple resource names since
2001 * the syntax would be about the same.
2004 has_multiple_resource(sa_share_t share
)
2006 sa_resource_t resource
;
2009 for (num
= 0, resource
= sa_get_share_resource(share
, NULL
);
2011 resource
= sa_get_next_resource(resource
)) {
2020 * show_share(share, verbose, properties, proto, iszfs, sharepath)
2022 * print out the share information. With the addition of resource as a
2023 * full object that can have multiple instances below the share, we
2024 * need to display that as well.
2028 show_share(sa_share_t share
, int verbose
, int properties
, char *proto
,
2029 int iszfs
, char *sharepath
)
2033 sa_resource_t resource
= NULL
;
2040 rsrcwithopt
= has_resource_with_opt(share
);
2042 if (verbose
|| (properties
&& rsrcwithopt
)) {
2043 /* First, indicate if transient */
2044 type
= sa_get_share_attr(share
, "type");
2045 if (type
!= NULL
&& !iszfs
&& verbose
&&
2046 strcmp(type
, "transient") == 0)
2047 (void) printf("\t* ");
2049 (void) printf("\t ");
2052 sa_free_attr_string(type
);
2055 * If we came in with verbose, we want to handle the case of
2056 * multiple resources as though they had properties set.
2058 multiple
= has_multiple_resource(share
);
2061 * if there is a description on the share and there
2062 * are resources, treat as multiple resources in order
2063 * to get all descriptions displayed.
2065 description
= sa_get_share_description(share
);
2066 resource
= sa_get_share_resource(share
, NULL
);
2068 if (description
!= NULL
&& resource
!= NULL
)
2071 /* Next, if not multiple follow old model */
2072 if (!multiple
&& !rsrcwithopt
) {
2073 rsrcname
= get_resource(share
);
2074 if (rsrcname
!= NULL
&& strlen(rsrcname
) > 0) {
2075 (void) printf("%s=%s", rsrcname
, sharepath
);
2077 (void) printf("%s", sharepath
);
2079 if (rsrcname
!= NULL
)
2080 sa_free_attr_string(rsrcname
);
2081 /* Print the description string if there is one. */
2082 print_rsrc_desc(resource
, description
);
2084 /* Treat as simple and then resources come later */
2085 (void) printf("%s", sharepath
);
2087 drive
= sa_get_share_attr(share
, "drive-letter");
2088 if (drive
!= NULL
) {
2089 if (strlen(drive
) > 0)
2090 (void) printf(gettext("\tdrive-letter=\"%s:\""),
2092 sa_free_attr_string(drive
);
2095 show_properties(share
, proto
, "\t");
2096 exclude
= sa_get_share_attr(share
, "exclude");
2097 if (exclude
!= NULL
) {
2098 (void) printf(gettext("\tnot-shared-with=[%s]"),
2100 sa_free_attr_string(exclude
);
2103 if (description
!= NULL
) {
2104 print_rsrc_desc((sa_resource_t
)share
, description
);
2107 * If there are resource names with options, show them
2108 * here, with one line per resource. Resource specific
2109 * options are at the end of the line followed by
2110 * description, if any.
2112 if (rsrcwithopt
|| multiple
) {
2113 for (resource
= sa_get_share_resource(share
, NULL
);
2115 resource
= sa_get_next_resource(resource
)) {
2119 (void) printf("\n\t\t ");
2120 rsrcname
= sa_get_resource_attr(resource
,
2122 if (rsrcname
== NULL
)
2125 rsrc
= conv_from_utf8(rsrcname
);
2126 has_space
= strpbrk(rsrc
, " ") != NULL
;
2129 (void) printf("\"%s\"=%s", rsrc
,
2132 (void) printf("%s=%s", rsrc
,
2134 if (rsrc
!= rsrcname
)
2135 sa_free_attr_string(rsrc
);
2136 sa_free_attr_string(rsrcname
);
2137 if (properties
|| rsrcwithopt
)
2138 show_properties(resource
, proto
, "\t");
2140 /* Get description string if any */
2141 print_rsrc_desc(resource
, description
);
2144 if (description
!= NULL
)
2145 sa_free_share_description(description
);
2147 (void) printf("\t %s", sharepath
);
2149 show_properties(share
, proto
, "\t");
2151 (void) printf("\n");
2155 * show_group(group, verbose, properties, proto, subgroup)
2157 * helper function to show the contents of a group.
2161 show_group(sa_group_t group
, int verbose
, int properties
, char *proto
,
2170 groupname
= sa_get_group_attr(group
, "name");
2171 if (groupname
!= NULL
) {
2172 if (proto
!= NULL
&& !has_protocol(group
, proto
)) {
2173 sa_free_attr_string(groupname
);
2177 * check to see if the group is managed by ZFS. If
2178 * there is an attribute, then it is. A non-NULL zfs
2179 * variable will trigger the different way to display
2180 * and will remove the transient property indicator
2183 zfs
= sa_get_group_attr(group
, "zfs");
2186 sa_free_attr_string(zfs
);
2188 share
= sa_get_share(group
, NULL
);
2189 if (subgroup
== NULL
)
2190 (void) printf("%s", groupname
);
2192 (void) printf(" %s/%s", subgroup
, groupname
);
2194 show_properties(group
, proto
, "");
2195 (void) printf("\n");
2196 if (strcmp(groupname
, "zfs") == 0) {
2199 for (zgroup
= sa_get_sub_group(group
);
2201 zgroup
= sa_get_next_group(zgroup
)) {
2202 show_group(zgroup
, verbose
, properties
, proto
,
2205 sa_free_attr_string(groupname
);
2209 * Have a group, so list the contents. Resource and
2210 * description are only listed if verbose is set.
2212 for (share
= sa_get_share(group
, NULL
);
2214 share
= sa_get_next_share(share
)) {
2215 sharepath
= sa_get_share_attr(share
, "path");
2216 if (sharepath
!= NULL
) {
2217 show_share(share
, verbose
, properties
, proto
,
2219 sa_free_attr_string(sharepath
);
2223 if (groupname
!= NULL
) {
2224 sa_free_attr_string(groupname
);
2229 * show_group_xml_init()
2231 * Create an XML document that will be used to display config info via
2236 show_group_xml_init()
2241 doc
= xmlNewDoc((xmlChar
*)"1.0");
2243 root
= xmlNewNode(NULL
, (xmlChar
*)"sharecfg");
2245 (void) xmlDocSetRootElement(doc
, root
);
2251 * show_group_xml(doc, group)
2253 * Copy the group info into the XML doc.
2257 show_group_xml(xmlDocPtr doc
, sa_group_t group
)
2262 root
= xmlDocGetRootElement(doc
);
2263 node
= xmlCopyNode((xmlNodePtr
)group
, 1);
2264 if (node
!= NULL
&& root
!= NULL
) {
2265 (void) xmlAddChild(root
, node
);
2267 * In the future, we may have interally used tags that
2268 * should not appear in the XML output. Remove
2269 * anything we don't want to show here.
2275 * sa_show(flags, argc, argv)
2277 * Implements the show subcommand.
2281 sa_show(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
2288 char *protocol
= NULL
;
2292 while ((c
= getopt(argc
, argv
, "?hvP:px")) != EOF
) {
2301 if (protocol
!= NULL
) {
2302 (void) printf(gettext(
2303 "Specifying multiple protocols "
2304 "not supported: %s\n"),
2306 return (SA_SYNTAX_ERR
);
2309 if (!sa_valid_protocol(protocol
)) {
2310 (void) printf(gettext(
2311 "Invalid protocol specified: %s\n"),
2313 return (SA_INVALID_PROTOCOL
);
2320 /* optopt on valid arg isn't defined */
2326 * Since a bad option gets to here, sort it
2327 * out and return a syntax error return value
2332 ret
= SA_SYNTAX_ERR
;
2338 (void) printf(gettext("usage: %s\n"),
2339 sa_get_usage(USAGE_SHOW
));
2345 doc
= show_group_xml_init();
2350 if (optind
== argc
) {
2351 /* No group specified so go through them all */
2352 for (group
= sa_get_group(handle
, NULL
);
2354 group
= sa_get_next_group(group
)) {
2356 * Have a group so check if one we want and then list
2357 * contents with appropriate options.
2360 show_group_xml(doc
, group
);
2362 show_group(group
, verbose
, properties
, protocol
,
2366 /* Have a specified list of groups */
2367 for (; optind
< argc
; optind
++) {
2368 group
= sa_get_group(handle
, argv
[optind
]);
2369 if (group
!= NULL
) {
2371 show_group_xml(doc
, group
);
2373 show_group(group
, verbose
, properties
,
2376 (void) printf(gettext("%s: not found\n"),
2378 ret
= SA_NO_SUCH_GROUP
;
2382 if (xml
&& ret
== SA_OK
) {
2383 (void) xmlDocFormatDump(stdout
, doc
, 1);
2391 * enable_share(group, share, update_legacy)
2393 * helper function to enable a share if the group is enabled.
2397 enable_share(sa_handle_t handle
, sa_group_t group
, sa_share_t share
,
2402 sa_optionset_t optionset
;
2410 * need to enable this share if the group is enabled but not
2411 * otherwise. The enable is also done on each protocol
2412 * represented in the group.
2414 value
= sa_get_group_attr(group
, "state");
2415 enabled
= value
!= NULL
&& strcmp(value
, "enabled") == 0;
2417 sa_free_attr_string(value
);
2418 /* remove legacy config if necessary */
2420 ret
= sa_delete_legacy(share
, NULL
);
2421 zfs
= sa_get_group_attr(group
, "zfs");
2424 sa_free_attr_string(zfs
);
2428 * Step through each optionset at the group level and
2429 * enable the share based on the protocol type. This
2430 * works because protocols must be set on the group
2431 * for the protocol to be enabled.
2433 isshare
= sa_is_share(share
);
2434 for (optionset
= sa_get_optionset(group
, NULL
);
2435 optionset
!= NULL
&& ret
== SA_OK
;
2436 optionset
= sa_get_next_optionset(optionset
)) {
2437 value
= sa_get_optionset_attr(optionset
, "type");
2438 if (value
!= NULL
) {
2441 err
= sa_enable_share(share
, value
);
2443 err
= sa_enable_resource(share
, value
);
2444 if (err
== SA_NOT_SUPPORTED
) {
2446 parent
= sa_get_resource_parent(
2449 err
= sa_enable_share(
2455 (void) printf(gettext(
2456 "Failed to enable share for "
2458 value
, sa_errorstr(ret
));
2462 * If we want to update the legacy, use a copy of
2463 * share so we can avoid breaking the loop we are in
2464 * since we might also need to go up the tree to the
2467 if (update_legacy
&& !iszfs
) {
2468 sa_share_t update
= share
;
2469 if (!sa_is_share(share
)) {
2470 update
= sa_get_resource_parent(share
);
2472 (void) sa_update_legacy(update
, value
);
2474 sa_free_attr_string(value
);
2478 (void) sa_update_config(handle
);
2483 * sa_require_resource(group)
2485 * if any of the defined protocols on the group require resource
2486 * names, then all shares must have them.
2490 sa_require_resource(sa_group_t group
)
2492 sa_optionset_t optionset
;
2494 for (optionset
= sa_get_optionset(group
, NULL
);
2496 optionset
= sa_get_next_optionset(optionset
)) {
2499 proto
= sa_get_optionset_attr(optionset
, "type");
2500 if (proto
!= NULL
) {
2503 features
= sa_proto_get_featureset(proto
);
2504 if (features
& SA_FEATURE_RESOURCE
) {
2505 sa_free_attr_string(proto
);
2508 sa_free_attr_string(proto
);
2515 * sa_addshare(flags, argc, argv)
2517 * implements add-share subcommand.
2521 sa_addshare(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
2529 sa_resource_t resource
= NULL
;
2530 char *sharepath
= NULL
;
2531 char *description
= NULL
;
2532 char *rsrcname
= NULL
;
2534 int persist
= SA_SHARE_PERMANENT
; /* default to persist */
2536 char dir
[MAXPATHLEN
];
2538 while ((c
= getopt(argc
, argv
, "?hvns:d:r:t")) != EOF
) {
2547 description
= optarg
;
2550 if (rsrcname
!= NULL
) {
2551 (void) printf(gettext("Adding multiple "
2552 "resource names not"
2554 return (SA_SYNTAX_ERR
);
2560 * Save share path into group. Currently limit
2561 * to one share per command.
2563 if (sharepath
!= NULL
) {
2564 (void) printf(gettext(
2565 "Adding multiple shares not supported\n"));
2566 return (SA_SYNTAX_ERR
);
2571 persist
= SA_SHARE_TRANSIENT
;
2574 /* optopt on valid arg isn't defined */
2580 * Since a bad option gets to here, sort it
2581 * out and return a syntax error return value
2586 ret
= SA_SYNTAX_ERR
;
2592 (void) printf(gettext("usage: %s\n"),
2593 sa_get_usage(USAGE_ADD_SHARE
));
2598 if (optind
>= argc
) {
2599 (void) printf(gettext("usage: %s\n"),
2600 sa_get_usage(USAGE_ADD_SHARE
));
2601 if (dryrun
|| sharepath
!= NULL
|| description
!= NULL
||
2602 rsrcname
!= NULL
|| verbose
|| persist
) {
2603 (void) printf(gettext("\tgroup must be specified\n"));
2604 ret
= SA_NO_SUCH_GROUP
;
2609 if (sharepath
== NULL
) {
2610 (void) printf(gettext("usage: %s\n"),
2611 sa_get_usage(USAGE_ADD_SHARE
));
2612 (void) printf(gettext(
2613 "\t-s sharepath must be specified\n"));
2617 if (realpath(sharepath
, dir
) == NULL
) {
2619 (void) printf(gettext("Path "
2620 "is not valid: %s\n"),
2626 if (ret
== SA_OK
&& rsrcname
!= NULL
) {
2627 /* check for valid syntax */
2628 if (validresource(rsrcname
)) {
2629 rsrc
= conv_to_utf8(rsrcname
);
2630 resource
= sa_find_resource(handle
, rsrc
);
2631 if (resource
!= NULL
) {
2633 * Resource names must be
2634 * unique in the system
2636 ret
= SA_DUPLICATE_NAME
;
2637 (void) printf(gettext("usage: %s\n"),
2638 sa_get_usage(USAGE_ADD_SHARE
));
2639 (void) printf(gettext(
2640 "\tresource names must be unique "
2641 "in the system\n"));
2644 (void) printf(gettext("usage: %s\n"),
2645 sa_get_usage(USAGE_ADD_SHARE
));
2646 (void) printf(gettext(
2647 "\tresource names use restricted "
2648 "character set\n"));
2649 ret
= SA_INVALID_NAME
;
2654 if (rsrc
!= NULL
&& rsrcname
!= rsrc
)
2655 sa_free_attr_string(rsrc
);
2659 share
= sa_find_share(handle
, sharepath
);
2660 if (share
!= NULL
) {
2661 if (rsrcname
== NULL
) {
2663 * Can only have a duplicate share if a new
2664 * resource name is being added.
2666 ret
= SA_DUPLICATE_NAME
;
2667 (void) printf(gettext("Share path already "
2668 "shared: %s\n"), sharepath
);
2674 group
= sa_get_group(handle
, argv
[optind
]);
2675 if (group
!= NULL
) {
2676 if (sa_require_resource(group
) == B_TRUE
&&
2678 (void) printf(gettext(
2679 "Resource name is required "
2680 "by at least one enabled protocol "
2682 return (SA_RESOURCE_REQUIRED
);
2684 if (share
== NULL
&& ret
== SA_OK
) {
2686 ret
= sa_check_path(group
, sharepath
,
2689 share
= sa_add_share(group
, sharepath
,
2693 * Make sure this isn't an attempt to put a resourced
2694 * share into a different group than it already is in.
2696 if (share
!= NULL
) {
2698 parent
= sa_get_parent_group(share
);
2699 if (parent
!= group
) {
2700 ret
= SA_DUPLICATE_NAME
;
2701 (void) printf(gettext(
2702 "Share path already "
2703 "shared: %s\n"), sharepath
);
2706 if (!dryrun
&& share
== NULL
) {
2707 (void) printf(gettext(
2708 "Could not add share: %s\n"),
2711 auth
= check_authorizations(argv
[optind
],
2713 if (!dryrun
&& ret
== SA_OK
) {
2714 if (rsrcname
!= NULL
) {
2715 resource
= sa_add_resource(
2722 description
!= NULL
) {
2723 if (resource
!= NULL
)
2735 /* now enable the share(s) */
2736 if (resource
!= NULL
) {
2749 ret
= sa_update_config(handle
);
2752 case SA_DUPLICATE_NAME
:
2753 (void) printf(gettext(
2759 (void) printf(gettext(
2767 } else if (dryrun
&& ret
== SA_OK
&&
2769 (void) printf(gettext(
2770 "Command would fail: %s\n"),
2771 sa_errorstr(SA_NO_PERMISSION
));
2772 ret
= SA_NO_PERMISSION
;
2778 (void) printf(gettext(
2779 "Group \"%s\" not found\n"), argv
[optind
]);
2780 ret
= SA_NO_SUCH_GROUP
;
2783 case SA_DUPLICATE_NAME
:
2792 * sa_moveshare(flags, argc, argv)
2794 * implements move-share subcommand.
2798 sa_moveshare(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
2806 char *rsrcname
= NULL
;
2807 char *sharepath
= NULL
;
2808 int authsrc
= 0, authdst
= 0;
2809 char dir
[MAXPATHLEN
];
2811 while ((c
= getopt(argc
, argv
, "?hvnr:s:")) != EOF
) {
2820 if (rsrcname
!= NULL
) {
2821 (void) printf(gettext(
2822 "Moving multiple resource names not"
2824 return (SA_SYNTAX_ERR
);
2830 * Remove share path from group. Currently limit
2831 * to one share per command.
2833 if (sharepath
!= NULL
) {
2834 (void) printf(gettext("Moving multiple shares"
2835 " not supported\n"));
2836 return (SA_SYNTAX_ERR
);
2841 /* optopt on valid arg isn't defined */
2847 * Since a bad option gets to here, sort it
2848 * out and return a syntax error return value
2853 ret
= SA_SYNTAX_ERR
;
2859 (void) printf(gettext("usage: %s\n"),
2860 sa_get_usage(USAGE_MOVE_SHARE
));
2865 if (optind
>= argc
|| sharepath
== NULL
) {
2866 (void) printf(gettext("usage: %s\n"),
2867 sa_get_usage(USAGE_MOVE_SHARE
));
2868 if (dryrun
|| verbose
|| sharepath
!= NULL
) {
2869 (void) printf(gettext("\tgroup must be specified\n"));
2870 ret
= SA_NO_SUCH_GROUP
;
2872 if (sharepath
== NULL
) {
2873 ret
= SA_SYNTAX_ERR
;
2874 (void) printf(gettext(
2875 "\tsharepath must be specified\n"));
2885 if (sharepath
== NULL
) {
2886 (void) printf(gettext(
2887 "sharepath must be specified with the -s "
2889 return (SA_BAD_PATH
);
2891 group
= sa_get_group(handle
, argv
[optind
]);
2892 if (group
== NULL
) {
2893 (void) printf(gettext("Group \"%s\" not found\n"),
2895 return (SA_NO_SUCH_GROUP
);
2897 share
= sa_find_share(handle
, sharepath
);
2899 * If a share wasn't found, it may have been a symlink
2900 * or has a trailing '/'. Try again after resolving
2903 if (share
== NULL
) {
2904 if (realpath(sharepath
, dir
) == NULL
) {
2905 (void) printf(gettext("Path "
2906 "is not valid: %s\n"),
2908 return (SA_BAD_PATH
);
2911 share
= sa_find_share(handle
, sharepath
);
2913 if (share
== NULL
) {
2914 (void) printf(gettext("Share not found: %s\n"),
2916 return (SA_NO_SUCH_PATH
);
2918 authdst
= check_authorizations(argv
[optind
], flags
);
2920 parent
= sa_get_parent_group(share
);
2921 if (parent
!= NULL
) {
2923 pname
= sa_get_group_attr(parent
, "name");
2924 if (pname
!= NULL
) {
2925 authsrc
= check_authorizations(pname
, flags
);
2926 sa_free_attr_string(pname
);
2928 zfsold
= sa_get_group_attr(parent
, "zfs");
2929 zfsnew
= sa_get_group_attr(group
, "zfs");
2930 if ((zfsold
!= NULL
&& zfsnew
== NULL
) ||
2931 (zfsold
== NULL
&& zfsnew
!= NULL
)) {
2932 ret
= SA_NOT_ALLOWED
;
2935 sa_free_attr_string(zfsold
);
2937 sa_free_attr_string(zfsnew
);
2940 if (ret
== SA_OK
&& parent
!= group
&& !dryrun
) {
2943 * Note that the share may need to be
2944 * "unshared" if the new group is disabled and
2945 * the old was enabled or it may need to be
2946 * share to update if the new group is
2947 * enabled. We disable before the move and
2948 * will have to enable after the move in order
2949 * to cleanup entries for protocols that
2950 * aren't in the new group.
2952 oldstate
= sa_get_group_attr(parent
, "state");
2953 if (oldstate
!= NULL
) {
2954 /* enable_share determines what to do */
2955 if (strcmp(oldstate
, "enabled") == 0)
2956 (void) sa_disable_share(share
, NULL
);
2957 sa_free_attr_string(oldstate
);
2961 if (!dryrun
&& ret
== SA_OK
)
2962 ret
= sa_move_share(group
, share
);
2965 * Reenable and update any config information.
2967 if (ret
== SA_OK
&& parent
!= group
&& !dryrun
) {
2968 ret
= sa_update_config(handle
);
2970 (void) enable_share(handle
, group
, share
, 1);
2974 (void) printf(gettext("Could not move share: %s\n"),
2977 if (dryrun
&& ret
== SA_OK
&& !(authsrc
& authdst
) &&
2979 (void) printf(gettext("Command would fail: %s\n"),
2980 sa_errorstr(SA_NO_PERMISSION
));
2987 * sa_removeshare(flags, argc, argv)
2989 * implements remove-share subcommand.
2993 sa_removeshare(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
3001 sa_resource_t resource
= NULL
;
3002 sa_share_t share
= NULL
;
3003 char *rsrcname
= NULL
;
3004 char *sharepath
= NULL
;
3005 char dir
[MAXPATHLEN
];
3008 while ((c
= getopt(argc
, argv
, "?hfnr:s:v")) != EOF
) {
3021 * Remove share path from group. Currently limit
3022 * to one share per command.
3024 if (sharepath
!= NULL
) {
3025 (void) printf(gettext(
3026 "Removing multiple shares not "
3028 return (SA_SYNTAX_ERR
);
3034 * Remove share from group if last resource or remove
3035 * resource from share if multiple resources.
3037 if (rsrcname
!= NULL
) {
3038 (void) printf(gettext(
3039 "Removing multiple resource names not "
3041 return (SA_SYNTAX_ERR
);
3046 /* optopt on valid arg isn't defined */
3052 * Since a bad option gets to here, sort it
3053 * out and return a syntax error return value
3058 ret
= SA_SYNTAX_ERR
;
3064 (void) printf(gettext("usage: %s\n"),
3065 sa_get_usage(USAGE_REMOVE_SHARE
));
3070 if (optind
>= argc
|| (rsrcname
== NULL
&& sharepath
== NULL
)) {
3071 if (sharepath
== NULL
&& rsrcname
== NULL
) {
3072 (void) printf(gettext("usage: %s\n"),
3073 sa_get_usage(USAGE_REMOVE_SHARE
));
3074 (void) printf(gettext("\t-s sharepath or -r resource"
3075 " must be specified\n"));
3085 if (optind
< argc
) {
3086 if ((optind
+ 1) < argc
) {
3087 (void) printf(gettext("Extraneous group(s) at end of "
3089 ret
= SA_SYNTAX_ERR
;
3091 group
= sa_get_group(handle
, argv
[optind
]);
3092 if (group
== NULL
) {
3093 (void) printf(gettext(
3094 "Group \"%s\" not found\n"), argv
[optind
]);
3095 ret
= SA_NO_SUCH_GROUP
;
3102 if (rsrcname
!= NULL
) {
3103 resource
= sa_find_resource(handle
, rsrcname
);
3104 if (resource
== NULL
) {
3105 ret
= SA_NO_SUCH_RESOURCE
;
3106 (void) printf(gettext(
3107 "Resource name not found for share: %s\n"),
3113 * Lookup the path in the internal configuration. Care
3114 * must be taken to handle the case where the
3115 * underlying path has been removed since we need to
3116 * be able to deal with that as well.
3119 if (sharepath
!= NULL
) {
3121 share
= sa_get_share(group
, sharepath
);
3123 share
= sa_find_share(handle
, sharepath
);
3126 if (resource
!= NULL
) {
3127 sa_share_t rsrcshare
;
3128 rsrcshare
= sa_get_resource_parent(resource
);
3131 else if (share
!= rsrcshare
) {
3132 ret
= SA_NO_SUCH_RESOURCE
;
3133 (void) printf(gettext(
3134 "Bad resource name for share: %s\n"),
3141 * If we didn't find the share with the provided path,
3142 * it may be a symlink so attempt to resolve it using
3143 * realpath and try again. Realpath will resolve any
3144 * symlinks and place them in "dir". Note that
3145 * sharepath is only used for the lookup the first
3146 * time and later for error messages. dir will be used
3147 * on the second attempt. Once a share is found, all
3148 * operations are based off of the share variable.
3150 if (share
== NULL
) {
3151 if (realpath(sharepath
, dir
) == NULL
) {
3153 (void) printf(gettext(
3154 "Path is not valid: %s\n"), sharepath
);
3157 share
= sa_get_share(group
, dir
);
3159 share
= sa_find_share(handle
, dir
);
3165 * If there hasn't been an error, there was likely a
3166 * path found. If not, give the appropriate error
3167 * message and set the return error. If it was found,
3168 * then disable the share and then remove it from the
3174 if (share
== NULL
) {
3176 (void) printf(gettext("Share not found in group %s:"
3177 " %s\n"), argv
[optind
], sharepath
);
3179 (void) printf(gettext("Share not found: %s\n"),
3181 ret
= SA_NO_SUCH_PATH
;
3184 group
= sa_get_parent_group(share
);
3187 if (resource
!= NULL
)
3188 ret
= sa_disable_resource(resource
,
3191 ret
= sa_disable_share(share
, NULL
);
3193 * We don't care if it fails since it
3194 * could be disabled already. Some
3195 * unexpected errors could occur that
3196 * prevent removal, so also check for
3199 if ((ret
== SA_OK
|| ret
== SA_NO_SUCH_PATH
||
3200 ret
== SA_NOT_SUPPORTED
||
3201 ret
== SA_SYSTEM_ERR
|| force
) &&
3203 ret
= sa_remove_share(share
);
3205 if ((ret
== SA_OK
|| ret
== SA_NO_SUCH_PATH
||
3206 ret
== SA_NOT_SUPPORTED
||
3207 ret
== SA_SYSTEM_ERR
|| force
) &&
3209 ret
= sa_remove_resource(resource
);
3214 * the share as well.
3217 sa_get_share_resource(
3219 if (resource
== NULL
)
3220 ret
= sa_remove_share(
3225 ret
= sa_update_config(handle
);
3228 (void) printf(gettext("Could not remove share:"
3229 " %s\n"), sa_errorstr(ret
));
3230 } else if (ret
== SA_OK
) {
3232 pname
= sa_get_group_attr(group
, "name");
3233 if (pname
!= NULL
) {
3234 auth
= check_authorizations(pname
, flags
);
3235 sa_free_attr_string(pname
);
3237 if (!auth
&& verbose
) {
3238 (void) printf(gettext(
3239 "Command would fail: %s\n"),
3240 sa_errorstr(SA_NO_PERMISSION
));
3248 * sa_set_share(flags, argc, argv)
3250 * implements set-share subcommand.
3254 sa_set_share(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
3259 sa_group_t group
, sharegroup
;
3260 sa_share_t share
= NULL
;
3261 sa_resource_t resource
= NULL
;
3262 char *sharepath
= NULL
;
3263 char *description
= NULL
;
3264 char *rsrcname
= NULL
;
3266 char *newname
= NULL
;
3268 char *groupname
= NULL
;
3272 while ((c
= getopt(argc
, argv
, "?hnd:r:s:")) != EOF
) {
3278 description
= optarg
;
3285 * Update share by resource name
3287 if (rsrcname
!= NULL
) {
3288 (void) printf(gettext(
3289 "Updating multiple resource names not "
3291 return (SA_SYNTAX_ERR
);
3297 * Save share path into group. Currently limit
3298 * to one share per command.
3300 if (sharepath
!= NULL
) {
3301 (void) printf(gettext(
3302 "Updating multiple shares not "
3304 return (SA_SYNTAX_ERR
);
3309 /* optopt on valid arg isn't defined */
3315 * Since a bad option gets to here, sort it
3316 * out and return a syntax error return value
3321 ret
= SA_SYNTAX_ERR
;
3327 (void) printf(gettext("usage: %s\n"),
3328 sa_get_usage(USAGE_SET_SHARE
));
3333 if (optind
>= argc
&& sharepath
== NULL
&& rsrcname
== NULL
) {
3334 if (sharepath
== NULL
) {
3335 (void) printf(gettext("usage: %s\n"),
3336 sa_get_usage(USAGE_SET_SHARE
));
3337 (void) printf(gettext("\tgroup must be specified\n"));
3343 if ((optind
+ 1) < argc
) {
3344 (void) printf(gettext("usage: %s\n"),
3345 sa_get_usage(USAGE_SET_SHARE
));
3346 (void) printf(gettext("\tExtraneous group(s) at end\n"));
3347 ret
= SA_SYNTAX_ERR
;
3351 * Must have at least one of sharepath and rsrcrname.
3352 * It is a syntax error to be missing both.
3354 if (sharepath
== NULL
&& rsrcname
== NULL
) {
3355 (void) printf(gettext("usage: %s\n"),
3356 sa_get_usage(USAGE_SET_SHARE
));
3357 ret
= SA_SYNTAX_ERR
;
3363 if (optind
< argc
) {
3364 groupname
= argv
[optind
];
3365 group
= sa_get_group(handle
, groupname
);
3370 if (rsrcname
!= NULL
) {
3372 * If rsrcname exists, split rename syntax and then
3373 * convert to utf 8 if no errors.
3375 newname
= strchr(rsrcname
, '=');
3376 if (newname
!= NULL
) {
3379 if (!validresource(rsrcname
)) {
3380 ret
= SA_INVALID_NAME
;
3381 (void) printf(gettext("Invalid resource name: "
3382 "\"%s\"\n"), rsrcname
);
3384 rsrc
= conv_to_utf8(rsrcname
);
3386 if (newname
!= NULL
) {
3387 if (!validresource(newname
)) {
3388 ret
= SA_INVALID_NAME
;
3389 (void) printf(gettext("Invalid resource name: "
3393 newrsrc
= conv_to_utf8(newname
);
3399 if (rsrcname
!= NULL
&& rsrcname
!= rsrc
)
3400 sa_free_attr_string(rsrc
);
3401 if (newname
!= NULL
&& newname
!= newrsrc
)
3402 sa_free_attr_string(newrsrc
);
3406 if (sharepath
!= NULL
) {
3407 share
= sa_find_share(handle
, sharepath
);
3408 } else if (rsrcname
!= NULL
) {
3409 resource
= sa_find_resource(handle
, rsrc
);
3410 if (resource
!= NULL
)
3411 share
= sa_get_resource_parent(resource
);
3413 ret
= SA_NO_SUCH_RESOURCE
;
3415 if (share
!= NULL
) {
3416 sharegroup
= sa_get_parent_group(share
);
3417 if (group
!= NULL
&& group
!= sharegroup
) {
3418 (void) printf(gettext("Group \"%s\" does not contain "
3420 argv
[optind
], sharepath
);
3423 int delgroupname
= 0;
3424 if (groupname
== NULL
) {
3425 groupname
= sa_get_group_attr(sharegroup
,
3429 if (groupname
!= NULL
) {
3430 auth
= check_authorizations(groupname
, flags
);
3432 sa_free_attr_string(groupname
);
3438 if (rsrcname
!= NULL
) {
3439 resource
= sa_find_resource(handle
, rsrc
);
3441 if (newname
!= NULL
&&
3443 ret
= sa_rename_resource(
3445 else if (newname
!= NULL
)
3446 ret
= SA_NO_SUCH_RESOURCE
;
3447 if (newname
!= NULL
&&
3449 sa_free_attr_string(newrsrc
);
3451 if (rsrc
!= rsrcname
)
3452 sa_free_attr_string(rsrc
);
3456 * If the user has set a description, it will be
3457 * on the resource if -r was used otherwise it
3458 * must be on the share.
3460 if (!dryrun
&& ret
== SA_OK
&& description
!= NULL
) {
3462 desc
= conv_to_utf8(description
);
3463 if (resource
!= NULL
)
3464 ret
= sa_set_resource_description(
3467 ret
= sa_set_share_description(share
,
3469 if (desc
!= description
)
3470 sa_free_share_description(desc
);
3473 if (!dryrun
&& ret
== SA_OK
) {
3474 if (resource
!= NULL
)
3475 (void) sa_enable_resource(resource
, NULL
);
3476 ret
= sa_update_config(handle
);
3479 case SA_DUPLICATE_NAME
:
3480 (void) printf(gettext("Resource name in use: %s\n"),
3484 (void) printf(gettext("Could not set: %s\n"),
3488 if (dryrun
&& !auth
&& verbose
) {
3489 (void) printf(gettext(
3490 "Command would fail: %s\n"),
3491 sa_errorstr(SA_NO_PERMISSION
));
3497 case SA_NO_SUCH_RESOURCE
:
3498 (void) printf(gettext("Resource \"%s\" not found\n"),
3502 if (sharepath
!= NULL
) {
3504 gettext("Share path \"%s\" not found\n"),
3506 ret
= SA_NO_SUCH_PATH
;
3508 (void) printf(gettext("Set failed: %s\n"),
3518 * add_security(group, sectype, optlist, proto, *err)
3520 * Helper function to add a security option (named optionset) to the
3525 add_security(sa_group_t group
, char *sectype
,
3526 struct options
*optlist
, char *proto
, int *err
)
3528 sa_security_t security
;
3533 sectype
= sa_proto_space_alias(proto
, sectype
);
3534 security
= sa_get_security(group
, sectype
, proto
);
3535 if (security
== NULL
)
3536 security
= sa_create_security(group
, sectype
, proto
);
3538 if (sectype
!= NULL
)
3539 sa_free_attr_string(sectype
);
3541 if (security
== NULL
)
3544 handle
= sa_find_group_handle(group
);
3545 if (handle
== NULL
) {
3546 ret
= SA_CONFIG_ERR
;
3549 while (optlist
!= NULL
) {
3551 prop
= sa_get_property(security
, optlist
->optname
);
3554 * Add the property, but only if it is
3555 * a non-NULL or non-zero length value
3557 if (optlist
->optvalue
!= NULL
) {
3558 prop
= sa_create_property(optlist
->optname
,
3561 ret
= sa_valid_property(handle
,
3562 security
, proto
, prop
);
3564 (void) sa_remove_property(prop
);
3565 (void) printf(gettext(
3567 "property %s: %s\n"),
3572 ret
= sa_add_property(security
,
3575 (void) printf(gettext(
3589 ret
= sa_update_property(prop
, optlist
->optvalue
);
3590 result
= 1; /* should check if really changed */
3592 optlist
= optlist
->next
;
3595 * When done, properties may have all been removed but
3596 * we need to keep the security type itself until
3597 * explicitly removed.
3600 ret
= sa_commit_properties(security
, 0);
3607 * zfscheck(group, share)
3609 * For the special case where a share was provided, make sure it is a
3610 * compatible path for a ZFS property change. The only path
3611 * acceptable is the path that defines the zfs sub-group (dataset with
3612 * the sharenfs property set) and not one of the paths that inherited
3613 * the NFS properties. Returns SA_OK if it is usable and
3614 * SA_NOT_ALLOWED if it isn't.
3616 * If group is not a ZFS group/subgroup, we assume OK since the check
3617 * on return will catch errors for those cases. What we are looking
3618 * for here is that the group is ZFS and the share is not the defining
3619 * share. All else is SA_OK.
3623 zfscheck(sa_group_t group
, sa_share_t share
)
3628 if (sa_group_is_zfs(group
)) {
3630 * The group is a ZFS group. Does the share represent
3631 * the dataset that defined the group? It is only OK
3632 * if the attribute "subgroup" exists on the share and
3633 * has a value of "true".
3636 ret
= SA_NOT_ALLOWED
;
3637 attr
= sa_get_share_attr(share
, "subgroup");
3639 if (strcmp(attr
, "true") == 0)
3641 sa_free_attr_string(attr
);
3648 * basic_set(groupname, optlist, protocol, sharepath, rsrcname, dryrun)
3650 * This function implements "set" when a name space (-S) is not
3651 * specified. It is a basic set. Options and other CLI parsing has
3652 * already been done.
3654 * "rsrcname" is a "resource name". If it is non-NULL, it must match
3655 * the sharepath if present or group if present, otherwise it is used
3658 * Resource names may take options if the protocol supports it. If the
3659 * protocol doesn't support resource level options, rsrcname is just
3660 * an alias for the share.
3664 basic_set(sa_handle_t handle
, char *groupname
, struct options
*optlist
,
3665 char *protocol
, char *sharepath
, char *rsrcname
, int dryrun
)
3670 struct list
*worklist
= NULL
;
3672 group
= sa_get_group(handle
, groupname
);
3673 if (group
!= NULL
) {
3674 sa_share_t share
= NULL
;
3675 sa_resource_t resource
= NULL
;
3678 * If there is a sharepath, make sure it belongs to
3681 if (sharepath
!= NULL
) {
3682 share
= sa_get_share(group
, sharepath
);
3683 if (share
== NULL
) {
3684 (void) printf(gettext(
3685 "Share does not exist in group %s\n"),
3686 groupname
, sharepath
);
3687 ret
= SA_NO_SUCH_PATH
;
3689 /* if ZFS and OK, then only group */
3690 ret
= zfscheck(group
, share
);
3692 sa_group_is_zfs(group
))
3694 if (ret
== SA_NOT_ALLOWED
)
3695 (void) printf(gettext(
3696 "Properties on ZFS group shares "
3697 "not supported: %s\n"), sharepath
);
3702 * If a resource name exists, make sure it belongs to
3703 * the share if present else it belongs to the
3704 * group. Also check the protocol to see if it
3705 * supports resource level properties or not. If not,
3708 if (rsrcname
!= NULL
) {
3709 if (share
!= NULL
) {
3710 resource
= sa_get_share_resource(share
,
3712 if (resource
== NULL
)
3713 ret
= SA_NO_SUCH_RESOURCE
;
3715 resource
= sa_get_resource(group
, rsrcname
);
3716 if (resource
!= NULL
)
3717 share
= sa_get_resource_parent(
3720 ret
= SA_NO_SUCH_RESOURCE
;
3722 if (ret
== SA_OK
&& resource
!= NULL
) {
3725 * Check to see if the resource can take
3726 * properties. If so, stick the resource into
3727 * "share" so it will all just work.
3729 features
= sa_proto_get_featureset(protocol
);
3730 if (features
& SA_FEATURE_RESOURCE
)
3731 share
= (sa_share_t
)resource
;
3736 /* group must exist */
3737 ret
= valid_options(handle
, optlist
, protocol
,
3738 share
== NULL
? group
: share
, NULL
);
3739 if (ret
== SA_OK
&& !dryrun
) {
3741 change
|= add_optionset(share
, optlist
,
3744 change
|= add_optionset(group
, optlist
,
3746 if (ret
== SA_OK
&& change
)
3747 worklist
= add_list(worklist
, group
,
3753 (void) printf(gettext("Group \"%s\" not found\n"), groupname
);
3754 ret
= SA_NO_SUCH_GROUP
;
3757 * we have a group and potentially legal additions
3761 * Commit to configuration if not a dryrunp and properties
3764 if (!dryrun
&& ret
== SA_OK
&& change
&& worklist
!= NULL
)
3765 /* properties changed, so update all shares */
3766 (void) enable_all_groups(handle
, worklist
, 0, 0, protocol
,
3769 if (worklist
!= NULL
)
3770 free_list(worklist
);
3775 * space_set(groupname, optlist, protocol, sharepath, dryrun)
3777 * This function implements "set" when a name space (-S) is
3778 * specified. It is a namespace set. Options and other CLI parsing has
3779 * already been done.
3783 space_set(sa_handle_t handle
, char *groupname
, struct options
*optlist
,
3784 char *protocol
, char *sharepath
, int dryrun
, char *sectype
)
3789 struct list
*worklist
= NULL
;
3792 * make sure protcol and sectype are valid
3795 if (sa_proto_valid_space(protocol
, sectype
) == 0) {
3796 (void) printf(gettext("Option space \"%s\" not valid "
3797 "for protocol.\n"), sectype
);
3798 return (SA_INVALID_SECURITY
);
3801 group
= sa_get_group(handle
, groupname
);
3802 if (group
!= NULL
) {
3803 sa_share_t share
= NULL
;
3804 if (sharepath
!= NULL
) {
3805 share
= sa_get_share(group
, sharepath
);
3806 if (share
== NULL
) {
3807 (void) printf(gettext(
3808 "Share does not exist in group %s\n"),
3809 groupname
, sharepath
);
3810 ret
= SA_NO_SUCH_PATH
;
3812 /* if ZFS and OK, then only group */
3813 ret
= zfscheck(group
, share
);
3815 sa_group_is_zfs(group
))
3817 if (ret
== SA_NOT_ALLOWED
)
3818 (void) printf(gettext(
3819 "Properties on ZFS group shares "
3820 "not supported: %s\n"), sharepath
);
3824 /* group must exist */
3825 ret
= valid_options(handle
, optlist
, protocol
,
3826 share
== NULL
? group
: share
, sectype
);
3827 if (ret
== SA_OK
&& !dryrun
) {
3829 change
= add_security(share
, sectype
,
3830 optlist
, protocol
, &ret
);
3832 change
= add_security(group
, sectype
,
3833 optlist
, protocol
, &ret
);
3835 (void) printf(gettext(
3836 "Could not set property: %s\n"),
3839 if (ret
== SA_OK
&& change
)
3840 worklist
= add_list(worklist
, group
, share
,
3845 (void) printf(gettext("Group \"%s\" not found\n"), groupname
);
3846 ret
= SA_NO_SUCH_GROUP
;
3850 * We have a group and potentially legal additions.
3853 /* Commit to configuration if not a dryrun */
3854 if (!dryrun
&& ret
== 0) {
3855 if (change
&& worklist
!= NULL
) {
3856 /* properties changed, so update all shares */
3857 (void) enable_all_groups(handle
, worklist
, 0, 0,
3860 ret
= sa_update_config(handle
);
3862 if (worklist
!= NULL
)
3863 free_list(worklist
);
3868 * sa_set(flags, argc, argv)
3870 * Implements the set subcommand. It keys off of -S to determine which
3871 * set of operations to actually do.
3875 sa_set(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
3881 char *protocol
= NULL
;
3883 struct options
*optlist
= NULL
;
3884 char *rsrcname
= NULL
;
3885 char *sharepath
= NULL
;
3886 char *optset
= NULL
;
3889 while ((c
= getopt(argc
, argv
, "?hvnP:p:r:s:S:")) != EOF
) {
3898 if (protocol
!= NULL
) {
3899 (void) printf(gettext(
3900 "Specifying multiple protocols "
3901 "not supported: %s\n"), protocol
);
3902 return (SA_SYNTAX_ERR
);
3905 if (!sa_valid_protocol(protocol
)) {
3906 (void) printf(gettext(
3907 "Invalid protocol specified: %s\n"),
3909 return (SA_INVALID_PROTOCOL
);
3913 ret
= add_opt(&optlist
, optarg
, 0);
3915 case OPT_ADD_SYNTAX
:
3916 (void) printf(gettext("Property syntax error:"
3918 return (SA_SYNTAX_ERR
);
3919 case OPT_ADD_MEMORY
:
3920 (void) printf(gettext("No memory to set "
3921 "property: %s\n"), optarg
);
3922 return (SA_NO_MEMORY
);
3928 if (rsrcname
!= NULL
) {
3929 (void) printf(gettext(
3930 "Setting multiple resource names not"
3932 return (SA_SYNTAX_ERR
);
3937 if (sharepath
!= NULL
) {
3938 (void) printf(gettext(
3939 "Setting multiple shares not supported\n"));
3940 return (SA_SYNTAX_ERR
);
3945 if (optset
!= NULL
) {
3946 (void) printf(gettext(
3947 "Specifying multiple property "
3948 "spaces not supported: %s\n"), optset
);
3949 return (SA_SYNTAX_ERR
);
3954 /* optopt on valid arg isn't defined */
3960 * Since a bad option gets to here, sort it
3961 * out and return a syntax error return value
3966 ret
= SA_SYNTAX_ERR
;
3972 (void) printf(gettext("usage: %s\n"),
3973 sa_get_usage(USAGE_SET
));
3978 if (optlist
!= NULL
)
3979 ret
= chk_opt(optlist
, optset
!= NULL
, protocol
);
3981 if (optind
>= argc
|| (optlist
== NULL
&& optset
== NULL
) ||
3982 protocol
== NULL
|| ret
!= OPT_ADD_OK
) {
3985 (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_SET
));
3986 if (optind
>= argc
) {
3987 (void) printf(gettext("%sgroup must be specified"),
3991 if (optlist
== NULL
) {
3992 (void) printf(gettext("%sat least one property must be"
3993 " specified"), sep
);
3996 if (protocol
== NULL
) {
3997 (void) printf(gettext("%sprotocol must be specified"),
4001 (void) printf("\n");
4002 ret
= SA_SYNTAX_ERR
;
4005 * Group already exists so we can proceed after a few
4006 * additional checks related to ZFS handling.
4009 groupname
= argv
[optind
];
4010 if (strcmp(groupname
, "zfs") == 0) {
4011 (void) printf(gettext("Changing properties for group "
4012 "\"zfs\" not allowed\n"));
4013 return (SA_NOT_ALLOWED
);
4016 auth
= check_authorizations(groupname
, flags
);
4018 ret
= basic_set(handle
, groupname
, optlist
, protocol
,
4019 sharepath
, rsrcname
, dryrun
);
4021 ret
= space_set(handle
, groupname
, optlist
, protocol
,
4022 sharepath
, dryrun
, optset
);
4023 if (dryrun
&& ret
== SA_OK
&& !auth
&& verbose
) {
4024 (void) printf(gettext("Command would fail: %s\n"),
4025 sa_errorstr(SA_NO_PERMISSION
));
4032 * remove_options(group, optlist, proto, *err)
4034 * Helper function to actually remove options from a group after all
4035 * preprocessing is done.
4039 remove_options(sa_group_t group
, struct options
*optlist
,
4040 char *proto
, int *err
)
4042 struct options
*cur
;
4043 sa_optionset_t optionset
;
4048 optionset
= sa_get_optionset(group
, proto
);
4049 if (optionset
!= NULL
) {
4050 for (cur
= optlist
; cur
!= NULL
; cur
= cur
->next
) {
4051 prop
= sa_get_property(optionset
, cur
->optname
);
4053 ret
= sa_remove_property(prop
);
4060 if (ret
== SA_OK
&& change
)
4061 ret
= sa_commit_properties(optionset
, 0);
4069 * valid_unset(group, optlist, proto)
4071 * Sanity check the optlist to make sure they can be removed. Issue an
4072 * error if a property doesn't exist.
4076 valid_unset(sa_group_t group
, struct options
*optlist
, char *proto
)
4078 struct options
*cur
;
4079 sa_optionset_t optionset
;
4083 optionset
= sa_get_optionset(group
, proto
);
4084 if (optionset
!= NULL
) {
4085 for (cur
= optlist
; cur
!= NULL
; cur
= cur
->next
) {
4086 prop
= sa_get_property(optionset
, cur
->optname
);
4088 (void) printf(gettext(
4089 "Could not unset property %s: not set\n"),
4091 ret
= SA_NO_SUCH_PROP
;
4099 * valid_unset_security(group, optlist, proto)
4101 * Sanity check the optlist to make sure they can be removed. Issue an
4102 * error if a property doesn't exist.
4106 valid_unset_security(sa_group_t group
, struct options
*optlist
, char *proto
,
4109 struct options
*cur
;
4110 sa_security_t security
;
4115 sec
= sa_proto_space_alias(proto
, sectype
);
4116 security
= sa_get_security(group
, sec
, proto
);
4117 if (security
!= NULL
) {
4118 for (cur
= optlist
; cur
!= NULL
; cur
= cur
->next
) {
4119 prop
= sa_get_property(security
, cur
->optname
);
4121 (void) printf(gettext(
4122 "Could not unset property %s: not set\n"),
4124 ret
= SA_NO_SUCH_PROP
;
4128 (void) printf(gettext(
4129 "Could not unset %s: space not defined\n"), sectype
);
4130 ret
= SA_NO_SUCH_SECURITY
;
4133 sa_free_attr_string(sec
);
4138 * remove_security(group, optlist, proto)
4140 * Remove the properties since they were checked as valid.
4144 remove_security(sa_group_t group
, char *sectype
,
4145 struct options
*optlist
, char *proto
, int *err
)
4147 sa_security_t security
;
4151 sectype
= sa_proto_space_alias(proto
, sectype
);
4152 security
= sa_get_security(group
, sectype
, proto
);
4153 if (sectype
!= NULL
)
4154 sa_free_attr_string(sectype
);
4156 if (security
!= NULL
) {
4157 while (optlist
!= NULL
) {
4159 prop
= sa_get_property(security
, optlist
->optname
);
4161 ret
= sa_remove_property(prop
);
4166 optlist
= optlist
->next
;
4169 * when done, properties may have all been removed but
4170 * we need to keep the security type itself until
4171 * explicitly removed.
4173 if (ret
== SA_OK
&& change
)
4174 ret
= sa_commit_properties(security
, 0);
4176 ret
= SA_NO_SUCH_PROP
;
4184 * basic_unset(groupname, optlist, protocol, sharepath, rsrcname, dryrun)
4186 * Unset non-named optionset properties.
4190 basic_unset(sa_handle_t handle
, char *groupname
, struct options
*optlist
,
4191 char *protocol
, char *sharepath
, char *rsrcname
, int dryrun
)
4196 struct list
*worklist
= NULL
;
4197 sa_share_t share
= NULL
;
4198 sa_resource_t resource
= NULL
;
4200 group
= sa_get_group(handle
, groupname
);
4205 * If there is a sharepath, make sure it belongs to
4208 if (sharepath
!= NULL
) {
4209 share
= sa_get_share(group
, sharepath
);
4210 if (share
== NULL
) {
4211 (void) printf(gettext(
4212 "Share does not exist in group %s\n"),
4213 groupname
, sharepath
);
4214 ret
= SA_NO_SUCH_PATH
;
4218 * If a resource name exists, make sure it belongs to
4219 * the share if present else it belongs to the
4220 * group. Also check the protocol to see if it
4221 * supports resource level properties or not. If not,
4224 if (rsrcname
!= NULL
) {
4225 if (share
!= NULL
) {
4226 resource
= sa_get_share_resource(share
, rsrcname
);
4227 if (resource
== NULL
)
4228 ret
= SA_NO_SUCH_RESOURCE
;
4230 resource
= sa_get_resource(group
, rsrcname
);
4231 if (resource
!= NULL
) {
4232 share
= sa_get_resource_parent(resource
);
4234 ret
= SA_NO_SUCH_RESOURCE
;
4237 if (ret
== SA_OK
&& resource
!= NULL
) {
4240 * Check to see if the resource can take
4241 * properties. If so, stick the resource into
4242 * "share" so it will all just work.
4244 features
= sa_proto_get_featureset(protocol
);
4245 if (features
& SA_FEATURE_RESOURCE
)
4246 share
= (sa_share_t
)resource
;
4251 /* group must exist */
4252 ret
= valid_unset(share
!= NULL
? share
: group
,
4254 if (ret
== SA_OK
&& !dryrun
) {
4255 if (share
!= NULL
) {
4256 sa_optionset_t optionset
;
4258 change
|= remove_options(share
, optlist
,
4261 * If a share optionset is
4264 optionset
= sa_get_optionset((sa_share_t
)share
,
4266 if (optionset
!= NULL
) {
4267 prop
= sa_get_property(optionset
, NULL
);
4269 (void) sa_destroy_optionset(
4273 change
|= remove_options(group
,
4274 optlist
, protocol
, &ret
);
4276 if (ret
== SA_OK
&& change
)
4277 worklist
= add_list(worklist
, group
, share
,
4280 (void) printf(gettext(
4281 "Could not remove properties: "
4282 "%s\n"), sa_errorstr(ret
));
4285 (void) printf(gettext("Group \"%s\" not found\n"), groupname
);
4286 ret
= SA_NO_SUCH_GROUP
;
4291 * We have a group and potentially legal additions
4293 * Commit to configuration if not a dryrun
4295 if (!dryrun
&& ret
== SA_OK
) {
4296 if (change
&& worklist
!= NULL
) {
4297 /* properties changed, so update all shares */
4298 (void) enable_all_groups(handle
, worklist
, 0, 0,
4302 if (worklist
!= NULL
)
4303 free_list(worklist
);
4308 * space_unset(groupname, optlist, protocol, sharepath, dryrun)
4310 * Unset named optionset properties.
4313 space_unset(sa_handle_t handle
, char *groupname
, struct options
*optlist
,
4314 char *protocol
, char *sharepath
, int dryrun
, char *sectype
)
4319 struct list
*worklist
= NULL
;
4320 sa_share_t share
= NULL
;
4322 group
= sa_get_group(handle
, groupname
);
4323 if (group
== NULL
) {
4324 (void) printf(gettext("Group \"%s\" not found\n"), groupname
);
4325 return (SA_NO_SUCH_GROUP
);
4327 if (sharepath
!= NULL
) {
4328 share
= sa_get_share(group
, sharepath
);
4329 if (share
== NULL
) {
4330 (void) printf(gettext(
4331 "Share does not exist in group %s\n"),
4332 groupname
, sharepath
);
4333 return (SA_NO_SUCH_PATH
);
4336 ret
= valid_unset_security(share
!= NULL
? share
: group
,
4337 optlist
, protocol
, sectype
);
4339 if (ret
== SA_OK
&& !dryrun
) {
4340 if (optlist
!= NULL
) {
4341 if (share
!= NULL
) {
4342 sa_security_t optionset
;
4344 change
= remove_security(share
,
4345 sectype
, optlist
, protocol
, &ret
);
4347 /* If a share security is empty, remove it */
4348 optionset
= sa_get_security((sa_group_t
)share
,
4350 if (optionset
!= NULL
) {
4351 prop
= sa_get_property(optionset
,
4354 ret
= sa_destroy_security(
4358 change
= remove_security(group
, sectype
,
4359 optlist
, protocol
, &ret
);
4362 sa_security_t security
;
4364 sec
= sa_proto_space_alias(protocol
, sectype
);
4365 security
= sa_get_security(group
, sec
, protocol
);
4367 sa_free_attr_string(sec
);
4368 if (security
!= NULL
) {
4369 ret
= sa_destroy_security(security
);
4373 ret
= SA_NO_SUCH_PROP
;
4377 (void) printf(gettext("Could not unset property: %s\n"),
4381 if (ret
== SA_OK
&& change
)
4382 worklist
= add_list(worklist
, group
, 0, protocol
);
4386 * We have a group and potentially legal additions
4389 /* Commit to configuration if not a dryrun */
4390 if (!dryrun
&& ret
== 0) {
4391 /* properties changed, so update all shares */
4392 if (change
&& worklist
!= NULL
)
4393 (void) enable_all_groups(handle
, worklist
, 0, 0,
4395 ret
= sa_update_config(handle
);
4397 if (worklist
!= NULL
)
4398 free_list(worklist
);
4403 * sa_unset(flags, argc, argv)
4405 * Implements the unset subcommand. Parsing done here and then basic
4406 * or space versions of the real code are called.
4410 sa_unset(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
4416 char *protocol
= NULL
;
4418 struct options
*optlist
= NULL
;
4419 char *rsrcname
= NULL
;
4420 char *sharepath
= NULL
;
4421 char *optset
= NULL
;
4424 while ((c
= getopt(argc
, argv
, "?hvnP:p:r:s:S:")) != EOF
) {
4433 if (protocol
!= NULL
) {
4434 (void) printf(gettext(
4435 "Specifying multiple protocols "
4436 "not supported: %s\n"), protocol
);
4437 return (SA_SYNTAX_ERR
);
4440 if (!sa_valid_protocol(protocol
)) {
4441 (void) printf(gettext(
4442 "Invalid protocol specified: %s\n"),
4444 return (SA_INVALID_PROTOCOL
);
4448 ret
= add_opt(&optlist
, optarg
, 1);
4450 case OPT_ADD_SYNTAX
:
4451 (void) printf(gettext("Property syntax error "
4452 "for property %s\n"), optarg
);
4453 return (SA_SYNTAX_ERR
);
4455 case OPT_ADD_PROPERTY
:
4456 (void) printf(gettext("Properties need to be "
4457 "set with set command: %s\n"), optarg
);
4458 return (SA_SYNTAX_ERR
);
4466 * Unset properties on resource if applicable or on
4467 * share if resource for this protocol doesn't use
4470 if (rsrcname
!= NULL
) {
4471 (void) printf(gettext(
4472 "Unsetting multiple resource "
4473 "names not supported\n"));
4474 return (SA_SYNTAX_ERR
);
4479 if (sharepath
!= NULL
) {
4480 (void) printf(gettext(
4481 "Adding multiple shares not supported\n"));
4482 return (SA_SYNTAX_ERR
);
4487 if (optset
!= NULL
) {
4488 (void) printf(gettext(
4489 "Specifying multiple property "
4490 "spaces not supported: %s\n"), optset
);
4491 return (SA_SYNTAX_ERR
);
4496 /* optopt on valid arg isn't defined */
4502 * Since a bad option gets to here, sort it
4503 * out and return a syntax error return value
4508 ret
= SA_SYNTAX_ERR
;
4514 (void) printf(gettext("usage: %s\n"),
4515 sa_get_usage(USAGE_UNSET
));
4520 if (optlist
!= NULL
)
4521 ret
= chk_opt(optlist
, optset
!= NULL
, protocol
);
4523 if (optind
>= argc
|| (optlist
== NULL
&& optset
== NULL
) ||
4526 (void) printf(gettext("usage: %s\n"),
4527 sa_get_usage(USAGE_UNSET
));
4528 if (optind
>= argc
) {
4529 (void) printf(gettext("%sgroup must be specified"),
4533 if (optlist
== NULL
) {
4534 (void) printf(gettext("%sat least one property must "
4535 "be specified"), sep
);
4538 if (protocol
== NULL
) {
4539 (void) printf(gettext("%sprotocol must be specified"),
4543 (void) printf("\n");
4544 ret
= SA_SYNTAX_ERR
;
4548 * If a group already exists, we can only add a new
4549 * protocol to it and not create a new one or add the
4550 * same protocol again.
4553 groupname
= argv
[optind
];
4554 auth
= check_authorizations(groupname
, flags
);
4556 ret
= basic_unset(handle
, groupname
, optlist
, protocol
,
4557 sharepath
, rsrcname
, dryrun
);
4559 ret
= space_unset(handle
, groupname
, optlist
, protocol
,
4560 sharepath
, dryrun
, optset
);
4562 if (dryrun
&& ret
== SA_OK
&& !auth
&& verbose
)
4563 (void) printf(gettext("Command would fail: %s\n"),
4564 sa_errorstr(SA_NO_PERMISSION
));
4570 * sa_enable_group(flags, argc, argv)
4572 * Implements the enable subcommand
4576 sa_enable_group(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
4583 char *protocol
= NULL
;
4585 struct list
*worklist
= NULL
;
4589 while ((c
= getopt(argc
, argv
, "?havnP:")) != EOF
) {
4598 if (protocol
!= NULL
) {
4599 (void) printf(gettext(
4600 "Specifying multiple protocols "
4601 "not supported: %s\n"), protocol
);
4602 return (SA_SYNTAX_ERR
);
4605 if (!sa_valid_protocol(protocol
)) {
4606 (void) printf(gettext(
4607 "Invalid protocol specified: %s\n"),
4609 return (SA_INVALID_PROTOCOL
);
4616 /* optopt on valid arg isn't defined */
4622 * Since a bad option gets to here, sort it
4623 * out and return a syntax error return value
4628 ret
= SA_SYNTAX_ERR
;
4632 (void) printf(gettext("usage: %s\n"),
4633 sa_get_usage(USAGE_ENABLE
));
4639 if (optind
== argc
&& !all
) {
4640 (void) printf(gettext("usage: %s\n"),
4641 sa_get_usage(USAGE_ENABLE
));
4642 (void) printf(gettext("\tmust specify group\n"));
4643 return (SA_NO_SUCH_PATH
);
4646 while (optind
< argc
) {
4647 group
= sa_get_group(handle
, argv
[optind
]);
4648 if (group
!= NULL
) {
4649 auth
&= check_authorizations(argv
[optind
],
4651 state
= sa_get_group_attr(group
, "state");
4652 if (state
!= NULL
&&
4653 strcmp(state
, "enabled") == 0) {
4654 /* already enabled */
4656 (void) printf(gettext(
4657 "Group \"%s\" is already "
4660 ret
= SA_BUSY
; /* already enabled */
4662 worklist
= add_list(worklist
, group
,
4665 (void) printf(gettext(
4666 "Enabling group \"%s\"\n"),
4670 sa_free_attr_string(state
);
4672 ret
= SA_NO_SUCH_GROUP
;
4677 for (group
= sa_get_group(handle
, NULL
);
4679 group
= sa_get_next_group(group
)) {
4680 worklist
= add_list(worklist
, group
, 0, protocol
);
4683 if (!dryrun
&& ret
== SA_OK
)
4684 ret
= enable_all_groups(handle
, worklist
, 1, 0, NULL
, B_FALSE
);
4686 if (ret
!= SA_OK
&& ret
!= SA_BUSY
)
4687 (void) printf(gettext("Could not enable group: %s\n"),
4692 if (worklist
!= NULL
)
4693 free_list(worklist
);
4694 if (dryrun
&& ret
== SA_OK
&& !auth
&& verbose
) {
4695 (void) printf(gettext("Command would fail: %s\n"),
4696 sa_errorstr(SA_NO_PERMISSION
));
4702 * disable_group(group, proto)
4704 * Disable all the shares in the specified group.. This is a helper
4705 * for disable_all_groups in order to simplify regular and subgroup
4706 * (zfs) disabling. Group has already been checked for non-NULL.
4710 disable_group(sa_group_t group
, char *proto
)
4716 * If the protocol isn't enabled, skip it and treat as
4719 if (!has_protocol(group
, proto
))
4722 for (share
= sa_get_share(group
, NULL
);
4723 share
!= NULL
&& ret
== SA_OK
;
4724 share
= sa_get_next_share(share
)) {
4725 ret
= sa_disable_share(share
, proto
);
4726 if (ret
== SA_NO_SUCH_PATH
) {
4728 * this is OK since the path is gone. we can't
4729 * re-share it anyway so no error.
4738 * disable_all_groups(work, setstate)
4740 * helper function that disables the shares in the list of groups
4741 * provided. It optionally marks the group as disabled. Used by both
4742 * enable and start subcommands.
4746 disable_all_groups(sa_handle_t handle
, struct list
*work
, int setstate
)
4749 sa_group_t subgroup
, group
;
4751 while (work
!= NULL
&& ret
== SA_OK
) {
4752 group
= (sa_group_t
)work
->item
;
4754 ret
= sa_set_group_attr(group
, "state", "disabled");
4757 name
= sa_get_group_attr(group
, "name");
4758 if (name
!= NULL
&& strcmp(name
, "zfs") == 0) {
4759 /* need to get the sub-groups for stopping */
4760 for (subgroup
= sa_get_sub_group(group
);
4762 subgroup
= sa_get_next_group(subgroup
)) {
4763 ret
= disable_group(subgroup
,
4767 ret
= disable_group(group
, work
->proto
);
4770 sa_free_attr_string(name
);
4772 * We don't want to "disable" since it won't come
4773 * up after a reboot. The SMF framework should do
4774 * the right thing. On enable we do want to do
4781 ret
= sa_update_config(handle
);
4786 * sa_disable_group(flags, argc, argv)
4788 * Implements the disable subcommand
4792 sa_disable_group(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
4799 char *protocol
= NULL
;
4801 struct list
*worklist
= NULL
;
4805 while ((c
= getopt(argc
, argv
, "?havn")) != EOF
) {
4814 if (protocol
!= NULL
) {
4815 (void) printf(gettext(
4816 "Specifying multiple protocols "
4817 "not supported: %s\n"), protocol
);
4818 return (SA_SYNTAX_ERR
);
4821 if (!sa_valid_protocol(protocol
)) {
4822 (void) printf(gettext(
4823 "Invalid protocol specified: %s\n"),
4825 return (SA_INVALID_PROTOCOL
);
4832 /* optopt on valid arg isn't defined */
4838 * Since a bad option gets to here, sort it
4839 * out and return a syntax error return value
4844 ret
= SA_SYNTAX_ERR
;
4850 (void) printf(gettext("usage: %s\n"),
4851 sa_get_usage(USAGE_DISABLE
));
4856 if (optind
== argc
&& !all
) {
4857 (void) printf(gettext("usage: %s\n"),
4858 sa_get_usage(USAGE_DISABLE
));
4859 (void) printf(gettext("\tmust specify group\n"));
4860 return (SA_NO_SUCH_PATH
);
4863 while (optind
< argc
) {
4864 group
= sa_get_group(handle
, argv
[optind
]);
4865 if (group
!= NULL
) {
4866 auth
&= check_authorizations(argv
[optind
],
4868 state
= sa_get_group_attr(group
, "state");
4869 if (state
== NULL
||
4870 strcmp(state
, "disabled") == 0) {
4871 /* already disabled */
4873 (void) printf(gettext(
4875 "already disabled\n"),
4877 ret
= SA_BUSY
; /* already disabled */
4879 worklist
= add_list(worklist
, group
, 0,
4882 (void) printf(gettext(
4884 "\"%s\"\n"), argv
[optind
]);
4887 sa_free_attr_string(state
);
4889 ret
= SA_NO_SUCH_GROUP
;
4894 for (group
= sa_get_group(handle
, NULL
);
4896 group
= sa_get_next_group(group
))
4897 worklist
= add_list(worklist
, group
, 0, protocol
);
4900 if (ret
== SA_OK
&& !dryrun
)
4901 ret
= disable_all_groups(handle
, worklist
, 1);
4902 if (ret
!= SA_OK
&& ret
!= SA_BUSY
)
4903 (void) printf(gettext("Could not disable group: %s\n"),
4907 if (worklist
!= NULL
)
4908 free_list(worklist
);
4909 if (dryrun
&& ret
== SA_OK
&& !auth
&& verbose
)
4910 (void) printf(gettext("Command would fail: %s\n"),
4911 sa_errorstr(SA_NO_PERMISSION
));
4916 * sa_start_group(flags, argc, argv)
4918 * Implements the start command.
4919 * This is similar to enable except it doesn't change the state
4920 * of the group(s) and only enables shares if the group is already
4925 sa_start_group(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
4930 int ret
= SMF_EXIT_OK
;
4931 char *protocol
= NULL
;
4933 struct list
*worklist
= NULL
;
4936 while ((c
= getopt(argc
, argv
, "?havP:")) != EOF
) {
4942 if (protocol
!= NULL
) {
4943 (void) printf(gettext(
4944 "Specifying multiple protocols "
4945 "not supported: %s\n"), protocol
);
4946 return (SA_SYNTAX_ERR
);
4949 if (!sa_valid_protocol(protocol
)) {
4950 (void) printf(gettext(
4951 "Invalid protocol specified: %s\n"),
4953 return (SA_INVALID_PROTOCOL
);
4960 /* optopt on valid arg isn't defined */
4966 * Since a bad option gets to here, sort it
4967 * out and return a syntax error return value
4973 ret
= SA_SYNTAX_ERR
;
4979 (void) printf(gettext("usage: %s\n"),
4980 sa_get_usage(USAGE_START
));
4985 if (optind
== argc
&& !all
) {
4986 (void) printf(gettext("usage: %s\n"),
4987 sa_get_usage(USAGE_START
));
4988 return (SMF_EXIT_ERR_FATAL
);
4992 while (optind
< argc
) {
4993 group
= sa_get_group(handle
, argv
[optind
]);
4994 if (group
!= NULL
) {
4995 state
= sa_get_group_attr(group
, "state");
4996 if (state
== NULL
||
4997 strcmp(state
, "enabled") == 0) {
4998 worklist
= add_list(worklist
, group
, 0,
5001 (void) printf(gettext(
5002 "Starting group \"%s\"\n"),
5006 * Determine if there are any
5007 * protocols. If there aren't any,
5008 * then there isn't anything to do in
5009 * any case so no error.
5011 if (sa_get_optionset(group
,
5012 protocol
) != NULL
) {
5017 sa_free_attr_string(state
);
5022 for (group
= sa_get_group(handle
, NULL
);
5024 group
= sa_get_next_group(group
)) {
5025 state
= sa_get_group_attr(group
, "state");
5026 if (state
== NULL
|| strcmp(state
, "enabled") == 0)
5027 worklist
= add_list(worklist
, group
, 0,
5030 sa_free_attr_string(state
);
5034 (void) enable_all_groups(handle
, worklist
, 0, 1, protocol
, B_FALSE
);
5036 if (worklist
!= NULL
)
5037 free_list(worklist
);
5042 * sa_stop_group(flags, argc, argv)
5044 * Implements the stop command.
5045 * This is similar to disable except it doesn't change the state
5046 * of the group(s) and only disables shares if the group is already
5050 sa_stop_group(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
5055 int ret
= SMF_EXIT_OK
;
5056 char *protocol
= NULL
;
5058 struct list
*worklist
= NULL
;
5061 while ((c
= getopt(argc
, argv
, "?havP:")) != EOF
) {
5067 if (protocol
!= NULL
) {
5068 (void) printf(gettext(
5069 "Specifying multiple protocols "
5070 "not supported: %s\n"), protocol
);
5071 return (SA_SYNTAX_ERR
);
5074 if (!sa_valid_protocol(protocol
)) {
5075 (void) printf(gettext(
5076 "Invalid protocol specified: %s\n"),
5078 return (SA_INVALID_PROTOCOL
);
5085 /* optopt on valid arg isn't defined */
5091 * Since a bad option gets to here, sort it
5092 * out and return a syntax error return value
5098 ret
= SA_SYNTAX_ERR
;
5104 (void) printf(gettext("usage: %s\n"),
5105 sa_get_usage(USAGE_STOP
));
5110 if (optind
== argc
&& !all
) {
5111 (void) printf(gettext("usage: %s\n"),
5112 sa_get_usage(USAGE_STOP
));
5113 return (SMF_EXIT_ERR_FATAL
);
5115 while (optind
< argc
) {
5116 group
= sa_get_group(handle
, argv
[optind
]);
5117 if (group
!= NULL
) {
5118 state
= sa_get_group_attr(group
, "state");
5119 if (state
== NULL
||
5120 strcmp(state
, "enabled") == 0) {
5121 worklist
= add_list(worklist
, group
, 0,
5124 (void) printf(gettext(
5125 "Stopping group \"%s\"\n"),
5131 sa_free_attr_string(state
);
5136 for (group
= sa_get_group(handle
, NULL
);
5138 group
= sa_get_next_group(group
)) {
5139 state
= sa_get_group_attr(group
, "state");
5140 if (state
== NULL
|| strcmp(state
, "enabled") == 0)
5141 worklist
= add_list(worklist
, group
, 0,
5144 sa_free_attr_string(state
);
5147 (void) disable_all_groups(handle
, worklist
, 0);
5148 ret
= sa_update_config(handle
);
5150 if (worklist
!= NULL
)
5151 free_list(worklist
);
5156 * remove_all_options(share, proto)
5158 * Removes all options on a share.
5162 remove_all_options(sa_share_t share
, char *proto
)
5164 sa_optionset_t optionset
;
5165 sa_security_t security
;
5166 sa_security_t prevsec
= NULL
;
5168 optionset
= sa_get_optionset(share
, proto
);
5169 if (optionset
!= NULL
)
5170 (void) sa_destroy_optionset(optionset
);
5171 for (security
= sa_get_security(share
, NULL
, NULL
);
5173 security
= sa_get_next_security(security
)) {
5176 * We walk through the list. prevsec keeps the
5177 * previous security so we can delete it without
5178 * destroying the list.
5180 if (prevsec
!= NULL
) {
5181 /* remove the previously seen security */
5182 (void) sa_destroy_security(prevsec
);
5183 /* set to NULL so we don't try multiple times */
5186 type
= sa_get_security_attr(security
, "type");
5189 * if the security matches the specified protocol, we
5190 * want to remove it. prevsec holds it until either
5191 * the next pass or we fall out of the loop.
5193 if (strcmp(type
, proto
) == 0)
5195 sa_free_attr_string(type
);
5198 /* in case there is one left */
5199 if (prevsec
!= NULL
)
5200 (void) sa_destroy_security(prevsec
);
5205 * for legacy support, we need to handle the old syntax. This is what
5206 * we get if sharemgr is called with the name "share" rather than
5211 format_legacy_path(char *buff
, int buffsize
, char *proto
, char *cmd
)
5215 err
= snprintf(buff
, buffsize
, "/usr/lib/fs/%s/%s", proto
, cmd
);
5223 * check_legacy_cmd(proto, cmd)
5225 * Check to see if the cmd exists in /usr/lib/fs/<proto>/<cmd> and is
5230 check_legacy_cmd(char *path
)
5235 if (stat(path
, &st
) == 0) {
5236 if (S_ISREG(st
.st_mode
) &&
5237 st
.st_mode
& (S_IXUSR
|S_IXGRP
|S_IXOTH
))
5244 * run_legacy_command(proto, cmd, argv)
5246 * We know the command exists, so attempt to execute it with all the
5247 * arguments. This implements full legacy share support for those
5248 * protocols that don't have plugin providers.
5252 run_legacy_command(char *path
, char *argv
[])
5256 ret
= execv(path
, argv
);
5260 ret
= SA_NO_PERMISSION
;
5263 ret
= SA_SYSTEM_ERR
;
5271 * out_share(out, group, proto)
5273 * Display the share information in the format that the "share"
5274 * command has traditionally used.
5278 out_share(FILE *out
, sa_group_t group
, char *proto
)
5285 * The original share command defaulted to displaying NFS
5286 * shares or allowed a protocol to be specified. We want to
5287 * skip those shares that are not the specified protocol.
5289 if (proto
!= NULL
&& sa_get_optionset(group
, proto
) == NULL
)
5296 * get the default property string. NFS uses "rw" but
5297 * everything else will use "".
5299 if (proto
!= NULL
&& strcmp(proto
, "nfs") != 0)
5304 for (share
= sa_get_share(group
, NULL
);
5306 share
= sa_get_next_share(share
)) {
5315 char shareopts
[MAXNAMLEN
];
5317 sharedstate
= sa_get_share_attr(share
, "shared");
5318 path
= sa_get_share_attr(share
, "path");
5319 type
= sa_get_share_attr(share
, "type");
5320 resource
= get_resource(share
);
5321 groupname
= sa_get_group_attr(group
, "name");
5323 if (groupname
!= NULL
&& strcmp(groupname
, "default") == 0) {
5324 sa_free_attr_string(groupname
);
5327 description
= sa_get_share_description(share
);
5330 * Want the sharetab version if it exists, defaulting
5331 * to NFS if no protocol specified.
5333 (void) snprintf(shareopts
, MAXNAMLEN
, "shareopts-%s", proto
);
5334 soptions
= sa_get_share_attr(share
, shareopts
);
5336 if (sharedstate
== NULL
)
5339 if (soptions
== NULL
)
5340 soptions
= sa_proto_legacy_format(proto
, share
, 1);
5343 /* only active shares go here */
5344 (void) snprintf(resfmt
, sizeof (resfmt
), "%s%s%s",
5345 resource
!= NULL
? resource
: "-",
5346 groupname
!= NULL
? "@" : "",
5347 groupname
!= NULL
? groupname
: "");
5348 (void) fprintf(out
, "%-14.14s %s %s \"%s\" \n",
5349 resfmt
, (path
!= NULL
) ? path
: "",
5350 (soptions
!= NULL
&& strlen(soptions
) > 0) ?
5352 (description
!= NULL
) ? description
: "");
5356 sa_free_attr_string(path
);
5358 sa_free_attr_string(type
);
5359 if (resource
!= NULL
)
5360 sa_free_attr_string(resource
);
5361 if (groupname
!= NULL
)
5362 sa_free_attr_string(groupname
);
5363 if (description
!= NULL
)
5364 sa_free_share_description(description
);
5365 if (sharedstate
!= NULL
)
5366 sa_free_attr_string(sharedstate
);
5367 if (soptions
!= NULL
)
5368 sa_format_free(soptions
);
5373 * output_legacy_file(out, proto)
5375 * Walk all of the groups for the specified protocol and call
5376 * out_share() to format and write in the format displayed by the
5377 * "share" command with no arguments.
5381 output_legacy_file(FILE *out
, char *proto
, sa_handle_t handle
)
5385 for (group
= sa_get_group(handle
, NULL
);
5387 group
= sa_get_next_group(group
)) {
5391 * Go through all the groups and ZFS
5392 * sub-groups. out_share() will format the shares in
5393 * the group appropriately.
5396 zfs
= sa_get_group_attr(group
, "zfs");
5399 sa_free_attr_string(zfs
);
5400 for (zgroup
= sa_get_sub_group(group
);
5402 zgroup
= sa_get_next_group(zgroup
)) {
5404 /* got a group, so display it */
5405 out_share(out
, zgroup
, proto
);
5408 out_share(out
, group
, proto
);
5414 sa_legacy_share(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
5416 char *protocol
= "nfs";
5417 char *options
= NULL
;
5418 char *description
= NULL
;
5419 char *groupname
= NULL
;
5420 char *sharepath
= NULL
;
5421 char *resource
= NULL
;
5422 char *groupstatus
= NULL
;
5423 int persist
= SA_SHARE_TRANSIENT
;
5428 int true_legacy
= 0;
5429 int curtype
= SA_SHARE_TRANSIENT
;
5430 char cmd
[MAXPATHLEN
];
5431 sa_group_t group
= NULL
;
5432 sa_resource_t rsrc
= NULL
;
5434 char dir
[MAXPATHLEN
];
5437 while ((c
= getopt(argc
, argv
, "?hF:d:o:p")) != EOF
) {
5440 description
= optarg
;
5445 if (!sa_valid_protocol(protocol
)) {
5446 if (format_legacy_path(cmd
, MAXPATHLEN
,
5447 protocol
, "share") == 0 &&
5448 check_legacy_cmd(cmd
)) {
5451 (void) fprintf(stderr
, gettext(
5452 "Invalid protocol specified: "
5454 return (SA_INVALID_PROTOCOL
);
5463 persist
= SA_SHARE_PERMANENT
;
5467 /* optopt on valid arg isn't defined */
5473 * Since a bad option gets to here, sort it
5474 * out and return a syntax error return value
5479 ret
= SA_LEGACY_ERR
;
5485 (void) fprintf(stderr
, gettext("usage: %s\n"),
5486 sa_get_usage(USAGE_SHARE
));
5491 /* Have the info so construct what is needed */
5492 if (!argsused
&& optind
== argc
) {
5493 /* display current info in share format */
5494 (void) output_legacy_file(stdout
, protocol
, handle
);
5498 /* We are modifying the configuration */
5499 if (optind
== argc
) {
5500 (void) fprintf(stderr
, gettext("usage: %s\n"),
5501 sa_get_usage(USAGE_SHARE
));
5502 return (SA_LEGACY_ERR
);
5505 /* If still using legacy share/unshare, exec it */
5506 ret
= run_legacy_command(cmd
, argv
);
5510 sharepath
= argv
[optind
++];
5511 if (optind
< argc
) {
5512 resource
= argv
[optind
];
5513 groupname
= strchr(resource
, '@');
5514 if (groupname
!= NULL
)
5515 *groupname
++ = '\0';
5517 if (realpath(sharepath
, dir
) == NULL
)
5522 share
= sa_find_share(handle
, sharepath
);
5526 features
= sa_proto_get_featureset(protocol
);
5528 if (groupname
!= NULL
) {
5529 ret
= SA_NOT_ALLOWED
;
5530 } else if (ret
== SA_OK
) {
5533 * The legacy group is always present and zfs groups
5534 * come and go. zfs shares may be in sub-groups and
5535 * the zfs share will already be in that group so it
5536 * isn't an error. If the protocol is "smb", the group
5537 * "smb" is used when "default" would otherwise be
5538 * used. "default" is NFS only and "smb" is SMB only.
5540 if (strcmp(protocol
, "smb") == 0)
5541 legacygroup
= "smb";
5543 legacygroup
= "default";
5546 * If the share exists (not NULL), then make sure it
5547 * is one we want to handle by getting the parent
5550 if (share
!= NULL
) {
5551 group
= sa_get_parent_group(share
);
5553 group
= sa_get_group(handle
, legacygroup
);
5554 if (group
== NULL
&& strcmp(legacygroup
, "smb") == 0) {
5556 * This group may not exist, so create
5557 * as necessary. It only contains the
5560 group
= sa_create_group(handle
, legacygroup
,
5563 (void) sa_create_optionset(group
,
5568 if (group
== NULL
) {
5569 ret
= SA_SYSTEM_ERR
;
5573 groupstatus
= group_status(group
);
5574 if (share
== NULL
) {
5575 share
= sa_add_share(group
, sharepath
,
5577 if (share
== NULL
&&
5578 ret
== SA_DUPLICATE_NAME
) {
5580 * Could be a ZFS path being started
5582 if (sa_zfs_is_shared(handle
,
5585 group
= sa_get_group(handle
,
5587 if (group
== NULL
) {
5592 ret
= SA_CONFIG_ERR
;
5594 share
= sa_add_share(
5603 * May want to change persist state, but the
5604 * important thing is to change options. We
5605 * need to change them regardless of the
5609 if (sa_zfs_is_shared(handle
, sharepath
)) {
5612 remove_all_options(share
, protocol
);
5613 type
= sa_get_share_attr(share
, "type");
5615 strcmp(type
, "transient") != 0) {
5616 curtype
= SA_SHARE_PERMANENT
;
5619 sa_free_attr_string(type
);
5620 if (curtype
!= persist
) {
5621 (void) sa_set_share_attr(share
, "type",
5622 persist
== SA_SHARE_PERMANENT
?
5623 "persist" : "transient");
5628 * If there is a resource name, we may
5629 * actually care about it if this is share for
5630 * a protocol that uses resource level sharing
5631 * (SMB). We need to find the resource and, if
5632 * it exists, make sure it belongs to the
5633 * current share. If it doesn't exist, attempt
5637 if (ret
== SA_OK
&& resource
!= NULL
) {
5638 rsrc
= sa_find_resource(handle
, resource
);
5640 if (share
!= sa_get_resource_parent(rsrc
))
5641 ret
= SA_DUPLICATE_NAME
;
5643 rsrc
= sa_add_resource(share
, resource
,
5646 if (features
& SA_FEATURE_RESOURCE
)
5650 /* Have a group to hold this share path */
5651 if (ret
== SA_OK
&& options
!= NULL
&&
5652 strlen(options
) > 0) {
5653 ret
= sa_parse_legacy_options(share
,
5659 * ZFS shares never have a description
5660 * and we can't store the values so
5663 if (ret
== SA_OK
&& description
!= NULL
)
5664 ret
= sa_set_share_description(share
,
5668 strcmp(groupstatus
, "enabled") == 0) {
5670 ret
= sa_enable_share(share
, protocol
);
5672 ret
= sa_enable_resource(rsrc
,
5675 persist
== SA_SHARE_PERMANENT
) {
5676 (void) sa_update_legacy(share
,
5680 ret
= sa_update_config(handle
);
5685 (void) fprintf(stderr
, gettext("Could not share: %s: %s\n"),
5686 sharepath
, sa_errorstr(ret
));
5687 ret
= SA_LEGACY_ERR
;
5693 * sa_legacy_unshare(flags, argc, argv)
5695 * Implements the original unshare command.
5698 sa_legacy_unshare(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
5700 char *protocol
= "nfs"; /* for now */
5701 char *options
= NULL
;
5702 char *sharepath
= NULL
;
5703 int persist
= SA_SHARE_TRANSIENT
;
5707 int true_legacy
= 0;
5708 uint64_t features
= 0;
5709 sa_resource_t resource
= NULL
;
5710 char cmd
[MAXPATHLEN
];
5712 while ((c
= getopt(argc
, argv
, "?hF:o:p")) != EOF
) {
5716 if (!sa_valid_protocol(protocol
)) {
5717 if (format_legacy_path(cmd
, MAXPATHLEN
,
5718 protocol
, "unshare") == 0 &&
5719 check_legacy_cmd(cmd
)) {
5722 (void) printf(gettext(
5723 "Invalid file system name\n"));
5724 return (SA_INVALID_PROTOCOL
);
5733 persist
= SA_SHARE_PERMANENT
;
5737 /* optopt on valid arg isn't defined */
5743 * Since a bad option gets to here, sort it
5744 * out and return a syntax error return value
5749 ret
= SA_LEGACY_ERR
;
5755 (void) printf(gettext("usage: %s\n"),
5756 sa_get_usage(USAGE_UNSHARE
));
5761 /* Have the info so construct what is needed */
5762 if (optind
== argc
|| (optind
+ 1) < argc
|| options
!= NULL
) {
5763 ret
= SA_SYNTAX_ERR
;
5766 char dir
[MAXPATHLEN
];
5768 /* if still using legacy share/unshare, exec it */
5769 ret
= run_legacy_command(cmd
, argv
);
5773 * Find the path in the internal configuration. If it
5774 * isn't found, attempt to resolve the path via
5775 * realpath() and try again.
5777 sharepath
= argv
[optind
++];
5778 share
= sa_find_share(handle
, sharepath
);
5779 if (share
== NULL
) {
5780 if (realpath(sharepath
, dir
) == NULL
) {
5781 ret
= SA_NO_SUCH_PATH
;
5783 share
= sa_find_share(handle
, dir
);
5786 if (share
== NULL
) {
5787 /* Could be a resource name so check that next */
5788 features
= sa_proto_get_featureset(protocol
);
5789 resource
= sa_find_resource(handle
, sharepath
);
5790 if (resource
!= NULL
) {
5791 share
= sa_get_resource_parent(resource
);
5792 if (features
& SA_FEATURE_RESOURCE
)
5793 (void) sa_disable_resource(resource
,
5795 if (persist
== SA_SHARE_PERMANENT
) {
5796 ret
= sa_remove_resource(resource
);
5798 ret
= sa_update_config(handle
);
5801 * If we still have a resource on the
5802 * share, we don't disable the share
5803 * itself. IF there aren't anymore, we
5804 * need to remove the share. The
5805 * removal will be done in the next
5806 * section if appropriate.
5808 resource
= sa_get_share_resource(share
, NULL
);
5809 if (resource
!= NULL
)
5811 } else if (ret
== SA_OK
) {
5812 /* Didn't find path and no resource */
5816 if (share
!= NULL
&& resource
== NULL
) {
5817 ret
= sa_disable_share(share
, protocol
);
5819 * Errors are ok and removal should still occur. The
5820 * legacy unshare is more forgiving of errors than the
5821 * remove-share subcommand which may need the force
5822 * flag set for some error conditions. That is, the
5823 * "unshare" command will always unshare if it can
5824 * while "remove-share" might require the force option.
5826 if (persist
== SA_SHARE_PERMANENT
) {
5827 ret
= sa_remove_share(share
);
5829 ret
= sa_update_config(handle
);
5831 } else if (ret
== SA_OK
&& share
== NULL
&& resource
== NULL
) {
5833 * If both share and resource are NULL, then
5834 * share not found. If one or the other was
5835 * found or there was an earlier error, we
5836 * assume it was handled earlier.
5838 ret
= SA_NOT_SHARED
;
5843 (void) printf("%s: %s\n", sharepath
, sa_errorstr(ret
));
5844 ret
= SA_LEGACY_ERR
;
5847 (void) printf(gettext("usage: %s\n"),
5848 sa_get_usage(USAGE_UNSHARE
));
5857 * Common commands that implement the sub-commands used by all
5858 * protocols. The entries are found via the lookup command
5861 static sa_command_t commands
[] = {
5862 {"add-share", 0, sa_addshare
, USAGE_ADD_SHARE
, SVC_SET
},
5863 {"create", 0, sa_create
, USAGE_CREATE
, SVC_SET
|SVC_ACTION
},
5864 {"delete", 0, sa_delete
, USAGE_DELETE
, SVC_SET
|SVC_ACTION
},
5865 {"disable", 0, sa_disable_group
, USAGE_DISABLE
, SVC_SET
|SVC_ACTION
},
5866 {"enable", 0, sa_enable_group
, USAGE_ENABLE
, SVC_SET
|SVC_ACTION
},
5867 {"list", 0, sa_list
, USAGE_LIST
},
5868 {"move-share", 0, sa_moveshare
, USAGE_MOVE_SHARE
, SVC_SET
},
5869 {"remove-share", 0, sa_removeshare
, USAGE_REMOVE_SHARE
, SVC_SET
},
5870 {"set", 0, sa_set
, USAGE_SET
, SVC_SET
},
5871 {"set-share", 0, sa_set_share
, USAGE_SET_SHARE
, SVC_SET
},
5872 {"show", 0, sa_show
, USAGE_SHOW
},
5873 {"share", 0, sa_legacy_share
, USAGE_SHARE
, SVC_SET
|SVC_ACTION
},
5874 {"start", CMD_NODISPLAY
, sa_start_group
, USAGE_START
,
5875 SVC_SET
|SVC_ACTION
},
5876 {"stop", CMD_NODISPLAY
, sa_stop_group
, USAGE_STOP
, SVC_SET
|SVC_ACTION
},
5877 {"unset", 0, sa_unset
, USAGE_UNSET
, SVC_SET
},
5878 {"unshare", 0, sa_legacy_unshare
, USAGE_UNSHARE
, SVC_SET
|SVC_ACTION
},
5883 sa_get_usage(sa_usage_t index
)
5887 case USAGE_ADD_SHARE
:
5888 ret
= gettext("add-share [-nth] [-r resource-name] "
5889 "[-d \"description text\"] -s sharepath group");
5893 "create [-nvh] [-P proto [-p property=value]] group");
5896 ret
= gettext("delete [-nvh] [-P proto] [-f] group");
5899 ret
= gettext("disable [-nvh] {-a | group ...}");
5902 ret
= gettext("enable [-nvh] {-a | group ...}");
5905 ret
= gettext("list [-vh] [-P proto]");
5907 case USAGE_MOVE_SHARE
:
5909 "move-share [-nvh] -s sharepath destination-group");
5911 case USAGE_REMOVE_SHARE
:
5913 "remove-share [-fnvh] {-s sharepath | -r resource} "
5917 ret
= gettext("set [-nvh] -P proto [-S optspace] "
5918 "[-p property=value]* [-s sharepath] [-r resource]] "
5921 case USAGE_SET_SECURITY
:
5922 ret
= gettext("set-security [-nvh] -P proto -S security-type "
5923 "[-p property=value]* group");
5925 case USAGE_SET_SHARE
:
5926 ret
= gettext("set-share [-nh] [-r resource] "
5927 "[-d \"description text\"] -s sharepath group");
5930 ret
= gettext("show [-pvxh] [-P proto] [group ...]");
5933 ret
= gettext("share [-F fstype] [-p] [-o optionlist]"
5934 "[-d description] [pathname [resourcename]]");
5937 ret
= gettext("start [-vh] [-P proto] {-a | group ...}");
5940 ret
= gettext("stop [-vh] [-P proto] {-a | group ...}");
5943 ret
= gettext("unset [-nvh] -P proto [-S optspace] "
5944 "[-p property]* group");
5946 case USAGE_UNSET_SECURITY
:
5947 ret
= gettext("unset-security [-nvh] -P proto "
5948 "-S security-type [-p property]* group");
5952 "unshare [-F fstype] [-p] [-o optionlist] sharepath");
5959 * sa_lookup(cmd, proto)
5961 * Lookup the sub-command. proto isn't currently used, but it may
5962 * eventually provide a way to provide protocol specific sub-commands.
5965 sa_lookup(char *cmd
, char *proto
)
5971 for (i
= 0; commands
[i
].cmdname
!= NULL
; i
++) {
5972 if (strncmp(cmd
, commands
[i
].cmdname
, len
) == 0)
5973 return (&commands
[i
]);
5979 sub_command_help(char *proto
)
5983 (void) printf(gettext("\tsub-commands:\n"));
5984 for (i
= 0; commands
[i
].cmdname
!= NULL
; i
++) {
5985 if (!(commands
[i
].flags
& (CMD_ALIAS
|CMD_NODISPLAY
)))
5986 (void) printf("\t%s\n",
5987 sa_get_usage((sa_usage_t
)commands
[i
].cmdidx
));