Try to make indent formatting less horrible
[oweals/busybox.git] / util-linux / fdisk.c
index ea8400cba5dd75cfbd42ef43ce0f4a82c13e5301..02c5c10ff134ed435a0128a1038f94117976731d 100644 (file)
@@ -7,19 +7,10 @@
  * published by the Free Software Foundation: either version 1 or
  * (at your option) any later version.
  *
- * For detailed old history, see older versions.
- * Contributions before 2001 by faith@cs.unc.edu, Michael Bischoff,
- * LeBlanc@mcc.ac.uk, martin@cs.unc.edu, leisner@sdsp.mc.xerox.com,
- * esr@snark.thyrsus.com, aeb@cwi.nl, quinlan@yggdrasil.com,
- * fasten@cs.bonn.edu, orschaer@cip.informatik.uni-erlangen.de,
- * jj@sunsite.mff.cuni.cz, fasten@shw.com, ANeuper@GUUG.de,
- * kgw@suse.de, kalium@gmx.de, dhuggins@linuxcare.com,
- * michal@ellpspace.math.ualberta.ca and probably others.
- *
  * Vladimir Oleynik <dzo@simtreas.ru> 2001,2002 Busybox port
  */
 
-#define UTIL_LINUX_VERSION "2.11w"
+#define UTIL_LINUX_VERSION "2.12"
 
 #define PROC_PARTITIONS "/proc/partitions"
 
 #include <scsi/scsi.h>          /* SCSI_IOCTL_GET_IDLUN */
 #undef u_char
 
-#ifdef HAVE_blkpg_h
-#include <linux/blkpg.h>
-#endif
-
 #include <sys/ioctl.h>
 #include <sys/param.h>
+#include <sys/sysmacros.h>     /* major */
 
-#include <linux/types.h>        /* for __u32, __u16, __u8, __s16 */
-#include <linux/major.h>        /* FLOPPY_MAJOR */
+#include <stdint.h>        /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
+
+/* Copied from linux/major.h */
+#define FLOPPY_MAJOR    2
 
 #include <sys/utsname.h>
 
@@ -65,7 +55,7 @@
 #define BLKGETSIZE _IO(0x12,96)    /* return device size */
 #define BLKFLSBUF  _IO(0x12,97)    /* flush buffer cache */
 #define BLKSSZGET  _IO(0x12,104)   /* get block device sector size */
-
+#define BLKGETSIZE64 _IOR(0x12,114,8)  /* 8 = sizeof(u64) */
 
 /*
    fdisk.h
 #define cround(n)       (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
 #define scround(x)      (((x)+units_per_sector-1)/units_per_sector)
 
-#if defined(__GNUC__) || defined(HAS_LONG_LONG)
-typedef long long ext2_loff_t;
+
+#if defined(CONFIG_LFS) || defined(FDISK_SUPPORT_LARGE_DISKS) || defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
+typedef long long fdisk_loff_t;
 #else
-typedef long      ext2_loff_t;
+typedef long fdisk_loff_t;
 #endif
 
+
 /* including <linux/hdreg.h> also fails */
 struct hd_geometry {
       unsigned char heads;
@@ -119,6 +111,9 @@ struct systypes {
        const unsigned char *name;
 };
 
+static uint    sector_size = DEFAULT_SECTOR_SIZE,
+       user_set_sector_size,
+       sector_offset = 1;
 
 /*
  * Raw disk label. For DOS-type partition tables the MBR,
@@ -130,7 +125,6 @@ static char MBRbuffer[MAX_SECTOR_SIZE];
 static int     sun_label;                  /* looking at sun disklabel */
 #else
 #define sun_label 0
-#define check_sun_label() 0
 #endif
 #ifdef CONFIG_FEATURE_SGI_LABEL
 static int     sgi_label;                  /* looking at sgi disklabel */
@@ -154,7 +148,6 @@ static int     possibly_osf_label;
 static uint heads, sectors, cylinders;
 static void update_units(void);
 
-static const char *partition_type(unsigned char type);
 
 /*
  * return partition name - uses static storage unless buf is supplied
@@ -214,27 +207,24 @@ enum failure {
 
 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
 
-struct geom {
-       unsigned int heads;
-       unsigned int sectors;
-       unsigned int cylinders;
-};
-
 static const char *disk_device;
-static char *line_ptr;
 static int fd;                  /* the disk */
 static int partitions = 4;      /* maximum partition + 1 */
 static uint display_in_cyl_units = 1;
 static uint units_per_sector = 1;
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static char *line_ptr;
 static void change_units(void);
-static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
-static void get_geometry(struct geom *);
-static int get_boot(enum action what);
+static void reread_partition_table(int leave);
+static void delete_partition(int i);
 static int  get_partition(int warn, int max);
 static void list_types(const struct systypes *sys);
-static void reread_partition_table(int leave);
-static int valid_part_table_flag(const unsigned char *b);
 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
+#endif
+static const char *partition_type(unsigned char type);
+static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
+static void get_geometry(void);
+static int get_boot(enum action what);
 
 #define PLURAL   0
 #define SINGULAR 1
@@ -278,13 +268,15 @@ static unsigned int get_nr_sects(const struct partition *p);
 static struct pte {
        struct partition *part_table;   /* points into sectorbuffer */
        struct partition *ext_pointer;  /* points into sectorbuffer */
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
        char changed;           /* boolean */
+#endif
        uint offset;            /* disk sector number */
        char *sectorbuffer;     /* disk sector contents */
 } ptes[MAXIMUM_PARTS];
 
-static char  line_buffer[LINE_LENGTH];
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static void
 set_all_unchanged(void) {
        int i;
@@ -297,7 +289,7 @@ static void
 set_changed(int i) {
        ptes[i].changed = 1;
 }
-
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
 
 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
 static struct partition *
@@ -314,6 +306,14 @@ str_units(int n) {      /* n==1: use singular */
                return display_in_cyl_units ? _("cylinders") : _("sectors");
 }
 
+static int
+valid_part_table_flag(const unsigned char *b) {
+       return (b[510] == 0x55 && b[511] == 0xaa);
+}
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static char  line_buffer[LINE_LENGTH];
+
 /* read line; return 0 or first char */
 static int
 read_line(void)
@@ -326,7 +326,6 @@ read_line(void)
                if (feof(stdin))
                        got_eof++;      /* user typed ^D ? */
                if (got_eof >= 3) {
-                       fflush(stdout);
                        fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
                        exit(1);
                }
@@ -377,6 +376,7 @@ read_hex(const struct systypes *sys)
           }
        }
 }
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
 
 #ifdef CONFIG_FEATURE_AIX_LABEL
 /*
@@ -402,8 +402,11 @@ typedef struct {
 
 /*
   Changes:
-  Sat Mar 20 09:51:38 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
-       Internationalization
+  * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+  *     Internationalization
+  *
+  * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
+  *      Some fixes
 */
 
 static  int     aix_other_endian;
@@ -497,7 +500,7 @@ check_aix_label( void )
 
 
 #ifndef BSD_DISKMAGIC
-#define BSD_DISKMAGIC     ((__u32) 0x82564557)
+#define BSD_DISKMAGIC     ((uint32_t) 0x82564557)
 #endif
 
 #ifndef BSD_MAXPARTITIONS
@@ -512,6 +515,9 @@ check_aix_label( void )
 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
 #define BSD_LABELSECTOR   0
 #define BSD_LABELOFFSET   64
+#elif defined (__s390__) || defined (__s390x__)
+#define BSD_LABELSECTOR   1
+#define BSD_LABELOFFSET   0
 #else
 #error unknown architecture
 #endif
@@ -520,31 +526,31 @@ check_aix_label( void )
 #define BSD_SBSIZE        8192          /* max size of fs superblock */
 
 struct xbsd_disklabel {
-       __u32   d_magic;                /* the magic number */
-       __s16   d_type;                 /* drive type */
-       __s16   d_subtype;              /* controller/d_type specific */
+       uint32_t   d_magic;                /* the magic number */
+       int16_t   d_type;                 /* drive type */
+       int16_t   d_subtype;              /* controller/d_type specific */
        char    d_typename[16];         /* type name, e.g. "eagle" */
        char    d_packname[16];                 /* pack identifier */
                        /* disk geometry: */
-       __u32   d_secsize;              /* # of bytes per sector */
-       __u32   d_nsectors;             /* # of data sectors per track */
-       __u32   d_ntracks;              /* # of tracks per cylinder */
-       __u32   d_ncylinders;           /* # of data cylinders per unit */
-       __u32   d_secpercyl;            /* # of data sectors per cylinder */
-       __u32   d_secperunit;           /* # of data sectors per unit */
+       uint32_t   d_secsize;              /* # of bytes per sector */
+       uint32_t   d_nsectors;             /* # of data sectors per track */
+       uint32_t   d_ntracks;              /* # of tracks per cylinder */
+       uint32_t   d_ncylinders;           /* # of data cylinders per unit */
+       uint32_t   d_secpercyl;            /* # of data sectors per cylinder */
+       uint32_t   d_secperunit;           /* # of data sectors per unit */
        /*
         * Spares (bad sector replacements) below
         * are not counted in d_nsectors or d_secpercyl.
         * Spare sectors are assumed to be physical sectors
         * which occupy space at the end of each track and/or cylinder.
         */
-       __u16   d_sparespertrack;       /* # of spare sectors per track */
-       __u16   d_sparespercyl;         /* # of spare sectors per cylinder */
+       uint16_t   d_sparespertrack;       /* # of spare sectors per track */
+       uint16_t   d_sparespercyl;         /* # of spare sectors per cylinder */
        /*
         * Alternate cylinders include maintenance, replacement,
         * configuration description areas, etc.
         */
-       __u32   d_acylinders;           /* # of alt. cylinders per unit */
+       uint32_t   d_acylinders;           /* # of alt. cylinders per unit */
 
                        /* hardware characteristics: */
        /*
@@ -563,30 +569,30 @@ struct xbsd_disklabel {
         * Finally, d_cylskew is the offset of sector 0 on cylinder N
         * relative to sector 0 on cylinder N-1.
         */
-       __u16   d_rpm;                  /* rotational speed */
-       __u16   d_interleave;           /* hardware sector interleave */
-       __u16   d_trackskew;            /* sector 0 skew, per track */
-       __u16   d_cylskew;              /* sector 0 skew, per cylinder */
-       __u32   d_headswitch;           /* head switch time, usec */
-       __u32   d_trkseek;              /* track-to-track seek, usec */
-       __u32   d_flags;                /* generic flags */
+       uint16_t   d_rpm;                  /* rotational speed */
+       uint16_t   d_interleave;           /* hardware sector interleave */
+       uint16_t   d_trackskew;            /* sector 0 skew, per track */
+       uint16_t   d_cylskew;              /* sector 0 skew, per cylinder */
+       uint32_t   d_headswitch;           /* head switch time, usec */
+       uint32_t   d_trkseek;              /* track-to-track seek, usec */
+       uint32_t   d_flags;                /* generic flags */
 #define NDDATA 5
-       __u32   d_drivedata[NDDATA];    /* drive-type specific information */
+       uint32_t   d_drivedata[NDDATA];    /* drive-type specific information */
 #define NSPARE 5
-       __u32   d_spare[NSPARE];        /* reserved for future use */
-       __u32   d_magic2;               /* the magic number (again) */
-       __u16   d_checksum;             /* xor of data incl. partitions */
+       uint32_t   d_spare[NSPARE];        /* reserved for future use */
+       uint32_t   d_magic2;               /* the magic number (again) */
+       uint16_t   d_checksum;             /* xor of data incl. partitions */
                        /* filesystem and partition information: */
-       __u16   d_npartitions;          /* number of partitions in following */
-       __u32   d_bbsize;               /* size of boot area at sn0, bytes */
-       __u32   d_sbsize;               /* max size of fs superblock, bytes */
+       uint16_t   d_npartitions;          /* number of partitions in following */
+       uint32_t   d_bbsize;               /* size of boot area at sn0, bytes */
+       uint32_t   d_sbsize;               /* max size of fs superblock, bytes */
        struct xbsd_partition    {      /* the partition table */
-               __u32   p_size;         /* number of sectors in partition */
-               __u32   p_offset;       /* starting sector */
-               __u32   p_fsize;        /* filesystem basic fragment size */
-               __u8    p_fstype;       /* filesystem type, see below */
-               __u8    p_frag;         /* filesystem fragments per block */
-               __u16   p_cpg;          /* filesystem cylinders per group */
+               uint32_t   p_size;         /* number of sectors in partition */
+               uint32_t   p_offset;       /* starting sector */
+               uint32_t   p_fsize;        /* filesystem basic fragment size */
+               uint8_t    p_fstype;       /* filesystem type, see below */
+               uint8_t    p_frag;         /* filesystem fragments per block */
+               uint16_t   p_cpg;          /* filesystem cylinders per group */
        } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
 };
 
@@ -792,9 +798,9 @@ typedef struct {
 #define SGI_INFO_MAGIC          0x00072959
 #define SGI_INFO_MAGIC_SWAPPED  0x59290700
 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
-                                : (__u16)(x))
+                                : (uint16_t)(x))
 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
-                                : (__u32)(x))
+                                : (uint32_t)(x))
 
 #define sgilabel ((sgi_partition *)MBRbuffer)
 #define sgiparam (sgilabel->devparam)
@@ -820,21 +826,23 @@ typedef struct {
        unsigned short nsect;      /* Sectors per track */
        unsigned char spare3[4];   /* Even more magic... */
        struct sun_partition {
-               __u32 start_cylinder;
-               __u32 num_sectors;
+               uint32_t start_cylinder;
+               uint32_t num_sectors;
        } partitions[8];
        unsigned short magic;      /* Magic number */
        unsigned short csum;       /* Label xor'd checksum */
 } sun_partition;
 
+
 #define SUN_LABEL_MAGIC          0xDABE
 #define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
 #define sunlabel ((sun_partition *)MBRbuffer)
 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
-                                : (__u16)(x))
+                                : (uint16_t)(x))
 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
-                                : (__u32)(x))
+                                : (uint32_t)(x))
 
+#if defined(FDISK_SUPPORT_LARGE_DISKS)
 /*
  * llseek.c -- stub calling the llseek system call
  *
@@ -843,61 +851,41 @@ typedef struct {
  */
 
 
-#ifdef __linux__
-
-#ifdef HAVE_LLSEEK
 #include <syscall.h>
 
-#else   /* HAVE_LLSEEK */
 
-#if defined(__alpha__) || defined(__ia64__)
+#if defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
 
 #define my_llseek lseek
 
 #else
-#include <linux/unistd.h>       /* for __NR__llseek */
 
 static int _llseek (unsigned int, unsigned long,
-                  unsigned long, ext2_loff_t *, unsigned int);
-
-#ifdef __NR__llseek
+                  unsigned long, fdisk_loff_t *, unsigned int);
 
 static _syscall5(int,_llseek,unsigned int,f_d,unsigned long,offset_high,
-                unsigned long, offset_low,ext2_loff_t *,result,
+                unsigned long, offset_low,fdisk_loff_t *,result,
                 unsigned int, origin)
 
-#else
-
-/* no __NR__llseek on compilation machine - might give it explicitly */
-static int _llseek (unsigned int f_d, unsigned long oh,
-                   unsigned long ol, ext2_loff_t *result,
-                   unsigned int origin) {
-       errno = ENOSYS;
-       return -1;
-}
-
-#endif
-
-static ext2_loff_t my_llseek (unsigned int f_d, ext2_loff_t offset,
+static fdisk_loff_t my_llseek (unsigned int f_d, fdisk_loff_t offset,
                unsigned int origin)
 {
-       ext2_loff_t result;
+       fdisk_loff_t result;
        int retval;
 
        retval = _llseek (f_d, ((unsigned long long) offset) >> 32,
                        ((unsigned long long) offset) & 0xffffffff,
                        &result, origin);
-       return (retval == -1 ? (ext2_loff_t) retval : result);
+       return (retval == -1 ? (fdisk_loff_t) retval : result);
 }
 
 #endif /* __alpha__ */
 
-#endif  /* HAVE_LLSEEK */
 
-static ext2_loff_t ext2_llseek (unsigned int f_d, ext2_loff_t offset,
+static fdisk_loff_t fdisk_llseek (unsigned int f_d, fdisk_loff_t offset,
                         unsigned int origin)
 {
-       ext2_loff_t result;
+       fdisk_loff_t result;
        static int do_compat = 0;
 
        if (!do_compat) {
@@ -915,28 +903,17 @@ static ext2_loff_t ext2_llseek (unsigned int f_d, ext2_loff_t offset,
                 */
        }
 
-       if ((sizeof(off_t) >= sizeof(ext2_loff_t)) ||
-           (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1))))
+       if ((sizeof(off_t) >= sizeof(fdisk_loff_t)) ||
+           (offset < ((fdisk_loff_t) 1 << ((sizeof(off_t)*8) -1))))
                return lseek(f_d, (off_t) offset, origin);
 
        errno = EINVAL;
        return -1;
 }
+#else
+# define fdisk_llseek lseek
+#endif  /* FDISK_SUPPORT_LARGE_DISKS */
 
-#else /* !linux */
-
-static ext2_loff_t ext2_llseek (unsigned int f_d, ext2_loff_t offset,
-                        unsigned int origin)
-{
-       if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
-           (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
-               errno = EINVAL;
-               return -1;
-       }
-       return lseek (f_d, (off_t) offset, origin);
-}
-
-#endif  /* linux */
 
 
 #ifdef CONFIG_FEATURE_OSF_LABEL
@@ -1007,7 +984,7 @@ check_osf_label(void) {
 static void xbsd_print_disklabel(int);
 
 static int
-btrydev (char * dev) {
+btrydev (const char * dev) {
        if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
                return -1;
        printf(_("\nBSD label for device: %s\n"), dev);
@@ -1196,60 +1173,59 @@ static void
 xbsd_print_disklabel (int show_all) {
   struct xbsd_disklabel *lp = &xbsd_dlabel;
   struct xbsd_partition *pp;
-  FILE *f = stdout;
   int i, j;
 
   if (show_all) {
 #if defined (__alpha__)
-    fprintf(f, "# %s:\n", disk_device);
+    printf("# %s:\n", disk_device);
 #else
-    fprintf(f, "# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
+    printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
 #endif
     if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
-      fprintf(f, _("type: %s\n"), xbsd_dktypenames[lp->d_type]);
+      printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
     else
-      fprintf(f, _("type: %d\n"), lp->d_type);
-    fprintf(f, _("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
-    fprintf(f, _("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
-    fprintf(f, _("flags:"));
+      printf(_("type: %d\n"), lp->d_type);
+    printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
+    printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
+    printf(_("flags:"));
     if (lp->d_flags & BSD_D_REMOVABLE)
-      fprintf(f, _(" removable"));
+      printf(_(" removable"));
     if (lp->d_flags & BSD_D_ECC)
-      fprintf(f, _(" ecc"));
+      printf(_(" ecc"));
     if (lp->d_flags & BSD_D_BADSECT)
-      fprintf(f, _(" badsect"));
-    fprintf(f, "\n");
+      printf(_(" badsect"));
+    printf("\n");
     /* On various machines the fields of *lp are short/int/long */
     /* In order to avoid problems, we cast them all to long. */
-    fprintf(f, _("bytes/sector: %ld\n"), (long) lp->d_secsize);
-    fprintf(f, _("sectors/track: %ld\n"), (long) lp->d_nsectors);
-    fprintf(f, _("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
-    fprintf(f, _("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
-    fprintf(f, _("cylinders: %ld\n"), (long) lp->d_ncylinders);
-    fprintf(f, _("rpm: %d\n"), lp->d_rpm);
-    fprintf(f, _("interleave: %d\n"), lp->d_interleave);
-    fprintf(f, _("trackskew: %d\n"), lp->d_trackskew);
-    fprintf(f, _("cylinderskew: %d\n"), lp->d_cylskew);
-    fprintf(f, _("headswitch: %ld\t\t# milliseconds\n"),
+    printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
+    printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
+    printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
+    printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
+    printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
+    printf(_("rpm: %d\n"), lp->d_rpm);
+    printf(_("interleave: %d\n"), lp->d_interleave);
+    printf(_("trackskew: %d\n"), lp->d_trackskew);
+    printf(_("cylinderskew: %d\n"), lp->d_cylskew);
+    printf(_("headswitch: %ld\t\t# milliseconds\n"),
            (long) lp->d_headswitch);
-    fprintf(f, _("track-to-track seek: %ld\t# milliseconds\n"),
+    printf(_("track-to-track seek: %ld\t# milliseconds\n"),
            (long) lp->d_trkseek);
-    fprintf(f, _("drivedata: "));
+    printf(_("drivedata: "));
     for (i = NDDATA - 1; i >= 0; i--)
       if (lp->d_drivedata[i])
        break;
     if (i < 0)
       i = 0;
     for (j = 0; j <= i; j++)
-      fprintf(f, "%ld ", (long) lp->d_drivedata[j]);
+      printf("%ld ", (long) lp->d_drivedata[j]);
   }
-  fprintf (f, _("\n%d partitions:\n"), lp->d_npartitions);
-  fprintf (f, _("#       start       end      size     fstype   [fsize bsize   cpg]\n"));
+  printf(_("\n%d partitions:\n"), lp->d_npartitions);
+  printf(_("#       start       end      size     fstype   [fsize bsize   cpg]\n"));
   pp = lp->d_partitions;
   for (i = 0; i < lp->d_npartitions; i++, pp++) {
     if (pp->p_size) {
       if (display_in_cyl_units && lp->d_secpercyl) {
-       fprintf(f, "  %c: %8ld%c %8ld%c %8ld%c  ",
+       printf("  %c: %8ld%c %8ld%c %8ld%c  ",
                'a' + i,
                (long) pp->p_offset / lp->d_secpercyl + 1,
                (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
@@ -1259,33 +1235,33 @@ xbsd_print_disklabel (int show_all) {
                (long) pp->p_size / lp->d_secpercyl,
                (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
       } else {
-       fprintf(f, "  %c: %8ld  %8ld  %8ld   ",
+       printf("  %c: %8ld  %8ld  %8ld   ",
                'a' + i,
                (long) pp->p_offset,
                (long) pp->p_offset + pp->p_size - 1,
                (long) pp->p_size);
       }
       if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
-       fprintf(f, "%8.8s", xbsd_fstypes[pp->p_fstype].name);
+       printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
       else
-       fprintf(f, "%8x", pp->p_fstype);
+       printf("%8x", pp->p_fstype);
       switch (pp->p_fstype) {
        case BSD_FS_UNUSED:
-         fprintf(f, "    %5ld %5ld %5.5s ",
+         printf("    %5ld %5ld %5.5s ",
                  (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
          break;
 
        case BSD_FS_BSDFFS:
-         fprintf(f, "    %5ld %5ld %5d ",
+         printf("    %5ld %5ld %5d ",
                  (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
                  pp->p_cpg);
          break;
 
        default:
-         fprintf(f, "%22.22s", "");
+         printf("%22.22s", "");
          break;
       }
-      fprintf(f, "\n");
+      printf("\n");
     }
   }
 }
@@ -1318,7 +1294,8 @@ xbsd_create_disklabel (void) {
                c = read_char (_("Do you want to create a disklabel? (y/n) "));
                if (c == 'y' || c == 'Y') {
                        if (xbsd_initlabel (
-#if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__)
+#if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
+    defined (__s390__) || defined (__s390x__)
                                NULL, &xbsd_dlabel, 0
 #else
                                xbsd_part, &xbsd_dlabel, xbsd_part_index
@@ -1464,7 +1441,7 @@ xbsd_write_bootstrap (void)
   sector = get_start_sect(xbsd_part);
 #endif
 
-  if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
+  if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
     fdisk_fatal (unable_to_seek);
   if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
     fdisk_fatal (unable_to_write);
@@ -1552,9 +1529,8 @@ xbsd_dkcksum (struct xbsd_disklabel *lp) {
 static int
 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
        struct xbsd_partition *pp;
-       struct geom g;
 
-       get_geometry (&g);
+       get_geometry ();
        bzero (d, sizeof (struct xbsd_disklabel));
 
        d -> d_magic = BSD_DISKMAGIC;
@@ -1574,10 +1550,10 @@ xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
        d -> d_flags = 0;
 #endif
        d -> d_secsize = SECTOR_SIZE;           /* bytes/sector  */
-       d -> d_nsectors = g.sectors;            /* sectors/track */
-       d -> d_ntracks = g.heads;               /* tracks/cylinder (heads) */
-       d -> d_ncylinders = g.cylinders;
-       d -> d_secpercyl  = g.sectors * g.heads;/* sectors/cylinder */
+       d -> d_nsectors = sectors;            /* sectors/track */
+       d -> d_ntracks = heads;               /* tracks/cylinder (heads) */
+       d -> d_ncylinders = cylinders;
+       d -> d_secpercyl  = sectors * heads;/* sectors/cylinder */
        if (d -> d_secpercyl == 0)
                d -> d_secpercyl = 1;           /* avoid segfaults */
        d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
@@ -1633,7 +1609,7 @@ xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
        sector = 0;
 #endif
 
-       if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
+       if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
                fdisk_fatal (unable_to_seek);
        if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
                fdisk_fatal (unable_to_read);
@@ -1660,7 +1636,7 @@ xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
 static int
 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
 {
-  int sector;
+  unsigned int sector;
 
 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
   sector = get_start_sect(p) + BSD_LABELSECTOR;
@@ -1679,12 +1655,12 @@ xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
 
 #if defined (__alpha__) && BSD_LABELSECTOR == 0
   alpha_bootblock_checksum (disklabelbuffer);
-  if (ext2_llseek (fd, (ext2_loff_t) 0, SEEK_SET) == -1)
+  if (fdisk_llseek (fd, (fdisk_loff_t) 0, SEEK_SET) == -1)
     fdisk_fatal (unable_to_seek);
   if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
     fdisk_fatal (unable_to_write);
 #else
-  if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
+  if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
                   SEEK_SET) == -1)
     fdisk_fatal (unable_to_seek);
   if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
@@ -1761,12 +1737,15 @@ alpha_bootblock_checksum (char *boot)
 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
 static inline unsigned short
 __swap16(unsigned short x) {
-       return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8);
+       return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
 }
 
-static inline __u32
-__swap32(__u32 x) {
-       return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24);
+static inline uint32_t
+__swap32(uint32_t x) {
+        return (((x & 0xFF) << 24) |
+               ((x & 0xFF00) << 8) |
+               ((x & 0xFF0000) >> 8) |
+               ((x & 0xFF000000) >> 24));
 }
 #endif
 
@@ -1792,40 +1771,39 @@ static  short   sgi_volumes=1;
  * only dealing with free blocks here
  */
 
-typedef struct { int first; int last; } freeblocks;
+typedef struct { unsigned int first; unsigned int last; } freeblocks;
 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
 
 static void
-setfreelist( int i, int f, int l ) {
+setfreelist(int i, unsigned int f, unsigned int l) {
        freelist[i].first = f;
        freelist[i].last = l;
 }
 
 static void
-add2freelist( int f, int l ) {
+add2freelist(unsigned int f, unsigned int l) {
        int i = 0;
-       for( ; i<17 ; i++ ) {
-               if(freelist[i].last==0) break;
-       }
-       setfreelist( i, f, l );
+       for ( ; i < 17 ; i++)
+               if (freelist[i].last == 0)
+                       break;
+       setfreelist(i, f, l);
 }
 
 static void
 clearfreelist(void) {
-       int i = 0;
-       for( ; i<17 ; i++ ) {
-               setfreelist( i, 0, 0 );
-       }
+       int i;
+
+       for (i = 0; i < 17 ; i++)
+               setfreelist(i, 0, 0);
 }
 
-static int
-isinfreelist( int b ) {
-       int i = 0;
-       for( ; i<17 ; i++ ) {
-               if (freelist[i].first <= b && freelist[i].last >= b) {
+static unsigned int
+isinfreelist(unsigned int b) {
+       int i;
+
+       for (i = 0; i < 17 ; i++)
+               if (freelist[i].first <= b && freelist[i].last >= b)
                        return freelist[i].last;
-               }
-       }
        return 0;
 }
        /* return last vacant block of this stride (never 0). */
@@ -1867,11 +1845,6 @@ sgi_get_ntrks(void) {
     return SGI_SSWAP16(sgilabel->devparam.ntrks);
 }
 
-static int
-sgi_get_pcylcount(void) {
-    return SGI_SSWAP16(sgilabel->devparam.pcylcount);
-}
-
 static void
 sgi_nolabel(void) {
     sgilabel->magic = 0;
@@ -1880,13 +1853,13 @@ sgi_nolabel(void) {
 }
 
 static unsigned int
-two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */ ) {
+two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
     int i=0;
     unsigned int sum=0;
 
-    size = size / sizeof( unsigned int );
-    for( i=0; i<size; i++ )
-       sum = sum - SGI_SSWAP32(base[i]);
+    size /= sizeof(unsigned int);
+    for (i = 0; i < size; i++)
+           sum -= SGI_SSWAP32(base[i]);
     return sum;
 }
 
@@ -1910,15 +1883,10 @@ check_sgi_label(void) {
     /*
      * test for correct checksum
      */
-    if( two_s_complement_32bit_sum( (unsigned int*)sgilabel,
-                       sizeof(*sgilabel) ) )
-    {
-       fprintf( stderr, _("Detected sgi disklabel with wrong checksum.\n"));
-    } else
-    {
-       heads = sgi_get_ntrks();
-       cylinders = sgi_get_pcylcount();
-       sectors = sgi_get_nsect();
+    if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
+                                      sizeof(*sgilabel))) {
+               fprintf(stderr,
+                       _("Detected sgi disklabel with wrong checksum.\n"));
     }
     update_units();
     sgi_label = 1;
@@ -1927,18 +1895,18 @@ check_sgi_label(void) {
     return 1;
 }
 
-static int
-sgi_get_start_sector( int i ) {
+static unsigned int
+sgi_get_start_sector(int i) {
     return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
 }
 
-static int
-sgi_get_num_sectors( int i ) {
+static unsigned int
+sgi_get_num_sectors(int i) {
     return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
 }
 
 static int
-sgi_get_sysid( int i )
+sgi_get_sysid(int i)
 {
     return SGI_SSWAP32(sgilabel->partitions[i].id);
 }
@@ -1956,14 +1924,11 @@ sgi_get_swappartition(void)
 }
 
 static void
-sgi_list_table( int xtra ) {
-    int i, w;
+sgi_list_table(int xtra) {
+    int i, w, wd;
     int kpi = 0;                /* kernel partition ID */
-    const char *type;
 
-    w = strlen( disk_device );
-
-    if( xtra ) {
+    if(xtra) {
        printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
               "%d cylinders, %d physical cylinders\n"
               "%d extra sects/cyl, interleave %d:1\n"
@@ -1982,38 +1947,42 @@ sgi_list_table( int xtra ) {
                disk_device, heads, sectors, cylinders,
                str_units(PLURAL), units_per_sector );
     }
+
+    w = strlen(disk_device);
+    wd = strlen(_("Device"));
+    if (w < wd)
+       w = wd;
+
     printf(_("----- partitions -----\n"
           "Pt# %*s  Info     Start       End   Sectors  Id  System\n"),
-          w + 1, _("Device"));
+           w + 2, _("Device"));
     for (i = 0 ; i < partitions; i++) {
            if( sgi_get_num_sectors(i) || debug ) {
-           __u32 start = sgi_get_start_sector(i);
-           __u32 len = sgi_get_num_sectors(i);
+           uint32_t start = sgi_get_start_sector(i);
+           uint32_t len = sgi_get_num_sectors(i);
            kpi++;              /* only count nonempty partitions */
            printf(
                "%2d: %s %4s %9ld %9ld %9ld  %2x  %s\n",
 /* fdisk part number */   i+1,
-/* device */              partname(disk_device, kpi, w+2),
+/* device */              partname(disk_device, kpi, w+3),
 /* flags */               (sgi_get_swappartition() == i) ? "swap" :
 /* flags */               (sgi_get_bootpartition() == i) ? "boot" : "    ",
 /* start */               (long) scround(start),
 /* end */                 (long) scround(start+len)-1,
 /* no odd flag on end */  (long) len,
 /* type id */             sgi_get_sysid(i),
-/* type name */           (type = partition_type(sgi_get_sysid(i)))
-                   ? type : _("Unknown"));
+/* type name */           partition_type(sgi_get_sysid(i)));
        }
     }
     printf(_("----- Bootinfo -----\nBootfile: %s\n"
             "----- Directory Entries -----\n"),
-          sgilabel->boot_file );
-    for (i = 0 ; i < sgi_volumes; i++)
-    {
-       if (sgilabel->directory[i].vol_file_size)
-       {
-           __u32 start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
-           __u32 len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
+              sgilabel->boot_file);
+       for (i = 0 ; i < sgi_volumes; i++) {
+           if (sgilabel->directory[i].vol_file_size) {
+           uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
+           uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
            char*name = sgilabel->directory[i].vol_file_name;
+
            printf(_("%2d: %-10s sector%5u size%8u\n"),
                    i, name, (unsigned int) start, (unsigned int) len);
        }
@@ -2026,7 +1995,7 @@ sgi_set_bootpartition( int i )
     sgilabel->boot_part = SGI_SSWAP16(((short)i));
 }
 
-static int
+static unsigned int
 sgi_get_lastblock(void) {
     return heads * sectors * cylinders;
 }
@@ -2037,28 +2006,29 @@ sgi_set_swappartition( int i ) {
 }
 
 static int
-sgi_check_bootfile( const char* aFile ) {
-    if( strlen( aFile ) < 3 ) /* "/a\n" is minimum */
-    {
-       printf( _("\nInvalid Bootfile!\n"
+sgi_check_bootfile(const char* aFile) {
+
+       if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
+               printf(_("\nInvalid Bootfile!\n"
                "\tThe bootfile must be an absolute non-zero pathname,\n"
-               "\te.g. \"/unix\" or \"/unix.save\".\n") );
+                        "\te.g. \"/unix\" or \"/unix.save\".\n"));
        return 0;
-    } else
-    if( strlen( aFile ) > 16 )
-    {
-       printf( _("\n\tName of Bootfile too long:  16 bytes maximum.\n") );
+       } else {
+               if (strlen(aFile) > 16) {
+                       printf(_("\n\tName of Bootfile too long:  "
+                                "16 bytes maximum.\n"));
        return 0;
-    } else
-    if( aFile[0] != '/' )
-    {
-       printf( _("\n\tBootfile must have a fully qualified pathname.\n") );
+               } else {
+                       if (aFile[0] != '/') {
+                               printf(_("\n\tBootfile must have a "
+                                        "fully qualified pathname.\n"));
        return 0;
     }
-    if( strncmp( aFile, sgilabel->boot_file, 16 ) )
-    {
-       printf( _("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
-               "SGI's default is \"/unix\" and for backup \"/unix.save\".\n") );
+               }
+       }
+       if (strncmp(aFile, sgilabel->boot_file, 16)) {
+               printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
+                        "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
        /* filename is correct and did change */
        return 1;
     }
@@ -2071,21 +2041,19 @@ sgi_get_bootfile(void) {
 }
 
 static void
-sgi_set_bootfile( const char* aFile )
-{
+sgi_set_bootfile(const char* aFile) {
     int i = 0;
-    if( sgi_check_bootfile( aFile ) )
-    {
-       while( i<16 )
-       {
-           if( (aFile[i] != '\n')      /* in principle caught again by next line */
-           &&  (strlen( aFile ) > i ) )
+
+    if (sgi_check_bootfile(aFile)) {
+       while (i < 16) {
+           if ((aFile[i] != '\n')  /* in principle caught again by next line */
+                           &&  (strlen(aFile) > i))
                sgilabel->boot_file[i] = aFile[i];
            else
                sgilabel->boot_file[i] = 0;
            i++;
        }
-       printf( _("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file );
+       printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
     }
 }
 
@@ -2093,200 +2061,179 @@ static void
 create_sgiinfo(void)
 {
     /* I keep SGI's habit to write the sgilabel to the second block */
-    sgilabel->directory[0].vol_file_start = SGI_SSWAP32( 2 );
-    sgilabel->directory[0].vol_file_size = SGI_SSWAP32( sizeof( sgiinfo ) );
-    strncpy( sgilabel->directory[0].vol_file_name, "sgilabel", 8 );
+    sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
+    sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
+    strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
 }
 
-static sgiinfo * fill_sgiinfo(void);
+static sgiinfo *fill_sgiinfo(void);
 
 static void
-sgi_write_table(void)
-{
+sgi_write_table(void) {
     sgilabel->csum = 0;
-    sgilabel->csum = SGI_SSWAP32( two_s_complement_32bit_sum(
+     sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
                                 (unsigned int*)sgilabel,
-                                sizeof(*sgilabel) ) );
-    assert( two_s_complement_32bit_sum(
-           (unsigned int*)sgilabel, sizeof(*sgilabel) ) == 0 );
-    if( lseek(fd, 0, SEEK_SET) < 0 )
+                                       sizeof(*sgilabel)));
+     assert(two_s_complement_32bit_sum(
+               (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
+     if (lseek(fd, 0, SEEK_SET) < 0)
        fdisk_fatal(unable_to_seek);
-    if( write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE )
+     if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
        fdisk_fatal(unable_to_write);
-    if( ! strncmp( sgilabel->directory[0].vol_file_name, "sgilabel",8 ) )
-    {
+     if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
        /*
-        * keep this habbit of first writing the "sgilabel".
+        * keep this habit of first writing the "sgilabel".
         * I never tested whether it works without (AN 981002).
         */
-       sgiinfo*info = fill_sgiinfo();  /* fills the block appropriately */
-       int infostartblock = SGI_SSWAP32( sgilabel->directory[0].vol_file_start );
-       if( ext2_llseek(fd, (ext2_loff_t)infostartblock*
-           SECTOR_SIZE, SEEK_SET) < 0 )
+        sgiinfo *info = fill_sgiinfo();
+        int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
+        if (fdisk_llseek(fd, (long long)infostartblock*
+                               SECTOR_SIZE, SEEK_SET) < 0)
            fdisk_fatal(unable_to_seek);
-       if( write(fd, info, SECTOR_SIZE) != SECTOR_SIZE )
+        if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
            fdisk_fatal(unable_to_write);
-       free( info );
+        free(info);
     }
 }
 
 static int
-compare_start( int *x, int *y ) {
+compare_start(int *x, int *y) {
     /*
      * sort according to start sectors
      * and prefers largest partition:
      * entry zero is entire disk entry
      */
-    int i = *x;
-    int j = *y;
-    int a = sgi_get_start_sector(i);
-    int b = sgi_get_start_sector(j);
-    int c = sgi_get_num_sectors(i);
-    int d = sgi_get_num_sectors(j);
-    if( a == b )
-    {
-       return( d - c );
-    }
-    return( a - b );
+    unsigned int i = *x;
+    unsigned int j = *y;
+    unsigned int a = sgi_get_start_sector(i);
+    unsigned int b = sgi_get_start_sector(j);
+    unsigned int c = sgi_get_num_sectors(i);
+    unsigned int d = sgi_get_num_sectors(j);
+
+    if (a == b)
+       return (d > c) ? 1 : (d == c) ? 0 : -1;
+    return (a > b) ? 1 : -1;
 }
 
 
 static int
-verify_sgi( int verbose )
+verify_sgi(int verbose)
 {
     int Index[16];      /* list of valid partitions */
     int sortcount = 0;  /* number of used partitions, i.e. non-zero lengths */
-    int entire = 0, i = 0;      /* local counters */
-    int start = 0;
-    int gap = 0;        /* count unused blocks */
-    int lastblock = sgi_get_lastblock();
-    /*
-     */
+    int entire = 0, i = 0;
+    unsigned int start = 0;
+    long long gap = 0;      /* count unused blocks */
+    unsigned int lastblock = sgi_get_lastblock();
+
     clearfreelist();
-    for( i=0; i<16; i++ )
-    {
-       if( sgi_get_num_sectors(i)!=0 )
-       {
+    for (i=0; i<16; i++) {
+       if (sgi_get_num_sectors(i) != 0) {
            Index[sortcount++]=i;
-           if( sgi_get_sysid(i) == ENTIRE_DISK )
-           {
-               if( entire++ == 1 )
-               {
-                   if(verbose)
+           if (sgi_get_sysid(i) == ENTIRE_DISK) {
+               if (entire++ == 1) {
+                   if (verbose)
                        printf(_("More than one entire disk entry present.\n"));
                }
            }
        }
     }
-    if( sortcount == 0 )
-    {
-       if(verbose)
+    if (sortcount == 0) {
+       if (verbose)
            printf(_("No partitions defined\n"));
-       return lastblock;
+              return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
     }
-    qsort( Index, sortcount, sizeof(Index[0]), (void*)compare_start );
-    if( sgi_get_sysid( Index[0] ) == ENTIRE_DISK )
-    {
-       if( ( Index[0] != 10 ) && verbose )
-           printf( _("IRIX likes when Partition 11 covers the entire disk.\n") );
-       if( ( sgi_get_start_sector( Index[0] ) != 0 ) && verbose )
-           printf( _("The entire disk partition should start at block 0,\nnot "
-                   "at diskblock %d.\n"), sgi_get_start_sector(Index[0] ) );
-    if(debug)   /* I do not understand how some disks fulfil it */
-       if( ( sgi_get_num_sectors( Index[0] ) != lastblock ) && verbose )
-           printf( _("The entire disk partition is only %d diskblock large,\n"
+    qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
+    if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
+       if ((Index[0] != 10) && verbose)
+           printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
+           if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
+               printf(_("The entire disk partition should start "
+                               "at block 0,\n"
+                               "not at diskblock %d.\n"),
+                             sgi_get_start_sector(Index[0]));
+               if (debug)      /* I do not understand how some disks fulfil it */
+                      if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
+                              printf(_("The entire disk partition is only %d diskblock large,\n"
                    "but the disk is %d diskblocks long.\n"),
-                   sgi_get_num_sectors( Index[0] ), lastblock );
-       lastblock = sgi_get_num_sectors( Index[0] );
-    } else
-    {
-       if( verbose )
-           printf( _("One Partition (#11) should cover the entire disk.\n") );
-       if(debug>2)
-           printf( "sysid=%d\tpartition=%d\n",
-                       sgi_get_sysid( Index[0] ), Index[0]+1 );
+                                     sgi_get_num_sectors(Index[0]), lastblock);
+               lastblock = sgi_get_num_sectors(Index[0]);
+    } else {
+           if (verbose)
+               printf(_("One Partition (#11) should cover the entire disk.\n"));
+           if (debug>2)
+               printf("sysid=%d\tpartition=%d\n",
+                             sgi_get_sysid(Index[0]), Index[0]+1);
     }
-    for( i=1, start=0; i<sortcount; i++ )
-    {
+    for (i=1, start=0; i<sortcount; i++) {
        int cylsize = sgi_get_nsect() * sgi_get_ntrks();
-       if( (sgi_get_start_sector( Index[i] ) % cylsize) != 0 )
-       {
-       if(debug)       /* I do not understand how some disks fulfil it */
-           if( verbose )
-               printf( _("Partition %d does not start on cylinder boundary.\n"),
-                       Index[i]+1 );
-       }
-       if( sgi_get_num_sectors( Index[i] ) % cylsize != 0 )
-       {
-       if(debug)       /* I do not understand how some disks fulfil it */
-           if( verbose )
-               printf( _("Partition %d does not end on cylinder boundary.\n"),
-                       Index[i]+1 );
+
+           if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
+               if (debug)      /* I do not understand how some disks fulfil it */
+                   if (verbose)
+                       printf(_("Partition %d does not start on cylinder boundary.\n"),
+                                             Index[i]+1);
+           }
+           if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
+               if (debug)      /* I do not understand how some disks fulfil it */
+                   if (verbose)
+                       printf(_("Partition %d does not end on cylinder boundary.\n"),
+                                             Index[i]+1);
        }
        /* We cannot handle several "entire disk" entries. */
-       if( sgi_get_sysid( Index[i] ) == ENTIRE_DISK ) continue;
-       if( start > sgi_get_start_sector( Index[i] ) )
-       {
-           if( verbose )
-               printf( _("The Partition %d and %d overlap by %d sectors.\n"),
+           if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
+           if (start > sgi_get_start_sector(Index[i])) {
+               if (verbose)
+                   printf(_("The Partition %d and %d overlap by %d sectors.\n"),
                        Index[i-1]+1, Index[i]+1,
-                       start - sgi_get_start_sector( Index[i] ) );
-           if( gap >  0 ) gap = -gap;
-           if( gap == 0 ) gap = -1;
-       }
-       if( start < sgi_get_start_sector( Index[i] ) )
-       {
-           if( verbose )
-               printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
-                       sgi_get_start_sector( Index[i] ) - start,
-                       start, sgi_get_start_sector( Index[i] )-1 );
-           gap += sgi_get_start_sector( Index[i] ) - start;
-           add2freelist( start, sgi_get_start_sector( Index[i] ) );
-       }
-       start = sgi_get_start_sector( Index[i] )
-             + sgi_get_num_sectors(  Index[i] );
-       if(debug>1)
-       {
-           if( verbose )
-               printf( "%2d:%12d\t%12d\t%12d\n", Index[i],
+                               start - sgi_get_start_sector(Index[i]));
+               if (gap >  0) gap = -gap;
+               if (gap == 0) gap = -1;
+           }
+           if (start < sgi_get_start_sector(Index[i])) {
+               if (verbose)
+                   printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
+                               sgi_get_start_sector(Index[i]) - start,
+                               start, sgi_get_start_sector(Index[i])-1);
+               gap += sgi_get_start_sector(Index[i]) - start;
+               add2freelist(start, sgi_get_start_sector(Index[i]));
+           }
+           start = sgi_get_start_sector(Index[i])
+                      + sgi_get_num_sectors(Index[i]);
+           if (debug > 1) {
+               if (verbose)
+                   printf("%2d:%12d\t%12d\t%12d\n", Index[i],
                        sgi_get_start_sector(Index[i]),
                        sgi_get_num_sectors(Index[i]),
-                       sgi_get_sysid(Index[i]) );
+                               sgi_get_sysid(Index[i]));
        }
     }
-    if( ( start < lastblock ) )
-    {
-       if( verbose )
-           printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
-                   lastblock - start, start, lastblock-1 );
+    if (start < lastblock) {
+       if (verbose)
+               printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
+                           lastblock - start, start, lastblock-1);
        gap += lastblock - start;
-       add2freelist( start, lastblock );
+       add2freelist(start, lastblock);
     }
     /*
      * Done with arithmetics
      * Go for details now
      */
-    if( verbose )
-    {
-       if( !sgi_get_num_sectors( sgi_get_bootpartition() ) )
-       {
-           printf( _("\nThe boot partition does not exist.\n") );
-       }
-       if( !sgi_get_num_sectors( sgi_get_swappartition() ) )
-       {
-           printf( _("\nThe swap partition does not exist.\n") );
-       } else
-       if( ( sgi_get_sysid( sgi_get_swappartition() ) != SGI_SWAP )
-       &&  ( sgi_get_sysid( sgi_get_swappartition() ) != LINUX_SWAP ) )
-       {
-           printf( _("\nThe swap partition has no swap type.\n") );
+    if (verbose) {
+       if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
+           printf(_("\nThe boot partition does not exist.\n"));
        }
-       if( sgi_check_bootfile( "/unix" ) )
-       {
-           printf( _("\tYou have chosen an unusual boot file name.\n") );
+       if (!sgi_get_num_sectors(sgi_get_swappartition())) {
+           printf(_("\nThe swap partition does not exist.\n"));
+       } else {
+           if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
+                       &&  (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
+               printf(_("\nThe swap partition has no swap type.\n"));
        }
+       if (sgi_check_bootfile("/unix"))
+           printf(_("\tYou have chosen an unusual boot file name.\n"));
     }
-    return gap;
+    return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
 }
 
 static int
@@ -2326,32 +2273,32 @@ sgi_change_sysid( int i, int sys )
 /* returns partition index of first entry marked as entire disk */
 static int
 sgi_entire(void) {
-    int i=0;
-    for( i=0; i<16; i++ )
-       if( sgi_get_sysid(i) == SGI_VOLUME )
+    int i;
+
+    for(i=0; i<16; i++)
+       if(sgi_get_sysid(i) == SGI_VOLUME)
            return i;
     return -1;
 }
 
 static void
-sgi_set_partition( int i, uint start, uint length, int sys ) {
-    sgilabel->partitions[i].id =
-           SGI_SSWAP32( sys );
-    sgilabel->partitions[i].num_sectors =
-           SGI_SSWAP32( length );
-    sgilabel->partitions[i].start_sector =
-           SGI_SSWAP32( start );
+sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
+
+    sgilabel->partitions[i].id = SGI_SSWAP32(sys);
+    sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
+    sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
     set_changed(i);
-    if( sgi_gaps() < 0 )        /* rebuild freelist */
+    if (sgi_gaps() < 0)     /* rebuild freelist */
        printf(_("Do You know, You got a partition overlap on the disk?\n"));
 }
 
 static void
 sgi_set_entire(void) {
     int n;
-    for( n=10; n<partitions; n++ ) {
-       if(!sgi_get_num_sectors( n ) ) {
-           sgi_set_partition( n, 0, sgi_get_lastblock(), SGI_VOLUME );
+
+    for(n=10; n < partitions; n++) {
+       if(!sgi_get_num_sectors(n) ) {
+           sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
            break;
        }
     }
@@ -2388,34 +2335,28 @@ static void
 sgi_add_partition( int n, int sys )
 {
     char mesg[256];
-    int first=0, last=0;
+    unsigned int first=0, last=0;
 
     if( n == 10 ) {
        sys = SGI_VOLUME;
     } else if ( n == 8 ) {
        sys = 0;
     }
-    if( sgi_get_num_sectors(n) )
-    {
+    if(sgi_get_num_sectors(n)) {
        printf(_("Partition %d is already defined.  Delete "
                "it before re-adding it.\n"), n + 1);
        return;
     }
-    if( (sgi_entire() == -1)
-    &&  (sys != SGI_VOLUME) )
-    {
+    if( (sgi_entire() == -1) &&  (sys != SGI_VOLUME) ) {
        printf(_("Attempting to generate entire disk entry automatically.\n"));
        sgi_set_entire();
        sgi_set_volhdr();
     }
-    if( (sgi_gaps() == 0)
-    &&  (sys != SGI_VOLUME) )
-    {
+    if( (sgi_gaps() == 0) &&  (sys != SGI_VOLUME) ) {
        printf(_("The entire disk is already covered with partitions.\n"));
        return;
     }
-    if( sgi_gaps() < 0 )
-    {
+    if(sgi_gaps() < 0) {
        printf(_("You got a partition overlap on the disk. Fix it first!\n"));
        return;
     }
@@ -2459,48 +2400,62 @@ sgi_add_partition( int n, int sys )
     sgi_set_partition( n, first, last-first, sys );
 }
 
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
 static void
 create_sgilabel(void)
 {
     struct hd_geometry geometry;
-    struct { int start;
-            int nsect;
-            int sysid; } old[4];
+    struct {
+       unsigned int start;
+       unsigned int nsect;
+       int sysid;
+    } old[4];
     int i=0;
+    long longsectors;               /* the number of sectors on the device */
+    int res;                        /* the result from the ioctl */
+    int sec_fac;                    /* the sector factor */
+
+    sec_fac = sector_size / 512;    /* determine the sector factor */
+
     fprintf( stderr,
        _("Building a new SGI disklabel. Changes will remain in memory only,\n"
        "until you decide to write them. After that, of course, the previous\n"
        "content will be unrecoverably lost.\n\n"));
 
     sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
-
-#ifdef HDIO_REQ
-    if (!ioctl(fd, HDIO_REQ, &geometry))
-#else
-    if (!ioctl(fd, HDIO_GETGEO, &geometry))
-#endif
-    {
+    res = ioctl(fd, BLKGETSIZE, &longsectors);
+    if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
        heads = geometry.heads;
        sectors = geometry.sectors;
+       if (res == 0) {
+           /* the get device size ioctl was successful */
+           cylinders = longsectors / (heads * sectors);
+           cylinders /= sec_fac;
+       } else {
+           /* otherwise print error and use truncated version */
        cylinders = geometry.cylinders;
+           fprintf(stderr,
+                  _("Warning:  BLKGETSIZE ioctl failed on %s.  "
+                    "Using geometry cylinder value of %d.\n"
+                    "This value may be truncated for devices"
+                    " > 33.8 GB.\n"), disk_device, cylinders);
     }
-    for (i = 0; i < 4; i++)
-    {
+    }
+    for (i = 0; i < 4; i++) {
        old[i].sysid = 0;
-       if( valid_part_table_flag(MBRbuffer) )
-       {
-           if( get_part_table(i)->sys_ind )
-           {
+       if(valid_part_table_flag(MBRbuffer)) {
+           if(get_part_table(i)->sys_ind) {
                old[i].sysid = get_part_table(i)->sys_ind;
-               old[i].start = get_start_sect( get_part_table(i) );
-               old[i].nsect = get_nr_sects( get_part_table(i) );
-               printf( _("Trying to keep parameters of partition %d.\n"), i );
-               if( debug )
-                   printf( _("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
-                           old[i].sysid, old[i].start, old[i].nsect );
+               old[i].start = get_start_sect(get_part_table(i));
+               old[i].nsect = get_nr_sects(get_part_table(i));
+               printf(_("Trying to keep parameters of partition %d.\n"), i);
+               if (debug)
+                   printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
+                       old[i].sysid, old[i].start, old[i].nsect);
            }
        }
     }
+
     memset(MBRbuffer, 0, sizeof(MBRbuffer));
     sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
     sgilabel->boot_part = SGI_SSWAP16(0);
@@ -2543,11 +2498,9 @@ create_sgilabel(void)
     sgi_volumes    = 15;
     sgi_set_entire();
     sgi_set_volhdr();
-    for (i = 0; i < 4; i++)
-    {
-       if( old[i].sysid )
-       {
-           sgi_set_partition( i, old[i].start, old[i].nsect, old[i].sysid );
+    for (i = 0; i < 4; i++) {
+       if(old[i].sysid) {
+           sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
        }
     }
 }
@@ -2557,14 +2510,16 @@ sgi_set_xcyl(void)
 {
     /* do nothing in the beginning */
 }
+#endif /* CONFIG_FEATURE_FDISK_ADVANCED */
 
 /* _____________________________________________________________
  */
 
-static sgiinfo*
+static sgiinfo *
 fill_sgiinfo(void)
 {
-    sgiinfo*info=calloc( 1, sizeof(sgiinfo) );
+    sgiinfo *info = calloc(1, sizeof(sgiinfo));
+
     info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
     info->b1=SGI_SSWAP32(-1);
     info->b2=SGI_SSWAP16(-1);
@@ -2603,6 +2558,7 @@ static int     floppy;
 #ifndef IDE1_MAJOR
 #define IDE1_MAJOR 22
 #endif
+
 static void guess_device_type(void) {
        struct stat bootstat;
 
@@ -2610,12 +2566,12 @@ static void guess_device_type(void) {
                scsi_disk = 0;
                floppy = 0;
        } else if (S_ISBLK(bootstat.st_mode)
-                  && ((bootstat.st_rdev >> 8) == IDE0_MAJOR ||
-                      (bootstat.st_rdev >> 8) == IDE1_MAJOR)) {
+                  && (major(bootstat.st_rdev) == IDE0_MAJOR ||
+                      major(bootstat.st_rdev) == IDE1_MAJOR)) {
                scsi_disk = 0;
                floppy = 0;
        } else if (S_ISBLK(bootstat.st_mode)
-                  && (bootstat.st_rdev >> 8) == FLOPPY_MAJOR) {
+                  && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
                scsi_disk = 0;
                floppy = 1;
        } else {
@@ -2841,11 +2797,7 @@ static void create_sunlabel(void)
            }
        }
        if (!p || floppy) {
-#ifdef HDIO_REQ
-           if (!ioctl(fd, HDIO_REQ, &geometry)) {
-#else
            if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
-#endif
                heads = geometry.heads;
                sectors = geometry.sectors;
                cylinders = geometry.cylinders;
@@ -3151,15 +3103,16 @@ and is of type `Whole disk'\n");
 
 static void
 sun_delete_partition(int i) {
+       unsigned int nsec;
+
        if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
            !sunlabel->partitions[i].start_cylinder &&
-           SUN_SSWAP32(sunlabel->partitions[i].num_sectors)
+           (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
              == heads * sectors * cylinders)
                printf(_("If you want to maintain SunOS/Solaris compatibility, "
                       "consider leaving this\n"
                       "partition as Whole disk (5), starting at 0, with %u "
-                      "sectors\n"),
-                      (uint) SUN_SSWAP32(sunlabel->partitions[i].num_sectors));
+                      "sectors\n"), nsec);
        sunlabel->infos[i].id = 0;
        sunlabel->partitions[i].num_sectors = 0;
 }
@@ -3194,7 +3147,6 @@ sun_change_sysid(int i, int sys) {
 static void
 sun_list_table(int xtra) {
        int i, w;
-       const char *type;
 
        w = strlen(disk_device);
        if (xtra)
@@ -3222,8 +3174,8 @@ sun_list_table(int xtra) {
               w + 1, _("Device"));
        for (i = 0 ; i < partitions; i++) {
                if (sunlabel->partitions[i].num_sectors) {
-                       __u32 start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
-                       __u32 len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
+                       uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
+                       uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
                        printf(
                            "%s %c%c %9ld %9ld %9ld%c  %2x  %s\n",
 /* device */              partname(disk_device, i+1, w),
@@ -3233,12 +3185,13 @@ sun_list_table(int xtra) {
 /* end */                 (long) scround(start+len),
 /* odd flag on end */     (long) len / 2, len & 1 ? '+' : ' ',
 /* type id */             sunlabel->infos[i].id,
-/* type name */           (type = partition_type(sunlabel->infos[i].id))
-                               ? type : _("Unknown"));
+/* type name */           partition_type(sunlabel->infos[i].id));
                }
        }
 }
 
+#ifdef CONFIG_FEATURE_FDISK_ADVANCED
+
 static void
 sun_set_alt_cyl(void) {
        sunlabel->nacyl =
@@ -3278,6 +3231,7 @@ sun_set_pcylcount(void) {
                SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
                                 _("Number of physical cylinders")));
 }
+#endif /* CONFIG_FEATURE_FDISK_ADVANCED */
 
 static void
 sun_write_table(void) {
@@ -3299,52 +3253,27 @@ sun_write_table(void) {
 static const struct systypes i386_sys_types[] = {
        {"\x00" "Empty"},
        {"\x01" "FAT12"},
-       {"\x02" "XENIX root"},
-       {"\x03" "XENIX usr"},
        {"\x04" "FAT16 <32M"},
        {"\x05" "Extended"},         /* DOS 3.3+ extended partition */
        {"\x06" "FAT16"},            /* DOS 16-bit >=32M */
        {"\x07" "HPFS/NTFS"},        /* OS/2 IFS, eg, HPFS or NTFS or QNX */
-       {"\x08" "AIX"},              /* AIX boot (AIX -- PS/2 port) or SplitDrive */
-       {"\x09" "AIX bootable"},     /* AIX data or Coherent */
        {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
        {"\x0b" "Win95 FAT32"},
        {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
        {"\x0e" "Win95 FAT16 (LBA)"},
        {"\x0f" "Win95 Ext'd (LBA)"},
-       {"\x10" "OPUS"},
        {"\x11" "Hidden FAT12"},
        {"\x12" "Compaq diagnostics"},
        {"\x14" "Hidden FAT16 <32M"},
        {"\x16" "Hidden FAT16"},
        {"\x17" "Hidden HPFS/NTFS"},
-       {"\x18" "AST SmartSleep"},
        {"\x1b" "Hidden Win95 FAT32"},
        {"\x1c" "Hidden Win95 FAT32 (LBA)"},
        {"\x1e" "Hidden Win95 FAT16 (LBA)"},
-       {"\x24" "NEC DOS"},
-       {"\x39" "Plan 9"},
        {"\x3c" "PartitionMagic recovery"},
-       {"\x40" "Venix 80286"},
        {"\x41" "PPC PReP Boot"},
        {"\x42" "SFS"},
-       {"\x4d" "QNX4.x"},
-       {"\x4e" "QNX4.x 2nd part"},
-       {"\x4f" "QNX4.x 3rd part"},
-       {"\x50" "OnTrack DM"},
-       {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
-       {"\x52" "CP/M"},             /* CP/M or Microport SysV/AT */
-       {"\x53" "OnTrack DM6 Aux3"},
-       {"\x54" "OnTrackDM6"},
-       {"\x55" "EZ-Drive"},
-       {"\x56" "Golden Bow"},
-       {"\x5c" "Priam Edisk"},
-       {"\x61" "SpeedStor"},
        {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
-       {"\x64" "Novell Netware 286"},
-       {"\x65" "Novell Netware 386"},
-       {"\x70" "DiskSecure Multi-Boot"},
-       {"\x75" "PC/IX"},
        {"\x80" "Old Minix"},        /* Minix 1.4a and earlier */
        {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
        {"\x82" "Linux swap"},       /* also Solaris */
@@ -3354,20 +3283,54 @@ static const struct systypes i386_sys_types[] = {
        {"\x86" "NTFS volume set"},
        {"\x87" "NTFS volume set"},
        {"\x8e" "Linux LVM"},
-       {"\x93" "Amoeba"},
-       {"\x94" "Amoeba BBT"},       /* (bad block table) */
        {"\x9f" "BSD/OS"},           /* BSDI */
        {"\xa0" "IBM Thinkpad hibernation"},
        {"\xa5" "FreeBSD"},          /* various BSD flavours */
        {"\xa6" "OpenBSD"},
-       {"\xa7" "NeXTSTEP"},
        {"\xa8" "Darwin UFS"},
        {"\xa9" "NetBSD"},
        {"\xab" "Darwin boot"},
        {"\xb7" "BSDI fs"},
        {"\xb8" "BSDI swap"},
-       {"\xbb" "Boot Wizard hidden"},
        {"\xbe" "Solaris boot"},
+       {"\xeb" "BeOS fs"},
+       {"\xee" "EFI GPT"},          /* Intel EFI GUID Partition Table */
+       {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
+       {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
+       {"\xf2" "DOS secondary"},    /* DOS 3.3+ secondary */
+       {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
+                                           autodetect using persistent
+                                           superblock */
+#ifdef CONFIG_WEIRD_PARTITION_TYPES
+       {"\x02" "XENIX root"},
+       {"\x03" "XENIX usr"},
+       {"\x08" "AIX"},              /* AIX boot (AIX -- PS/2 port) or SplitDrive */
+       {"\x09" "AIX bootable"},     /* AIX data or Coherent */
+       {"\x10" "OPUS"},
+       {"\x18" "AST SmartSleep"},
+       {"\x24" "NEC DOS"},
+       {"\x39" "Plan 9"},
+       {"\x40" "Venix 80286"},
+       {"\x4d" "QNX4.x"},
+       {"\x4e" "QNX4.x 2nd part"},
+       {"\x4f" "QNX4.x 3rd part"},
+       {"\x50" "OnTrack DM"},
+       {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
+       {"\x52" "CP/M"},             /* CP/M or Microport SysV/AT */
+       {"\x53" "OnTrack DM6 Aux3"},
+       {"\x54" "OnTrackDM6"},
+       {"\x55" "EZ-Drive"},
+       {"\x56" "Golden Bow"},
+       {"\x5c" "Priam Edisk"},
+       {"\x61" "SpeedStor"},
+       {"\x64" "Novell Netware 286"},
+       {"\x65" "Novell Netware 386"},
+       {"\x70" "DiskSecure Multi-Boot"},
+       {"\x75" "PC/IX"},
+       {"\x93" "Amoeba"},
+       {"\x94" "Amoeba BBT"},       /* (bad block table) */
+       {"\xa7" "NeXTSTEP"},
+       {"\xbb" "Boot Wizard hidden"},
        {"\xc1" "DRDOS/sec (FAT-12)"},
        {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
        {"\xc6" "DRDOS/sec (FAT-16)"},
@@ -3382,23 +3345,15 @@ static const struct systypes i386_sys_types[] = {
        {"\xe3" "DOS R/O"},          /* DOS R/O or SpeedStor */
        {"\xe4" "SpeedStor"},        /* SpeedStor 16-bit FAT extended
                                        partition < 1024 cyl. */
-       {"\xeb" "BeOS fs"},
-       {"\xee" "EFI GPT"},          /* Intel EFI GUID Partition Table */
-       {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
-       {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
        {"\xf1" "SpeedStor"},
        {"\xf4" "SpeedStor"},        /* SpeedStor large partition */
-       {"\xf2" "DOS secondary"},    /* DOS 3.3+ secondary */
-       {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
-                                           autodetect using persistent
-                                           superblock */
        {"\xfe" "LANstep"},          /* SpeedStor >1024 cyl. or LANstep */
        {"\xff" "BBT"},              /* Xenix Bad Block Table */
+#endif
        { 0 }
 };
 
 
-static void delete_partition(int i);
 
 /* A valid partition table sector ends in 0x55 0xaa */
 static unsigned int
@@ -3406,11 +3361,8 @@ part_table_flag(const char *b) {
        return ((uint) b[510]) + (((uint) b[511]) << 8);
 }
 
-static int
-valid_part_table_flag(const unsigned char *b) {
-       return (b[510] == 0x55 && b[511] == 0xaa);
-}
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static void
 write_part_table_flag(char *b) {
        b[510] = 0x55;
@@ -3426,6 +3378,7 @@ store4_little_endian(unsigned char *cp, unsigned int val) {
        cp[2] = ((val >> 16) & 0xff);
        cp[3] = ((val >> 24) & 0xff);
 }
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
 
 static unsigned int
 read4_little_endian(const unsigned char *cp) {
@@ -3433,20 +3386,24 @@ read4_little_endian(const unsigned char *cp) {
                + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
 }
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static void
 set_start_sect(struct partition *p, unsigned int start_sect) {
        store4_little_endian(p->start4, start_sect);
 }
+#endif
 
 static unsigned int
 get_start_sect(const struct partition *p) {
        return read4_little_endian(p->start4);
 }
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static void
 set_nr_sects(struct partition *p, unsigned int nr_sects) {
        store4_little_endian(p->size4, nr_sects);
 }
+#endif
 
 static unsigned int
 get_nr_sects(const struct partition *p) {
@@ -3459,9 +3416,12 @@ static int type_open = O_RDWR;
 
 static int ext_index,               /* the prime extended partition */
        listing,                    /* no aborts for fdisk -l */
-       nowarn,                     /* no warnings for fdisk -l/-s */
-       dos_compatible_flag = ~0,
-       dos_changed;
+       dos_compatible_flag = ~0;
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static int dos_changed;
+static int nowarn;            /* no warnings for fdisk -l/-s */
+#endif
+
 
 
 static uint    user_cylinders, user_heads, user_sectors;
@@ -3469,11 +3429,8 @@ static uint    pt_heads, pt_sectors;
 static uint    kern_heads, kern_sectors;
 
 static uint extended_offset;            /* offset of link pointers */
-static uint    sector_size = DEFAULT_SECTOR_SIZE,
-       user_set_sector_size,
-       sector_offset = 1;
 
-static unsigned long total_number_of_sectors;
+static unsigned long long total_number_of_sectors;
 
 
 static jmp_buf listingbuf;
@@ -3513,34 +3470,32 @@ static void fdisk_fatal(enum failure why) {
 
 static void
 seek_sector(uint secno) {
-       ext2_loff_t offset = (ext2_loff_t) secno * sector_size;
-       if (ext2_llseek(fd, offset, SEEK_SET) == (ext2_loff_t) -1)
+       fdisk_loff_t offset = (fdisk_loff_t) secno * sector_size;
+       if (fdisk_llseek(fd, offset, SEEK_SET) == (fdisk_loff_t) -1)
                fdisk_fatal(unable_to_seek);
 }
 
-static void
-read_sector(uint secno, char *buf) {
-       seek_sector(secno);
-       if (read(fd, buf, sector_size) != sector_size)
-               fdisk_fatal(unable_to_read);
-}
-
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static void
 write_sector(uint secno, char *buf) {
        seek_sector(secno);
        if (write(fd, buf, sector_size) != sector_size)
                fdisk_fatal(unable_to_write);
 }
+#endif
 
 /* Allocate a buffer and read a partition table sector */
 static void
-read_pte(int pno, uint offset) {
-       struct pte *pe = &ptes[pno];
+read_pte(struct pte *pe, uint offset) {
 
        pe->offset = offset;
        pe->sectorbuffer = (char *) xmalloc(sector_size);
-       read_sector(offset, pe->sectorbuffer);
+       seek_sector(offset);
+       if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
+               fdisk_fatal(unable_to_read);
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
        pe->changed = 0;
+#endif
        pe->part_table = pe->ext_pointer = NULL;
 }
 
@@ -3549,6 +3504,7 @@ get_partition_start(const struct pte *pe) {
        return pe->offset + get_start_sect(pe->part_table);
 }
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 /*
  * Avoid warning about DOS partitions when no DOS partition was changed.
  * Here a heuristic "is probably dos partition".
@@ -3640,6 +3596,8 @@ menu(void) {
 #endif
        }
 }
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
 
 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
 static void
@@ -3722,19 +3680,7 @@ xmenu(void) {
 }
 #endif /* ADVANCED mode */
 
-
-static int
-get_sysid(int i) {
-       return (
-#ifdef CONFIG_FEATURE_SUN_LABEL
-               sun_label ? sunlabel->infos[i].id :
-#endif
-#ifdef CONFIG_FEATURE_SGI_LABEL
-               sgi_label ? sgi_get_sysid(i) :
-#endif
-               ptes[i].part_table->sys_ind);
-}
-
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static const struct systypes *
 get_sys_types(void) {
        return (
@@ -3746,6 +3692,9 @@ get_sys_types(void) {
 #endif
                i386_sys_types);
 }
+#else
+#define get_sys_types() i386_sys_types
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
 
 static const char *partition_type(unsigned char type)
 {
@@ -3756,7 +3705,21 @@ static const char *partition_type(unsigned char type)
                if (types[i].name[0] == type)
                        return types[i].name + 1;
 
-       return NULL;
+       return _("Unknown");
+}
+
+
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+static int
+get_sysid(int i) {
+       return (
+#ifdef CONFIG_FEATURE_SUN_LABEL
+               sun_label ? sunlabel->infos[i].id :
+#endif
+#ifdef CONFIG_FEATURE_SGI_LABEL
+               sgi_label ? sgi_get_sysid(i) :
+#endif
+               ptes[i].part_table->sys_ind);
 }
 
 void list_types(const struct systypes *sys)
@@ -3773,7 +3736,7 @@ void list_types(const struct systypes *sys)
 
        do {
                printf("%c%2x  %-15.15s", i ? ' ' : '\n',
-                       sys[next].name[0], sys[next].name + 1);
+                       sys[next].name[0], partition_type(sys[next].name[0]));
                next = last[i++] + done;
                if (i > 3 || next >= last[i]) {
                        i = 0;
@@ -3782,6 +3745,7 @@ void list_types(const struct systypes *sys)
        } while (done < last[0]);
        putchar('\n');
 }
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
 
 static int
 is_cleared_partition(const struct partition *p) {
@@ -3794,18 +3758,10 @@ static void
 clear_partition(struct partition *p) {
        if (!p)
                return;
-       p->boot_ind = 0;
-       p->head = 0;
-       p->sector = 0;
-       p->cyl = 0;
-       p->sys_ind = 0;
-       p->end_head = 0;
-       p->end_sector = 0;
-       p->end_cyl = 0;
-       set_start_sect(p,0);
-       set_nr_sects(p,0);
+       memset(p, 0, sizeof(struct partition));
 }
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static void
 set_partition(int i, int doext, uint start, uint stop, int sysid) {
        struct partition *p;
@@ -3830,6 +3786,7 @@ set_partition(int i, int doext, uint start, uint stop, int sysid) {
        set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
        ptes[i].changed = 1;
 }
+#endif
 
 static int
 test_c(const char **m, const char *mesg) {
@@ -3857,9 +3814,13 @@ warn_geometry(void) {
                prev = test_c(&m, _("cylinders"));
        if (!m)
                return 0;
-       fprintf(stderr,
-               _("%s%s.\nYou can do this from the extra functions menu.\n"),
-               prev ? _(" and ") : " ", m);
+
+       fprintf(stderr, "%s%s.\n"
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+                       "You can do this from the extra functions menu.\n"
+#endif
+               , prev ? _(" and ") : " ", m);
+
        return 1;
 }
 
@@ -3873,6 +3834,7 @@ static void update_units(void)
                units_per_sector = 1;   /* in sectors */
 }
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static void
 warn_cylinders(void) {
        if (dos_label && cylinders > 1024 && !nowarn)
@@ -3885,6 +3847,7 @@ warn_cylinders(void) {
 "   (e.g., DOS FDISK, OS/2 FDISK)\n"),
                        cylinders);
 }
+#endif
 
 static void
 read_extended(int ext) {
@@ -3911,16 +3874,17 @@ read_extended(int ext) {
                           this program uses arrays of size MAXIMUM_PARTS.
                           Do not try to `improve' this test. */
                        struct pte *pre = &ptes[partitions-1];
-
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
                        fprintf(stderr,
                                _("Warning: deleting partitions after %d\n"),
                                partitions);
-                       clear_partition(pre->ext_pointer);
                        pre->changed = 1;
+#endif
+                       clear_partition(pre->ext_pointer);
                        return;
                }
 
-               read_pte(partitions, extended_offset + get_start_sect(p));
+               read_pte(pe, extended_offset + get_start_sect(p));
 
                if (!extended_offset)
                        extended_offset = get_start_sect(p);
@@ -3964,6 +3928,7 @@ read_extended(int ext) {
                partitions++;
        }
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
        /* remove empty links */
  remove:
        for (i = 4; i < partitions; i++) {
@@ -3976,8 +3941,10 @@ read_extended(int ext) {
                        goto remove;    /* numbering changed */
                }
        }
+#endif
 }
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static void
 create_doslabel(void) {
        int i;
@@ -4009,7 +3976,7 @@ create_doslabel(void) {
        set_changed(0);
        get_boot(create_empty_dos);
 }
-
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
 
 static void
 get_sectorsize(void) {
@@ -4024,7 +3991,7 @@ get_sectorsize(void) {
        }
 }
 
-static void
+static inline void
 get_kernel_geometry(void) {
        struct hd_geometry geometry;
 
@@ -4037,7 +4004,7 @@ get_kernel_geometry(void) {
 
 static void
 get_partition_table_geometry(void) {
-       unsigned char *bufp = MBRbuffer;
+       const unsigned char *bufp = MBRbuffer;
        struct partition *p;
        int i, h, s, hh, ss;
        int first = 1;
@@ -4068,9 +4035,9 @@ get_partition_table_geometry(void) {
 }
 
 void
-get_geometry(struct geom *g) {
+get_geometry(void) {
        int sec_fac;
-       unsigned long longsectors;
+       unsigned long long bytes;       /* really u64 */
 
        get_sectorsize();
        sec_fac = sector_size / 512;
@@ -4090,26 +4057,25 @@ get_geometry(struct geom *g) {
        sectors = user_sectors ? user_sectors :
                pt_sectors ? pt_sectors :
                kern_sectors ? kern_sectors : 63;
+       if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
+               /* got bytes */
+       } else {
+               unsigned long longsectors;
 
        if (ioctl(fd, BLKGETSIZE, &longsectors))
                longsectors = 0;
+                       bytes = ((unsigned long long) longsectors) << 9;
+       }
+
+       total_number_of_sectors = (bytes >> 9);
 
        sector_offset = 1;
        if (dos_compatible_flag)
                sector_offset = sectors;
 
-       cylinders = longsectors / (heads * sectors);
-       cylinders /= sec_fac;
+       cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
        if (!cylinders)
                cylinders = user_cylinders;
-
-       if (g) {
-               g->heads = heads;
-               g->sectors = sectors;
-               g->cylinders = cylinders;
-       }
-
-       total_number_of_sectors = longsectors;
 }
 
 /*
@@ -4131,14 +4097,19 @@ get_boot(enum action what) {
                pe->ext_pointer = NULL;
                pe->offset = 0;
                pe->sectorbuffer = MBRbuffer;
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
                pe->changed = (what == create_empty_dos);
+#endif
        }
 
+#ifdef CONFIG_FEATURE_SUN_LABEL
        if (what == create_empty_sun && check_sun_label())
                return 0;
+#endif
 
        memset(MBRbuffer, 0, 512);
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
        if (what == create_empty_dos)
                goto got_dos_table;             /* skip reading disk */
 
@@ -4157,13 +4128,21 @@ get_boot(enum action what) {
                        return 1;
                fdisk_fatal(unable_to_read);
        }
+#else
+       if ((fd = open(disk_device, O_RDONLY)) < 0)
+               return 1;
+       if (512 != read(fd, MBRbuffer, 512))
+               return 1;
+#endif
 
-       get_geometry(NULL);
+       get_geometry();
 
        update_units();
 
+#ifdef CONFIG_FEATURE_SUN_LABEL
        if (check_sun_label())
                return 0;
+#endif
 
 #ifdef CONFIG_FEATURE_SGI_LABEL
        if (check_sgi_label())
@@ -4187,9 +4166,14 @@ get_boot(enum action what) {
        }
 #endif
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 got_dos_table:
+#endif
 
        if (!valid_part_table_flag(MBRbuffer)) {
+#ifndef CONFIG_FEATURE_FDISK_WRITABLE
+               return -1;
+#else
                switch(what) {
                case fdisk:
                        fprintf(stderr,
@@ -4204,20 +4188,23 @@ got_dos_table:
                        create_doslabel();
 #endif
                        return 0;
-               case require:
-                       return -1;
                case try_only:
                        return -1;
                case create_empty_dos:
+#ifdef CONFIG_FEATURE_SUN_LABEL
                case create_empty_sun:
+#endif
                        break;
                default:
                        fprintf(stderr, _("Internal error\n"));
                        exit(1);
                }
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
        }
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
        warn_cylinders();
+#endif
        warn_geometry();
 
        for (i = 0; i < 4; i++) {
@@ -4240,13 +4227,16 @@ got_dos_table:
                                _("Warning: invalid flag 0x%04x of partition "
                                "table %d will be corrected by w(rite)\n"),
                                part_table_flag(pe->sectorbuffer), i + 1);
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
                        pe->changed = 1;
+#endif
                }
        }
 
        return 0;
 }
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 /*
  * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
  * If the user hits Enter, DFLT is returned.
@@ -4271,10 +4261,10 @@ read_int(uint low, uint dflt, uint high, uint base, char *mesg)
                default_ok = 0;
 
        if (default_ok)
-               snprintf(ms, mslen, _("%s (%d-%d, default %d): "),
+               snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
                         mesg, low, high, dflt);
        else
-               snprintf(ms, mslen, "%s (%d-%d): ",
+               snprintf(ms, mslen, "%s (%u-%u): ",
                         mesg, low, high);
 
        while (1) {
@@ -4285,41 +4275,52 @@ read_int(uint low, uint dflt, uint high, uint base, char *mesg)
                       && *line_ptr != '-' && *line_ptr != '+')
                        continue;
 
-               if (*line_ptr == '+' || *line_ptr == '-') {
-                       i = atoi(line_ptr+1);
-                       if (*line_ptr == '-')
-                               i = -i;
-                       while (isdigit(*++line_ptr))
-                               use_default = 0;
-                       switch (*line_ptr) {
-                               case 'c':
-                               case 'C':
+               if (*line_ptr == '+' || *line_ptr == '-') {
+                      int minus = (*line_ptr == '-');
+                      int absolute = 0;
+
+                      i = atoi(line_ptr+1);
+
+                      while (isdigit(*++line_ptr))
+                              use_default = 0;
+           
+                      switch (*line_ptr) {
+                              case 'c':
+                              case 'C':
                                        if (!display_in_cyl_units)
                                                i *= heads * sectors;
                                        break;
-                               case 'k':
-                               case 'K':
-                                       i *= 2;
-                                       i /= (sector_size / 512);
-                                       i /= units_per_sector;
-                                       break;
-                               case 'm':
-                               case 'M':
-                                       i *= 2048;
-                                       i /= (sector_size / 512);
-                                       i /= units_per_sector;
-                                       break;
-                               case 'g':
-                               case 'G':
-                                       i *= 2048000;
-                                       i /= (sector_size / 512);
-                                       i /= units_per_sector;
-                                       break;
-                               default:
+                              case 'K':
+                                       absolute = 1024;
                                        break;
+                               case 'k':
+                                      absolute = 1000;
+                                      break;
+                              case 'm':
+                              case 'M':
+                                      absolute = 1000000;
+                                      break;
+                              case 'g':
+                              case 'G':
+                                      absolute = 1000000000;
+                                      break;
+                              default:
+                                      break;
+                      }
+                      if (absolute) {
+                              unsigned long long bytes;
+                              unsigned long unit;
+
+                              bytes = (unsigned long long) i * absolute;
+                              unit = sector_size * units_per_sector;
+                              bytes += unit/2; /* round */
+                              bytes /= unit;
+                              i = bytes;
                        }
-                       i += base;
-               } else {
+                      if (minus)
+                              i = -i;
+                      i += base;
+               } else {
                        i = atoi(line_ptr);
                        while (isdigit(*line_ptr)) {
                                line_ptr++;
@@ -4327,7 +4328,7 @@ read_int(uint low, uint dflt, uint high, uint base, char *mesg)
                        }
                }
                if (use_default)
-                       printf(_("Using default value %d\n"), i = dflt);
+                       printf(_("Using default value %u\n"), i = dflt);
                if (i >= low && i <= high)
                        break;
                else
@@ -4527,11 +4528,21 @@ delete_partition(int i) {
 
 static void
 change_sysid(void) {
-       const char *temp;
        int i, sys, origsys;
        struct partition *p;
 
+#ifdef CONFIG_FEATURE_SGI_LABEL
+       /* If sgi_label then don't use get_existing_partition,
+          let the user select a partition, since get_existing_partition()
+          only works for Linux like partition tables. */
+       if (!sgi_label) {
+       i = get_existing_partition(0, partitions);
+       } else {
+               i = get_partition(0, partitions);
+       }
+#else
        i = get_existing_partition(0, partitions);
+#endif
        if (i == -1)
                return;
        p = ptes[i].part_table;
@@ -4592,8 +4603,7 @@ change_sysid(void) {
                                p->sys_ind = sys;
                        printf (_("Changed system type of partition %d "
                                "to %x (%s)\n"), i + 1, sys,
-                               (temp = partition_type(sys)) ? temp :
-                               _("Unknown"));
+                               partition_type(sys));
                        ptes[i].changed = 1;
                        if (is_dos_partition(origsys) ||
                            is_dos_partition(sys))
@@ -4602,6 +4612,8 @@ change_sysid(void) {
                }
        }
 }
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
+
 
 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
  * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
@@ -4670,7 +4682,7 @@ static void check_consistency(const struct partition *p, int partition) {
 
 /* Ending on cylinder boundary? */
        if (peh != (heads - 1) || pes != sectors) {
-               printf(_("Partition %i does not end on cylinder boundary:\n"),
+               printf(_("Partition %i does not end on cylinder boundary.\n"),
                        partition + 1);
 #if 0
                printf(_("     phys=(%d, %d, %d) "), pec, peh, pes);
@@ -4682,7 +4694,7 @@ static void check_consistency(const struct partition *p, int partition) {
 
 static void
 list_disk_geometry(void) {
-       long long bytes = (long long) total_number_of_sectors * 512;
+       long long bytes = (total_number_of_sectors << 9);
        long megabytes = bytes/1000000;
 
        if (megabytes < 10000)
@@ -4694,10 +4706,9 @@ list_disk_geometry(void) {
        printf(_("%d heads, %d sectors/track, %d cylinders"),
               heads, sectors, cylinders);
        if (units_per_sector == 1)
-               printf(_(", total %lu sectors"),
+               printf(_(", total %llu sectors"),
                       total_number_of_sectors / (sector_size/512));
-       printf("\n");
-       printf(_("Units = %s of %d * %d = %d bytes\n\n"),
+       printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
               str_units(PLURAL),
               units_per_sector, sector_size, units_per_sector * sector_size);
 }
@@ -4801,7 +4812,6 @@ fix_chain_of_logicals(void) {
 }
 
 
-
 static void
 fix_partition_table_order(void) {
        struct pte *pei, *pek;
@@ -4844,7 +4854,6 @@ fix_partition_table_order(void) {
 static void
 list_table(int xtra) {
        const struct partition *p;
-       const char *type;
        int i, w;
 
 #ifdef CONFIG_FEATURE_SUN_LABEL
@@ -4898,17 +4907,16 @@ list_table(int xtra) {
                        if (sector_size > 1024)
                                pblocks *= (sector_size / 1024);
                        printf(
-                           "%s  %c %9ld %9ld %9ld%c  %2x  %s\n",
+                           "%s  %c %11lu %11lu %11lu%c  %2x  %s\n",
                        partname(disk_device, i+1, w+2),
 /* boot flag */         !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
                        ? '*' : '?',
-/* start */             (long) cround(get_partition_start(pe)),
-/* end */               (long) cround(get_partition_start(pe) + psects
+/* start */             (unsigned long) cround(get_partition_start(pe)),
+/* end */               (unsigned long) cround(get_partition_start(pe) + psects
                                - (psects ? 1 : 0)),
-/* odd flag on end */   (long) pblocks, podd ? '+' : ' ',
+/* odd flag on end */   (unsigned long) pblocks, podd ? '+' : ' ',
 /* type id */           p->sys_ind,
-/* type name */         (type = partition_type(p->sys_ind)) ?
-                       type : _("Unknown"));
+/* type name */         partition_type(p->sys_ind));
                        check_consistency(p, i);
                }
        }
@@ -4935,7 +4943,7 @@ x_list_table(int extend) {
                pe = &ptes[i];
                p = (extend ? pe->ext_pointer : pe->part_table);
                if (p != NULL) {
-                       printf("%2d %02x%4d%4d%5d%4d%4d%5d%9d%9d %02x\n",
+                       printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
                                i + 1, p->boot_ind, p->head,
                                sector(p->sector),
                                cylinder(p->sector, p->cyl), p->end_head,
@@ -4949,6 +4957,7 @@ x_list_table(int extend) {
 }
 #endif
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static void
 fill_bounds(uint *first, uint *last) {
        int i;
@@ -5074,6 +5083,7 @@ add_partition(int n, int sys) {
        int i, readed = 0;
        struct partition *p = ptes[n].part_table;
        struct partition *q = ptes[ext_index].part_table;
+       long long llimit;
        uint start, stop = 0, limit, temp,
                first[partitions], last[partitions];
 
@@ -5085,10 +5095,13 @@ add_partition(int n, int sys) {
        fill_bounds(first, last);
        if (n < 4) {
                start = sector_offset;
-               if (display_in_cyl_units)
-                       limit = heads * sectors * cylinders - 1;
+               if (display_in_cyl_units || !total_number_of_sectors)
+                       llimit = heads * sectors * cylinders - 1;
                else
-                       limit = total_number_of_sectors - 1;
+                       llimit = total_number_of_sectors - 1;
+               limit = llimit;
+               if (limit != llimit)
+                       limit = 0x7fffffff;
                if (extended_offset) {
                        first[ext_index] = extended_offset;
                        last[ext_index] = get_start_sect(q) +
@@ -5238,13 +5251,14 @@ new_partition(void) {
        }
 #endif
 
-       if (partitions >= MAXIMUM_PARTS) {
-               printf(_("The maximum number of partitions has been created\n"));
-               return;
-       }
-
        for (i = 0; i < 4; i++)
                free_primary += !ptes[i].part_table->sys_ind;
+
+       if (!free_primary && partitions >= MAXIMUM_PARTS) {
+               printf(_("The maximum number of partitions has been created\n"));
+               return;
+       }
+
        if (!free_primary) {
                if (extended_offset)
                        add_logical();
@@ -5364,6 +5378,7 @@ reread_partition_table(int leave) {
                exit(!!i);
        }
 }
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
 
 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
 #define MAX_PER_LINE    16
@@ -5602,8 +5617,10 @@ try(const char *device, int user_specified) {
                } else {
                        close(fd);
                        list_table(0);
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
                        if (!sun_label && partitions > 4)
                                delete_partition(ext_index);
+#endif
                }
        } else {
                /* Ignore other errors, since we try IDE
@@ -5624,7 +5641,7 @@ tryprocpt(void) {
        char line[100], ptname[100], devname[120], *s;
        int ma, mi, sz;
 
-       procpt = wfopen(PROC_PARTITIONS, "r");
+       procpt = bb_wfopen(PROC_PARTITIONS, "r");
 
        while (fgets(line, sizeof(line), procpt)) {
                if (sscanf (line, " %d %d %d %[^\n ]",
@@ -5633,21 +5650,29 @@ tryprocpt(void) {
                for (s = ptname; *s; s++);
                if (isdigit(s[-1]))
                        continue;
-               snprintf(devname, sizeof(devname), "/dev/%s", ptname);
+               sprintf(devname, "/dev/%s", ptname);
                try(devname, 0);
        }
+#ifdef CONFIG_FEATURE_CLEAN_UP
        fclose(procpt);
+#endif
 }
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
 static void
 unknown_command(int c) {
        printf(_("%c: unknown command\n"), c);
 }
+#endif
 
 int fdisk_main(int argc, char **argv) {
-       int j, c;
-       int optl = 0, opts = 0;
-
+       int c;
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
+       int optl = 0;
+#endif
+#ifdef CONFIG_FEATURE_FDISK_BLKSIZE
+       int opts = 0;
+#endif
        /*
         * Calls:
         *  fdisk -v
@@ -5658,7 +5683,11 @@ int fdisk_main(int argc, char **argv) {
         * Options -C, -H, -S set the geometry.
         *
         */
-       while ((c = getopt(argc, argv, "b:C:H:lsS:uvV")) != -1) {
+       while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
+#ifdef CONFIG_FEATURE_FDISK_BLKSIZE
+                                       "s"
+#endif
+                                               )) != -1) {
                switch (c) {
                case 'b':
                        /* Ugly: this sector size is really per device,
@@ -5668,7 +5697,7 @@ int fdisk_main(int argc, char **argv) {
                        sector_size = atoi(optarg);
                        if (sector_size != 512 && sector_size != 1024 &&
                            sector_size != 2048)
-                               show_usage();
+                               bb_show_usage();
                        sector_offset = 2;
                        user_set_sector_size = 1;
                        break;
@@ -5686,11 +5715,15 @@ int fdisk_main(int argc, char **argv) {
                                user_sectors = 0;
                        break;
                case 'l':
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
                        optl = 1;
+#endif
                        break;
+#ifdef CONFIG_FEATURE_FDISK_BLKSIZE
                case 's':
                        opts = 1;
                        break;
+#endif
                case 'u':
                        display_in_cyl_units = 0;
                        break;
@@ -5699,7 +5732,7 @@ int fdisk_main(int argc, char **argv) {
                        printf("fdisk v" UTIL_LINUX_VERSION "\n");
                        return 0;
                default:
-                       show_usage();
+                       bb_show_usage();
                }
        }
 
@@ -5712,8 +5745,10 @@ int fdisk_main(int argc, char **argv) {
                         " be used with one specified device\n"));
 #endif
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
        if (optl) {
                nowarn = 1;
+#endif
                type_open = O_RDONLY;
                if (argc > optind) {
                        int k;
@@ -5731,17 +5766,21 @@ int fdisk_main(int argc, char **argv) {
                        tryprocpt();
                }
                return 0;
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
        }
+#endif
 
+#ifdef CONFIG_FEATURE_FDISK_BLKSIZE
        if (opts) {
                long size;
+               int j;
 
                nowarn = 1;
                type_open = O_RDONLY;
 
                opts = argc - optind;
                if (opts <= 0)
-                       show_usage();
+                       bb_show_usage();
 
                for (j = optind; j < argc; j++) {
                        disk_device = argv[j];
@@ -5757,11 +5796,13 @@ int fdisk_main(int argc, char **argv) {
                }
                return 0;
        }
+#endif
 
+#ifdef CONFIG_FEATURE_FDISK_WRITABLE
        if (argc-optind == 1)
                disk_device = argv[optind];
        else
-               show_usage();
+               bb_show_usage();
 
        get_boot(fdisk);
 
@@ -5830,9 +5871,24 @@ int fdisk_main(int argc, char **argv) {
                                unknown_command(c);
                        break;
                case 'd':
-                       j = get_existing_partition(1, partitions);
-                       if (j >= 0)
-                               delete_partition(j);
+                       {
+                               int j;
+#ifdef CONFIG_FEATURE_SGI_LABEL
+                       /* If sgi_label then don't use get_existing_partition,
+                          let the user select a partition, since
+                          get_existing_partition() only works for Linux-like
+                          partition tables */
+                               if (!sgi_label) {
+                                       j = get_existing_partition(1, partitions);
+                               } else {
+                                       j = get_partition(1, partitions);
+                               }
+#else
+                               j = get_existing_partition(1, partitions);
+#endif
+                               if (j >= 0)
+                                       delete_partition(j);
+                       }
                        break;
                case 'i':
 #ifdef CONFIG_FEATURE_SGI_LABEL
@@ -5896,4 +5952,5 @@ int fdisk_main(int argc, char **argv) {
                }
        }
        return 0;
+#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
 }