1 /* $OpenBSD: user.c,v 1.51 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 <stdio.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 #include "part.h" 29 #include "mbr.h" 30 #include "misc.h" 31 #include "cmd.h" 32 #include "user.h" 33 #include "gpt.h" 34 35 /* Our command table */ 36 struct cmd cmd_table[] = { 37 {"help", 1, Xhelp, "Command help list"}, 38 {"manual", 1, Xmanual, "Show entire OpenBSD man page for fdisk"}, 39 {"reinit", 1, Xreinit, "Re-initialize loaded MBR (to defaults)"}, 40 {"setpid", 1, Xsetpid, "Set the identifier of a given table entry"}, 41 {"disk", 0, Xdisk, "Edit current drive stats"}, 42 {"edit", 1, Xedit, "Edit given table entry"}, 43 {"flag", 1, Xflag, "Flag given table entry as bootable"}, 44 {"update", 0, Xupdate, "Update machine code in loaded MBR"}, 45 {"select", 0, Xselect, "Select extended partition table entry MBR"}, 46 {"swap", 1, Xswap, "Swap two partition entries"}, 47 {"print", 1, Xprint, "Print loaded MBR partition table"}, 48 {"write", 1, Xwrite, "Write loaded MBR to disk"}, 49 {"exit", 1, Xexit, "Exit edit of current MBR, without saving changes"}, 50 {"quit", 1, Xquit, "Quit edit of current MBR, saving current changes"}, 51 {"abort", 1, Xabort, "Abort program without saving current changes"}, 52 {NULL, 0, NULL, NULL} 53 }; 54 55 56 int modified; 57 58 void 59 USER_edit(off_t offset, off_t reloff) 60 { 61 static int editlevel; 62 struct dos_mbr dos_mbr; 63 struct mbr mbr; 64 char *cmd, *args; 65 int i, st, error; 66 67 /* One level deeper */ 68 editlevel += 1; 69 70 /* Read MBR & partition */ 71 error = MBR_read(offset, &dos_mbr); 72 if (error == -1) 73 goto done; 74 75 /* Parse the sucker */ 76 MBR_parse(&dos_mbr, offset, reloff, &mbr); 77 78 if (editlevel == 1) { 79 memset(&gh, 0, sizeof(gh)); 80 memset(&gp, 0, sizeof(gp)); 81 if (MBR_protective_mbr(&mbr) == 0) 82 GPT_get_gpt(0); 83 } 84 85 printf("Enter 'help' for information\n"); 86 87 /* Edit cycle */ 88 again: 89 do { 90 printf("fdisk:%c%d> ", (modified)?'*':' ', editlevel); 91 fflush(stdout); 92 ask_cmd(&cmd, &args); 93 94 if (cmd[0] == '\0') 95 continue; 96 for (i = 0; cmd_table[i].cmd != NULL; i++) 97 if (strstr(cmd_table[i].cmd, cmd) == cmd_table[i].cmd) 98 break; 99 100 /* Quick hack to put in '?' == 'help' */ 101 if (!strcmp(cmd, "?")) 102 i = 0; 103 104 /* Check for valid command */ 105 if ((cmd_table[i].cmd == NULL) || (letoh64(gh.gh_sig) == 106 GPTSIGNATURE && cmd_table[i].gpt == 0)) { 107 printf("Invalid command '%s'. Try 'help'.\n", cmd); 108 continue; 109 } 110 111 /* Call function */ 112 st = cmd_table[i].fcn(args, &mbr); 113 114 /* Update status */ 115 if (st == CMD_EXIT) 116 break; 117 if (st == CMD_SAVE) 118 break; 119 if (st == CMD_CLEAN) 120 modified = 0; 121 if (st == CMD_DIRTY) 122 modified = 1; 123 } while (1); 124 125 /* Write out MBR */ 126 if (modified) { 127 if (st == CMD_SAVE) { 128 if (Xwrite(NULL, &mbr) == CMD_CONT) 129 goto again; 130 } else 131 printf("Aborting changes to current MBR.\n"); 132 } 133 134 done: 135 /* One level less */ 136 editlevel -= 1; 137 } 138 139 void 140 USER_print_disk(int verbosity) 141 { 142 off_t offset, firstoff; 143 int i, error; 144 struct dos_mbr dos_mbr; 145 struct mbr mbr; 146 147 offset = firstoff = 0; 148 149 do { 150 error = MBR_read(offset, &dos_mbr); 151 if (error == -1) 152 break; 153 MBR_parse(&dos_mbr, offset, firstoff, &mbr); 154 if (offset == 0) { 155 if (verbosity || MBR_protective_mbr(&mbr) == 0) { 156 if (verbosity) { 157 printf("Primary GPT:\n"); 158 GPT_get_gpt(1); /* Get Primary */ 159 } 160 if (letoh64(gh.gh_sig) == GPTSIGNATURE) 161 GPT_print("s", verbosity); 162 else 163 printf("\tNot Found\n"); 164 if (verbosity) { 165 printf("\n"); 166 printf("Secondary GPT:\n"); 167 GPT_get_gpt(2); /* Get Secondary */ 168 if (letoh64(gh.gh_sig) == GPTSIGNATURE) 169 GPT_print("s", verbosity); 170 else 171 printf("\tNot Found\n"); 172 printf("\nMBR:\n"); 173 } else 174 break; 175 } 176 } 177 178 MBR_print(&mbr, NULL); 179 180 /* Print out extended partitions too */ 181 for (offset = i = 0; i < 4; i++) 182 if (mbr.part[i].id == DOSPTYP_EXTEND || 183 mbr.part[i].id == DOSPTYP_EXTENDL) { 184 offset = (off_t)mbr.part[i].bs; 185 if (firstoff == 0) 186 firstoff = offset; 187 } 188 } while (offset); 189 } 190