1 /* $OpenBSD: fdisk.c,v 1.63 2014/03/20 13:18:21 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 <sys/types.h> 29 #include <sys/fcntl.h> 30 #include <sys/disklabel.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <unistd.h> 35 #include <paths.h> 36 #include <stdint.h> 37 #include <err.h> 38 39 #include "disk.h" 40 #include "part.h" 41 #include "mbr.h" 42 #include "misc.h" 43 #include "user.h" 44 45 #define _PATH_MBR _PATH_BOOTDIR "mbr" 46 static unsigned char builtin_mbr[] = { 47 #include "mbrcode.h" 48 }; 49 50 int y_flag; 51 52 static void 53 usage(void) 54 { 55 extern char * __progname; 56 57 fprintf(stderr, "usage: %s " 58 "[-eiuy] [-c cylinders -h heads -s sectors] [-f mbrfile] [-l blocks] disk\n" 59 "\t-i: initialize disk with virgin MBR\n" 60 "\t-u: update MBR code, preserve partition table\n" 61 "\t-e: edit MBRs on disk interactively\n" 62 "\t-f: specify non-standard MBR template\n" 63 "\t-chs: specify disk geometry\n" 64 "\t-l: specify LBA block count\n" 65 "\t-y: do not ask questions\n" 66 "`disk' may be of the forms: sd0 or /dev/rsd0c.\n", 67 __progname); 68 exit(1); 69 } 70 71 72 int 73 main(int argc, char *argv[]) 74 { 75 int ch, fd, error; 76 int i_flag = 0, m_flag = 0, u_flag = 0; 77 int c_arg = 0, h_arg = 0, s_arg = 0; 78 struct disk disk; 79 u_int32_t l_arg = 0; 80 #ifdef HAS_MBR 81 char *mbrfile = _PATH_MBR; 82 #else 83 char *mbrfile = NULL; 84 #endif 85 struct mbr mbr; 86 struct dos_mbr dos_mbr; 87 88 while ((ch = getopt(argc, argv, "ieuf:c:h:s:l:y")) != -1) { 89 const char *errstr; 90 91 switch(ch) { 92 case 'i': 93 i_flag = 1; 94 break; 95 case 'u': 96 u_flag = 1; 97 break; 98 case 'e': 99 m_flag = 1; 100 break; 101 case 'f': 102 mbrfile = optarg; 103 break; 104 case 'c': 105 c_arg = strtonum(optarg, 1, 262144, &errstr); 106 if (errstr) 107 errx(1, "Cylinder argument %s [1..262144].", 108 errstr); 109 break; 110 case 'h': 111 h_arg = strtonum(optarg, 1, 256, &errstr); 112 if (errstr) 113 errx(1, "Head argument %s [1..256].", errstr); 114 break; 115 case 's': 116 s_arg = strtonum(optarg, 1, 63, &errstr); 117 if (errstr) 118 errx(1, "Sector argument %s [1..63].", errstr); 119 break; 120 case 'l': 121 l_arg = strtonum(optarg, 64, UINT32_MAX, &errstr); 122 if (errstr) 123 errx(1, "Block argument %s [64..%u].", errstr, 124 UINT32_MAX); 125 break; 126 case 'y': 127 y_flag = 1; 128 break; 129 default: 130 usage(); 131 } 132 } 133 argc -= optind; 134 argv += optind; 135 136 memset(&disk, 0, sizeof(disk)); 137 138 /* Argument checking */ 139 if (argc != 1) 140 usage(); 141 else 142 disk.name = argv[0]; 143 144 /* Start with the disklabel geometry and get the sector size. */ 145 DISK_getlabelgeometry(&disk); 146 147 if (c_arg | h_arg | s_arg) { 148 /* Use supplied geometry if it is completely specified. */ 149 if (c_arg && h_arg && s_arg) { 150 disk.cylinders = c_arg; 151 disk.heads = h_arg; 152 disk.sectors = s_arg; 153 disk.size = c_arg * h_arg * s_arg; 154 } else 155 errx(1, "Please specify a full geometry with [-chs]."); 156 } else if (l_arg) { 157 /* Use supplied size to calculate a geometry. */ 158 disk.cylinders = l_arg / 64; 159 disk.heads = 1; 160 disk.sectors = 64; 161 disk.size = l_arg; 162 } 163 164 if (disk.size == 0 || disk.cylinders == 0 || disk.heads == 0 || 165 disk.sectors == 0 || unit_types[SECTORS].conversion == 0) 166 errx(1, "Can't get disk geometry, please use [-chs] " 167 "to specify."); 168 169 /* Print out current MBRs on disk */ 170 if ((i_flag + u_flag + m_flag) == 0) 171 exit(USER_print_disk(&disk)); 172 173 /* Parse mbr template, to pass on later */ 174 if (mbrfile != NULL && (fd = open(mbrfile, O_RDONLY)) == -1) { 175 warn("%s", mbrfile); 176 warnx("using builtin MBR"); 177 mbrfile = NULL; 178 } 179 if (mbrfile == NULL) { 180 memcpy(&dos_mbr, builtin_mbr, sizeof(dos_mbr)); 181 } else { 182 error = MBR_read(fd, 0, &dos_mbr); 183 if (error == -1) 184 err(1, "Unable to read MBR"); 185 close(fd); 186 } 187 MBR_parse(&disk, &dos_mbr, 0, 0, &mbr); 188 189 /* Now do what we are supposed to */ 190 if (i_flag || u_flag) 191 if (USER_init(&disk, &mbr, u_flag) == -1) 192 err(1, "error initializing MBR"); 193 194 if (m_flag) 195 USER_modify(&disk, &mbr, 0, 0); 196 197 return (0); 198 } 199