diff options
Diffstat (limited to 'diskdev_cmds/fdisk.tproj/fdisk.c')
-rw-r--r-- | diskdev_cmds/fdisk.tproj/fdisk.c | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/diskdev_cmds/fdisk.tproj/fdisk.c b/diskdev_cmds/fdisk.tproj/fdisk.c new file mode 100644 index 0000000..e7b45cb --- /dev/null +++ b/diskdev_cmds/fdisk.tproj/fdisk.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <paths.h> +#include <sys/types.h> +#include <sys/fcntl.h> +#include "disk.h" +#include "user.h" +#include "auto.h" + +#define _PATH_MBR "/usr/standalone/i386/boot0" + +void +usage() +{ + extern char * __progname; + fprintf(stderr, "usage: %s " + "[-ieu] [-f mbrboot] [-c cyl -h head -s sect] [-S size] [-r] [-a style] disk\n" + "\t-i: initialize disk with new MBR\n" + "\t-u: update MBR code, preserve partition table\n" + "\t-e: edit MBRs on disk interactively\n" + "\t-f: specify non-standard MBR template\n" + "\t-chs: specify disk geometry\n" + "\t-S: specify disk size\n" + "\t-r: read partition specs from stdin (implies -i)\n" + "\t-a: auto-partition with the given style\n" + "\t-d: dump partition table\n" + "\t-y: don't ask any questions\n" + "\t-t: test if disk is partitioned\n" + "`disk' is of the form /dev/rdisk0.\n", + __progname); + fprintf(stderr, "auto-partition styles:\n"); + AUTO_print_styles(stderr); + exit(1); +} + +char *mbr_binary = NULL; +int +main(argc, argv) + int argc; + char **argv; +{ + int ch, fd; + int i_flag = 0, m_flag = 0, u_flag = 0, r_flag = 0, d_flag = 0, y_flag = 0, t_flag = 0; + int c_arg = 0, h_arg = 0, s_arg = 0; + int size_arg = 0; + int block_size_arg = 0; + disk_t disk; + DISK_metrics *usermetrics; + char *mbrfile = _PATH_MBR; + mbr_t *mp; + char *auto_style = NULL; + + while ((ch = getopt(argc, argv, "ieuf:c:h:s:b:S:ra:dyt")) != -1) { + switch(ch) { + case 'i': + i_flag = 1; + break; + case 'u': + u_flag = 1; + break; + case 'e': + m_flag = 1; + break; + case 'f': + mbrfile = optarg; + break; + case 'c': + c_arg = atoi(optarg); + if (c_arg < 1 || c_arg > 262144) + errx(1, "Cylinder argument out of range."); + break; + case 'h': + h_arg = atoi(optarg); + if (h_arg < 1 || h_arg > 256) + errx(1, "Head argument out of range."); + break; + case 's': + s_arg = atoi(optarg); + if (s_arg < 1 || s_arg > 63) + errx(1, "Sector argument out of range."); + break; + case 'b': + block_size_arg = atoi(optarg); + if (block_size_arg & (block_size_arg - 1)) + errx(1, "Block size argument not a power of two."); + if (block_size_arg < 512 || block_size_arg > 4096) + errx(1, "Block size argument out of range 512..4096."); + break; + case 'S': + size_arg = atoi(optarg); + break; + case 'r': + r_flag = 1; + break; + case 'a': + auto_style = optarg; + break; + case 'd': + d_flag = 1; + break; + case 'y': + y_flag = 1; + break; + case 't': + t_flag = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + /* Argument checking */ + if (argc != 1) + usage(); + else + disk.name = argv[0]; + + if (i_flag && u_flag) errx(1, "-i and -u cannot be specified simultaneously"); + + /* Put in supplied geometry if there */ + if (c_arg | h_arg | s_arg | size_arg | block_size_arg) { + usermetrics = malloc(sizeof(DISK_metrics)); + if (usermetrics != NULL) { + if (c_arg && h_arg && s_arg) { + usermetrics->cylinders = c_arg; + usermetrics->heads = h_arg; + usermetrics->sectors = s_arg; + if (size_arg) { + usermetrics->size = size_arg; + } else { + usermetrics->size = c_arg * h_arg * s_arg; + } + } else { + if (size_arg) { + usermetrics->size = size_arg; + DISK_fake_CHS(usermetrics); + } else { + errx(1, "Please specify a full geometry with [-chs]."); + } + } + if (block_size_arg) { + usermetrics->sector_size = block_size_arg; + } else { + DISK_get_sector_size(&disk, usermetrics); + } + } + } else { + usermetrics = NULL; + } + + /* Get the geometry */ + disk.real = NULL; + if (DISK_getmetrics(&disk, usermetrics)) + errx(1, "Can't get disk geometry, please use [-chs] to specify."); + + /* If only testing, read MBR and silently exit */ + if (t_flag) { + mbr_t *mbr; + + mp = mbr = MBR_read_all(&disk); + while (mp) { + if (mp->signature != MBR_SIGNATURE) { + MBR_free(mbr); + exit(1); + } + mp = mp->next; + } + MBR_free(mbr); + exit(0); + } + + /* If not editing the disk, print out current MBRs on disk */ + if ((i_flag + r_flag + u_flag + m_flag) == 0) { + exit(USER_print_disk(&disk, d_flag)); + } + + /* Parse mbr template or read partition specs, to pass on later */ + if (auto_style && r_flag) { + errx(1, "Can't specify both -r and -a"); + } + + mbr_binary = (char *)malloc(MBR_CODE_SIZE); + if ((fd = open(mbrfile, O_RDONLY)) == -1) { + warn("could not open MBR file %s", mbrfile); + bzero(mbr_binary, MBR_CODE_SIZE); + } else { + int cc; + cc = read(fd, mbr_binary, MBR_CODE_SIZE); + if (cc < MBR_CODE_SIZE) { + err(1, "could not read MBR code"); + } + close(fd); + } + + if (u_flag) { + /* Don't hose the partition table; just write the boot code */ + mp = MBR_read_all(&disk); + bcopy(mbr_binary, mp->code, MBR_CODE_SIZE); + MBR_make(mp); + } else if (i_flag) { + /* If they didn't specify -a, they'll get the default auto style */ + mp = MBR_alloc(NULL); + if (AUTO_init(&disk, auto_style, mp) != AUTO_OK) { + errx(1, "error initializing disk"); + } + bcopy(mbr_binary, mp->code, MBR_CODE_SIZE); + MBR_make(mp); + } else if (r_flag) { + mp = MBR_parse_spec(stdin, &disk); + bcopy(mbr_binary, mp->code, MBR_CODE_SIZE); + MBR_make(mp); + } else { + /* Use what's on the disk. */ + mp = MBR_read_all(&disk); + } + + /* Now do what we are supposed to */ + if (i_flag || r_flag || u_flag) { + USER_write(&disk, mp, u_flag, y_flag); + } + + if (m_flag) { + USER_modify(&disk, mp, 0, 0); + } + + if (mbr_binary) + free(mbr_binary); + + return (0); +} |