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