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