1 /* $OpenBSD: fdisk.c,v 1.103 2018/04/26 15:55:14 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Tobias Weingartner 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/disklabel.h> 21 22 #include <err.h> 23 #include <fcntl.h> 24 #include <paths.h> 25 #include <stdint.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 31 #include "disk.h" 32 #include "part.h" 33 #include "mbr.h" 34 #include "misc.h" 35 #include "cmd.h" 36 #include "user.h" 37 #include "gpt.h" 38 39 #define _PATH_MBR _PATH_BOOTDIR "mbr" 40 static unsigned char builtin_mbr[] = { 41 #include "mbrcode.h" 42 }; 43 44 u_int32_t b_arg; 45 int y_flag; 46 47 static void 48 usage(void) 49 { 50 extern char * __progname; 51 52 fprintf(stderr, "usage: %s " 53 "[-egvy] [-i|-u] [-b #] [-c # -h # -s #] " 54 "[-f mbrfile] [-l # ] disk\n" 55 "\t-b: specify special boot partition block count; requires -i\n" 56 "\t-chs: specify disk geometry; all three must be specified\n" 57 "\t-e: interactively edit MBR or GPT\n" 58 "\t-f: specify non-standard MBR template\n" 59 "\t-g: initialize disk with GPT; requires -i\n" 60 "\t-i: initialize disk with MBR unless -g is also specified\n" 61 "\t-l: specify LBA block count; cannot be used with -chs\n" 62 "\t-u: update MBR code; preserve partition table\n" 63 "\t-v: print the MBR, the Primary GPT and the Secondary GPT\n" 64 "\t-y: do not ask questions\n" 65 "`disk' may be of the forms: sd0 or /dev/rsd0c.\n", 66 __progname); 67 exit(1); 68 } 69 70 int 71 main(int argc, char *argv[]) 72 { 73 ssize_t len; 74 int ch, fd, error; 75 int e_flag = 0, g_flag = 0, i_flag = 0, u_flag = 0; 76 int verbosity = 0; 77 int c_arg = 0, h_arg = 0, s_arg = 0; 78 u_int32_t l_arg = 0; 79 char *query; 80 #ifdef HAS_MBR 81 char *mbrfile = _PATH_MBR; 82 #else 83 char *mbrfile = NULL; 84 #endif 85 struct dos_mbr dos_mbr; 86 struct mbr mbr; 87 88 while ((ch = getopt(argc, argv, "iegpuvf:c:h:s:l:b: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 e_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 disk.cylinders = c_arg; 110 disk.size = c_arg * h_arg * s_arg; 111 break; 112 case 'h': 113 h_arg = strtonum(optarg, 1, 256, &errstr); 114 if (errstr) 115 errx(1, "Head argument %s [1..256].", errstr); 116 disk.heads = h_arg; 117 disk.size = c_arg * h_arg * s_arg; 118 break; 119 case 's': 120 s_arg = strtonum(optarg, 1, 63, &errstr); 121 if (errstr) 122 errx(1, "Sector argument %s [1..63].", errstr); 123 disk.sectors = s_arg; 124 disk.size = c_arg * h_arg * s_arg; 125 break; 126 case 'g': 127 g_flag = 1; 128 break; 129 case 'b': 130 b_arg = strtonum(optarg, 64, UINT32_MAX, &errstr); 131 if (errstr) 132 errx(1, "Block argument %s [64..%u].", errstr, 133 UINT32_MAX); 134 break; 135 case 'l': 136 l_arg = strtonum(optarg, 64, UINT32_MAX, &errstr); 137 if (errstr) 138 errx(1, "Block argument %s [64..%u].", errstr, 139 UINT32_MAX); 140 disk.cylinders = l_arg / 64; 141 disk.heads = 1; 142 disk.sectors = 64; 143 disk.size = l_arg; 144 break; 145 case 'y': 146 y_flag = 1; 147 break; 148 case 'v': 149 verbosity++; 150 break; 151 default: 152 usage(); 153 } 154 } 155 argc -= optind; 156 argv += optind; 157 158 /* Argument checking */ 159 if (argc != 1 || (i_flag && u_flag) || 160 (i_flag == 0 && (b_arg || g_flag)) || 161 ((c_arg | h_arg | s_arg) && !(c_arg && h_arg && s_arg)) || 162 ((c_arg | h_arg | s_arg) && l_arg)) 163 usage(); 164 165 disk.name = argv[0]; 166 DISK_open(i_flag || u_flag || e_flag); 167 168 /* "proc exec" for man page display */ 169 if (pledge("stdio rpath wpath disklabel proc exec", NULL) == -1) 170 err(1, "pledge"); 171 172 error = MBR_read(0, &dos_mbr); 173 if (error) 174 errx(1, "Can't read sector 0!"); 175 MBR_parse(&dos_mbr, 0, 0, &mbr); 176 177 /* Get the GPT if present. Either primary or secondary is ok. */ 178 if (MBR_protective_mbr(&mbr) == 0) 179 GPT_get_gpt(0); 180 181 if (!(i_flag || u_flag || e_flag)) { 182 if (pledge("stdio", NULL) == -1) 183 err(1, "pledge"); 184 USER_print_disk(verbosity); 185 goto done; 186 } 187 188 /* Create initial/default MBR. */ 189 if (mbrfile == NULL) { 190 memcpy(&dos_mbr, builtin_mbr, sizeof(dos_mbr)); 191 } else { 192 fd = open(mbrfile, O_RDONLY); 193 if (fd == -1) { 194 warn("%s", mbrfile); 195 warnx("using builtin MBR"); 196 memcpy(&dos_mbr, builtin_mbr, sizeof(dos_mbr)); 197 } else { 198 len = read(fd, &dos_mbr, sizeof(dos_mbr)); 199 close(fd); 200 if (len == -1) 201 err(1, "Unable to read MBR from '%s'", mbrfile); 202 else if (len != sizeof(dos_mbr)) 203 errx(1, "Unable to read complete MBR from '%s'", 204 mbrfile); 205 } 206 } 207 MBR_parse(&dos_mbr, 0, 0, &initial_mbr); 208 209 query = NULL; 210 if (i_flag) { 211 reinited = 1; 212 if (g_flag) { 213 MBR_init_GPT(&initial_mbr); 214 GPT_init(); 215 query = "Do you wish to write new GPT?"; 216 } else { 217 MBR_init(&initial_mbr); 218 query = "Do you wish to write new MBR and " 219 "partition table?"; 220 } 221 } else if (u_flag) { 222 memcpy(initial_mbr.part, mbr.part, sizeof(initial_mbr.part)); 223 query = "Do you wish to write new MBR?"; 224 } 225 if (query && ask_yn(query)) 226 Xwrite(NULL, &initial_mbr); 227 228 if (e_flag) 229 USER_edit(0, 0); 230 231 done: 232 close(disk.fd); 233 234 return (0); 235 } 236