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 <fcntl.h> 29*0e42dee6Sartem #include <stdio.h> 30*0e42dee6Sartem #include <stdlib.h> 31*0e42dee6Sartem #include <sys/types.h> 32*0e42dee6Sartem #include <sys/stat.h> 33*0e42dee6Sartem #include <unistd.h> 34*0e42dee6Sartem #include <libintl.h> 35*0e42dee6Sartem #include <locale.h> 36*0e42dee6Sartem #include <string.h> 37*0e42dee6Sartem #include <strings.h> 38*0e42dee6Sartem #include <errno.h> 39*0e42dee6Sartem #include <dirent.h> 40*0e42dee6Sartem #include <dlfcn.h> 41*0e42dee6Sartem #include <sys/wait.h> 42*0e42dee6Sartem #include <sys/fstyp.h> 43*0e42dee6Sartem #include <libfstyp.h> 44*0e42dee6Sartem #include <sys/dktp/fdisk.h> 45*0e42dee6Sartem #include <sys/fs/pc_label.h> 46*0e42dee6Sartem 47*0e42dee6Sartem #define FSTYP_LIBFS_DIR "/usr/lib/fs" 48*0e42dee6Sartem 49*0e42dee6Sartem static const char *getmodfsname(); 50*0e42dee6Sartem static char *getexecpathname(); 51*0e42dee6Sartem static void dump_nvlist(nvlist_t *list, int indent); 52*0e42dee6Sartem static boolean_t dos_to_dev(char *path, char **devpath, int *num); 53*0e42dee6Sartem static boolean_t find_dos_drive(int fd, int num, int *relsect, int *numsect, 54*0e42dee6Sartem int *systid); 55*0e42dee6Sartem static void run_legacy_cmds(int fd, char *device, int vflag); 56*0e42dee6Sartem static int run_cmd(char *path, char *arg0, char *arg1, char *arg2); 57*0e42dee6Sartem 58*0e42dee6Sartem 59*0e42dee6Sartem static void 60*0e42dee6Sartem usage(void) 61*0e42dee6Sartem { 62*0e42dee6Sartem (void) fprintf(stderr, gettext("Usage: fstyp [-av] <device>\n")); 63*0e42dee6Sartem exit(1); 64*0e42dee6Sartem } 65*0e42dee6Sartem 66*0e42dee6Sartem int 67*0e42dee6Sartem main(int argc, char **argv) 68*0e42dee6Sartem { 69*0e42dee6Sartem int fd = -1; 70*0e42dee6Sartem int c; 71*0e42dee6Sartem int aflag = 0; 72*0e42dee6Sartem int vflag = 0; 73*0e42dee6Sartem int indent = 0; 74*0e42dee6Sartem char *devpath; 75*0e42dee6Sartem boolean_t is_dos; 76*0e42dee6Sartem int dos_num, systid, relsect, numsect; 77*0e42dee6Sartem off_t offset = 0; 78*0e42dee6Sartem nvlist_t *attr = NULL; 79*0e42dee6Sartem fstyp_handle_t h = NULL; 80*0e42dee6Sartem const char *modfsname; 81*0e42dee6Sartem const char *fsname; 82*0e42dee6Sartem int error = FSTYP_ERR_NO_MATCH; 83*0e42dee6Sartem 84*0e42dee6Sartem (void) setlocale(LC_ALL, ""); 85*0e42dee6Sartem 86*0e42dee6Sartem #if !defined(TEXT_DOMAIN) 87*0e42dee6Sartem #define TEXT_DOMAIN "SYS_TEST" 88*0e42dee6Sartem #endif 89*0e42dee6Sartem (void) textdomain(TEXT_DOMAIN); 90*0e42dee6Sartem 91*0e42dee6Sartem while ((c = getopt(argc, argv, "av")) != -1) { 92*0e42dee6Sartem switch (c) { 93*0e42dee6Sartem case 'a': 94*0e42dee6Sartem aflag = 1; 95*0e42dee6Sartem break; 96*0e42dee6Sartem case 'v': 97*0e42dee6Sartem vflag = 1; 98*0e42dee6Sartem break; 99*0e42dee6Sartem default: 100*0e42dee6Sartem usage(); 101*0e42dee6Sartem break; 102*0e42dee6Sartem } 103*0e42dee6Sartem } 104*0e42dee6Sartem 105*0e42dee6Sartem argv += optind; 106*0e42dee6Sartem argc -= optind; 107*0e42dee6Sartem 108*0e42dee6Sartem if (argc != 1) { 109*0e42dee6Sartem usage(); 110*0e42dee6Sartem } 111*0e42dee6Sartem 112*0e42dee6Sartem modfsname = getmodfsname(); 113*0e42dee6Sartem 114*0e42dee6Sartem /* 115*0e42dee6Sartem * Open device, find partition offset if requested 116*0e42dee6Sartem */ 117*0e42dee6Sartem if (!(is_dos = dos_to_dev(argv[0], &devpath, &dos_num))) { 118*0e42dee6Sartem devpath = argv[0]; 119*0e42dee6Sartem } 120*0e42dee6Sartem if ((fd = open(devpath, O_RDONLY)) < 0) { 121*0e42dee6Sartem error = FSTYP_ERR_DEV_OPEN; 122*0e42dee6Sartem goto out; 123*0e42dee6Sartem } 124*0e42dee6Sartem if (is_dos) { 125*0e42dee6Sartem if (find_dos_drive(fd, dos_num, &relsect, &numsect, &systid)) { 126*0e42dee6Sartem offset = (off_t)relsect * 512; 127*0e42dee6Sartem } else { 128*0e42dee6Sartem error = FSTYP_ERR_NO_PARTITION; 129*0e42dee6Sartem goto out; 130*0e42dee6Sartem } 131*0e42dee6Sartem } 132*0e42dee6Sartem 133*0e42dee6Sartem /* 134*0e42dee6Sartem * Use libfstyp to identify filesystem 135*0e42dee6Sartem */ 136*0e42dee6Sartem if ((error = fstyp_init(fd, offset, NULL, &h)) != 0) { 137*0e42dee6Sartem goto out; 138*0e42dee6Sartem } 139*0e42dee6Sartem if ((error = fstyp_ident(h, modfsname, &fsname)) != 0) { 140*0e42dee6Sartem fstyp_fini(h); 141*0e42dee6Sartem h = NULL; 142*0e42dee6Sartem 143*0e42dee6Sartem run_legacy_cmds(fd, argv[0], vflag); 144*0e42dee6Sartem 145*0e42dee6Sartem goto out; 146*0e42dee6Sartem } 147*0e42dee6Sartem 148*0e42dee6Sartem (void) printf("%s\n", fsname); 149*0e42dee6Sartem 150*0e42dee6Sartem /* 151*0e42dee6Sartem * Output additional info if requested 152*0e42dee6Sartem */ 153*0e42dee6Sartem if (vflag) { 154*0e42dee6Sartem error = fstyp_dump(h, stdout, stderr); 155*0e42dee6Sartem } 156*0e42dee6Sartem if (aflag || (vflag && (error == FSTYP_ERR_NOP))) { 157*0e42dee6Sartem if ((error = fstyp_get_attr(h, &attr)) != 0) { 158*0e42dee6Sartem goto out; 159*0e42dee6Sartem } 160*0e42dee6Sartem dump_nvlist(attr, indent); 161*0e42dee6Sartem } 162*0e42dee6Sartem 163*0e42dee6Sartem out: 164*0e42dee6Sartem if (error != 0) { 165*0e42dee6Sartem (void) fprintf(stderr, gettext("unknown_fstyp (%s)\n"), 166*0e42dee6Sartem fstyp_strerror(h, error)); 167*0e42dee6Sartem } 168*0e42dee6Sartem if (h != NULL) { 169*0e42dee6Sartem fstyp_fini(h); 170*0e42dee6Sartem } 171*0e42dee6Sartem if (fd >= 0) { 172*0e42dee6Sartem (void) close(fd); 173*0e42dee6Sartem } 174*0e42dee6Sartem if (devpath != argv[0]) { 175*0e42dee6Sartem free(devpath); 176*0e42dee6Sartem } 177*0e42dee6Sartem return (error); 178*0e42dee6Sartem 179*0e42dee6Sartem } 180*0e42dee6Sartem 181*0e42dee6Sartem #define NVP(elem, type, vtype, ptype, format) { \ 182*0e42dee6Sartem vtype value; \ 183*0e42dee6Sartem \ 184*0e42dee6Sartem (void) nvpair_value_##type(elem, &value); \ 185*0e42dee6Sartem (void) printf("%*s%s: " format "\n", indent, "", \ 186*0e42dee6Sartem nvpair_name(elem), (ptype)value); \ 187*0e42dee6Sartem } 188*0e42dee6Sartem 189*0e42dee6Sartem #define NVPA(elem, type, vtype, ptype, format) { \ 190*0e42dee6Sartem uint_t i, count; \ 191*0e42dee6Sartem vtype *value; \ 192*0e42dee6Sartem \ 193*0e42dee6Sartem (void) nvpair_value_##type(elem, &value, &count); \ 194*0e42dee6Sartem for (i = 0; i < count; i++) { \ 195*0e42dee6Sartem (void) printf("%*s%s[%d]: " format "\n", indent, "", \ 196*0e42dee6Sartem nvpair_name(elem), i, (ptype)value[i]); \ 197*0e42dee6Sartem } \ 198*0e42dee6Sartem } 199*0e42dee6Sartem 200*0e42dee6Sartem static void 201*0e42dee6Sartem dump_nvlist(nvlist_t *list, int indent) 202*0e42dee6Sartem { 203*0e42dee6Sartem nvpair_t *elem = NULL; 204*0e42dee6Sartem boolean_t bool_value; 205*0e42dee6Sartem nvlist_t *nvlist_value; 206*0e42dee6Sartem nvlist_t **nvlist_array_value; 207*0e42dee6Sartem uint_t i, count; 208*0e42dee6Sartem 209*0e42dee6Sartem if (list == NULL) { 210*0e42dee6Sartem return; 211*0e42dee6Sartem } 212*0e42dee6Sartem 213*0e42dee6Sartem while ((elem = nvlist_next_nvpair(list, elem)) != NULL) { 214*0e42dee6Sartem switch (nvpair_type(elem)) { 215*0e42dee6Sartem case DATA_TYPE_BOOLEAN_VALUE: 216*0e42dee6Sartem (void) nvpair_value_boolean_value(elem, &bool_value); 217*0e42dee6Sartem (void) printf("%*s%s: %s\n", indent, "", 218*0e42dee6Sartem nvpair_name(elem), bool_value ? "true" : "false"); 219*0e42dee6Sartem break; 220*0e42dee6Sartem 221*0e42dee6Sartem case DATA_TYPE_BYTE: 222*0e42dee6Sartem NVP(elem, byte, uchar_t, int, "%u"); 223*0e42dee6Sartem break; 224*0e42dee6Sartem 225*0e42dee6Sartem case DATA_TYPE_INT8: 226*0e42dee6Sartem NVP(elem, int8, int8_t, int, "%d"); 227*0e42dee6Sartem break; 228*0e42dee6Sartem 229*0e42dee6Sartem case DATA_TYPE_UINT8: 230*0e42dee6Sartem NVP(elem, uint8, uint8_t, int, "%u"); 231*0e42dee6Sartem break; 232*0e42dee6Sartem 233*0e42dee6Sartem case DATA_TYPE_INT16: 234*0e42dee6Sartem NVP(elem, int16, int16_t, int, "%d"); 235*0e42dee6Sartem break; 236*0e42dee6Sartem 237*0e42dee6Sartem case DATA_TYPE_UINT16: 238*0e42dee6Sartem NVP(elem, uint16, uint16_t, int, "%u"); 239*0e42dee6Sartem break; 240*0e42dee6Sartem 241*0e42dee6Sartem case DATA_TYPE_INT32: 242*0e42dee6Sartem NVP(elem, int32, int32_t, long, "%ld"); 243*0e42dee6Sartem break; 244*0e42dee6Sartem 245*0e42dee6Sartem case DATA_TYPE_UINT32: 246*0e42dee6Sartem NVP(elem, uint32, uint32_t, ulong_t, "%lu"); 247*0e42dee6Sartem break; 248*0e42dee6Sartem 249*0e42dee6Sartem case DATA_TYPE_INT64: 250*0e42dee6Sartem NVP(elem, int64, int64_t, longlong_t, "%lld"); 251*0e42dee6Sartem break; 252*0e42dee6Sartem 253*0e42dee6Sartem case DATA_TYPE_UINT64: 254*0e42dee6Sartem NVP(elem, uint64, uint64_t, u_longlong_t, "%llu"); 255*0e42dee6Sartem break; 256*0e42dee6Sartem 257*0e42dee6Sartem case DATA_TYPE_STRING: 258*0e42dee6Sartem NVP(elem, string, char *, char *, "'%s'"); 259*0e42dee6Sartem break; 260*0e42dee6Sartem 261*0e42dee6Sartem case DATA_TYPE_BYTE_ARRAY: 262*0e42dee6Sartem NVPA(elem, byte_array, uchar_t, int, "%u"); 263*0e42dee6Sartem break; 264*0e42dee6Sartem 265*0e42dee6Sartem case DATA_TYPE_INT8_ARRAY: 266*0e42dee6Sartem NVPA(elem, int8_array, int8_t, int, "%d"); 267*0e42dee6Sartem break; 268*0e42dee6Sartem 269*0e42dee6Sartem case DATA_TYPE_UINT8_ARRAY: 270*0e42dee6Sartem NVPA(elem, uint8_array, uint8_t, int, "%u"); 271*0e42dee6Sartem break; 272*0e42dee6Sartem 273*0e42dee6Sartem case DATA_TYPE_INT16_ARRAY: 274*0e42dee6Sartem NVPA(elem, int16_array, int16_t, int, "%d"); 275*0e42dee6Sartem break; 276*0e42dee6Sartem 277*0e42dee6Sartem case DATA_TYPE_UINT16_ARRAY: 278*0e42dee6Sartem NVPA(elem, uint16_array, uint16_t, int, "%u"); 279*0e42dee6Sartem break; 280*0e42dee6Sartem 281*0e42dee6Sartem case DATA_TYPE_INT32_ARRAY: 282*0e42dee6Sartem NVPA(elem, int32_array, int32_t, long, "%ld"); 283*0e42dee6Sartem break; 284*0e42dee6Sartem 285*0e42dee6Sartem case DATA_TYPE_UINT32_ARRAY: 286*0e42dee6Sartem NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu"); 287*0e42dee6Sartem break; 288*0e42dee6Sartem 289*0e42dee6Sartem case DATA_TYPE_INT64_ARRAY: 290*0e42dee6Sartem NVPA(elem, int64_array, int64_t, longlong_t, "%lld"); 291*0e42dee6Sartem break; 292*0e42dee6Sartem 293*0e42dee6Sartem case DATA_TYPE_UINT64_ARRAY: 294*0e42dee6Sartem NVPA(elem, uint64_array, uint64_t, u_longlong_t, 295*0e42dee6Sartem "%llu"); 296*0e42dee6Sartem break; 297*0e42dee6Sartem 298*0e42dee6Sartem case DATA_TYPE_STRING_ARRAY: 299*0e42dee6Sartem NVPA(elem, string_array, char *, char *, "'%s'"); 300*0e42dee6Sartem break; 301*0e42dee6Sartem 302*0e42dee6Sartem case DATA_TYPE_NVLIST: 303*0e42dee6Sartem (void) nvpair_value_nvlist(elem, &nvlist_value); 304*0e42dee6Sartem (void) printf("%*s%s:\n", indent, "", 305*0e42dee6Sartem nvpair_name(elem)); 306*0e42dee6Sartem dump_nvlist(nvlist_value, indent + 4); 307*0e42dee6Sartem break; 308*0e42dee6Sartem 309*0e42dee6Sartem case DATA_TYPE_NVLIST_ARRAY: 310*0e42dee6Sartem (void) nvpair_value_nvlist_array(elem, 311*0e42dee6Sartem &nvlist_array_value, &count); 312*0e42dee6Sartem for (i = 0; i < count; i++) { 313*0e42dee6Sartem (void) printf("%*s%s[%u]:\n", indent, "", 314*0e42dee6Sartem nvpair_name(elem), i); 315*0e42dee6Sartem dump_nvlist(nvlist_array_value[i], indent + 4); 316*0e42dee6Sartem } 317*0e42dee6Sartem break; 318*0e42dee6Sartem 319*0e42dee6Sartem default: 320*0e42dee6Sartem (void) printf(gettext("bad config type %d for %s\n"), 321*0e42dee6Sartem nvpair_type(elem), nvpair_name(elem)); 322*0e42dee6Sartem } 323*0e42dee6Sartem } 324*0e42dee6Sartem } 325*0e42dee6Sartem 326*0e42dee6Sartem /* 327*0e42dee6Sartem * If the executable is a fs-specific hardlink, /usr/lib/fs/<fsname>/fstyp, 328*0e42dee6Sartem * return that fsname; otherwise return NULL. 329*0e42dee6Sartem */ 330*0e42dee6Sartem static const char * 331*0e42dee6Sartem getmodfsname() 332*0e42dee6Sartem { 333*0e42dee6Sartem static char fsname_buf[FSTYPSZ + 1]; 334*0e42dee6Sartem char *fsname = NULL; 335*0e42dee6Sartem char *path; 336*0e42dee6Sartem char *p; 337*0e42dee6Sartem int len; 338*0e42dee6Sartem 339*0e42dee6Sartem if ((path = getexecpathname()) == NULL) { 340*0e42dee6Sartem return (NULL); 341*0e42dee6Sartem } 342*0e42dee6Sartem if ((p = strrchr(path, '/')) != NULL) { 343*0e42dee6Sartem *p = '\0'; 344*0e42dee6Sartem if ((p = strrchr(path, '/')) != NULL) { 345*0e42dee6Sartem *p++ = '\0'; 346*0e42dee6Sartem len = strlen(p); 347*0e42dee6Sartem if ((strcmp(path, FSTYP_LIBFS_DIR) == 0) && 348*0e42dee6Sartem (len > 0) && (len < sizeof (fsname_buf))) { 349*0e42dee6Sartem (void) strlcpy(fsname_buf, p, 350*0e42dee6Sartem sizeof (fsname_buf)); 351*0e42dee6Sartem fsname = fsname_buf; 352*0e42dee6Sartem } 353*0e42dee6Sartem } 354*0e42dee6Sartem } 355*0e42dee6Sartem free(path); 356*0e42dee6Sartem return (fsname); 357*0e42dee6Sartem } 358*0e42dee6Sartem 359*0e42dee6Sartem /* 360*0e42dee6Sartem * Return executable's absolute pathname 361*0e42dee6Sartem */ 362*0e42dee6Sartem static char * 363*0e42dee6Sartem getexecpathname() 364*0e42dee6Sartem { 365*0e42dee6Sartem size_t size; 366*0e42dee6Sartem const char *execname; 367*0e42dee6Sartem char *cwd; 368*0e42dee6Sartem char *path; 369*0e42dee6Sartem char *rpath; 370*0e42dee6Sartem 371*0e42dee6Sartem size = pathconf(".", _PC_PATH_MAX) + 1; 372*0e42dee6Sartem path = malloc(size); 373*0e42dee6Sartem rpath = malloc(size); 374*0e42dee6Sartem cwd = getcwd(NULL, size); 375*0e42dee6Sartem if ((path == NULL) || (rpath == NULL) || (cwd == NULL)) { 376*0e42dee6Sartem goto out; 377*0e42dee6Sartem } 378*0e42dee6Sartem execname = getexecname(); 379*0e42dee6Sartem 380*0e42dee6Sartem if (execname[0] == '/') { 381*0e42dee6Sartem (void) snprintf(path, size, "%s", execname); 382*0e42dee6Sartem } else { 383*0e42dee6Sartem (void) snprintf(path, size, "%s/%s", cwd, execname); 384*0e42dee6Sartem } 385*0e42dee6Sartem if (realpath(path, rpath) == NULL) { 386*0e42dee6Sartem free(rpath); 387*0e42dee6Sartem rpath = NULL; 388*0e42dee6Sartem } 389*0e42dee6Sartem 390*0e42dee6Sartem out: 391*0e42dee6Sartem if (path != NULL) { 392*0e42dee6Sartem free(path); 393*0e42dee6Sartem } 394*0e42dee6Sartem if (cwd != NULL) { 395*0e42dee6Sartem free(cwd); 396*0e42dee6Sartem } 397*0e42dee6Sartem return (rpath); 398*0e42dee6Sartem } 399*0e42dee6Sartem 400*0e42dee6Sartem /* 401*0e42dee6Sartem * Separates dos notation device spec into device and drive number 402*0e42dee6Sartem */ 403*0e42dee6Sartem static boolean_t 404*0e42dee6Sartem dos_to_dev(char *path, char **devpath, int *num) 405*0e42dee6Sartem { 406*0e42dee6Sartem char *p; 407*0e42dee6Sartem 408*0e42dee6Sartem if ((p = strrchr(path, ':')) == NULL) { 409*0e42dee6Sartem return (B_FALSE); 410*0e42dee6Sartem } 411*0e42dee6Sartem if ((*num = atoi(p + 1)) == 0) { 412*0e42dee6Sartem return (B_FALSE); 413*0e42dee6Sartem } 414*0e42dee6Sartem p[0] = '\0'; 415*0e42dee6Sartem *devpath = strdup(path); 416*0e42dee6Sartem p[0] = ':'; 417*0e42dee6Sartem return (*devpath != NULL); 418*0e42dee6Sartem } 419*0e42dee6Sartem 420*0e42dee6Sartem static boolean_t 421*0e42dee6Sartem is_dos_drive(uchar_t type) 422*0e42dee6Sartem { 423*0e42dee6Sartem return ((type == 1) || (type == 4) || (type == 5) || (type == 6) || 424*0e42dee6Sartem ((type >= 8) && (type <= 0xf))); 425*0e42dee6Sartem } 426*0e42dee6Sartem 427*0e42dee6Sartem static boolean_t 428*0e42dee6Sartem is_dos_extended(uchar_t id) 429*0e42dee6Sartem { 430*0e42dee6Sartem return ((id == EXTDOS) || (id == FDISK_EXTLBA)); 431*0e42dee6Sartem } 432*0e42dee6Sartem 433*0e42dee6Sartem struct part_find_s { 434*0e42dee6Sartem int num; 435*0e42dee6Sartem int count; 436*0e42dee6Sartem int systid; 437*0e42dee6Sartem int r_systid; 438*0e42dee6Sartem int r_relsect; 439*0e42dee6Sartem int r_numsect; 440*0e42dee6Sartem }; 441*0e42dee6Sartem 442*0e42dee6Sartem enum { WALK_CONTINUE, WALK_TERMINATE }; 443*0e42dee6Sartem 444*0e42dee6Sartem /* 445*0e42dee6Sartem * Walk partition tables and invoke a callback for each. 446*0e42dee6Sartem */ 447*0e42dee6Sartem static void 448*0e42dee6Sartem walk_partitions(int fd, int startsec, int (*f)(void *, int, int, int), 449*0e42dee6Sartem void *arg) 450*0e42dee6Sartem { 451*0e42dee6Sartem uint32_t buf[1024/4]; 452*0e42dee6Sartem int bufsize = 1024; 453*0e42dee6Sartem struct mboot *mboot = (struct mboot *)&buf[0]; 454*0e42dee6Sartem struct ipart ipart[FD_NUMPART]; 455*0e42dee6Sartem int sec = startsec; 456*0e42dee6Sartem int lastsec = sec + 1; 457*0e42dee6Sartem int relsect; 458*0e42dee6Sartem int ext = 0; 459*0e42dee6Sartem int systid; 460*0e42dee6Sartem boolean_t valid; 461*0e42dee6Sartem int i; 462*0e42dee6Sartem 463*0e42dee6Sartem while (sec != lastsec) { 464*0e42dee6Sartem if (pread(fd, buf, bufsize, (off_t)sec * 512) != bufsize) { 465*0e42dee6Sartem break; 466*0e42dee6Sartem } 467*0e42dee6Sartem lastsec = sec; 468*0e42dee6Sartem if (ltohs(mboot->signature) != MBB_MAGIC) { 469*0e42dee6Sartem break; 470*0e42dee6Sartem } 471*0e42dee6Sartem bcopy(mboot->parts, ipart, FD_NUMPART * sizeof (struct ipart)); 472*0e42dee6Sartem 473*0e42dee6Sartem for (i = 0; i < FD_NUMPART; i++) { 474*0e42dee6Sartem systid = ipart[i].systid; 475*0e42dee6Sartem relsect = sec + ltohi(ipart[i].relsect); 476*0e42dee6Sartem if (systid == 0) { 477*0e42dee6Sartem continue; 478*0e42dee6Sartem } 479*0e42dee6Sartem valid = B_TRUE; 480*0e42dee6Sartem if (is_dos_extended(systid) && (sec == lastsec)) { 481*0e42dee6Sartem sec = startsec + ltohi(ipart[i].relsect); 482*0e42dee6Sartem if (ext++ == 0) { 483*0e42dee6Sartem relsect = startsec = sec; 484*0e42dee6Sartem } else { 485*0e42dee6Sartem valid = B_FALSE; 486*0e42dee6Sartem } 487*0e42dee6Sartem } 488*0e42dee6Sartem if (valid && f(arg, ipart[i].systid, relsect, 489*0e42dee6Sartem ltohi(ipart[i].numsect)) == WALK_TERMINATE) { 490*0e42dee6Sartem return; 491*0e42dee6Sartem } 492*0e42dee6Sartem } 493*0e42dee6Sartem } 494*0e42dee6Sartem } 495*0e42dee6Sartem 496*0e42dee6Sartem static int 497*0e42dee6Sartem find_dos_drive_cb(void *arg, int systid, int relsect, int numsect) 498*0e42dee6Sartem { 499*0e42dee6Sartem struct part_find_s *p = arg; 500*0e42dee6Sartem 501*0e42dee6Sartem if (is_dos_drive(systid)) { 502*0e42dee6Sartem if (++p->count == p->num) { 503*0e42dee6Sartem p->r_relsect = relsect; 504*0e42dee6Sartem p->r_numsect = numsect; 505*0e42dee6Sartem p->r_systid = systid; 506*0e42dee6Sartem return (WALK_TERMINATE); 507*0e42dee6Sartem } 508*0e42dee6Sartem } 509*0e42dee6Sartem 510*0e42dee6Sartem return (WALK_CONTINUE); 511*0e42dee6Sartem } 512*0e42dee6Sartem 513*0e42dee6Sartem /* 514*0e42dee6Sartem * Given a dos drive number, return its relative sector number, 515*0e42dee6Sartem * number of sectors in partition and the system id. 516*0e42dee6Sartem */ 517*0e42dee6Sartem static boolean_t 518*0e42dee6Sartem find_dos_drive(int fd, int num, int *relsect, int *numsect, int *systid) 519*0e42dee6Sartem { 520*0e42dee6Sartem struct part_find_s p = { 0, 0, 0, 0, 0, 0 }; 521*0e42dee6Sartem 522*0e42dee6Sartem p.num = num; 523*0e42dee6Sartem 524*0e42dee6Sartem if (num > 0) { 525*0e42dee6Sartem walk_partitions(fd, 0, find_dos_drive_cb, &p); 526*0e42dee6Sartem if (p.count == num) { 527*0e42dee6Sartem *relsect = p.r_relsect; 528*0e42dee6Sartem *numsect = p.r_numsect; 529*0e42dee6Sartem *systid = p.r_systid; 530*0e42dee6Sartem return (B_TRUE); 531*0e42dee6Sartem } 532*0e42dee6Sartem } 533*0e42dee6Sartem 534*0e42dee6Sartem return (B_FALSE); 535*0e42dee6Sartem } 536*0e42dee6Sartem 537*0e42dee6Sartem /* 538*0e42dee6Sartem * libfstyp identification failed: as a last resort, try to 539*0e42dee6Sartem * find and run legacy /usr/lib/fs/<fsname>/fstyp commands. 540*0e42dee6Sartem */ 541*0e42dee6Sartem static void 542*0e42dee6Sartem run_legacy_cmds(int fd, char *device, int vflag) 543*0e42dee6Sartem { 544*0e42dee6Sartem char *lib_dir = FSTYP_LIBFS_DIR; 545*0e42dee6Sartem char *path; 546*0e42dee6Sartem long name_max; 547*0e42dee6Sartem DIR *dirp; 548*0e42dee6Sartem struct dirent *dp_mem, *dp; 549*0e42dee6Sartem struct stat st; 550*0e42dee6Sartem fstyp_handle_t h; 551*0e42dee6Sartem int error; 552*0e42dee6Sartem char *arg1, *arg2; 553*0e42dee6Sartem 554*0e42dee6Sartem if (vflag) { 555*0e42dee6Sartem arg1 = "-v"; 556*0e42dee6Sartem arg2 = device; 557*0e42dee6Sartem } else { 558*0e42dee6Sartem arg1 = device; 559*0e42dee6Sartem arg2 = NULL; 560*0e42dee6Sartem } 561*0e42dee6Sartem 562*0e42dee6Sartem if ((dirp = opendir(lib_dir)) == NULL) { 563*0e42dee6Sartem return; 564*0e42dee6Sartem } 565*0e42dee6Sartem 566*0e42dee6Sartem name_max = pathconf(lib_dir, _PC_NAME_MAX); 567*0e42dee6Sartem path = calloc(1, name_max + 1); 568*0e42dee6Sartem dp = dp_mem = calloc(1, sizeof (struct dirent) + name_max + 1); 569*0e42dee6Sartem if ((path == NULL) || (dp_mem == NULL)) { 570*0e42dee6Sartem goto out; 571*0e42dee6Sartem } 572*0e42dee6Sartem 573*0e42dee6Sartem while ((readdir_r(dirp, dp, &dp) == 0) && (dp != NULL)) { 574*0e42dee6Sartem if (dp->d_name[0] == '.') { 575*0e42dee6Sartem continue; 576*0e42dee6Sartem } 577*0e42dee6Sartem (void) snprintf(path, name_max, "%s/%s", lib_dir, dp->d_name); 578*0e42dee6Sartem 579*0e42dee6Sartem /* it's legacy if there's no libfstyp module for it */ 580*0e42dee6Sartem error = fstyp_init(fd, 0, path, &h); 581*0e42dee6Sartem if (error != FSTYP_ERR_MOD_NOT_FOUND) { 582*0e42dee6Sartem if (error == 0) { 583*0e42dee6Sartem fstyp_fini(h); 584*0e42dee6Sartem } 585*0e42dee6Sartem continue; 586*0e42dee6Sartem } 587*0e42dee6Sartem 588*0e42dee6Sartem /* file must exist and be executable */ 589*0e42dee6Sartem (void) snprintf(path, name_max, 590*0e42dee6Sartem "%s/%s/fstyp", lib_dir, dp->d_name); 591*0e42dee6Sartem if ((stat(path, &st) < 0) || 592*0e42dee6Sartem ((st.st_mode & S_IXUSR) == 0)) { 593*0e42dee6Sartem continue; 594*0e42dee6Sartem } 595*0e42dee6Sartem 596*0e42dee6Sartem if ((error = run_cmd(path, "fstyp", arg1, arg2)) == 0) { 597*0e42dee6Sartem exit(0); 598*0e42dee6Sartem } 599*0e42dee6Sartem } 600*0e42dee6Sartem 601*0e42dee6Sartem out: 602*0e42dee6Sartem if (dp_mem != NULL) { 603*0e42dee6Sartem free(dp_mem); 604*0e42dee6Sartem } 605*0e42dee6Sartem if (path != NULL) { 606*0e42dee6Sartem free(path); 607*0e42dee6Sartem } 608*0e42dee6Sartem (void) closedir(dirp); 609*0e42dee6Sartem } 610*0e42dee6Sartem 611*0e42dee6Sartem static int 612*0e42dee6Sartem run_cmd(char *path, char *arg0, char *arg1, char *arg2) 613*0e42dee6Sartem { 614*0e42dee6Sartem pid_t pid; 615*0e42dee6Sartem int status = 1; 616*0e42dee6Sartem 617*0e42dee6Sartem pid = fork(); 618*0e42dee6Sartem if (pid < 0) { 619*0e42dee6Sartem return (1); 620*0e42dee6Sartem } else if (pid == 0) { 621*0e42dee6Sartem /* child */ 622*0e42dee6Sartem (void) execl(path, arg0, arg1, arg2, 0); 623*0e42dee6Sartem exit(1); 624*0e42dee6Sartem } 625*0e42dee6Sartem /* parent */ 626*0e42dee6Sartem (void) wait(&status); 627*0e42dee6Sartem return (status); 628*0e42dee6Sartem } 629