fdisk.c

Go to the documentation of this file.
00001 /* fdisk - partition a hard disk        Author: Jakob Schripsema */
00002 
00003 /* Run this with:
00004  *
00005  *      fdisk [-hheads] [-ssectors] [device]
00006  *
00007  * e.g.,
00008  *
00009  *      fdisk                           (to get the default)
00010  *      fdisk -h4 -s17 /dev/hd0         (MINIX default)
00011  *      fdisk -h4 -s17 c:               (DOS default)
00012  *      fdisk -h6 -s25 /dev/hd5         (second drive, probably RLL)
00013  *      fdisk junkfile                  (to experiment safely)
00014  *
00015  * The device is opened in read-only mode if the file permissions do not
00016  * permit read-write mode, so it is convenient to use a login account with
00017  * only read permission to look at the partition table safely.
00018  *
00019  * Compile with:
00020  *
00021  *      cc -i -o fdisk fdisk.c          (MINIX)
00022  *      cl -DDOS fdisk.c                (DOS with MS C compiler)
00023  *
00024  * This was modified extensively by Bruce Evans 28 Dec 89.
00025  * The new version has not been tried with DOS.  The open modes are suspect
00026  * (everyone should convert to use fcntl.h).
00027  *
00028  * Changed 18 Dec 92 by Kees J. Bot: Bootstrap code and geometry from device.
00029  *
00030  * modified 01 March 95 by asw: updated list of known partition types. Also
00031  * changed display format slightly to allow for partition type names of
00032  * up to 9 chars (previous format allowed for 7, but there were already
00033  * some 8 char names in the list).
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                    /* for MINIX */
00058 #endif
00059 
00060 /* Constants */
00061 
00062 #define DEFAULT_NHEAD   4       /* # heads               */
00063 #define DEFAULT_NSEC    17      /* sectors / track       */
00064 #define SECSIZE         512     /* sector size           */
00065 #define OK              0
00066 #define ERR             1
00067 
00068 #define CYL_MASK        0xc0    /* mask to extract cyl bits from sec field */
00069 #define CYL_SHIFT       2       /* shift to extract cyl bits from sec field */
00070 #define SEC_MASK        0x3f    /* mask to extract sec bits from sec field */
00071 
00072 /* Globals  */
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 /* One featureful master bootstrap. */
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   /* Init */
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   /* Align the sector buffer in such a way that the partition table is at
00173    * a mod 4 offset in memory.  Some weird people add alignment checks to
00174    * their Minix!
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 /* Load buffer from file  */
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 /* Save to file  */
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 /* Display partition table */
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;           /* no contribution of cyl to sec */
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         /* Prepare warnings about confusing setups from old versions. */
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         /* Calculate the "device numbers" resulting from the misguided sorting
00407          * in the wini drivers.  The drivers use this conditional for
00408          * swapping wn[j] > wn[j+1]:
00409          *
00410          *      if ((wn[j].wn_low == 0 && wn[j+1].wn_low != 0) ||
00411          *          (wn[j].wn_low > wn[j+1].wn_low && wn[j+1].wn_low != 0)) {
00412          *
00413          * which simplifies to:
00414          *
00415          *      if (wn[j+1].wn_low != 0 &&
00416          *          (wn[j].wn_low == 0 || wn[j].wn_low > wn[j+1].wn_low)) {
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;       /* pe1 contents < pe contents */
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 /* Check partition table */
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, &sector, &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, &sector, &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 /* Convert a logical sector number to  head / sector / cylinder */
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 /* Mark a partition as being of type MINIX. */
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 /* Get partition info : first & last cylinder */
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;        /* sec0 is master boot record */
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         /* Adjust size to even since Minix works with blocks of 2 sectors. */
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   /* Accept the MINIX partition type.  Usually ignore foreign types, so this
00620    * fdisk can be used on foreign partitions.  Don't allow NO_PART, because
00621    * many DOS fdisks crash on it.
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 /* Read 1 character and discard rest of line */
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 /* Here are the DOS routines for reading and writing the boot sector. */
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 /* Read boot sector  */
00705 
00706   segread(&sregs);              /* get ds */
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;            /* read 1 sectors        */
00719   regs.h.ch = 0;                /* cylinder              */
00720   regs.h.cl = 1;                /* first sector = 1      */
00721   regs.h.dh = 0;                /* head = 0              */
00722   regs.h.dl = 0x80 + drivenum;  /* drive = 0             */
00723   sregs.es = sregs.ds;          /* buffer address        */
00724   regs.x.bx = (int) buffer;
00725 
00726   int86x(0x13, &regs, &regs, &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 /* Write boot sector  */
00738 
00739   regs.x.ax = 0x301;            /* read 1 sectors        */
00740   regs.h.ch = 0;                /* cylinder              */
00741   regs.h.cl = 1;                /* first sector = 1      */
00742   regs.h.dh = 0;                /* head = 0              */
00743   regs.h.dl = 0x80 + drivenum;  /* drive = 0             */
00744   sregs.es = sregs.ds;          /* buffer address        */
00745   regs.x.bx = (int) buffer;
00746 
00747   int86x(0x13, &regs, &regs, &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 /* Adjust base sector of partition, usually to make it even. */
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 /* Adjust size of partition by reducing high sector. */
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 /* Ask for a valid partition number and return its entry. */
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 /* Explain the footnotes. */
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 /* Read an int from the start of line of stdin, discard rest of line. */
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 /* Print all known partition types. */
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 /* Mark a partition with arbitrary type. */
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;                     /* as for fgets(), but must be >= 2 */
00929 {
00930 /* Get a non-empty line of maximum length 'length'. */
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 /* Convert system indicator into system name. */
00949 /* asw 01.03.95: added types based on info in kjb's part.c and output
00950  * from Linux (1.0.8) fdisk. Note comments here, there are disagreements.
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");  /* LINUX says AIX bootable */
00964         case 0x0a: return("OS/2");      /* LINUX says OPUS */
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");    /*LINUX calls this GNU HURD */
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 /* Toggle active flag of a partition. */
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 /* Print usage message and exit. */
01005 
01006   printf("Usage: fdisk [-hheads] [-ssectors] [device]\n");
01007   exit(1);
01008 }
01009 

Generated on Fri Apr 14 22:56:57 2006 for minix by  doxygen 1.4.6