1 /* $OpenBSD: user.c,v 1.35 2014/03/31 22:03:29 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 <sys/types.h> 29 #include <sys/fcntl.h> 30 #include <sys/disklabel.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <unistd.h> 34 35 #include "disk.h" 36 #include "part.h" 37 #include "mbr.h" 38 #include "misc.h" 39 #include "cmd.h" 40 #include "user.h" 41 42 /* Our command table */ 43 struct cmd cmd_table[] = { 44 {"help", Xhelp, "Command help list"}, 45 {"manual", Xmanual, "Show entire OpenBSD man page for fdisk"}, 46 {"reinit", Xreinit, "Re-initialize loaded MBR (to defaults)"}, 47 {"setpid", Xsetpid, "Set the identifier of a given table entry"}, 48 {"disk", Xdisk, "Edit current drive stats"}, 49 {"edit", Xedit, "Edit given table entry"}, 50 {"flag", Xflag, "Flag given table entry as bootable"}, 51 {"update", Xupdate, "Update machine code in loaded MBR"}, 52 {"select", Xselect, "Select extended partition table entry MBR"}, 53 {"swap", Xswap, "Swap two partition entries"}, 54 {"print", Xprint, "Print loaded MBR partition table"}, 55 {"write", Xwrite, "Write loaded MBR to disk"}, 56 {"exit", Xexit, "Exit edit of current MBR, without saving changes"}, 57 {"quit", Xquit, "Quit edit of current MBR, saving current changes"}, 58 {"abort", Xabort, "Abort program without saving current changes"}, 59 {NULL, NULL, NULL} 60 }; 61 62 int 63 USER_init(struct disk *disk, struct mbr *tt, int preserve) 64 { 65 char *query; 66 67 if (preserve) { 68 MBR_pcopy(disk, tt); 69 query = "Do you wish to write new MBR?"; 70 } else { 71 MBR_init(disk, tt); 72 query = "Do you wish to write new MBR and partition table?"; 73 } 74 75 if (ask_yn(query)) 76 Xwrite(NULL, disk, tt, NULL, 0); 77 78 return (0); 79 } 80 81 int modified; 82 83 int 84 USER_modify(struct disk *disk, struct mbr *tt, off_t offset, off_t reloff) 85 { 86 static int editlevel; 87 struct dos_mbr dos_mbr; 88 struct mbr mbr; 89 char *cmd, *args; 90 int i, st, fd, error; 91 92 /* One level deeper */ 93 editlevel += 1; 94 95 /* Read MBR & partition */ 96 fd = DISK_open(disk->name, O_RDONLY); 97 error = MBR_read(fd, offset, &dos_mbr); 98 close(fd); 99 if (error == -1) 100 goto done; 101 102 /* Parse the sucker */ 103 MBR_parse(disk, &dos_mbr, offset, reloff, &mbr); 104 105 printf("Enter 'help' for information\n"); 106 107 /* Edit cycle */ 108 do { 109 again: 110 printf("fdisk:%c%d> ", (modified)?'*':' ', editlevel); 111 fflush(stdout); 112 ask_cmd(&cmd, &args); 113 114 if (cmd[0] == '\0') 115 goto again; 116 for (i = 0; cmd_table[i].cmd != NULL; i++) 117 if (strstr(cmd_table[i].cmd, cmd) == cmd_table[i].cmd) 118 break; 119 120 /* Quick hack to put in '?' == 'help' */ 121 if (!strcmp(cmd, "?")) 122 i = 0; 123 124 /* Check for valid command */ 125 if (cmd_table[i].cmd == NULL) { 126 printf("Invalid command '%s'. Try 'help'.\n", cmd); 127 continue; 128 } 129 130 /* Call function */ 131 st = cmd_table[i].fcn(args, disk, &mbr, tt, offset); 132 133 /* Update status */ 134 if (st == CMD_EXIT) 135 break; 136 if (st == CMD_SAVE) 137 break; 138 if (st == CMD_CLEAN) 139 modified = 0; 140 if (st == CMD_DIRTY) 141 modified = 1; 142 } while (1); 143 144 /* Write out MBR */ 145 if (modified) { 146 if (st == CMD_SAVE) { 147 if (Xwrite(NULL, disk, &mbr, NULL, offset) == CMD_CONT) 148 goto again; 149 close(fd); 150 } else 151 printf("Aborting changes to current MBR.\n"); 152 } 153 154 done: 155 /* One level less */ 156 editlevel -= 1; 157 158 return (0); 159 } 160 161 int 162 USER_print_disk(struct disk *disk) 163 { 164 off_t offset, firstoff; 165 int fd, i, error; 166 struct dos_mbr dos_mbr; 167 struct mbr mbr; 168 169 fd = DISK_open(disk->name, O_RDONLY); 170 offset = firstoff = 0; 171 172 DISK_printgeometry(disk, NULL); 173 174 do { 175 error = MBR_read(fd, offset, &dos_mbr); 176 if (error == -1) 177 break; 178 MBR_parse(disk, &dos_mbr, offset, firstoff, &mbr); 179 180 printf("Offset: %lld\t", offset); 181 MBR_print(&mbr, NULL); 182 183 /* Print out extended partitions too */ 184 for (offset = i = 0; i < 4; i++) 185 if (mbr.part[i].id == DOSPTYP_EXTEND || 186 mbr.part[i].id == DOSPTYP_EXTENDL) { 187 offset = (off_t)mbr.part[i].bs; 188 if (firstoff == 0) 189 firstoff = offset; 190 } 191 } while (offset); 192 193 return (close(fd)); 194 } 195