xref: /onnv-gate/usr/src/cmd/hal/utils/fsutils.c (revision 6395)
12912Sartem /***************************************************************************
22912Sartem  *
32912Sartem  * fsutils.c : filesystem utilities
42912Sartem  *
5*6395Sartem  * 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  *
102912Sartem  **************************************************************************/
112912Sartem 
122916Sartem #pragma ident	"%Z%%M%	%I%	%E% SMI"
132912Sartem 
142912Sartem #ifdef HAVE_CONFIG_H
152912Sartem #  include <config.h>
162912Sartem #endif
172912Sartem 
182912Sartem #include <stdio.h>
192912Sartem #include <sys/types.h>
202912Sartem #include <sys/scsi/impl/uscsi.h>
212912Sartem #include <string.h>
222912Sartem #include <strings.h>
232912Sartem #include <ctype.h>
242912Sartem #include <unistd.h>
252912Sartem #include <stdlib.h>
262912Sartem #include <errno.h>
272912Sartem #include <fcntl.h>
282912Sartem #include <sys/dkio.h>
292912Sartem #include <libintl.h>
302912Sartem #include <sys/dktp/fdisk.h>
312912Sartem #include <sys/fs/pc_label.h>
322912Sartem 
332912Sartem #include <libhal.h>
342912Sartem #include "fsutils.h"
352912Sartem 
362912Sartem /*
372912Sartem  * Separates dos notation device spec into device and drive number
382912Sartem  */
392912Sartem boolean_t
402912Sartem dos_to_dev(char *path, char **devpath, int *num)
412912Sartem {
422912Sartem 	char *p;
432912Sartem 
442912Sartem 	if ((p = strrchr(path, ':')) == NULL) {
452912Sartem 		return (B_FALSE);
462912Sartem 	}
472912Sartem 	if ((*num = atoi(p + 1)) == 0) {
482912Sartem 		return (B_FALSE);
492912Sartem 	}
502912Sartem 	p[0] = '\0';
512912Sartem 	*devpath = strdup(path);
522912Sartem 	p[0] = ':';
532912Sartem 	return (*devpath != NULL);
542912Sartem }
552912Sartem 
562912Sartem char *
572912Sartem get_slice_name (char *devlink)
582912Sartem {
592912Sartem 	char	*part, *slice, *disk;
602912Sartem 	char	*s = NULL;
612912Sartem 	char	*p;
622912Sartem 
632912Sartem 	if ((p = strstr(devlink, "/lofi/")) != 0) {
642912Sartem 		return (p + sizeof ("/lofi/") - 1);
652912Sartem 	}
662912Sartem 
672912Sartem 	part = strrchr(devlink, 'p');
682912Sartem 	slice = strrchr(devlink, 's');
692912Sartem 	disk = strrchr(devlink, 'd');
702912Sartem 
712912Sartem 	if ((part != NULL) && (part > slice) && (part > disk)) {
722912Sartem 		s = part;
732912Sartem 	} else if ((slice != NULL) && (slice > disk)) {
742912Sartem 		s = slice;
752912Sartem 	} else {
762912Sartem 		s = disk;
772912Sartem 	}
782912Sartem 	if ((s != NULL) && isdigit(s[1])) {
792912Sartem 		return (s);
802912Sartem 	} else {
812912Sartem 		return ("");
822912Sartem 	}
832912Sartem }
842912Sartem 
852912Sartem boolean_t
862912Sartem is_dos_drive(uchar_t type)
872912Sartem {
883602Sartem 	return ((type == DOSOS12) || (type == DOSOS16) ||
893602Sartem 	    (type == DOSHUGE) || (type == FDISK_WINDOWS) ||
903602Sartem 	    (type == FDISK_EXT_WIN) || (type == FDISK_FAT95) ||
913602Sartem 	    (type == DIAGPART));
922912Sartem }
932912Sartem 
942912Sartem boolean_t
952912Sartem is_dos_extended(uchar_t id)
962912Sartem {
972912Sartem 	return ((id == EXTDOS) || (id == FDISK_EXTLBA));
982912Sartem }
992912Sartem 
1002912Sartem struct part_find_s {
1012912Sartem 	int	num;
1022912Sartem 	int	count;
1032912Sartem 	int	systid;
1042912Sartem 	int	r_systid;
1052912Sartem 	int	r_relsect;
1062912Sartem 	int	r_numsect;
1072912Sartem };
1082912Sartem 
1092912Sartem enum { WALK_CONTINUE, WALK_TERMINATE };
1102912Sartem 
1112912Sartem /*
1122912Sartem  * Walk partition tables and invoke a callback for each.
1132912Sartem  */
1142912Sartem static void
115*6395Sartem walk_partitions(int fd, int startsec, uint_t secsz,
116*6395Sartem     int (*f)(void *, int, int, int), void *arg)
1172912Sartem {
1182912Sartem 	uint32_t buf[1024/4];
1192912Sartem 	int bufsize = 1024;
1202912Sartem 	struct mboot *mboot = (struct mboot *)&buf[0];
1212912Sartem 	struct ipart ipart[FD_NUMPART];
1222912Sartem 	int sec = startsec;
1232912Sartem 	int lastsec = sec + 1;
1242912Sartem 	int relsect;
1252912Sartem 	int ext = 0;
1262912Sartem 	int systid;
1272912Sartem 	boolean_t valid;
1282912Sartem 	int i;
1292912Sartem 
1302912Sartem 	while (sec != lastsec) {
131*6395Sartem 		if (pread(fd, buf, bufsize, (off_t)sec * secsz) != bufsize) {
1322912Sartem 			break;
1332912Sartem 		}
1342912Sartem 		lastsec = sec;
1352912Sartem 		if (ltohs(mboot->signature) != MBB_MAGIC) {
1362912Sartem 			break;
1372912Sartem 		}
1382912Sartem 		bcopy(mboot->parts, ipart, FD_NUMPART * sizeof (struct ipart));
1392912Sartem 
1402912Sartem 		for (i = 0; i < FD_NUMPART; i++) {
1412912Sartem 			systid = ipart[i].systid;
1422912Sartem 			relsect = sec + ltohi(ipart[i].relsect);
1432912Sartem 			if (systid == 0) {
1442912Sartem 				continue;
1452912Sartem 			}
1462912Sartem 			valid = B_TRUE;
1472912Sartem 			if (is_dos_extended(systid) && (sec == lastsec)) {
1482912Sartem 				sec = startsec + ltohi(ipart[i].relsect);
1492912Sartem 				if (ext++ == 0) {
1502912Sartem 					relsect = startsec = sec;
1512912Sartem 				} else {
1522912Sartem 					valid = B_FALSE;
1532912Sartem 				}
1542912Sartem 			}
1552912Sartem 			if (valid && f(arg, ipart[i].systid, relsect,
1562912Sartem 			    ltohi(ipart[i].numsect)) == WALK_TERMINATE) {
1572912Sartem 				return;
1582912Sartem 			}
1592912Sartem 		}
1602912Sartem 	}
1612912Sartem }
1622912Sartem 
1632912Sartem static int
1642912Sartem find_dos_drive_cb(void *arg, int systid, int relsect, int numsect)
1652912Sartem {
1662912Sartem 	struct part_find_s *p = arg;
1672912Sartem 
1682912Sartem 	if (is_dos_drive(systid)) {
1692912Sartem 		if (++p->count == p->num) {
1702912Sartem 			p->r_relsect = relsect;
1712912Sartem 			p->r_numsect = numsect;
1722912Sartem 			p->r_systid = systid;
1732912Sartem 			return (WALK_TERMINATE);
1742912Sartem 		}
1752912Sartem 	}
1762912Sartem 
1772912Sartem 	return (WALK_CONTINUE);
1782912Sartem }
1792912Sartem 
1802912Sartem /*
1812912Sartem  * Given a dos drive number, return its relative sector number,
1822912Sartem  * number of sectors in partition and the system id.
1832912Sartem  */
1842912Sartem boolean_t
185*6395Sartem find_dos_drive(int fd, int num, uint_t secsz, off_t *offset)
1862912Sartem {
1872912Sartem 	struct part_find_s p = { 0, 0, 0, 0, 0, 0 };
1882912Sartem 
1892912Sartem 	p.num = num;
1902912Sartem 
1912912Sartem 	if (num > 0) {
192*6395Sartem 		walk_partitions(fd, 0, secsz, find_dos_drive_cb, &p);
1932912Sartem 		if (p.count == num) {
194*6395Sartem 			*offset = (off_t)p.r_relsect * secsz;
1952912Sartem 			return (B_TRUE);
1962912Sartem 		}
1972912Sartem 	}
1982912Sartem 
1992912Sartem 	return (B_FALSE);
2002912Sartem }
2012912Sartem 
2022912Sartem static int
2032912Sartem get_num_dos_drives_cb(void *arg, int systid, int relsect, int numsect)
2042912Sartem {
2052912Sartem 	if (is_dos_drive(systid)) {
2062912Sartem 		(*(int *)arg)++;
2072912Sartem 	}
2082912Sartem 	return (WALK_CONTINUE);
2092912Sartem }
2102912Sartem 
2112912Sartem int
212*6395Sartem get_num_dos_drives(int fd, uint_t secsz)
2132912Sartem {
2142912Sartem 	int count = 0;
2152912Sartem 
216*6395Sartem 	walk_partitions(fd, 0, secsz, get_num_dos_drives_cb, &count);
2172912Sartem 
2182912Sartem 	return (count);
2192912Sartem }
2202912Sartem 
2212912Sartem /*
2222912Sartem  * Return true if all non-empty slices in vtoc have identical start/size and
2232912Sartem  * are tagged backup/entire disk.
2242912Sartem  */
2252912Sartem boolean_t
2262912Sartem vtoc_one_slice_entire_disk(struct vtoc *vtoc)
2272912Sartem {
2282912Sartem 	int		i;
2292912Sartem 	struct partition *p;
2302912Sartem 	daddr_t		prev_start;
2312912Sartem 	long		prev_size;
2322912Sartem 
2332912Sartem 	for (i = 0; i < vtoc->v_nparts; i++) {
2342912Sartem 		p = &vtoc->v_part[i];
2352912Sartem 		if (p->p_size == 0) {
2362912Sartem 			continue;
2372912Sartem 		}
2382912Sartem 		if ((p->p_tag != V_BACKUP) && ((p->p_tag != V_UNASSIGNED))) {
2392912Sartem 			return (B_FALSE);
2402912Sartem 		}
2412912Sartem 		if ((i > 0) &&
2422912Sartem 		    ((p->p_start != prev_start) || (p->p_size != prev_size))) {
2432912Sartem 			return (B_FALSE);
2442912Sartem 		}
2452912Sartem 		prev_start = p->p_start;
2462912Sartem 		prev_size = p->p_size;
2472912Sartem 	}
2482912Sartem 
2492912Sartem 	return (B_TRUE);
2502912Sartem }
251