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