118c2aff7Sartem /*************************************************************************** 218c2aff7Sartem * 318c2aff7Sartem * fsutils.c : filesystem utilities 418c2aff7Sartem * 5*422ee277Sartem * 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 * 1018c2aff7Sartem **************************************************************************/ 1118c2aff7Sartem 1292f38132Sartem #pragma ident "%Z%%M% %I% %E% SMI" 1318c2aff7Sartem 1418c2aff7Sartem #ifdef HAVE_CONFIG_H 1518c2aff7Sartem # include <config.h> 1618c2aff7Sartem #endif 1718c2aff7Sartem 1818c2aff7Sartem #include <stdio.h> 1918c2aff7Sartem #include <sys/types.h> 2018c2aff7Sartem #include <sys/scsi/impl/uscsi.h> 2118c2aff7Sartem #include <string.h> 2218c2aff7Sartem #include <strings.h> 2318c2aff7Sartem #include <ctype.h> 2418c2aff7Sartem #include <unistd.h> 2518c2aff7Sartem #include <stdlib.h> 2618c2aff7Sartem #include <errno.h> 2718c2aff7Sartem #include <fcntl.h> 2818c2aff7Sartem #include <sys/dkio.h> 2918c2aff7Sartem #include <libintl.h> 3018c2aff7Sartem #include <sys/dktp/fdisk.h> 3118c2aff7Sartem #include <sys/fs/pc_label.h> 3218c2aff7Sartem 3318c2aff7Sartem #include <libhal.h> 3418c2aff7Sartem #include "fsutils.h" 3518c2aff7Sartem 3618c2aff7Sartem /* 3718c2aff7Sartem * Separates dos notation device spec into device and drive number 3818c2aff7Sartem */ 3918c2aff7Sartem boolean_t 4018c2aff7Sartem dos_to_dev(char *path, char **devpath, int *num) 4118c2aff7Sartem { 4218c2aff7Sartem char *p; 4318c2aff7Sartem 4418c2aff7Sartem if ((p = strrchr(path, ':')) == NULL) { 4518c2aff7Sartem return (B_FALSE); 4618c2aff7Sartem } 4718c2aff7Sartem if ((*num = atoi(p + 1)) == 0) { 4818c2aff7Sartem return (B_FALSE); 4918c2aff7Sartem } 5018c2aff7Sartem p[0] = '\0'; 5118c2aff7Sartem *devpath = strdup(path); 5218c2aff7Sartem p[0] = ':'; 5318c2aff7Sartem return (*devpath != NULL); 5418c2aff7Sartem } 5518c2aff7Sartem 5618c2aff7Sartem char * 5718c2aff7Sartem get_slice_name (char *devlink) 5818c2aff7Sartem { 5918c2aff7Sartem char *part, *slice, *disk; 6018c2aff7Sartem char *s = NULL; 6118c2aff7Sartem char *p; 6218c2aff7Sartem 6318c2aff7Sartem if ((p = strstr(devlink, "/lofi/")) != 0) { 6418c2aff7Sartem return (p + sizeof ("/lofi/") - 1); 6518c2aff7Sartem } 6618c2aff7Sartem 6718c2aff7Sartem part = strrchr(devlink, 'p'); 6818c2aff7Sartem slice = strrchr(devlink, 's'); 6918c2aff7Sartem disk = strrchr(devlink, 'd'); 7018c2aff7Sartem 7118c2aff7Sartem if ((part != NULL) && (part > slice) && (part > disk)) { 7218c2aff7Sartem s = part; 7318c2aff7Sartem } else if ((slice != NULL) && (slice > disk)) { 7418c2aff7Sartem s = slice; 7518c2aff7Sartem } else { 7618c2aff7Sartem s = disk; 7718c2aff7Sartem } 7818c2aff7Sartem if ((s != NULL) && isdigit(s[1])) { 7918c2aff7Sartem return (s); 8018c2aff7Sartem } else { 8118c2aff7Sartem return (""); 8218c2aff7Sartem } 8318c2aff7Sartem } 8418c2aff7Sartem 8518c2aff7Sartem boolean_t 8618c2aff7Sartem is_dos_drive(uchar_t type) 8718c2aff7Sartem { 88e5d31070Sartem return ((type == DOSOS12) || (type == DOSOS16) || 89e5d31070Sartem (type == DOSHUGE) || (type == FDISK_WINDOWS) || 90e5d31070Sartem (type == FDISK_EXT_WIN) || (type == FDISK_FAT95) || 91e5d31070Sartem (type == DIAGPART)); 9218c2aff7Sartem } 9318c2aff7Sartem 9418c2aff7Sartem boolean_t 9518c2aff7Sartem is_dos_extended(uchar_t id) 9618c2aff7Sartem { 9718c2aff7Sartem return ((id == EXTDOS) || (id == FDISK_EXTLBA)); 9818c2aff7Sartem } 9918c2aff7Sartem 10018c2aff7Sartem struct part_find_s { 10118c2aff7Sartem int num; 10218c2aff7Sartem int count; 10318c2aff7Sartem int systid; 10418c2aff7Sartem int r_systid; 10518c2aff7Sartem int r_relsect; 10618c2aff7Sartem int r_numsect; 10718c2aff7Sartem }; 10818c2aff7Sartem 10918c2aff7Sartem enum { WALK_CONTINUE, WALK_TERMINATE }; 11018c2aff7Sartem 11118c2aff7Sartem /* 11218c2aff7Sartem * Walk partition tables and invoke a callback for each. 11318c2aff7Sartem */ 11418c2aff7Sartem static void 115*422ee277Sartem walk_partitions(int fd, int startsec, uint_t secsz, 116*422ee277Sartem int (*f)(void *, int, int, int), void *arg) 11718c2aff7Sartem { 11818c2aff7Sartem uint32_t buf[1024/4]; 11918c2aff7Sartem int bufsize = 1024; 12018c2aff7Sartem struct mboot *mboot = (struct mboot *)&buf[0]; 12118c2aff7Sartem struct ipart ipart[FD_NUMPART]; 12218c2aff7Sartem int sec = startsec; 12318c2aff7Sartem int lastsec = sec + 1; 12418c2aff7Sartem int relsect; 12518c2aff7Sartem int ext = 0; 12618c2aff7Sartem int systid; 12718c2aff7Sartem boolean_t valid; 12818c2aff7Sartem int i; 12918c2aff7Sartem 13018c2aff7Sartem while (sec != lastsec) { 131*422ee277Sartem if (pread(fd, buf, bufsize, (off_t)sec * secsz) != bufsize) { 13218c2aff7Sartem break; 13318c2aff7Sartem } 13418c2aff7Sartem lastsec = sec; 13518c2aff7Sartem if (ltohs(mboot->signature) != MBB_MAGIC) { 13618c2aff7Sartem break; 13718c2aff7Sartem } 13818c2aff7Sartem bcopy(mboot->parts, ipart, FD_NUMPART * sizeof (struct ipart)); 13918c2aff7Sartem 14018c2aff7Sartem for (i = 0; i < FD_NUMPART; i++) { 14118c2aff7Sartem systid = ipart[i].systid; 14218c2aff7Sartem relsect = sec + ltohi(ipart[i].relsect); 14318c2aff7Sartem if (systid == 0) { 14418c2aff7Sartem continue; 14518c2aff7Sartem } 14618c2aff7Sartem valid = B_TRUE; 14718c2aff7Sartem if (is_dos_extended(systid) && (sec == lastsec)) { 14818c2aff7Sartem sec = startsec + ltohi(ipart[i].relsect); 14918c2aff7Sartem if (ext++ == 0) { 15018c2aff7Sartem relsect = startsec = sec; 15118c2aff7Sartem } else { 15218c2aff7Sartem valid = B_FALSE; 15318c2aff7Sartem } 15418c2aff7Sartem } 15518c2aff7Sartem if (valid && f(arg, ipart[i].systid, relsect, 15618c2aff7Sartem ltohi(ipart[i].numsect)) == WALK_TERMINATE) { 15718c2aff7Sartem return; 15818c2aff7Sartem } 15918c2aff7Sartem } 16018c2aff7Sartem } 16118c2aff7Sartem } 16218c2aff7Sartem 16318c2aff7Sartem static int 16418c2aff7Sartem find_dos_drive_cb(void *arg, int systid, int relsect, int numsect) 16518c2aff7Sartem { 16618c2aff7Sartem struct part_find_s *p = arg; 16718c2aff7Sartem 16818c2aff7Sartem if (is_dos_drive(systid)) { 16918c2aff7Sartem if (++p->count == p->num) { 17018c2aff7Sartem p->r_relsect = relsect; 17118c2aff7Sartem p->r_numsect = numsect; 17218c2aff7Sartem p->r_systid = systid; 17318c2aff7Sartem return (WALK_TERMINATE); 17418c2aff7Sartem } 17518c2aff7Sartem } 17618c2aff7Sartem 17718c2aff7Sartem return (WALK_CONTINUE); 17818c2aff7Sartem } 17918c2aff7Sartem 18018c2aff7Sartem /* 18118c2aff7Sartem * Given a dos drive number, return its relative sector number, 18218c2aff7Sartem * number of sectors in partition and the system id. 18318c2aff7Sartem */ 18418c2aff7Sartem boolean_t 185*422ee277Sartem find_dos_drive(int fd, int num, uint_t secsz, off_t *offset) 18618c2aff7Sartem { 18718c2aff7Sartem struct part_find_s p = { 0, 0, 0, 0, 0, 0 }; 18818c2aff7Sartem 18918c2aff7Sartem p.num = num; 19018c2aff7Sartem 19118c2aff7Sartem if (num > 0) { 192*422ee277Sartem walk_partitions(fd, 0, secsz, find_dos_drive_cb, &p); 19318c2aff7Sartem if (p.count == num) { 194*422ee277Sartem *offset = (off_t)p.r_relsect * secsz; 19518c2aff7Sartem return (B_TRUE); 19618c2aff7Sartem } 19718c2aff7Sartem } 19818c2aff7Sartem 19918c2aff7Sartem return (B_FALSE); 20018c2aff7Sartem } 20118c2aff7Sartem 20218c2aff7Sartem static int 20318c2aff7Sartem get_num_dos_drives_cb(void *arg, int systid, int relsect, int numsect) 20418c2aff7Sartem { 20518c2aff7Sartem if (is_dos_drive(systid)) { 20618c2aff7Sartem (*(int *)arg)++; 20718c2aff7Sartem } 20818c2aff7Sartem return (WALK_CONTINUE); 20918c2aff7Sartem } 21018c2aff7Sartem 21118c2aff7Sartem int 212*422ee277Sartem get_num_dos_drives(int fd, uint_t secsz) 21318c2aff7Sartem { 21418c2aff7Sartem int count = 0; 21518c2aff7Sartem 216*422ee277Sartem walk_partitions(fd, 0, secsz, get_num_dos_drives_cb, &count); 21718c2aff7Sartem 21818c2aff7Sartem return (count); 21918c2aff7Sartem } 22018c2aff7Sartem 22118c2aff7Sartem /* 22218c2aff7Sartem * Return true if all non-empty slices in vtoc have identical start/size and 22318c2aff7Sartem * are tagged backup/entire disk. 22418c2aff7Sartem */ 22518c2aff7Sartem boolean_t 22618c2aff7Sartem vtoc_one_slice_entire_disk(struct vtoc *vtoc) 22718c2aff7Sartem { 22818c2aff7Sartem int i; 22918c2aff7Sartem struct partition *p; 23018c2aff7Sartem daddr_t prev_start; 23118c2aff7Sartem long prev_size; 23218c2aff7Sartem 23318c2aff7Sartem for (i = 0; i < vtoc->v_nparts; i++) { 23418c2aff7Sartem p = &vtoc->v_part[i]; 23518c2aff7Sartem if (p->p_size == 0) { 23618c2aff7Sartem continue; 23718c2aff7Sartem } 23818c2aff7Sartem if ((p->p_tag != V_BACKUP) && ((p->p_tag != V_UNASSIGNED))) { 23918c2aff7Sartem return (B_FALSE); 24018c2aff7Sartem } 24118c2aff7Sartem if ((i > 0) && 24218c2aff7Sartem ((p->p_start != prev_start) || (p->p_size != prev_size))) { 24318c2aff7Sartem return (B_FALSE); 24418c2aff7Sartem } 24518c2aff7Sartem prev_start = p->p_start; 24618c2aff7Sartem prev_size = p->p_size; 24718c2aff7Sartem } 24818c2aff7Sartem 24918c2aff7Sartem return (B_TRUE); 25018c2aff7Sartem } 251