1 /* $OpenBSD: user.c,v 1.25 2011/02/21 19:26:13 krw Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Tobias Weingartner 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <err.h> 29 #include <errno.h> 30 #include <util.h> 31 #include <stdio.h> 32 #include <unistd.h> 33 #include <string.h> 34 #include <sys/fcntl.h> 35 #include <sys/types.h> 36 #include <sys/stat.h> 37 #include <sys/disklabel.h> 38 #include <machine/param.h> 39 #include "user.h" 40 #include "disk.h" 41 #include "misc.h" 42 #include "mbr.h" 43 #include "cmd.h" 44 45 46 /* Our command table */ 47 static cmd_table_t cmd_table[] = { 48 {"help", Xhelp, "Command help list"}, 49 {"manual", Xmanual, "Show entire OpenBSD man page for fdisk"}, 50 {"reinit", Xreinit, "Re-initialize loaded MBR (to defaults)"}, 51 {"setpid", Xsetpid, "Set the identifier of a given table entry"}, 52 {"disk", Xdisk, "Edit current drive stats"}, 53 {"edit", Xedit, "Edit given table entry"}, 54 {"flag", Xflag, "Flag given table entry as bootable"}, 55 {"update", Xupdate, "Update machine code in loaded MBR"}, 56 {"select", Xselect, "Select extended partition table entry MBR"}, 57 {"swap", Xswap, "Swap two partition entries"}, 58 {"print", Xprint, "Print loaded MBR partition table"}, 59 {"write", Xwrite, "Write loaded MBR to disk"}, 60 {"exit", Xexit, "Exit edit of current MBR, without saving changes"}, 61 {"quit", Xquit, "Quit edit of current MBR, saving current changes"}, 62 {"abort", Xabort, "Abort program without saving current changes"}, 63 {NULL, NULL, NULL} 64 }; 65 66 67 int 68 USER_init(disk_t *disk, mbr_t *tt, int preserve) 69 { 70 char *query; 71 72 if (preserve) { 73 MBR_pcopy(disk, tt); 74 query = "Do you wish to write new MBR?"; 75 } else { 76 MBR_init(disk, tt); 77 query = "Do you wish to write new MBR and partition table?"; 78 } 79 80 if (ask_yn(query)) 81 Xwrite(NULL, disk, tt, NULL, 0); 82 83 return (0); 84 } 85 86 int modified; 87 88 int 89 USER_modify(disk_t *disk, mbr_t *tt, off_t offset, off_t reloff) 90 { 91 static int editlevel; 92 char mbr_buf[DEV_BSIZE]; 93 mbr_t mbr; 94 cmd_t cmd; 95 int i, st, fd, error; 96 97 /* One level deeper */ 98 editlevel += 1; 99 100 /* Set up command table pointer */ 101 cmd.table = cmd_table; 102 103 /* Read MBR & partition */ 104 fd = DISK_open(disk->name, O_RDONLY); 105 error = MBR_read(fd, offset, mbr_buf); 106 close(fd); 107 if (error == -1) 108 goto done; 109 110 /* Parse the sucker */ 111 MBR_parse(disk, mbr_buf, offset, reloff, &mbr); 112 113 printf("Enter 'help' for information\n"); 114 115 /* Edit cycle */ 116 do { 117 again: 118 printf("fdisk:%c%d> ", (modified)?'*':' ', editlevel); 119 fflush(stdout); 120 ask_cmd(&cmd); 121 122 if (cmd.cmd[0] == '\0') 123 goto again; 124 for (i = 0; cmd_table[i].cmd != NULL; i++) 125 if (strstr(cmd_table[i].cmd, cmd.cmd)==cmd_table[i].cmd) 126 break; 127 128 /* Quick hack to put in '?' == 'help' */ 129 if (!strcmp(cmd.cmd, "?")) 130 i = 0; 131 132 /* Check for valid command */ 133 if (cmd_table[i].cmd == NULL) { 134 printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd); 135 continue; 136 } else 137 strlcpy(cmd.cmd, cmd_table[i].cmd, sizeof cmd.cmd); 138 139 /* Call function */ 140 st = cmd_table[i].fcn(&cmd, disk, &mbr, tt, offset); 141 142 /* Update status */ 143 if (st == CMD_EXIT) 144 break; 145 if (st == CMD_SAVE) 146 break; 147 if (st == CMD_CLEAN) 148 modified = 0; 149 if (st == CMD_DIRTY) 150 modified = 1; 151 } while (1); 152 153 /* Write out MBR */ 154 if (modified) { 155 if (st == CMD_SAVE) { 156 if (Xwrite(NULL, disk, &mbr, NULL, offset) == CMD_CONT) 157 goto again; 158 close(fd); 159 } else 160 printf("Aborting changes to current MBR.\n"); 161 } 162 163 done: 164 /* One level less */ 165 editlevel -= 1; 166 167 return (0); 168 } 169 170 int 171 USER_print_disk(disk_t *disk) 172 { 173 off_t offset, firstoff; 174 int fd, i, error; 175 char mbr_buf[DEV_BSIZE]; 176 mbr_t mbr; 177 178 fd = DISK_open(disk->name, O_RDONLY); 179 offset = firstoff = 0; 180 181 DISK_printmetrics(disk, NULL); 182 183 do { 184 error = MBR_read(fd, offset, mbr_buf); 185 if (error == -1) 186 break; 187 MBR_parse(disk, mbr_buf, offset, firstoff, &mbr); 188 189 printf("Offset: %lld\t", offset); 190 MBR_print(&mbr, NULL); 191 192 /* Print out extended partitions too */ 193 for (offset = i = 0; i < 4; i++) 194 if (mbr.part[i].id == DOSPTYP_EXTEND || 195 mbr.part[i].id == DOSPTYP_EXTENDL) { 196 offset = (off_t)mbr.part[i].bs; 197 if (firstoff == 0) 198 firstoff = offset; 199 } 200 } while (offset); 201 202 return (close(fd)); 203 } 204 205