xref: /titanic_44/usr/src/cmd/hal/utils/fsutils.c (revision 18c2aff776a775d34a4c9893a4c72e0434d68e36)
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