]>
git.cameronkatri.com Git - apple_cmds.git/blob - diskdev_cmds/fdisk.tproj/disk.c
2 * Copyright (c) 2002, 2012 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1997, 2001 Tobias Weingartner
26 * All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by Tobias Weingartner.
39 * 4. The name of the author may not be used to endorse or promote products
40 * derived from this software without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
51 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 #include <sys/fcntl.h>
61 #include <sys/ioctl.h>
62 #include <sys/types.h>
64 #include <sys/reboot.h>
66 #include <sys/param.h>
67 #include <sys/sysctl.h>
69 #include <pexpert/i386/boot.h>
81 fd
= open(disk
, mode
);
84 if (fstat(fd
, &st
) == -1)
86 /* Don't be so picky about needing a character device */
87 if (!S_ISCHR(st
.st_mode
) && !S_ISBLK(st
.st_mode
) && !S_ISREG(st
.st_mode
))
88 errx(1, "%s is not a character device or a regular file", disk
);
93 DISK_openshared(disk
, mode
, shared
)
102 fd
= open(disk
, mode
|O_EXLOCK
);
104 // if we can't have exclusive access, attempt
105 // to gracefully degrade to shared access
106 fd
= open(disk
, mode
|O_SHLOCK
);
113 if (fstat(fd
, &st
) == -1)
115 /* Don't be so picky about needing a character device */
116 if (!S_ISCHR(st
.st_mode
) && !S_ISBLK(st
.st_mode
) && !S_ISREG(st
.st_mode
))
117 errx(1, "%s is not a character device or a regular file", disk
);
129 /* Given a size in the metrics,
130 * fake up a CHS geometry.
133 DISK_fake_CHS(DISK_metrics
*lm
)
137 int cylinders
= (lm
->size
/ heads
/ spt
);
139 while (cylinders
> 1024 && heads
< 256) {
145 cylinders
= (lm
->size
/ heads
/ spt
);
147 lm
->cylinders
= cylinders
;
152 /* Routine to go after the disklabel for geometry
153 * information. This should work everywhere, but
154 * in the land of PC, things are not always what
158 DISK_getlabelmetrics(name
)
161 DISK_metrics
*lm
= NULL
;
163 uint32_t sector_size
;
167 /* Get label metrics */
168 if ((fd
= DISK_open(name
, O_RDONLY
)) != -1) {
169 lm
= malloc(sizeof(DISK_metrics
));
171 if (fstat(fd
, &st
) == -1)
173 if (!S_ISREG(st
.st_mode
) || S_ISBLK(st
.st_mode
)) {
174 if (ioctl(fd
, DKIOCGETBLOCKCOUNT
, &size
) == -1) {
175 err(1, "Could not get disk block count");
179 if (ioctl(fd
, DKIOCGETBLOCKSIZE
, §or_size
) == -1) {
180 err(1, "Could not get disk block size");
186 size
= st
.st_size
/ sector_size
;
189 lm
->sector_size
= sector_size
;
199 * Don't try to get BIOS disk metrics.
202 DISK_getbiosmetrics(name
)
208 /* This is ugly, and convoluted. All the magic
209 * for disk geo/size happens here. Basically,
210 * the real size is the one we will use in the
211 * rest of the program, the label size is what we
212 * got from the disklabel. If the disklabel fails,
213 * we assume we are working with a normal file,
214 * and should request the user to specify the
215 * geometry he/she wishes to use.
218 DISK_getmetrics(disk
, user
)
223 disk
->label
= DISK_getlabelmetrics(disk
->name
);
224 disk
->bios
= DISK_getbiosmetrics(disk
->name
);
226 /* If user supplied, use that */
232 /* Fixup bios metrics to include cylinders past 1023 boundary */
233 if(disk
->label
&& disk
->bios
){
236 cyls
= disk
->label
->size
/ (disk
->bios
->heads
* disk
->bios
->sectors
);
237 secs
= cyls
* (disk
->bios
->heads
* disk
->bios
->sectors
);
238 if (disk
->label
->size
< secs
) {
239 errx(1, "BIOS fixup botch (%u sectors)", disk
->label
->size
- secs
);
241 disk
->bios
->cylinders
= cyls
;
242 disk
->bios
->size
= secs
;
245 /* If we have a (fixed) BIOS geometry, use that */
247 disk
->real
= disk
->bios
;
251 /* If we have a label, use that */
253 disk
->real
= disk
->label
;
257 /* Can not get geometry, punt */
262 /* Get the disk's native sector size, updating the metrics' sector_size field.
265 DISK_get_sector_size(disk
, user
)
271 uint32_t sector_size
;
273 /* Default to 512 bytes per sector, in case of failure. */
274 user
->sector_size
= 512;
277 fd
= DISK_open(disk
->name
, O_RDONLY
);
279 err(1, "Could not open %s", disk
->name
);
281 if (ioctl(fd
, DKIOCGETBLOCKSIZE
, §or_size
) == -1) {
282 err(1, "Could not get disk block size");
284 user
->sector_size
= sector_size
;
293 DISK_printmetrics(disk
)
297 printf("Disk: %s\t", disk
->name
);
299 printf("geometry: %u/%u/%u [%u sectors]\n", disk
->real
->cylinders
,
300 disk
->real
->heads
, disk
->real
->sectors
, disk
->real
->size
);
301 if (disk
->real
->sector_size
!= 512)
302 printf("Sector size: %u bytes\n", disk
->real
->sector_size
);
304 printf("geometry: <none>\n");