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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
31 #include "libshare_impl.h"
34 #include <sys/types.h>
35 #include <sys/param.h>
39 #include <sys/systeminfo.h>
43 #define MAXISALEN 257 /* based on sysinfo(2) man page */
46 * protocol plugin interface
48 * finds plugins and makes them accessible. This is only "used" by
52 struct sa_proto_plugin
*sap_proto_list
;
54 static struct sa_proto_handle sa_proto_handle
;
56 void proto_plugin_fini();
59 * Returns true if name is "." or "..", otherwise returns false.
62 proto_is_dot_or_dotdot(const char *name
)
67 if ((name
[1] == '\0') || (name
[1] == '.' && name
[2] == '\0'))
76 * Initialize the protocol specific plugin modules.
78 * Walk /usr/lib/fs/\* for libshare_*.so modules, for example,
79 * /usr/lib/fs/nfs/libshare_nfs.so. A protocol specific directory
80 * would have modules with names of the form libshare_<proto>.so.
81 * For each protocol found, initialize it and add it to the internal
82 * list of protocols. These are used for protocol specific operations.
88 struct sa_proto_plugin
*proto
;
90 struct sa_plugin_ops
*plugin_ops
;
99 if (sysinfo(SI_ARCHITECTURE_64
, isa
, MAXISALEN
) == -1)
105 if ((dir
= opendir(SA_LIB_DIR
)) == NULL
)
108 while ((dent
= readdir(dir
)) != NULL
) {
109 char path
[MAXPATHLEN
];
111 if (proto_is_dot_or_dotdot(dent
->d_name
))
114 (void) snprintf(path
, MAXPATHLEN
,
115 "%s/%s/%s/libshare_%s.so.1", SA_LIB_DIR
,
116 dent
->d_name
, isa
, dent
->d_name
);
119 * If file doesn't exist, don't try to map it
121 if (stat(path
, &st
) < 0)
124 if ((dlhandle
= dlopen(path
, RTLD_FIRST
|RTLD_LAZY
)) == NULL
) {
125 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
126 "Error in plugin for protocol %s: %s\n"),
127 dent
->d_name
, dlerror());
131 plugin_ops
= (struct sa_plugin_ops
*)
132 dlsym(dlhandle
, "sa_plugin_ops");
133 if (plugin_ops
== NULL
) {
134 (void) fprintf(stderr
, dgettext(TEXT_DOMAIN
,
135 "Error in plugin ops for protocol %s: %s\n"),
136 dent
->d_name
, dlerror());
137 (void) dlclose(dlhandle
);
141 proto
= (struct sa_proto_plugin
*)
142 calloc(1, sizeof (struct sa_proto_plugin
));
144 (void) dlclose(dlhandle
);
149 proto
->plugin_ops
= plugin_ops
;
150 proto
->plugin_handle
= dlhandle
;
152 proto
->plugin_next
= sap_proto_list
;
153 sap_proto_list
= proto
;
156 (void) closedir(dir
);
158 if (num_protos
!= 0) {
159 sa_proto_handle
.sa_proto
=
160 (char **)calloc(num_protos
, sizeof (char *));
161 sa_proto_handle
.sa_ops
=
162 (struct sa_plugin_ops
**)calloc(num_protos
,
163 sizeof (struct sa_plugin_ops
*));
164 if (sa_proto_handle
.sa_proto
!= NULL
&&
165 sa_proto_handle
.sa_ops
!= NULL
) {
167 struct sa_proto_plugin
*tmp
;
169 for (i
= 0, tmp
= sap_proto_list
;
170 i
< num_protos
&& tmp
!= NULL
;
171 tmp
= tmp
->plugin_next
) {
174 if (tmp
->plugin_ops
->sa_init
!= NULL
)
175 err
= tmp
->plugin_ops
->sa_init();
178 * Only include if the init
179 * succeeded or was NULL
181 sa_proto_handle
.sa_num_proto
++;
182 sa_proto_handle
.sa_ops
[i
] =
184 sa_proto_handle
.sa_proto
[i
] =
185 tmp
->plugin_ops
->sa_protocol
;
195 * There was an error, so cleanup prior to return of failure.
204 * proto_plugin_fini()
206 * Uninitialize all the plugin modules.
212 struct sa_proto_plugin
*p
;
215 * Protocols may call this framework during _fini
216 * (the smbfs plugin is known to do this) so do
217 * two passes: 1st call _fini; 2nd free, dlclose.
219 for (p
= sap_proto_list
; p
!= NULL
; p
= p
->plugin_next
)
220 p
->plugin_ops
->sa_fini();
222 while ((p
= sap_proto_list
) != NULL
) {
223 sap_proto_list
= p
->plugin_next
;
225 if (p
->plugin_handle
!= NULL
)
226 (void) dlclose(p
->plugin_handle
);
229 if (sa_proto_handle
.sa_ops
!= NULL
) {
230 free(sa_proto_handle
.sa_ops
);
231 sa_proto_handle
.sa_ops
= NULL
;
233 if (sa_proto_handle
.sa_proto
!= NULL
) {
234 free(sa_proto_handle
.sa_proto
);
235 sa_proto_handle
.sa_proto
= NULL
;
237 sa_proto_handle
.sa_num_proto
= 0;
241 * find_protocol(proto)
243 * Search the plugin list for the specified protocol and return the
244 * ops vector. NULL if protocol is not defined.
247 static struct sa_plugin_ops
*
248 find_protocol(char *proto
)
251 struct sa_plugin_ops
*ops
= NULL
;
252 extern mutex_t sa_global_lock
;
254 (void) mutex_lock(&sa_global_lock
);
256 for (i
= 0; i
< sa_proto_handle
.sa_num_proto
; i
++) {
257 if (strcmp(proto
, sa_proto_handle
.sa_proto
[i
]) == 0) {
258 ops
= sa_proto_handle
.sa_ops
[i
];
263 (void) mutex_unlock(&sa_global_lock
);
268 * sa_proto_share(proto, share)
270 * Activate a share for the specified protocol.
274 sa_proto_share(char *proto
, sa_share_t share
)
276 struct sa_plugin_ops
*ops
= find_protocol(proto
);
277 int ret
= SA_INVALID_PROTOCOL
;
279 if (ops
!= NULL
&& ops
->sa_share
!= NULL
)
280 ret
= ops
->sa_share(share
);
285 * sa_proto_unshare(proto, share)
287 * Deactivate (unshare) the share for this protocol.
291 sa_proto_unshare(sa_share_t share
, char *proto
, char *path
)
293 struct sa_plugin_ops
*ops
= find_protocol(proto
);
294 int ret
= SA_INVALID_PROTOCOL
;
296 if (ops
!= NULL
&& ops
->sa_unshare
!= NULL
)
297 ret
= ops
->sa_unshare(share
, path
);
302 * sa_proto_share_resource(char *proto, sa_resource_t resource)
304 * For protocols that actually enable at the resource level, do the
305 * protocol specific resource enable. If it doesn't, return an error.
306 * Note that the resource functions are optional so can return
311 sa_proto_share_resource(char *proto
, sa_resource_t resource
)
313 struct sa_plugin_ops
*ops
= find_protocol(proto
);
314 int ret
= SA_INVALID_PROTOCOL
;
317 if (ops
->sa_enable_resource
!= NULL
)
318 ret
= ops
->sa_enable_resource(resource
);
320 ret
= SA_NOT_SUPPORTED
;
326 * sa_proto_unshare_resource(char *proto, sa_resource_t resource)
328 * For protocols that actually disable at the resource level, do the
329 * protocol specific resource disable. If it doesn't, return an error.
333 sa_proto_unshare_resource(char *proto
, sa_resource_t resource
)
335 struct sa_plugin_ops
*ops
= find_protocol(proto
);
336 int ret
= SA_INVALID_PROTOCOL
;
339 if (ops
->sa_disable_resource
!= NULL
)
340 ret
= ops
->sa_disable_resource(resource
);
342 ret
= SA_NOT_SUPPORTED
;
348 * sa_proto_valid_prop(handle, proto, prop, opt)
350 * Check to see if the specified prop is valid for this protocol.
354 sa_proto_valid_prop(sa_handle_t handle
, char *proto
, sa_property_t prop
,
357 struct sa_plugin_ops
*ops
= find_protocol(proto
);
360 if (ops
!= NULL
&& ops
->sa_valid_prop
!= NULL
)
361 ret
= ops
->sa_valid_prop(handle
, prop
, opt
);
366 * sa_proto_valid_space(proto, space)
368 * Check if space is valid optionspace for proto.
369 * Protocols that don't implement this don't support spaces.
372 sa_proto_valid_space(char *proto
, char *token
)
374 struct sa_plugin_ops
*ops
= find_protocol(proto
);
377 if (ops
!= NULL
&& ops
->sa_valid_space
!= NULL
)
378 ret
= ops
->sa_valid_space(token
);
383 * sa_proto_space_alias(proto, space)
385 * If the name for space is an alias, return its proper name. This is
386 * used to translate "default" values into proper form.
389 sa_proto_space_alias(char *proto
, char *space
)
391 struct sa_plugin_ops
*ops
= find_protocol(proto
);
394 if (ops
!= NULL
&& ops
->sa_space_alias
!= NULL
)
395 ret
= ops
->sa_space_alias(space
);
400 * sa_proto_security_prop(proto, token)
402 * Check to see if the property name in token is a valid named
403 * optionset property.
407 sa_proto_security_prop(char *proto
, char *token
)
409 struct sa_plugin_ops
*ops
= find_protocol(proto
);
412 if (ops
!= NULL
&& ops
->sa_security_prop
!= NULL
)
413 ret
= ops
->sa_security_prop(token
);
418 * sa_proto_legacy_opts(proto, grouup, options)
420 * Have the protocol specific parser parse the options string and add
421 * an appropriate optionset to group.
425 sa_proto_legacy_opts(char *proto
, sa_group_t group
, char *options
)
427 struct sa_plugin_ops
*ops
= find_protocol(proto
);
428 int ret
= SA_INVALID_PROTOCOL
;
430 if (ops
!= NULL
&& ops
->sa_legacy_opts
!= NULL
)
431 ret
= ops
->sa_legacy_opts(group
, options
);
436 * sa_proto_legacy_format(proto, group, hier)
438 * Return a legacy format string representing either the group's
439 * properties or the groups hierarchical properties.
443 sa_proto_legacy_format(char *proto
, sa_group_t group
, int hier
)
445 struct sa_plugin_ops
*ops
= find_protocol(proto
);
448 if (ops
!= NULL
&& ops
->sa_legacy_format
!= NULL
)
449 ret
= ops
->sa_legacy_format(group
, hier
);
454 sa_format_free(char *str
)
460 * sharectl related API functions
464 * sa_proto_get_properties(proto)
466 * Return the set of properties that are specific to the
467 * protocol. These are usually in /etc/dfs/<proto> and related files,
468 * but only the protocol module knows which ones for sure.
471 sa_protocol_properties_t
472 sa_proto_get_properties(char *proto
)
474 struct sa_plugin_ops
*ops
= find_protocol(proto
);
475 sa_protocol_properties_t props
= NULL
;
477 if (ops
!= NULL
&& ops
->sa_get_proto_set
!= NULL
)
478 props
= ops
->sa_get_proto_set();
483 * sa_proto_set_property(proto, prop)
485 * Update the protocol specific property.
489 sa_proto_set_property(char *proto
, sa_property_t prop
)
491 struct sa_plugin_ops
*ops
= find_protocol(proto
);
494 if (ops
!= NULL
&& ops
->sa_set_proto_prop
!= NULL
)
495 ret
= ops
->sa_set_proto_prop(prop
);
500 * sa_valid_protocol(proto)
502 * Check to see if the protocol specified is defined by a
503 * plugin. Returns true (1) or false (0)
507 sa_valid_protocol(char *proto
)
509 struct sa_plugin_ops
*ops
= find_protocol(proto
);
510 return (ops
!= NULL
);
514 * Return the current operational status of the protocol
518 sa_get_protocol_status(char *proto
)
520 struct sa_plugin_ops
*ops
= find_protocol(proto
);
522 if (ops
!= NULL
&& ops
->sa_get_proto_status
!= NULL
)
523 ret
= ops
->sa_get_proto_status(proto
);
528 * sa_proto_update_legacy(proto, share)
530 * Update the protocol specific legacy files if necessary for the
535 sa_proto_update_legacy(char *proto
, sa_share_t share
)
537 struct sa_plugin_ops
*ops
= find_protocol(proto
);
538 int ret
= SA_NOT_IMPLEMENTED
;
541 if (ops
->sa_update_legacy
!= NULL
)
542 ret
= ops
->sa_update_legacy(share
);
548 * sa_delete_legacy(proto, share)
550 * Remove the specified share from the protocol specific legacy files.
554 sa_proto_delete_legacy(char *proto
, sa_share_t share
)
556 struct sa_plugin_ops
*ops
= find_protocol(proto
);
557 int ret
= SA_NOT_IMPLEMENTED
;
560 if (ops
->sa_delete_legacy
!= NULL
)
561 ret
= ops
->sa_delete_legacy(share
);
564 ret
= SA_NOT_IMPLEMENTED
;
566 ret
= SA_INVALID_PROTOCOL
;
572 * sa_proto_delete_section(proto, section)
574 * Remove the specified section from the protocol specific legacy files,
579 sa_proto_delete_section(char *proto
, char *section
)
581 struct sa_plugin_ops
*ops
= find_protocol(proto
);
585 if (ops
->sa_delete_proto_section
!= NULL
)
586 ret
= ops
->sa_delete_proto_section(section
);
589 ret
= SA_NOT_IMPLEMENTED
;
591 ret
= SA_INVALID_PROTOCOL
;
597 * sa_proto_change_notify(share, char *protocol)
599 * Notify the protocol that a change has been made to the share
603 sa_proto_change_notify(sa_share_t share
, char *proto
)
605 struct sa_plugin_ops
*ops
= find_protocol(proto
);
606 int ret
= SA_NOT_IMPLEMENTED
;
609 if (ops
->sa_change_notify
!= NULL
)
610 ret
= ops
->sa_change_notify(share
);
611 } else if (proto
== NULL
) {
613 ret
= SA_INVALID_PROTOCOL
;
619 * sa_proto_notify_resource(resource, char *protocol)
621 * Notify the protocol that a change has been made to the share
625 sa_proto_notify_resource(sa_resource_t resource
, char *proto
)
627 struct sa_plugin_ops
*ops
= find_protocol(proto
);
628 int ret
= SA_NOT_IMPLEMENTED
;
631 if (ops
->sa_notify_resource
!= NULL
)
632 ret
= ops
->sa_notify_resource(resource
);
633 } else if (proto
== NULL
) {
634 ret
= SA_INVALID_PROTOCOL
;
640 * sa_proto_get_featureset(protocol)
642 * Get bitmask of defined features of the protocol. These are
643 * primarily things like SA_FEATURE_RESOURCE (shares are by resource
644 * name rather than path) and other operational features that affect
649 sa_proto_get_featureset(char *proto
)
651 struct sa_plugin_ops
*ops
= find_protocol(proto
);
655 if (ops
->sa_features
!= NULL
)
656 ret
= ops
->sa_features();
658 /* if not implemented, zero is valid */
663 * sa_proto_get_transients(sa_handle_t)
665 * Called to get any protocol specific transient shares. NFS doesn't
666 * use this since the info is in sharetab which is processed as a
667 * common transient store.
669 * The protocol plugin should verify that the share isn't in the
670 * repository and then add it as a transient.
672 * Not having an entry is not a problem. It returns 0 in that case.
676 sa_proto_get_transients(sa_handle_t handle
, char *proto
)
678 struct sa_plugin_ops
*ops
= find_protocol(proto
);
682 if (ops
->sa_get_transient_shares
!= NULL
)
683 ret
= ops
->sa_get_transient_shares(handle
);
689 * sa_proto_rename_resource(sa_handle_t, proto, sa_resource_t, newname)
691 * Protocols may need to know when a resource has changed names in
692 * order to notify clients. This must be done "before" the name in the
693 * resource has been changed. Not being implemented is not a problem.
697 sa_proto_rename_resource(sa_handle_t handle
, char *proto
,
698 sa_resource_t resource
, char *newname
)
700 struct sa_plugin_ops
*ops
= find_protocol(proto
);
704 if (ops
->sa_rename_resource
!= NULL
)
705 ret
= ops
->sa_rename_resource(handle
, resource
,