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
) {
1171 if (protolist
!= NULL
)
1178 * sa_create(flags, argc, argv)
1179 * create a new group
1180 * this may or may not have a protocol associated with it.
1181 * No protocol means "all" protocols in this case.
1184 sa_create(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
1189 boolean_t force
= B_FALSE
;
1190 boolean_t verbose
= B_FALSE
;
1191 boolean_t dryrun
= B_FALSE
;
1193 char *protocol
= NULL
;
1195 struct options
*optlist
= NULL
;
1198 boolean_t created
= B_FALSE
;
1200 while ((c
= getopt(argc
, argv
, "?fhvnP:p:")) != EOF
) {
1212 if (protocol
!= NULL
) {
1213 (void) printf(gettext("Specifying "
1214 "multiple protocols "
1215 "not supported: %s\n"), protocol
);
1216 return (SA_SYNTAX_ERR
);
1219 if (sa_valid_protocol(protocol
))
1221 (void) printf(gettext(
1222 "Invalid protocol specified: %s\n"), protocol
);
1223 return (SA_INVALID_PROTOCOL
);
1225 ret
= add_opt(&optlist
, optarg
, 0);
1227 case OPT_ADD_SYNTAX
:
1228 (void) printf(gettext(
1229 "Property syntax error for property: %s\n"),
1231 return (SA_SYNTAX_ERR
);
1232 case OPT_ADD_SECURITY
:
1233 (void) printf(gettext(
1234 "Security properties need "
1235 "to be set with set-security: %s\n"),
1237 return (SA_SYNTAX_ERR
);
1243 /* optopt on valid arg isn't defined */
1249 * Since a bad option gets to here, sort it
1250 * out and return a syntax error return value
1255 err
= SA_SYNTAX_ERR
;
1261 (void) printf(gettext("usage: %s\n"),
1262 sa_get_usage(USAGE_CREATE
));
1267 if (optind
>= argc
) {
1268 (void) printf(gettext("usage: %s\n"),
1269 sa_get_usage(USAGE_CREATE
));
1270 (void) printf(gettext("\tgroup must be specified.\n"));
1271 return (SA_BAD_PATH
);
1274 if ((optind
+ 1) < argc
) {
1275 (void) printf(gettext("usage: %s\n"),
1276 sa_get_usage(USAGE_CREATE
));
1277 (void) printf(gettext("\textraneous group(s) at end\n"));
1278 return (SA_SYNTAX_ERR
);
1281 if (protocol
== NULL
&& optlist
!= NULL
) {
1282 /* lookup default protocol */
1283 (void) printf(gettext("usage: %s\n"),
1284 sa_get_usage(USAGE_CREATE
));
1285 (void) printf(gettext("\tprotocol must be specified "
1286 "with properties\n"));
1287 return (SA_INVALID_PROTOCOL
);
1290 if (optlist
!= NULL
)
1291 ret
= chk_opt(optlist
, 0, protocol
);
1292 if (ret
== OPT_ADD_SECURITY
) {
1293 (void) printf(gettext("Security properties not "
1294 "supported with create\n"));
1295 return (SA_SYNTAX_ERR
);
1299 * If a group already exists, we can only add a new protocol
1300 * to it and not create a new one or add the same protocol
1304 groupname
= argv
[optind
];
1306 auth
= check_authorizations(groupname
, flags
);
1308 group
= sa_get_group(handle
, groupname
);
1309 if (group
!= NULL
) {
1310 /* group exists so must be a protocol add */
1311 ret
= check_valid_group(group
, groupname
, protocol
);
1314 * is it a valid name? Must comply with SMF instance
1315 * name restrictions.
1317 if (!sa_valid_group_name(groupname
)) {
1318 ret
= SA_INVALID_NAME
;
1319 (void) printf(gettext("Invalid group name: %s\n"),
1324 /* check protocol vs optlist */
1325 if (optlist
!= NULL
) {
1326 /* check options, if any, for validity */
1327 ret
= valid_options(handle
, optlist
, protocol
,
1331 if (ret
== SA_OK
&& !dryrun
) {
1332 if (group
== NULL
) {
1333 group
= sa_create_group(handle
, (char *)groupname
,
1337 if (group
!= NULL
) {
1338 sa_optionset_t optionset
;
1341 * Check group and protocol against featureset
1344 ret
= enforce_featureset(group
, protocol
,
1350 * So far so good. Now add the required
1351 * optionset(s) to the group.
1353 if (optlist
!= NULL
) {
1354 (void) add_optionset(group
, optlist
, protocol
,
1356 } else if (protocol
!= NULL
) {
1357 optionset
= sa_create_optionset(group
,
1359 if (optionset
== NULL
)
1361 } else if (protocol
== NULL
) {
1362 /* default group create so add all protocols */
1363 ret
= set_all_protocols(group
);
1366 * We have a group and legal additions
1370 * Commit to configuration for protocols that
1371 * need to do block updates. For NFS, this
1372 * doesn't do anything but it will be run for
1373 * all protocols that implement the
1374 * appropriate plugin.
1376 ret
= sa_update_config(handle
);
1379 (void) sa_remove_group(group
);
1383 (void) printf(gettext("Could not create group: %s\n"),
1387 if (dryrun
&& ret
== SA_OK
&& !auth
&& verbose
) {
1388 (void) printf(gettext("Command would fail: %s\n"),
1389 sa_errorstr(SA_NO_PERMISSION
));
1390 ret
= SA_NO_PERMISSION
;
1393 if (ret
!= SA_OK
&& created
)
1394 ret
= sa_remove_group(group
);
1401 * group_status(group)
1403 * return the current status (enabled/disabled) of the group.
1407 group_status(sa_group_t group
)
1412 state
= sa_get_group_attr(group
, "state");
1413 if (state
!= NULL
) {
1414 if (strcmp(state
, "enabled") == 0) {
1417 sa_free_attr_string(state
);
1419 return (enabled
? "enabled" : "disabled");
1423 * sa_delete(flags, argc, argv)
1429 sa_delete(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
1438 char *protocol
= NULL
;
1439 char *sectype
= NULL
;
1443 while ((c
= getopt(argc
, argv
, "?hvnP:fS:")) != EOF
) {
1452 if (protocol
!= NULL
) {
1453 (void) printf(gettext("Specifying "
1454 "multiple protocols "
1455 "not supported: %s\n"), protocol
);
1456 return (SA_SYNTAX_ERR
);
1459 if (!sa_valid_protocol(protocol
)) {
1460 (void) printf(gettext("Invalid protocol "
1461 "specified: %s\n"), protocol
);
1462 return (SA_INVALID_PROTOCOL
);
1466 if (sectype
!= NULL
) {
1467 (void) printf(gettext("Specifying "
1468 "multiple property "
1469 "spaces not supported: %s\n"), sectype
);
1470 return (SA_SYNTAX_ERR
);
1478 /* optopt on valid arg isn't defined */
1484 * Since a bad option gets to here, sort it
1485 * out and return a syntax error return value
1490 ret
= SA_SYNTAX_ERR
;
1496 (void) printf(gettext("usage: %s\n"),
1497 sa_get_usage(USAGE_DELETE
));
1502 if (optind
>= argc
) {
1503 (void) printf(gettext("usage: %s\n"),
1504 sa_get_usage(USAGE_DELETE
));
1505 (void) printf(gettext("\tgroup must be specified.\n"));
1506 return (SA_SYNTAX_ERR
);
1509 if ((optind
+ 1) < argc
) {
1510 (void) printf(gettext("usage: %s\n"),
1511 sa_get_usage(USAGE_DELETE
));
1512 (void) printf(gettext("\textraneous group(s) at end\n"));
1513 return (SA_SYNTAX_ERR
);
1516 if (sectype
!= NULL
&& protocol
== NULL
) {
1517 (void) printf(gettext("usage: %s\n"),
1518 sa_get_usage(USAGE_DELETE
));
1519 (void) printf(gettext("\tsecurity requires protocol to be "
1521 return (SA_SYNTAX_ERR
);
1525 * Determine if the group already exists since it must in
1526 * order to be removed.
1528 * We can delete when:
1531 * - force flag is set
1532 * - if protocol specified, only delete the protocol
1535 groupname
= argv
[optind
];
1536 group
= sa_get_group(handle
, groupname
);
1537 if (group
== NULL
) {
1538 ret
= SA_NO_SUCH_GROUP
;
1541 auth
= check_authorizations(groupname
, flags
);
1542 if (protocol
== NULL
) {
1543 share
= sa_get_share(group
, NULL
);
1546 if (share
== NULL
|| (share
!= NULL
&& force
== 1)) {
1549 while (share
!= NULL
) {
1550 sa_share_t next_share
;
1551 next_share
= sa_get_next_share(share
);
1553 * need to do the disable of
1554 * each share, but don't
1555 * actually do anything on a
1558 ret
= sa_disable_share(share
, NULL
);
1559 ret
= sa_remove_share(share
);
1562 ret
= sa_remove_group(group
);
1565 /* Commit to configuration if not a dryrun */
1566 if (!dryrun
&& ret
== SA_OK
) {
1567 ret
= sa_update_config(handle
);
1570 /* a protocol delete */
1571 sa_optionset_t optionset
;
1572 sa_security_t security
;
1573 if (sectype
!= NULL
) {
1574 /* only delete specified security */
1575 security
= sa_get_security(group
, sectype
, protocol
);
1576 if (security
!= NULL
&& !dryrun
)
1577 ret
= sa_destroy_security(security
);
1579 ret
= SA_INVALID_PROTOCOL
;
1581 optionset
= sa_get_optionset(group
, protocol
);
1582 if (optionset
!= NULL
&& !dryrun
) {
1584 * have an optionset with
1585 * protocol to delete
1587 ret
= sa_destroy_optionset(optionset
);
1589 * Now find all security sets
1590 * for the protocol and remove
1591 * them. Don't remove other
1595 sa_get_security(group
, NULL
, NULL
);
1596 ret
== SA_OK
&& security
!= NULL
;
1597 security
= sa_get_next_security(security
)) {
1599 secprot
= sa_get_security_attr(security
,
1601 if (secprot
!= NULL
&&
1602 strcmp(secprot
, protocol
) == 0)
1603 ret
= sa_destroy_security(
1605 if (secprot
!= NULL
)
1606 sa_free_attr_string(secprot
);
1610 ret
= SA_INVALID_PROTOCOL
;
1614 * With the protocol items removed, make sure that all
1615 * the shares are updated in the legacy files, if
1618 for (share
= sa_get_share(group
, NULL
);
1620 share
= sa_get_next_share(share
)) {
1621 (void) sa_delete_legacy(share
, protocol
);
1627 (void) printf(gettext("Could not delete group: %s\n"),
1629 } else if (dryrun
&& !auth
&& verbose
) {
1630 (void) printf(gettext("Command would fail: %s\n"),
1631 sa_errorstr(SA_NO_PERMISSION
));
1637 * strndupr(*buff, str, buffsize)
1639 * used with small strings to duplicate and possibly increase the
1640 * buffer size of a string.
1643 strndupr(char *buff
, char *str
, int *buffsize
)
1646 char *orig_buff
= buff
;
1649 buff
= (char *)malloc(64);
1655 limit
= strlen(buff
) + strlen(str
) + 1;
1656 if (limit
> *buffsize
) {
1657 limit
= *buffsize
= *buffsize
+ ((limit
/ 64) + 64);
1658 buff
= realloc(buff
, limit
);
1661 (void) strcat(buff
, str
);
1663 /* if it fails, fail it hard */
1664 if (orig_buff
!= NULL
)
1671 * group_proto(group)
1673 * return a string of all the protocols (space separated) associated
1678 group_proto(sa_group_t group
)
1680 sa_optionset_t optionset
;
1686 * get the protocol list by finding the optionsets on this
1687 * group and extracting the type value. The initial call to
1688 * strndupr() initailizes buff.
1690 buff
= strndupr(buff
, "", &buffsize
);
1692 for (optionset
= sa_get_optionset(group
, NULL
);
1693 optionset
!= NULL
&& buff
!= NULL
;
1694 optionset
= sa_get_next_optionset(optionset
)) {
1696 * extract out the protocol type from this optionset
1697 * and append it to the buffer "buff". strndupr() will
1698 * reallocate space as necessay.
1700 proto
= sa_get_optionset_attr(optionset
, "type");
1701 if (proto
!= NULL
) {
1703 buff
= strndupr(buff
, " ", &buffsize
);
1704 buff
= strndupr(buff
, proto
, &buffsize
);
1705 sa_free_attr_string(proto
);
1713 * sa_list(flags, argc, argv)
1715 * implements the "list" subcommand to list groups and optionally
1716 * their state and protocols.
1720 sa_list(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
1725 char *protocol
= NULL
;
1731 while ((c
= getopt(argc
, argv
, "?hvP:")) != EOF
) {
1737 if (protocol
!= NULL
) {
1738 (void) printf(gettext(
1739 "Specifying multiple protocols "
1740 "not supported: %s\n"),
1742 return (SA_SYNTAX_ERR
);
1745 if (!sa_valid_protocol(protocol
)) {
1746 (void) printf(gettext(
1747 "Invalid protocol specified: %s\n"),
1749 return (SA_INVALID_PROTOCOL
);
1753 /* optopt on valid arg isn't defined */
1759 * Since a bad option gets to here, sort it
1760 * out and return a syntax error return value
1765 ret
= SA_SYNTAX_ERR
;
1771 (void) printf(gettext("usage: %s\n"),
1772 sa_get_usage(USAGE_LIST
));
1777 if (optind
!= argc
) {
1778 (void) printf(gettext("usage: %s\n"),
1779 sa_get_usage(USAGE_LIST
));
1780 return (SA_SYNTAX_ERR
);
1783 for (group
= sa_get_group(handle
, NULL
);
1785 group
= sa_get_next_group(group
)) {
1788 if (protocol
== NULL
|| has_protocol(group
, protocol
)) {
1789 name
= sa_get_group_attr(group
, "name");
1790 if (name
!= NULL
&& (verbose
> 1 || name
[0] != '#')) {
1791 (void) printf("%s", (char *)name
);
1794 * Need the list of protocols
1795 * and current status once
1796 * available. We do want to
1798 * enabled/disabled text here.
1800 (void) printf("\t%s", isenabled(group
) ?
1801 gettext("enabled") :
1802 gettext("disabled"));
1803 proto
= group_proto(group
);
1804 if (proto
!= NULL
) {
1805 (void) printf("\t%s",
1810 (void) printf("\n");
1813 sa_free_attr_string(name
);
1820 * out_properties(optionset, proto, sec)
1822 * Format the properties and encode the protocol and optional named
1823 * optionset into the string.
1825 * format is protocol[:name]=(property-list)
1829 out_properties(sa_optionset_t optionset
, char *proto
, char *sec
)
1837 (void) printf(" %s=(", proto
? proto
: gettext("all"));
1839 (void) printf(" %s:%s=(", proto
? proto
: gettext("all"), sec
);
1841 for (spacer
= 0, prop
= sa_get_property(optionset
, NULL
);
1843 prop
= sa_get_next_property(prop
)) {
1846 * extract the property name/value and output with
1847 * appropriate spacing. I.e. no prefixed space the
1848 * first time through but a space on subsequent
1851 type
= sa_get_property_attr(prop
, "type");
1852 value
= sa_get_property_attr(prop
, "value");
1854 (void) printf("%s%s=", spacer
? " " : "", type
);
1857 (void) printf("\"%s\"", value
);
1859 (void) printf("\"\"");
1862 sa_free_attr_string(type
);
1864 sa_free_attr_string(value
);
1870 * show_properties(group, protocol, prefix)
1872 * print the properties for a group. If protocol is NULL, do all
1873 * protocols otherwise only the specified protocol. All security
1874 * (named groups specific to the protocol) are included.
1876 * The "prefix" is always applied. The caller knows whether it wants
1877 * some type of prefix string (white space) or not. Once the prefix
1878 * has been output, it is reduced to the zero length string for the
1879 * remainder of the property output.
1883 show_properties(sa_group_t group
, char *protocol
, char *prefix
)
1885 sa_optionset_t optionset
;
1886 sa_security_t security
;
1890 if (protocol
!= NULL
) {
1891 optionset
= sa_get_optionset(group
, protocol
);
1892 if (optionset
!= NULL
) {
1893 (void) printf("%s", prefix
);
1895 out_properties(optionset
, protocol
, NULL
);
1897 security
= sa_get_security(group
, protocol
, NULL
);
1898 if (security
!= NULL
) {
1899 (void) printf("%s", prefix
);
1901 out_properties(security
, protocol
, NULL
);
1904 for (optionset
= sa_get_optionset(group
, protocol
);
1906 optionset
= sa_get_next_optionset(optionset
)) {
1908 value
= sa_get_optionset_attr(optionset
, "type");
1909 (void) printf("%s", prefix
);
1911 out_properties(optionset
, value
, 0);
1913 sa_free_attr_string(value
);
1915 for (security
= sa_get_security(group
, NULL
, protocol
);
1917 security
= sa_get_next_security(security
)) {
1919 value
= sa_get_security_attr(security
, "type");
1920 secvalue
= sa_get_security_attr(security
, "sectype");
1921 (void) printf("%s", prefix
);
1923 out_properties(security
, value
, secvalue
);
1925 sa_free_attr_string(value
);
1926 if (secvalue
!= NULL
)
1927 sa_free_attr_string(secvalue
);
1933 * get_resource(share)
1935 * Get the first resource name, if any, and fix string to be in
1936 * current locale and have quotes if it has embedded spaces. Return
1937 * an attr string that must be freed.
1941 get_resource(sa_share_t share
)
1943 sa_resource_t resource
;
1944 char *resstring
= NULL
;
1947 if ((resource
= sa_get_share_resource(share
, NULL
)) != NULL
) {
1948 resstring
= sa_get_resource_attr(resource
, "name");
1949 if (resstring
!= NULL
) {
1953 retstring
= conv_from_utf8(resstring
);
1954 if (retstring
!= resstring
) {
1955 sa_free_attr_string(resstring
);
1956 resstring
= retstring
;
1958 if (strpbrk(resstring
, " ") != NULL
) {
1959 /* account for quotes */
1960 len
= strlen(resstring
) + 3;
1961 cp
= calloc(len
, sizeof (char));
1963 (void) snprintf(cp
, len
,
1964 "\"%s\"", resstring
);
1965 sa_free_attr_string(resstring
);
1968 sa_free_attr_string(resstring
);
1978 * has_resource_with_opt(share)
1980 * Check to see if the share has any resource names with optionsets
1981 * set. Also indicate if multiple resource names since the syntax
1982 * would be about the same.
1985 has_resource_with_opt(sa_share_t share
)
1987 sa_resource_t resource
;
1990 for (resource
= sa_get_share_resource(share
, NULL
);
1992 resource
= sa_get_next_resource(resource
)) {
1994 if (sa_get_optionset(resource
, NULL
) != NULL
) {
2003 * has_multiple_resource(share)
2005 * Check to see if the share has multiple resource names since
2006 * the syntax would be about the same.
2009 has_multiple_resource(sa_share_t share
)
2011 sa_resource_t resource
;
2014 for (num
= 0, resource
= sa_get_share_resource(share
, NULL
);
2016 resource
= sa_get_next_resource(resource
)) {
2025 * show_share(share, verbose, properties, proto, iszfs, sharepath)
2027 * print out the share information. With the addition of resource as a
2028 * full object that can have multiple instances below the share, we
2029 * need to display that as well.
2033 show_share(sa_share_t share
, int verbose
, int properties
, char *proto
,
2034 int iszfs
, char *sharepath
)
2038 sa_resource_t resource
= NULL
;
2045 rsrcwithopt
= has_resource_with_opt(share
);
2047 if (verbose
|| (properties
&& rsrcwithopt
)) {
2048 /* First, indicate if transient */
2049 type
= sa_get_share_attr(share
, "type");
2050 if (type
!= NULL
&& !iszfs
&& verbose
&&
2051 strcmp(type
, "transient") == 0)
2052 (void) printf("\t* ");
2054 (void) printf("\t ");
2057 sa_free_attr_string(type
);
2060 * If we came in with verbose, we want to handle the case of
2061 * multiple resources as though they had properties set.
2063 multiple
= has_multiple_resource(share
);
2066 * if there is a description on the share and there
2067 * are resources, treat as multiple resources in order
2068 * to get all descriptions displayed.
2070 description
= sa_get_share_description(share
);
2071 resource
= sa_get_share_resource(share
, NULL
);
2073 if (description
!= NULL
&& resource
!= NULL
)
2076 /* Next, if not multiple follow old model */
2077 if (!multiple
&& !rsrcwithopt
) {
2078 rsrcname
= get_resource(share
);
2079 if (rsrcname
!= NULL
&& strlen(rsrcname
) > 0) {
2080 (void) printf("%s=%s", rsrcname
, sharepath
);
2082 (void) printf("%s", sharepath
);
2084 if (rsrcname
!= NULL
)
2085 sa_free_attr_string(rsrcname
);
2086 /* Print the description string if there is one. */
2087 print_rsrc_desc(resource
, description
);
2089 /* Treat as simple and then resources come later */
2090 (void) printf("%s", sharepath
);
2092 drive
= sa_get_share_attr(share
, "drive-letter");
2093 if (drive
!= NULL
) {
2094 if (strlen(drive
) > 0)
2095 (void) printf(gettext("\tdrive-letter=\"%s:\""),
2097 sa_free_attr_string(drive
);
2100 show_properties(share
, proto
, "\t");
2101 exclude
= sa_get_share_attr(share
, "exclude");
2102 if (exclude
!= NULL
) {
2103 (void) printf(gettext("\tnot-shared-with=[%s]"),
2105 sa_free_attr_string(exclude
);
2108 if (description
!= NULL
) {
2109 print_rsrc_desc((sa_resource_t
)share
, description
);
2112 * If there are resource names with options, show them
2113 * here, with one line per resource. Resource specific
2114 * options are at the end of the line followed by
2115 * description, if any.
2117 if (rsrcwithopt
|| multiple
) {
2118 for (resource
= sa_get_share_resource(share
, NULL
);
2120 resource
= sa_get_next_resource(resource
)) {
2124 (void) printf("\n\t\t ");
2125 rsrcname
= sa_get_resource_attr(resource
,
2127 if (rsrcname
== NULL
)
2130 rsrc
= conv_from_utf8(rsrcname
);
2131 has_space
= strpbrk(rsrc
, " ") != NULL
;
2134 (void) printf("\"%s\"=%s", rsrc
,
2137 (void) printf("%s=%s", rsrc
,
2139 if (rsrc
!= rsrcname
)
2140 sa_free_attr_string(rsrc
);
2141 sa_free_attr_string(rsrcname
);
2142 if (properties
|| rsrcwithopt
)
2143 show_properties(resource
, proto
, "\t");
2145 /* Get description string if any */
2146 print_rsrc_desc(resource
, description
);
2149 if (description
!= NULL
)
2150 sa_free_share_description(description
);
2152 (void) printf("\t %s", sharepath
);
2154 show_properties(share
, proto
, "\t");
2156 (void) printf("\n");
2160 * show_group(group, verbose, properties, proto, subgroup)
2162 * helper function to show the contents of a group.
2166 show_group(sa_group_t group
, int verbose
, int properties
, char *proto
,
2175 groupname
= sa_get_group_attr(group
, "name");
2176 if (groupname
!= NULL
) {
2177 if (proto
!= NULL
&& !has_protocol(group
, proto
)) {
2178 sa_free_attr_string(groupname
);
2182 * check to see if the group is managed by ZFS. If
2183 * there is an attribute, then it is. A non-NULL zfs
2184 * variable will trigger the different way to display
2185 * and will remove the transient property indicator
2188 zfs
= sa_get_group_attr(group
, "zfs");
2191 sa_free_attr_string(zfs
);
2193 share
= sa_get_share(group
, NULL
);
2194 if (subgroup
== NULL
)
2195 (void) printf("%s", groupname
);
2197 (void) printf(" %s/%s", subgroup
, groupname
);
2199 show_properties(group
, proto
, "");
2200 (void) printf("\n");
2201 if (strcmp(groupname
, "zfs") == 0) {
2204 for (zgroup
= sa_get_sub_group(group
);
2206 zgroup
= sa_get_next_group(zgroup
)) {
2207 show_group(zgroup
, verbose
, properties
, proto
,
2210 sa_free_attr_string(groupname
);
2214 * Have a group, so list the contents. Resource and
2215 * description are only listed if verbose is set.
2217 for (share
= sa_get_share(group
, NULL
);
2219 share
= sa_get_next_share(share
)) {
2220 sharepath
= sa_get_share_attr(share
, "path");
2221 if (sharepath
!= NULL
) {
2222 show_share(share
, verbose
, properties
, proto
,
2224 sa_free_attr_string(sharepath
);
2228 if (groupname
!= NULL
) {
2229 sa_free_attr_string(groupname
);
2234 * show_group_xml_init()
2236 * Create an XML document that will be used to display config info via
2241 show_group_xml_init()
2246 doc
= xmlNewDoc((xmlChar
*)"1.0");
2248 root
= xmlNewNode(NULL
, (xmlChar
*)"sharecfg");
2250 (void) xmlDocSetRootElement(doc
, root
);
2256 * show_group_xml(doc, group)
2258 * Copy the group info into the XML doc.
2262 show_group_xml(xmlDocPtr doc
, sa_group_t group
)
2267 root
= xmlDocGetRootElement(doc
);
2268 node
= xmlCopyNode((xmlNodePtr
)group
, 1);
2269 if (node
!= NULL
&& root
!= NULL
) {
2270 (void) xmlAddChild(root
, node
);
2272 * In the future, we may have interally used tags that
2273 * should not appear in the XML output. Remove
2274 * anything we don't want to show here.
2280 * sa_show(flags, argc, argv)
2282 * Implements the show subcommand.
2286 sa_show(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
2293 char *protocol
= NULL
;
2300 while ((c
= getopt(argc
, argv
, "?hvP:px")) != EOF
) {
2309 if (protocol
!= NULL
) {
2310 (void) printf(gettext(
2311 "Specifying multiple protocols "
2312 "not supported: %s\n"),
2314 return (SA_SYNTAX_ERR
);
2317 if (!sa_valid_protocol(protocol
)) {
2318 (void) printf(gettext(
2319 "Invalid protocol specified: %s\n"),
2321 return (SA_INVALID_PROTOCOL
);
2328 /* optopt on valid arg isn't defined */
2334 * Since a bad option gets to here, sort it
2335 * out and return a syntax error return value
2340 ret
= SA_SYNTAX_ERR
;
2346 (void) printf(gettext("usage: %s\n"),
2347 sa_get_usage(USAGE_SHOW
));
2353 doc
= show_group_xml_init();
2358 if (optind
== argc
) {
2359 /* No group specified so go through them all */
2360 for (group
= sa_get_group(handle
, NULL
);
2362 group
= sa_get_next_group(group
)) {
2364 * Have a group so check if one we want and then list
2365 * contents with appropriate options.
2368 show_group_xml(doc
, group
);
2370 show_group(group
, verbose
, properties
, protocol
,
2374 /* Have a specified list of groups */
2375 for (; optind
< argc
; optind
++) {
2376 group
= sa_get_group(handle
, argv
[optind
]);
2377 if (group
!= NULL
) {
2379 show_group_xml(doc
, group
);
2381 show_group(group
, verbose
, properties
,
2384 (void) printf(gettext("%s: not found\n"),
2386 ret
= SA_NO_SUCH_GROUP
;
2390 if (xml
&& ret
== SA_OK
) {
2391 (void) xmlDocFormatDump(stdout
, doc
, 1);
2399 * enable_share(group, share, update_legacy)
2401 * helper function to enable a share if the group is enabled.
2405 enable_share(sa_handle_t handle
, sa_group_t group
, sa_share_t share
,
2410 sa_optionset_t optionset
;
2418 * need to enable this share if the group is enabled but not
2419 * otherwise. The enable is also done on each protocol
2420 * represented in the group.
2422 value
= sa_get_group_attr(group
, "state");
2423 enabled
= value
!= NULL
&& strcmp(value
, "enabled") == 0;
2425 sa_free_attr_string(value
);
2426 /* remove legacy config if necessary */
2428 ret
= sa_delete_legacy(share
, NULL
);
2429 zfs
= sa_get_group_attr(group
, "zfs");
2432 sa_free_attr_string(zfs
);
2436 * Step through each optionset at the group level and
2437 * enable the share based on the protocol type. This
2438 * works because protocols must be set on the group
2439 * for the protocol to be enabled.
2441 isshare
= sa_is_share(share
);
2442 for (optionset
= sa_get_optionset(group
, NULL
);
2443 optionset
!= NULL
&& ret
== SA_OK
;
2444 optionset
= sa_get_next_optionset(optionset
)) {
2445 value
= sa_get_optionset_attr(optionset
, "type");
2446 if (value
!= NULL
) {
2449 err
= sa_enable_share(share
, value
);
2451 err
= sa_enable_resource(share
, value
);
2452 if (err
== SA_NOT_SUPPORTED
) {
2454 parent
= sa_get_resource_parent(
2457 err
= sa_enable_share(
2463 (void) printf(gettext(
2464 "Failed to enable share for "
2466 value
, sa_errorstr(ret
));
2470 * If we want to update the legacy, use a copy of
2471 * share so we can avoid breaking the loop we are in
2472 * since we might also need to go up the tree to the
2475 if (update_legacy
&& !iszfs
) {
2476 sa_share_t update
= share
;
2477 if (!sa_is_share(share
)) {
2478 update
= sa_get_resource_parent(share
);
2480 (void) sa_update_legacy(update
, value
);
2482 sa_free_attr_string(value
);
2486 (void) sa_update_config(handle
);
2491 * sa_require_resource(group)
2493 * if any of the defined protocols on the group require resource
2494 * names, then all shares must have them.
2498 sa_require_resource(sa_group_t group
)
2500 sa_optionset_t optionset
;
2502 for (optionset
= sa_get_optionset(group
, NULL
);
2504 optionset
= sa_get_next_optionset(optionset
)) {
2507 proto
= sa_get_optionset_attr(optionset
, "type");
2508 if (proto
!= NULL
) {
2511 features
= sa_proto_get_featureset(proto
);
2512 if (features
& SA_FEATURE_RESOURCE
) {
2513 sa_free_attr_string(proto
);
2516 sa_free_attr_string(proto
);
2523 * sa_addshare(flags, argc, argv)
2525 * implements add-share subcommand.
2529 sa_addshare(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
2537 sa_resource_t resource
= NULL
;
2538 char *sharepath
= NULL
;
2539 char *description
= NULL
;
2540 char *rsrcname
= NULL
;
2542 int persist
= SA_SHARE_PERMANENT
; /* default to persist */
2544 char dir
[MAXPATHLEN
];
2546 while ((c
= getopt(argc
, argv
, "?hvns:d:r:t")) != EOF
) {
2555 description
= optarg
;
2558 if (rsrcname
!= NULL
) {
2559 (void) printf(gettext("Adding multiple "
2560 "resource names not"
2562 return (SA_SYNTAX_ERR
);
2568 * Save share path into group. Currently limit
2569 * to one share per command.
2571 if (sharepath
!= NULL
) {
2572 (void) printf(gettext(
2573 "Adding multiple shares not supported\n"));
2574 return (SA_SYNTAX_ERR
);
2579 persist
= SA_SHARE_TRANSIENT
;
2582 /* optopt on valid arg isn't defined */
2588 * Since a bad option gets to here, sort it
2589 * out and return a syntax error return value
2594 ret
= SA_SYNTAX_ERR
;
2600 (void) printf(gettext("usage: %s\n"),
2601 sa_get_usage(USAGE_ADD_SHARE
));
2606 if (optind
>= argc
) {
2607 (void) printf(gettext("usage: %s\n"),
2608 sa_get_usage(USAGE_ADD_SHARE
));
2609 if (dryrun
|| sharepath
!= NULL
|| description
!= NULL
||
2610 rsrcname
!= NULL
|| verbose
|| persist
) {
2611 (void) printf(gettext("\tgroup must be specified\n"));
2612 ret
= SA_NO_SUCH_GROUP
;
2617 if (sharepath
== NULL
) {
2618 (void) printf(gettext("usage: %s\n"),
2619 sa_get_usage(USAGE_ADD_SHARE
));
2620 (void) printf(gettext(
2621 "\t-s sharepath must be specified\n"));
2625 if (realpath(sharepath
, dir
) == NULL
) {
2627 (void) printf(gettext("Path "
2628 "is not valid: %s\n"),
2634 if (ret
== SA_OK
&& rsrcname
!= NULL
) {
2635 /* check for valid syntax */
2636 if (validresource(rsrcname
)) {
2637 rsrc
= conv_to_utf8(rsrcname
);
2638 resource
= sa_find_resource(handle
, rsrc
);
2639 if (resource
!= NULL
) {
2641 * Resource names must be
2642 * unique in the system
2644 ret
= SA_DUPLICATE_NAME
;
2645 (void) printf(gettext("usage: %s\n"),
2646 sa_get_usage(USAGE_ADD_SHARE
));
2647 (void) printf(gettext(
2648 "\tresource names must be unique "
2649 "in the system\n"));
2652 (void) printf(gettext("usage: %s\n"),
2653 sa_get_usage(USAGE_ADD_SHARE
));
2654 (void) printf(gettext(
2655 "\tresource names use restricted "
2656 "character set\n"));
2657 ret
= SA_INVALID_NAME
;
2662 if (rsrc
!= NULL
&& rsrcname
!= rsrc
)
2663 sa_free_attr_string(rsrc
);
2667 share
= sa_find_share(handle
, sharepath
);
2668 if (share
!= NULL
) {
2669 if (rsrcname
== NULL
) {
2671 * Can only have a duplicate share if a new
2672 * resource name is being added.
2674 ret
= SA_DUPLICATE_NAME
;
2675 (void) printf(gettext("Share path already "
2676 "shared: %s\n"), sharepath
);
2682 group
= sa_get_group(handle
, argv
[optind
]);
2683 if (group
!= NULL
) {
2684 if (sa_require_resource(group
) == B_TRUE
&&
2686 (void) printf(gettext(
2687 "Resource name is required "
2688 "by at least one enabled protocol "
2690 return (SA_RESOURCE_REQUIRED
);
2692 if (share
== NULL
&& ret
== SA_OK
) {
2694 ret
= sa_check_path(group
, sharepath
,
2697 share
= sa_add_share(group
, sharepath
,
2701 * Make sure this isn't an attempt to put a resourced
2702 * share into a different group than it already is in.
2704 if (share
!= NULL
) {
2706 parent
= sa_get_parent_group(share
);
2707 if (parent
!= group
) {
2708 ret
= SA_DUPLICATE_NAME
;
2709 (void) printf(gettext(
2710 "Share path already "
2711 "shared: %s\n"), sharepath
);
2714 if (!dryrun
&& share
== NULL
) {
2715 (void) printf(gettext(
2716 "Could not add share: %s\n"),
2719 auth
= check_authorizations(argv
[optind
],
2721 if (!dryrun
&& ret
== SA_OK
) {
2722 if (rsrcname
!= NULL
) {
2723 resource
= sa_add_resource(
2730 description
!= NULL
) {
2731 if (resource
!= NULL
)
2743 /* now enable the share(s) */
2744 if (resource
!= NULL
) {
2757 ret
= sa_update_config(handle
);
2760 case SA_DUPLICATE_NAME
:
2761 (void) printf(gettext(
2767 (void) printf(gettext(
2775 } else if (dryrun
&& ret
== SA_OK
&&
2777 (void) printf(gettext(
2778 "Command would fail: %s\n"),
2779 sa_errorstr(SA_NO_PERMISSION
));
2780 ret
= SA_NO_PERMISSION
;
2786 (void) printf(gettext(
2787 "Group \"%s\" not found\n"), argv
[optind
]);
2788 ret
= SA_NO_SUCH_GROUP
;
2791 case SA_DUPLICATE_NAME
:
2800 * sa_moveshare(flags, argc, argv)
2802 * implements move-share subcommand.
2806 sa_moveshare(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
2814 char *rsrcname
= NULL
;
2815 char *sharepath
= NULL
;
2816 int authsrc
= 0, authdst
= 0;
2817 char dir
[MAXPATHLEN
];
2819 while ((c
= getopt(argc
, argv
, "?hvnr:s:")) != EOF
) {
2828 if (rsrcname
!= NULL
) {
2829 (void) printf(gettext(
2830 "Moving multiple resource names not"
2832 return (SA_SYNTAX_ERR
);
2838 * Remove share path from group. Currently limit
2839 * to one share per command.
2841 if (sharepath
!= NULL
) {
2842 (void) printf(gettext("Moving multiple shares"
2843 " not supported\n"));
2844 return (SA_SYNTAX_ERR
);
2849 /* optopt on valid arg isn't defined */
2855 * Since a bad option gets to here, sort it
2856 * out and return a syntax error return value
2861 ret
= SA_SYNTAX_ERR
;
2867 (void) printf(gettext("usage: %s\n"),
2868 sa_get_usage(USAGE_MOVE_SHARE
));
2873 if (optind
>= argc
|| sharepath
== NULL
) {
2874 (void) printf(gettext("usage: %s\n"),
2875 sa_get_usage(USAGE_MOVE_SHARE
));
2876 if (dryrun
|| verbose
|| sharepath
!= NULL
) {
2877 (void) printf(gettext("\tgroup must be specified\n"));
2878 ret
= SA_NO_SUCH_GROUP
;
2880 if (sharepath
== NULL
) {
2881 ret
= SA_SYNTAX_ERR
;
2882 (void) printf(gettext(
2883 "\tsharepath must be specified\n"));
2893 if (sharepath
== NULL
) {
2894 (void) printf(gettext(
2895 "sharepath must be specified with the -s "
2897 return (SA_BAD_PATH
);
2899 group
= sa_get_group(handle
, argv
[optind
]);
2900 if (group
== NULL
) {
2901 (void) printf(gettext("Group \"%s\" not found\n"),
2903 return (SA_NO_SUCH_GROUP
);
2905 share
= sa_find_share(handle
, sharepath
);
2907 * If a share wasn't found, it may have been a symlink
2908 * or has a trailing '/'. Try again after resolving
2911 if (share
== NULL
) {
2912 if (realpath(sharepath
, dir
) == NULL
) {
2913 (void) printf(gettext("Path "
2914 "is not valid: %s\n"),
2916 return (SA_BAD_PATH
);
2919 share
= sa_find_share(handle
, sharepath
);
2921 if (share
== NULL
) {
2922 (void) printf(gettext("Share not found: %s\n"),
2924 return (SA_NO_SUCH_PATH
);
2926 authdst
= check_authorizations(argv
[optind
], flags
);
2928 parent
= sa_get_parent_group(share
);
2929 if (parent
!= NULL
) {
2931 pname
= sa_get_group_attr(parent
, "name");
2932 if (pname
!= NULL
) {
2933 authsrc
= check_authorizations(pname
, flags
);
2934 sa_free_attr_string(pname
);
2936 zfsold
= sa_get_group_attr(parent
, "zfs");
2937 zfsnew
= sa_get_group_attr(group
, "zfs");
2938 if ((zfsold
!= NULL
&& zfsnew
== NULL
) ||
2939 (zfsold
== NULL
&& zfsnew
!= NULL
)) {
2940 ret
= SA_NOT_ALLOWED
;
2943 sa_free_attr_string(zfsold
);
2945 sa_free_attr_string(zfsnew
);
2948 if (ret
== SA_OK
&& parent
!= group
&& !dryrun
) {
2951 * Note that the share may need to be
2952 * "unshared" if the new group is disabled and
2953 * the old was enabled or it may need to be
2954 * share to update if the new group is
2955 * enabled. We disable before the move and
2956 * will have to enable after the move in order
2957 * to cleanup entries for protocols that
2958 * aren't in the new group.
2960 oldstate
= sa_get_group_attr(parent
, "state");
2961 if (oldstate
!= NULL
) {
2962 /* enable_share determines what to do */
2963 if (strcmp(oldstate
, "enabled") == 0)
2964 (void) sa_disable_share(share
, NULL
);
2965 sa_free_attr_string(oldstate
);
2969 if (!dryrun
&& ret
== SA_OK
)
2970 ret
= sa_move_share(group
, share
);
2973 * Reenable and update any config information.
2975 if (ret
== SA_OK
&& parent
!= group
&& !dryrun
) {
2976 ret
= sa_update_config(handle
);
2978 (void) enable_share(handle
, group
, share
, 1);
2982 (void) printf(gettext("Could not move share: %s\n"),
2985 if (dryrun
&& ret
== SA_OK
&& !(authsrc
& authdst
) &&
2987 (void) printf(gettext("Command would fail: %s\n"),
2988 sa_errorstr(SA_NO_PERMISSION
));
2995 * sa_removeshare(flags, argc, argv)
2997 * implements remove-share subcommand.
3001 sa_removeshare(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
3009 sa_resource_t resource
= NULL
;
3010 sa_share_t share
= NULL
;
3011 char *rsrcname
= NULL
;
3012 char *sharepath
= NULL
;
3013 char dir
[MAXPATHLEN
];
3016 while ((c
= getopt(argc
, argv
, "?hfnr:s:v")) != EOF
) {
3029 * Remove share path from group. Currently limit
3030 * to one share per command.
3032 if (sharepath
!= NULL
) {
3033 (void) printf(gettext(
3034 "Removing multiple shares not "
3036 return (SA_SYNTAX_ERR
);
3042 * Remove share from group if last resource or remove
3043 * resource from share if multiple resources.
3045 if (rsrcname
!= NULL
) {
3046 (void) printf(gettext(
3047 "Removing multiple resource names not "
3049 return (SA_SYNTAX_ERR
);
3054 /* optopt on valid arg isn't defined */
3060 * Since a bad option gets to here, sort it
3061 * out and return a syntax error return value
3066 ret
= SA_SYNTAX_ERR
;
3072 (void) printf(gettext("usage: %s\n"),
3073 sa_get_usage(USAGE_REMOVE_SHARE
));
3078 if (optind
>= argc
|| (rsrcname
== NULL
&& sharepath
== NULL
)) {
3079 if (sharepath
== NULL
&& rsrcname
== NULL
) {
3080 (void) printf(gettext("usage: %s\n"),
3081 sa_get_usage(USAGE_REMOVE_SHARE
));
3082 (void) printf(gettext("\t-s sharepath or -r resource"
3083 " must be specified\n"));
3093 if (optind
< argc
) {
3094 if ((optind
+ 1) < argc
) {
3095 (void) printf(gettext("Extraneous group(s) at end of "
3097 ret
= SA_SYNTAX_ERR
;
3099 group
= sa_get_group(handle
, argv
[optind
]);
3100 if (group
== NULL
) {
3101 (void) printf(gettext(
3102 "Group \"%s\" not found\n"), argv
[optind
]);
3103 ret
= SA_NO_SUCH_GROUP
;
3110 if (rsrcname
!= NULL
) {
3111 resource
= sa_find_resource(handle
, rsrcname
);
3112 if (resource
== NULL
) {
3113 ret
= SA_NO_SUCH_RESOURCE
;
3114 (void) printf(gettext(
3115 "Resource name not found for share: %s\n"),
3121 * Lookup the path in the internal configuration. Care
3122 * must be taken to handle the case where the
3123 * underlying path has been removed since we need to
3124 * be able to deal with that as well.
3127 if (sharepath
!= NULL
) {
3129 share
= sa_get_share(group
, sharepath
);
3131 share
= sa_find_share(handle
, sharepath
);
3134 if (resource
!= NULL
) {
3135 sa_share_t rsrcshare
;
3136 rsrcshare
= sa_get_resource_parent(resource
);
3139 else if (share
!= rsrcshare
) {
3140 ret
= SA_NO_SUCH_RESOURCE
;
3141 (void) printf(gettext(
3142 "Bad resource name for share: %s\n"),
3149 * If we didn't find the share with the provided path,
3150 * it may be a symlink so attempt to resolve it using
3151 * realpath and try again. Realpath will resolve any
3152 * symlinks and place them in "dir". Note that
3153 * sharepath is only used for the lookup the first
3154 * time and later for error messages. dir will be used
3155 * on the second attempt. Once a share is found, all
3156 * operations are based off of the share variable.
3158 if (share
== NULL
) {
3159 if (realpath(sharepath
, dir
) == NULL
) {
3161 (void) printf(gettext(
3162 "Path is not valid: %s\n"), sharepath
);
3165 share
= sa_get_share(group
, dir
);
3167 share
= sa_find_share(handle
, dir
);
3173 * If there hasn't been an error, there was likely a
3174 * path found. If not, give the appropriate error
3175 * message and set the return error. If it was found,
3176 * then disable the share and then remove it from the
3182 if (share
== NULL
) {
3184 (void) printf(gettext("Share not found in group %s:"
3185 " %s\n"), argv
[optind
], sharepath
);
3187 (void) printf(gettext("Share not found: %s\n"),
3189 ret
= SA_NO_SUCH_PATH
;
3192 group
= sa_get_parent_group(share
);
3195 if (resource
!= NULL
)
3196 ret
= sa_disable_resource(resource
,
3199 ret
= sa_disable_share(share
, NULL
);
3201 * We don't care if it fails since it
3202 * could be disabled already. Some
3203 * unexpected errors could occur that
3204 * prevent removal, so also check for
3207 if ((ret
== SA_OK
|| ret
== SA_NO_SUCH_PATH
||
3208 ret
== SA_NOT_SUPPORTED
||
3209 ret
== SA_SYSTEM_ERR
|| force
) &&
3211 ret
= sa_remove_share(share
);
3213 if ((ret
== SA_OK
|| ret
== SA_NO_SUCH_PATH
||
3214 ret
== SA_NOT_SUPPORTED
||
3215 ret
== SA_SYSTEM_ERR
|| force
) &&
3217 ret
= sa_remove_resource(resource
);
3222 * the share as well.
3225 sa_get_share_resource(
3227 if (resource
== NULL
)
3228 ret
= sa_remove_share(
3233 ret
= sa_update_config(handle
);
3236 (void) printf(gettext("Could not remove share:"
3237 " %s\n"), sa_errorstr(ret
));
3238 } else if (ret
== SA_OK
) {
3240 pname
= sa_get_group_attr(group
, "name");
3241 if (pname
!= NULL
) {
3242 auth
= check_authorizations(pname
, flags
);
3243 sa_free_attr_string(pname
);
3245 if (!auth
&& verbose
) {
3246 (void) printf(gettext(
3247 "Command would fail: %s\n"),
3248 sa_errorstr(SA_NO_PERMISSION
));
3256 * sa_set_share(flags, argc, argv)
3258 * implements set-share subcommand.
3262 sa_set_share(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
3267 sa_group_t group
, sharegroup
;
3268 sa_share_t share
= NULL
;
3269 sa_resource_t resource
= NULL
;
3270 char *sharepath
= NULL
;
3271 char *description
= NULL
;
3272 char *rsrcname
= NULL
;
3274 char *newname
= NULL
;
3276 char *groupname
= NULL
;
3280 while ((c
= getopt(argc
, argv
, "?hnd:r:s:")) != EOF
) {
3286 description
= optarg
;
3293 * Update share by resource name
3295 if (rsrcname
!= NULL
) {
3296 (void) printf(gettext(
3297 "Updating multiple resource names not "
3299 return (SA_SYNTAX_ERR
);
3305 * Save share path into group. Currently limit
3306 * to one share per command.
3308 if (sharepath
!= NULL
) {
3309 (void) printf(gettext(
3310 "Updating multiple shares not "
3312 return (SA_SYNTAX_ERR
);
3317 /* optopt on valid arg isn't defined */
3323 * Since a bad option gets to here, sort it
3324 * out and return a syntax error return value
3329 ret
= SA_SYNTAX_ERR
;
3335 (void) printf(gettext("usage: %s\n"),
3336 sa_get_usage(USAGE_SET_SHARE
));
3341 if (optind
>= argc
&& sharepath
== NULL
&& rsrcname
== NULL
) {
3342 if (sharepath
== NULL
) {
3343 (void) printf(gettext("usage: %s\n"),
3344 sa_get_usage(USAGE_SET_SHARE
));
3345 (void) printf(gettext("\tgroup must be specified\n"));
3351 if ((optind
+ 1) < argc
) {
3352 (void) printf(gettext("usage: %s\n"),
3353 sa_get_usage(USAGE_SET_SHARE
));
3354 (void) printf(gettext("\tExtraneous group(s) at end\n"));
3355 ret
= SA_SYNTAX_ERR
;
3359 * Must have at least one of sharepath and rsrcrname.
3360 * It is a syntax error to be missing both.
3362 if (sharepath
== NULL
&& rsrcname
== NULL
) {
3363 (void) printf(gettext("usage: %s\n"),
3364 sa_get_usage(USAGE_SET_SHARE
));
3365 ret
= SA_SYNTAX_ERR
;
3371 if (optind
< argc
) {
3372 groupname
= argv
[optind
];
3373 group
= sa_get_group(handle
, groupname
);
3378 if (rsrcname
!= NULL
) {
3380 * If rsrcname exists, split rename syntax and then
3381 * convert to utf 8 if no errors.
3383 newname
= strchr(rsrcname
, '=');
3384 if (newname
!= NULL
) {
3387 if (!validresource(rsrcname
)) {
3388 ret
= SA_INVALID_NAME
;
3389 (void) printf(gettext("Invalid resource name: "
3390 "\"%s\"\n"), rsrcname
);
3392 rsrc
= conv_to_utf8(rsrcname
);
3394 if (newname
!= NULL
) {
3395 if (!validresource(newname
)) {
3396 ret
= SA_INVALID_NAME
;
3397 (void) printf(gettext("Invalid resource name: "
3401 newrsrc
= conv_to_utf8(newname
);
3407 if (rsrcname
!= NULL
&& rsrcname
!= rsrc
)
3408 sa_free_attr_string(rsrc
);
3409 if (newname
!= NULL
&& newname
!= newrsrc
)
3410 sa_free_attr_string(newrsrc
);
3414 if (sharepath
!= NULL
) {
3415 share
= sa_find_share(handle
, sharepath
);
3416 } else if (rsrcname
!= NULL
) {
3417 resource
= sa_find_resource(handle
, rsrc
);
3418 if (resource
!= NULL
)
3419 share
= sa_get_resource_parent(resource
);
3421 ret
= SA_NO_SUCH_RESOURCE
;
3423 if (share
!= NULL
) {
3424 sharegroup
= sa_get_parent_group(share
);
3425 if (group
!= NULL
&& group
!= sharegroup
) {
3426 (void) printf(gettext("Group \"%s\" does not contain "
3428 argv
[optind
], sharepath
);
3431 int delgroupname
= 0;
3432 if (groupname
== NULL
) {
3433 groupname
= sa_get_group_attr(sharegroup
,
3437 if (groupname
!= NULL
) {
3438 auth
= check_authorizations(groupname
, flags
);
3440 sa_free_attr_string(groupname
);
3446 if (rsrcname
!= NULL
) {
3447 resource
= sa_find_resource(handle
, rsrc
);
3449 if (newname
!= NULL
&&
3451 ret
= sa_rename_resource(
3453 else if (newname
!= NULL
)
3454 ret
= SA_NO_SUCH_RESOURCE
;
3455 if (newname
!= NULL
&&
3457 sa_free_attr_string(newrsrc
);
3459 if (rsrc
!= rsrcname
)
3460 sa_free_attr_string(rsrc
);
3464 * If the user has set a description, it will be
3465 * on the resource if -r was used otherwise it
3466 * must be on the share.
3468 if (!dryrun
&& ret
== SA_OK
&& description
!= NULL
) {
3470 desc
= conv_to_utf8(description
);
3471 if (resource
!= NULL
)
3472 ret
= sa_set_resource_description(
3475 ret
= sa_set_share_description(share
,
3477 if (desc
!= description
)
3478 sa_free_share_description(desc
);
3481 if (!dryrun
&& ret
== SA_OK
) {
3482 if (resource
!= NULL
)
3483 (void) sa_enable_resource(resource
, NULL
);
3484 ret
= sa_update_config(handle
);
3487 case SA_DUPLICATE_NAME
:
3488 (void) printf(gettext("Resource name in use: %s\n"),
3492 (void) printf(gettext("Could not set: %s\n"),
3496 if (dryrun
&& !auth
&& verbose
) {
3497 (void) printf(gettext(
3498 "Command would fail: %s\n"),
3499 sa_errorstr(SA_NO_PERMISSION
));
3505 case SA_NO_SUCH_RESOURCE
:
3506 (void) printf(gettext("Resource \"%s\" not found\n"),
3510 if (sharepath
!= NULL
) {
3512 gettext("Share path \"%s\" not found\n"),
3514 ret
= SA_NO_SUCH_PATH
;
3516 (void) printf(gettext("Set failed: %s\n"),
3526 * add_security(group, sectype, optlist, proto, *err)
3528 * Helper function to add a security option (named optionset) to the
3533 add_security(sa_group_t group
, char *sectype
,
3534 struct options
*optlist
, char *proto
, int *err
)
3536 sa_security_t security
;
3541 sectype
= sa_proto_space_alias(proto
, sectype
);
3542 security
= sa_get_security(group
, sectype
, proto
);
3543 if (security
== NULL
)
3544 security
= sa_create_security(group
, sectype
, proto
);
3546 if (sectype
!= NULL
)
3547 sa_free_attr_string(sectype
);
3549 if (security
== NULL
)
3552 handle
= sa_find_group_handle(group
);
3553 if (handle
== NULL
) {
3554 ret
= SA_CONFIG_ERR
;
3557 while (optlist
!= NULL
) {
3559 prop
= sa_get_property(security
, optlist
->optname
);
3562 * Add the property, but only if it is
3563 * a non-NULL or non-zero length value
3565 if (optlist
->optvalue
!= NULL
) {
3566 prop
= sa_create_property(optlist
->optname
,
3569 ret
= sa_valid_property(handle
,
3570 security
, proto
, prop
);
3572 (void) sa_remove_property(prop
);
3573 (void) printf(gettext(
3575 "property %s: %s\n"),
3580 ret
= sa_add_property(security
,
3583 (void) printf(gettext(
3597 ret
= sa_update_property(prop
, optlist
->optvalue
);
3598 result
= 1; /* should check if really changed */
3600 optlist
= optlist
->next
;
3603 * When done, properties may have all been removed but
3604 * we need to keep the security type itself until
3605 * explicitly removed.
3608 ret
= sa_commit_properties(security
, 0);
3615 * zfscheck(group, share)
3617 * For the special case where a share was provided, make sure it is a
3618 * compatible path for a ZFS property change. The only path
3619 * acceptable is the path that defines the zfs sub-group (dataset with
3620 * the sharenfs property set) and not one of the paths that inherited
3621 * the NFS properties. Returns SA_OK if it is usable and
3622 * SA_NOT_ALLOWED if it isn't.
3624 * If group is not a ZFS group/subgroup, we assume OK since the check
3625 * on return will catch errors for those cases. What we are looking
3626 * for here is that the group is ZFS and the share is not the defining
3627 * share. All else is SA_OK.
3631 zfscheck(sa_group_t group
, sa_share_t share
)
3636 if (sa_group_is_zfs(group
)) {
3638 * The group is a ZFS group. Does the share represent
3639 * the dataset that defined the group? It is only OK
3640 * if the attribute "subgroup" exists on the share and
3641 * has a value of "true".
3644 ret
= SA_NOT_ALLOWED
;
3645 attr
= sa_get_share_attr(share
, "subgroup");
3647 if (strcmp(attr
, "true") == 0)
3649 sa_free_attr_string(attr
);
3656 * basic_set(groupname, optlist, protocol, sharepath, rsrcname, dryrun)
3658 * This function implements "set" when a name space (-S) is not
3659 * specified. It is a basic set. Options and other CLI parsing has
3660 * already been done.
3662 * "rsrcname" is a "resource name". If it is non-NULL, it must match
3663 * the sharepath if present or group if present, otherwise it is used
3666 * Resource names may take options if the protocol supports it. If the
3667 * protocol doesn't support resource level options, rsrcname is just
3668 * an alias for the share.
3672 basic_set(sa_handle_t handle
, char *groupname
, struct options
*optlist
,
3673 char *protocol
, char *sharepath
, char *rsrcname
, int dryrun
)
3678 struct list
*worklist
= NULL
;
3680 group
= sa_get_group(handle
, groupname
);
3681 if (group
!= NULL
) {
3682 sa_share_t share
= NULL
;
3683 sa_resource_t resource
= NULL
;
3686 * If there is a sharepath, make sure it belongs to
3689 if (sharepath
!= NULL
) {
3690 share
= sa_get_share(group
, sharepath
);
3691 if (share
== NULL
) {
3692 (void) printf(gettext(
3693 "Share does not exist in group %s\n"),
3694 groupname
, sharepath
);
3695 ret
= SA_NO_SUCH_PATH
;
3697 /* if ZFS and OK, then only group */
3698 ret
= zfscheck(group
, share
);
3700 sa_group_is_zfs(group
))
3702 if (ret
== SA_NOT_ALLOWED
)
3703 (void) printf(gettext(
3704 "Properties on ZFS group shares "
3705 "not supported: %s\n"), sharepath
);
3710 * If a resource name exists, make sure it belongs to
3711 * the share if present else it belongs to the
3712 * group. Also check the protocol to see if it
3713 * supports resource level properties or not. If not,
3716 if (rsrcname
!= NULL
) {
3717 if (share
!= NULL
) {
3718 resource
= sa_get_share_resource(share
,
3720 if (resource
== NULL
)
3721 ret
= SA_NO_SUCH_RESOURCE
;
3723 resource
= sa_get_resource(group
, rsrcname
);
3724 if (resource
!= NULL
)
3725 share
= sa_get_resource_parent(
3728 ret
= SA_NO_SUCH_RESOURCE
;
3730 if (ret
== SA_OK
&& resource
!= NULL
) {
3733 * Check to see if the resource can take
3734 * properties. If so, stick the resource into
3735 * "share" so it will all just work.
3737 features
= sa_proto_get_featureset(protocol
);
3738 if (features
& SA_FEATURE_RESOURCE
)
3739 share
= (sa_share_t
)resource
;
3744 /* group must exist */
3745 ret
= valid_options(handle
, optlist
, protocol
,
3746 share
== NULL
? group
: share
, NULL
);
3747 if (ret
== SA_OK
&& !dryrun
) {
3749 change
|= add_optionset(share
, optlist
,
3752 change
|= add_optionset(group
, optlist
,
3754 if (ret
== SA_OK
&& change
)
3755 worklist
= add_list(worklist
, group
,
3761 (void) printf(gettext("Group \"%s\" not found\n"), groupname
);
3762 ret
= SA_NO_SUCH_GROUP
;
3765 * we have a group and potentially legal additions
3769 * Commit to configuration if not a dryrunp and properties
3772 if (!dryrun
&& ret
== SA_OK
&& change
&& worklist
!= NULL
)
3773 /* properties changed, so update all shares */
3774 (void) enable_all_groups(handle
, worklist
, 0, 0, protocol
,
3777 if (worklist
!= NULL
)
3778 free_list(worklist
);
3783 * space_set(groupname, optlist, protocol, sharepath, dryrun)
3785 * This function implements "set" when a name space (-S) is
3786 * specified. It is a namespace set. Options and other CLI parsing has
3787 * already been done.
3791 space_set(sa_handle_t handle
, char *groupname
, struct options
*optlist
,
3792 char *protocol
, char *sharepath
, int dryrun
, char *sectype
)
3797 struct list
*worklist
= NULL
;
3800 * make sure protcol and sectype are valid
3803 if (sa_proto_valid_space(protocol
, sectype
) == 0) {
3804 (void) printf(gettext("Option space \"%s\" not valid "
3805 "for protocol.\n"), sectype
);
3806 return (SA_INVALID_SECURITY
);
3809 group
= sa_get_group(handle
, groupname
);
3810 if (group
!= NULL
) {
3811 sa_share_t share
= NULL
;
3812 if (sharepath
!= NULL
) {
3813 share
= sa_get_share(group
, sharepath
);
3814 if (share
== NULL
) {
3815 (void) printf(gettext(
3816 "Share does not exist in group %s\n"),
3817 groupname
, sharepath
);
3818 ret
= SA_NO_SUCH_PATH
;
3820 /* if ZFS and OK, then only group */
3821 ret
= zfscheck(group
, share
);
3823 sa_group_is_zfs(group
))
3825 if (ret
== SA_NOT_ALLOWED
)
3826 (void) printf(gettext(
3827 "Properties on ZFS group shares "
3828 "not supported: %s\n"), sharepath
);
3832 /* group must exist */
3833 ret
= valid_options(handle
, optlist
, protocol
,
3834 share
== NULL
? group
: share
, sectype
);
3835 if (ret
== SA_OK
&& !dryrun
) {
3837 change
= add_security(share
, sectype
,
3838 optlist
, protocol
, &ret
);
3840 change
= add_security(group
, sectype
,
3841 optlist
, protocol
, &ret
);
3843 (void) printf(gettext(
3844 "Could not set property: %s\n"),
3847 if (ret
== SA_OK
&& change
)
3848 worklist
= add_list(worklist
, group
, share
,
3853 (void) printf(gettext("Group \"%s\" not found\n"), groupname
);
3854 ret
= SA_NO_SUCH_GROUP
;
3858 * We have a group and potentially legal additions.
3861 /* Commit to configuration if not a dryrun */
3862 if (!dryrun
&& ret
== 0) {
3863 if (change
&& worklist
!= NULL
) {
3864 /* properties changed, so update all shares */
3865 (void) enable_all_groups(handle
, worklist
, 0, 0,
3868 ret
= sa_update_config(handle
);
3870 if (worklist
!= NULL
)
3871 free_list(worklist
);
3876 * sa_set(flags, argc, argv)
3878 * Implements the set subcommand. It keys off of -S to determine which
3879 * set of operations to actually do.
3883 sa_set(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
3889 char *protocol
= NULL
;
3891 struct options
*optlist
= NULL
;
3892 char *rsrcname
= NULL
;
3893 char *sharepath
= NULL
;
3894 char *optset
= NULL
;
3897 while ((c
= getopt(argc
, argv
, "?hvnP:p:r:s:S:")) != EOF
) {
3906 if (protocol
!= NULL
) {
3907 (void) printf(gettext(
3908 "Specifying multiple protocols "
3909 "not supported: %s\n"), protocol
);
3910 return (SA_SYNTAX_ERR
);
3913 if (!sa_valid_protocol(protocol
)) {
3914 (void) printf(gettext(
3915 "Invalid protocol specified: %s\n"),
3917 return (SA_INVALID_PROTOCOL
);
3921 ret
= add_opt(&optlist
, optarg
, 0);
3923 case OPT_ADD_SYNTAX
:
3924 (void) printf(gettext("Property syntax error:"
3926 return (SA_SYNTAX_ERR
);
3927 case OPT_ADD_MEMORY
:
3928 (void) printf(gettext("No memory to set "
3929 "property: %s\n"), optarg
);
3930 return (SA_NO_MEMORY
);
3936 if (rsrcname
!= NULL
) {
3937 (void) printf(gettext(
3938 "Setting multiple resource names not"
3940 return (SA_SYNTAX_ERR
);
3945 if (sharepath
!= NULL
) {
3946 (void) printf(gettext(
3947 "Setting multiple shares not supported\n"));
3948 return (SA_SYNTAX_ERR
);
3953 if (optset
!= NULL
) {
3954 (void) printf(gettext(
3955 "Specifying multiple property "
3956 "spaces not supported: %s\n"), optset
);
3957 return (SA_SYNTAX_ERR
);
3962 /* optopt on valid arg isn't defined */
3968 * Since a bad option gets to here, sort it
3969 * out and return a syntax error return value
3974 ret
= SA_SYNTAX_ERR
;
3980 (void) printf(gettext("usage: %s\n"),
3981 sa_get_usage(USAGE_SET
));
3986 if (optlist
!= NULL
)
3987 ret
= chk_opt(optlist
, optset
!= NULL
, protocol
);
3989 if (optind
>= argc
|| (optlist
== NULL
&& optset
== NULL
) ||
3990 protocol
== NULL
|| ret
!= OPT_ADD_OK
) {
3993 (void) printf(gettext("usage: %s\n"), sa_get_usage(USAGE_SET
));
3994 if (optind
>= argc
) {
3995 (void) printf(gettext("%sgroup must be specified"),
3999 if (optlist
== NULL
) {
4000 (void) printf(gettext("%sat least one property must be"
4001 " specified"), sep
);
4004 if (protocol
== NULL
) {
4005 (void) printf(gettext("%sprotocol must be specified"),
4009 (void) printf("\n");
4010 ret
= SA_SYNTAX_ERR
;
4013 * Group already exists so we can proceed after a few
4014 * additional checks related to ZFS handling.
4017 groupname
= argv
[optind
];
4018 if (strcmp(groupname
, "zfs") == 0) {
4019 (void) printf(gettext("Changing properties for group "
4020 "\"zfs\" not allowed\n"));
4021 return (SA_NOT_ALLOWED
);
4024 auth
= check_authorizations(groupname
, flags
);
4026 ret
= basic_set(handle
, groupname
, optlist
, protocol
,
4027 sharepath
, rsrcname
, dryrun
);
4029 ret
= space_set(handle
, groupname
, optlist
, protocol
,
4030 sharepath
, dryrun
, optset
);
4031 if (dryrun
&& ret
== SA_OK
&& !auth
&& verbose
) {
4032 (void) printf(gettext("Command would fail: %s\n"),
4033 sa_errorstr(SA_NO_PERMISSION
));
4040 * remove_options(group, optlist, proto, *err)
4042 * Helper function to actually remove options from a group after all
4043 * preprocessing is done.
4047 remove_options(sa_group_t group
, struct options
*optlist
,
4048 char *proto
, int *err
)
4050 struct options
*cur
;
4051 sa_optionset_t optionset
;
4056 optionset
= sa_get_optionset(group
, proto
);
4057 if (optionset
!= NULL
) {
4058 for (cur
= optlist
; cur
!= NULL
; cur
= cur
->next
) {
4059 prop
= sa_get_property(optionset
, cur
->optname
);
4061 ret
= sa_remove_property(prop
);
4068 if (ret
== SA_OK
&& change
)
4069 ret
= sa_commit_properties(optionset
, 0);
4077 * valid_unset(group, optlist, proto)
4079 * Sanity check the optlist to make sure they can be removed. Issue an
4080 * error if a property doesn't exist.
4084 valid_unset(sa_group_t group
, struct options
*optlist
, char *proto
)
4086 struct options
*cur
;
4087 sa_optionset_t optionset
;
4091 optionset
= sa_get_optionset(group
, proto
);
4092 if (optionset
!= NULL
) {
4093 for (cur
= optlist
; cur
!= NULL
; cur
= cur
->next
) {
4094 prop
= sa_get_property(optionset
, cur
->optname
);
4096 (void) printf(gettext(
4097 "Could not unset property %s: not set\n"),
4099 ret
= SA_NO_SUCH_PROP
;
4107 * valid_unset_security(group, optlist, proto)
4109 * Sanity check the optlist to make sure they can be removed. Issue an
4110 * error if a property doesn't exist.
4114 valid_unset_security(sa_group_t group
, struct options
*optlist
, char *proto
,
4117 struct options
*cur
;
4118 sa_security_t security
;
4123 sec
= sa_proto_space_alias(proto
, sectype
);
4124 security
= sa_get_security(group
, sec
, proto
);
4125 if (security
!= NULL
) {
4126 for (cur
= optlist
; cur
!= NULL
; cur
= cur
->next
) {
4127 prop
= sa_get_property(security
, cur
->optname
);
4129 (void) printf(gettext(
4130 "Could not unset property %s: not set\n"),
4132 ret
= SA_NO_SUCH_PROP
;
4136 (void) printf(gettext(
4137 "Could not unset %s: space not defined\n"), sectype
);
4138 ret
= SA_NO_SUCH_SECURITY
;
4141 sa_free_attr_string(sec
);
4146 * remove_security(group, optlist, proto)
4148 * Remove the properties since they were checked as valid.
4152 remove_security(sa_group_t group
, char *sectype
,
4153 struct options
*optlist
, char *proto
, int *err
)
4155 sa_security_t security
;
4159 sectype
= sa_proto_space_alias(proto
, sectype
);
4160 security
= sa_get_security(group
, sectype
, proto
);
4161 if (sectype
!= NULL
)
4162 sa_free_attr_string(sectype
);
4164 if (security
!= NULL
) {
4165 while (optlist
!= NULL
) {
4167 prop
= sa_get_property(security
, optlist
->optname
);
4169 ret
= sa_remove_property(prop
);
4174 optlist
= optlist
->next
;
4177 * when done, properties may have all been removed but
4178 * we need to keep the security type itself until
4179 * explicitly removed.
4181 if (ret
== SA_OK
&& change
)
4182 ret
= sa_commit_properties(security
, 0);
4184 ret
= SA_NO_SUCH_PROP
;
4192 * basic_unset(groupname, optlist, protocol, sharepath, rsrcname, dryrun)
4194 * Unset non-named optionset properties.
4198 basic_unset(sa_handle_t handle
, char *groupname
, struct options
*optlist
,
4199 char *protocol
, char *sharepath
, char *rsrcname
, int dryrun
)
4204 struct list
*worklist
= NULL
;
4205 sa_share_t share
= NULL
;
4206 sa_resource_t resource
= NULL
;
4208 group
= sa_get_group(handle
, groupname
);
4213 * If there is a sharepath, make sure it belongs to
4216 if (sharepath
!= NULL
) {
4217 share
= sa_get_share(group
, sharepath
);
4218 if (share
== NULL
) {
4219 (void) printf(gettext(
4220 "Share does not exist in group %s\n"),
4221 groupname
, sharepath
);
4222 ret
= SA_NO_SUCH_PATH
;
4226 * If a resource name exists, make sure it belongs to
4227 * the share if present else it belongs to the
4228 * group. Also check the protocol to see if it
4229 * supports resource level properties or not. If not,
4232 if (rsrcname
!= NULL
) {
4233 if (share
!= NULL
) {
4234 resource
= sa_get_share_resource(share
, rsrcname
);
4235 if (resource
== NULL
)
4236 ret
= SA_NO_SUCH_RESOURCE
;
4238 resource
= sa_get_resource(group
, rsrcname
);
4239 if (resource
!= NULL
) {
4240 share
= sa_get_resource_parent(resource
);
4242 ret
= SA_NO_SUCH_RESOURCE
;
4245 if (ret
== SA_OK
&& resource
!= NULL
) {
4248 * Check to see if the resource can take
4249 * properties. If so, stick the resource into
4250 * "share" so it will all just work.
4252 features
= sa_proto_get_featureset(protocol
);
4253 if (features
& SA_FEATURE_RESOURCE
)
4254 share
= (sa_share_t
)resource
;
4259 /* group must exist */
4260 ret
= valid_unset(share
!= NULL
? share
: group
,
4262 if (ret
== SA_OK
&& !dryrun
) {
4263 if (share
!= NULL
) {
4264 sa_optionset_t optionset
;
4266 change
|= remove_options(share
, optlist
,
4269 * If a share optionset is
4272 optionset
= sa_get_optionset((sa_share_t
)share
,
4274 if (optionset
!= NULL
) {
4275 prop
= sa_get_property(optionset
, NULL
);
4277 (void) sa_destroy_optionset(
4281 change
|= remove_options(group
,
4282 optlist
, protocol
, &ret
);
4284 if (ret
== SA_OK
&& change
)
4285 worklist
= add_list(worklist
, group
, share
,
4288 (void) printf(gettext(
4289 "Could not remove properties: "
4290 "%s\n"), sa_errorstr(ret
));
4293 (void) printf(gettext("Group \"%s\" not found\n"), groupname
);
4294 ret
= SA_NO_SUCH_GROUP
;
4299 * We have a group and potentially legal additions
4301 * Commit to configuration if not a dryrun
4303 if (!dryrun
&& ret
== SA_OK
) {
4304 if (change
&& worklist
!= NULL
) {
4305 /* properties changed, so update all shares */
4306 (void) enable_all_groups(handle
, worklist
, 0, 0,
4310 if (worklist
!= NULL
)
4311 free_list(worklist
);
4316 * space_unset(groupname, optlist, protocol, sharepath, dryrun)
4318 * Unset named optionset properties.
4321 space_unset(sa_handle_t handle
, char *groupname
, struct options
*optlist
,
4322 char *protocol
, char *sharepath
, int dryrun
, char *sectype
)
4327 struct list
*worklist
= NULL
;
4328 sa_share_t share
= NULL
;
4330 group
= sa_get_group(handle
, groupname
);
4331 if (group
== NULL
) {
4332 (void) printf(gettext("Group \"%s\" not found\n"), groupname
);
4333 return (SA_NO_SUCH_GROUP
);
4335 if (sharepath
!= NULL
) {
4336 share
= sa_get_share(group
, sharepath
);
4337 if (share
== NULL
) {
4338 (void) printf(gettext(
4339 "Share does not exist in group %s\n"),
4340 groupname
, sharepath
);
4341 return (SA_NO_SUCH_PATH
);
4344 ret
= valid_unset_security(share
!= NULL
? share
: group
,
4345 optlist
, protocol
, sectype
);
4347 if (ret
== SA_OK
&& !dryrun
) {
4348 if (optlist
!= NULL
) {
4349 if (share
!= NULL
) {
4350 sa_security_t optionset
;
4352 change
= remove_security(share
,
4353 sectype
, optlist
, protocol
, &ret
);
4355 /* If a share security is empty, remove it */
4356 optionset
= sa_get_security((sa_group_t
)share
,
4358 if (optionset
!= NULL
) {
4359 prop
= sa_get_property(optionset
,
4362 ret
= sa_destroy_security(
4366 change
= remove_security(group
, sectype
,
4367 optlist
, protocol
, &ret
);
4370 sa_security_t security
;
4372 sec
= sa_proto_space_alias(protocol
, sectype
);
4373 security
= sa_get_security(group
, sec
, protocol
);
4375 sa_free_attr_string(sec
);
4376 if (security
!= NULL
) {
4377 ret
= sa_destroy_security(security
);
4381 ret
= SA_NO_SUCH_PROP
;
4385 (void) printf(gettext("Could not unset property: %s\n"),
4389 if (ret
== SA_OK
&& change
)
4390 worklist
= add_list(worklist
, group
, 0, protocol
);
4394 * We have a group and potentially legal additions
4397 /* Commit to configuration if not a dryrun */
4398 if (!dryrun
&& ret
== 0) {
4399 /* properties changed, so update all shares */
4400 if (change
&& worklist
!= NULL
)
4401 (void) enable_all_groups(handle
, worklist
, 0, 0,
4403 ret
= sa_update_config(handle
);
4405 if (worklist
!= NULL
)
4406 free_list(worklist
);
4411 * sa_unset(flags, argc, argv)
4413 * Implements the unset subcommand. Parsing done here and then basic
4414 * or space versions of the real code are called.
4418 sa_unset(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
4424 char *protocol
= NULL
;
4426 struct options
*optlist
= NULL
;
4427 char *rsrcname
= NULL
;
4428 char *sharepath
= NULL
;
4429 char *optset
= NULL
;
4432 while ((c
= getopt(argc
, argv
, "?hvnP:p:r:s:S:")) != EOF
) {
4441 if (protocol
!= NULL
) {
4442 (void) printf(gettext(
4443 "Specifying multiple protocols "
4444 "not supported: %s\n"), protocol
);
4445 return (SA_SYNTAX_ERR
);
4448 if (!sa_valid_protocol(protocol
)) {
4449 (void) printf(gettext(
4450 "Invalid protocol specified: %s\n"),
4452 return (SA_INVALID_PROTOCOL
);
4456 ret
= add_opt(&optlist
, optarg
, 1);
4458 case OPT_ADD_SYNTAX
:
4459 (void) printf(gettext("Property syntax error "
4460 "for property %s\n"), optarg
);
4461 return (SA_SYNTAX_ERR
);
4463 case OPT_ADD_PROPERTY
:
4464 (void) printf(gettext("Properties need to be "
4465 "set with set command: %s\n"), optarg
);
4466 return (SA_SYNTAX_ERR
);
4474 * Unset properties on resource if applicable or on
4475 * share if resource for this protocol doesn't use
4478 if (rsrcname
!= NULL
) {
4479 (void) printf(gettext(
4480 "Unsetting multiple resource "
4481 "names not supported\n"));
4482 return (SA_SYNTAX_ERR
);
4487 if (sharepath
!= NULL
) {
4488 (void) printf(gettext(
4489 "Adding multiple shares not supported\n"));
4490 return (SA_SYNTAX_ERR
);
4495 if (optset
!= NULL
) {
4496 (void) printf(gettext(
4497 "Specifying multiple property "
4498 "spaces not supported: %s\n"), optset
);
4499 return (SA_SYNTAX_ERR
);
4504 /* optopt on valid arg isn't defined */
4510 * Since a bad option gets to here, sort it
4511 * out and return a syntax error return value
4516 ret
= SA_SYNTAX_ERR
;
4522 (void) printf(gettext("usage: %s\n"),
4523 sa_get_usage(USAGE_UNSET
));
4528 if (optlist
!= NULL
)
4529 ret
= chk_opt(optlist
, optset
!= NULL
, protocol
);
4531 if (optind
>= argc
|| (optlist
== NULL
&& optset
== NULL
) ||
4534 (void) printf(gettext("usage: %s\n"),
4535 sa_get_usage(USAGE_UNSET
));
4536 if (optind
>= argc
) {
4537 (void) printf(gettext("%sgroup must be specified"),
4541 if (optlist
== NULL
) {
4542 (void) printf(gettext("%sat least one property must "
4543 "be specified"), sep
);
4546 if (protocol
== NULL
) {
4547 (void) printf(gettext("%sprotocol must be specified"),
4551 (void) printf("\n");
4552 ret
= SA_SYNTAX_ERR
;
4556 * If a group already exists, we can only add a new
4557 * protocol to it and not create a new one or add the
4558 * same protocol again.
4561 groupname
= argv
[optind
];
4562 auth
= check_authorizations(groupname
, flags
);
4564 ret
= basic_unset(handle
, groupname
, optlist
, protocol
,
4565 sharepath
, rsrcname
, dryrun
);
4567 ret
= space_unset(handle
, groupname
, optlist
, protocol
,
4568 sharepath
, dryrun
, optset
);
4570 if (dryrun
&& ret
== SA_OK
&& !auth
&& verbose
)
4571 (void) printf(gettext("Command would fail: %s\n"),
4572 sa_errorstr(SA_NO_PERMISSION
));
4578 * sa_enable_group(flags, argc, argv)
4580 * Implements the enable subcommand
4584 sa_enable_group(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
4591 char *protocol
= NULL
;
4593 struct list
*worklist
= NULL
;
4597 while ((c
= getopt(argc
, argv
, "?havnP:")) != EOF
) {
4606 if (protocol
!= NULL
) {
4607 (void) printf(gettext(
4608 "Specifying multiple protocols "
4609 "not supported: %s\n"), protocol
);
4610 return (SA_SYNTAX_ERR
);
4613 if (!sa_valid_protocol(protocol
)) {
4614 (void) printf(gettext(
4615 "Invalid protocol specified: %s\n"),
4617 return (SA_INVALID_PROTOCOL
);
4624 /* optopt on valid arg isn't defined */
4630 * Since a bad option gets to here, sort it
4631 * out and return a syntax error return value
4636 ret
= SA_SYNTAX_ERR
;
4640 (void) printf(gettext("usage: %s\n"),
4641 sa_get_usage(USAGE_ENABLE
));
4647 if (optind
== argc
&& !all
) {
4648 (void) printf(gettext("usage: %s\n"),
4649 sa_get_usage(USAGE_ENABLE
));
4650 (void) printf(gettext("\tmust specify group\n"));
4651 return (SA_NO_SUCH_PATH
);
4654 while (optind
< argc
) {
4655 group
= sa_get_group(handle
, argv
[optind
]);
4656 if (group
!= NULL
) {
4657 auth
&= check_authorizations(argv
[optind
],
4659 state
= sa_get_group_attr(group
, "state");
4660 if (state
!= NULL
&&
4661 strcmp(state
, "enabled") == 0) {
4662 /* already enabled */
4664 (void) printf(gettext(
4665 "Group \"%s\" is already "
4668 ret
= SA_BUSY
; /* already enabled */
4670 worklist
= add_list(worklist
, group
,
4673 (void) printf(gettext(
4674 "Enabling group \"%s\"\n"),
4678 sa_free_attr_string(state
);
4680 ret
= SA_NO_SUCH_GROUP
;
4685 for (group
= sa_get_group(handle
, NULL
);
4687 group
= sa_get_next_group(group
)) {
4688 worklist
= add_list(worklist
, group
, 0, protocol
);
4691 if (!dryrun
&& ret
== SA_OK
)
4692 ret
= enable_all_groups(handle
, worklist
, 1, 0, NULL
, B_FALSE
);
4694 if (ret
!= SA_OK
&& ret
!= SA_BUSY
)
4695 (void) printf(gettext("Could not enable group: %s\n"),
4700 if (worklist
!= NULL
)
4701 free_list(worklist
);
4702 if (dryrun
&& ret
== SA_OK
&& !auth
&& verbose
) {
4703 (void) printf(gettext("Command would fail: %s\n"),
4704 sa_errorstr(SA_NO_PERMISSION
));
4710 * disable_group(group, proto)
4712 * Disable all the shares in the specified group.. This is a helper
4713 * for disable_all_groups in order to simplify regular and subgroup
4714 * (zfs) disabling. Group has already been checked for non-NULL.
4718 disable_group(sa_group_t group
, char *proto
)
4724 * If the protocol isn't enabled, skip it and treat as
4727 if (!has_protocol(group
, proto
))
4730 for (share
= sa_get_share(group
, NULL
);
4731 share
!= NULL
&& ret
== SA_OK
;
4732 share
= sa_get_next_share(share
)) {
4733 ret
= sa_disable_share(share
, proto
);
4734 if (ret
== SA_NO_SUCH_PATH
) {
4736 * this is OK since the path is gone. we can't
4737 * re-share it anyway so no error.
4746 * disable_all_groups(work, setstate)
4748 * helper function that disables the shares in the list of groups
4749 * provided. It optionally marks the group as disabled. Used by both
4750 * enable and start subcommands.
4754 disable_all_groups(sa_handle_t handle
, struct list
*work
, int setstate
)
4757 sa_group_t subgroup
, group
;
4759 while (work
!= NULL
&& ret
== SA_OK
) {
4760 group
= (sa_group_t
)work
->item
;
4762 ret
= sa_set_group_attr(group
, "state", "disabled");
4765 name
= sa_get_group_attr(group
, "name");
4766 if (name
!= NULL
&& strcmp(name
, "zfs") == 0) {
4767 /* need to get the sub-groups for stopping */
4768 for (subgroup
= sa_get_sub_group(group
);
4770 subgroup
= sa_get_next_group(subgroup
)) {
4771 ret
= disable_group(subgroup
,
4775 ret
= disable_group(group
, work
->proto
);
4778 sa_free_attr_string(name
);
4780 * We don't want to "disable" since it won't come
4781 * up after a reboot. The SMF framework should do
4782 * the right thing. On enable we do want to do
4789 ret
= sa_update_config(handle
);
4794 * sa_disable_group(flags, argc, argv)
4796 * Implements the disable subcommand
4800 sa_disable_group(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
4807 char *protocol
= NULL
;
4809 struct list
*worklist
= NULL
;
4813 while ((c
= getopt(argc
, argv
, "?havn")) != EOF
) {
4822 if (protocol
!= NULL
) {
4823 (void) printf(gettext(
4824 "Specifying multiple protocols "
4825 "not supported: %s\n"), protocol
);
4826 return (SA_SYNTAX_ERR
);
4829 if (!sa_valid_protocol(protocol
)) {
4830 (void) printf(gettext(
4831 "Invalid protocol specified: %s\n"),
4833 return (SA_INVALID_PROTOCOL
);
4840 /* optopt on valid arg isn't defined */
4846 * Since a bad option gets to here, sort it
4847 * out and return a syntax error return value
4852 ret
= SA_SYNTAX_ERR
;
4858 (void) printf(gettext("usage: %s\n"),
4859 sa_get_usage(USAGE_DISABLE
));
4864 if (optind
== argc
&& !all
) {
4865 (void) printf(gettext("usage: %s\n"),
4866 sa_get_usage(USAGE_DISABLE
));
4867 (void) printf(gettext("\tmust specify group\n"));
4868 return (SA_NO_SUCH_PATH
);
4871 while (optind
< argc
) {
4872 group
= sa_get_group(handle
, argv
[optind
]);
4873 if (group
!= NULL
) {
4874 auth
&= check_authorizations(argv
[optind
],
4876 state
= sa_get_group_attr(group
, "state");
4877 if (state
== NULL
||
4878 strcmp(state
, "disabled") == 0) {
4879 /* already disabled */
4881 (void) printf(gettext(
4883 "already disabled\n"),
4885 ret
= SA_BUSY
; /* already disabled */
4887 worklist
= add_list(worklist
, group
, 0,
4890 (void) printf(gettext(
4892 "\"%s\"\n"), argv
[optind
]);
4895 sa_free_attr_string(state
);
4897 ret
= SA_NO_SUCH_GROUP
;
4902 for (group
= sa_get_group(handle
, NULL
);
4904 group
= sa_get_next_group(group
))
4905 worklist
= add_list(worklist
, group
, 0, protocol
);
4908 if (ret
== SA_OK
&& !dryrun
)
4909 ret
= disable_all_groups(handle
, worklist
, 1);
4910 if (ret
!= SA_OK
&& ret
!= SA_BUSY
)
4911 (void) printf(gettext("Could not disable group: %s\n"),
4915 if (worklist
!= NULL
)
4916 free_list(worklist
);
4917 if (dryrun
&& ret
== SA_OK
&& !auth
&& verbose
)
4918 (void) printf(gettext("Command would fail: %s\n"),
4919 sa_errorstr(SA_NO_PERMISSION
));
4924 * sa_start_group(flags, argc, argv)
4926 * Implements the start command.
4927 * This is similar to enable except it doesn't change the state
4928 * of the group(s) and only enables shares if the group is already
4933 sa_start_group(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
4938 int ret
= SMF_EXIT_OK
;
4939 char *protocol
= NULL
;
4941 struct list
*worklist
= NULL
;
4947 while ((c
= getopt(argc
, argv
, "?havP:")) != EOF
) {
4953 if (protocol
!= NULL
) {
4954 (void) printf(gettext(
4955 "Specifying multiple protocols "
4956 "not supported: %s\n"), protocol
);
4957 return (SA_SYNTAX_ERR
);
4960 if (!sa_valid_protocol(protocol
)) {
4961 (void) printf(gettext(
4962 "Invalid protocol specified: %s\n"),
4964 return (SA_INVALID_PROTOCOL
);
4971 /* optopt on valid arg isn't defined */
4977 * Since a bad option gets to here, sort it
4978 * out and return a syntax error return value
4984 ret
= SA_SYNTAX_ERR
;
4990 (void) printf(gettext("usage: %s\n"),
4991 sa_get_usage(USAGE_START
));
4996 if (optind
== argc
&& !all
) {
4997 (void) printf(gettext("usage: %s\n"),
4998 sa_get_usage(USAGE_START
));
4999 return (SMF_EXIT_ERR_FATAL
);
5003 while (optind
< argc
) {
5004 group
= sa_get_group(handle
, argv
[optind
]);
5005 if (group
!= NULL
) {
5006 state
= sa_get_group_attr(group
, "state");
5007 if (state
== NULL
||
5008 strcmp(state
, "enabled") == 0) {
5009 worklist
= add_list(worklist
, group
, 0,
5012 (void) printf(gettext(
5013 "Starting group \"%s\"\n"),
5017 * Determine if there are any
5018 * protocols. If there aren't any,
5019 * then there isn't anything to do in
5020 * any case so no error.
5022 if (sa_get_optionset(group
,
5023 protocol
) != NULL
) {
5028 sa_free_attr_string(state
);
5033 for (group
= sa_get_group(handle
, NULL
);
5035 group
= sa_get_next_group(group
)) {
5036 state
= sa_get_group_attr(group
, "state");
5037 if (state
== NULL
|| strcmp(state
, "enabled") == 0)
5038 worklist
= add_list(worklist
, group
, 0,
5041 sa_free_attr_string(state
);
5045 (void) enable_all_groups(handle
, worklist
, 0, 1, protocol
, B_FALSE
);
5047 if (worklist
!= NULL
)
5048 free_list(worklist
);
5053 * sa_stop_group(flags, argc, argv)
5055 * Implements the stop command.
5056 * This is similar to disable except it doesn't change the state
5057 * of the group(s) and only disables shares if the group is already
5061 sa_stop_group(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
5066 int ret
= SMF_EXIT_OK
;
5067 char *protocol
= NULL
;
5069 struct list
*worklist
= NULL
;
5075 while ((c
= getopt(argc
, argv
, "?havP:")) != EOF
) {
5081 if (protocol
!= NULL
) {
5082 (void) printf(gettext(
5083 "Specifying multiple protocols "
5084 "not supported: %s\n"), protocol
);
5085 return (SA_SYNTAX_ERR
);
5088 if (!sa_valid_protocol(protocol
)) {
5089 (void) printf(gettext(
5090 "Invalid protocol specified: %s\n"),
5092 return (SA_INVALID_PROTOCOL
);
5099 /* optopt on valid arg isn't defined */
5105 * Since a bad option gets to here, sort it
5106 * out and return a syntax error return value
5112 ret
= SA_SYNTAX_ERR
;
5118 (void) printf(gettext("usage: %s\n"),
5119 sa_get_usage(USAGE_STOP
));
5124 if (optind
== argc
&& !all
) {
5125 (void) printf(gettext("usage: %s\n"),
5126 sa_get_usage(USAGE_STOP
));
5127 return (SMF_EXIT_ERR_FATAL
);
5129 while (optind
< argc
) {
5130 group
= sa_get_group(handle
, argv
[optind
]);
5131 if (group
!= NULL
) {
5132 state
= sa_get_group_attr(group
, "state");
5133 if (state
== NULL
||
5134 strcmp(state
, "enabled") == 0) {
5135 worklist
= add_list(worklist
, group
, 0,
5138 (void) printf(gettext(
5139 "Stopping group \"%s\"\n"),
5145 sa_free_attr_string(state
);
5150 for (group
= sa_get_group(handle
, NULL
);
5152 group
= sa_get_next_group(group
)) {
5153 state
= sa_get_group_attr(group
, "state");
5154 if (state
== NULL
|| strcmp(state
, "enabled") == 0)
5155 worklist
= add_list(worklist
, group
, 0,
5158 sa_free_attr_string(state
);
5161 (void) disable_all_groups(handle
, worklist
, 0);
5162 ret
= sa_update_config(handle
);
5164 if (worklist
!= NULL
)
5165 free_list(worklist
);
5170 * remove_all_options(share, proto)
5172 * Removes all options on a share.
5176 remove_all_options(sa_share_t share
, char *proto
)
5178 sa_optionset_t optionset
;
5179 sa_security_t security
;
5180 sa_security_t prevsec
= NULL
;
5182 optionset
= sa_get_optionset(share
, proto
);
5183 if (optionset
!= NULL
)
5184 (void) sa_destroy_optionset(optionset
);
5185 for (security
= sa_get_security(share
, NULL
, NULL
);
5187 security
= sa_get_next_security(security
)) {
5190 * We walk through the list. prevsec keeps the
5191 * previous security so we can delete it without
5192 * destroying the list.
5194 if (prevsec
!= NULL
) {
5195 /* remove the previously seen security */
5196 (void) sa_destroy_security(prevsec
);
5197 /* set to NULL so we don't try multiple times */
5200 type
= sa_get_security_attr(security
, "type");
5203 * if the security matches the specified protocol, we
5204 * want to remove it. prevsec holds it until either
5205 * the next pass or we fall out of the loop.
5207 if (strcmp(type
, proto
) == 0)
5209 sa_free_attr_string(type
);
5212 /* in case there is one left */
5213 if (prevsec
!= NULL
)
5214 (void) sa_destroy_security(prevsec
);
5219 * for legacy support, we need to handle the old syntax. This is what
5220 * we get if sharemgr is called with the name "share" rather than
5225 format_legacy_path(char *buff
, int buffsize
, char *proto
, char *cmd
)
5229 err
= snprintf(buff
, buffsize
, "/usr/lib/fs/%s/%s", proto
, cmd
);
5237 * check_legacy_cmd(proto, cmd)
5239 * Check to see if the cmd exists in /usr/lib/fs/<proto>/<cmd> and is
5244 check_legacy_cmd(char *path
)
5249 if (stat(path
, &st
) == 0) {
5250 if (S_ISREG(st
.st_mode
) &&
5251 st
.st_mode
& (S_IXUSR
|S_IXGRP
|S_IXOTH
))
5258 * run_legacy_command(proto, cmd, argv)
5260 * We know the command exists, so attempt to execute it with all the
5261 * arguments. This implements full legacy share support for those
5262 * protocols that don't have plugin providers.
5266 run_legacy_command(char *path
, char *argv
[])
5270 ret
= execv(path
, argv
);
5274 ret
= SA_NO_PERMISSION
;
5277 ret
= SA_SYSTEM_ERR
;
5285 * out_share(out, group, proto)
5287 * Display the share information in the format that the "share"
5288 * command has traditionally used.
5292 out_share(FILE *out
, sa_group_t group
, char *proto
)
5299 * The original share command defaulted to displaying NFS
5300 * shares or allowed a protocol to be specified. We want to
5301 * skip those shares that are not the specified protocol.
5303 if (proto
!= NULL
&& sa_get_optionset(group
, proto
) == NULL
)
5310 * get the default property string. NFS uses "rw" but
5311 * everything else will use "".
5313 if (proto
!= NULL
&& strcmp(proto
, "nfs") != 0)
5318 for (share
= sa_get_share(group
, NULL
);
5320 share
= sa_get_next_share(share
)) {
5329 char shareopts
[MAXNAMLEN
];
5331 sharedstate
= sa_get_share_attr(share
, "shared");
5332 path
= sa_get_share_attr(share
, "path");
5333 type
= sa_get_share_attr(share
, "type");
5334 resource
= get_resource(share
);
5335 groupname
= sa_get_group_attr(group
, "name");
5337 if (groupname
!= NULL
&& strcmp(groupname
, "default") == 0) {
5338 sa_free_attr_string(groupname
);
5341 description
= sa_get_share_description(share
);
5344 * Want the sharetab version if it exists, defaulting
5345 * to NFS if no protocol specified.
5347 (void) snprintf(shareopts
, MAXNAMLEN
, "shareopts-%s", proto
);
5348 soptions
= sa_get_share_attr(share
, shareopts
);
5350 if (sharedstate
== NULL
)
5353 if (soptions
== NULL
)
5354 soptions
= sa_proto_legacy_format(proto
, share
, 1);
5357 /* only active shares go here */
5358 (void) snprintf(resfmt
, sizeof (resfmt
), "%s%s%s",
5359 resource
!= NULL
? resource
: "-",
5360 groupname
!= NULL
? "@" : "",
5361 groupname
!= NULL
? groupname
: "");
5362 (void) fprintf(out
, "%-14.14s %s %s \"%s\" \n",
5363 resfmt
, (path
!= NULL
) ? path
: "",
5364 (soptions
!= NULL
&& strlen(soptions
) > 0) ?
5366 (description
!= NULL
) ? description
: "");
5370 sa_free_attr_string(path
);
5372 sa_free_attr_string(type
);
5373 if (resource
!= NULL
)
5374 sa_free_attr_string(resource
);
5375 if (groupname
!= NULL
)
5376 sa_free_attr_string(groupname
);
5377 if (description
!= NULL
)
5378 sa_free_share_description(description
);
5379 if (sharedstate
!= NULL
)
5380 sa_free_attr_string(sharedstate
);
5381 if (soptions
!= NULL
)
5382 sa_format_free(soptions
);
5387 * output_legacy_file(out, proto)
5389 * Walk all of the groups for the specified protocol and call
5390 * out_share() to format and write in the format displayed by the
5391 * "share" command with no arguments.
5395 output_legacy_file(FILE *out
, char *proto
, sa_handle_t handle
)
5399 for (group
= sa_get_group(handle
, NULL
);
5401 group
= sa_get_next_group(group
)) {
5405 * Go through all the groups and ZFS
5406 * sub-groups. out_share() will format the shares in
5407 * the group appropriately.
5410 zfs
= sa_get_group_attr(group
, "zfs");
5413 sa_free_attr_string(zfs
);
5414 for (zgroup
= sa_get_sub_group(group
);
5416 zgroup
= sa_get_next_group(zgroup
)) {
5418 /* got a group, so display it */
5419 out_share(out
, zgroup
, proto
);
5422 out_share(out
, group
, proto
);
5428 sa_legacy_share(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
5430 char *protocol
= "nfs";
5431 char *options
= NULL
;
5432 char *description
= NULL
;
5433 char *groupname
= NULL
;
5434 char *sharepath
= NULL
;
5435 char *resource
= NULL
;
5436 char *groupstatus
= NULL
;
5437 int persist
= SA_SHARE_TRANSIENT
;
5442 int true_legacy
= 0;
5443 int curtype
= SA_SHARE_TRANSIENT
;
5444 char cmd
[MAXPATHLEN
];
5445 sa_group_t group
= NULL
;
5446 sa_resource_t rsrc
= NULL
;
5448 char dir
[MAXPATHLEN
];
5454 while ((c
= getopt(argc
, argv
, "?hF:d:o:p")) != EOF
) {
5457 description
= optarg
;
5462 if (!sa_valid_protocol(protocol
)) {
5463 if (format_legacy_path(cmd
, MAXPATHLEN
,
5464 protocol
, "share") == 0 &&
5465 check_legacy_cmd(cmd
)) {
5468 (void) fprintf(stderr
, gettext(
5469 "Invalid protocol specified: "
5471 return (SA_INVALID_PROTOCOL
);
5480 persist
= SA_SHARE_PERMANENT
;
5484 /* optopt on valid arg isn't defined */
5490 * Since a bad option gets to here, sort it
5491 * out and return a syntax error return value
5496 ret
= SA_LEGACY_ERR
;
5502 (void) fprintf(stderr
, gettext("usage: %s\n"),
5503 sa_get_usage(USAGE_SHARE
));
5508 /* Have the info so construct what is needed */
5509 if (!argsused
&& optind
== argc
) {
5510 /* display current info in share format */
5511 (void) output_legacy_file(stdout
, protocol
, handle
);
5515 /* We are modifying the configuration */
5516 if (optind
== argc
) {
5517 (void) fprintf(stderr
, gettext("usage: %s\n"),
5518 sa_get_usage(USAGE_SHARE
));
5519 return (SA_LEGACY_ERR
);
5522 /* If still using legacy share/unshare, exec it */
5523 ret
= run_legacy_command(cmd
, argv
);
5527 sharepath
= argv
[optind
++];
5528 if (optind
< argc
) {
5529 resource
= argv
[optind
];
5530 groupname
= strchr(resource
, '@');
5531 if (groupname
!= NULL
)
5532 *groupname
++ = '\0';
5534 if (realpath(sharepath
, dir
) == NULL
)
5539 share
= sa_find_share(handle
, sharepath
);
5543 features
= sa_proto_get_featureset(protocol
);
5545 if (groupname
!= NULL
) {
5546 ret
= SA_NOT_ALLOWED
;
5547 } else if (ret
== SA_OK
) {
5550 * The legacy group is always present and zfs groups
5551 * come and go. zfs shares may be in sub-groups and
5552 * the zfs share will already be in that group so it
5553 * isn't an error. If the protocol is "smb", the group
5554 * "smb" is used when "default" would otherwise be
5555 * used. "default" is NFS only and "smb" is SMB only.
5557 if (strcmp(protocol
, "smb") == 0)
5558 legacygroup
= "smb";
5560 legacygroup
= "default";
5563 * If the share exists (not NULL), then make sure it
5564 * is one we want to handle by getting the parent
5567 if (share
!= NULL
) {
5568 group
= sa_get_parent_group(share
);
5570 group
= sa_get_group(handle
, legacygroup
);
5571 if (group
== NULL
&& strcmp(legacygroup
, "smb") == 0) {
5573 * This group may not exist, so create
5574 * as necessary. It only contains the
5577 group
= sa_create_group(handle
, legacygroup
,
5580 (void) sa_create_optionset(group
,
5585 if (group
== NULL
) {
5586 ret
= SA_SYSTEM_ERR
;
5590 groupstatus
= group_status(group
);
5591 if (share
== NULL
) {
5592 share
= sa_add_share(group
, sharepath
,
5594 if (share
== NULL
&&
5595 ret
== SA_DUPLICATE_NAME
) {
5597 * Could be a ZFS path being started
5599 if (sa_zfs_is_shared(handle
,
5602 group
= sa_get_group(handle
,
5604 if (group
== NULL
) {
5609 ret
= SA_CONFIG_ERR
;
5611 share
= sa_add_share(
5620 * May want to change persist state, but the
5621 * important thing is to change options. We
5622 * need to change them regardless of the
5626 if (sa_zfs_is_shared(handle
, sharepath
)) {
5629 remove_all_options(share
, protocol
);
5630 type
= sa_get_share_attr(share
, "type");
5632 strcmp(type
, "transient") != 0) {
5633 curtype
= SA_SHARE_PERMANENT
;
5636 sa_free_attr_string(type
);
5637 if (curtype
!= persist
) {
5638 (void) sa_set_share_attr(share
, "type",
5639 persist
== SA_SHARE_PERMANENT
?
5640 "persist" : "transient");
5645 * If there is a resource name, we may
5646 * actually care about it if this is share for
5647 * a protocol that uses resource level sharing
5648 * (SMB). We need to find the resource and, if
5649 * it exists, make sure it belongs to the
5650 * current share. If it doesn't exist, attempt
5654 if (ret
== SA_OK
&& resource
!= NULL
) {
5655 rsrc
= sa_find_resource(handle
, resource
);
5657 if (share
!= sa_get_resource_parent(rsrc
))
5658 ret
= SA_DUPLICATE_NAME
;
5660 rsrc
= sa_add_resource(share
, resource
,
5663 if (features
& SA_FEATURE_RESOURCE
)
5667 /* Have a group to hold this share path */
5668 if (ret
== SA_OK
&& options
!= NULL
&&
5669 strlen(options
) > 0) {
5670 ret
= sa_parse_legacy_options(share
,
5676 * ZFS shares never have a description
5677 * and we can't store the values so
5680 if (ret
== SA_OK
&& description
!= NULL
)
5681 ret
= sa_set_share_description(share
,
5685 strcmp(groupstatus
, "enabled") == 0) {
5687 ret
= sa_enable_share(share
, protocol
);
5689 ret
= sa_enable_resource(rsrc
,
5692 persist
== SA_SHARE_PERMANENT
) {
5693 (void) sa_update_legacy(share
,
5697 ret
= sa_update_config(handle
);
5702 (void) fprintf(stderr
, gettext("Could not share: %s: %s\n"),
5703 sharepath
, sa_errorstr(ret
));
5704 ret
= SA_LEGACY_ERR
;
5710 * sa_legacy_unshare(flags, argc, argv)
5712 * Implements the original unshare command.
5715 sa_legacy_unshare(sa_handle_t handle
, int flags
, int argc
, char *argv
[])
5717 char *protocol
= "nfs"; /* for now */
5718 char *options
= NULL
;
5719 char *sharepath
= NULL
;
5720 int persist
= SA_SHARE_TRANSIENT
;
5724 int true_legacy
= 0;
5725 uint64_t features
= 0;
5726 sa_resource_t resource
= NULL
;
5727 char cmd
[MAXPATHLEN
];
5733 while ((c
= getopt(argc
, argv
, "?hF:o:p")) != EOF
) {
5737 if (!sa_valid_protocol(protocol
)) {
5738 if (format_legacy_path(cmd
, MAXPATHLEN
,
5739 protocol
, "unshare") == 0 &&
5740 check_legacy_cmd(cmd
)) {
5743 (void) printf(gettext(
5744 "Invalid file system name\n"));
5745 return (SA_INVALID_PROTOCOL
);
5754 persist
= SA_SHARE_PERMANENT
;
5758 /* optopt on valid arg isn't defined */
5764 * Since a bad option gets to here, sort it
5765 * out and return a syntax error return value
5770 ret
= SA_LEGACY_ERR
;
5776 (void) printf(gettext("usage: %s\n"),
5777 sa_get_usage(USAGE_UNSHARE
));
5782 /* Have the info so construct what is needed */
5783 if (optind
== argc
|| (optind
+ 1) < argc
|| options
!= NULL
) {
5784 ret
= SA_SYNTAX_ERR
;
5787 char dir
[MAXPATHLEN
];
5789 /* if still using legacy share/unshare, exec it */
5790 ret
= run_legacy_command(cmd
, argv
);
5794 * Find the path in the internal configuration. If it
5795 * isn't found, attempt to resolve the path via
5796 * realpath() and try again.
5798 sharepath
= argv
[optind
++];
5799 share
= sa_find_share(handle
, sharepath
);
5800 if (share
== NULL
) {
5801 if (realpath(sharepath
, dir
) == NULL
) {
5802 ret
= SA_NO_SUCH_PATH
;
5804 share
= sa_find_share(handle
, dir
);
5807 if (share
== NULL
) {
5808 /* Could be a resource name so check that next */
5809 features
= sa_proto_get_featureset(protocol
);
5810 resource
= sa_find_resource(handle
, sharepath
);
5811 if (resource
!= NULL
) {
5812 share
= sa_get_resource_parent(resource
);
5813 if (features
& SA_FEATURE_RESOURCE
)
5814 (void) sa_disable_resource(resource
,
5816 if (persist
== SA_SHARE_PERMANENT
) {
5817 ret
= sa_remove_resource(resource
);
5819 ret
= sa_update_config(handle
);
5822 * If we still have a resource on the
5823 * share, we don't disable the share
5824 * itself. IF there aren't anymore, we
5825 * need to remove the share. The
5826 * removal will be done in the next
5827 * section if appropriate.
5829 resource
= sa_get_share_resource(share
, NULL
);
5830 if (resource
!= NULL
)
5832 } else if (ret
== SA_OK
) {
5833 /* Didn't find path and no resource */
5837 if (share
!= NULL
&& resource
== NULL
) {
5838 ret
= sa_disable_share(share
, protocol
);
5840 * Errors are ok and removal should still occur. The
5841 * legacy unshare is more forgiving of errors than the
5842 * remove-share subcommand which may need the force
5843 * flag set for some error conditions. That is, the
5844 * "unshare" command will always unshare if it can
5845 * while "remove-share" might require the force option.
5847 if (persist
== SA_SHARE_PERMANENT
) {
5848 ret
= sa_remove_share(share
);
5850 ret
= sa_update_config(handle
);
5852 } else if (ret
== SA_OK
&& share
== NULL
&& resource
== NULL
) {
5854 * If both share and resource are NULL, then
5855 * share not found. If one or the other was
5856 * found or there was an earlier error, we
5857 * assume it was handled earlier.
5859 ret
= SA_NOT_SHARED
;
5864 (void) printf("%s: %s\n", sharepath
, sa_errorstr(ret
));
5865 ret
= SA_LEGACY_ERR
;
5868 (void) printf(gettext("usage: %s\n"),
5869 sa_get_usage(USAGE_UNSHARE
));
5878 * Common commands that implement the sub-commands used by all
5879 * protocols. The entries are found via the lookup command
5882 static sa_command_t commands
[] = {
5883 {"add-share", 0, sa_addshare
, USAGE_ADD_SHARE
, SVC_SET
},
5884 {"create", 0, sa_create
, USAGE_CREATE
, SVC_SET
|SVC_ACTION
},
5885 {"delete", 0, sa_delete
, USAGE_DELETE
, SVC_SET
|SVC_ACTION
},
5886 {"disable", 0, sa_disable_group
, USAGE_DISABLE
, SVC_SET
|SVC_ACTION
},
5887 {"enable", 0, sa_enable_group
, USAGE_ENABLE
, SVC_SET
|SVC_ACTION
},
5888 {"list", 0, sa_list
, USAGE_LIST
},
5889 {"move-share", 0, sa_moveshare
, USAGE_MOVE_SHARE
, SVC_SET
},
5890 {"remove-share", 0, sa_removeshare
, USAGE_REMOVE_SHARE
, SVC_SET
},
5891 {"set", 0, sa_set
, USAGE_SET
, SVC_SET
},
5892 {"set-share", 0, sa_set_share
, USAGE_SET_SHARE
, SVC_SET
},
5893 {"show", 0, sa_show
, USAGE_SHOW
},
5894 {"share", 0, sa_legacy_share
, USAGE_SHARE
, SVC_SET
|SVC_ACTION
},
5895 {"start", CMD_NODISPLAY
, sa_start_group
, USAGE_START
,
5896 SVC_SET
|SVC_ACTION
},
5897 {"stop", CMD_NODISPLAY
, sa_stop_group
, USAGE_STOP
, SVC_SET
|SVC_ACTION
},
5898 {"unset", 0, sa_unset
, USAGE_UNSET
, SVC_SET
},
5899 {"unshare", 0, sa_legacy_unshare
, USAGE_UNSHARE
, SVC_SET
|SVC_ACTION
},
5900 {NULL
, 0, NULL
, NULL
}
5904 sa_get_usage(sa_usage_t index
)
5908 case USAGE_ADD_SHARE
:
5909 ret
= gettext("add-share [-nth] [-r resource-name] "
5910 "[-d \"description text\"] -s sharepath group");
5914 "create [-nvh] [-P proto [-p property=value]] group");
5917 ret
= gettext("delete [-nvh] [-P proto] [-f] group");
5920 ret
= gettext("disable [-nvh] {-a | group ...}");
5923 ret
= gettext("enable [-nvh] {-a | group ...}");
5926 ret
= gettext("list [-vh] [-P proto]");
5928 case USAGE_MOVE_SHARE
:
5930 "move-share [-nvh] -s sharepath destination-group");
5932 case USAGE_REMOVE_SHARE
:
5934 "remove-share [-fnvh] {-s sharepath | -r resource} "
5938 ret
= gettext("set [-nvh] -P proto [-S optspace] "
5939 "[-p property=value]* [-s sharepath] [-r resource]] "
5942 case USAGE_SET_SECURITY
:
5943 ret
= gettext("set-security [-nvh] -P proto -S security-type "
5944 "[-p property=value]* group");
5946 case USAGE_SET_SHARE
:
5947 ret
= gettext("set-share [-nh] [-r resource] "
5948 "[-d \"description text\"] -s sharepath group");
5951 ret
= gettext("show [-pvxh] [-P proto] [group ...]");
5954 ret
= gettext("share [-F fstype] [-p] [-o optionlist]"
5955 "[-d description] [pathname [resourcename]]");
5958 ret
= gettext("start [-vh] [-P proto] {-a | group ...}");
5961 ret
= gettext("stop [-vh] [-P proto] {-a | group ...}");
5964 ret
= gettext("unset [-nvh] -P proto [-S optspace] "
5965 "[-p property]* group");
5967 case USAGE_UNSET_SECURITY
:
5968 ret
= gettext("unset-security [-nvh] -P proto "
5969 "-S security-type [-p property]* group");
5973 "unshare [-F fstype] [-p] [-o optionlist] sharepath");
5980 * sa_lookup(cmd, proto)
5982 * Lookup the sub-command. proto isn't currently used, but it may
5983 * eventually provide a way to provide protocol specific sub-commands.
5986 sa_lookup(char *cmd
, char *proto
)
5995 for (i
= 0; commands
[i
].cmdname
!= NULL
; i
++) {
5996 if (strncmp(cmd
, commands
[i
].cmdname
, len
) == 0)
5997 return (&commands
[i
]);
6003 sub_command_help(char *proto
)
6010 (void) printf(gettext("\tsub-commands:\n"));
6011 for (i
= 0; commands
[i
].cmdname
!= NULL
; i
++) {
6012 if (!(commands
[i
].flags
& (CMD_ALIAS
|CMD_NODISPLAY
)))
6013 (void) printf("\t%s\n",
6014 sa_get_usage((sa_usage_t
)commands
[i
].cmdidx
));