13034Sdougm /*
23034Sdougm  * CDDL HEADER START
33034Sdougm  *
43034Sdougm  * The contents of this file are subject to the terms of the
53034Sdougm  * Common Development and Distribution License (the "License").
63034Sdougm  * You may not use this file except in compliance with the License.
73034Sdougm  *
83034Sdougm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93034Sdougm  * or http://www.opensolaris.org/os/licensing.
103034Sdougm  * See the License for the specific language governing permissions
113034Sdougm  * and limitations under the License.
123034Sdougm  *
133034Sdougm  * When distributing Covered Code, include this CDDL HEADER in each
143034Sdougm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153034Sdougm  * If applicable, add the following below this CDDL HEADER, with the
163034Sdougm  * fields enclosed by brackets "[]" replaced with your own identifying
173034Sdougm  * information: Portions Copyright [yyyy] [name of copyright owner]
183034Sdougm  *
193034Sdougm  * CDDL HEADER END
203034Sdougm  */
213034Sdougm 
223034Sdougm /*
236007Sthurlow  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
243034Sdougm  * Use is subject to license terms.
253034Sdougm  */
263034Sdougm 
273034Sdougm #pragma ident	"%Z%%M%	%I%	%E% SMI"
283034Sdougm 
293034Sdougm #include <stdio.h>
303034Sdougm #include <stdlib.h>
313034Sdougm #include <string.h>
323034Sdougm #include <libshare.h>
333034Sdougm #include "libshare_impl.h"
343034Sdougm #include <dlfcn.h>
353034Sdougm #include <link.h>
363034Sdougm #include <sys/types.h>
373034Sdougm #include <sys/param.h>
383034Sdougm #include <sys/stat.h>
393034Sdougm #include <dirent.h>
403034Sdougm #include <libintl.h>
413910Sdougm #include <sys/systeminfo.h>
426304Sdougm #include <thread.h>
436304Sdougm #include <synch.h>
443910Sdougm 
453910Sdougm #define	MAXISALEN	257	/* based on sysinfo(2) man page */
463034Sdougm 
473034Sdougm /*
483034Sdougm  * protocol plugin interface
493034Sdougm  *
503034Sdougm  * finds plugins and makes them accessible. This is only "used" by
513034Sdougm  * libshare.so.
523034Sdougm  */
533034Sdougm 
543034Sdougm struct sa_proto_plugin *sap_proto_list;
553034Sdougm 
563034Sdougm static struct sa_proto_handle sa_proto_handle;
573034Sdougm 
583034Sdougm void proto_plugin_fini();
593034Sdougm 
603034Sdougm /*
613034Sdougm  * proto_plugin_init()
623034Sdougm  *
633034Sdougm  * Initialize the protocol specific plugin modules.
643034Sdougm  *
653034Sdougm  * Walk /usr/lib/fs/\* for libshare_*.so modules. That is,
663034Sdougm  * /usr/lib/fs/nfs/libshare_nfs.so. The protocol specific directory
673034Sdougm  * would have a modules with name libshare_<proto>.so. If one is
683034Sdougm  * found, initialize it and add to the internal list of
695331Samw  * protocols. These are used for protocol specific operations.
703034Sdougm  */
713034Sdougm 
723034Sdougm int
733034Sdougm proto_plugin_init()
743034Sdougm {
753034Sdougm 	struct sa_proto_plugin *proto;
763034Sdougm 	int num_protos = 0;
773034Sdougm 	struct sa_plugin_ops *plugin_ops;
783034Sdougm 	void *dlhandle;
793034Sdougm 	DIR *dir;
803034Sdougm 	struct dirent *dent;
813034Sdougm 	int ret = SA_OK;
823034Sdougm 	struct stat st;
833034Sdougm 
843034Sdougm 	/*
854653Sdougm 	 * Should walk "/usr/lib/fs/" for files of the form:
863034Sdougm 	 * libshare_*.so
873034Sdougm 	 */
883034Sdougm 	dir = opendir(SA_LIB_DIR);
893034Sdougm 	if (dir != NULL) {
904653Sdougm 		while (ret == SA_OK && (dent = readdir(dir)) != NULL) {
914653Sdougm 			char path[MAXPATHLEN];
924653Sdougm 			char isa[MAXISALEN];
933910Sdougm 
943910Sdougm #if defined(_LP64)
954653Sdougm 			if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1)
964653Sdougm 				isa[0] = '\0';
973910Sdougm #else
984653Sdougm 			isa[0] = '\0';
993910Sdougm #endif
1004653Sdougm 			(void) snprintf(path, MAXPATHLEN,
1014653Sdougm 			    "%s/%s/%s/libshare_%s.so.1", SA_LIB_DIR,
1024653Sdougm 			    dent->d_name, isa, dent->d_name);
1034653Sdougm 			/*
1044653Sdougm 			 * If file doesn't exist, don't try to map it
1054653Sdougm 			 */
1064653Sdougm 			if (stat(path, &st) < 0)
1074653Sdougm 				continue;
1084653Sdougm 
1094653Sdougm 			dlhandle = dlopen(path, RTLD_FIRST|RTLD_LAZY);
1104653Sdougm 			if (dlhandle != NULL) {
1114653Sdougm 				plugin_ops = (struct sa_plugin_ops *)
1124653Sdougm 				    dlsym(dlhandle, "sa_plugin_ops");
1134653Sdougm 				proto = (struct sa_proto_plugin *)
1144653Sdougm 				    calloc(1, sizeof (struct sa_proto_plugin));
1154653Sdougm 				if (proto != NULL) {
1164653Sdougm 					proto->plugin_ops = plugin_ops;
1174653Sdougm 					proto->plugin_handle = dlhandle;
1184653Sdougm 					num_protos++;
1194653Sdougm 					proto->plugin_next = sap_proto_list;
1204653Sdougm 					sap_proto_list = proto;
1214653Sdougm 				} else {
1224653Sdougm 					ret = SA_NO_MEMORY;
1236304Sdougm 					/* Don't leak a dlhandle */
1246304Sdougm 					(void) dlclose(dlhandle);
1256304Sdougm 					break;
1264653Sdougm 				}
1274653Sdougm 			} else {
1284653Sdougm 				(void) fprintf(stderr,
1294653Sdougm 				    dgettext(TEXT_DOMAIN,
1304653Sdougm 				    "Error in plugin for protocol %s: %s\n"),
1314653Sdougm 				    dent->d_name, dlerror());
1324653Sdougm 			}
1333034Sdougm 		}
1344653Sdougm 		(void) closedir(dir);
1353034Sdougm 	}
1363034Sdougm 	if (ret == SA_OK) {
1374653Sdougm 		sa_proto_handle.sa_proto =
1384653Sdougm 		    (char **)calloc(num_protos, sizeof (char *));
1394653Sdougm 		sa_proto_handle.sa_ops =
1404653Sdougm 		    (struct sa_plugin_ops **)calloc(num_protos,
1414653Sdougm 		    sizeof (struct sa_plugin_ops *));
1424653Sdougm 		if (sa_proto_handle.sa_proto != NULL &&
1434653Sdougm 		    sa_proto_handle.sa_ops != NULL) {
1444653Sdougm 			int i;
1454653Sdougm 			struct sa_proto_plugin *tmp;
1464653Sdougm 
1474653Sdougm 			for (i = 0, tmp = sap_proto_list;
1486162Sdougm 			    i < num_protos && tmp != NULL;
1494653Sdougm 			    tmp = tmp->plugin_next) {
1506304Sdougm 				int err;
1516304Sdougm 				err = SA_OK;
1524653Sdougm 				if (tmp->plugin_ops->sa_init != NULL)
1534653Sdougm 					err = tmp->plugin_ops->sa_init();
1544653Sdougm 				if (err == SA_OK) {
1554653Sdougm 					/*
1564653Sdougm 					 * Only include if the init
1574653Sdougm 					 * succeeded or was NULL
1584653Sdougm 					 */
1594653Sdougm 					sa_proto_handle.sa_num_proto++;
1604653Sdougm 					sa_proto_handle.sa_ops[i] =
1614653Sdougm 					    tmp->plugin_ops;
1624653Sdougm 					sa_proto_handle.sa_proto[i] =
1634653Sdougm 					    tmp->plugin_ops->sa_protocol;
1644653Sdougm 					i++;
1654653Sdougm 				}
1664653Sdougm 			}
1676304Sdougm 		} else {
1686304Sdougm 			ret = SA_NO_MEMORY;
1693034Sdougm 		}
1706304Sdougm 	}
1716304Sdougm 
1726304Sdougm 	/*
1736304Sdougm 	 * There was an error, so cleanup prior to return of failure.
1746304Sdougm 	 */
1756304Sdougm 	if (ret != SA_OK)
1764653Sdougm 		proto_plugin_fini();
1776304Sdougm 
1783034Sdougm 	return (ret);
1793034Sdougm }
1803034Sdougm 
1813034Sdougm /*
1823034Sdougm  * proto_plugin_fini()
1833034Sdougm  *
1844653Sdougm  * Uninitialize all the plugin modules.
1853034Sdougm  */
1863034Sdougm 
1873034Sdougm void
1883034Sdougm proto_plugin_fini()
1893034Sdougm {
190*7010Sgwr 	struct sa_proto_plugin *p;
1914653Sdougm 
192*7010Sgwr 	/*
193*7010Sgwr 	 * Protocols may call this framework during _fini
194*7010Sgwr 	 * (the smbfs plugin is known to do this) so do
195*7010Sgwr 	 * two passes: 1st call _fini; 2nd free, dlclose.
196*7010Sgwr 	 */
197*7010Sgwr 	for (p = sap_proto_list; p != NULL; p = p->plugin_next)
198*7010Sgwr 		p->plugin_ops->sa_fini();
199*7010Sgwr 
200*7010Sgwr 	while ((p = sap_proto_list) != NULL) {
201*7010Sgwr 		sap_proto_list = p->plugin_next;
202*7010Sgwr 
203*7010Sgwr 		if (p->plugin_handle != NULL)
204*7010Sgwr 			(void) dlclose(p->plugin_handle);
205*7010Sgwr 		free(p);
2063034Sdougm 	}
2073034Sdougm 	if (sa_proto_handle.sa_ops != NULL) {
2084653Sdougm 		free(sa_proto_handle.sa_ops);
2094653Sdougm 		sa_proto_handle.sa_ops = NULL;
2103034Sdougm 	}
2113034Sdougm 	if (sa_proto_handle.sa_proto != NULL) {
2124653Sdougm 		free(sa_proto_handle.sa_proto);
2134653Sdougm 		sa_proto_handle.sa_proto = NULL;
2143034Sdougm 	}
2153034Sdougm 	sa_proto_handle.sa_num_proto = 0;
2163034Sdougm }
2173034Sdougm 
2183034Sdougm /*
2193034Sdougm  * find_protocol(proto)
2203034Sdougm  *
2213034Sdougm  * Search the plugin list for the specified protocol and return the
2223034Sdougm  * ops vector.  NULL if protocol is not defined.
2233034Sdougm  */
2243034Sdougm 
2253034Sdougm static struct sa_plugin_ops *
2263034Sdougm find_protocol(char *proto)
2273034Sdougm {
2283034Sdougm 	int i;
2296304Sdougm 	struct sa_plugin_ops *ops = NULL;
2306304Sdougm 	extern mutex_t sa_global_lock;
2313034Sdougm 
2326304Sdougm 	(void) mutex_lock(&sa_global_lock);
2333034Sdougm 	if (proto != NULL) {
2344653Sdougm 		for (i = 0; i < sa_proto_handle.sa_num_proto; i++) {
2356304Sdougm 			if (strcmp(proto, sa_proto_handle.sa_proto[i]) == 0) {
2366304Sdougm 				ops = sa_proto_handle.sa_ops[i];
2376304Sdougm 				break;
2386304Sdougm 			}
2394653Sdougm 		}
2403034Sdougm 	}
2416304Sdougm 	(void) mutex_unlock(&sa_global_lock);
2426304Sdougm 	return (ops);
2433034Sdougm }
2443034Sdougm 
2453034Sdougm /*
2463034Sdougm  * sa_proto_share(proto, share)
2473034Sdougm  *
2483034Sdougm  * Activate a share for the specified protocol.
2493034Sdougm  */
2503034Sdougm 
2513034Sdougm int
2523034Sdougm sa_proto_share(char *proto, sa_share_t share)
2533034Sdougm {
2543034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2553034Sdougm 	int ret = SA_INVALID_PROTOCOL;
2563034Sdougm 
2573034Sdougm 	if (ops != NULL && ops->sa_share != NULL)
2584653Sdougm 		ret = ops->sa_share(share);
2593034Sdougm 	return (ret);
2603034Sdougm }
2613034Sdougm 
2623034Sdougm /*
2635331Samw  * sa_proto_unshare(proto, share)
2643034Sdougm  *
2655331Samw  * Deactivate (unshare) the share for this protocol.
2663034Sdougm  */
2673034Sdougm 
2683034Sdougm int
2694543Smarks sa_proto_unshare(sa_share_t share, char *proto, char *path)
2703034Sdougm {
2713034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
2723034Sdougm 	int ret = SA_INVALID_PROTOCOL;
2733034Sdougm 
2743034Sdougm 	if (ops != NULL && ops->sa_unshare != NULL)
2754653Sdougm 		ret = ops->sa_unshare(share, path);
2763034Sdougm 	return (ret);
2773034Sdougm }
2783034Sdougm 
2793034Sdougm /*
2805331Samw  * sa_proto_share_resource(char *proto, sa_resource_t resource)
2815331Samw  *
2825331Samw  * For protocols that actually enable at the resource level, do the
2835331Samw  * protocol specific resource enable. If it doesn't, return an error.
2845331Samw  * Note that the resource functions are optional so can return
2855331Samw  * SA_NOT_SUPPORTED.
2865331Samw  */
2875331Samw 
2885331Samw int
2895331Samw sa_proto_share_resource(char *proto, sa_resource_t resource)
2905331Samw {
2915331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
2925331Samw 	int ret = SA_INVALID_PROTOCOL;
2935331Samw 
2945331Samw 	if (ops != NULL) {
2955331Samw 		if (ops->sa_enable_resource != NULL)
2965331Samw 			ret = ops->sa_enable_resource(resource);
2975331Samw 		else
2985331Samw 			ret = SA_NOT_SUPPORTED;
2995331Samw 	}
3005331Samw 	return (ret);
3015331Samw }
3025331Samw 
3035331Samw /*
3045331Samw  * sa_proto_unshare_resource(char *proto, sa_resource_t resource)
3055331Samw  *
3065331Samw  * For protocols that actually disable at the resource level, do the
3075331Samw  * protocol specific resource disable. If it doesn't, return an error.
3085331Samw  */
3095331Samw 
3105331Samw int
3115331Samw sa_proto_unshare_resource(char *proto, sa_resource_t resource)
3125331Samw {
3135331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
3145331Samw 	int ret = SA_INVALID_PROTOCOL;
3155331Samw 
3165331Samw 	if (ops != NULL) {
3175331Samw 		if (ops->sa_disable_resource != NULL)
3185331Samw 			ret = ops->sa_disable_resource(resource);
3195331Samw 		else
3205331Samw 			ret = SA_NOT_SUPPORTED;
3215331Samw 	}
3225331Samw 	return (ret);
3235331Samw }
3245331Samw 
3255331Samw /*
3266214Sdougm  * sa_proto_valid_prop(handle, proto, prop, opt)
3273034Sdougm  *
3284653Sdougm  * Check to see if the specified prop is valid for this protocol.
3293034Sdougm  */
3303034Sdougm 
3313034Sdougm int
3326214Sdougm sa_proto_valid_prop(sa_handle_t handle, char *proto, sa_property_t prop,
3336214Sdougm     sa_optionset_t opt)
3343034Sdougm {
3353034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3363034Sdougm 	int ret = 0;
3373034Sdougm 
3383034Sdougm 	if (ops != NULL && ops->sa_valid_prop != NULL)
3396214Sdougm 		ret = ops->sa_valid_prop(handle, prop, opt);
3403034Sdougm 	return (ret);
3413034Sdougm }
3423034Sdougm 
3433034Sdougm /*
3443034Sdougm  * sa_proto_valid_space(proto, space)
3453034Sdougm  *
3464653Sdougm  * Check if space is valid optionspace for proto.
3473034Sdougm  * Protocols that don't implement this don't support spaces.
3483034Sdougm  */
3493034Sdougm int
3503034Sdougm sa_proto_valid_space(char *proto, char *token)
3513034Sdougm {
3523034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3533034Sdougm 	int ret = 0;
3543034Sdougm 
3553034Sdougm 	if (ops != NULL && ops->sa_valid_space != NULL)
3564653Sdougm 		ret = ops->sa_valid_space(token);
3573034Sdougm 	return (ret);
3583034Sdougm }
3593034Sdougm 
3603034Sdougm /*
3613034Sdougm  * sa_proto_space_alias(proto, space)
3623034Sdougm  *
3634653Sdougm  * If the name for space is an alias, return its proper name.  This is
3643034Sdougm  * used to translate "default" values into proper form.
3653034Sdougm  */
3663034Sdougm char *
3673034Sdougm sa_proto_space_alias(char *proto, char *space)
3683034Sdougm {
3693034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3703034Sdougm 	char *ret = space;
3713034Sdougm 
3723034Sdougm 	if (ops != NULL && ops->sa_space_alias != NULL)
3734653Sdougm 		ret = ops->sa_space_alias(space);
3743034Sdougm 	return (ret);
3753034Sdougm }
3763034Sdougm 
3773034Sdougm /*
3783034Sdougm  * sa_proto_security_prop(proto, token)
3793034Sdougm  *
3803034Sdougm  * Check to see if the property name in token is a valid named
3813034Sdougm  * optionset property.
3823034Sdougm  */
3833034Sdougm 
3843034Sdougm int
3853034Sdougm sa_proto_security_prop(char *proto, char *token)
3863034Sdougm {
3873034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
3883034Sdougm 	int ret = 0;
3893034Sdougm 
3903034Sdougm 	if (ops != NULL && ops->sa_security_prop != NULL)
3914653Sdougm 		ret = ops->sa_security_prop(token);
3923034Sdougm 	return (ret);
3933034Sdougm }
3943034Sdougm 
3953034Sdougm /*
3963034Sdougm  * sa_proto_legacy_opts(proto, grouup, options)
3973034Sdougm  *
3983034Sdougm  * Have the protocol specific parser parse the options string and add
3993034Sdougm  * an appropriate optionset to group.
4003034Sdougm  */
4013034Sdougm 
4023034Sdougm int
4033034Sdougm sa_proto_legacy_opts(char *proto, sa_group_t group, char *options)
4043034Sdougm {
4053034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4063034Sdougm 	int ret = SA_INVALID_PROTOCOL;
4073034Sdougm 
4083034Sdougm 	if (ops != NULL && ops->sa_legacy_opts != NULL)
4094653Sdougm 		ret = ops->sa_legacy_opts(group, options);
4103034Sdougm 	return (ret);
4113034Sdougm }
4123034Sdougm 
4133034Sdougm /*
4143034Sdougm  * sa_proto_legacy_format(proto, group, hier)
4153034Sdougm  *
4163034Sdougm  * Return a legacy format string representing either the group's
4173034Sdougm  * properties or the groups hierarchical properties.
4183034Sdougm  */
4193034Sdougm 
4203034Sdougm char *
4213034Sdougm sa_proto_legacy_format(char *proto, sa_group_t group, int hier)
4223034Sdougm {
4233034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4243034Sdougm 	char *ret = NULL;
4253034Sdougm 
4263034Sdougm 	if (ops != NULL && ops->sa_legacy_format != NULL)
4274653Sdougm 		ret = ops->sa_legacy_format(group, hier);
4283034Sdougm 	return (ret);
4293034Sdougm }
4303034Sdougm 
4313034Sdougm void
4323034Sdougm sa_format_free(char *str)
4333034Sdougm {
4343034Sdougm 	free(str);
4353034Sdougm }
4363034Sdougm 
4373034Sdougm /*
4383034Sdougm  * sharectl related API functions
4393034Sdougm  */
4403034Sdougm 
4413034Sdougm /*
4423034Sdougm  * sa_proto_get_properties(proto)
4433034Sdougm  *
4443034Sdougm  * Return the set of properties that are specific to the
4453034Sdougm  * protocol. These are usually in /etc/dfs/<proto> and related files,
4463034Sdougm  * but only the protocol module knows which ones for sure.
4473034Sdougm  */
4483034Sdougm 
4493034Sdougm sa_protocol_properties_t
4503034Sdougm sa_proto_get_properties(char *proto)
4513034Sdougm {
4523034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4533034Sdougm 	sa_protocol_properties_t props = NULL;
4543034Sdougm 
4553034Sdougm 	if (ops != NULL && ops->sa_get_proto_set != NULL)
4564653Sdougm 		props = ops->sa_get_proto_set();
4573034Sdougm 	return (props);
4583034Sdougm }
4593034Sdougm 
4603034Sdougm /*
4613034Sdougm  * sa_proto_set_property(proto, prop)
4623034Sdougm  *
4635331Samw  * Update the protocol specific property.
4643034Sdougm  */
4653034Sdougm 
4663034Sdougm int
4673034Sdougm sa_proto_set_property(char *proto, sa_property_t prop)
4683034Sdougm {
4693034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4703034Sdougm 	int ret = SA_OK;
4714653Sdougm 
4723034Sdougm 	if (ops != NULL && ops->sa_set_proto_prop != NULL)
4734653Sdougm 		ret = ops->sa_set_proto_prop(prop);
4743034Sdougm 	return (ret);
4753034Sdougm }
4763034Sdougm 
4773034Sdougm /*
4783034Sdougm  * sa_valid_protocol(proto)
4793034Sdougm  *
4804653Sdougm  * Check to see if the protocol specified is defined by a
4813034Sdougm  * plugin. Returns true (1) or false (0)
4823034Sdougm  */
4833034Sdougm 
4843034Sdougm int
4853034Sdougm sa_valid_protocol(char *proto)
4863034Sdougm {
4873034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4883034Sdougm 	return (ops != NULL);
4893034Sdougm }
4903034Sdougm 
4913034Sdougm /*
4923034Sdougm  * Return the current operational status of the protocol
4933034Sdougm  */
4943034Sdougm 
4953034Sdougm char *
4963034Sdougm sa_get_protocol_status(char *proto)
4973034Sdougm {
4983034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
4993034Sdougm 	char *ret = NULL;
5003034Sdougm 	if (ops != NULL && ops->sa_get_proto_status != NULL)
5014653Sdougm 		ret = ops->sa_get_proto_status(proto);
5023034Sdougm 	return (ret);
5033034Sdougm }
5043034Sdougm 
5053034Sdougm /*
5063034Sdougm  * sa_proto_update_legacy(proto, share)
5073034Sdougm  *
5083034Sdougm  * Update the protocol specific legacy files if necessary for the
5093034Sdougm  * specified share.
5103034Sdougm  */
5113034Sdougm 
5123034Sdougm int
5133034Sdougm sa_proto_update_legacy(char *proto, sa_share_t share)
5143034Sdougm {
5153034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
5163034Sdougm 	int ret = SA_NOT_IMPLEMENTED;
5173034Sdougm 
5183034Sdougm 	if (ops != NULL) {
5194653Sdougm 		if (ops->sa_update_legacy != NULL)
5204653Sdougm 			ret = ops->sa_update_legacy(share);
5213034Sdougm 	}
5223034Sdougm 	return (ret);
5233034Sdougm }
5243034Sdougm 
5253034Sdougm /*
5263034Sdougm  * sa_delete_legacy(proto, share)
5273034Sdougm  *
5284653Sdougm  * Remove the specified share from the protocol specific legacy files.
5293034Sdougm  */
5303034Sdougm 
5313034Sdougm int
5323034Sdougm sa_proto_delete_legacy(char *proto, sa_share_t share)
5333034Sdougm {
5343034Sdougm 	struct sa_plugin_ops *ops = find_protocol(proto);
5355331Samw 	int ret = SA_NOT_IMPLEMENTED;
5363034Sdougm 
5373034Sdougm 	if (ops != NULL) {
5384653Sdougm 		if (ops->sa_delete_legacy != NULL)
5394653Sdougm 			ret = ops->sa_delete_legacy(share);
5406007Sthurlow 	} else {
5416007Sthurlow 		if (proto != NULL)
5426007Sthurlow 			ret = SA_NOT_IMPLEMENTED;
5436007Sthurlow 		else
5446007Sthurlow 			ret = SA_INVALID_PROTOCOL;
5456007Sthurlow 	}
5466007Sthurlow 	return (ret);
5476007Sthurlow }
5486007Sthurlow 
5496007Sthurlow /*
5506007Sthurlow  * sa_proto_delete_section(proto, section)
5516007Sthurlow  *
5526007Sthurlow  * Remove the specified section from the protocol specific legacy files,
5536007Sthurlow  * if supported.
5546007Sthurlow  */
5556007Sthurlow 
5566007Sthurlow int
5576007Sthurlow sa_proto_delete_section(char *proto, char *section)
5586007Sthurlow {
5596007Sthurlow 	struct sa_plugin_ops *ops = find_protocol(proto);
5606007Sthurlow 	int ret = SA_OK;
5616007Sthurlow 
5626007Sthurlow 	if (ops != NULL) {
5636007Sthurlow 		if (ops->sa_delete_proto_section != NULL)
5646007Sthurlow 			ret = ops->sa_delete_proto_section(section);
5656007Sthurlow 	} else {
5666007Sthurlow 		if (proto != NULL)
5676007Sthurlow 			ret = SA_NOT_IMPLEMENTED;
5686007Sthurlow 		else
5696007Sthurlow 			ret = SA_INVALID_PROTOCOL;
5705331Samw 	}
5715331Samw 	return (ret);
5725331Samw }
5735331Samw 
5745331Samw /*
5755331Samw  * sa_proto_change_notify(share, char *protocol)
5765331Samw  *
5775331Samw  * Notify the protocol that a change has been made to the share
5785331Samw  */
5795331Samw 
5805331Samw int
5815331Samw sa_proto_change_notify(sa_share_t share, char *proto)
5825331Samw {
5835331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
5845331Samw 	int ret = SA_NOT_IMPLEMENTED;
5855331Samw 
5865331Samw 	if (ops != NULL) {
5875331Samw 		if (ops->sa_change_notify != NULL)
5885331Samw 			ret = ops->sa_change_notify(share);
5895331Samw 	} else	if (proto == NULL) {
5906007Sthurlow 
5915331Samw 			ret = SA_INVALID_PROTOCOL;
5925331Samw 	}
5935331Samw 	return (ret);
5945331Samw }
5955331Samw 
5965331Samw /*
5975331Samw  * sa_proto_notify_resource(resource, char *protocol)
5985331Samw  *
5995331Samw  * Notify the protocol that a change has been made to the share
6005331Samw  */
6015331Samw 
6025331Samw int
6035331Samw sa_proto_notify_resource(sa_resource_t resource, char *proto)
6045331Samw {
6055331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
6065331Samw 	int ret = SA_NOT_IMPLEMENTED;
6075331Samw 
6085331Samw 	if (ops != NULL) {
6095331Samw 		if (ops->sa_notify_resource != NULL)
6105331Samw 			ret = ops->sa_notify_resource(resource);
6115331Samw 	} else if (proto == NULL) {
6124653Sdougm 			ret = SA_INVALID_PROTOCOL;
6133034Sdougm 	}
6143034Sdougm 	return (ret);
6153034Sdougm }
6165331Samw 
6175331Samw /*
6185331Samw  * sa_proto_get_featureset(protocol)
6195331Samw  *
6205331Samw  * Get bitmask of defined features of the protocol. These are
6215331Samw  * primarily things like SA_FEATURE_RESOURCE (shares are by resource
6225331Samw  * name rather than path) and other operational features that affect
6235331Samw  * behavior.
6245331Samw  */
6255331Samw 
6265331Samw uint64_t
6275331Samw sa_proto_get_featureset(char *proto)
6285331Samw {
6295331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
6305331Samw 	uint64_t ret = 0;
6315331Samw 
6325331Samw 	if (ops != NULL) {
6335331Samw 		if (ops->sa_features != NULL)
6345331Samw 			ret = ops->sa_features();
6355331Samw 	}
6365331Samw 	/* if not implemented, zero is valid */
6375331Samw 	return (ret);
6385331Samw }
6395331Samw 
6405331Samw /*
6415331Samw  * sa_proto_get_transients(sa_handle_t)
6425331Samw  *
6435331Samw  * Called to get any protocol specific transient shares.  NFS doesn't
6445331Samw  * use this since the info is in sharetab which is processed as a
6455331Samw  * common transient store.
6465331Samw  *
6475331Samw  * The protocol plugin should verify that the share isn't in the
6485331Samw  * repository and then add it as a transient.
6495331Samw  *
6505331Samw  * Not having an entry is not a problem. It returns 0 in that case.
6515331Samw  */
6525331Samw 
6535331Samw int
6545331Samw sa_proto_get_transients(sa_handle_t handle, char *proto)
6555331Samw {
6565331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
6575331Samw 	int ret = 0;
6585331Samw 
6595331Samw 	if (ops != NULL) {
6605331Samw 		if (ops->sa_get_transient_shares != NULL)
6615331Samw 			ret = ops->sa_get_transient_shares(handle);
6625331Samw 	}
6635331Samw 	return (ret);
6645331Samw }
6655331Samw 
6665331Samw /*
6675331Samw  * sa_proto_rename_resource(sa_handle_t, proto, sa_resource_t, newname)
6685331Samw  *
6695331Samw  * Protocols may need to know when a resource has changed names in
6705331Samw  * order to notify clients. This must be done "before" the name in the
6715331Samw  * resource has been changed. Not being implemented is not a problem.
6725331Samw  */
6735331Samw 
6745331Samw int
6755331Samw sa_proto_rename_resource(sa_handle_t handle, char *proto,
6765331Samw     sa_resource_t resource, char *newname)
6775331Samw {
6785331Samw 	struct sa_plugin_ops *ops = find_protocol(proto);
6795331Samw 	int ret = SA_OK;
6805331Samw 
6815331Samw 	if (ops != NULL) {
6825331Samw 		if (ops->sa_rename_resource != NULL)
6835331Samw 			ret = ops->sa_rename_resource(handle, resource,
6845331Samw 			    newname);
6855331Samw 	}
6865331Samw 	return (ret);
6875331Samw }
688