1 /* $OpenBSD: user.c,v 1.16 2001/01/01 21:05:34 angelos 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) 72 disk_t *disk; 73 mbr_t *tt; 74 { 75 int fd; 76 char mbr_buf[DEV_BSIZE]; 77 78 MBR_init(disk, tt); 79 80 /* Write sector 0 */ 81 printf("\a\n" 82 "\t-----------------------------------------------------\n" 83 "\t------ ATTENTION - UPDATING MASTER BOOT RECORD ------\n" 84 "\t-----------------------------------------------------\n"); 85 if (ask_yn("\nDo you wish to write new MBR?")) { 86 fd = DISK_open(disk->name, O_RDWR); 87 MBR_make(tt, mbr_buf); 88 MBR_write(fd, (off_t)0, mbr_buf); 89 DISK_close(fd); 90 } else 91 printf("MBR is unchanged\n"); 92 93 return (0); 94 } 95 96 int modified; 97 98 int 99 USER_modify(disk, tt, offset, reloff) 100 disk_t *disk; 101 mbr_t *tt; 102 off_t offset; 103 off_t reloff; 104 { 105 static int editlevel; 106 char mbr_buf[DEV_BSIZE]; 107 mbr_t mbr; 108 cmd_t cmd; 109 int i, st, fd; 110 111 /* One level deeper */ 112 editlevel += 1; 113 114 /* Set up command table pointer */ 115 cmd.table = cmd_table; 116 117 /* Read MBR & partition */ 118 fd = DISK_open(disk->name, O_RDONLY); 119 MBR_read(fd, offset, mbr_buf); 120 DISK_close(fd); 121 122 /* Parse the sucker */ 123 MBR_parse(disk, mbr_buf, offset, reloff, &mbr); 124 125 printf("Enter 'help' for information\n"); 126 127 /* Edit cycle */ 128 do { 129 again: 130 printf("fdisk:%c%d> ", (modified)?'*':' ', editlevel); 131 fflush(stdout); 132 ask_cmd(&cmd); 133 134 if (cmd.cmd[0] == '\0') 135 goto again; 136 for (i = 0; cmd_table[i].cmd != NULL; i++) 137 if (strstr(cmd_table[i].cmd, cmd.cmd)==cmd_table[i].cmd) 138 break; 139 140 /* Quick hack to put in '?' == 'help' */ 141 if (!strcmp(cmd.cmd, "?")) 142 i = 0; 143 144 /* Check for valid command */ 145 if (cmd_table[i].cmd == NULL) { 146 printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd); 147 continue; 148 } else 149 strcpy(cmd.cmd, cmd_table[i].cmd); 150 151 /* Call function */ 152 st = cmd_table[i].fcn(&cmd, disk, &mbr, tt, offset); 153 154 /* Update status */ 155 if (st == CMD_EXIT) 156 break; 157 if (st == CMD_SAVE) 158 break; 159 if (st == CMD_CLEAN) 160 modified = 0; 161 if (st == CMD_DIRTY) 162 modified = 1; 163 } while (1); 164 165 /* Write out MBR */ 166 if (modified) { 167 if (st == CMD_SAVE) { 168 printf("Writing current MBR to disk.\n"); 169 fd = DISK_open(disk->name, O_RDWR); 170 MBR_make(&mbr, mbr_buf); 171 MBR_write(fd, offset, mbr_buf); 172 close(fd); 173 } else 174 printf("Aborting changes to current MBR.\n"); 175 } 176 177 /* One level less */ 178 editlevel -= 1; 179 180 return (0); 181 } 182 183 int 184 USER_print_disk(disk) 185 disk_t *disk; 186 { 187 int fd, offset, firstoff, i; 188 char mbr_buf[DEV_BSIZE]; 189 mbr_t mbr; 190 191 fd = DISK_open(disk->name, O_RDONLY); 192 offset = firstoff = 0; 193 194 DISK_printmetrics(disk); 195 196 do { 197 MBR_read(fd, (off_t)offset, mbr_buf); 198 MBR_parse(disk, mbr_buf, offset, firstoff, &mbr); 199 200 printf("Offset: %d\t", (int)offset); 201 MBR_print(&mbr); 202 203 /* Print out extended partitions too */ 204 for (offset = i = 0; i < 4; i++) 205 if (mbr.part[i].id == DOSPTYP_EXTEND || 206 mbr.part[i].id == DOSPTYP_EXTENDL) { 207 offset = mbr.part[i].bs; 208 if (firstoff == 0) 209 firstoff = offset; 210 } 211 } while (offset); 212 213 return (DISK_close(fd)); 214 } 215 216