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