dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / hal / utils / fsutils.c
blob7e1f66019e4729f5dcac77356bb91550c30f8088
1 /*
3 * fsutils.c : filesystem utilities
5 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
6 * Use is subject to license terms.
8 * Licensed under the Academic Free License version 2.1
12 #ifdef HAVE_CONFIG_H
13 #include <config.h>
14 #endif
16 #include <stdio.h>
17 #include <sys/types.h>
18 #include <sys/scsi/impl/uscsi.h>
19 #include <string.h>
20 #include <strings.h>
21 #include <ctype.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <sys/dkio.h>
27 #include <libintl.h>
28 #include <sys/dktp/fdisk.h>
29 #include <sys/fs/pc_label.h>
31 #include <libhal.h>
32 #include "fsutils.h"
35 * Separates dos notation device spec into device and drive number
37 boolean_t
38 dos_to_dev(char *path, char **devpath, int *num)
40 char *p;
42 if ((p = strrchr(path, ':')) == NULL) {
43 return (B_FALSE);
45 if ((*num = atoi(p + 1)) == 0) {
46 return (B_FALSE);
48 p[0] = '\0';
49 *devpath = strdup(path);
50 p[0] = ':';
51 return (*devpath != NULL);
54 char *
55 get_slice_name(char *devlink)
57 char *part, *slice, *disk;
58 char *s = NULL;
59 char *p;
61 if ((p = strstr(devlink, "/lofi/")) != 0) {
62 return (p + sizeof ("/lofi/") - 1);
65 part = strrchr(devlink, 'p');
66 slice = strrchr(devlink, 's');
67 disk = strrchr(devlink, 'd');
69 if ((part != NULL) && (part > slice) && (part > disk)) {
70 s = part;
71 } else if ((slice != NULL) && (slice > disk)) {
72 s = slice;
73 } else {
74 s = disk;
76 if ((s != NULL) && isdigit(s[1])) {
77 return (s);
78 } else {
79 return ("");
83 boolean_t
84 is_dos_drive(uchar_t type)
86 return ((type == DOSOS12) || (type == DOSOS16) ||
87 (type == DOSHUGE) || (type == FDISK_WINDOWS) ||
88 (type == FDISK_EXT_WIN) || (type == FDISK_FAT95) ||
89 (type == DIAGPART));
92 boolean_t
93 is_dos_extended(uchar_t id)
95 return ((id == EXTDOS) || (id == FDISK_EXTLBA));
98 struct part_find_s {
99 int num;
100 int count;
101 int systid;
102 int r_systid;
103 uint_t r_relsect;
104 uint_t r_numsect;
107 enum { WALK_CONTINUE, WALK_TERMINATE };
110 * Walk partition tables and invoke a callback for each.
112 static void
113 walk_partitions(int fd, int startsec, uint_t secsz,
114 int (*f)(void *, int, uint_t, uint_t), void *arg)
116 uint32_t buf[1024/4];
117 int bufsize = 1024;
118 struct mboot *mboot = (struct mboot *)&buf[0];
119 struct ipart ipart[FD_NUMPART];
120 uint_t sec = startsec;
121 uint_t lastsec = sec + 1;
122 uint_t relsect;
123 int ext = 0;
124 int systid;
125 boolean_t valid;
126 int i;
128 while (sec != lastsec) {
129 if (pread(fd, buf, bufsize, (off_t)sec * secsz) != bufsize) {
130 break;
132 lastsec = sec;
133 if (ltohs(mboot->signature) != MBB_MAGIC) {
134 break;
136 bcopy(mboot->parts, ipart, FD_NUMPART * sizeof (struct ipart));
138 for (i = 0; i < FD_NUMPART; i++) {
139 systid = ipart[i].systid;
140 relsect = sec + ltohi(ipart[i].relsect);
141 if (systid == 0) {
142 continue;
144 valid = B_TRUE;
145 if (is_dos_extended(systid) && (sec == lastsec)) {
146 sec = startsec + ltohi(ipart[i].relsect);
147 if (ext++ == 0) {
148 relsect = startsec = sec;
149 } else {
150 valid = B_FALSE;
153 if (valid && f(arg, ipart[i].systid, relsect,
154 ltohi(ipart[i].numsect)) == WALK_TERMINATE) {
155 return;
161 static int
162 find_dos_drive_cb(void *arg, int systid, uint_t relsect, uint_t numsect)
164 struct part_find_s *p = arg;
166 if (is_dos_drive(systid)) {
167 if (++p->count == p->num) {
168 p->r_relsect = relsect;
169 p->r_numsect = numsect;
170 p->r_systid = systid;
171 return (WALK_TERMINATE);
175 return (WALK_CONTINUE);
179 * Given a dos drive number, return its relative sector number,
180 * number of sectors in partition and the system id.
182 boolean_t
183 find_dos_drive(int fd, int num, uint_t secsz, off_t *offset)
185 struct part_find_s p = { 0, 0, 0, 0, 0, 0 };
187 p.num = num;
189 if (num > 0) {
190 walk_partitions(fd, 0, secsz, find_dos_drive_cb, &p);
191 if (p.count == num) {
192 *offset = (off_t)p.r_relsect * secsz;
193 return (B_TRUE);
197 return (B_FALSE);
200 static int
201 get_num_dos_drives_cb(void *arg, int systid, uint_t relsect, uint_t numsect)
203 if (is_dos_drive(systid)) {
204 (*(int *)arg)++;
206 return (WALK_CONTINUE);
210 get_num_dos_drives(int fd, uint_t secsz)
212 int count = 0;
214 walk_partitions(fd, 0, secsz, get_num_dos_drives_cb, &count);
216 return (count);
220 * Return true if all non-empty slices in vtoc have identical start/size and
221 * are tagged backup/entire disk.
223 boolean_t
224 vtoc_one_slice_entire_disk(struct extvtoc *vtoc)
226 int i;
227 struct extpartition *p;
228 diskaddr_t prev_start;
229 diskaddr_t prev_size;
231 for (i = 0; i < vtoc->v_nparts; i++) {
232 p = &vtoc->v_part[i];
233 if (p->p_size == 0) {
234 continue;
236 if ((p->p_tag != V_BACKUP) && ((p->p_tag != V_UNASSIGNED))) {
237 return (B_FALSE);
239 if ((i > 0) &&
240 ((p->p_start != prev_start) || (p->p_size != prev_size))) {
241 return (B_FALSE);
243 prev_start = p->p_start;
244 prev_size = p->p_size;
247 return (B_TRUE);