1 /* $OpenBSD: user.c,v 1.83 2022/07/18 15:06:22 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 <stdio.h> 24 #include <string.h> 25 26 #include "part.h" 27 #include "mbr.h" 28 #include "misc.h" 29 #include "cmd.h" 30 #include "user.h" 31 #include "gpt.h" 32 #include "disk.h" 33 34 struct cmd { 35 char *cmd_name; 36 int cmd_gpt; 37 int (*cmd_fcn)(const char *, struct mbr *); 38 char *cmd_help; 39 }; 40 41 const struct cmd cmd_table[] = { 42 {"help", 1, Xhelp, "Display summary of available commands"}, 43 {"manual", 1, Xmanual, "Display fdisk man page"}, 44 {"reinit", 1, Xreinit, "Initialize the partition table"}, 45 {"setpid", 1, Xsetpid, "Set identifier of table entry"}, 46 {"edit", 1, Xedit, "Edit table entry"}, 47 {"flag", 1, Xflag, "Set flag value of table entry"}, 48 {"update", 0, Xupdate, "Update MBR bootcode"}, 49 {"select", 0, Xselect, "Select MBR extended table entry"}, 50 {"swap", 1, Xswap, "Swap two table entries"}, 51 {"print", 1, Xprint, "Print partition table"}, 52 {"write", 1, Xwrite, "Write partition table to disk"}, 53 {"exit", 1, Xexit, "Discard changes and exit edit level"}, 54 {"quit", 1, Xquit, "Save changes and exit edit level"}, 55 {"abort", 1, Xabort, "Discard changes and terminate fdisk"}, 56 }; 57 58 int modified; 59 60 int ask_cmd(char **); 61 62 void 63 USER_edit(const uint64_t lba_self, const uint64_t lba_firstembr) 64 { 65 struct mbr mbr; 66 char *args; 67 int i, st; 68 static int editlevel; 69 70 if (MBR_read(lba_self, lba_firstembr, &mbr)) 71 return; 72 73 editlevel += 1; 74 75 if (editlevel == 1) 76 GPT_read(ANYGPT); 77 78 printf("Enter 'help' for information\n"); 79 80 for (;;) { 81 if (gh.gh_sig == GPTSIGNATURE && editlevel > 1) 82 break; /* 'reinit gpt'. Unwind recursion! */ 83 84 printf("%s%s: %d> ", disk.dk_name, modified ? "*" : "", 85 editlevel); 86 fflush(stdout); 87 i = ask_cmd(&args); 88 if (i == -1) 89 continue; 90 91 st = cmd_table[i].cmd_fcn(args ? args : "", &mbr); 92 93 if (st == CMD_EXIT) { 94 if (modified) 95 printf("Aborting changes to current MBR\n"); 96 break; 97 } 98 if (st == CMD_QUIT) { 99 if (modified && Xwrite(NULL, &mbr) == CMD_CONT) 100 continue; 101 break; 102 } 103 if (st == CMD_CLEAN) 104 modified = 0; 105 if (st == CMD_DIRTY) 106 modified = 1; 107 } 108 109 editlevel -= 1; 110 } 111 112 void 113 USER_print_disk(const int verbosity) 114 { 115 struct mbr mbr; 116 uint64_t lba_self, lba_firstembr; 117 int i; 118 119 lba_self = lba_firstembr = 0; 120 121 do { 122 if (MBR_read(lba_self, lba_firstembr, &mbr)) 123 break; 124 if (lba_self == 0) { 125 if (GPT_read(ANYGPT)) { 126 if (verbosity == VERBOSE) { 127 printf("Primary GPT:\nNot Found\n"); 128 printf("\nSecondary GPT:\nNot Found\n"); 129 } 130 } else if (verbosity == TERSE) { 131 GPT_print("s", verbosity); 132 return; 133 } else { 134 printf("Primary GPT:\n"); 135 GPT_read(PRIMARYGPT); 136 if (gh.gh_sig == GPTSIGNATURE) 137 GPT_print("s", verbosity); 138 else 139 printf("\tNot Found\n"); 140 printf("\nSecondary GPT:\n"); 141 GPT_read(SECONDARYGPT); 142 if (gh.gh_sig == GPTSIGNATURE) 143 GPT_print("s", verbosity); 144 else 145 printf("\tNot Found\n"); 146 } 147 if (verbosity == VERBOSE) 148 printf("\nMBR:\n"); 149 } 150 151 MBR_print(&mbr, "s"); 152 153 for (lba_self = i = 0; i < 4; i++) 154 if (mbr.mbr_prt[i].prt_id == DOSPTYP_EXTEND || 155 mbr.mbr_prt[i].prt_id == DOSPTYP_EXTENDL) { 156 lba_self = mbr.mbr_prt[i].prt_bs; 157 if (lba_firstembr == 0) 158 lba_firstembr = lba_self; 159 } 160 } while (lba_self); 161 } 162 163 void 164 USER_help(void) 165 { 166 unsigned int i; 167 168 for (i = 0; i < nitems(cmd_table); i++) { 169 if (gh.gh_sig == GPTSIGNATURE && cmd_table[i].cmd_gpt == 0) 170 continue; 171 printf("\t%s\t\t%s\n", cmd_table[i].cmd_name, 172 cmd_table[i].cmd_help); 173 } 174 } 175 176 int 177 ask_cmd(char **arg) 178 { 179 static char lbuf[LINEBUFSZ]; 180 char *cmd; 181 unsigned int i; 182 183 string_from_line(lbuf, sizeof(lbuf), TRIMMED); 184 185 *arg = lbuf; 186 cmd = strsep(arg, WHITESPACE); 187 188 if (*arg != NULL) 189 *arg += strspn(*arg, WHITESPACE); 190 191 if (strlen(cmd) == 0) 192 return -1; 193 if (strcmp(cmd, "?") == 0) 194 cmd = "help"; 195 196 for (i = 0; i < nitems(cmd_table); i++) { 197 if (gh.gh_sig == GPTSIGNATURE && cmd_table[i].cmd_gpt == 0) 198 continue; 199 if (strstr(cmd_table[i].cmd_name, cmd) == cmd_table[i].cmd_name) 200 return i; 201 } 202 203 printf("Invalid command '%s", cmd); 204 if (*arg && strlen(*arg) > 0) 205 printf(" %s", *arg); 206 printf("'. Try 'help'.\n"); 207 208 return -1; 209 } 210