fdisk: Now we are doing PC style partition tables import an fdisk tool
authorAlan Cox <alan@linux.intel.com>
Sun, 28 Dec 2014 23:54:12 +0000 (23:54 +0000)
committerAlan Cox <alan@linux.intel.com>
Sun, 28 Dec 2014 23:54:12 +0000 (23:54 +0000)
Applications/util/Makefile
Applications/util/fdisk.c [new file with mode: 0644]
Applications/util/fdisk.h [new file with mode: 0644]

index f96f5a9..7872325 100644 (file)
@@ -32,6 +32,7 @@ SRCS  = basename.c \
        echo.c \
        ed.c \
        false.c \
+       fdisk.c \
        fsck.c \
        grep.c \
        id.c \
diff --git a/Applications/util/fdisk.c b/Applications/util/fdisk.c
new file mode 100644 (file)
index 0000000..4f38479
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ *  fdisk.c  Disk partitioning program.
+ *  Copyright (C) 1997  David Murn
+ *
+ *  This program is distributed under the GNU General Public Licence, and
+ *  as such, may be freely distributed.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "fdisk.h"
+
+#define isxdigit(x)    ( ((x)>='0' && (x)<='9') || ((x)>='A' && (x)<='F') \
+                                                || ((x)>='a' && (x)<='f') )
+
+#define die { printf("Usage %s [-l] <device-name>\n",argv[0]); fflush(stdout); exit(1); }
+#define spc ((unsigned long)(geometry.heads*geometry.sectors))
+
+static Funcs funcs[] = {
+    { 'a',"Add partion",           add_part },
+    { 'b',"Set bootable flag",     set_boot },
+    { 'd',"Delete partition",      del_part },
+    { 'l',"List partition types",  list_types },
+    { 'p',"Print partition table", list_part },
+    { 'q',"Quit fdisk",            quit },
+    { 't',"Set partition type",    set_type },
+    { 'w',"Write partition table", write_out },
+    { '?',"Help",                  help },
+    {  0,  NULL,                   NULL }
+};
+
+/* Table indexing the valid partition types.
+ *
+ * Any value of 'Y' indicates a valid partition type, and
+ * any other value says otherwise.
+ *
+ * The types in this list are those recognised by the fdisk
+ * command that is distributed with Red Hat Linux 6.2.
+ */
+
+const char partOK[257] =     /*        '0123456789ABCDEF'              */
+
+                               "YYYYYYYYYYYYY.YY"      /*  0x  */
+                               "YYY.Y.YYY..YY.Y."      /*  1x  */
+                               "....Y..........."      /*  2x  */
+                               "............Y..."      /*  3x  */
+                               "YYY..........YYY"      /*  4x  */
+                               "YYYYYYY.....Y..."      /*  5x  */
+                               ".Y.YYY.........."      /*  6x  */
+                               "Y....Y.........."      /*  7x  */
+                               "YYYYYYYY........"      /*  8x  */
+                               "...YY..........."      /*  9x  */
+                               "Y....YYY........"      /*  Ax  */
+                               ".......YY......."      /*  Bx  */
+                               ".Y..Y.YY........"      /*  Cx  */
+                               "...........Y...."      /*  Dx  */
+                               ".Y.YY......Y...."      /*  Ex  */
+                               ".YY.Y........YYY"      /*  Fx  */
+;
+
+#define valid(n)       (partOK[n] == 'Y')
+
+void list_types(void)  /* FIXME - Should make this more flexible */
+{
+    printf(
+       " 0 Empty                  3c PartitionMagic recovery 85 Linux extended\n"
+       " 1 FAT12                  40 Venix 80286             86 NTFS volume set\n"
+       " 2 XENIX root             41 PPC PReP Boot           87 NTFS volume set\n"
+       " 3 XENIX usr              42 SFS                     93 Amoeba\n"
+       " 4 FAT16 <32M             4d QNX4.x                  94 Amoeba BBT\n"
+       " 5 Extended               4e QNX4.x 2nd part         a0 IBM Thinkpad hibernate\n"
+       " 6 FAT16                  4f QNX4.x 3rd part         a5 BSD/386\n"
+       " 7 HPFS/NTFS              50 OnTrack DM              a6 OpenBSD\n"
+       " 8 AIX                    51 OnTrack DM6 Aux1        a7 NeXTSTEP\n"
+       " 9 AIX bootable           52 CP/M                    b7 BSDI fs\n"
+       " a OS/2 Boot Manager      53 OnTrack DM6 Aux3        b8 BSDI swap\n"
+       " b Win9x FAT32            54 OnTrack DM6             c1 DR-DOS/sec FAT-12\n"
+       " c Win9x FAT32 (LBA)      55 EZ-Drive                c4 DR-DOS/sec FAT-16 <32M\n"
+       " e Win9x FAT16 (LBA)      56 Golden Bow              c6 DR-DOS/sec FAT-16\n"
+       " f Win9x Extended (LBA)   5c Priam Edisk             c7 Syrinx\n"
+       "10 OPUS                   61 SpeedStor               db CP/M / CTOS / ...\n"
+       "11 Hide FAT12             63 GNU HURD or SysV        e1 DOS access\n"
+       "12 Compaq diagnostics     64 Novell Netware 286      e3 DOS R/O\n"
+       "14 Hide FAT16 <32M        65 Novell Netware 386      e4 SpeedStor\n"
+       "16 Hide FAT16             70 DiskSecure Multi-Boot   eb BeOS fs\n"
+       "17 Hide HPFS/NTFS         75 PC/IX                   f1 SpeedStor\n"
+       "18 AST Windows swapfile   80 ELKS / Old Minix        f2 DOS secondary\n"
+       "1b Hide Win9x FAT32       81 New Minix / Old Linux   f4 SpeedStor\n"
+       "1c Hide Win9x FAT32 (LBA) 82 Linux swap              fd Linux raid autodetect\n"
+       "1e Hide Win9x FAT16 (LBA) 83 New Linux               fe LANstep\n"
+       "24 NEC DOS                84 OS/2 Hide C:            ff BBT\n"
+    );
+    fflush(stdout);
+}
+
+void quit(void)
+{
+    exit(1);
+}
+
+void list_part(void)
+{
+    if(*dev!=0)
+       list_partition(NULL);
+}
+
+void add_part(void)
+{
+    unsigned char pentry[16];
+    char buf[8];
+    unsigned long tmp;
+    unsigned char *oset;
+    int part, scyl, ecyl;
+
+    pentry[0]=0;
+    printf("Add partition:\n\n");
+    for (part=0;part<1 || part>4;) {
+       printf("Which partition to add(1-4): ");
+       fflush(stdout);
+       fgets(buf,8,stdin);
+       part=atoi(buf);
+       if (*buf=='\n')
+           return;
+    }
+
+    oset=partitiontable+(0x1be)+((part-1)*16);
+
+    printf("geo.cyl=%d\n",geometry.cylinders);
+    for (scyl=geometry.cylinders+1;scyl<0 || scyl>geometry.cylinders;) {
+       printf("First cylinder(%d-%d):",0,geometry.cylinders);
+       fflush(stdout);
+       fgets(buf,8,stdin);
+       scyl=atoi(buf);
+       if (*buf=='\n')
+           return;
+    }
+
+    pentry[1]=scyl==0?1:0;
+    pentry[2]=1+((scyl >> 2) & 0xc0);
+    pentry[3]=(scyl&0xff);
+
+#ifdef PART_TYPE
+    pentry[4]=PART_TYPE;
+#else
+    pentry[4]=0x80;
+#endif
+
+    for (ecyl=geometry.cylinders+1;ecyl<scyl || ecyl>geometry.cylinders;) {
+       printf("Ending cylinder(%d-%d):",0,geometry.cylinders);
+       fflush(stdout);
+       fgets(buf,8,stdin);
+       ecyl=atoi(buf);
+       if(*buf=='\n')
+           return;
+    }
+
+    pentry[5]=geometry.heads-1;
+    pentry[6]=geometry.sectors+((ecyl >> 2) & 0xc0);
+    pentry[7]=(ecyl&0xff);
+
+    tmp=spc*(unsigned long)scyl;
+    if (scyl==0)
+       tmp=(unsigned long)geometry.sectors;
+
+    pentry[11]=(unsigned char)((tmp>>24uL)&0x000000ffuL);
+    pentry[10]=(unsigned char)((tmp>>16uL)&0x000000ffuL);
+    pentry[ 9]=(unsigned char)((tmp>> 8uL)&0x000000ffuL);
+    pentry[ 8]=(unsigned char)((tmp      )&0x000000fful);
+
+    tmp=spc*(unsigned long)(ecyl-scyl+1);
+    if (scyl==0)
+       tmp-=(unsigned long)geometry.sectors;
+
+    pentry[15]=(unsigned char)((tmp>>24uL)&0x000000ffuL);
+    pentry[14]=(unsigned char)((tmp>>16uL)&0x000000ffuL);
+    pentry[13]=(unsigned char)((tmp>> 8uL)&0x000000ffuL);
+    pentry[12]=(unsigned char)((tmp      )&0x000000ffuL);
+
+    printf("Adding partition");
+    memcpy(oset,pentry,16);
+    printf("\n");
+    fflush(stdout);
+}
+
+void set_boot(void)
+{
+    char buf[8];
+    int part, a;
+
+    printf("Toggle bootable flag:\n\n");
+    for(part=0;part<1 || part>4;) {
+       printf("Which partition to toggle(1-4): ");
+       fflush(stdout);
+       fgets(buf,8,stdin);
+       part=atoi(buf);
+       if (*buf=='\n')
+           return;
+    }
+
+    a=(0x1ae)+(part*16);
+    partitiontable[a]=(partitiontable[a]==0x00?0x80:0x00);
+}
+
+int atohex(char *s)
+{
+    int n, r;
+
+    n = 0;
+    if (!isxdigit(*s))
+       return 256;
+    while (*s) {
+       if (*s >= '0' && *s <= '9')
+           r = *s - '0';
+       else if (*s >= 'A' && *s <= 'F')
+           r = *s - 'A' + 10;
+       else if (*s >= 'a' && *s <= 'f')
+           r = *s - 'a' + 10;
+       else
+           break;
+       n = 16 * n + r;
+       s++;
+    }
+    return n;
+}
+
+void set_type(void)  /* FIXME - Should make this more flexible */
+{
+    char buf[8];
+    int part, type, a;
+
+    printf("Set partition type:\n\n");
+    for (part=0;part<1 || part>4;) {
+       printf("Which partition to toggle(1-4): ");
+       fflush(stdout);
+       fgets(buf,8,stdin);
+       part=atoi(buf);
+       if (*buf=='\n')
+           return;
+    }
+    a=(0x1ae)+(part*16)+4;
+    type=256;
+    while (!valid(type)) {
+       printf("Set partition type (l for list, q to quit): ");
+       fflush(stdout);
+       fgets(buf,8,stdin);
+       if (isxdigit(*buf))
+           type=atohex(buf) % 256;
+       else
+           switch (*buf) {
+
+               case 'l':
+                   list_types();
+                   break;
+
+               case 'q':
+                   return;
+
+               default:
+                   printf("Invalid: %c\n", *buf);
+                   break;
+           }
+    }
+    partitiontable[a]=type;
+}
+
+void del_part(void)
+{
+    char buf[8];
+    int part;
+
+    printf("Delete partition:\n\n");
+    for (part=0;part<1 || part>4;) {
+       printf("Which partition to delete(1-4): ");
+       fflush(stdout);
+       fgets(buf,8,stdin);
+       part=atoi(buf);
+       if (*buf=='\n')
+           return;
+    }
+    printf("Deleting partition %d...",part);
+    memset(partitiontable+(0x1be)+((part-1)*16),0,16);
+    printf("Done\n");
+    fflush(stdout);
+}
+
+void write_out(void)
+{
+    int i;
+
+    if (lseek(pFd,0L,SEEK_SET)!=0)
+       printf("ERROR!  Cannot seek to offset 0.\n");
+    else {
+        partitiontable[510] = 0x55;
+        partitiontable[511] = 0xAA;
+       if ((i=write(pFd,partitiontable,512))!=512) {
+           printf("ERROR!  Only wrote %d of 512 bytes to the partition table.\n",i);
+           printf("        Table possibly corrupted.\n");
+       } else
+           printf("Successfully wrote %d bytes to %s\n",i,dev);
+    }
+    fflush(stdout);
+}
+
+void help(void)
+{
+    Funcs *tmp;
+
+    printf("Key Description\n");
+    for (tmp=funcs;tmp->cmd;tmp++)
+       printf("%c   %s\n",tmp->cmd,tmp->help);
+    fflush(stdout);
+}
+
+void list_partition(char *devname)
+{
+    unsigned char ptbl[512],*partition;
+    unsigned long seccnt;
+    int i;
+
+    if (devname!=NULL) {
+       if ((pFd=open(devname,O_RDONLY))==-1) {
+           printf("Error opening %s (%d)\n",devname,-pFd);
+           exit(1);
+       }
+       if ((i=read(pFd,ptbl,512))!=512) {
+           printf("Unable to read first 512 bytes from %s, only read %d bytes\n",
+                  devname,i);
+           exit(1);
+       }
+    } else
+       memcpy(ptbl,partitiontable,512);
+    printf("                      START                  END\n");
+    printf("Device    Boot  Head Sector Cylinder   Head Sector Cylinder  Type  Sector count\n\n");
+    for (i=0x1be;i<0x1fe;i+=16) {
+       partition=ptbl+i;   /* FIXME /--- gotta be a better way to do this ---\ */
+       seccnt= ((unsigned long) partition[15] << 24uL) + \
+               ((unsigned long) partition[14] << 16uL) + \
+               ((unsigned long) partition[13] <<  8uL) + \
+                (unsigned long) partition[12];
+       if (partition[5])
+           printf("%s%d  %c     %2d    %3d    %5d     %2d    %3d    %5d    %2x    %10ld\n",
+               devname==NULL?dev:devname,1+((i-0x1be)/16),
+               partition[0]==0?' ':(partition[0]==0x80?'*':'?'),
+               partition[1],                                /* Start head */
+               partition[2] & 0x3f,                         /* Start sector */
+               partition[3] | ((partition[2] & 0xc0) << 2), /* Start cylinder */
+               partition[5],                                /* End head */
+               partition[6] & 0x3f,                         /* End sector */
+               partition[7] | ((partition[6] & 0xc0) << 2), /* End cylinder */
+               partition[4],                                /* Partition type */
+               seccnt);                                     /* Sector count */
+    }
+    if (devname!=NULL)
+       close(pFd);
+    fflush(stdout);
+}
+
+int main(int argc,char *argv[])
+{
+    int i, mode=MODE_EDIT;
+
+    dev[0]=0;
+    for (i=1;i<argc;i++) {
+       if (*argv[i]=='/') {
+           if (*dev!=0) {
+               printf("Can only specify one device on the command line.\n");
+               exit(1);
+           } else
+               strncpy(dev,argv[i],256); /* FIXME - Should be some value from a header */
+       } else
+           if (*argv[i]=='-')
+               switch(*(argv[i]+1)) {
+                   case 'l':
+                       mode=MODE_LIST;
+                       break;
+                   default:
+                       printf("Unknown command: %s\n",argv[i]);
+                       exit(1);
+               }
+           else
+               die;
+    }
+
+    if(argc==1)
+#ifdef DEFAULT_DEV
+       strncpy(dev,DEFAULT_DEV,256);
+#else
+       die;
+#endif
+
+
+    if (mode==MODE_LIST) {
+       if (*dev!=0)
+           list_partition(dev);
+       else {
+           list_partition("/dev/hda");
+           list_partition("/dev/hdb");
+           /* Other drives */
+       }
+       return(1);
+    }
+
+    if (mode==MODE_EDIT) {
+       char buf[CMDLEN];
+       Funcs *tmp;
+       int flag=0;
+
+       if ((pFd=open(dev,O_RDWR))==-1) {
+           printf("Error opening %s (%d)\n",dev,-pFd);
+           exit(1);
+       }
+
+       if ((i=read(pFd,partitiontable,512))!=512) {
+           printf("Unable to read first 512 bytes from %s, only read %d bytes\n",
+                  dev,i);
+           exit(1);
+       }
+
+       if (ioctl(pFd, HDIO_GETGEO, &geometry)) {
+           printf("Error getting geometry of disk, exiting.\n");
+           exit(1);
+       }
+       if (geometry.heads==0 && geometry.cylinders==0 && geometry.sectors==0)
+           printf("WARNING!  Read disk geometry as 0/0/0.  Things may break.\n");
+       printf("\nGeometry: %d cylinders, %d heads, %d sectors.\n\n",
+               geometry.cylinders,geometry.heads,geometry.sectors);
+       fflush(stdout);
+       while(!feof(stdin)) {
+           printf("Command%s:",flag==0?" (? for help)":"");
+           flag=1;
+           fflush(stdout);
+           *buf = 0;
+           if (fgets(buf,CMDLEN-1,stdin)) {
+               printf("\n");
+               for (tmp=funcs; tmp->cmd; tmp++)
+                   if (*buf==tmp->cmd) {
+                       tmp->func();
+                       break;
+                   }
+           }
+       }
+    }
+    exit(0);
+}
diff --git a/Applications/util/fdisk.h b/Applications/util/fdisk.h
new file mode 100644 (file)
index 0000000..6a2177a
--- /dev/null
@@ -0,0 +1,33 @@
+#define MODE_EDIT 0
+#define MODE_LIST 1
+#define MODE_SIZE 2
+
+#define CMDLEN 8
+
+#define DEFAULT_DEV "/dev/hda"
+
+void quit(void);
+void list_part(void);
+void del_part(void);
+void add_part(void);
+void help(void);
+void write_out(void);
+void list_types(void);
+void list_part(void);
+void set_boot(void);
+void set_type(void);
+
+void list_partition(char *dev);
+
+char dev[256]; /* FIXME - should be a #define'd number from header file */
+int pFd;
+unsigned char partitiontable[512];
+
+typedef struct {
+  int cmd;
+  char *help;
+  void (*func)();
+} Funcs;
+
+struct hd_geometry geometry;
+