1 /* $OpenBSD: fdisk.c,v 1.101 2016/06/25 17:03:22 tb 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/fcntl.h> 21 #include <sys/disklabel.h> 22 23 #include <err.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 (letoh64(gh.gh_sig) != GPTSIGNATURE) { 182 if (DL_GETDSIZE(&dl) > disk.size) 183 warnx("disk too large (%llu sectors). size truncated.", 184 (unsigned long long)DL_GETDSIZE(&dl)); 185 } 186 187 if (!(i_flag || u_flag || e_flag)) { 188 if (pledge("stdio", NULL) == -1) 189 err(1, "pledge"); 190 USER_print_disk(verbosity); 191 goto done; 192 } 193 194 /* Create initial/default MBR. */ 195 if (mbrfile == NULL) { 196 memcpy(&dos_mbr, builtin_mbr, sizeof(dos_mbr)); 197 } else { 198 fd = open(mbrfile, O_RDONLY); 199 if (fd == -1) { 200 warn("%s", mbrfile); 201 warnx("using builtin MBR"); 202 memcpy(&dos_mbr, builtin_mbr, sizeof(dos_mbr)); 203 } else { 204 len = read(fd, &dos_mbr, sizeof(dos_mbr)); 205 close(fd); 206 if (len == -1) 207 err(1, "Unable to read MBR from '%s'", mbrfile); 208 else if (len != sizeof(dos_mbr)) 209 errx(1, "Unable to read complete MBR from '%s'", 210 mbrfile); 211 } 212 } 213 MBR_parse(&dos_mbr, 0, 0, &initial_mbr); 214 215 query = NULL; 216 if (i_flag) { 217 reinited = 1; 218 if (g_flag) { 219 MBR_init_GPT(&initial_mbr); 220 GPT_init(); 221 query = "Do you wish to write new GPT?"; 222 } else { 223 MBR_init(&initial_mbr); 224 query = "Do you wish to write new MBR and " 225 "partition table?"; 226 } 227 } else if (u_flag) { 228 memcpy(initial_mbr.part, mbr.part, sizeof(initial_mbr.part)); 229 query = "Do you wish to write new MBR?"; 230 } 231 if (query && ask_yn(query)) 232 Xwrite(NULL, &initial_mbr); 233 234 if (e_flag) 235 USER_edit(0, 0); 236 237 done: 238 close(disk.fd); 239 240 return (0); 241 } 242