xref: /onnv-gate/usr/src/lib/libfstyp/common/libfstyp.c (revision 2212:4d4fd25d9b6e)
1*2212Sartem /*
2*2212Sartem  * CDDL HEADER START
3*2212Sartem  *
4*2212Sartem  * The contents of this file are subject to the terms of the
5*2212Sartem  * Common Development and Distribution License (the "License").
6*2212Sartem  * You may not use this file except in compliance with the License.
7*2212Sartem  *
8*2212Sartem  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2212Sartem  * or http://www.opensolaris.org/os/licensing.
10*2212Sartem  * See the License for the specific language governing permissions
11*2212Sartem  * and limitations under the License.
12*2212Sartem  *
13*2212Sartem  * When distributing Covered Code, include this CDDL HEADER in each
14*2212Sartem  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2212Sartem  * If applicable, add the following below this CDDL HEADER, with the
16*2212Sartem  * fields enclosed by brackets "[]" replaced with your own identifying
17*2212Sartem  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2212Sartem  *
19*2212Sartem  * CDDL HEADER END
20*2212Sartem  */
21*2212Sartem /*
22*2212Sartem  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*2212Sartem  * Use is subject to license terms.
24*2212Sartem  */
25*2212Sartem 
26*2212Sartem #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*2212Sartem 
28*2212Sartem #include <stdio.h>
29*2212Sartem #include <stdlib.h>
30*2212Sartem #include <libintl.h>
31*2212Sartem #include <errno.h>
32*2212Sartem #include <strings.h>
33*2212Sartem #include <unistd.h>
34*2212Sartem #include <sys/types.h>
35*2212Sartem #include <sys/stat.h>
36*2212Sartem #include <sys/param.h>
37*2212Sartem #include <sys/fstyp.h>
38*2212Sartem #include <fcntl.h>
39*2212Sartem #include <errno.h>
40*2212Sartem #include <dirent.h>
41*2212Sartem #include <dlfcn.h>
42*2212Sartem #include <link.h>
43*2212Sartem #include <libnvpair.h>
44*2212Sartem #include <libfstyp.h>
45*2212Sartem #include <libfstyp_module.h>
46*2212Sartem 
47*2212Sartem /* default module directory */
48*2212Sartem const char *default_libfs_dir = "/usr/lib/fs";
49*2212Sartem 
50*2212Sartem #define	FSTYP_VERSION	1
51*2212Sartem 
52*2212Sartem #ifndef	TEXT_DOMAIN
53*2212Sartem #define	TEXT_DOMAIN	"SYS_TEST"
54*2212Sartem #endif
55*2212Sartem 
56*2212Sartem typedef struct fstyp_ops {
57*2212Sartem 	int		(*fstyp_init)(int fd, off64_t offset,
58*2212Sartem 			fstyp_mod_handle_t *handle);
59*2212Sartem 	void		(*fstyp_fini)(fstyp_mod_handle_t handle);
60*2212Sartem 	int		(*fstyp_ident)(fstyp_mod_handle_t handle);
61*2212Sartem 	int		(*fstyp_get_attr)(fstyp_mod_handle_t handle,
62*2212Sartem 			nvlist_t **attr);
63*2212Sartem 	int		(*fstyp_dump)(fstyp_mod_handle_t handle,
64*2212Sartem 			FILE *fout, FILE *ferr);
65*2212Sartem } fstyp_ops_t;
66*2212Sartem 
67*2212Sartem typedef struct fstyp_module {
68*2212Sartem 	struct fstyp_module *next;
69*2212Sartem 	char		fsname[FSTYPSZ + 1];
70*2212Sartem 	char		*pathname;	/* absolute module pathname */
71*2212Sartem 	void		*dl_handle;	/* can be NULL if not loaded */
72*2212Sartem 	fstyp_ops_t	ops;
73*2212Sartem 	fstyp_mod_handle_t mod_handle;
74*2212Sartem } fstyp_module_t;
75*2212Sartem 
76*2212Sartem struct fstyp_handle {
77*2212Sartem 	char		*libfs_dir;	/* directory to look for modules */
78*2212Sartem 	char		*module_dir;	/* specific module directory */
79*2212Sartem 	fstyp_module_t	*modules;	/* list of modules */
80*2212Sartem 	fstyp_module_t	*modules_tail;	/* last module in the list */
81*2212Sartem 	fstyp_module_t	*ident;		/* identified module */
82*2212Sartem 	int		fd;
83*2212Sartem 	off64_t		offset;
84*2212Sartem 	long		name_max;
85*2212Sartem };
86*2212Sartem 
87*2212Sartem #define	NELEM(a)	sizeof (a) / sizeof (*(a))
88*2212Sartem 
89*2212Sartem /* local functions */
90*2212Sartem static int	fstyp_ident_all(struct fstyp_handle *h, const char **ident);
91*2212Sartem static int	fstyp_ident_one(struct fstyp_handle *h, const char *fsname,
92*2212Sartem 		const char **ident);
93*2212Sartem static fstyp_module_t *fstyp_find_module_by_name(struct fstyp_handle *h,
94*2212Sartem 		const char *fsname);
95*2212Sartem static int	fstyp_init_module(struct fstyp_handle *h,
96*2212Sartem 		char *mdir, char *fsname, fstyp_module_t **mpp);
97*2212Sartem static void	fstyp_fini_module(struct fstyp_handle *h,
98*2212Sartem 		fstyp_module_t *mp);
99*2212Sartem static int	fstyp_init_all_modules(struct fstyp_handle *h);
100*2212Sartem static void	fstyp_fini_all_modules(struct fstyp_handle *h);
101*2212Sartem static int	fstyp_load_module(struct fstyp_handle *h,
102*2212Sartem 		fstyp_module_t *mp);
103*2212Sartem static void	fstyp_unload_module(struct fstyp_handle *h,
104*2212Sartem 		fstyp_module_t *);
105*2212Sartem 
106*2212Sartem /*
107*2212Sartem  * Locate and initialize all modules.
108*2212Sartem  * If 'module_dir' is specified, only initialize module from this dir.
109*2212Sartem  */
110*2212Sartem int
fstyp_init(int fd,off64_t offset,char * module_dir,fstyp_handle_t * handle)111*2212Sartem fstyp_init(int fd, off64_t offset, char *module_dir, fstyp_handle_t *handle)
112*2212Sartem {
113*2212Sartem 	struct fstyp_handle *h;
114*2212Sartem 	int		error;
115*2212Sartem 
116*2212Sartem 	if ((h = calloc(1, sizeof (struct fstyp_handle))) == NULL) {
117*2212Sartem 		return (FSTYP_ERR_NOMEM);
118*2212Sartem 	}
119*2212Sartem 	if ((module_dir != NULL) &&
120*2212Sartem 	    ((h->module_dir = strdup(module_dir)) == NULL)) {
121*2212Sartem 		free(h);
122*2212Sartem 		return (FSTYP_ERR_NOMEM);
123*2212Sartem 	}
124*2212Sartem 
125*2212Sartem 	h->fd = fd;
126*2212Sartem 	h->offset = offset;
127*2212Sartem 	h->libfs_dir = (char *)default_libfs_dir;
128*2212Sartem 
129*2212Sartem 	if ((h->name_max = pathconf(h->libfs_dir, _PC_NAME_MAX)) < 0) {
130*2212Sartem 		h->name_max = MAXNAMELEN;
131*2212Sartem 	}
132*2212Sartem 	h->name_max++;
133*2212Sartem 
134*2212Sartem 	if (h->module_dir == NULL) {
135*2212Sartem 		error = fstyp_init_all_modules(h);
136*2212Sartem 	} else {
137*2212Sartem 		error = fstyp_init_module(h, h->module_dir, "", NULL);
138*2212Sartem 	}
139*2212Sartem 	if (error != 0) {
140*2212Sartem 		fstyp_fini(h);
141*2212Sartem 		return (error);
142*2212Sartem 	}
143*2212Sartem 
144*2212Sartem 	*handle = h;
145*2212Sartem 	return (0);
146*2212Sartem }
147*2212Sartem 
148*2212Sartem void
fstyp_fini(struct fstyp_handle * h)149*2212Sartem fstyp_fini(struct fstyp_handle *h)
150*2212Sartem {
151*2212Sartem 	if (h != NULL) {
152*2212Sartem 		fstyp_fini_all_modules(h);
153*2212Sartem 		if (h->module_dir != NULL) {
154*2212Sartem 			free(h->module_dir);
155*2212Sartem 		}
156*2212Sartem 		free(h);
157*2212Sartem 	}
158*2212Sartem }
159*2212Sartem 
160*2212Sartem /*
161*2212Sartem  * Identify the filesystem, return result in 'ident'.
162*2212Sartem  * If 'fsname' is specified, only attempt that filesystem.
163*2212Sartem  */
164*2212Sartem int
fstyp_ident(struct fstyp_handle * h,const char * fsname,const char ** ident)165*2212Sartem fstyp_ident(struct fstyp_handle *h, const char *fsname, const char **ident)
166*2212Sartem {
167*2212Sartem 	if (fsname == NULL) {
168*2212Sartem 		return (fstyp_ident_all(h, ident));
169*2212Sartem 	} else {
170*2212Sartem 		return (fstyp_ident_one(h, fsname, ident));
171*2212Sartem 	}
172*2212Sartem }
173*2212Sartem 
174*2212Sartem /*
175*2212Sartem  * use all modules for identification
176*2212Sartem  */
177*2212Sartem static int
fstyp_ident_all(struct fstyp_handle * h,const char ** ident)178*2212Sartem fstyp_ident_all(struct fstyp_handle *h, const char **ident)
179*2212Sartem {
180*2212Sartem 	fstyp_module_t	*mp;
181*2212Sartem 
182*2212Sartem 	if (h->ident != NULL) {
183*2212Sartem 		*ident = &h->ident->fsname[0];
184*2212Sartem 		return (0);
185*2212Sartem 	}
186*2212Sartem 
187*2212Sartem 	for (mp = h->modules; mp != NULL; mp = mp->next) {
188*2212Sartem 		if ((fstyp_load_module(h, mp) == 0) &&
189*2212Sartem 		    (mp->ops.fstyp_ident(mp->mod_handle) == 0)) {
190*2212Sartem 			if (h->ident != NULL) {
191*2212Sartem 				h->ident = NULL;
192*2212Sartem 				*ident = NULL;
193*2212Sartem 				return (FSTYP_ERR_MULT_MATCH);
194*2212Sartem 			} else {
195*2212Sartem 				h->ident = mp;
196*2212Sartem 				*ident = &mp->fsname[0];
197*2212Sartem 				return (0);
198*2212Sartem 			}
199*2212Sartem 		}
200*2212Sartem 	}
201*2212Sartem 	return (FSTYP_ERR_NO_MATCH);
202*2212Sartem }
203*2212Sartem 
204*2212Sartem /*
205*2212Sartem  * use only the specified module for identification
206*2212Sartem  */
207*2212Sartem static int
fstyp_ident_one(struct fstyp_handle * h,const char * fsname,const char ** ident)208*2212Sartem fstyp_ident_one(struct fstyp_handle *h, const char *fsname, const char **ident)
209*2212Sartem {
210*2212Sartem 	fstyp_module_t	*mp;
211*2212Sartem 	int		error = FSTYP_ERR_NO_MATCH;
212*2212Sartem 
213*2212Sartem 	if (h->ident != NULL) {
214*2212Sartem 		if (strcmp(h->ident->fsname, fsname) == 0) {
215*2212Sartem 			*ident = (char *)fsname;
216*2212Sartem 			return (0);
217*2212Sartem 		} else {
218*2212Sartem 			return (FSTYP_ERR_NO_MATCH);
219*2212Sartem 		}
220*2212Sartem 	}
221*2212Sartem 
222*2212Sartem 	if (strlen(fsname) > FSTYPSZ) {
223*2212Sartem 		return (FSTYP_ERR_NAME_TOO_LONG);
224*2212Sartem 	}
225*2212Sartem 	if (h->module_dir == NULL) {
226*2212Sartem 		mp = fstyp_find_module_by_name(h, fsname);
227*2212Sartem 	} else {
228*2212Sartem 		mp = h->modules;
229*2212Sartem 	}
230*2212Sartem 	if (mp == NULL) {
231*2212Sartem 		return (FSTYP_ERR_MOD_NOT_FOUND);
232*2212Sartem 	}
233*2212Sartem 
234*2212Sartem 	if (((error = fstyp_load_module(h, mp)) == 0) &&
235*2212Sartem 	    ((error = mp->ops.fstyp_ident(mp->mod_handle)) == 0)) {
236*2212Sartem 		h->ident = mp;
237*2212Sartem 		*ident = (char *)fsname;
238*2212Sartem 		return (0);
239*2212Sartem 	}
240*2212Sartem 	return (error);
241*2212Sartem }
242*2212Sartem 
243*2212Sartem /*
244*2212Sartem  * Get the list of fs attributes.
245*2212Sartem  */
246*2212Sartem int
fstyp_get_attr(struct fstyp_handle * h,nvlist_t ** attr)247*2212Sartem fstyp_get_attr(struct fstyp_handle *h, nvlist_t **attr)
248*2212Sartem {
249*2212Sartem 	fstyp_module_t	*mp = h->ident;
250*2212Sartem 
251*2212Sartem 	if (mp == NULL) {
252*2212Sartem 		return (FSTYP_ERR_NO_MATCH);
253*2212Sartem 	}
254*2212Sartem 
255*2212Sartem 	return (mp->ops.fstyp_get_attr(mp->mod_handle, attr));
256*2212Sartem }
257*2212Sartem 
258*2212Sartem /*
259*2212Sartem  * Dump free-form filesystem information.
260*2212Sartem  */
261*2212Sartem int
fstyp_dump(struct fstyp_handle * h,FILE * fout,FILE * ferr)262*2212Sartem fstyp_dump(struct fstyp_handle *h, FILE *fout, FILE *ferr)
263*2212Sartem {
264*2212Sartem 	fstyp_module_t	*mp = h->ident;
265*2212Sartem 
266*2212Sartem 	if (mp == NULL) {
267*2212Sartem 		return (FSTYP_ERR_NO_MATCH);
268*2212Sartem 	}
269*2212Sartem 
270*2212Sartem 	if (mp->ops.fstyp_dump == NULL) {
271*2212Sartem 		return (FSTYP_ERR_NOP);
272*2212Sartem 	}
273*2212Sartem 
274*2212Sartem 	return (mp->ops.fstyp_dump(mp->mod_handle, fout, ferr));
275*2212Sartem }
276*2212Sartem 
277*2212Sartem /* ARGSUSED */
278*2212Sartem const char *
fstyp_strerror(struct fstyp_handle * h,int error)279*2212Sartem fstyp_strerror(struct fstyp_handle *h, int error)
280*2212Sartem {
281*2212Sartem 	char *str;
282*2212Sartem 
283*2212Sartem 	switch (error) {
284*2212Sartem 	case FSTYP_ERR_OK:
285*2212Sartem 		str = dgettext(TEXT_DOMAIN, "success");
286*2212Sartem 		break;
287*2212Sartem 	case FSTYP_ERR_NO_MATCH:
288*2212Sartem 		str = dgettext(TEXT_DOMAIN, "no matches");
289*2212Sartem 		break;
290*2212Sartem 	case FSTYP_ERR_MULT_MATCH:
291*2212Sartem 		str = dgettext(TEXT_DOMAIN, "multiple matches");
292*2212Sartem 		break;
293*2212Sartem 	case FSTYP_ERR_HANDLE:
294*2212Sartem 		str = dgettext(TEXT_DOMAIN, "invalid handle");
295*2212Sartem 		break;
296*2212Sartem 	case FSTYP_ERR_OFFSET:
297*2212Sartem 		str = dgettext(TEXT_DOMAIN, "invalid or unsupported offset");
298*2212Sartem 		break;
299*2212Sartem 	case FSTYP_ERR_NO_PARTITION:
300*2212Sartem 		str = dgettext(TEXT_DOMAIN, "partition not found");
301*2212Sartem 		break;
302*2212Sartem 	case FSTYP_ERR_NOP:
303*2212Sartem 		str = dgettext(TEXT_DOMAIN, "no such operation");
304*2212Sartem 		break;
305*2212Sartem 	case FSTYP_ERR_DEV_OPEN:
306*2212Sartem 		str = dgettext(TEXT_DOMAIN, "cannot open device");
307*2212Sartem 		break;
308*2212Sartem 	case FSTYP_ERR_IO:
309*2212Sartem 		str = dgettext(TEXT_DOMAIN, "i/o error");
310*2212Sartem 		break;
311*2212Sartem 	case FSTYP_ERR_NOMEM:
312*2212Sartem 		str = dgettext(TEXT_DOMAIN, "out of memory");
313*2212Sartem 		break;
314*2212Sartem 	case FSTYP_ERR_MOD_NOT_FOUND:
315*2212Sartem 		str = dgettext(TEXT_DOMAIN, "module not found");
316*2212Sartem 		break;
317*2212Sartem 	case FSTYP_ERR_MOD_DIR_OPEN:
318*2212Sartem 		str = dgettext(TEXT_DOMAIN, "cannot open module directory");
319*2212Sartem 		break;
320*2212Sartem 	case FSTYP_ERR_MOD_OPEN:
321*2212Sartem 		str = dgettext(TEXT_DOMAIN, "cannot open module");
322*2212Sartem 		break;
323*2212Sartem 	case FSTYP_ERR_MOD_VERSION:
324*2212Sartem 		str = dgettext(TEXT_DOMAIN, "invalid module version");
325*2212Sartem 		break;
326*2212Sartem 	case FSTYP_ERR_MOD_INVALID:
327*2212Sartem 		str = dgettext(TEXT_DOMAIN, "invalid module");
328*2212Sartem 		break;
329*2212Sartem 	case FSTYP_ERR_NAME_TOO_LONG:
330*2212Sartem 		str = dgettext(TEXT_DOMAIN, "filesystem name too long");
331*2212Sartem 		break;
332*2212Sartem 	default:
333*2212Sartem 		str = dgettext(TEXT_DOMAIN, "undefined error");
334*2212Sartem 		break;
335*2212Sartem 	}
336*2212Sartem 
337*2212Sartem 	return (str);
338*2212Sartem }
339*2212Sartem 
340*2212Sartem 
341*2212Sartem static fstyp_module_t *
fstyp_find_module_by_name(struct fstyp_handle * h,const char * fsname)342*2212Sartem fstyp_find_module_by_name(struct fstyp_handle *h, const char *fsname)
343*2212Sartem {
344*2212Sartem 	fstyp_module_t	*mp;
345*2212Sartem 
346*2212Sartem 	for (mp = h->modules; mp != NULL; mp = mp->next) {
347*2212Sartem 		if (strcmp(mp->fsname, fsname) == 0) {
348*2212Sartem 			return (mp);
349*2212Sartem 		}
350*2212Sartem 	}
351*2212Sartem 	return (NULL);
352*2212Sartem }
353*2212Sartem 
354*2212Sartem /*
355*2212Sartem  * Allocate and initialize module structure. Do not load just yet.
356*2212Sartem  * A pointer to the existing module is returned, if such is found.
357*2212Sartem  */
358*2212Sartem static int
fstyp_init_module(struct fstyp_handle * h,char * mdir,char * fsname,fstyp_module_t ** mpp)359*2212Sartem fstyp_init_module(struct fstyp_handle *h, char *mdir, char *fsname,
360*2212Sartem     fstyp_module_t **mpp)
361*2212Sartem {
362*2212Sartem 	char		*pathname;
363*2212Sartem 	struct stat	sb;
364*2212Sartem 	fstyp_module_t	*mp;
365*2212Sartem 
366*2212Sartem 	/* if it's already inited, just return the pointer */
367*2212Sartem 	if ((mp = fstyp_find_module_by_name(h, fsname)) != NULL) {
368*2212Sartem 		if (mpp != NULL) {
369*2212Sartem 			*mpp = mp;
370*2212Sartem 		}
371*2212Sartem 		return (0);
372*2212Sartem 	}
373*2212Sartem 
374*2212Sartem 	/* allocate pathname buffer */
375*2212Sartem 	if ((pathname = calloc(1, h->name_max)) == NULL) {
376*2212Sartem 		return (FSTYP_ERR_NOMEM);
377*2212Sartem 	}
378*2212Sartem 
379*2212Sartem 	/* locate module */
380*2212Sartem 	(void) snprintf(pathname, h->name_max, "%s/fstyp.so.%d", mdir,
381*2212Sartem 	    FSTYP_VERSION);
382*2212Sartem 	if (stat(pathname, &sb) < 0) {
383*2212Sartem 		return (FSTYP_ERR_MOD_NOT_FOUND);
384*2212Sartem 	}
385*2212Sartem 
386*2212Sartem 	if ((mp = calloc(1, sizeof (fstyp_module_t))) == NULL) {
387*2212Sartem 		free(pathname);
388*2212Sartem 		return (FSTYP_ERR_NOMEM);
389*2212Sartem 	}
390*2212Sartem 
391*2212Sartem 	mp->pathname = pathname;
392*2212Sartem 	(void) strlcpy(mp->fsname, fsname, sizeof (mp->fsname));
393*2212Sartem 
394*2212Sartem 	/* append to list */
395*2212Sartem 	if (h->modules_tail == NULL) {
396*2212Sartem 		h->modules = h->modules_tail = mp;
397*2212Sartem 	} else {
398*2212Sartem 		h->modules_tail->next = mp;
399*2212Sartem 		h->modules_tail = mp;
400*2212Sartem 	}
401*2212Sartem 
402*2212Sartem 	if (mpp != NULL) {
403*2212Sartem 		*mpp = mp;
404*2212Sartem 	}
405*2212Sartem 	return (0);
406*2212Sartem }
407*2212Sartem 
408*2212Sartem /*
409*2212Sartem  * Free module resources. NOTE: this does not update the module list.
410*2212Sartem  */
411*2212Sartem static void
fstyp_fini_module(struct fstyp_handle * h,fstyp_module_t * mp)412*2212Sartem fstyp_fini_module(struct fstyp_handle *h, fstyp_module_t *mp)
413*2212Sartem {
414*2212Sartem 	if (h->ident == mp) {
415*2212Sartem 		h->ident = NULL;
416*2212Sartem 	}
417*2212Sartem 	fstyp_unload_module(h, mp);
418*2212Sartem 	if (mp->pathname != NULL) {
419*2212Sartem 		free(mp->pathname);
420*2212Sartem 	}
421*2212Sartem 	free(mp);
422*2212Sartem }
423*2212Sartem 
424*2212Sartem /*
425*2212Sartem  * Look for .so's and save them in the list.
426*2212Sartem  */
427*2212Sartem static int
fstyp_init_all_modules(struct fstyp_handle * h)428*2212Sartem fstyp_init_all_modules(struct fstyp_handle *h)
429*2212Sartem {
430*2212Sartem 	char		*mdir;
431*2212Sartem 	DIR		*dirp;
432*2212Sartem 	struct dirent	*dp_mem, *dp;
433*2212Sartem 
434*2212Sartem 	if ((mdir = calloc(1, h->name_max)) == NULL) {
435*2212Sartem 		return (FSTYP_ERR_NOMEM);
436*2212Sartem 	}
437*2212Sartem 	dp = dp_mem = calloc(1, sizeof (struct dirent) + h->name_max + 1);
438*2212Sartem 	if (dp == NULL) {
439*2212Sartem 		return (FSTYP_ERR_NOMEM);
440*2212Sartem 	}
441*2212Sartem 	if ((dirp = opendir(h->libfs_dir)) == NULL) {
442*2212Sartem 		free(mdir);
443*2212Sartem 		free(dp_mem);
444*2212Sartem 		return (FSTYP_ERR_MOD_DIR_OPEN);
445*2212Sartem 	}
446*2212Sartem 
447*2212Sartem 	while ((readdir_r(dirp, dp, &dp) == 0) && (dp != NULL)) {
448*2212Sartem 		if (dp->d_name[0] == '.') {
449*2212Sartem 			continue;
450*2212Sartem 		}
451*2212Sartem 		(void) snprintf(mdir, h->name_max,
452*2212Sartem 		    "%s/%s", h->libfs_dir, dp->d_name);
453*2212Sartem 		(void) fstyp_init_module(h, mdir, dp->d_name, NULL);
454*2212Sartem 	}
455*2212Sartem 
456*2212Sartem 	free(mdir);
457*2212Sartem 	free(dp_mem);
458*2212Sartem 	(void) closedir(dirp);
459*2212Sartem 	return (0);
460*2212Sartem }
461*2212Sartem 
462*2212Sartem static void
fstyp_fini_all_modules(struct fstyp_handle * h)463*2212Sartem fstyp_fini_all_modules(struct fstyp_handle *h)
464*2212Sartem {
465*2212Sartem 	fstyp_module_t	*mp, *mp_next;
466*2212Sartem 
467*2212Sartem 	for (mp = h->modules; mp != NULL; mp = mp_next) {
468*2212Sartem 		mp_next = mp->next;
469*2212Sartem 		fstyp_fini_module(h, mp);
470*2212Sartem 	}
471*2212Sartem 	h->modules = h->modules_tail = h->ident = NULL;
472*2212Sartem }
473*2212Sartem 
474*2212Sartem 
475*2212Sartem /*
476*2212Sartem  * Load the .so module.
477*2212Sartem  */
478*2212Sartem static int
fstyp_load_module(struct fstyp_handle * h,fstyp_module_t * mp)479*2212Sartem fstyp_load_module(struct fstyp_handle *h, fstyp_module_t *mp)
480*2212Sartem {
481*2212Sartem 	int	error;
482*2212Sartem 
483*2212Sartem 	if (mp->dl_handle != NULL) {
484*2212Sartem 		return (0);
485*2212Sartem 	}
486*2212Sartem 
487*2212Sartem 	if ((mp->dl_handle = dlopen(mp->pathname, RTLD_LAZY)) == NULL) {
488*2212Sartem 		return (FSTYP_ERR_MOD_OPEN);
489*2212Sartem 	}
490*2212Sartem 
491*2212Sartem 	mp->ops.fstyp_init = (int (*)(int, off64_t, fstyp_mod_handle_t *))
492*2212Sartem 	    dlsym(mp->dl_handle, "fstyp_mod_init");
493*2212Sartem 	mp->ops.fstyp_fini = (void (*)(fstyp_mod_handle_t))
494*2212Sartem 	    dlsym(mp->dl_handle, "fstyp_mod_fini");
495*2212Sartem 	mp->ops.fstyp_ident = (int (*)(fstyp_mod_handle_t))
496*2212Sartem 	    dlsym(mp->dl_handle, "fstyp_mod_ident");
497*2212Sartem 	mp->ops.fstyp_get_attr = (int (*)(fstyp_mod_handle_t, nvlist_t **))
498*2212Sartem 	    dlsym(mp->dl_handle, "fstyp_mod_get_attr");
499*2212Sartem 	mp->ops.fstyp_dump = (int (*)(fstyp_mod_handle_t, FILE *, FILE *))
500*2212Sartem 	    dlsym(mp->dl_handle, "fstyp_mod_dump");
501*2212Sartem 
502*2212Sartem 	if (((mp->ops.fstyp_init) == NULL) ||
503*2212Sartem 	    ((mp->ops.fstyp_fini) == NULL) ||
504*2212Sartem 	    ((mp->ops.fstyp_ident) == NULL) ||
505*2212Sartem 	    ((mp->ops.fstyp_get_attr) == NULL)) {
506*2212Sartem 		fstyp_unload_module(h, mp);
507*2212Sartem 		return (FSTYP_ERR_MOD_INVALID);
508*2212Sartem 	}
509*2212Sartem 
510*2212Sartem 	error = mp->ops.fstyp_init(h->fd, h->offset, &mp->mod_handle);
511*2212Sartem 	if (error != 0) {
512*2212Sartem 		fstyp_unload_module(h, mp);
513*2212Sartem 		return (error);
514*2212Sartem 	}
515*2212Sartem 
516*2212Sartem 	return (0);
517*2212Sartem }
518*2212Sartem 
519*2212Sartem /*ARGSUSED*/
520*2212Sartem static void
fstyp_unload_module(struct fstyp_handle * h,fstyp_module_t * mp)521*2212Sartem fstyp_unload_module(struct fstyp_handle *h, fstyp_module_t *mp)
522*2212Sartem {
523*2212Sartem 	if (mp->mod_handle != NULL) {
524*2212Sartem 		mp->ops.fstyp_fini(mp->mod_handle);
525*2212Sartem 		mp->mod_handle = NULL;
526*2212Sartem 	}
527*2212Sartem 	if (mp->dl_handle != NULL) {
528*2212Sartem 		(void) dlclose(mp->dl_handle);
529*2212Sartem 		mp->dl_handle = NULL;
530*2212Sartem 	}
531*2212Sartem }
532