1*342440ecSPrasad Singamsetty /* 218c2aff7Sartem * 318c2aff7Sartem * fsutils.c : filesystem utilities 418c2aff7Sartem * 5422ee277Sartem * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 618c2aff7Sartem * Use is subject to license terms. 718c2aff7Sartem * 818c2aff7Sartem * Licensed under the Academic Free License version 2.1 918c2aff7Sartem * 10*342440ecSPrasad Singamsetty */ 1118c2aff7Sartem 1218c2aff7Sartem #ifdef HAVE_CONFIG_H 1318c2aff7Sartem #include <config.h> 1418c2aff7Sartem #endif 1518c2aff7Sartem 1618c2aff7Sartem #include <stdio.h> 1718c2aff7Sartem #include <sys/types.h> 1818c2aff7Sartem #include <sys/scsi/impl/uscsi.h> 1918c2aff7Sartem #include <string.h> 2018c2aff7Sartem #include <strings.h> 2118c2aff7Sartem #include <ctype.h> 2218c2aff7Sartem #include <unistd.h> 2318c2aff7Sartem #include <stdlib.h> 2418c2aff7Sartem #include <errno.h> 2518c2aff7Sartem #include <fcntl.h> 2618c2aff7Sartem #include <sys/dkio.h> 2718c2aff7Sartem #include <libintl.h> 2818c2aff7Sartem #include <sys/dktp/fdisk.h> 2918c2aff7Sartem #include <sys/fs/pc_label.h> 3018c2aff7Sartem 3118c2aff7Sartem #include <libhal.h> 3218c2aff7Sartem #include "fsutils.h" 3318c2aff7Sartem 3418c2aff7Sartem /* 3518c2aff7Sartem * Separates dos notation device spec into device and drive number 3618c2aff7Sartem */ 3718c2aff7Sartem boolean_t 3818c2aff7Sartem dos_to_dev(char *path, char **devpath, int *num) 3918c2aff7Sartem { 4018c2aff7Sartem char *p; 4118c2aff7Sartem 4218c2aff7Sartem if ((p = strrchr(path, ':')) == NULL) { 4318c2aff7Sartem return (B_FALSE); 4418c2aff7Sartem } 4518c2aff7Sartem if ((*num = atoi(p + 1)) == 0) { 4618c2aff7Sartem return (B_FALSE); 4718c2aff7Sartem } 4818c2aff7Sartem p[0] = '\0'; 4918c2aff7Sartem *devpath = strdup(path); 5018c2aff7Sartem p[0] = ':'; 5118c2aff7Sartem return (*devpath != NULL); 5218c2aff7Sartem } 5318c2aff7Sartem 5418c2aff7Sartem char * 5518c2aff7Sartem get_slice_name(char *devlink) 5618c2aff7Sartem { 5718c2aff7Sartem char *part, *slice, *disk; 5818c2aff7Sartem char *s = NULL; 5918c2aff7Sartem char *p; 6018c2aff7Sartem 6118c2aff7Sartem if ((p = strstr(devlink, "/lofi/")) != 0) { 6218c2aff7Sartem return (p + sizeof ("/lofi/") - 1); 6318c2aff7Sartem } 6418c2aff7Sartem 6518c2aff7Sartem part = strrchr(devlink, 'p'); 6618c2aff7Sartem slice = strrchr(devlink, 's'); 6718c2aff7Sartem disk = strrchr(devlink, 'd'); 6818c2aff7Sartem 6918c2aff7Sartem if ((part != NULL) && (part > slice) && (part > disk)) { 7018c2aff7Sartem s = part; 7118c2aff7Sartem } else if ((slice != NULL) && (slice > disk)) { 7218c2aff7Sartem s = slice; 7318c2aff7Sartem } else { 7418c2aff7Sartem s = disk; 7518c2aff7Sartem } 7618c2aff7Sartem if ((s != NULL) && isdigit(s[1])) { 7718c2aff7Sartem return (s); 7818c2aff7Sartem } else { 7918c2aff7Sartem return (""); 8018c2aff7Sartem } 8118c2aff7Sartem } 8218c2aff7Sartem 8318c2aff7Sartem boolean_t 8418c2aff7Sartem is_dos_drive(uchar_t type) 8518c2aff7Sartem { 86e5d31070Sartem return ((type == DOSOS12) || (type == DOSOS16) || 87e5d31070Sartem (type == DOSHUGE) || (type == FDISK_WINDOWS) || 88e5d31070Sartem (type == FDISK_EXT_WIN) || (type == FDISK_FAT95) || 89e5d31070Sartem (type == DIAGPART)); 9018c2aff7Sartem } 9118c2aff7Sartem 9218c2aff7Sartem boolean_t 9318c2aff7Sartem is_dos_extended(uchar_t id) 9418c2aff7Sartem { 9518c2aff7Sartem return ((id == EXTDOS) || (id == FDISK_EXTLBA)); 9618c2aff7Sartem } 9718c2aff7Sartem 9818c2aff7Sartem struct part_find_s { 9918c2aff7Sartem int num; 10018c2aff7Sartem int count; 10118c2aff7Sartem int systid; 10218c2aff7Sartem int r_systid; 103*342440ecSPrasad Singamsetty uint_t r_relsect; 104*342440ecSPrasad Singamsetty uint_t r_numsect; 10518c2aff7Sartem }; 10618c2aff7Sartem 10718c2aff7Sartem enum { WALK_CONTINUE, WALK_TERMINATE }; 10818c2aff7Sartem 10918c2aff7Sartem /* 11018c2aff7Sartem * Walk partition tables and invoke a callback for each. 11118c2aff7Sartem */ 11218c2aff7Sartem static void 113422ee277Sartem walk_partitions(int fd, int startsec, uint_t secsz, 114*342440ecSPrasad Singamsetty int (*f)(void *, int, uint_t, uint_t), void *arg) 11518c2aff7Sartem { 11618c2aff7Sartem uint32_t buf[1024/4]; 11718c2aff7Sartem int bufsize = 1024; 11818c2aff7Sartem struct mboot *mboot = (struct mboot *)&buf[0]; 11918c2aff7Sartem struct ipart ipart[FD_NUMPART]; 120*342440ecSPrasad Singamsetty uint_t sec = startsec; 121*342440ecSPrasad Singamsetty uint_t lastsec = sec + 1; 122*342440ecSPrasad Singamsetty uint_t relsect; 12318c2aff7Sartem int ext = 0; 12418c2aff7Sartem int systid; 12518c2aff7Sartem boolean_t valid; 12618c2aff7Sartem int i; 12718c2aff7Sartem 12818c2aff7Sartem while (sec != lastsec) { 129422ee277Sartem if (pread(fd, buf, bufsize, (off_t)sec * secsz) != bufsize) { 13018c2aff7Sartem break; 13118c2aff7Sartem } 13218c2aff7Sartem lastsec = sec; 13318c2aff7Sartem if (ltohs(mboot->signature) != MBB_MAGIC) { 13418c2aff7Sartem break; 13518c2aff7Sartem } 13618c2aff7Sartem bcopy(mboot->parts, ipart, FD_NUMPART * sizeof (struct ipart)); 13718c2aff7Sartem 13818c2aff7Sartem for (i = 0; i < FD_NUMPART; i++) { 13918c2aff7Sartem systid = ipart[i].systid; 14018c2aff7Sartem relsect = sec + ltohi(ipart[i].relsect); 14118c2aff7Sartem if (systid == 0) { 14218c2aff7Sartem continue; 14318c2aff7Sartem } 14418c2aff7Sartem valid = B_TRUE; 14518c2aff7Sartem if (is_dos_extended(systid) && (sec == lastsec)) { 14618c2aff7Sartem sec = startsec + ltohi(ipart[i].relsect); 14718c2aff7Sartem if (ext++ == 0) { 14818c2aff7Sartem relsect = startsec = sec; 14918c2aff7Sartem } else { 15018c2aff7Sartem valid = B_FALSE; 15118c2aff7Sartem } 15218c2aff7Sartem } 15318c2aff7Sartem if (valid && f(arg, ipart[i].systid, relsect, 15418c2aff7Sartem ltohi(ipart[i].numsect)) == WALK_TERMINATE) { 15518c2aff7Sartem return; 15618c2aff7Sartem } 15718c2aff7Sartem } 15818c2aff7Sartem } 15918c2aff7Sartem } 16018c2aff7Sartem 16118c2aff7Sartem static int 162*342440ecSPrasad Singamsetty find_dos_drive_cb(void *arg, int systid, uint_t relsect, uint_t numsect) 16318c2aff7Sartem { 16418c2aff7Sartem struct part_find_s *p = arg; 16518c2aff7Sartem 16618c2aff7Sartem if (is_dos_drive(systid)) { 16718c2aff7Sartem if (++p->count == p->num) { 16818c2aff7Sartem p->r_relsect = relsect; 16918c2aff7Sartem p->r_numsect = numsect; 17018c2aff7Sartem p->r_systid = systid; 17118c2aff7Sartem return (WALK_TERMINATE); 17218c2aff7Sartem } 17318c2aff7Sartem } 17418c2aff7Sartem 17518c2aff7Sartem return (WALK_CONTINUE); 17618c2aff7Sartem } 17718c2aff7Sartem 17818c2aff7Sartem /* 17918c2aff7Sartem * Given a dos drive number, return its relative sector number, 18018c2aff7Sartem * number of sectors in partition and the system id. 18118c2aff7Sartem */ 18218c2aff7Sartem boolean_t 183422ee277Sartem find_dos_drive(int fd, int num, uint_t secsz, off_t *offset) 18418c2aff7Sartem { 18518c2aff7Sartem struct part_find_s p = { 0, 0, 0, 0, 0, 0 }; 18618c2aff7Sartem 18718c2aff7Sartem p.num = num; 18818c2aff7Sartem 18918c2aff7Sartem if (num > 0) { 190422ee277Sartem walk_partitions(fd, 0, secsz, find_dos_drive_cb, &p); 19118c2aff7Sartem if (p.count == num) { 192422ee277Sartem *offset = (off_t)p.r_relsect * secsz; 19318c2aff7Sartem return (B_TRUE); 19418c2aff7Sartem } 19518c2aff7Sartem } 19618c2aff7Sartem 19718c2aff7Sartem return (B_FALSE); 19818c2aff7Sartem } 19918c2aff7Sartem 20018c2aff7Sartem static int 201*342440ecSPrasad Singamsetty get_num_dos_drives_cb(void *arg, int systid, uint_t relsect, uint_t numsect) 20218c2aff7Sartem { 20318c2aff7Sartem if (is_dos_drive(systid)) { 20418c2aff7Sartem (*(int *)arg)++; 20518c2aff7Sartem } 20618c2aff7Sartem return (WALK_CONTINUE); 20718c2aff7Sartem } 20818c2aff7Sartem 20918c2aff7Sartem int 210422ee277Sartem get_num_dos_drives(int fd, uint_t secsz) 21118c2aff7Sartem { 21218c2aff7Sartem int count = 0; 21318c2aff7Sartem 214422ee277Sartem walk_partitions(fd, 0, secsz, get_num_dos_drives_cb, &count); 21518c2aff7Sartem 21618c2aff7Sartem return (count); 21718c2aff7Sartem } 21818c2aff7Sartem 21918c2aff7Sartem /* 22018c2aff7Sartem * Return true if all non-empty slices in vtoc have identical start/size and 22118c2aff7Sartem * are tagged backup/entire disk. 22218c2aff7Sartem */ 22318c2aff7Sartem boolean_t 224*342440ecSPrasad Singamsetty vtoc_one_slice_entire_disk(struct extvtoc *vtoc) 22518c2aff7Sartem { 22618c2aff7Sartem int i; 227*342440ecSPrasad Singamsetty struct extpartition *p; 228*342440ecSPrasad Singamsetty diskaddr_t prev_start; 229*342440ecSPrasad Singamsetty diskaddr_t prev_size; 23018c2aff7Sartem 23118c2aff7Sartem for (i = 0; i < vtoc->v_nparts; i++) { 23218c2aff7Sartem p = &vtoc->v_part[i]; 23318c2aff7Sartem if (p->p_size == 0) { 23418c2aff7Sartem continue; 23518c2aff7Sartem } 23618c2aff7Sartem if ((p->p_tag != V_BACKUP) && ((p->p_tag != V_UNASSIGNED))) { 23718c2aff7Sartem return (B_FALSE); 23818c2aff7Sartem } 23918c2aff7Sartem if ((i > 0) && 24018c2aff7Sartem ((p->p_start != prev_start) || (p->p_size != prev_size))) { 24118c2aff7Sartem return (B_FALSE); 24218c2aff7Sartem } 24318c2aff7Sartem prev_start = p->p_start; 24418c2aff7Sartem prev_size = p->p_size; 24518c2aff7Sartem } 24618c2aff7Sartem 24718c2aff7Sartem return (B_TRUE); 24818c2aff7Sartem } 249