1/* 2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25/* 26 * Copyright (c) 1997 Tobias Weingartner 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 2. Redistributions in binary form must reproduce the above copyright 35 * notice, this list of conditions and the following disclaimer in the 36 * documentation and/or other materials provided with the distribution. 37 * 3. All advertising materials mentioning features or use of this software 38 * must display the following acknowledgement: 39 * This product includes software developed by Tobias Weingartner. 40 * 4. The name of the author may not be used to endorse or promote products 41 * derived from this software without specific prior written permission. 42 * 43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 44 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 45 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 46 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 47 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 48 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 52 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 */ 54 55#include <err.h> 56#include <util.h> 57#include <stdio.h> 58#include <unistd.h> 59#include <string.h> 60#include <sys/fcntl.h> 61#include <sys/types.h> 62#include <sys/stat.h> 63#include <machine/param.h> 64#include "user.h" 65#include "disk.h" 66#include "misc.h" 67#include "mbr.h" 68#include "cmd.h" 69 70 71/* Our command table */ 72static cmd_table_t cmd_table[] = { 73 {"help", Xhelp, "Command help list"}, 74 {"manual", Xmanual, "Show entire man page for fdisk"}, 75 {"reinit", Xreinit, "Re-initialize loaded MBR (to defaults)"}, 76 {"auto", Xauto, "Auto-partition the disk with a partition style"}, 77 {"setpid", Xsetpid, "Set the identifier of a given table entry"}, 78 {"disk", Xdisk, "Edit current drive stats"}, 79 {"edit", Xedit, "Edit given table entry"}, 80 {"erase", Xerase, "Erase current MBR"}, 81 {"flag", Xflag, "Flag given table entry as bootable"}, 82 {"update", Xupdate, "Update machine code in loaded MBR"}, 83 {"select", Xselect, "Select extended partition table entry MBR"}, 84 {"print", Xprint, "Print loaded MBR partition table"}, 85 {"write", Xwrite, "Write loaded MBR to disk"}, 86 {"exit", Xexit, "Exit edit of current MBR, without saving changes"}, 87 {"quit", Xquit, "Quit edit of current MBR, saving current changes"}, 88 {"abort", Xabort, "Abort program without saving current changes"}, 89 {NULL, NULL, NULL} 90}; 91 92 93int 94USER_write(disk, tt, preserve, force) 95 disk_t *disk; 96 mbr_t *tt; /* Template MBR to write */ 97 int preserve; /* Preserve partition table and just write boot code */ 98 int force; /* Don't ask any questions */ 99{ 100 int fd, yn; 101 char *msgp = "\nDo you wish to write new MBR?"; 102 char *msgk = "\nDo you wish to write new MBR and partition table?"; 103 104 /* Write sector 0 */ 105 if (force) { 106 yn = 1; 107 } else { 108 printf("\a\n" 109 "\t-----------------------------------------------------\n" 110 "\t------ ATTENTION - UPDATING MASTER BOOT RECORD ------\n" 111 "\t-----------------------------------------------------\n"); 112 if (preserve) 113 yn = ask_yn(msgp, 0); 114 else 115 yn = ask_yn(msgk, 0); 116 } 117 118 if (yn) { 119 if (preserve) { 120 int shared; 121 /* Only write the first one, if there's more than one in an extended partition chain */ 122 /* Since we're updating boot code, we don't require exclusive access */ 123 fd = DISK_openshared(disk->name, O_RDWR, &shared); 124 MBR_make(tt); 125 MBR_write(disk, fd, tt); 126 DISK_close(fd); 127 } else { 128 MBR_write_all(disk, tt); 129 } 130 } else { 131 printf("MBR is unchanged\n"); 132 } 133 134 return (0); 135} 136 137 138int 139USER_modify(disk, tt, offset, reloff) 140 disk_t *disk; 141 mbr_t *tt; 142 off_t offset; 143 off_t reloff; 144{ 145 static int editlevel; 146 mbr_t *mbr; 147 cmd_t cmd; 148 int i, st, fd; 149 int modified = 0; 150 151 /* One level deeper */ 152 editlevel += 1; 153 154 /* Set up command table pointer */ 155 cmd.table = cmd_table; 156 157 /* Read MBR & partition */ 158 mbr = MBR_alloc(NULL); 159 fd = DISK_open(disk->name, O_RDONLY); 160 MBR_read(disk, fd, offset, mbr); 161 DISK_close(fd); 162 163 /* Parse the sucker */ 164 MBR_parse(disk, offset, reloff, mbr); 165 166 if (mbr->signature != MBR_SIGNATURE) { 167 int yn = ask_yn("The signature for this MBR is invalid.\nWould you like to initialize the partition table?", 1); 168 if (yn) { 169 strcpy(cmd.cmd, "erase"); 170 cmd.args[0] = '\0'; 171 st = Xerase(&cmd, disk, mbr, tt, offset); 172 modified = 1; 173 } 174 } 175 176 printf("Enter 'help' for information\n"); 177 178 /* Edit cycle */ 179 do { 180again: 181 printf("fdisk:%c%d> ", (modified)?'*':' ', editlevel); 182 fflush(stdout); 183 ask_cmd(&cmd); 184 185 if (cmd.cmd[0] == '\0') 186 goto again; 187 for (i = 0; cmd_table[i].cmd != NULL; i++) 188 if (strstr(cmd_table[i].cmd, cmd.cmd)==cmd_table[i].cmd) 189 break; 190 191 /* Quick hack to put in '?' == 'help' */ 192 if (!strcmp(cmd.cmd, "?")) 193 i = 0; 194 195 /* Check for valid command */ 196 if (cmd_table[i].cmd == NULL) { 197 printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd); 198 continue; 199 } else 200 strcpy(cmd.cmd, cmd_table[i].cmd); 201 202 /* Call function */ 203 st = cmd_table[i].fcn(&cmd, disk, mbr, tt, offset); 204 205 /* Update status */ 206 if (st == CMD_EXIT) 207 break; 208 if (st == CMD_SAVE) 209 break; 210 if (st == CMD_CLEAN) 211 modified = 0; 212 if (st == CMD_DIRTY) 213 modified = 1; 214 } while (1); 215 216 /* Write out MBR */ 217 if (modified) { 218 if (st == CMD_SAVE) { 219 int shared = 0; 220 printf("Writing current MBR to disk.\n"); 221 fd = DISK_openshared(disk->name, O_RDWR, &shared); 222 if(shared) { 223 if(!ask_yn("Device could not be accessed exclusively.\nA reboot will be needed for changes to take effect. OK?", 0)) { 224 close(fd); 225 goto again; 226 } 227 } 228 229 MBR_make(mbr); 230 MBR_write(disk, fd, mbr); 231 close(fd); 232 } else { 233 int yn = ask_yn("MBR was modified; really quit without saving?", 0); 234 if (yn) { 235 printf("Aborting changes to current MBR.\n"); 236 } else { 237 goto again; 238 } 239 } 240 } 241 242 /* One level less */ 243 editlevel -= 1; 244 245 MBR_free(mbr); 246 247 return (0); 248} 249 250int 251USER_print_disk(disk, do_dump) 252 disk_t *disk; 253 int do_dump; 254{ 255 int fd, offset, firstoff; 256 mbr_t *mbr; 257 258 fd = DISK_open(disk->name, O_RDONLY); 259 offset = firstoff = 0; 260 261 if (!do_dump) 262 DISK_printmetrics(disk); 263 264 mbr = MBR_read_all(disk); 265 if (do_dump) 266 MBR_dump_all(mbr); 267 else 268 MBR_print_all(mbr); 269 MBR_free(mbr); 270 271 return (DISK_close(fd)); 272} 273 274 275 276