1 /* $OpenBSD: fdisk.c,v 1.52 2011/02/21 19:26:12 krw Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Tobias Weingartner 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <err.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 #include <paths.h> 34 #include <sys/types.h> 35 #include <sys/fcntl.h> 36 #include <sys/disklabel.h> 37 #include "disk.h" 38 #include "user.h" 39 40 #define _PATH_MBR _PATH_BOOTDIR "mbr" 41 static unsigned char builtin_mbr[] = { 42 #include "mbrcode.h" 43 }; 44 45 int y_flag; 46 47 static void 48 usage(void) 49 { 50 extern char * __progname; 51 52 fprintf(stderr, "usage: %s " 53 "[-eiuy] [-c cylinders -h heads -s sectors] [-f mbrfile] disk\n" 54 "\t-i: initialize disk with virgin MBR\n" 55 "\t-u: update MBR code, preserve partition table\n" 56 "\t-e: edit MBRs on disk interactively\n" 57 "\t-f: specify non-standard MBR template\n" 58 "\t-chs: specify disk geometry\n" 59 "\t-y: do not ask questions\n" 60 "`disk' may be of the forms: sd0 or /dev/rsd0c.\n", 61 __progname); 62 exit(1); 63 } 64 65 66 int 67 main(int argc, char *argv[]) 68 { 69 int ch, fd, error; 70 int i_flag = 0, m_flag = 0, u_flag = 0; 71 int c_arg = 0, h_arg = 0, s_arg = 0; 72 disk_t disk; 73 DISK_metrics *usermetrics; 74 #ifdef HAS_MBR 75 char *mbrfile = _PATH_MBR; 76 #else 77 char *mbrfile = NULL; 78 #endif 79 mbr_t mbr; 80 char mbr_buf[DEV_BSIZE]; 81 82 while ((ch = getopt(argc, argv, "ieuf:c:h:s:y")) != -1) { 83 const char *errstr; 84 85 switch(ch) { 86 case 'i': 87 i_flag = 1; 88 break; 89 case 'u': 90 u_flag = 1; 91 break; 92 case 'e': 93 m_flag = 1; 94 break; 95 case 'f': 96 mbrfile = optarg; 97 break; 98 case 'c': 99 c_arg = strtonum(optarg, 1, 262144, &errstr); 100 if (errstr) 101 errx(1, "Cylinder argument %s [1..262144].", 102 errstr); 103 break; 104 case 'h': 105 h_arg = strtonum(optarg, 1, 256, &errstr); 106 if (errstr) 107 errx(1, "Head argument %s [1..256].", errstr); 108 break; 109 case 's': 110 s_arg = strtonum(optarg, 1, 63, &errstr); 111 if (errstr) 112 errx(1, "Sector argument %s [1..63].", errstr); 113 break; 114 case 'y': 115 y_flag = 1; 116 break; 117 default: 118 usage(); 119 } 120 } 121 argc -= optind; 122 argv += optind; 123 124 /* Argument checking */ 125 if (argc != 1) 126 usage(); 127 else 128 disk.name = argv[0]; 129 130 /* Put in supplied geometry if there */ 131 if (c_arg | h_arg | s_arg) { 132 usermetrics = malloc(sizeof(DISK_metrics)); 133 if (usermetrics != NULL) { 134 if (c_arg && h_arg && s_arg) { 135 usermetrics->cylinders = c_arg; 136 usermetrics->heads = h_arg; 137 usermetrics->sectors = s_arg; 138 usermetrics->size = c_arg * h_arg * s_arg; 139 } else 140 errx(1, "Please specify a full geometry with [-chs]."); 141 } 142 } else 143 usermetrics = NULL; 144 145 /* Get the geometry */ 146 disk.real = NULL; 147 if (DISK_getmetrics(&disk, usermetrics)) 148 errx(1, "Can't get disk geometry, please use [-chs] to specify."); 149 150 151 /* Print out current MBRs on disk */ 152 if ((i_flag + u_flag + m_flag) == 0) 153 exit(USER_print_disk(&disk)); 154 155 /* Parse mbr template, to pass on later */ 156 if (mbrfile != NULL && (fd = open(mbrfile, O_RDONLY)) == -1) { 157 warn("%s", mbrfile); 158 warnx("using builtin MBR"); 159 mbrfile = NULL; 160 } 161 if (mbrfile == NULL) { 162 memcpy(mbr_buf, builtin_mbr, sizeof(mbr_buf)); 163 } else { 164 error = MBR_read(fd, 0, mbr_buf); 165 close(fd); 166 if (error == -1) { 167 printf("Unable to read MBR\n"); 168 return (1); 169 } 170 } 171 MBR_parse(&disk, mbr_buf, 0, 0, &mbr); 172 173 /* Now do what we are supposed to */ 174 if (i_flag || u_flag) 175 if (USER_init(&disk, &mbr, u_flag) == -1) 176 err(1, "error initializing MBR"); 177 178 if (m_flag) 179 USER_modify(&disk, &mbr, 0, 0); 180 181 return (0); 182 } 183 184