1*7563SPrasad.Singamsetty@Sun.COM /* 22912Sartem * 32912Sartem * fsutils.c : filesystem utilities 42912Sartem * 56395Sartem * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 62912Sartem * Use is subject to license terms. 72912Sartem * 82912Sartem * Licensed under the Academic Free License version 2.1 92912Sartem * 10*7563SPrasad.Singamsetty@Sun.COM */ 112912Sartem 122912Sartem #ifdef HAVE_CONFIG_H 13*7563SPrasad.Singamsetty@Sun.COM #include <config.h> 142912Sartem #endif 152912Sartem 162912Sartem #include <stdio.h> 172912Sartem #include <sys/types.h> 182912Sartem #include <sys/scsi/impl/uscsi.h> 192912Sartem #include <string.h> 202912Sartem #include <strings.h> 212912Sartem #include <ctype.h> 222912Sartem #include <unistd.h> 232912Sartem #include <stdlib.h> 242912Sartem #include <errno.h> 252912Sartem #include <fcntl.h> 262912Sartem #include <sys/dkio.h> 272912Sartem #include <libintl.h> 282912Sartem #include <sys/dktp/fdisk.h> 292912Sartem #include <sys/fs/pc_label.h> 302912Sartem 312912Sartem #include <libhal.h> 322912Sartem #include "fsutils.h" 332912Sartem 342912Sartem /* 352912Sartem * Separates dos notation device spec into device and drive number 362912Sartem */ 372912Sartem boolean_t 382912Sartem dos_to_dev(char *path, char **devpath, int *num) 392912Sartem { 402912Sartem char *p; 412912Sartem 422912Sartem if ((p = strrchr(path, ':')) == NULL) { 432912Sartem return (B_FALSE); 442912Sartem } 452912Sartem if ((*num = atoi(p + 1)) == 0) { 462912Sartem return (B_FALSE); 472912Sartem } 482912Sartem p[0] = '\0'; 492912Sartem *devpath = strdup(path); 502912Sartem p[0] = ':'; 512912Sartem return (*devpath != NULL); 522912Sartem } 532912Sartem 542912Sartem char * 55*7563SPrasad.Singamsetty@Sun.COM get_slice_name(char *devlink) 562912Sartem { 572912Sartem char *part, *slice, *disk; 582912Sartem char *s = NULL; 592912Sartem char *p; 602912Sartem 612912Sartem if ((p = strstr(devlink, "/lofi/")) != 0) { 622912Sartem return (p + sizeof ("/lofi/") - 1); 632912Sartem } 642912Sartem 652912Sartem part = strrchr(devlink, 'p'); 662912Sartem slice = strrchr(devlink, 's'); 672912Sartem disk = strrchr(devlink, 'd'); 682912Sartem 692912Sartem if ((part != NULL) && (part > slice) && (part > disk)) { 702912Sartem s = part; 712912Sartem } else if ((slice != NULL) && (slice > disk)) { 722912Sartem s = slice; 732912Sartem } else { 742912Sartem s = disk; 752912Sartem } 762912Sartem if ((s != NULL) && isdigit(s[1])) { 772912Sartem return (s); 782912Sartem } else { 792912Sartem return (""); 802912Sartem } 812912Sartem } 822912Sartem 832912Sartem boolean_t 842912Sartem is_dos_drive(uchar_t type) 852912Sartem { 863602Sartem return ((type == DOSOS12) || (type == DOSOS16) || 873602Sartem (type == DOSHUGE) || (type == FDISK_WINDOWS) || 883602Sartem (type == FDISK_EXT_WIN) || (type == FDISK_FAT95) || 893602Sartem (type == DIAGPART)); 902912Sartem } 912912Sartem 922912Sartem boolean_t 932912Sartem is_dos_extended(uchar_t id) 942912Sartem { 952912Sartem return ((id == EXTDOS) || (id == FDISK_EXTLBA)); 962912Sartem } 972912Sartem 982912Sartem struct part_find_s { 992912Sartem int num; 1002912Sartem int count; 1012912Sartem int systid; 1022912Sartem int r_systid; 103*7563SPrasad.Singamsetty@Sun.COM uint_t r_relsect; 104*7563SPrasad.Singamsetty@Sun.COM uint_t r_numsect; 1052912Sartem }; 1062912Sartem 1072912Sartem enum { WALK_CONTINUE, WALK_TERMINATE }; 1082912Sartem 1092912Sartem /* 1102912Sartem * Walk partition tables and invoke a callback for each. 1112912Sartem */ 1122912Sartem static void 1136395Sartem walk_partitions(int fd, int startsec, uint_t secsz, 114*7563SPrasad.Singamsetty@Sun.COM int (*f)(void *, int, uint_t, uint_t), void *arg) 1152912Sartem { 1162912Sartem uint32_t buf[1024/4]; 1172912Sartem int bufsize = 1024; 1182912Sartem struct mboot *mboot = (struct mboot *)&buf[0]; 1192912Sartem struct ipart ipart[FD_NUMPART]; 120*7563SPrasad.Singamsetty@Sun.COM uint_t sec = startsec; 121*7563SPrasad.Singamsetty@Sun.COM uint_t lastsec = sec + 1; 122*7563SPrasad.Singamsetty@Sun.COM uint_t relsect; 1232912Sartem int ext = 0; 1242912Sartem int systid; 1252912Sartem boolean_t valid; 1262912Sartem int i; 1272912Sartem 1282912Sartem while (sec != lastsec) { 1296395Sartem if (pread(fd, buf, bufsize, (off_t)sec * secsz) != bufsize) { 1302912Sartem break; 1312912Sartem } 1322912Sartem lastsec = sec; 1332912Sartem if (ltohs(mboot->signature) != MBB_MAGIC) { 1342912Sartem break; 1352912Sartem } 1362912Sartem bcopy(mboot->parts, ipart, FD_NUMPART * sizeof (struct ipart)); 1372912Sartem 1382912Sartem for (i = 0; i < FD_NUMPART; i++) { 1392912Sartem systid = ipart[i].systid; 1402912Sartem relsect = sec + ltohi(ipart[i].relsect); 1412912Sartem if (systid == 0) { 1422912Sartem continue; 1432912Sartem } 1442912Sartem valid = B_TRUE; 1452912Sartem if (is_dos_extended(systid) && (sec == lastsec)) { 1462912Sartem sec = startsec + ltohi(ipart[i].relsect); 1472912Sartem if (ext++ == 0) { 1482912Sartem relsect = startsec = sec; 1492912Sartem } else { 1502912Sartem valid = B_FALSE; 1512912Sartem } 1522912Sartem } 1532912Sartem if (valid && f(arg, ipart[i].systid, relsect, 1542912Sartem ltohi(ipart[i].numsect)) == WALK_TERMINATE) { 1552912Sartem return; 1562912Sartem } 1572912Sartem } 1582912Sartem } 1592912Sartem } 1602912Sartem 1612912Sartem static int 162*7563SPrasad.Singamsetty@Sun.COM find_dos_drive_cb(void *arg, int systid, uint_t relsect, uint_t numsect) 1632912Sartem { 1642912Sartem struct part_find_s *p = arg; 1652912Sartem 1662912Sartem if (is_dos_drive(systid)) { 1672912Sartem if (++p->count == p->num) { 1682912Sartem p->r_relsect = relsect; 1692912Sartem p->r_numsect = numsect; 1702912Sartem p->r_systid = systid; 1712912Sartem return (WALK_TERMINATE); 1722912Sartem } 1732912Sartem } 1742912Sartem 1752912Sartem return (WALK_CONTINUE); 1762912Sartem } 1772912Sartem 1782912Sartem /* 1792912Sartem * Given a dos drive number, return its relative sector number, 1802912Sartem * number of sectors in partition and the system id. 1812912Sartem */ 1822912Sartem boolean_t 1836395Sartem find_dos_drive(int fd, int num, uint_t secsz, off_t *offset) 1842912Sartem { 1852912Sartem struct part_find_s p = { 0, 0, 0, 0, 0, 0 }; 1862912Sartem 1872912Sartem p.num = num; 1882912Sartem 1892912Sartem if (num > 0) { 1906395Sartem walk_partitions(fd, 0, secsz, find_dos_drive_cb, &p); 1912912Sartem if (p.count == num) { 1926395Sartem *offset = (off_t)p.r_relsect * secsz; 1932912Sartem return (B_TRUE); 1942912Sartem } 1952912Sartem } 1962912Sartem 1972912Sartem return (B_FALSE); 1982912Sartem } 1992912Sartem 2002912Sartem static int 201*7563SPrasad.Singamsetty@Sun.COM get_num_dos_drives_cb(void *arg, int systid, uint_t relsect, uint_t numsect) 2022912Sartem { 2032912Sartem if (is_dos_drive(systid)) { 2042912Sartem (*(int *)arg)++; 2052912Sartem } 2062912Sartem return (WALK_CONTINUE); 2072912Sartem } 2082912Sartem 2092912Sartem int 2106395Sartem get_num_dos_drives(int fd, uint_t secsz) 2112912Sartem { 2122912Sartem int count = 0; 2132912Sartem 2146395Sartem walk_partitions(fd, 0, secsz, get_num_dos_drives_cb, &count); 2152912Sartem 2162912Sartem return (count); 2172912Sartem } 2182912Sartem 2192912Sartem /* 2202912Sartem * Return true if all non-empty slices in vtoc have identical start/size and 2212912Sartem * are tagged backup/entire disk. 2222912Sartem */ 2232912Sartem boolean_t 224*7563SPrasad.Singamsetty@Sun.COM vtoc_one_slice_entire_disk(struct extvtoc *vtoc) 2252912Sartem { 2262912Sartem int i; 227*7563SPrasad.Singamsetty@Sun.COM struct extpartition *p; 228*7563SPrasad.Singamsetty@Sun.COM diskaddr_t prev_start; 229*7563SPrasad.Singamsetty@Sun.COM diskaddr_t prev_size; 2302912Sartem 2312912Sartem for (i = 0; i < vtoc->v_nparts; i++) { 2322912Sartem p = &vtoc->v_part[i]; 2332912Sartem if (p->p_size == 0) { 2342912Sartem continue; 2352912Sartem } 2362912Sartem if ((p->p_tag != V_BACKUP) && ((p->p_tag != V_UNASSIGNED))) { 2372912Sartem return (B_FALSE); 2382912Sartem } 2392912Sartem if ((i > 0) && 2402912Sartem ((p->p_start != prev_start) || (p->p_size != prev_size))) { 2412912Sartem return (B_FALSE); 2422912Sartem } 2432912Sartem prev_start = p->p_start; 2442912Sartem prev_size = p->p_size; 2452912Sartem } 2462912Sartem 2472912Sartem return (B_TRUE); 2482912Sartem } 249