fdisk.c revision 36262
1219019Sgabor/* 2219019Sgabor * Mach Operating System 3219019Sgabor * Copyright (c) 1992 Carnegie Mellon University 4219019Sgabor * All Rights Reserved. 5219019Sgabor * 6219019Sgabor * Permission to use, copy, modify and distribute this software and its 7219019Sgabor * documentation is hereby granted, provided that both the copyright 8219019Sgabor * notice and this permission notice appear in all copies of the 9219019Sgabor * software, derivative works or modified versions, and any portions 10219019Sgabor * thereof, and that both notices appear in supporting documentation. 11219019Sgabor * 12219019Sgabor * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 13219019Sgabor * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14219019Sgabor * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15219019Sgabor * 16219019Sgabor * Carnegie Mellon requests users of this software to return to 17219019Sgabor * 18219019Sgabor * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19219019Sgabor * School of Computer Science 20219019Sgabor * Carnegie Mellon University 21219019Sgabor * Pittsburgh PA 15213-3890 22219019Sgabor * 23219019Sgabor * any improvements or extensions that they make and grant Carnegie Mellon 24219019Sgabor * the rights to redistribute these changes. 25219019Sgabor */ 26219019Sgabor 27219019Sgabor#include <sys/types.h> 28219019Sgabor#include <sys/disklabel.h> 29219019Sgabor#include <stdio.h> 30219019Sgabor#include <string.h> 31219019Sgabor#include <errno.h> 32219019Sgabor#include <sys/stat.h> 33219019Sgabor#include <sys/ioctl.h> 34219019Sgabor#include <fcntl.h> 35219019Sgabor#include <unistd.h> 36219019Sgabor 37219019Sgaborint iotest; 38219019Sgabor 39219019Sgabor#define LBUF 100 40219019Sgaborstatic char lbuf[LBUF]; 41219019Sgabor 42219019Sgabor/* 43219019Sgabor * 44219019Sgabor * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 45219019Sgabor * 46219019Sgabor * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 47219019Sgabor * Copyright (c) 1989 Robert. V. Baron 48219019Sgabor * Created. 49219019Sgabor */ 50219019Sgabor 51219019Sgabor#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp 52219019Sgabor#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp 53219019Sgabor#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); } 54219019Sgabor 55219019Sgabor#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 56219019Sgabor 57219019Sgabor#define MAX_SEC_SIZE 2048 /* maximum section size that is supported */ 58219019Sgabor#define MIN_SEC_SIZE 512 /* the sector size to start sensing at */ 59219019Sgaborint secsize = 0; /* the sensed sector size */ 60219019Sgabor 61219019Sgaborconst char *disk; 62219019Sgaborconst char *disks[] = 63219019Sgabor{ 64219019Sgabor "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0 65219019Sgabor}; 66219019Sgabor 67219019Sgaborchar *name; 68219019Sgabor 69219019Sgaborstruct disklabel disklabel; /* disk parameters */ 70219019Sgabor 71219019Sgaborint cyls, sectors, heads, cylsecs, disksecs; 72219019Sgabor 73219019Sgaborstruct mboot 74219019Sgabor{ 75219019Sgabor unsigned char padding[2]; /* force the longs to be long alligned */ 76219019Sgabor unsigned char bootinst[DOSPARTOFF]; 77219019Sgabor struct dos_partition parts[4]; 78219019Sgabor unsigned short int signature; 79219019Sgabor /* room to read in MBRs that are bigger then DEV_BSIZE */ 80219019Sgabor unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE]; 81219019Sgabor}; 82219019Sgaborstruct mboot mboot; 83219019Sgabor 84219019Sgabor#define ACTIVE 0x80 85219019Sgabor#define BOOT_MAGIC 0xAA55 86219019Sgabor 87219019Sgaborint dos_cyls; 88219019Sgaborint dos_heads; 89219019Sgaborint dos_sectors; 90260264Sdimint dos_cylsecs; 91219019Sgabor 92219019Sgabor#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 93219019Sgabor#define DOSCYL(c) (c & 0xff) 94219019Sgaborstatic int partition = -1; 95219019Sgabor 96219019Sgabor 97219019Sgabor#define MAX_ARGS 10 98219019Sgabor 99219019Sgaborstatic int current_line_number; 100219019Sgabor 101219019Sgaborstatic int geom_processed = 0; 102219019Sgaborstatic int part_processed = 0; 103219019Sgaborstatic int active_processed = 0; 104219019Sgabor 105219019Sgabor 106219019Sgabortypedef struct cmd { 107219019Sgabor char cmd; 108260264Sdim int n_args; 109219019Sgabor struct arg { 110219019Sgabor char argtype; 111219019Sgabor int arg_val; 112219019Sgabor } args[MAX_ARGS]; 113219019Sgabor} CMD; 114219019Sgabor 115219019Sgabor 116219019Sgaborstatic int a_flag = 0; /* set active partition */ 117219019Sgaborstatic int i_flag = 0; /* replace partition data */ 118219019Sgaborstatic int u_flag = 0; /* update partition data */ 119219019Sgaborstatic int t_flag = 0; /* test only, if f_flag is given */ 120219019Sgaborstatic char *f_flag = NULL; /* Read config info from file */ 121219019Sgaborstatic int v_flag = 0; /* Be verbose */ 122219019Sgabor 123219019Sgaborstatic unsigned char bootcode[] = { 124219019Sgabor0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf, 125219019Sgabor0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe, 126219019Sgabor0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd, 127219019Sgabor0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74, 128219019Sgabor0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00, 129219019Sgabor0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe, 130219019Sgabor0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00, 131219019Sgabor0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10, 132219019Sgabor0xeb, 0xf4, 0xfb, 0xeb, 0xfe, 133219019Sgabor'M', 'i', 's', 's', 'i', 'n', 'g', ' ', 134219019Sgabor 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0, 135219019Sgabor'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ', 136219019Sgabor 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0, 137219019Sgabor'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ', 138219019Sgabor 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0, 139219019Sgabor'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ', 140219019Sgabor 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0, 141219019Sgabor 142219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 153219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154219019Sgabor 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 155219019Sgabor}; 156219019Sgabor 157219019Sgaborstruct part_type 158219019Sgabor{ 159219019Sgabor unsigned char type; 160219019Sgabor char *name; 161219019Sgabor}part_types[] = 162219019Sgabor{ 163219019Sgabor {0x00, "unused"} 164219019Sgabor ,{0x01, "Primary DOS with 12 bit FAT"} 165219019Sgabor ,{0x02, "XENIX / filesystem"} 166219019Sgabor ,{0x03, "XENIX /usr filesystem"} 167219019Sgabor ,{0x04, "Primary DOS with 16 bit FAT (<= 32MB)"} 168219019Sgabor ,{0x05, "Extended DOS"} 169219019Sgabor ,{0x06, "Primary 'big' DOS (> 32MB)"} 170219019Sgabor ,{0x07, "OS/2 HPFS, NTFS, QNX or Advanced UNIX"} 171219019Sgabor ,{0x08, "AIX filesystem"} 172219019Sgabor ,{0x09, "AIX boot partition or Coherent"} 173219019Sgabor ,{0x0A, "OS/2 Boot Manager or OPUS"} 174219019Sgabor ,{0x0B, "DOS or Windows 95 with 32 bit FAT"} 175219019Sgabor ,{0x0C, "DOS or Windows 95 with 32 bit FAT, LBA"} 176219019Sgabor ,{0x0E, "Primary 'big' DOS (> 32MB, LBA)"} 177219019Sgabor ,{0x0F, "Extended DOS, LBA"} 178219019Sgabor ,{0x10, "OPUS"} 179219019Sgabor ,{0x40, "VENIX 286"} 180219019Sgabor ,{0x50, "DM"} 181219019Sgabor ,{0x51, "DM"} 182219019Sgabor ,{0x52, "CP/M or Microport SysV/AT"} 183219019Sgabor ,{0x56, "GB"} 184219019Sgabor ,{0x61, "Speed"} 185219019Sgabor ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"} 186219019Sgabor ,{0x64, "Novell Netware 2.xx"} 187219019Sgabor ,{0x65, "Novell Netware 3.xx"} 188219019Sgabor ,{0x75, "PCIX"} 189219019Sgabor ,{0x80, "Minix 1.1 ... 1.4a"} 190219019Sgabor ,{0x81, "Minix 1.4b ... 1.5.10"} 191219019Sgabor ,{0x82, "Linux swap"} 192219019Sgabor ,{0x83, "Linux filesystem"} 193219019Sgabor ,{0x93, "Amoeba filesystem"} 194219019Sgabor ,{0x94, "Amoeba bad block table"} 195219019Sgabor ,{0xA5, "FreeBSD/NetBSD/386BSD"} 196219019Sgabor ,{0xA6, "OpenBSD"} 197219019Sgabor ,{0xA7, "NEXTSTEP"} 198219019Sgabor ,{0xB7, "BSDI BSD/386 filesystem"} 199219019Sgabor ,{0xB8, "BSDI BSD/386 swap"} 200219019Sgabor ,{0xDB, "Concurrent CPM or C.DOS or CTOS"} 201219019Sgabor ,{0xE1, "Speed"} 202219019Sgabor ,{0xE3, "Speed"} 203219019Sgabor ,{0xE4, "Speed"} 204219019Sgabor ,{0xF1, "Speed"} 205219019Sgabor ,{0xF2, "DOS 3.3+ Secondary"} 206219019Sgabor ,{0xF4, "Speed"} 207219019Sgabor ,{0xFF, "BBT (Bad Blocks Table)"} 208219019Sgabor}; 209219019Sgabor 210219019Sgaborstatic void print_s0(int which); 211219019Sgaborstatic void print_part(int i); 212219019Sgaborstatic void init_sector0(unsigned long start); 213219019Sgaborstatic void init_boot(void); 214219019Sgaborstatic void change_part(int i); 215219019Sgaborstatic void print_params(); 216219019Sgaborstatic void change_active(int which); 217219019Sgaborstatic void get_params_to_use(); 218219019Sgaborstatic void dos(int sec, int size, unsigned char *c, unsigned char *s, 219219019Sgabor unsigned char *h); 220219019Sgaborstatic int open_disk(int u_flag); 221219019Sgaborstatic ssize_t read_disk(off_t sector, void *buf); 222219019Sgaborstatic ssize_t write_disk(off_t sector, void *buf); 223219019Sgaborstatic int get_params(); 224219019Sgaborstatic int read_s0(); 225219019Sgaborstatic int write_s0(); 226219019Sgaborstatic int ok(char *str); 227219019Sgaborstatic int decimal(char *str, int *num, int deflt); 228219019Sgaborstatic char *get_type(int type); 229219019Sgaborstatic int read_config(char *config_file); 230219019Sgaborstatic void reset_boot(void); 231219019Sgabor#if 0 232219019Sgaborstatic int hex(char *str, int *num, int deflt); 233219019Sgaborstatic int string(char *str, char **ans); 234219019Sgabor#endif 235219019Sgabor 236219019Sgabor 237219019Sgaborint 238219019Sgabormain(int argc, char *argv[]) 239219019Sgabor{ 240219019Sgabor int i; 241219019Sgabor 242219019Sgabor name = *argv; 243219019Sgabor {register char *cp = name; 244219019Sgabor while (*cp) if (*cp++ == '/') name = cp; 245219019Sgabor } 246219019Sgabor 247219019Sgabor for ( argv++ ; --argc ; argv++ ) { register char *token = *argv; 248219019Sgabor if (*token++ != '-' || !*token) 249219019Sgabor break; 250219019Sgabor else { register int flag; 251219019Sgabor for ( ; (flag = *token++) ; ) { 252219019Sgabor switch (flag) { 253219019Sgabor case '1': 254219019Sgabor partition = 1; 255219019Sgabor break; 256219019Sgabor case '2': 257219019Sgabor partition = 2; 258219019Sgabor break; 259219019Sgabor case '3': 260219019Sgabor partition = 3; 261219019Sgabor break; 262219019Sgabor case '4': 263219019Sgabor partition = 4; 264219019Sgabor break; 265219019Sgabor case 'a': 266219019Sgabor a_flag = 1; 267219019Sgabor break; 268219019Sgabor case 'f': 269219019Sgabor if (*token) 270219019Sgabor { 271219019Sgabor f_flag = token; 272219019Sgabor token = ""; 273219019Sgabor } 274219019Sgabor else 275219019Sgabor { 276219019Sgabor if (argc == 1) 277219019Sgabor { 278219019Sgabor goto usage; 279219019Sgabor } 280219019Sgabor --argc; 281219019Sgabor f_flag = *++argv; 282219019Sgabor } 283219019Sgabor /* 284219019Sgabor * u_flag is needed, because we're 285219019Sgabor * writing to the disk. 286219019Sgabor */ 287219019Sgabor u_flag = 1; 288219019Sgabor break; 289219019Sgabor case 'i': 290219019Sgabor i_flag = 1; 291219019Sgabor case 'u': 292219019Sgabor u_flag = 1; 293219019Sgabor break; 294219019Sgabor case 't': 295219019Sgabor t_flag = 1; 296219019Sgabor case 'v': 297219019Sgabor v_flag = 1; 298219019Sgabor break; 299219019Sgabor default: 300219019Sgabor goto usage; 301219019Sgabor } 302219019Sgabor } 303219019Sgabor } 304219019Sgabor } 305219019Sgabor 306219019Sgabor if (argc > 0) 307219019Sgabor { 308219019Sgabor static char realname[12]; 309219019Sgabor 310219019Sgabor if(strncmp(argv[0], "/dev", 4) == 0) 311219019Sgabor disk = argv[0]; 312219019Sgabor else 313219019Sgabor { 314219019Sgabor snprintf(realname, 12, "/dev/r%s", argv[0]); 315219019Sgabor disk = realname; 316219019Sgabor } 317219019Sgabor 318219019Sgabor if (open_disk(u_flag) < 0) 319219019Sgabor { 320219019Sgabor fprintf(stderr, "Cannot open disk %s (%s)\n", 321219019Sgabor disk, sys_errlist[errno]); 322219019Sgabor exit(1); 323219019Sgabor } 324219019Sgabor } 325219019Sgabor else 326219019Sgabor { 327219019Sgabor int i, rv = 0; 328219019Sgabor 329219019Sgabor for(i = 0; disks[i]; i++) 330219019Sgabor { 331219019Sgabor disk = disks[i]; 332219019Sgabor rv = open_disk(u_flag); 333219019Sgabor if(rv != -2) break; 334219019Sgabor } 335219019Sgabor if(rv < 0) 336219019Sgabor { 337219019Sgabor fprintf(stderr, "Cannot open any disk (%s)\n", 338219019Sgabor sys_errlist[errno]); 339219019Sgabor exit(1); 340219019Sgabor } 341219019Sgabor } 342219019Sgabor 343219019Sgabor printf("******* Working on device %s *******\n",disk); 344219019Sgabor 345219019Sgabor if (f_flag) 346219019Sgabor { 347219019Sgabor if (read_s0() || i_flag) 348219019Sgabor { 349219019Sgabor reset_boot(); 350219019Sgabor } 351219019Sgabor 352219019Sgabor if (!read_config(f_flag)) 353219019Sgabor { 354219019Sgabor exit(1); 355219019Sgabor } 356219019Sgabor if (v_flag) 357219019Sgabor { 358219019Sgabor print_s0(-1); 359219019Sgabor } 360219019Sgabor if (!t_flag) 361219019Sgabor { 362219019Sgabor write_s0(); 363219019Sgabor } 364219019Sgabor } 365219019Sgabor else 366219019Sgabor { 367219019Sgabor if(u_flag) 368219019Sgabor { 369219019Sgabor get_params_to_use(); 370219019Sgabor } 371219019Sgabor else 372219019Sgabor { 373219019Sgabor print_params(); 374219019Sgabor } 375219019Sgabor 376219019Sgabor if (read_s0()) 377219019Sgabor init_sector0(1); 378219019Sgabor 379219019Sgabor printf("Media sector size is %d\n", secsize); 380219019Sgabor printf("Warning: BIOS sector numbering starts with sector 1\n"); 381219019Sgabor printf("Information from DOS bootblock is:\n"); 382219019Sgabor if (partition == -1) 383219019Sgabor for (i = 1; i <= NDOSPART; i++) 384219019Sgabor change_part(i); 385219019Sgabor else 386219019Sgabor change_part(partition); 387219019Sgabor 388219019Sgabor if (u_flag || a_flag) 389219019Sgabor change_active(partition); 390219019Sgabor 391219019Sgabor if (u_flag || a_flag) { 392219019Sgabor if (!t_flag) 393219019Sgabor { 394219019Sgabor printf("\nWe haven't changed the partition table yet. "); 395219019Sgabor printf("This is your last chance.\n"); 396219019Sgabor } 397219019Sgabor print_s0(-1); 398219019Sgabor if (!t_flag) 399219019Sgabor { 400219019Sgabor if (ok("Should we write new partition table?")) 401219019Sgabor write_s0(); 402219019Sgabor } 403219019Sgabor else 404219019Sgabor { 405219019Sgabor printf("\n-t flag specified -- partition table not written.\n"); 406219019Sgabor } 407219019Sgabor } 408219019Sgabor } 409219019Sgabor 410219019Sgabor exit(0); 411219019Sgabor 412219019Sgaborusage: 413219019Sgabor printf("fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{1,2,3,4}] [disk]\n"); 414219019Sgabor return(1); 415219019Sgabor} 416219019Sgabor 417219019Sgaborstatic void 418219019Sgaborprint_s0(int which) 419219019Sgabor{ 420219019Sgaborint i; 421219019Sgabor 422219019Sgabor print_params(); 423219019Sgabor printf("Information from DOS bootblock is:\n"); 424219019Sgabor if (which == -1) 425219019Sgabor for (i = 1; i <= NDOSPART; i++) 426219019Sgabor printf("%d: ", i), print_part(i); 427219019Sgabor else 428219019Sgabor print_part(which); 429219019Sgabor} 430219019Sgabor 431219019Sgaborstatic struct dos_partition mtpart = { 0 }; 432219019Sgabor 433219019Sgaborstatic void 434219019Sgaborprint_part(int i) 435219019Sgabor{ 436219019Sgabor struct dos_partition *partp; 437219019Sgabor u_int64_t part_mb; 438219019Sgabor 439219019Sgabor partp = ((struct dos_partition *) &mboot.parts) + i - 1; 440219019Sgabor 441219019Sgabor if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 442219019Sgabor printf("<UNUSED>\n"); 443219019Sgabor return; 444219019Sgabor } 445219019Sgabor /* 446219019Sgabor * Be careful not to overflow. 447219019Sgabor */ 448219019Sgabor part_mb = partp->dp_size; 449219019Sgabor part_mb *= secsize; 450219019Sgabor part_mb /= (1024 * 1024); 451219019Sgabor printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ)); 452219019Sgabor printf(" start %ld, size %ld (%qd Meg), flag %x%s\n", 453219019Sgabor partp->dp_start, 454219019Sgabor partp->dp_size, 455219019Sgabor part_mb, 456219019Sgabor partp->dp_flag, 457219019Sgabor partp->dp_flag == ACTIVE ? " (active)" : ""); 458219019Sgabor printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n" 459219019Sgabor ,DPCYL(partp->dp_scyl, partp->dp_ssect) 460219019Sgabor ,DPSECT(partp->dp_ssect) 461219019Sgabor ,partp->dp_shd 462219019Sgabor ,DPCYL(partp->dp_ecyl, partp->dp_esect) 463219019Sgabor ,DPSECT(partp->dp_esect) 464219019Sgabor ,partp->dp_ehd); 465219019Sgabor} 466219019Sgabor 467219019Sgabor 468219019Sgaborstatic void 469219019Sgaborinit_boot(void) 470219019Sgabor{ 471219019Sgabor memcpy(mboot.bootinst, bootcode, sizeof(bootcode)); 472219019Sgabor mboot.signature = BOOT_MAGIC; 473219019Sgabor} 474219019Sgabor 475219019Sgabor 476219019Sgaborstatic void 477219019Sgaborinit_sector0(unsigned long start) 478219019Sgabor{ 479219019Sgaborstruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 480219019Sgaborunsigned long size = disksecs - start; 481219019Sgabor 482219019Sgabor init_boot(); 483219019Sgabor 484219019Sgabor partp->dp_typ = DOSPTYP_386BSD; 485219019Sgabor partp->dp_flag = ACTIVE; 486219019Sgabor partp->dp_start = start; 487219019Sgabor partp->dp_size = size; 488219019Sgabor 489219019Sgabor dos(partp->dp_start, partp->dp_size, 490219019Sgabor &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 491219019Sgabor dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 492219019Sgabor &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 493219019Sgabor} 494219019Sgabor 495219019Sgaborstatic void 496219019Sgaborchange_part(int i) 497219019Sgabor{ 498219019Sgaborstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i - 1; 499219019Sgabor 500219019Sgabor printf("The data for partition %d is:\n", i); 501219019Sgabor print_part(i); 502 503 if (u_flag && ok("Do you want to change it?")) { 504 int tmp; 505 506 if (i_flag) { 507 bzero((char *)partp, sizeof (struct dos_partition)); 508 if (i == 4) { 509 init_sector0(1); 510 printf("\nThe static data for the DOS partition 4 has been reinitialized to:\n"); 511 print_part(i); 512 } 513 } 514 515 do { 516 Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp); 517 Decimal("start", partp->dp_start, tmp); 518 Decimal("size", partp->dp_size, tmp); 519 520 if (ok("Explicitly specify beg/end address ?")) 521 { 522 int tsec,tcyl,thd; 523 tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 524 thd = partp->dp_shd; 525 tsec = DPSECT(partp->dp_ssect); 526 Decimal("beginning cylinder", tcyl, tmp); 527 Decimal("beginning head", thd, tmp); 528 Decimal("beginning sector", tsec, tmp); 529 partp->dp_scyl = DOSCYL(tcyl); 530 partp->dp_ssect = DOSSECT(tsec,tcyl); 531 partp->dp_shd = thd; 532 533 tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 534 thd = partp->dp_ehd; 535 tsec = DPSECT(partp->dp_esect); 536 Decimal("ending cylinder", tcyl, tmp); 537 Decimal("ending head", thd, tmp); 538 Decimal("ending sector", tsec, tmp); 539 partp->dp_ecyl = DOSCYL(tcyl); 540 partp->dp_esect = DOSSECT(tsec,tcyl); 541 partp->dp_ehd = thd; 542 } else { 543 dos(partp->dp_start, partp->dp_size, 544 &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 545 dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 546 &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 547 } 548 549 print_part(i); 550 } while (!ok("Are we happy with this entry?")); 551 } 552} 553 554static void 555print_params() 556{ 557 printf("parameters extracted from in-core disklabel are:\n"); 558 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 559 ,cyls,heads,sectors,cylsecs); 560 if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255)) 561 printf("Figures below won't work with BIOS for partitions not in cyl 1\n"); 562 printf("parameters to be used for BIOS calculations are:\n"); 563 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 564 ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 565} 566 567static void 568change_active(int which) 569{ 570int i; 571int active = 4, tmp; 572struct dos_partition *partp = ((struct dos_partition *) &mboot.parts); 573 574 if (a_flag && which != -1) 575 active = which; 576 if (!ok("Do you want to change the active partition?")) 577 return; 578setactive: 579 active = 4; 580 do { 581 Decimal("active partition", active, tmp); 582 if (active < 1 || 4 < active) { 583 printf("Active partition number must be in range 1-4." 584 " Try again.\n"); 585 goto setactive; 586 } 587 } while (!ok("Are you happy with this choice")); 588 for (i = 0; i < NDOSPART; i++) 589 partp[i].dp_flag = 0; 590 if (active > 0 && active <= NDOSPART) 591 partp[active-1].dp_flag = ACTIVE; 592} 593 594void 595get_params_to_use() 596{ 597 int tmp; 598 print_params(); 599 if (ok("Do you want to change our idea of what BIOS thinks ?")) 600 { 601 do 602 { 603 Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 604 Decimal("BIOS's idea of #heads", dos_heads, tmp); 605 Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 606 dos_cylsecs = dos_heads * dos_sectors; 607 print_params(); 608 } 609 while(!ok("Are you happy with this choice")); 610 } 611} 612 613 614/***********************************************\ 615* Change real numbers into strange dos numbers * 616\***********************************************/ 617static void 618dos(sec, size, c, s, h) 619int sec, size; 620unsigned char *c, *s, *h; 621{ 622int cy; 623int hd; 624 625 if (sec == 0 && size == 0) { 626 *s = *c = *h = 0; 627 return; 628 } 629 630 cy = sec / ( dos_cylsecs ); 631 sec = sec - cy * ( dos_cylsecs ); 632 633 hd = sec / dos_sectors; 634 sec = (sec - hd * dos_sectors) + 1; 635 636 *h = hd; 637 *c = cy & 0xff; 638 *s = (sec & 0x3f) | ( (cy & 0x300) >> 2); 639} 640 641int fd; 642 643 /* Getting device status */ 644 645static int 646open_disk(int u_flag) 647{ 648struct stat st; 649 650 if (stat(disk, &st) == -1) { 651 fprintf(stderr, "%s: Can't get file status of %s\n", 652 name, disk); 653 return -1; 654 } 655 if ( !(st.st_mode & S_IFCHR) ) 656 fprintf(stderr,"%s: Device %s is not character special\n", 657 name, disk); 658 if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) { 659 if(errno == ENXIO) 660 return -2; 661 fprintf(stderr,"%s: Can't open device %s\n", name, disk); 662 return -1; 663 } 664 if (get_params(0) == -1) { 665 fprintf(stderr, "%s: Can't get disk parameters on %s\n", 666 name, disk); 667 return -1; 668 } 669 return fd; 670} 671 672static ssize_t 673read_disk(off_t sector, void *buf) 674{ 675 lseek(fd,(sector * 512), 0); 676 if( secsize == 0 ) 677 for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 ) 678 { 679 /* try the read */ 680 int size = read(fd, buf, secsize); 681 if( size == secsize ) 682 /* it worked so return */ 683 return secsize; 684 } 685 else 686 return read( fd, buf, secsize ); 687 688 /* we failed to read at any of the sizes */ 689 return -1; 690} 691 692static ssize_t 693write_disk(off_t sector, void *buf) 694{ 695 lseek(fd,(sector * 512), 0); 696 /* write out in the size that the read_disk found worked */ 697 return write(fd, buf, secsize); 698} 699 700static int 701get_params() 702{ 703 704 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 705 fprintf(stderr, 706 "%s: Can't get disk parameters on %s; supplying dummy ones\n", 707 name, disk); 708 dos_cyls = cyls = 1; 709 dos_heads = heads = 1; 710 dos_sectors = sectors = 1; 711 dos_cylsecs = cylsecs = heads * sectors; 712 disksecs = cyls * heads * sectors; 713 return disksecs; 714 } 715 716 dos_cyls = cyls = disklabel.d_ncylinders; 717 dos_heads = heads = disklabel.d_ntracks; 718 dos_sectors = sectors = disklabel.d_nsectors; 719 dos_cylsecs = cylsecs = heads * sectors; 720 disksecs = cyls * heads * sectors; 721 722 return (disksecs); 723} 724 725 726static int 727read_s0() 728{ 729 if (read_disk(0, (char *) mboot.bootinst) == -1) { 730 fprintf(stderr, "%s: Can't read fdisk partition table\n", name); 731 return -1; 732 } 733 if (mboot.signature != BOOT_MAGIC) { 734 fprintf(stderr, "%s: Invalid fdisk partition table found\n", 735 name); 736 /* So should we initialize things */ 737 return -1; 738 } 739 return 0; 740} 741 742static int 743write_s0() 744{ 745 int flag; 746 if (iotest) { 747 print_s0(-1); 748 return 0; 749 } 750 /* 751 * write enable label sector before write (if necessary), 752 * disable after writing. 753 * needed if the disklabel protected area also protects 754 * sector 0. (e.g. empty disk) 755 */ 756 flag = 1; 757#ifdef NOT_NOW 758 if (ioctl(fd, DIOCWLABEL, &flag) < 0) 759 perror("ioctl DIOCWLABEL"); 760#endif 761 if (write_disk(0, (char *) mboot.bootinst) == -1) { 762 fprintf(stderr, "%s: Can't write fdisk partition table\n", 763 name); 764 return -1; 765 flag = 0; 766#ifdef NOT_NOW 767 (void) ioctl(fd, DIOCWLABEL, &flag); 768#endif 769 } 770 return(0); 771} 772 773 774static int 775ok(str) 776char *str; 777{ 778 printf("%s [n] ", str); 779 fgets(lbuf, LBUF, stdin); 780 lbuf[strlen(lbuf)-1] = 0; 781 782 if (*lbuf && 783 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 784 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 785 return 1; 786 else 787 return 0; 788} 789 790static int 791decimal(char *str, int *num, int deflt) 792{ 793int acc = 0, c; 794char *cp; 795 796 while (1) { 797 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 798 fgets(lbuf, LBUF, stdin); 799 lbuf[strlen(lbuf)-1] = 0; 800 801 if (!*lbuf) 802 return 0; 803 804 cp = lbuf; 805 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 806 if (!c) 807 return 0; 808 while ((c = *cp++)) { 809 if (c <= '9' && c >= '0') 810 acc = acc * 10 + c - '0'; 811 else 812 break; 813 } 814 if (c == ' ' || c == '\t') 815 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 816 if (!c) { 817 *num = acc; 818 return 1; 819 } else 820 printf("%s is an invalid decimal number. Try again.\n", 821 lbuf); 822 } 823 824} 825 826#if 0 827static int 828hex(char *str, int *num, int deflt) 829{ 830int acc = 0, c; 831char *cp; 832 833 while (1) { 834 printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 835 fgets(lbuf, LBUF, stdin); 836 lbuf[strlen(lbuf)-1] = 0; 837 838 if (!*lbuf) 839 return 0; 840 841 cp = lbuf; 842 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 843 if (!c) 844 return 0; 845 while ((c = *cp++)) { 846 if (c <= '9' && c >= '0') 847 acc = (acc << 4) + c - '0'; 848 else if (c <= 'f' && c >= 'a') 849 acc = (acc << 4) + c - 'a' + 10; 850 else if (c <= 'F' && c >= 'A') 851 acc = (acc << 4) + c - 'A' + 10; 852 else 853 break; 854 } 855 if (c == ' ' || c == '\t') 856 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 857 if (!c) { 858 *num = acc; 859 return 1; 860 } else 861 printf("%s is an invalid hex number. Try again.\n", 862 lbuf); 863 } 864 865} 866 867static int 868string(char *str, char **ans) 869{ 870int c; 871char *cp = lbuf; 872 873 while (1) { 874 printf("Supply a string value for \"%s\" [%s] ", str, *ans); 875 fgets(lbuf, LBUF, stdin); 876 lbuf[strlen(lbuf)-1] = 0; 877 878 if (!*lbuf) 879 return 0; 880 881 while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 882 if (c == '"') { 883 c = *++cp; 884 *ans = cp; 885 while ((c = *cp) && c != '"') cp++; 886 } else { 887 *ans = cp; 888 while ((c = *cp) && c != ' ' && c != '\t') cp++; 889 } 890 891 if (c) 892 *cp = 0; 893 return 1; 894 } 895} 896#endif 897 898static char * 899get_type(int type) 900{ 901 int numentries = (sizeof(part_types)/sizeof(struct part_type)); 902 int counter = 0; 903 struct part_type *ptr = part_types; 904 905 906 while(counter < numentries) 907 { 908 if(ptr->type == type) 909 { 910 return(ptr->name); 911 } 912 ptr++; 913 counter++; 914 } 915 return("unknown"); 916} 917 918 919static void 920parse_config_line(line, command) 921 char *line; 922 CMD *command; 923{ 924 char *cp, *end; 925 926 cp = line; 927 while (1) /* dirty trick used to insure one exit point for this 928 function */ 929 { 930 memset(command, 0, sizeof(*command)); 931 932 while (isspace(*cp)) ++cp; 933 if (*cp == '\0' || *cp == '#') 934 { 935 break; 936 } 937 command->cmd = *cp++; 938 939 /* 940 * Parse args 941 */ 942 while (1) 943 { 944 while (isspace(*cp)) ++cp; 945 if (*cp == '#') 946 { 947 break; /* found comment */ 948 } 949 if (isalpha(*cp)) 950 { 951 command->args[command->n_args].argtype = *cp++; 952 } 953 if (!isdigit(*cp)) 954 { 955 break; /* assume end of line */ 956 } 957 end = NULL; 958 command->args[command->n_args].arg_val = strtol(cp, &end, 0); 959 if (cp == end) 960 { 961 break; /* couldn't parse number */ 962 } 963 cp = end; 964 command->n_args++; 965 } 966 break; 967 } 968} 969 970 971static int 972process_geometry(command) 973 CMD *command; 974{ 975 int status = 1, i; 976 977 while (1) 978 { 979 geom_processed = 1; 980 if (part_processed) 981 { 982 fprintf(stderr, 983 "%s: ERROR line %d: the geometry specification line must occur before\n\ 984 all partition specifications.\n", 985 name, current_line_number); 986 status = 0; 987 break; 988 } 989 if (command->n_args != 3) 990 { 991 fprintf(stderr, 992 "%s: ERROR line %d: incorrect number of geometry args\n", 993 name, current_line_number); 994 status = 0; 995 break; 996 } 997 dos_cyls = -1; 998 dos_heads = -1; 999 dos_sectors = -1; 1000 for (i = 0; i < 3; ++i) 1001 { 1002 switch (command->args[i].argtype) 1003 { 1004 case 'c': 1005 dos_cyls = command->args[i].arg_val; 1006 break; 1007 case 'h': 1008 dos_heads = command->args[i].arg_val; 1009 break; 1010 case 's': 1011 dos_sectors = command->args[i].arg_val; 1012 break; 1013 default: 1014 fprintf(stderr, 1015 "%s: ERROR line %d: unknown geometry arg type: '%c' (0x%02x)\n", 1016 name, current_line_number, command->args[i].argtype, 1017 command->args[i].argtype); 1018 status = 0; 1019 break; 1020 } 1021 } 1022 if (status == 0) 1023 { 1024 break; 1025 } 1026 1027 dos_cylsecs = dos_heads * dos_sectors; 1028 1029 /* 1030 * Do sanity checks on parameter values 1031 */ 1032 if (dos_cyls < 0) 1033 { 1034 fprintf(stderr, 1035 "%s: ERROR line %d: number of cylinders not specified\n", 1036 name, current_line_number); 1037 status = 0; 1038 } 1039 if (dos_cyls == 0 || dos_cyls > 1024) 1040 { 1041 fprintf(stderr, 1042 "%s: WARNING line %d: number of cylinders (%d) may be out-of-range\n\ 1043 (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\ 1044 is dedicated to FreeBSD).\n", 1045 name, current_line_number, dos_cyls); 1046 } 1047 1048 if (dos_heads < 0) 1049 { 1050 fprintf(stderr, 1051 "%s: ERROR line %d: number of heads not specified\n", 1052 name, current_line_number); 1053 status = 0; 1054 } 1055 else if (dos_heads < 1 || dos_heads > 256) 1056 { 1057 fprintf(stderr, 1058 "%s: ERROR line %d: number of heads must be within (1-256)\n", 1059 name, current_line_number); 1060 status = 0; 1061 } 1062 1063 if (dos_sectors < 0) 1064 { 1065 fprintf(stderr, "%s: ERROR line %d: number of sectors not specified\n", 1066 name, current_line_number); 1067 status = 0; 1068 } 1069 else if (dos_sectors < 1 || dos_sectors > 63) 1070 { 1071 fprintf(stderr, 1072 "%s: ERROR line %d: number of sectors must be within (1-63)\n", 1073 name, current_line_number); 1074 status = 0; 1075 } 1076 1077 break; 1078 } 1079 return (status); 1080} 1081 1082 1083static int 1084process_partition(command) 1085 CMD *command; 1086{ 1087 int status = 0, partition; 1088 unsigned long chunks, adj_size, max_end; 1089 struct dos_partition *partp; 1090 1091 while (1) 1092 { 1093 part_processed = 1; 1094 if (command->n_args != 4) 1095 { 1096 fprintf(stderr, 1097 "%s: ERROR line %d: incorrect number of partition args\n", 1098 name, current_line_number); 1099 break; 1100 } 1101 partition = command->args[0].arg_val; 1102 if (partition < 1 || partition > 4) 1103 { 1104 fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n", 1105 name, current_line_number, partition); 1106 break; 1107 } 1108 partp = ((struct dos_partition *) &mboot.parts) + partition - 1; 1109 bzero((char *)partp, sizeof (struct dos_partition)); 1110 partp->dp_typ = command->args[1].arg_val; 1111 partp->dp_start = command->args[2].arg_val; 1112 partp->dp_size = command->args[3].arg_val; 1113 max_end = partp->dp_start + partp->dp_size; 1114 1115 if (partp->dp_typ == 0) 1116 { 1117 /* 1118 * Get out, the partition is marked as unused. 1119 */ 1120 /* 1121 * Insure that it's unused. 1122 */ 1123 bzero((char *)partp, sizeof (struct dos_partition)); 1124 status = 1; 1125 break; 1126 } 1127 1128 /* 1129 * Adjust start upwards, if necessary, to fall on an head boundary. 1130 */ 1131 if (partp->dp_start % dos_sectors != 0) 1132 { 1133 adj_size = 1134 (partp->dp_start / dos_sectors + 1) * dos_sectors; 1135 if (adj_size > max_end) 1136 { 1137 /* 1138 * Can't go past end of partition 1139 */ 1140 fprintf(stderr, 1141 "%s: ERROR line %d: unable to adjust start of partition %d to fall on\n\ 1142 a cylinder boundary.\n", 1143 name, current_line_number, partition); 1144 break; 1145 } 1146 fprintf(stderr, 1147 "%s: WARNING: adjusting start offset of partition '%d' from %d\n\ 1148 to %d, to round to an head boundary.\n", 1149 name, partition, partp->dp_start, adj_size); 1150 partp->dp_start = adj_size; 1151 } 1152 1153 /* 1154 * Adjust size downwards, if necessary, to fall on a cylinder 1155 * boundary. 1156 */ 1157 chunks = 1158 ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs; 1159 adj_size = chunks - partp->dp_start; 1160 if (adj_size != partp->dp_size) 1161 { 1162 fprintf(stderr, 1163 "%s: WARNING: adjusting size of partition '%d' from %d to %d,\n\ 1164 to round to a cylinder boundary.\n", 1165 name, partition, partp->dp_size, adj_size); 1166 if (chunks > 0) 1167 { 1168 partp->dp_size = adj_size; 1169 } 1170 else 1171 { 1172 partp->dp_size = 0; 1173 } 1174 } 1175 if (partp->dp_size < 1) 1176 { 1177 fprintf(stderr, 1178 "%s: ERROR line %d: size for partition '%d' is zero.\n", 1179 name, current_line_number, partition); 1180 break; 1181 } 1182 1183 dos(partp->dp_start, partp->dp_size, 1184 &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 1185 dos(partp->dp_start+partp->dp_size - 1, partp->dp_size, 1186 &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 1187 status = 1; 1188 break; 1189 } 1190 return (status); 1191} 1192 1193 1194static int 1195process_active(command) 1196 CMD *command; 1197{ 1198 int status = 0, partition, i; 1199 struct dos_partition *partp; 1200 1201 while (1) 1202 { 1203 active_processed = 1; 1204 if (command->n_args != 1) 1205 { 1206 fprintf(stderr, 1207 "%s: ERROR line %d: incorrect number of active args\n", 1208 name, current_line_number); 1209 status = 0; 1210 break; 1211 } 1212 partition = command->args[0].arg_val; 1213 if (partition < 1 || partition > 4) 1214 { 1215 fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n", 1216 name, current_line_number, partition); 1217 break; 1218 } 1219 /* 1220 * Reset active partition 1221 */ 1222 partp = ((struct dos_partition *) &mboot.parts); 1223 for (i = 0; i < NDOSPART; i++) 1224 partp[i].dp_flag = 0; 1225 partp[partition-1].dp_flag = ACTIVE; 1226 1227 status = 1; 1228 break; 1229 } 1230 return (status); 1231} 1232 1233 1234static int 1235process_line(line) 1236 char *line; 1237{ 1238 CMD command; 1239 int status = 1; 1240 1241 while (1) 1242 { 1243 parse_config_line(line, &command); 1244 switch (command.cmd) 1245 { 1246 case 0: 1247 /* 1248 * Comment or blank line 1249 */ 1250 break; 1251 case 'g': 1252 /* 1253 * Set geometry 1254 */ 1255 status = process_geometry(&command); 1256 break; 1257 case 'p': 1258 status = process_partition(&command); 1259 break; 1260 case 'a': 1261 status = process_active(&command); 1262 break; 1263 default: 1264 status = 0; 1265 break; 1266 } 1267 break; 1268 } 1269 return (status); 1270} 1271 1272 1273static int 1274read_config(config_file) 1275 char *config_file; 1276{ 1277 FILE *fp = NULL; 1278 int status = 1; 1279 char buf[1010]; 1280 1281 while (1) /* dirty trick used to insure one exit point for this 1282 function */ 1283 { 1284 if (strcmp(config_file, "-") != 0) 1285 { 1286 /* 1287 * We're not reading from stdin 1288 */ 1289 if ((fp = fopen(config_file, "r")) == NULL) 1290 { 1291 status = 0; 1292 break; 1293 } 1294 } 1295 else 1296 { 1297 fp = stdin; 1298 } 1299 current_line_number = 0; 1300 while (!feof(fp)) 1301 { 1302 if (fgets(buf, sizeof(buf), fp) == NULL) 1303 { 1304 break; 1305 } 1306 ++current_line_number; 1307 status = process_line(buf); 1308 if (status == 0) 1309 { 1310 break; 1311 } 1312 } 1313 break; 1314 } 1315 if (fp) 1316 { 1317 /* 1318 * It doesn't matter if we're reading from stdin, as we've reached EOF 1319 */ 1320 fclose(fp); 1321 } 1322 return (status); 1323} 1324 1325 1326static void 1327reset_boot(void) 1328{ 1329 int i; 1330 struct dos_partition *partp; 1331 1332 init_boot(); 1333 for (i = 0; i < 4; ++i) 1334 { 1335 partp = ((struct dos_partition *) &mboot.parts) + i; 1336 bzero((char *)partp, sizeof (struct dos_partition)); 1337 } 1338} 1339