1*2912Sartem /*************************************************************************** 2*2912Sartem * 3*2912Sartem * fsutils.c : filesystem utilities 4*2912Sartem * 5*2912Sartem * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 6*2912Sartem * Use is subject to license terms. 7*2912Sartem * 8*2912Sartem * Licensed under the Academic Free License version 2.1 9*2912Sartem * 10*2912Sartem **************************************************************************/ 11*2912Sartem 12*2912Sartem #pragma ident "%Z%%M% %I% %E% SMI" 13*2912Sartem 14*2912Sartem #ifdef HAVE_CONFIG_H 15*2912Sartem # include <config.h> 16*2912Sartem #endif 17*2912Sartem 18*2912Sartem #include <stdio.h> 19*2912Sartem #include <sys/types.h> 20*2912Sartem #include <sys/scsi/impl/uscsi.h> 21*2912Sartem #include <string.h> 22*2912Sartem #include <strings.h> 23*2912Sartem #include <ctype.h> 24*2912Sartem #include <unistd.h> 25*2912Sartem #include <stdlib.h> 26*2912Sartem #include <errno.h> 27*2912Sartem #include <fcntl.h> 28*2912Sartem #include <sys/dkio.h> 29*2912Sartem #include <libintl.h> 30*2912Sartem #include <sys/dktp/fdisk.h> 31*2912Sartem #include <sys/fs/pc_label.h> 32*2912Sartem 33*2912Sartem #include <libhal.h> 34*2912Sartem #include "fsutils.h" 35*2912Sartem 36*2912Sartem /* 37*2912Sartem * Separates dos notation device spec into device and drive number 38*2912Sartem */ 39*2912Sartem boolean_t 40*2912Sartem dos_to_dev(char *path, char **devpath, int *num) 41*2912Sartem { 42*2912Sartem char *p; 43*2912Sartem 44*2912Sartem if ((p = strrchr(path, ':')) == NULL) { 45*2912Sartem return (B_FALSE); 46*2912Sartem } 47*2912Sartem if ((*num = atoi(p + 1)) == 0) { 48*2912Sartem return (B_FALSE); 49*2912Sartem } 50*2912Sartem p[0] = '\0'; 51*2912Sartem *devpath = strdup(path); 52*2912Sartem p[0] = ':'; 53*2912Sartem return (*devpath != NULL); 54*2912Sartem } 55*2912Sartem 56*2912Sartem char * 57*2912Sartem get_slice_name (char *devlink) 58*2912Sartem { 59*2912Sartem char *part, *slice, *disk; 60*2912Sartem char *s = NULL; 61*2912Sartem char *p; 62*2912Sartem 63*2912Sartem if ((p = strstr(devlink, "/lofi/")) != 0) { 64*2912Sartem return (p + sizeof ("/lofi/") - 1); 65*2912Sartem } 66*2912Sartem 67*2912Sartem part = strrchr(devlink, 'p'); 68*2912Sartem slice = strrchr(devlink, 's'); 69*2912Sartem disk = strrchr(devlink, 'd'); 70*2912Sartem 71*2912Sartem if ((part != NULL) && (part > slice) && (part > disk)) { 72*2912Sartem s = part; 73*2912Sartem } else if ((slice != NULL) && (slice > disk)) { 74*2912Sartem s = slice; 75*2912Sartem } else { 76*2912Sartem s = disk; 77*2912Sartem } 78*2912Sartem if ((s != NULL) && isdigit(s[1])) { 79*2912Sartem return (s); 80*2912Sartem } else { 81*2912Sartem return (""); 82*2912Sartem } 83*2912Sartem } 84*2912Sartem 85*2912Sartem boolean_t 86*2912Sartem is_dos_drive(uchar_t type) 87*2912Sartem { 88*2912Sartem return ((type == 1) || (type == 4) || (type == 5) || (type == 6) || 89*2912Sartem ((type >= 8) && (type <= 0xf))); 90*2912Sartem } 91*2912Sartem 92*2912Sartem boolean_t 93*2912Sartem is_dos_extended(uchar_t id) 94*2912Sartem { 95*2912Sartem return ((id == EXTDOS) || (id == FDISK_EXTLBA)); 96*2912Sartem } 97*2912Sartem 98*2912Sartem struct part_find_s { 99*2912Sartem int num; 100*2912Sartem int count; 101*2912Sartem int systid; 102*2912Sartem int r_systid; 103*2912Sartem int r_relsect; 104*2912Sartem int r_numsect; 105*2912Sartem }; 106*2912Sartem 107*2912Sartem enum { WALK_CONTINUE, WALK_TERMINATE }; 108*2912Sartem 109*2912Sartem /* 110*2912Sartem * Walk partition tables and invoke a callback for each. 111*2912Sartem */ 112*2912Sartem static void 113*2912Sartem walk_partitions(int fd, int startsec, int (*f)(void *, int, int, int), 114*2912Sartem void *arg) 115*2912Sartem { 116*2912Sartem uint32_t buf[1024/4]; 117*2912Sartem int bufsize = 1024; 118*2912Sartem struct mboot *mboot = (struct mboot *)&buf[0]; 119*2912Sartem struct ipart ipart[FD_NUMPART]; 120*2912Sartem int sec = startsec; 121*2912Sartem int lastsec = sec + 1; 122*2912Sartem int relsect; 123*2912Sartem int ext = 0; 124*2912Sartem int systid; 125*2912Sartem boolean_t valid; 126*2912Sartem int i; 127*2912Sartem 128*2912Sartem while (sec != lastsec) { 129*2912Sartem if (pread(fd, buf, bufsize, (off_t)sec * 512) != bufsize) { 130*2912Sartem break; 131*2912Sartem } 132*2912Sartem lastsec = sec; 133*2912Sartem if (ltohs(mboot->signature) != MBB_MAGIC) { 134*2912Sartem break; 135*2912Sartem } 136*2912Sartem bcopy(mboot->parts, ipart, FD_NUMPART * sizeof (struct ipart)); 137*2912Sartem 138*2912Sartem for (i = 0; i < FD_NUMPART; i++) { 139*2912Sartem systid = ipart[i].systid; 140*2912Sartem relsect = sec + ltohi(ipart[i].relsect); 141*2912Sartem if (systid == 0) { 142*2912Sartem continue; 143*2912Sartem } 144*2912Sartem valid = B_TRUE; 145*2912Sartem if (is_dos_extended(systid) && (sec == lastsec)) { 146*2912Sartem sec = startsec + ltohi(ipart[i].relsect); 147*2912Sartem if (ext++ == 0) { 148*2912Sartem relsect = startsec = sec; 149*2912Sartem } else { 150*2912Sartem valid = B_FALSE; 151*2912Sartem } 152*2912Sartem } 153*2912Sartem if (valid && f(arg, ipart[i].systid, relsect, 154*2912Sartem ltohi(ipart[i].numsect)) == WALK_TERMINATE) { 155*2912Sartem return; 156*2912Sartem } 157*2912Sartem } 158*2912Sartem } 159*2912Sartem } 160*2912Sartem 161*2912Sartem static int 162*2912Sartem find_dos_drive_cb(void *arg, int systid, int relsect, int numsect) 163*2912Sartem { 164*2912Sartem struct part_find_s *p = arg; 165*2912Sartem 166*2912Sartem if (is_dos_drive(systid)) { 167*2912Sartem if (++p->count == p->num) { 168*2912Sartem p->r_relsect = relsect; 169*2912Sartem p->r_numsect = numsect; 170*2912Sartem p->r_systid = systid; 171*2912Sartem return (WALK_TERMINATE); 172*2912Sartem } 173*2912Sartem } 174*2912Sartem 175*2912Sartem return (WALK_CONTINUE); 176*2912Sartem } 177*2912Sartem 178*2912Sartem /* 179*2912Sartem * Given a dos drive number, return its relative sector number, 180*2912Sartem * number of sectors in partition and the system id. 181*2912Sartem */ 182*2912Sartem boolean_t 183*2912Sartem find_dos_drive(int fd, int num, int *relsect, int *numsect, int *systid) 184*2912Sartem { 185*2912Sartem struct part_find_s p = { 0, 0, 0, 0, 0, 0 }; 186*2912Sartem 187*2912Sartem p.num = num; 188*2912Sartem 189*2912Sartem if (num > 0) { 190*2912Sartem walk_partitions(fd, 0, find_dos_drive_cb, &p); 191*2912Sartem if (p.count == num) { 192*2912Sartem *relsect = p.r_relsect; 193*2912Sartem *numsect = p.r_numsect; 194*2912Sartem *systid = p.r_systid; 195*2912Sartem return (B_TRUE); 196*2912Sartem } 197*2912Sartem } 198*2912Sartem 199*2912Sartem return (B_FALSE); 200*2912Sartem } 201*2912Sartem 202*2912Sartem static int 203*2912Sartem get_num_dos_drives_cb(void *arg, int systid, int relsect, int numsect) 204*2912Sartem { 205*2912Sartem if (is_dos_drive(systid)) { 206*2912Sartem (*(int *)arg)++; 207*2912Sartem } 208*2912Sartem return (WALK_CONTINUE); 209*2912Sartem } 210*2912Sartem 211*2912Sartem int 212*2912Sartem get_num_dos_drives(int fd) 213*2912Sartem { 214*2912Sartem int count = 0; 215*2912Sartem 216*2912Sartem walk_partitions(fd, 0, get_num_dos_drives_cb, &count); 217*2912Sartem 218*2912Sartem return (count); 219*2912Sartem } 220*2912Sartem 221*2912Sartem /* 222*2912Sartem * Return true if all non-empty slices in vtoc have identical start/size and 223*2912Sartem * are tagged backup/entire disk. 224*2912Sartem */ 225*2912Sartem boolean_t 226*2912Sartem vtoc_one_slice_entire_disk(struct vtoc *vtoc) 227*2912Sartem { 228*2912Sartem int i; 229*2912Sartem struct partition *p; 230*2912Sartem daddr_t prev_start; 231*2912Sartem long prev_size; 232*2912Sartem 233*2912Sartem for (i = 0; i < vtoc->v_nparts; i++) { 234*2912Sartem p = &vtoc->v_part[i]; 235*2912Sartem if (p->p_size == 0) { 236*2912Sartem continue; 237*2912Sartem } 238*2912Sartem if ((p->p_tag != V_BACKUP) && ((p->p_tag != V_UNASSIGNED))) { 239*2912Sartem return (B_FALSE); 240*2912Sartem } 241*2912Sartem if ((i > 0) && 242*2912Sartem ((p->p_start != prev_start) || (p->p_size != prev_size))) { 243*2912Sartem return (B_FALSE); 244*2912Sartem } 245*2912Sartem prev_start = p->p_start; 246*2912Sartem prev_size = p->p_size; 247*2912Sartem } 248*2912Sartem 249*2912Sartem return (B_TRUE); 250*2912Sartem } 251