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