10e42dee6Sartem /* 20e42dee6Sartem * CDDL HEADER START 30e42dee6Sartem * 40e42dee6Sartem * The contents of this file are subject to the terms of the 50e42dee6Sartem * Common Development and Distribution License (the "License"). 60e42dee6Sartem * You may not use this file except in compliance with the License. 70e42dee6Sartem * 80e42dee6Sartem * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90e42dee6Sartem * or http://www.opensolaris.org/os/licensing. 100e42dee6Sartem * See the License for the specific language governing permissions 110e42dee6Sartem * and limitations under the License. 120e42dee6Sartem * 130e42dee6Sartem * When distributing Covered Code, include this CDDL HEADER in each 140e42dee6Sartem * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150e42dee6Sartem * If applicable, add the following below this CDDL HEADER, with the 160e42dee6Sartem * fields enclosed by brackets "[]" replaced with your own identifying 170e42dee6Sartem * information: Portions Copyright [yyyy] [name of copyright owner] 180e42dee6Sartem * 190e42dee6Sartem * CDDL HEADER END 200e42dee6Sartem */ 210e42dee6Sartem /* 22ca29f3daSprabahar * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230e42dee6Sartem * Use is subject to license terms. 240e42dee6Sartem */ 250e42dee6Sartem 260e42dee6Sartem #include <fcntl.h> 270e42dee6Sartem #include <stdio.h> 280e42dee6Sartem #include <stdlib.h> 290e42dee6Sartem #include <sys/types.h> 300e42dee6Sartem #include <sys/stat.h> 310e42dee6Sartem #include <unistd.h> 320e42dee6Sartem #include <libintl.h> 330e42dee6Sartem #include <locale.h> 340e42dee6Sartem #include <string.h> 350e42dee6Sartem #include <strings.h> 360e42dee6Sartem #include <errno.h> 370e42dee6Sartem #include <dirent.h> 380e42dee6Sartem #include <dlfcn.h> 390e42dee6Sartem #include <sys/wait.h> 400e42dee6Sartem #include <sys/fstyp.h> 41ca29f3daSprabahar #include <sys/dkio.h> 42ca29f3daSprabahar #include <sys/param.h> 430e42dee6Sartem #include <libfstyp.h> 440e42dee6Sartem #include <sys/dktp/fdisk.h> 450e42dee6Sartem #include <sys/fs/pc_label.h> 460e42dee6Sartem 47f5ac0e94Smc #include "libadm.h" 48f5ac0e94Smc 490e42dee6Sartem #define FSTYP_LIBFS_DIR "/usr/lib/fs" 500e42dee6Sartem 510e42dee6Sartem static const char *getmodfsname(); 520e42dee6Sartem static char *getexecpathname(); 530e42dee6Sartem static void dump_nvlist(nvlist_t *list, int indent); 540e42dee6Sartem static boolean_t dos_to_dev(char *path, char **devpath, int *num); 55ca29f3daSprabahar static boolean_t find_dos_drive(int fd, int num, off_t *offset); 560e42dee6Sartem static void run_legacy_cmds(int fd, char *device, int vflag); 570e42dee6Sartem static int run_cmd(char *path, char *arg0, char *arg1, char *arg2); 580e42dee6Sartem 590e42dee6Sartem 600e42dee6Sartem static void 610e42dee6Sartem usage(void) 620e42dee6Sartem { 630e42dee6Sartem (void) fprintf(stderr, gettext("Usage: fstyp [-av] <device>\n")); 640e42dee6Sartem exit(1); 650e42dee6Sartem } 660e42dee6Sartem 670e42dee6Sartem int 680e42dee6Sartem main(int argc, char **argv) 690e42dee6Sartem { 700e42dee6Sartem int fd = -1; 710e42dee6Sartem int c; 720e42dee6Sartem int aflag = 0; 730e42dee6Sartem int vflag = 0; 740e42dee6Sartem int indent = 0; 750e42dee6Sartem char *devpath; 760e42dee6Sartem boolean_t is_dos; 77ca29f3daSprabahar int dos_num; 780e42dee6Sartem off_t offset = 0; 790e42dee6Sartem nvlist_t *attr = NULL; 800e42dee6Sartem fstyp_handle_t h = NULL; 810e42dee6Sartem const char *modfsname; 820e42dee6Sartem const char *fsname; 830e42dee6Sartem int error = FSTYP_ERR_NO_MATCH; 840e42dee6Sartem 850e42dee6Sartem (void) setlocale(LC_ALL, ""); 860e42dee6Sartem 870e42dee6Sartem #if !defined(TEXT_DOMAIN) 880e42dee6Sartem #define TEXT_DOMAIN "SYS_TEST" 890e42dee6Sartem #endif 900e42dee6Sartem (void) textdomain(TEXT_DOMAIN); 910e42dee6Sartem 920e42dee6Sartem while ((c = getopt(argc, argv, "av")) != -1) { 930e42dee6Sartem switch (c) { 940e42dee6Sartem case 'a': 950e42dee6Sartem aflag = 1; 960e42dee6Sartem break; 970e42dee6Sartem case 'v': 980e42dee6Sartem vflag = 1; 990e42dee6Sartem break; 1000e42dee6Sartem default: 1010e42dee6Sartem usage(); 1020e42dee6Sartem break; 1030e42dee6Sartem } 1040e42dee6Sartem } 1050e42dee6Sartem 1060e42dee6Sartem argv += optind; 1070e42dee6Sartem argc -= optind; 1080e42dee6Sartem 1090e42dee6Sartem if (argc != 1) { 1100e42dee6Sartem usage(); 1110e42dee6Sartem } 1120e42dee6Sartem 1130e42dee6Sartem modfsname = getmodfsname(); 1140e42dee6Sartem 1150e42dee6Sartem /* 1160e42dee6Sartem * Open device, find partition offset if requested 1170e42dee6Sartem */ 1180e42dee6Sartem if (!(is_dos = dos_to_dev(argv[0], &devpath, &dos_num))) { 1190e42dee6Sartem devpath = argv[0]; 1200e42dee6Sartem } 1210e42dee6Sartem if ((fd = open(devpath, O_RDONLY)) < 0) { 1220e42dee6Sartem error = FSTYP_ERR_DEV_OPEN; 1230e42dee6Sartem goto out; 1240e42dee6Sartem } 1250e42dee6Sartem if (is_dos) { 126ca29f3daSprabahar if (!find_dos_drive(fd, dos_num, &offset)) { 1270e42dee6Sartem error = FSTYP_ERR_NO_PARTITION; 1280e42dee6Sartem goto out; 1290e42dee6Sartem } 1300e42dee6Sartem } 1310e42dee6Sartem 1320e42dee6Sartem /* 1330e42dee6Sartem * Use libfstyp to identify filesystem 1340e42dee6Sartem */ 1350e42dee6Sartem if ((error = fstyp_init(fd, offset, NULL, &h)) != 0) { 1360e42dee6Sartem goto out; 1370e42dee6Sartem } 1380e42dee6Sartem if ((error = fstyp_ident(h, modfsname, &fsname)) != 0) { 1390e42dee6Sartem fstyp_fini(h); 1400e42dee6Sartem h = NULL; 1410e42dee6Sartem 1420e42dee6Sartem run_legacy_cmds(fd, argv[0], vflag); 1430e42dee6Sartem 1440e42dee6Sartem goto out; 1450e42dee6Sartem } 1460e42dee6Sartem 1470e42dee6Sartem (void) printf("%s\n", fsname); 1480e42dee6Sartem 1490e42dee6Sartem /* 1500e42dee6Sartem * Output additional info if requested 1510e42dee6Sartem */ 1520e42dee6Sartem if (vflag) { 1530e42dee6Sartem error = fstyp_dump(h, stdout, stderr); 1540e42dee6Sartem } 1550e42dee6Sartem if (aflag || (vflag && (error == FSTYP_ERR_NOP))) { 1560e42dee6Sartem if ((error = fstyp_get_attr(h, &attr)) != 0) { 1570e42dee6Sartem goto out; 1580e42dee6Sartem } 1590e42dee6Sartem dump_nvlist(attr, indent); 1600e42dee6Sartem } 1610e42dee6Sartem 1620e42dee6Sartem out: 1630e42dee6Sartem if (error != 0) { 1640e42dee6Sartem (void) fprintf(stderr, gettext("unknown_fstyp (%s)\n"), 1650e42dee6Sartem fstyp_strerror(h, error)); 1660e42dee6Sartem } 1670e42dee6Sartem if (h != NULL) { 1680e42dee6Sartem fstyp_fini(h); 1690e42dee6Sartem } 1700e42dee6Sartem if (fd >= 0) { 1710e42dee6Sartem (void) close(fd); 1720e42dee6Sartem } 1730e42dee6Sartem if (devpath != argv[0]) { 1740e42dee6Sartem free(devpath); 1750e42dee6Sartem } 1760e42dee6Sartem return (error); 1770e42dee6Sartem 1780e42dee6Sartem } 1790e42dee6Sartem 1800e42dee6Sartem #define NVP(elem, type, vtype, ptype, format) { \ 1810e42dee6Sartem vtype value; \ 1820e42dee6Sartem \ 1830e42dee6Sartem (void) nvpair_value_##type(elem, &value); \ 1840e42dee6Sartem (void) printf("%*s%s: " format "\n", indent, "", \ 1850e42dee6Sartem nvpair_name(elem), (ptype)value); \ 1860e42dee6Sartem } 1870e42dee6Sartem 1880e42dee6Sartem #define NVPA(elem, type, vtype, ptype, format) { \ 1890e42dee6Sartem uint_t i, count; \ 1900e42dee6Sartem vtype *value; \ 1910e42dee6Sartem \ 1920e42dee6Sartem (void) nvpair_value_##type(elem, &value, &count); \ 1930e42dee6Sartem for (i = 0; i < count; i++) { \ 1940e42dee6Sartem (void) printf("%*s%s[%d]: " format "\n", indent, "", \ 1950e42dee6Sartem nvpair_name(elem), i, (ptype)value[i]); \ 1960e42dee6Sartem } \ 1970e42dee6Sartem } 1980e42dee6Sartem 1990e42dee6Sartem static void 2000e42dee6Sartem dump_nvlist(nvlist_t *list, int indent) 2010e42dee6Sartem { 2020e42dee6Sartem nvpair_t *elem = NULL; 2030e42dee6Sartem boolean_t bool_value; 2040e42dee6Sartem nvlist_t *nvlist_value; 2050e42dee6Sartem nvlist_t **nvlist_array_value; 2060e42dee6Sartem uint_t i, count; 2070e42dee6Sartem 2080e42dee6Sartem if (list == NULL) { 2090e42dee6Sartem return; 2100e42dee6Sartem } 2110e42dee6Sartem 2120e42dee6Sartem while ((elem = nvlist_next_nvpair(list, elem)) != NULL) { 2130e42dee6Sartem switch (nvpair_type(elem)) { 2140e42dee6Sartem case DATA_TYPE_BOOLEAN_VALUE: 2150e42dee6Sartem (void) nvpair_value_boolean_value(elem, &bool_value); 2160e42dee6Sartem (void) printf("%*s%s: %s\n", indent, "", 2170e42dee6Sartem nvpair_name(elem), bool_value ? "true" : "false"); 2180e42dee6Sartem break; 2190e42dee6Sartem 2200e42dee6Sartem case DATA_TYPE_BYTE: 2210e42dee6Sartem NVP(elem, byte, uchar_t, int, "%u"); 2220e42dee6Sartem break; 2230e42dee6Sartem 2240e42dee6Sartem case DATA_TYPE_INT8: 2250e42dee6Sartem NVP(elem, int8, int8_t, int, "%d"); 2260e42dee6Sartem break; 2270e42dee6Sartem 2280e42dee6Sartem case DATA_TYPE_UINT8: 2290e42dee6Sartem NVP(elem, uint8, uint8_t, int, "%u"); 2300e42dee6Sartem break; 2310e42dee6Sartem 2320e42dee6Sartem case DATA_TYPE_INT16: 2330e42dee6Sartem NVP(elem, int16, int16_t, int, "%d"); 2340e42dee6Sartem break; 2350e42dee6Sartem 2360e42dee6Sartem case DATA_TYPE_UINT16: 2370e42dee6Sartem NVP(elem, uint16, uint16_t, int, "%u"); 2380e42dee6Sartem break; 2390e42dee6Sartem 2400e42dee6Sartem case DATA_TYPE_INT32: 2410e42dee6Sartem NVP(elem, int32, int32_t, long, "%ld"); 2420e42dee6Sartem break; 2430e42dee6Sartem 2440e42dee6Sartem case DATA_TYPE_UINT32: 2450e42dee6Sartem NVP(elem, uint32, uint32_t, ulong_t, "%lu"); 2460e42dee6Sartem break; 2470e42dee6Sartem 2480e42dee6Sartem case DATA_TYPE_INT64: 2490e42dee6Sartem NVP(elem, int64, int64_t, longlong_t, "%lld"); 2500e42dee6Sartem break; 2510e42dee6Sartem 2520e42dee6Sartem case DATA_TYPE_UINT64: 2530e42dee6Sartem NVP(elem, uint64, uint64_t, u_longlong_t, "%llu"); 2540e42dee6Sartem break; 2550e42dee6Sartem 2560e42dee6Sartem case DATA_TYPE_STRING: 2570e42dee6Sartem NVP(elem, string, char *, char *, "'%s'"); 2580e42dee6Sartem break; 2590e42dee6Sartem 2600e42dee6Sartem case DATA_TYPE_BYTE_ARRAY: 2610e42dee6Sartem NVPA(elem, byte_array, uchar_t, int, "%u"); 2620e42dee6Sartem break; 2630e42dee6Sartem 2640e42dee6Sartem case DATA_TYPE_INT8_ARRAY: 2650e42dee6Sartem NVPA(elem, int8_array, int8_t, int, "%d"); 2660e42dee6Sartem break; 2670e42dee6Sartem 2680e42dee6Sartem case DATA_TYPE_UINT8_ARRAY: 2690e42dee6Sartem NVPA(elem, uint8_array, uint8_t, int, "%u"); 2700e42dee6Sartem break; 2710e42dee6Sartem 2720e42dee6Sartem case DATA_TYPE_INT16_ARRAY: 2730e42dee6Sartem NVPA(elem, int16_array, int16_t, int, "%d"); 2740e42dee6Sartem break; 2750e42dee6Sartem 2760e42dee6Sartem case DATA_TYPE_UINT16_ARRAY: 2770e42dee6Sartem NVPA(elem, uint16_array, uint16_t, int, "%u"); 2780e42dee6Sartem break; 2790e42dee6Sartem 2800e42dee6Sartem case DATA_TYPE_INT32_ARRAY: 2810e42dee6Sartem NVPA(elem, int32_array, int32_t, long, "%ld"); 2820e42dee6Sartem break; 2830e42dee6Sartem 2840e42dee6Sartem case DATA_TYPE_UINT32_ARRAY: 2850e42dee6Sartem NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu"); 2860e42dee6Sartem break; 2870e42dee6Sartem 2880e42dee6Sartem case DATA_TYPE_INT64_ARRAY: 2890e42dee6Sartem NVPA(elem, int64_array, int64_t, longlong_t, "%lld"); 2900e42dee6Sartem break; 2910e42dee6Sartem 2920e42dee6Sartem case DATA_TYPE_UINT64_ARRAY: 2930e42dee6Sartem NVPA(elem, uint64_array, uint64_t, u_longlong_t, 2940e42dee6Sartem "%llu"); 2950e42dee6Sartem break; 2960e42dee6Sartem 2970e42dee6Sartem case DATA_TYPE_STRING_ARRAY: 2980e42dee6Sartem NVPA(elem, string_array, char *, char *, "'%s'"); 2990e42dee6Sartem break; 3000e42dee6Sartem 3010e42dee6Sartem case DATA_TYPE_NVLIST: 3020e42dee6Sartem (void) nvpair_value_nvlist(elem, &nvlist_value); 3030e42dee6Sartem (void) printf("%*s%s:\n", indent, "", 3040e42dee6Sartem nvpair_name(elem)); 3050e42dee6Sartem dump_nvlist(nvlist_value, indent + 4); 3060e42dee6Sartem break; 3070e42dee6Sartem 3080e42dee6Sartem case DATA_TYPE_NVLIST_ARRAY: 3090e42dee6Sartem (void) nvpair_value_nvlist_array(elem, 3100e42dee6Sartem &nvlist_array_value, &count); 3110e42dee6Sartem for (i = 0; i < count; i++) { 3120e42dee6Sartem (void) printf("%*s%s[%u]:\n", indent, "", 3130e42dee6Sartem nvpair_name(elem), i); 3140e42dee6Sartem dump_nvlist(nvlist_array_value[i], indent + 4); 3150e42dee6Sartem } 3160e42dee6Sartem break; 3170e42dee6Sartem 3180e42dee6Sartem default: 3190e42dee6Sartem (void) printf(gettext("bad config type %d for %s\n"), 3200e42dee6Sartem nvpair_type(elem), nvpair_name(elem)); 3210e42dee6Sartem } 3220e42dee6Sartem } 3230e42dee6Sartem } 3240e42dee6Sartem 3250e42dee6Sartem /* 3260e42dee6Sartem * If the executable is a fs-specific hardlink, /usr/lib/fs/<fsname>/fstyp, 3270e42dee6Sartem * return that fsname; otherwise return NULL. 3280e42dee6Sartem */ 3290e42dee6Sartem static const char * 3300e42dee6Sartem getmodfsname() 3310e42dee6Sartem { 3320e42dee6Sartem static char fsname_buf[FSTYPSZ + 1]; 3330e42dee6Sartem char *fsname = NULL; 3340e42dee6Sartem char *path; 3350e42dee6Sartem char *p; 3360e42dee6Sartem int len; 3370e42dee6Sartem 3380e42dee6Sartem if ((path = getexecpathname()) == NULL) { 3390e42dee6Sartem return (NULL); 3400e42dee6Sartem } 3410e42dee6Sartem if ((p = strrchr(path, '/')) != NULL) { 3420e42dee6Sartem *p = '\0'; 3430e42dee6Sartem if ((p = strrchr(path, '/')) != NULL) { 3440e42dee6Sartem *p++ = '\0'; 3450e42dee6Sartem len = strlen(p); 3460e42dee6Sartem if ((strcmp(path, FSTYP_LIBFS_DIR) == 0) && 3470e42dee6Sartem (len > 0) && (len < sizeof (fsname_buf))) { 3480e42dee6Sartem (void) strlcpy(fsname_buf, p, 3490e42dee6Sartem sizeof (fsname_buf)); 3500e42dee6Sartem fsname = fsname_buf; 3510e42dee6Sartem } 3520e42dee6Sartem } 3530e42dee6Sartem } 3540e42dee6Sartem free(path); 3550e42dee6Sartem return (fsname); 3560e42dee6Sartem } 3570e42dee6Sartem 3580e42dee6Sartem /* 3590e42dee6Sartem * Return executable's absolute pathname 3600e42dee6Sartem */ 3610e42dee6Sartem static char * 3620e42dee6Sartem getexecpathname() 3630e42dee6Sartem { 3640e42dee6Sartem size_t size; 3650e42dee6Sartem const char *execname; 3660e42dee6Sartem char *cwd; 3670e42dee6Sartem char *path; 3680e42dee6Sartem char *rpath; 3690e42dee6Sartem 3700e42dee6Sartem size = pathconf(".", _PC_PATH_MAX) + 1; 3710e42dee6Sartem path = malloc(size); 3720e42dee6Sartem rpath = malloc(size); 3730e42dee6Sartem cwd = getcwd(NULL, size); 3740e42dee6Sartem if ((path == NULL) || (rpath == NULL) || (cwd == NULL)) { 3750e42dee6Sartem goto out; 3760e42dee6Sartem } 3770e42dee6Sartem execname = getexecname(); 3780e42dee6Sartem 3790e42dee6Sartem if (execname[0] == '/') { 3800e42dee6Sartem (void) snprintf(path, size, "%s", execname); 3810e42dee6Sartem } else { 3820e42dee6Sartem (void) snprintf(path, size, "%s/%s", cwd, execname); 3830e42dee6Sartem } 3840e42dee6Sartem if (realpath(path, rpath) == NULL) { 3850e42dee6Sartem free(rpath); 3860e42dee6Sartem rpath = NULL; 3870e42dee6Sartem } 3880e42dee6Sartem 3890e42dee6Sartem out: 3900e42dee6Sartem if (path != NULL) { 3910e42dee6Sartem free(path); 3920e42dee6Sartem } 3930e42dee6Sartem if (cwd != NULL) { 3940e42dee6Sartem free(cwd); 3950e42dee6Sartem } 3960e42dee6Sartem return (rpath); 3970e42dee6Sartem } 3980e42dee6Sartem 3990e42dee6Sartem /* 4000e42dee6Sartem * Separates dos notation device spec into device and drive number 4010e42dee6Sartem */ 4020e42dee6Sartem static boolean_t 4030e42dee6Sartem dos_to_dev(char *path, char **devpath, int *num) 4040e42dee6Sartem { 4050e42dee6Sartem char *p; 4060e42dee6Sartem 4070e42dee6Sartem if ((p = strrchr(path, ':')) == NULL) { 4080e42dee6Sartem return (B_FALSE); 4090e42dee6Sartem } 4100e42dee6Sartem if ((*num = atoi(p + 1)) == 0) { 4110e42dee6Sartem return (B_FALSE); 4120e42dee6Sartem } 4130e42dee6Sartem p[0] = '\0'; 414f5ac0e94Smc *devpath = getfullrawname(path); 4150e42dee6Sartem p[0] = ':'; 416f5ac0e94Smc if (*devpath != NULL && **devpath == '\0') { 417f5ac0e94Smc free(*devpath); 418f5ac0e94Smc *devpath = NULL; 419f5ac0e94Smc } 4200e42dee6Sartem return (*devpath != NULL); 4210e42dee6Sartem } 4220e42dee6Sartem 4230e42dee6Sartem static boolean_t 4240e42dee6Sartem is_dos_drive(uchar_t type) 4250e42dee6Sartem { 4262d700530Sartem return ((type == DOSOS12) || (type == DOSOS16) || 4272d700530Sartem (type == DOSHUGE) || (type == FDISK_WINDOWS) || 4282d700530Sartem (type == FDISK_EXT_WIN) || (type == FDISK_FAT95) || 4292d700530Sartem (type == DIAGPART)); 4300e42dee6Sartem } 4310e42dee6Sartem 4320e42dee6Sartem static boolean_t 4330e42dee6Sartem is_dos_extended(uchar_t id) 4340e42dee6Sartem { 4350e42dee6Sartem return ((id == EXTDOS) || (id == FDISK_EXTLBA)); 4360e42dee6Sartem } 4370e42dee6Sartem 4380e42dee6Sartem struct part_find_s { 4390e42dee6Sartem int num; 4400e42dee6Sartem int count; 4410e42dee6Sartem int systid; 4420e42dee6Sartem int r_systid; 443*342440ecSPrasad Singamsetty uint32_t r_relsect; 444*342440ecSPrasad Singamsetty uint32_t r_numsect; 4450e42dee6Sartem }; 4460e42dee6Sartem 4470e42dee6Sartem enum { WALK_CONTINUE, WALK_TERMINATE }; 4480e42dee6Sartem 4490e42dee6Sartem /* 4500e42dee6Sartem * Walk partition tables and invoke a callback for each. 4510e42dee6Sartem */ 4520e42dee6Sartem static void 453*342440ecSPrasad Singamsetty walk_partitions(int fd, uint32_t startsec, off_t secsz, 454*342440ecSPrasad Singamsetty int (*f)(void *, int, uint32_t, uint32_t), void *arg) 4550e42dee6Sartem { 4560e42dee6Sartem uint32_t buf[1024/4]; 4570e42dee6Sartem int bufsize = 1024; 4580e42dee6Sartem struct mboot *mboot = (struct mboot *)&buf[0]; 4590e42dee6Sartem struct ipart ipart[FD_NUMPART]; 460*342440ecSPrasad Singamsetty uint32_t sec = startsec; 461*342440ecSPrasad Singamsetty uint32_t lastsec = sec + 1; 462*342440ecSPrasad Singamsetty uint32_t relsect; 4630e42dee6Sartem int ext = 0; 4640e42dee6Sartem int systid; 4650e42dee6Sartem boolean_t valid; 4660e42dee6Sartem int i; 4670e42dee6Sartem 4680e42dee6Sartem while (sec != lastsec) { 469ca29f3daSprabahar if (pread(fd, buf, bufsize, (off_t)sec * secsz) != bufsize) { 4700e42dee6Sartem break; 4710e42dee6Sartem } 4720e42dee6Sartem lastsec = sec; 4730e42dee6Sartem if (ltohs(mboot->signature) != MBB_MAGIC) { 4740e42dee6Sartem break; 4750e42dee6Sartem } 4760e42dee6Sartem bcopy(mboot->parts, ipart, FD_NUMPART * sizeof (struct ipart)); 4770e42dee6Sartem 4780e42dee6Sartem for (i = 0; i < FD_NUMPART; i++) { 4790e42dee6Sartem systid = ipart[i].systid; 4800e42dee6Sartem relsect = sec + ltohi(ipart[i].relsect); 4810e42dee6Sartem if (systid == 0) { 4820e42dee6Sartem continue; 4830e42dee6Sartem } 4840e42dee6Sartem valid = B_TRUE; 4850e42dee6Sartem if (is_dos_extended(systid) && (sec == lastsec)) { 4860e42dee6Sartem sec = startsec + ltohi(ipart[i].relsect); 4870e42dee6Sartem if (ext++ == 0) { 4880e42dee6Sartem relsect = startsec = sec; 4890e42dee6Sartem } else { 4900e42dee6Sartem valid = B_FALSE; 4910e42dee6Sartem } 4920e42dee6Sartem } 4930e42dee6Sartem if (valid && f(arg, ipart[i].systid, relsect, 4940e42dee6Sartem ltohi(ipart[i].numsect)) == WALK_TERMINATE) { 4950e42dee6Sartem return; 4960e42dee6Sartem } 4970e42dee6Sartem } 4980e42dee6Sartem } 4990e42dee6Sartem } 5000e42dee6Sartem 5010e42dee6Sartem static int 502*342440ecSPrasad Singamsetty find_dos_drive_cb(void *arg, int systid, uint32_t relsect, uint32_t numsect) 5030e42dee6Sartem { 5040e42dee6Sartem struct part_find_s *p = arg; 5050e42dee6Sartem 5060e42dee6Sartem if (is_dos_drive(systid)) { 5070e42dee6Sartem if (++p->count == p->num) { 5080e42dee6Sartem p->r_relsect = relsect; 5090e42dee6Sartem p->r_numsect = numsect; 5100e42dee6Sartem p->r_systid = systid; 5110e42dee6Sartem return (WALK_TERMINATE); 5120e42dee6Sartem } 5130e42dee6Sartem } 5140e42dee6Sartem 5150e42dee6Sartem return (WALK_CONTINUE); 5160e42dee6Sartem } 5170e42dee6Sartem 5180e42dee6Sartem /* 519ca29f3daSprabahar * Given a dos drive number, return its relative offset in the drive. 5200e42dee6Sartem */ 5210e42dee6Sartem static boolean_t 522ca29f3daSprabahar find_dos_drive(int fd, int num, off_t *offset) 5230e42dee6Sartem { 524ca29f3daSprabahar struct dk_minfo mi; 525ca29f3daSprabahar off_t secsz; 5260e42dee6Sartem struct part_find_s p = { 0, 0, 0, 0, 0, 0 }; 5270e42dee6Sartem 5280e42dee6Sartem p.num = num; 5290e42dee6Sartem 530ca29f3daSprabahar /* 531ca29f3daSprabahar * It is possible that the media we are dealing with can have different 532ca29f3daSprabahar * sector size than the default 512 bytes. Query the driver and check 533ca29f3daSprabahar * whether the media has different sector size. 534ca29f3daSprabahar */ 535ca29f3daSprabahar if (ioctl(fd, DKIOCGMEDIAINFO, &mi) < 0) 536ca29f3daSprabahar secsz = DEV_BSIZE; 537ca29f3daSprabahar else 538ca29f3daSprabahar secsz = mi.dki_lbsize; 539ca29f3daSprabahar 5400e42dee6Sartem if (num > 0) { 541ca29f3daSprabahar walk_partitions(fd, 0, secsz, find_dos_drive_cb, &p); 5420e42dee6Sartem if (p.count == num) { 543ca29f3daSprabahar *offset = secsz * (off_t)p.r_relsect; 5440e42dee6Sartem return (B_TRUE); 5450e42dee6Sartem } 5460e42dee6Sartem } 5470e42dee6Sartem 5480e42dee6Sartem return (B_FALSE); 5490e42dee6Sartem } 5500e42dee6Sartem 5510e42dee6Sartem /* 5520e42dee6Sartem * libfstyp identification failed: as a last resort, try to 5530e42dee6Sartem * find and run legacy /usr/lib/fs/<fsname>/fstyp commands. 5540e42dee6Sartem */ 5550e42dee6Sartem static void 5560e42dee6Sartem run_legacy_cmds(int fd, char *device, int vflag) 5570e42dee6Sartem { 5580e42dee6Sartem char *lib_dir = FSTYP_LIBFS_DIR; 5590e42dee6Sartem char *path; 5600e42dee6Sartem long name_max; 5610e42dee6Sartem DIR *dirp; 5620e42dee6Sartem struct dirent *dp_mem, *dp; 5630e42dee6Sartem struct stat st; 5640e42dee6Sartem fstyp_handle_t h; 5650e42dee6Sartem int error; 5660e42dee6Sartem char *arg1, *arg2; 5670e42dee6Sartem 5680e42dee6Sartem if (vflag) { 5690e42dee6Sartem arg1 = "-v"; 5700e42dee6Sartem arg2 = device; 5710e42dee6Sartem } else { 5720e42dee6Sartem arg1 = device; 5730e42dee6Sartem arg2 = NULL; 5740e42dee6Sartem } 5750e42dee6Sartem 5760e42dee6Sartem if ((dirp = opendir(lib_dir)) == NULL) { 5770e42dee6Sartem return; 5780e42dee6Sartem } 5790e42dee6Sartem 5800e42dee6Sartem name_max = pathconf(lib_dir, _PC_NAME_MAX); 5810e42dee6Sartem path = calloc(1, name_max + 1); 5820e42dee6Sartem dp = dp_mem = calloc(1, sizeof (struct dirent) + name_max + 1); 5830e42dee6Sartem if ((path == NULL) || (dp_mem == NULL)) { 5840e42dee6Sartem goto out; 5850e42dee6Sartem } 5860e42dee6Sartem 5870e42dee6Sartem while ((readdir_r(dirp, dp, &dp) == 0) && (dp != NULL)) { 5880e42dee6Sartem if (dp->d_name[0] == '.') { 5890e42dee6Sartem continue; 5900e42dee6Sartem } 5910e42dee6Sartem (void) snprintf(path, name_max, "%s/%s", lib_dir, dp->d_name); 5920e42dee6Sartem 5930e42dee6Sartem /* it's legacy if there's no libfstyp module for it */ 5940e42dee6Sartem error = fstyp_init(fd, 0, path, &h); 5950e42dee6Sartem if (error != FSTYP_ERR_MOD_NOT_FOUND) { 5960e42dee6Sartem if (error == 0) { 5970e42dee6Sartem fstyp_fini(h); 5980e42dee6Sartem } 5990e42dee6Sartem continue; 6000e42dee6Sartem } 6010e42dee6Sartem 6020e42dee6Sartem /* file must exist and be executable */ 6030e42dee6Sartem (void) snprintf(path, name_max, 6040e42dee6Sartem "%s/%s/fstyp", lib_dir, dp->d_name); 6050e42dee6Sartem if ((stat(path, &st) < 0) || 6060e42dee6Sartem ((st.st_mode & S_IXUSR) == 0)) { 6070e42dee6Sartem continue; 6080e42dee6Sartem } 6090e42dee6Sartem 6100e42dee6Sartem if ((error = run_cmd(path, "fstyp", arg1, arg2)) == 0) { 6110e42dee6Sartem exit(0); 6120e42dee6Sartem } 6130e42dee6Sartem } 6140e42dee6Sartem 6150e42dee6Sartem out: 6160e42dee6Sartem if (dp_mem != NULL) { 6170e42dee6Sartem free(dp_mem); 6180e42dee6Sartem } 6190e42dee6Sartem if (path != NULL) { 6200e42dee6Sartem free(path); 6210e42dee6Sartem } 6220e42dee6Sartem (void) closedir(dirp); 6230e42dee6Sartem } 6240e42dee6Sartem 6250e42dee6Sartem static int 6260e42dee6Sartem run_cmd(char *path, char *arg0, char *arg1, char *arg2) 6270e42dee6Sartem { 6280e42dee6Sartem pid_t pid; 6290e42dee6Sartem int status = 1; 6300e42dee6Sartem 6310e42dee6Sartem pid = fork(); 6320e42dee6Sartem if (pid < 0) { 6330e42dee6Sartem return (1); 6340e42dee6Sartem } else if (pid == 0) { 6350e42dee6Sartem /* child */ 6360e42dee6Sartem (void) execl(path, arg0, arg1, arg2, 0); 6370e42dee6Sartem exit(1); 6380e42dee6Sartem } 6390e42dee6Sartem /* parent */ 6400e42dee6Sartem (void) wait(&status); 6410e42dee6Sartem return (status); 6420e42dee6Sartem } 643