1 /* $OpenBSD: user.c,v 1.67 2021/07/21 12:22:54 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 const 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 ask_cmd(char **, char **); 59 60 void 61 USER_edit(const uint64_t lba_self, const uint64_t lba_firstembr) 62 { 63 struct mbr mbr; 64 char *cmd, *args; 65 int i, st, error; 66 static int editlevel; 67 68 /* One level deeper */ 69 editlevel += 1; 70 71 error = MBR_read(lba_self, lba_firstembr, &mbr); 72 if (error == -1) 73 goto done; 74 75 if (editlevel == 1) 76 GPT_read(ANYGPT); 77 78 printf("Enter 'help' for information\n"); 79 80 again: 81 do { 82 printf("%s%s: %d> ", disk.dk_name, modified ? "*" : "", editlevel); 83 fflush(stdout); 84 ask_cmd(&cmd, &args); 85 86 if (cmd[0] == '\0') 87 continue; 88 for (i = 0; cmd_table[i].cmd_name != NULL; i++) 89 if (strstr(cmd_table[i].cmd_name, cmd) == cmd_table[i].cmd_name) 90 break; 91 92 /* Quick hack to put in '?' == 'help' */ 93 if (!strcmp(cmd, "?")) 94 i = 0; 95 96 if ((cmd_table[i].cmd_name == NULL) || (letoh64(gh.gh_sig) == 97 GPTSIGNATURE && cmd_table[i].cmd_gpt == 0)) { 98 printf("Invalid command '%s'. Try 'help'.\n", cmd); 99 continue; 100 } 101 102 st = cmd_table[i].cmd_fcn(args, &mbr); 103 104 /* Update status */ 105 if (st == CMD_EXIT) 106 break; 107 if (st == CMD_SAVE) 108 break; 109 if (st == CMD_CLEAN) 110 modified = 0; 111 if (st == CMD_DIRTY) 112 modified = 1; 113 } while (1); 114 115 if (modified) { 116 if (st == CMD_SAVE) { 117 if (Xwrite(NULL, &mbr) == CMD_CONT) 118 goto again; 119 } else 120 printf("Aborting changes to current MBR.\n"); 121 } 122 123 done: 124 editlevel -= 1; 125 } 126 127 void 128 USER_print_disk(const int verbosity) 129 { 130 struct mbr mbr; 131 uint64_t lba_self, lba_firstembr; 132 int i, error; 133 134 lba_self = lba_firstembr = 0; 135 136 do { 137 error = MBR_read(lba_self, lba_firstembr, &mbr); 138 if (error == -1) 139 break; 140 if (lba_self == 0) { 141 if (GPT_read(ANYGPT)) { 142 if (verbosity == VERBOSE) { 143 printf("Primary GPT:\nNot Found\n"); 144 printf("\nSecondary GPT:\nNot Found\n"); 145 } 146 } else if (verbosity == TERSE) { 147 GPT_print("s", verbosity); 148 return; 149 } else { 150 printf("Primary GPT:\n"); 151 GPT_read(PRIMARYGPT); 152 if (letoh64(gh.gh_sig) == GPTSIGNATURE) 153 GPT_print("s", verbosity); 154 else 155 printf("\tNot Found\n"); 156 printf("\nSecondary GPT:\n"); 157 GPT_read(SECONDARYGPT); 158 if (letoh64(gh.gh_sig) == GPTSIGNATURE) 159 GPT_print("s", verbosity); 160 else 161 printf("\tNot Found\n"); 162 } 163 if (verbosity == VERBOSE) 164 printf("\nMBR:\n"); 165 } 166 167 MBR_print(&mbr, NULL); 168 169 for (lba_self = i = 0; i < 4; i++) 170 if (mbr.mbr_prt[i].prt_id == DOSPTYP_EXTEND || 171 mbr.mbr_prt[i].prt_id == DOSPTYP_EXTENDL) { 172 lba_self = mbr.mbr_prt[i].prt_bs; 173 if (lba_firstembr == 0) 174 lba_firstembr = lba_self; 175 } 176 } while (lba_self); 177 } 178 179 void 180 ask_cmd(char **cmd, char **arg) 181 { 182 static char lbuf[100]; 183 size_t cmdstart, cmdend, argstart; 184 185 if (string_from_line(lbuf, sizeof(lbuf))) 186 errx(1, "eof"); 187 188 cmdstart = strspn(lbuf, " \t"); 189 cmdend = cmdstart + strcspn(&lbuf[cmdstart], " \t"); 190 argstart = cmdend + strspn(&lbuf[cmdend], " \t"); 191 192 /* *cmd and *arg may be set to point at final NUL! */ 193 *cmd = &lbuf[cmdstart]; 194 lbuf[cmdend] = '\0'; 195 *arg = &lbuf[argstart]; 196 } 197