xref: /onnv-gate/usr/src/cmd/hal/utils/fsutils.c (revision 2912)
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