xref: /onnv-gate/usr/src/cmd/hal/utils/fsutils.c (revision 7563:84ec90ffc3f7)
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
dos_to_dev(char * path,char ** devpath,int * num)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 *
get_slice_name(char * devlink)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
is_dos_drive(uchar_t type)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
is_dos_extended(uchar_t id)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
walk_partitions(int fd,int startsec,uint_t secsz,int (* f)(void *,int,uint_t,uint_t),void * arg)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
find_dos_drive_cb(void * arg,int systid,uint_t relsect,uint_t numsect)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
find_dos_drive(int fd,int num,uint_t secsz,off_t * offset)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
get_num_dos_drives_cb(void * arg,int systid,uint_t relsect,uint_t numsect)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
get_num_dos_drives(int fd,uint_t secsz)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
vtoc_one_slice_entire_disk(struct extvtoc * vtoc)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