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
17 #include <sys/types.h>
18 #include <sys/scsi/impl/uscsi.h>
28 #include <sys/dktp/fdisk.h>
29 #include <sys/fs/pc_label.h>
35 * Separates dos notation device spec into device and drive number
38 dos_to_dev(char *path
, char **devpath
, int *num
)
42 if ((p
= strrchr(path
, ':')) == NULL
) {
45 if ((*num
= atoi(p
+ 1)) == 0) {
49 *devpath
= strdup(path
);
51 return (*devpath
!= NULL
);
55 get_slice_name(char *devlink
)
57 char *part
, *slice
, *disk
;
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
)) {
71 } else if ((slice
!= NULL
) && (slice
> disk
)) {
76 if ((s
!= NULL
) && isdigit(s
[1])) {
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
) ||
93 is_dos_extended(uchar_t id
)
95 return ((id
== EXTDOS
) || (id
== FDISK_EXTLBA
));
107 enum { WALK_CONTINUE
, WALK_TERMINATE
};
110 * Walk partition tables and invoke a callback for each.
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];
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;
128 while (sec
!= lastsec
) {
129 if (pread(fd
, buf
, bufsize
, (off_t
)sec
* secsz
) != bufsize
) {
133 if (ltohs(mboot
->signature
) != MBB_MAGIC
) {
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
);
145 if (is_dos_extended(systid
) && (sec
== lastsec
)) {
146 sec
= startsec
+ ltohi(ipart
[i
].relsect
);
148 relsect
= startsec
= sec
;
153 if (valid
&& f(arg
, ipart
[i
].systid
, relsect
,
154 ltohi(ipart
[i
].numsect
)) == WALK_TERMINATE
) {
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.
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 };
190 walk_partitions(fd
, 0, secsz
, find_dos_drive_cb
, &p
);
191 if (p
.count
== num
) {
192 *offset
= (off_t
)p
.r_relsect
* secsz
;
201 get_num_dos_drives_cb(void *arg
, int systid
, uint_t relsect
, uint_t numsect
)
203 if (is_dos_drive(systid
)) {
206 return (WALK_CONTINUE
);
210 get_num_dos_drives(int fd
, uint_t secsz
)
214 walk_partitions(fd
, 0, secsz
, get_num_dos_drives_cb
, &count
);
220 * Return true if all non-empty slices in vtoc have identical start/size and
221 * are tagged backup/entire disk.
224 vtoc_one_slice_entire_disk(struct extvtoc
*vtoc
)
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) {
236 if ((p
->p_tag
!= V_BACKUP
) && ((p
->p_tag
!= V_UNASSIGNED
))) {
240 ((p
->p_start
!= prev_start
) || (p
->p_size
!= prev_size
))) {
243 prev_start
= p
->p_start
;
244 prev_size
= p
->p_size
;