00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <sys/types.h>
00037 #include <ibm/partition.h>
00038 #include <minix/partition.h>
00039 #include <sys/ioctl.h>
00040 #include <sys/stat.h>
00041 #include <fcntl.h>
00042 #include <string.h>
00043 #include <stdlib.h>
00044 #include <unistd.h>
00045 #include <stdio.h>
00046 #include <errno.h>
00047
00048 #ifdef DOS
00049 #include <dos.h>
00050 #define DEFAULT_DEV "c:"
00051 #define LOAD_OPEN_MODE 0x8000
00052 #define SAVE_CREAT_MODE 0644
00053 #else
00054 #define DEFAULT_DEV "/dev/hd0"
00055 #define LOAD_OPEN_MODE 0
00056 #define SAVE_CREAT_MODE 0644
00057 #define UNIX
00058 #endif
00059
00060
00061
00062 #define DEFAULT_NHEAD 4
00063 #define DEFAULT_NSEC 17
00064 #define SECSIZE 512
00065 #define OK 0
00066 #define ERR 1
00067
00068 #define CYL_MASK 0xc0
00069 #define CYL_SHIFT 2
00070 #define SEC_MASK 0x3f
00071
00072
00073 char rawsecbuf[SECSIZE + sizeof(long)];
00074 char *secbuf;
00075 int badbases;
00076 int badsizes;
00077 int badorders;
00078 char *devname;
00079 int nhead;
00080 int nsec;
00081 int ncyl = 1024;
00082 int readonly;
00083 int override= 0;
00084
00085 _PROTOTYPE(int main, (int argc, char *argv []));
00086 _PROTOTYPE(void getgeom, (void));
00087 _PROTOTYPE(int getboot, (char *buffer));
00088 _PROTOTYPE(int putboot, (char *buffer));
00089 _PROTOTYPE(int load_from_file, (void));
00090 _PROTOTYPE(int save_to_file, (void));
00091 _PROTOTYPE(int dpl_partitions, (int rawflag));
00092 _PROTOTYPE(int chk_table, (void));
00093 _PROTOTYPE(int sec_to_hst, (long logsec, unsigned char *hd, unsigned char *sec,
00094 unsigned char *cyl));
00095 _PROTOTYPE(int mark_partition, (struct part_entry *pe));
00096 _PROTOTYPE(int change_partition, (struct part_entry *entry));
00097 _PROTOTYPE(int get_a_char, (void));
00098 _PROTOTYPE(int print_menu, (void));
00099 _PROTOTYPE(void adj_base, (struct part_entry *pe));
00100 _PROTOTYPE(void adj_size, (struct part_entry *pe));
00101 _PROTOTYPE(struct part_entry *ask_partition, (void));
00102 _PROTOTYPE(void footnotes, (void));
00103 _PROTOTYPE(int get_an_int, (char *prompt, int *intptr));
00104 _PROTOTYPE(void list_part_types, (void));
00105 _PROTOTYPE(void mark_npartition, (struct part_entry *pe));
00106 _PROTOTYPE(int mygets, (char *buf, int length));
00107 _PROTOTYPE(char *systype, (int type));
00108 _PROTOTYPE(void toggle_active, (struct part_entry *pe));
00109 _PROTOTYPE(void usage, (void));
00110
00111
00112 char bootstrap[] = {
00113 0353,0001,0000,0061,0300,0216,0330,0216,0300,0372,0216,0320,0274,0000,0174,0373,
00114 0275,0276,0007,0211,0346,0126,0277,0000,0006,0271,0000,0001,0374,0363,0245,0352,
00115 0044,0006,0000,0000,0264,0002,0315,0026,0250,0010,0164,0033,0350,0071,0001,0174,
00116 0007,0060,0344,0315,0026,0242,0205,0007,0054,0060,0074,0012,0163,0363,0120,0350,
00117 0046,0001,0205,0007,0130,0353,0012,0240,0002,0006,0204,0300,0165,0003,0351,0147,
00118 0000,0230,0262,0005,0366,0362,0262,0200,0000,0302,0210,0340,0120,0350,0234,0000,
00119 0163,0003,0351,0147,0000,0130,0054,0001,0175,0003,0351,0141,0000,0276,0276,0175,
00120 0211,0357,0271,0040,0000,0363,0245,0200,0301,0004,0211,0356,0215,0174,0020,0070,
00121 0154,0004,0164,0016,0213,0135,0010,0053,0134,0010,0213,0135,0012,0033,0134,0012,
00122 0163,0014,0212,0044,0206,0144,0020,0210,0044,0106,0071,0376,0162,0364,0211,0376,
00123 0201,0376,0356,0007,0162,0326,0342,0322,0211,0356,0264,0020,0366,0344,0001,0306,
00124 0200,0174,0004,0001,0162,0026,0353,0021,0204,0322,0175,0041,0211,0356,0200,0174,
00125 0004,0000,0164,0013,0366,0004,0200,0164,0006,0350,0070,0000,0162,0053,0303,0203,
00126 0306,0020,0201,0376,0376,0007,0162,0346,0350,0215,0000,0211,0007,0376,0302,0204,
00127 0322,0174,0023,0315,0021,0321,0340,0321,0340,0200,0344,0003,0070,0342,0167,0355,
00128 0350,0011,0000,0162,0350,0303,0350,0003,0000,0162,0146,0303,0211,0356,0214,0134,
00129 0010,0214,0134,0012,0277,0003,0000,0122,0006,0127,0264,0010,0315,0023,0137,0007,
00130 0200,0341,0077,0376,0306,0210,0310,0366,0346,0211,0303,0213,0104,0010,0213,0124,
00131 0012,0367,0363,0222,0210,0325,0366,0361,0060,0322,0321,0352,0321,0352,0010,0342,
00132 0210,0321,0376,0301,0132,0210,0306,0273,0000,0174,0270,0001,0002,0315,0023,0163,
00133 0020,0200,0374,0200,0164,0011,0117,0174,0006,0060,0344,0315,0023,0163,0270,0371,
00134 0303,0201,0076,0376,0175,0125,0252,0165,0001,0303,0350,0013,0000,0243,0007,0353,
00135 0005,0350,0004,0000,0227,0007,0353,0376,0136,0255,0126,0211,0306,0254,0204,0300,
00136 0164,0011,0264,0016,0273,0001,0000,0315,0020,0353,0362,0303,0057,0144,0145,0166,
00137 0057,0150,0144,0077,0010,0000,0015,0012,0000,0116,0157,0156,0145,0040,0141,0143,
00138 0164,0151,0166,0145,0015,0012,0000,0122,0145,0141,0144,0040,0145,0162,0162,0157,
00139 0162,0040,0000,0116,0157,0164,0040,0142,0157,0157,0164,0141,0142,0154,0145,0040,
00140 0000,0000,
00141 };
00142
00143 main(argc, argv)
00144 int argc;
00145 char *argv[];
00146 {
00147 int argn;
00148 char *argp;
00149 int ch;
00150
00151
00152
00153 nhead = DEFAULT_NHEAD;
00154 nsec = DEFAULT_NSEC;
00155 for (argn = 1; argn < argc && (argp = argv[argn])[0] == '-'; ++argn) {
00156 if (argp[1] == 'h')
00157 nhead = atoi(argp + 2);
00158 else
00159 if (argp[1] == 's') nsec = atoi(argp + 2);
00160 else
00161 usage();
00162 override= 1;
00163 }
00164
00165 if (argn == argc)
00166 devname = DEFAULT_DEV;
00167 else if (argn == argc - 1)
00168 devname = argv[argn];
00169 else
00170 usage();
00171
00172
00173
00174
00175
00176 secbuf = rawsecbuf;
00177 while ((long)(secbuf + PART_TABLE_OFF) % sizeof(long) != 0) secbuf++;
00178
00179 getgeom();
00180 getboot(secbuf);
00181 chk_table();
00182
00183 do {
00184 putchar('\n');
00185 dpl_partitions(0);
00186 printf(
00187 "\n(Enter 'h' for help. A null line will abort any operation) ");
00188 ch = get_a_char();
00189 putchar('\n');
00190 switch (ch) {
00191 case '+': footnotes(); break;
00192 case 'a': toggle_active(ask_partition()); break;
00193 case 'B': adj_base(ask_partition()); break;
00194 case 'c': change_partition(ask_partition()); break;
00195 case 'h': print_menu(); break;
00196 case 'l': load_from_file(); break;
00197 case 'm': mark_partition(ask_partition()); break;
00198 case 'n': mark_npartition(ask_partition()); break;
00199 case 'p': dpl_partitions(1); break;
00200 case 0:
00201 case 'q': exit(0);
00202 case 'S': adj_size(ask_partition()); break;
00203 case 's': save_to_file(); break;
00204 case 't': list_part_types(); break;
00205 case 'v':
00206 printf("Partition table is %svalid\n",
00207 chk_table() == OK ? "" : "in");
00208 break;
00209 case 'w':
00210 if (readonly)
00211 printf("Write disabled\n");
00212 else if(chk_table() == OK) {
00213 putboot(secbuf);
00214 printf(
00215 "Partition table has been updated and the file system synced.\n");
00216 printf("Please reboot now.\n");
00217 exit(0);
00218 } else
00219 printf("Not written\n");
00220 break;
00221 default: printf(" %c ????\n", ch); break;
00222 }
00223 }
00224 while (1);
00225 }
00226
00227
00228 #ifdef UNIX
00229
00230 void getgeom()
00231 {
00232 struct partition geom;
00233 int fd, r;
00234
00235 if (override) return;
00236
00237 if ((fd= open(devname, O_RDONLY)) < 0) return;
00238
00239 r = ioctl(fd, DIOCGETP, &geom);
00240 close(fd);
00241 if (r < 0) return;
00242
00243 nhead = geom.heads;
00244 nsec = geom.sectors;
00245 ncyl = geom.cylinders;
00246
00247 printf("Geometry of %s: %dx%dx%d\n", devname, ncyl, nhead, nsec);
00248 }
00249
00250 static int devfd;
00251
00252 getboot(buffer)
00253 char *buffer;
00254 {
00255 devfd = open(devname, 2);
00256 if (devfd < 0) {
00257 printf("No write permission on %s\n", devname);
00258 readonly = 1;
00259 devfd = open(devname, 0);
00260 }
00261 if (devfd < 0) {
00262 printf("Cannot open device %s\n", devname);
00263 exit(1);
00264 }
00265 if (read(devfd, buffer, SECSIZE) != SECSIZE) {
00266 printf("Cannot read boot sector\n");
00267 exit(1);
00268 }
00269 if (* (unsigned short *) &buffer[510] != 0xAA55) {
00270 printf("Invalid boot sector on %s.\n", devname);
00271 printf("Partition table reset and boot code installed.\n");
00272 memset(buffer, 0, 512);
00273 memcpy(buffer, bootstrap, sizeof(bootstrap));
00274 * (unsigned short *) &buffer[510] = 0xAA55;
00275 }
00276 }
00277
00278 putboot(buffer)
00279 char *buffer;
00280 {
00281 if (lseek(devfd, 0L, 0) < 0) {
00282 printf("Seek error during write\n");
00283 exit(1);
00284 }
00285 if (write(devfd, buffer, SECSIZE) != SECSIZE) {
00286 printf("Write error\n");
00287 exit(1);
00288 }
00289 sync();
00290 }
00291
00292 #endif
00293
00294
00295 load_from_file()
00296 {
00297
00298
00299 char file[80];
00300 int fd;
00301
00302 printf("Enter name of file to load from: ");
00303 if (!mygets(file, (int) sizeof file)) return;
00304 fd = open(file, LOAD_OPEN_MODE);
00305 if (fd < 0) {
00306 printf("Cannot open %s\n", file);
00307 return;
00308 }
00309 if (read(fd, secbuf, SECSIZE) != SECSIZE || close(fd) != 0) {
00310 printf("Read error\n");
00311 exit(1);
00312 }
00313 printf("Loaded from %s OK\n", file);
00314 chk_table();
00315 }
00316
00317
00318 save_to_file()
00319 {
00320
00321
00322 char file[80];
00323 int fd;
00324
00325 printf("Enter name of file to save to: ");
00326 if (!mygets(file, (int) sizeof file)) return;
00327 if(chk_table() != OK) printf("Saving anyway\n");
00328 fd = creat(file, SAVE_CREAT_MODE);
00329 #ifdef DOS
00330 if (fd < 0) {
00331 printf("Cannot creat %s\n", file);
00332 return;
00333 }
00334 close(fd);
00335 fd = open(file, 0x8001);
00336 #endif
00337 if (fd < 0)
00338 printf("Cannot open %s\n", file);
00339 else if (write(fd, secbuf, SECSIZE) != SECSIZE || close(fd) != 0)
00340 printf("Write error\n");
00341 else
00342 printf("Saved to %s OK\n", file);
00343 }
00344
00345
00346 dpl_partitions(rawflag)
00347 int rawflag;
00348 {
00349
00350
00351 char active[5];
00352 char basefootnote;
00353 int cyl_mask;
00354 int devnum;
00355 char *format;
00356 int i;
00357 int i1;
00358 char orderfootnote;
00359 struct part_entry *pe;
00360 struct part_entry *pe1;
00361 int sec_mask;
00362 char sizefootnote;
00363 char type[10];
00364
00365 badbases = 0;
00366 badsizes = 0;
00367 badorders = 0;
00368 if (rawflag) {
00369 cyl_mask = 0;
00370 sec_mask = 0xff;
00371 format =
00372 "%2d %3d%c %4s %-9s x%02x %3d x%02x x%02x %3d x%02x %7ld%c%7ld %7ld%c\n";
00373 } else {
00374 cyl_mask = CYL_MASK;
00375 sec_mask = SEC_MASK;
00376 format =
00377 "%2d %3d%c %4s %-9s %4d %3d %3d %4d %3d %3d %7ld%c%7ld %7ld%c\n";
00378 }
00379 printf(
00380 " ----first---- -----last---- --------sectors-------\n"
00381 );
00382 printf(
00383 "Num Sorted Act Type Cyl Head Sec Cyl Head Sec Base Last Size\n"
00384 );
00385 pe = (struct part_entry *) &secbuf[PART_TABLE_OFF];
00386 for (i = 1; i <= NR_PARTITIONS; i++, pe++) {
00387 if (rawflag) {
00388 sprintf(active, "0x%02x", pe->bootind);
00389 sprintf(type, "0x%02x", pe->sysind);
00390 } else {
00391 sprintf(active, "%s", pe->bootind == ACTIVE_FLAG ? "A " : "");
00392 sprintf(type, "%s", systype(pe->sysind));
00393 }
00394
00395
00396 basefootnote = orderfootnote = sizefootnote = ' ';
00397 if (pe->sysind == MINIX_PART && pe->lowsec & 1) {
00398 basefootnote = '+';
00399 ++badbases;
00400 }
00401 if (pe->size & 1) {
00402 sizefootnote = '-';
00403 ++badsizes;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 devnum = 1;
00419 for (i1 = 1, pe1 = (struct part_entry *) &secbuf[PART_TABLE_OFF];
00420 i1 <= NR_PARTITIONS; ++i1, ++pe1)
00421 if (pe1->lowsec == 0 && pe->lowsec == 0 && pe1 < pe ||
00422 pe1->lowsec != 0 &&
00423 (pe->lowsec == 0 || pe->lowsec > pe1->lowsec))
00424 ++devnum;
00425 if (devnum != i) {
00426 orderfootnote = '#';
00427 ++badorders;
00428 }
00429
00430 printf(format,
00431 i,
00432 devnum,
00433 orderfootnote,
00434 active,
00435 type,
00436 pe->start_cyl + ((pe->start_sec & cyl_mask) << CYL_SHIFT),
00437 pe->start_head,
00438 pe->start_sec & sec_mask,
00439 pe->last_cyl + ((pe->last_sec & cyl_mask) << CYL_SHIFT),
00440 pe->last_head,
00441 pe->last_sec & sec_mask,
00442 pe->lowsec,
00443 basefootnote,
00444 pe->lowsec + (pe->size == 0 ? 0 : pe->size - 1),
00445 pe->size,
00446 sizefootnote);
00447 }
00448 }
00449
00450
00451 int chk_table()
00452 {
00453
00454
00455 int active;
00456 unsigned char cylinder;
00457 unsigned char head;
00458 int i;
00459 int i1;
00460 int maxhead;
00461 int maxsec;
00462 struct part_entry *pe;
00463 struct part_entry *pe1;
00464 unsigned char sector;
00465 int seenpart;
00466 int status;
00467
00468 active = 0;
00469 maxhead = 0;
00470 maxsec = 0;
00471 pe = (struct part_entry *) &secbuf[PART_TABLE_OFF];
00472 seenpart = 0;
00473 status = OK;
00474 for (i = 1; i <= NR_PARTITIONS; i++, ++pe) {
00475 if (pe->bootind == ACTIVE_FLAG) active++;
00476 sec_to_hst(pe->lowsec, &head, §or, &cylinder);
00477 if (pe->size == 0 && pe->lowsec == 0) sector = 0;
00478 if (head != pe->start_head || sector != pe->start_sec ||
00479 cylinder != pe->start_cyl) {
00480 printf("Inconsistent base in partition %d.\n", i);
00481 printf("Suspect head and sector parameters.\n");
00482 status = ERR;
00483 }
00484 if (pe->size != 0 || pe->lowsec != 0)
00485 sec_to_hst(pe->lowsec + pe->size - 1, &head, §or, &cylinder);
00486 if (head != pe->last_head || sector != pe->last_sec ||
00487 cylinder != pe->last_cyl) {
00488 printf("Inconsistent size in partition %d.\n", i);
00489 printf("Suspect head and sector parameters.\n");
00490 status = ERR;
00491 }
00492 if (pe->size == 0) continue;
00493 seenpart = 1;
00494 for (i1 = i + 1, pe1 = pe + 1; i1 <= NR_PARTITIONS; ++i1, ++pe1) {
00495 if (pe->lowsec >= pe1->lowsec &&
00496 pe->lowsec < pe1->lowsec + pe1->size ||
00497 pe->lowsec + pe->size - 1 >= pe1->lowsec &&
00498 pe->lowsec + pe->size - 1 < pe1->lowsec + pe1->size)
00499 {
00500 printf("Overlap between partitions %d and %d\n",
00501 i, i1);
00502 status = ERR;
00503 }
00504 }
00505 if (pe->lowsec + pe->size < pe->lowsec) {
00506 printf("Overflow from preposterous size in partition %d.\n",
00507 i);
00508 status = ERR;
00509 }
00510 if (maxhead < pe->start_head) maxhead = pe->start_head;
00511 if (maxhead < pe->last_head) maxhead = pe->last_head;
00512 if (maxsec < (pe->start_sec & SEC_MASK))
00513 maxsec = (pe->start_sec & SEC_MASK);
00514 if (maxsec < (pe->last_sec & SEC_MASK))
00515 maxsec = (pe->last_sec & SEC_MASK);
00516 }
00517 if (seenpart) {
00518 if (maxhead + 1 != nhead || maxsec != nsec) {
00519 printf(
00520 "Disk appears to have mis-specified number of heads or sectors.\n");
00521 printf("Try fdisk -h%d -s%d %s instead of\n",
00522 maxhead + 1, maxsec, devname);
00523 printf(" fdisk -h%d -s%d %s\n", nhead, nsec, devname);
00524 seenpart = 0;
00525 }
00526 } else {
00527 printf(
00528 "Empty table - skipping test on number of heads and sectors.\n");
00529 printf("Assuming %d heads and %d sectors.\n", nhead, nsec);
00530 }
00531 if (!seenpart) printf("Do not write the table if you are not sure!.\n");
00532 if (active > 1) {
00533 printf("%d active partitions\n", active);
00534 status = ERR;
00535 }
00536 return(status);
00537 }
00538
00539 sec_to_hst(logsec, hd, sec, cyl)
00540 long logsec;
00541 unsigned char *hd, *sec, *cyl;
00542 {
00543
00544
00545 int bigcyl;
00546
00547 bigcyl = logsec / (nhead * nsec);
00548 *sec = (logsec % nsec) + 1 + ((bigcyl >> CYL_SHIFT) & CYL_MASK);
00549 *cyl = bigcyl;
00550 *hd = (logsec % (nhead * nsec)) / nsec;
00551 }
00552
00553 mark_partition(pe)
00554 struct part_entry *pe;
00555 {
00556
00557
00558 if (pe != NULL) {
00559 pe->sysind = MINIX_PART;
00560 printf("Partition type is now MINIX\n");
00561 }
00562 }
00563
00564 change_partition(entry)
00565 struct part_entry *entry;
00566 {
00567
00568
00569 int first, last;
00570 long low, high;
00571 int ch;
00572
00573 if (entry == NULL) return;
00574 while (1) {
00575 if (!get_an_int("\tEnter first cylinder (an integer >= 0): ", &first))
00576 return;
00577 if (first >= 0) break;
00578 printf("\t\tThat looks like %d which is negative\n", first);
00579 }
00580 while (1) {
00581 if (!get_an_int(
00582 "\tEnter last cylinder (an integer >= the first cylinder): ", &last))
00583 return;
00584 if (last >= first) break;
00585 printf("\t\tThat looks like %d which is too small\n", last);
00586 }
00587 if (first == 0 && last == 0) {
00588 entry->bootind = 0;
00589 entry->start_head = 0;
00590 entry->start_sec = 0;
00591 entry->start_cyl = 0;
00592 entry->sysind = NO_PART;
00593 entry->last_head = 0;
00594 entry->last_sec = 0;
00595 entry->last_cyl = 0;
00596 entry->lowsec = 0;
00597 entry->size = 0;
00598 printf("Partition deleted\n");
00599 return;
00600 }
00601 low = first & 0xffff;
00602 low = low * nsec * nhead;
00603 if (low == 0) low = 1;
00604 high = last & 0xffff;
00605 high = (high + 1) * nsec * nhead - 1;
00606 entry->lowsec = low;
00607 entry->size = high - low + 1;
00608 if (entry->size & 1) {
00609
00610 --high;
00611 --entry->size;
00612 printf("Size reduced by 1 to make it even\n");
00613 }
00614 sec_to_hst(low, &entry->start_head, &entry->start_sec, &entry->start_cyl);
00615 sec_to_hst(high, &entry->last_head, &entry->last_sec, &entry->last_cyl);
00616 printf("Base of partition changed to %ld, size changed to %ld\n",
00617 entry->lowsec, entry->size);
00618
00619
00620
00621
00622
00623 if (entry->sysind == NO_PART) {
00624 entry->sysind = MINIX_PART;
00625 printf("Partition type changed from None to MINIX\n");
00626 } else if (entry->sysind == MINIX_PART)
00627 printf("Leaving partition type as MINIX\n");
00628 else while (1) {
00629 printf("\tChange partition type from %s to MINIX? (y/n) ",
00630 systype(entry->sysind));
00631 ch = get_a_char();
00632 if (ch == 0 || ch == 'n') {
00633 printf("Leaving partition type as %s\n",
00634 systype(entry->sysind));
00635 break;
00636 } else if (ch == 'y') {
00637 entry->sysind = MINIX_PART;
00638 printf("Partition type changed from %s to MINIX\n",
00639 systype(entry->sysind));
00640 break;
00641 }
00642 }
00643
00644 if (entry->bootind == ACTIVE_FLAG)
00645 printf("Leaving partition active\n");
00646 else while (1) {
00647 printf("\tChange partition to active? (y/n) ");
00648 ch = get_a_char();
00649 if (ch == 0 || ch == 'n') {
00650 printf("Leaving partition inactive\n");
00651 break;
00652 } else if (ch == 'y') {
00653 toggle_active(entry);
00654 break;
00655 }
00656 }
00657 }
00658
00659 get_a_char()
00660 {
00661
00662
00663 char buf[80];
00664 int ch;
00665
00666 if (!mygets(buf, (int) sizeof buf)) return(0);
00667 return(*buf);
00668 }
00669
00670 print_menu()
00671 {
00672 printf("Type a command letter, then a carriage return:\n");
00673 printf(" + - explain any footnotes (+, -, #)\n");
00674 printf(" a - toggle an active flag\n");
00675 printf(" B - adjust a base sector\n");
00676 printf(" c - change a partition\n");
00677 printf(" l - load boot block (including partition table) from a file\n");
00678 printf(" m - mark a partition as a MINIX partition\n");
00679 printf(" n - mark a partition as a non-MINIX partition\n");
00680 printf(" p - print raw partition table\n");
00681 printf(" q - quit without making any changes\n");
00682 printf(" S - adjust a size (by changing the last sector)\n");
00683 printf(" s - save boot block (including partition table) on a file\n");
00684 printf(" t - print known partition types\n");
00685 printf(" v - verify partition table\n");
00686 if (readonly)
00687 printf(" w - write (disabled)\n");
00688 else
00689 printf(" w - write changed partition table back to disk and exit\n");
00690 }
00691
00692
00693
00694
00695 #ifdef DOS
00696
00697 union REGS regs;
00698 struct SREGS sregs;
00699 int drivenum;
00700
00701 getboot(buffer)
00702 char *buffer;
00703 {
00704
00705
00706 segread(&sregs);
00707
00708 if (devname[1] != ':') {
00709 printf("Invalid drive %s\n", devname);
00710 exit(1);
00711 }
00712 if (*devname >= 'a') *devname += 'A' - 'a';
00713 drivenum = (*devname - 'C') & 0xff;
00714 if (drivenum < 0 || drivenum > 7) {
00715 printf("Funny drive number %d\n", drivenum);
00716 exit(1);
00717 }
00718 regs.x.ax = 0x201;
00719 regs.h.ch = 0;
00720 regs.h.cl = 1;
00721 regs.h.dh = 0;
00722 regs.h.dl = 0x80 + drivenum;
00723 sregs.es = sregs.ds;
00724 regs.x.bx = (int) buffer;
00725
00726 int86x(0x13, ®s, ®s, &sregs);
00727 if (regs.x.cflag) {
00728 printf("Cannot read boot sector\n");
00729 exit(1);
00730 }
00731 }
00732
00733
00734 putboot(buffer)
00735 char *buffer;
00736 {
00737
00738
00739 regs.x.ax = 0x301;
00740 regs.h.ch = 0;
00741 regs.h.cl = 1;
00742 regs.h.dh = 0;
00743 regs.h.dl = 0x80 + drivenum;
00744 sregs.es = sregs.ds;
00745 regs.x.bx = (int) buffer;
00746
00747 int86x(0x13, ®s, ®s, &sregs);
00748 if (regs.x.cflag) {
00749 printf("Cannot write boot sector\n");
00750 exit(1);
00751 }
00752 }
00753
00754 #endif
00755
00756 void adj_base(pe)
00757 struct part_entry *pe;
00758 {
00759
00760
00761 int adj;
00762
00763 if (pe == NULL) return;
00764 while (1) {
00765
00766 if (!get_an_int("\tEnter adjustment to base (an integer): ", &adj))
00767 return;
00768 if (pe->lowsec + adj < 1)
00769 printf(
00770 "\t\tThat would make the base %d and too small\n", pe->lowsec + adj);
00771 else if (pe->size - adj < 1)
00772 printf(
00773 "\t\tThat would make the size %d and too small\n", pe->size - adj);
00774 else
00775 break;
00776 }
00777 pe->lowsec += adj;
00778 pe->size -= adj;
00779 sec_to_hst(pe->lowsec, &pe->start_head, &pe->start_sec, &pe->start_cyl);
00780 printf("Base of partition adjusted to %ld, size adjusted to %ld\n",
00781 pe->lowsec, pe->size);
00782 }
00783
00784 void adj_size(pe)
00785 struct part_entry *pe;
00786 {
00787
00788
00789 int adj;
00790
00791 if (pe == NULL) return;
00792 while (1) {
00793 if (!get_an_int("\tEnter adjustment to size (an integer): ", &adj))
00794 return;
00795 if (pe->size + adj >= 1) break;
00796 printf("\t\tThat would make the size %d and too small \n",
00797 pe->size + adj);
00798 }
00799 pe->size += adj;
00800 sec_to_hst(pe->lowsec + pe->size - 1,
00801 &pe->last_head, &pe->last_sec, &pe->last_cyl);
00802 printf("Size of partition adjusted to %ld\n", pe->size);
00803 }
00804
00805 struct part_entry *ask_partition()
00806 {
00807
00808
00809 int num;
00810
00811 while (1) {
00812
00813 if (!get_an_int("Enter partition number (1 to 4): ", &num))
00814 return(NULL);
00815 if (num >= 1 && num <= NR_PARTITIONS) break;
00816 printf("\tThat does not look like 1 to 4\n");
00817 }
00818 printf("Partition %d\n", num);
00819 return((struct part_entry *) &secbuf[PART_TABLE_OFF] + (num - 1));
00820 }
00821
00822 void footnotes()
00823 {
00824
00825
00826 if (badbases != 0) {
00827 printf(
00828 "+ The old Minix wini drivers (before V1.5) discarded odd base sectors.\n");
00829 printf(
00830 " This causes some old (Minix) file systems to be offset by 1 sector.\n");
00831 printf(
00832 " To use these with the new drivers, increase the base by 1 using 'B'.\n");
00833 }
00834
00835 if (badsizes != 0) {
00836 if (badbases != 0) putchar('\n');
00837 printf(
00838 "- Minix cannot access the last sector on an odd-sized partition. This\n");
00839 printf(
00840 " causes trouble for programs like dosread. This program will by default\n");
00841 printf(
00842 " only create partitions with even sizes. If possible, the current odd\n");
00843 printf(
00844 " sizes should be decreased by 1 using 'S'. This is safe for all Minix\n");
00845 printf(
00846 " partitions, and may be safe for other partitions which are about to be\n");
00847 printf(
00848 " reformatted.\n");
00849 }
00850
00851 if (badorders!= 0 ) {
00852 if (badbases != 0 || badsizes != 0) putchar('\n');
00853 printf(
00854 "# The partitions are in a funny order. This is normal if they were created\n");
00855 printf(
00856 " by DOS fdisks prior to DOS 3.3. The Minix wini drivers further confuse\n");
00857 printf(
00858 " the order by sorting the partitions on their base. Be careful if the\n");
00859 printf(
00860 " device numbers of unchanged partitions have changed.\n");
00861 }
00862 }
00863
00864 int get_an_int(prompt, intptr)
00865 char *prompt;
00866 int *intptr;
00867 {
00868
00869
00870 char buf[80];
00871
00872 while (1) {
00873 printf("%s", prompt);
00874 if (!mygets(buf, (int) sizeof buf)) return(0);
00875 if ((sscanf(buf, "%d", intptr)) == 1) return(1);
00876 printf("\t\tThat does not look like an integer\n");
00877 }
00878 }
00879
00880 void list_part_types()
00881 {
00882
00883
00884 int column;
00885 int type;
00886
00887 for (column = 0, type = 0; type < 0x100; ++type)
00888 if (strcmp(systype(type), "Unknown") != 0) {
00889 printf("0x%02x: %-9s", type, systype(type));
00890 column += 16;
00891 if (column < 80)
00892 putchar(' ');
00893 else {
00894 putchar('\n');
00895 column = 0;
00896 }
00897 }
00898 if (column != 0) putchar('\n');
00899 }
00900
00901 void mark_npartition(pe)
00902 struct part_entry *pe;
00903 {
00904
00905
00906 char buf[80];
00907 unsigned type;
00908
00909 if (pe == NULL) return;
00910 printf("\nKnown partition types are:\n\n");
00911 list_part_types();
00912 while (1) {
00913 printf("\nEnter partition type (in 2-digit hex): ");
00914 if (!mygets(buf, (int) sizeof buf)) return;
00915 if (sscanf(buf, "%x", &type) != 1)
00916 printf("Invalid hex number\n");
00917 else if (type >= 0x100)
00918 printf("Hex number too large\n");
00919 else
00920 break;
00921 }
00922 pe->sysind = type;
00923 printf("Partition type changed to 0x%02x (%s)\n", type, systype(type));
00924 }
00925
00926 int mygets(buf, length)
00927 char *buf;
00928 int length;
00929 {
00930
00931
00932 while (1) {
00933 fflush(stdout);
00934 if (fgets(buf, length, stdin) == NULL) {
00935 putchar('\n');
00936 return(0);
00937 }
00938 if (strrchr(buf, '\n') != NULL) *strrchr(buf, '\n') = 0;
00939 if (*buf != 0) return(1);
00940 printf("Use the EOF character to create a null line.\n");
00941 printf("Otherwise, please type something before the newline: ");
00942 }
00943 }
00944
00945 char *systype(type)
00946 int type;
00947 {
00948
00949
00950
00951
00952 switch(type) {
00953 case NO_PART:
00954 return("None");
00955 case 1: return("DOS-12");
00956 case 2: return("XENIX");
00957 case 3: return("XENIX usr");
00958 case 4: return("DOS-16");
00959 case 5: return("DOS-EXT");
00960 case 6: return("DOS-BIG");
00961 case 7: return("HPFS");
00962 case 8: return("AIX");
00963 case 9: return("COHERENT");
00964 case 0x0a: return("OS/2");
00965 case 0x10: return("OPUS");
00966 case 0x40: return("VENIX286");
00967 case 0x51: return("NOVELL?");
00968 case 0x52: return("MICROPORT");
00969 case 0x63: return("386/IX");
00970 case 0x64: return("NOVELL286");
00971 case 0x65: return("NOVELL386");
00972 case 0x75: return("PC/IX");
00973 case 0x80: return("MINIX old");
00974 case 0x81: return("MINIX");
00975 case 0x82: return("LINUXswap");
00976 case 0x83: return("LINUX");
00977 case 0x93: return("AMOEBA");
00978 case 0x94: return("AMOEBAbad");
00979 case 0xa5: return("386BSD");
00980 case 0xb7: return("BSDI");
00981 case 0xb8: return("BSDIswap");
00982 case 0xc7: return("Syrinx");
00983 case 0xDB: return("CP/M");
00984 case 0xe1: return("DOS acc");
00985 case 0xe3: return("DOS r/o");
00986 case 0xf2: return("DOS 2ary");
00987 case 0xFF: return("Badblocks");
00988 default: return("Unknown");
00989 }
00990 }
00991
00992 void toggle_active(pe)
00993 struct part_entry *pe;
00994 {
00995
00996
00997 if (pe == NULL) return;
00998 pe->bootind = (pe->bootind == ACTIVE_FLAG) ? 0 : ACTIVE_FLAG;
00999 printf("Partition changed to %sactive\n", pe->bootind ? "" : "in");
01000 }
01001
01002 void usage()
01003 {
01004
01005
01006 printf("Usage: fdisk [-hheads] [-ssectors] [device]\n");
01007 exit(1);
01008 }
01009