1 /* $OpenBSD: user.c,v 1.17 2001/12/15 02:12:26 kjell 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Tobias Weingartner. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <err.h> 34 #include <util.h> 35 #include <stdio.h> 36 #include <unistd.h> 37 #include <string.h> 38 #include <sys/fcntl.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <sys/disklabel.h> 42 #include <machine/param.h> 43 #include "user.h" 44 #include "disk.h" 45 #include "misc.h" 46 #include "mbr.h" 47 #include "cmd.h" 48 49 50 /* Our command table */ 51 static cmd_table_t cmd_table[] = { 52 {"help", Xhelp, "Command help list"}, 53 {"manual", Xmanual, "Show entire OpenBSD man page for fdisk"}, 54 {"reinit", Xreinit, "Re-initialize loaded MBR (to defaults)"}, 55 {"setpid", Xsetpid, "Set the identifier of a given table entry"}, 56 {"disk", Xdisk, "Edit current drive stats"}, 57 {"edit", Xedit, "Edit given table entry"}, 58 {"flag", Xflag, "Flag given table entry as bootable"}, 59 {"update", Xupdate, "Update machine code in loaded MBR"}, 60 {"select", Xselect, "Select extended partition table entry MBR"}, 61 {"print", Xprint, "Print loaded MBR partition table"}, 62 {"write", Xwrite, "Write loaded MBR to disk"}, 63 {"exit", Xexit, "Exit edit of current MBR, without saving changes"}, 64 {"quit", Xquit, "Quit edit of current MBR, saving current changes"}, 65 {"abort", Xabort, "Abort program without saving current changes"}, 66 {NULL, NULL, NULL} 67 }; 68 69 70 int 71 USER_init(disk, tt, preserve) 72 disk_t *disk; 73 mbr_t *tt; 74 int preserve; 75 { 76 int fd, yn; 77 char mbr_buf[DEV_BSIZE]; 78 char *msgp = "\nDo you wish to write new MBR?"; 79 char *msgk = "\nDo you wish to write new MBR and partition table?"; 80 81 if (preserve) 82 MBR_pcopy(disk, tt); 83 else 84 MBR_init(disk, tt); 85 86 /* Write sector 0 */ 87 printf("\a\n" 88 "\t-----------------------------------------------------\n" 89 "\t------ ATTENTION - UPDATING MASTER BOOT RECORD ------\n" 90 "\t-----------------------------------------------------\n"); 91 if (preserve) 92 yn = ask_yn(msgp); 93 else 94 yn = ask_yn(msgk); 95 96 if (yn) { 97 fd = DISK_open(disk->name, O_RDWR); 98 MBR_make(tt, mbr_buf); 99 MBR_write(fd, (off_t)0, mbr_buf); 100 DISK_close(fd); 101 } else 102 printf("MBR is unchanged\n"); 103 104 return (0); 105 } 106 107 int modified; 108 109 int 110 USER_modify(disk, tt, offset, reloff) 111 disk_t *disk; 112 mbr_t *tt; 113 off_t offset; 114 off_t reloff; 115 { 116 static int editlevel; 117 char mbr_buf[DEV_BSIZE]; 118 mbr_t mbr; 119 cmd_t cmd; 120 int i, st, fd; 121 122 /* One level deeper */ 123 editlevel += 1; 124 125 /* Set up command table pointer */ 126 cmd.table = cmd_table; 127 128 /* Read MBR & partition */ 129 fd = DISK_open(disk->name, O_RDONLY); 130 MBR_read(fd, offset, mbr_buf); 131 DISK_close(fd); 132 133 /* Parse the sucker */ 134 MBR_parse(disk, mbr_buf, offset, reloff, &mbr); 135 136 printf("Enter 'help' for information\n"); 137 138 /* Edit cycle */ 139 do { 140 again: 141 printf("fdisk:%c%d> ", (modified)?'*':' ', editlevel); 142 fflush(stdout); 143 ask_cmd(&cmd); 144 145 if (cmd.cmd[0] == '\0') 146 goto again; 147 for (i = 0; cmd_table[i].cmd != NULL; i++) 148 if (strstr(cmd_table[i].cmd, cmd.cmd)==cmd_table[i].cmd) 149 break; 150 151 /* Quick hack to put in '?' == 'help' */ 152 if (!strcmp(cmd.cmd, "?")) 153 i = 0; 154 155 /* Check for valid command */ 156 if (cmd_table[i].cmd == NULL) { 157 printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd); 158 continue; 159 } else 160 strcpy(cmd.cmd, cmd_table[i].cmd); 161 162 /* Call function */ 163 st = cmd_table[i].fcn(&cmd, disk, &mbr, tt, offset); 164 165 /* Update status */ 166 if (st == CMD_EXIT) 167 break; 168 if (st == CMD_SAVE) 169 break; 170 if (st == CMD_CLEAN) 171 modified = 0; 172 if (st == CMD_DIRTY) 173 modified = 1; 174 } while (1); 175 176 /* Write out MBR */ 177 if (modified) { 178 if (st == CMD_SAVE) { 179 printf("Writing current MBR to disk.\n"); 180 fd = DISK_open(disk->name, O_RDWR); 181 MBR_make(&mbr, mbr_buf); 182 MBR_write(fd, offset, mbr_buf); 183 close(fd); 184 } else 185 printf("Aborting changes to current MBR.\n"); 186 } 187 188 /* One level less */ 189 editlevel -= 1; 190 191 return (0); 192 } 193 194 int 195 USER_print_disk(disk) 196 disk_t *disk; 197 { 198 int fd, offset, firstoff, i; 199 char mbr_buf[DEV_BSIZE]; 200 mbr_t mbr; 201 202 fd = DISK_open(disk->name, O_RDONLY); 203 offset = firstoff = 0; 204 205 DISK_printmetrics(disk); 206 207 do { 208 MBR_read(fd, (off_t)offset, mbr_buf); 209 MBR_parse(disk, mbr_buf, offset, firstoff, &mbr); 210 211 printf("Offset: %d\t", (int)offset); 212 MBR_print(&mbr); 213 214 /* Print out extended partitions too */ 215 for (offset = i = 0; i < 4; i++) 216 if (mbr.part[i].id == DOSPTYP_EXTEND || 217 mbr.part[i].id == DOSPTYP_EXTENDL) { 218 offset = mbr.part[i].bs; 219 if (firstoff == 0) 220 firstoff = offset; 221 } 222 } while (offset); 223 224 return (DISK_close(fd)); 225 } 226 227