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