getty: do not emit bogus error message on EOF
[oweals/busybox.git] / util-linux / fdisk.c
index 4416408314ca77d221c0661b09d7274a26515960..8e133178de40e3c87749d04eca140bfaf29c980e 100644 (file)
@@ -9,15 +9,25 @@
 
 #ifndef _LARGEFILE64_SOURCE
 /* For lseek64 */
 
 #ifndef _LARGEFILE64_SOURCE
 /* For lseek64 */
-#define _LARGEFILE64_SOURCE
+# define _LARGEFILE64_SOURCE
 #endif
 #include <assert.h>             /* assert */
 #include <sys/mount.h>
 #if !defined(BLKSSZGET)
 # define BLKSSZGET _IO(0x12, 104)
 #endif
 #endif
 #include <assert.h>             /* assert */
 #include <sys/mount.h>
 #if !defined(BLKSSZGET)
 # define BLKSSZGET _IO(0x12, 104)
 #endif
+#if !defined(BLKGETSIZE64)
+# define BLKGETSIZE64 _IOR(0x12,114,size_t)
+#endif
 #include "libbb.h"
 
 #include "libbb.h"
 
+#if BB_LITTLE_ENDIAN
+# define inline_if_little_endian ALWAYS_INLINE
+#else
+# define inline_if_little_endian /* nothing */
+#endif
+
+
 /* Looks like someone forgot to add this to config system */
 #ifndef ENABLE_FEATURE_FDISK_BLKSIZE
 # define ENABLE_FEATURE_FDISK_BLKSIZE 0
 /* Looks like someone forgot to add this to config system */
 #ifndef ENABLE_FEATURE_FDISK_BLKSIZE
 # define ENABLE_FEATURE_FDISK_BLKSIZE 0
@@ -53,8 +63,18 @@ enum {
 };
 
 
 };
 
 
-/* Used for sector numbers. Today's disk sizes make it necessary */
 typedef unsigned long long ullong;
 typedef unsigned long long ullong;
+/* Used for sector numbers. Partition formats we know
+ * do not support more than 2^32 sectors
+ */
+typedef uint32_t sector_t;
+#if UINT_MAX == 4294967295
+# define SECT_FMT ""
+#elif ULONG_MAX == 4294967295
+# define SECT_FMT "l"
+#else
+# error Cant detect sizeof(uint32_t)
+#endif
 
 struct hd_geometry {
        unsigned char heads;
 
 struct hd_geometry {
        unsigned char heads;
@@ -71,7 +91,7 @@ static const char msg_building_new_label[] ALIGN1 =
 "won't be recoverable.\n\n";
 
 static const char msg_part_already_defined[] ALIGN1 =
 "won't be recoverable.\n\n";
 
 static const char msg_part_already_defined[] ALIGN1 =
-"Partition %d is already defined, delete it before re-adding\n";
+"Partition %u is already defined, delete it before re-adding\n";
 
 
 struct partition {
 
 
 struct partition {
@@ -136,9 +156,9 @@ static void update_units(void);
 static void change_units(void);
 static void reread_partition_table(int leave);
 static void delete_partition(int i);
 static void change_units(void);
 static void reread_partition_table(int leave);
 static void delete_partition(int i);
-static int get_partition(int warn, int max);
+static unsigned get_partition(int warn, unsigned max);
 static void list_types(const char *const *sys);
 static void list_types(const char *const *sys);
-static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
+static sector_t read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg);
 #endif
 static const char *partition_type(unsigned char type);
 static void get_geometry(void);
 #endif
 static const char *partition_type(unsigned char type);
 static void get_geometry(void);
@@ -151,8 +171,8 @@ static int get_boot(void);
 #define PLURAL   0
 #define SINGULAR 1
 
 #define PLURAL   0
 #define SINGULAR 1
 
-static unsigned get_start_sect(const struct partition *p);
-static unsigned get_nr_sects(const struct partition *p);
+static sector_t get_start_sect(const struct partition *p);
+static sector_t get_nr_sects(const struct partition *p);
 
 /*
  * per partition table entry data
 
 /*
  * per partition table entry data
@@ -165,10 +185,10 @@ static unsigned get_nr_sects(const struct partition *p);
 struct pte {
        struct partition *part_table;   /* points into sectorbuffer */
        struct partition *ext_pointer;  /* points into sectorbuffer */
 struct pte {
        struct partition *part_table;   /* points into sectorbuffer */
        struct partition *ext_pointer;  /* points into sectorbuffer */
-       ullong offset;          /* disk sector number */
-       char *sectorbuffer;     /* disk sector contents */
+       sector_t offset_from_dev_start; /* disk sector number */
+       char *sectorbuffer;             /* disk sector contents */
 #if ENABLE_FEATURE_FDISK_WRITABLE
 #if ENABLE_FEATURE_FDISK_WRITABLE
-       char changed;           /* boolean */
+       char changed;                   /* boolean */
 #endif
 };
 
 #endif
 };
 
@@ -308,8 +328,8 @@ struct globals {
        unsigned user_cylinders, user_heads, user_sectors;
        unsigned pt_heads, pt_sectors;
        unsigned kern_heads, kern_sectors;
        unsigned user_cylinders, user_heads, user_sectors;
        unsigned pt_heads, pt_sectors;
        unsigned kern_heads, kern_sectors;
-       ullong extended_offset;         /* offset of link pointers */
-       ullong total_number_of_sectors;
+       sector_t extended_offset;       /* offset of link pointers */
+       sector_t total_number_of_sectors;
 
        jmp_buf listingbuf;
        char line_buffer[80];
 
        jmp_buf listingbuf;
        char line_buffer[80];
@@ -364,18 +384,42 @@ struct globals {
 
 
 /* TODO: move to libbb? */
 
 
 /* TODO: move to libbb? */
-static ullong bb_BLKGETSIZE_sectors(int fd)
+/* TODO: return unsigned long long, FEATURE_FDISK_BLKSIZE _can_ handle
+ * disks > 2^32 sectors
+ */
+static sector_t bb_BLKGETSIZE_sectors(int fd)
 {
        uint64_t v64;
        unsigned long longsectors;
 
        if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
                /* Got bytes, convert to 512 byte sectors */
 {
        uint64_t v64;
        unsigned long longsectors;
 
        if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
                /* Got bytes, convert to 512 byte sectors */
-               return (v64 >> 9);
+               v64 >>= 9;
+               if (v64 != (sector_t)v64) {
+ ret_trunc:
+                       /* Not only DOS, but all other partition tables
+                        * we support can't record more than 32 bit
+                        * sector counts or offsets
+                        */
+                       bb_error_msg("device has more than 2^32 sectors, can't use all of them");
+                       v64 = (uint32_t)-1L;
+               }
+               return v64;
        }
        /* Needs temp of type long */
        }
        /* Needs temp of type long */
-       if (ioctl(fd, BLKGETSIZE, &longsectors))
+       if (ioctl(fd, BLKGETSIZE, &longsectors)) {
+               /* Perhaps this is a disk image */
+               off_t sz = lseek(fd, 0, SEEK_END);
                longsectors = 0;
                longsectors = 0;
+               if (sz > 0)
+                       longsectors = (uoff_t)sz / sector_size;
+               lseek(fd, 0, SEEK_SET);
+       }
+       if (sizeof(long) > sizeof(sector_t)
+        && longsectors != (sector_t)longsectors
+       ) {
+               goto ret_trunc;
+       }
        return longsectors;
 }
 
        return longsectors;
 }
 
@@ -397,16 +441,6 @@ static ullong bb_BLKGETSIZE_sectors(int fd)
 #define hsc2sector(h,s,c) \
        (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
 
 #define hsc2sector(h,s,c) \
        (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
 
-#define set_hsc(h,s,c,sector) \
-       do { \
-               s = sector % g_sectors + 1;  \
-               sector /= g_sectors;         \
-               h = sector % g_heads;        \
-               sector /= g_heads;           \
-               c = sector & 0xff;           \
-               s |= (sector >> 2) & 0xc0;   \
-       } while (0)
-
 static void
 close_dev_fd(void)
 {
 static void
 close_dev_fd(void)
 {
@@ -414,27 +448,6 @@ close_dev_fd(void)
        xmove_fd(xopen(bb_dev_null, O_RDONLY), dev_fd);
 }
 
        xmove_fd(xopen(bb_dev_null, O_RDONLY), dev_fd);
 }
 
-#if ENABLE_FEATURE_FDISK_WRITABLE
-/* Read line; return 0 or first printable char */
-static int
-read_line(const char *prompt)
-{
-       int sz;
-
-       sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
-       if (sz <= 0)
-               exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
-
-       if (line_buffer[sz-1] == '\n')
-               line_buffer[--sz] = '\0';
-
-       line_ptr = line_buffer;
-       while (*line_ptr && !isgraph(*line_ptr))
-               line_ptr++;
-       return *line_ptr;
-}
-#endif
-
 /*
  * Return partition name - uses static storage
  */
 /*
  * Return partition name - uses static storage
  */
@@ -466,30 +479,13 @@ partname(const char *dev, int pno, int lth)
 
        if (lth) {
                snprintf(bufp, bufsiz, "%*.*s%s%-2u",
 
        if (lth) {
                snprintf(bufp, bufsiz, "%*.*s%s%-2u",
-                        lth-wp-2, w, dev, p, pno);
+                       lth-wp-2, w, dev, p, pno);
        } else {
                snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
        }
        return bufp;
 }
 
        } else {
                snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
        }
        return bufp;
 }
 
-#if ENABLE_FEATURE_FDISK_WRITABLE
-static void
-set_all_unchanged(void)
-{
-       int i;
-
-       for (i = 0; i < MAXIMUM_PARTS; i++)
-               ptes[i].changed = 0;
-}
-
-static ALWAYS_INLINE void
-set_changed(int i)
-{
-       ptes[i].changed = 1;
-}
-#endif /* FEATURE_FDISK_WRITABLE */
-
 static ALWAYS_INLINE struct partition *
 get_part_table(int i)
 {
 static ALWAYS_INLINE struct partition *
 get_part_table(int i)
 {
@@ -510,7 +506,67 @@ valid_part_table_flag(const char *mbuffer)
        return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
 }
 
        return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
 }
 
+static void fdisk_fatal(const char *why)
+{
+       if (listing) {
+               close_dev_fd();
+               longjmp(listingbuf, 1);
+       }
+       bb_error_msg_and_die(why, disk_device);
+}
+
+static void
+seek_sector(sector_t secno)
+{
+#if ENABLE_FDISK_SUPPORT_LARGE_DISKS
+       off64_t off = (off64_t)secno * sector_size;
+       if (lseek64(dev_fd, off, SEEK_SET) == (off64_t) -1)
+               fdisk_fatal(unable_to_seek);
+#else
+       uint64_t off = (uint64_t)secno * sector_size;
+       if (off > MAXINT(off_t)
+        || lseek(dev_fd, (off_t)off, SEEK_SET) == (off_t) -1
+       ) {
+               fdisk_fatal(unable_to_seek);
+       }
+#endif
+}
+
 #if ENABLE_FEATURE_FDISK_WRITABLE
 #if ENABLE_FEATURE_FDISK_WRITABLE
+/* Read line; return 0 or first printable char */
+static int
+read_line(const char *prompt)
+{
+       int sz;
+
+       sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
+       if (sz <= 0)
+               exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
+
+       if (line_buffer[sz-1] == '\n')
+               line_buffer[--sz] = '\0';
+
+       line_ptr = line_buffer;
+       while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ')
+               line_ptr++;
+       return *line_ptr;
+}
+
+static void
+set_all_unchanged(void)
+{
+       int i;
+
+       for (i = 0; i < MAXIMUM_PARTS; i++)
+               ptes[i].changed = 0;
+}
+
+static ALWAYS_INLINE void
+set_changed(int i)
+{
+       ptes[i].changed = 1;
+}
+
 static ALWAYS_INLINE void
 write_part_table_flag(char *b)
 {
 static ALWAYS_INLINE void
 write_part_table_flag(char *b)
 {
@@ -543,57 +599,28 @@ read_hex(const char *const *sys)
        unsigned long v;
        while (1) {
                read_nonempty("Hex code (type L to list codes): ");
        unsigned long v;
        while (1) {
                read_nonempty("Hex code (type L to list codes): ");
-               if (*line_ptr == 'l' || *line_ptr == 'L') {
+               if ((line_ptr[0] | 0x20) == 'l') {
                        list_types(sys);
                        continue;
                }
                v = bb_strtoul(line_ptr, NULL, 16);
                        list_types(sys);
                        continue;
                }
                v = bb_strtoul(line_ptr, NULL, 16);
-               if (v > 0xff)
-                       /* Bad input also triggers this */
-                       continue;
-               return v;
-       }
-}
-#endif /* FEATURE_FDISK_WRITABLE */
-
-static void fdisk_fatal(const char *why)
-{
-       if (listing) {
-               close_dev_fd();
-               longjmp(listingbuf, 1);
-       }
-       bb_error_msg_and_die(why, disk_device);
-}
-
-static void
-seek_sector(ullong secno)
-{
-       secno *= sector_size;
-#if ENABLE_FDISK_SUPPORT_LARGE_DISKS
-       if (lseek64(dev_fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
-               fdisk_fatal(unable_to_seek);
-#else
-       if (secno > MAXINT(off_t)
-        || lseek(dev_fd, (off_t)secno, SEEK_SET) == (off_t) -1
-       ) {
-               fdisk_fatal(unable_to_seek);
+               if (v <= 0xff)
+                       return v;
        }
        }
-#endif
 }
 
 }
 
-#if ENABLE_FEATURE_FDISK_WRITABLE
 static void
 static void
-write_sector(ullong secno, const void *buf)
+write_sector(sector_t secno, const void *buf)
 {
        seek_sector(secno);
        xwrite(dev_fd, buf, sector_size);
 }
 {
        seek_sector(secno);
        xwrite(dev_fd, buf, sector_size);
 }
-#endif
+#endif /* FEATURE_FDISK_WRITABLE */
 
 
 #include "fdisk_aix.c"
 
 
 
 #include "fdisk_aix.c"
 
-typedef struct {
+struct sun_partition {
        unsigned char info[128];   /* Informative text string */
        unsigned char spare0[14];
        struct sun_info {
        unsigned char info[128];   /* Informative text string */
        unsigned char spare0[14];
        struct sun_info {
@@ -619,7 +646,8 @@ typedef struct {
        } partitions[8];
        unsigned short magic;      /* Magic number */
        unsigned short csum;       /* Label xor'd checksum */
        } partitions[8];
        unsigned short magic;      /* Magic number */
        unsigned short csum;       /* Label xor'd checksum */
-} sun_partition;
+} FIX_ALIASING;
+typedef struct sun_partition sun_partition;
 #define sunlabel ((sun_partition *)MBRbuffer)
 STATIC_OSF void bsd_select(void);
 STATIC_OSF void xbsd_print_disklabel(int);
 #define sunlabel ((sun_partition *)MBRbuffer)
 STATIC_OSF void bsd_select(void);
 STATIC_OSF void xbsd_print_disklabel(int);
@@ -680,40 +708,42 @@ STATIC_SUN void sun_write_table(void);
 #include "fdisk_sun.c"
 
 
 #include "fdisk_sun.c"
 
 
-#if ENABLE_FEATURE_FDISK_WRITABLE
-/* start_sect and nr_sects are stored little endian on all machines */
-/* moreover, they are not aligned correctly */
-static void
-store4_little_endian(unsigned char *cp, unsigned val)
+static inline_if_little_endian unsigned
+read4_little_endian(const unsigned char *cp)
 {
 {
-       cp[0] = val;
-       cp[1] = val >> 8;
-       cp[2] = val >> 16;
-       cp[3] = val >> 24;
+       uint32_t v;
+       move_from_unaligned32(v, cp);
+       return SWAP_LE32(v);
 }
 }
-#endif /* FEATURE_FDISK_WRITABLE */
 
 
-static unsigned
-read4_little_endian(const unsigned char *cp)
+static sector_t
+get_start_sect(const struct partition *p)
+{
+       return read4_little_endian(p->start4);
+}
+
+static sector_t
+get_nr_sects(const struct partition *p)
 {
 {
-       return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
+       return read4_little_endian(p->size4);
 }
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
 }
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
-static void
-set_start_sect(struct partition *p, unsigned start_sect)
+/* start_sect and nr_sects are stored little endian on all machines */
+/* moreover, they are not aligned correctly */
+static inline_if_little_endian void
+store4_little_endian(unsigned char *cp, unsigned val)
 {
 {
-       store4_little_endian(p->start4, start_sect);
+       uint32_t v = SWAP_LE32(val);
+       move_to_unaligned32(cp, v);
 }
 }
-#endif
 
 
-static unsigned
-get_start_sect(const struct partition *p)
+static void
+set_start_sect(struct partition *p, unsigned start_sect)
 {
 {
-       return read4_little_endian(p->start4);
+       store4_little_endian(p->start4, start_sect);
 }
 
 }
 
-#if ENABLE_FEATURE_FDISK_WRITABLE
 static void
 set_nr_sects(struct partition *p, unsigned nr_sects)
 {
 static void
 set_nr_sects(struct partition *p, unsigned nr_sects)
 {
@@ -721,17 +751,11 @@ set_nr_sects(struct partition *p, unsigned nr_sects)
 }
 #endif
 
 }
 #endif
 
-static unsigned
-get_nr_sects(const struct partition *p)
-{
-       return read4_little_endian(p->size4);
-}
-
 /* Allocate a buffer and read a partition table sector */
 static void
 /* Allocate a buffer and read a partition table sector */
 static void
-read_pte(struct pte *pe, ullong offset)
+read_pte(struct pte *pe, sector_t offset)
 {
 {
-       pe->offset = offset;
+       pe->offset_from_dev_start = offset;
        pe->sectorbuffer = xzalloc(sector_size);
        seek_sector(offset);
        /* xread would make us abort - bad for fdisk -l */
        pe->sectorbuffer = xzalloc(sector_size);
        seek_sector(offset);
        /* xread would make us abort - bad for fdisk -l */
@@ -743,10 +767,10 @@ read_pte(struct pte *pe, ullong offset)
        pe->part_table = pe->ext_pointer = NULL;
 }
 
        pe->part_table = pe->ext_pointer = NULL;
 }
 
-static unsigned
-get_partition_start(const struct pte *pe)
+static sector_t
+get_partition_start_from_dev_start(const struct pte *pe)
 {
 {
-       return pe->offset + get_start_sect(pe->part_table);
+       return pe->offset_from_dev_start + get_start_sect(pe->part_table);
 }
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
 }
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
@@ -909,7 +933,7 @@ get_sys_types(void)
 }
 #else
 #define get_sys_types() i386_sys_types
 }
 #else
 #define get_sys_types() i386_sys_types
-#endif /* FEATURE_FDISK_WRITABLE */
+#endif
 
 static const char *
 partition_type(unsigned char type)
 
 static const char *
 partition_type(unsigned char type)
@@ -924,6 +948,24 @@ partition_type(unsigned char type)
        return "Unknown";
 }
 
        return "Unknown";
 }
 
+static int
+is_cleared_partition(const struct partition *p)
+{
+       /* We consider partition "cleared" only if it has only zeros */
+       const char *cp = (const char *)p;
+       int cnt = sizeof(*p);
+       char bits = 0;
+       while (--cnt >= 0)
+               bits |= *cp++;
+       return (bits == 0);
+}
+
+static void
+clear_partition(struct partition *p)
+{
+       if (p)
+               memset(p, 0, sizeof(*p));
+}
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
 static int
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
 static int
@@ -965,48 +1007,46 @@ list_types(const char *const *sys)
        } while (done < last[0]);
        bb_putchar('\n');
 }
        } while (done < last[0]);
        bb_putchar('\n');
 }
-#endif /* FEATURE_FDISK_WRITABLE */
 
 
-static int
-is_cleared_partition(const struct partition *p)
-{
-       return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
-                p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
-                get_start_sect(p) || get_nr_sects(p));
-}
+#define set_hsc(h, s, c, sector) do \
+{ \
+       s = sector % g_sectors + 1;  \
+       sector /= g_sectors;         \
+       h = sector % g_heads;        \
+       sector /= g_heads;           \
+       c = sector & 0xff;           \
+       s |= (sector >> 2) & 0xc0;   \
+} while (0)
 
 
-static void
-clear_partition(struct partition *p)
+static void set_hsc_start_end(struct partition *p, sector_t start, sector_t stop)
 {
 {
-       if (!p)
-               return;
-       memset(p, 0, sizeof(struct partition));
+       if (dos_compatible_flag && (start / (g_sectors * g_heads) > 1023))
+               start = g_heads * g_sectors * 1024 - 1;
+       set_hsc(p->head, p->sector, p->cyl, start);
+
+       if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
+               stop = g_heads * g_sectors * 1024 - 1;
+       set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
 }
 
 }
 
-#if ENABLE_FEATURE_FDISK_WRITABLE
 static void
 static void
-set_partition(int i, int doext, ullong start, ullong stop, int sysid)
+set_partition(int i, int doext, sector_t start, sector_t stop, int sysid)
 {
        struct partition *p;
 {
        struct partition *p;
-       ullong offset;
+       sector_t offset;
 
        if (doext) {
                p = ptes[i].ext_pointer;
                offset = extended_offset;
        } else {
                p = ptes[i].part_table;
 
        if (doext) {
                p = ptes[i].ext_pointer;
                offset = extended_offset;
        } else {
                p = ptes[i].part_table;
-               offset = ptes[i].offset;
+               offset = ptes[i].offset_from_dev_start;
        }
        p->boot_ind = 0;
        p->sys_ind = sysid;
        set_start_sect(p, start - offset);
        set_nr_sects(p, stop - start + 1);
        }
        p->boot_ind = 0;
        p->sys_ind = sysid;
        set_start_sect(p, start - offset);
        set_nr_sects(p, stop - start + 1);
-       if (dos_compatible_flag && (start / (g_sectors * g_heads) > 1023))
-               start = g_heads * g_sectors * 1024 - 1;
-       set_hsc(p->head, p->sector, p->cyl, start);
-       if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
-               stop = g_heads * g_sectors * 1024 - 1;
-       set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
+       set_hsc_start_end(p, start, stop);
        ptes[i].changed = 1;
 }
 #endif
        ptes[i].changed = 1;
 }
 #endif
@@ -1049,7 +1089,7 @@ warn_cylinders(void)
 {
        if (LABEL_IS_DOS && g_cylinders > 1024 && !nowarn)
                printf("\n"
 {
        if (LABEL_IS_DOS && g_cylinders > 1024 && !nowarn)
                printf("\n"
-"The number of cylinders for this disk is set to %d.\n"
+"The number of cylinders for this disk is set to %u.\n"
 "There is nothing wrong with that, but this is larger than 1024,\n"
 "and could in certain setups cause problems with:\n"
 "1) software that runs at boot time (e.g., old versions of LILO)\n"
 "There is nothing wrong with that, but this is larger than 1024,\n"
 "and could in certain setups cause problems with:\n"
 "1) software that runs at boot time (e.g., old versions of LILO)\n"
@@ -1085,7 +1125,7 @@ read_extended(int ext)
                           Do not try to 'improve' this test. */
                        struct pte *pre = &ptes[g_partitions - 1];
 #if ENABLE_FEATURE_FDISK_WRITABLE
                           Do not try to 'improve' this test. */
                        struct pte *pre = &ptes[g_partitions - 1];
 #if ENABLE_FEATURE_FDISK_WRITABLE
-                       printf("Warning: deleting partitions after %d\n",
+                       printf("Warning: deleting partitions after %u\n",
                                g_partitions);
                        pre->changed = 1;
 #endif
                                g_partitions);
                        pre->changed = 1;
 #endif
@@ -1104,14 +1144,14 @@ read_extended(int ext)
                                if (pe->ext_pointer)
                                        printf("Warning: extra link "
                                                "pointer in partition table"
                                if (pe->ext_pointer)
                                        printf("Warning: extra link "
                                                "pointer in partition table"
-                                               " %d\n", g_partitions + 1);
+                                               " %u\n", g_partitions + 1);
                                else
                                        pe->ext_pointer = p;
                        } else if (p->sys_ind) {
                                if (pe->part_table)
                                        printf("Warning: ignoring extra "
                                                  "data in partition table"
                                else
                                        pe->ext_pointer = p;
                        } else if (p->sys_ind) {
                                if (pe->part_table)
                                        printf("Warning: ignoring extra "
                                                  "data in partition table"
-                                                 " %d\n", g_partitions + 1);
+                                                 " %u\n", g_partitions + 1);
                                else
                                        pe->part_table = p;
                        }
                                else
                                        pe->part_table = p;
                        }
@@ -1144,7 +1184,7 @@ read_extended(int ext)
                if (!get_nr_sects(pe->part_table)
                 && (g_partitions > 5 || ptes[4].part_table->sys_ind)
                ) {
                if (!get_nr_sects(pe->part_table)
                 && (g_partitions > 5 || ptes[4].part_table->sys_ind)
                ) {
-                       printf("Omitting empty partition (%d)\n", i+1);
+                       printf("Omitting empty partition (%u)\n", i+1);
                        delete_partition(i);
                        goto remove;    /* numbering changed */
                }
                        delete_partition(i);
                        goto remove;    /* numbering changed */
                }
@@ -1156,26 +1196,22 @@ read_extended(int ext)
 static void
 create_doslabel(void)
 {
 static void
 create_doslabel(void)
 {
-       int i;
-
        printf(msg_building_new_label, "DOS disklabel");
 
        current_label_type = LABEL_DOS;
        printf(msg_building_new_label, "DOS disklabel");
 
        current_label_type = LABEL_DOS;
-
 #if ENABLE_FEATURE_OSF_LABEL
        possibly_osf_label = 0;
 #endif
        g_partitions = 4;
 
 #if ENABLE_FEATURE_OSF_LABEL
        possibly_osf_label = 0;
 #endif
        g_partitions = 4;
 
-       for (i = 510-64; i < 510; i++)
-               MBRbuffer[i] = 0;
+       memset(&MBRbuffer[510 - 4*16], 0, 4*16);
        write_part_table_flag(MBRbuffer);
        extended_offset = 0;
        set_all_unchanged();
        set_changed(0);
        get_boot(CREATE_EMPTY_DOS);
 }
        write_part_table_flag(MBRbuffer);
        extended_offset = 0;
        set_all_unchanged();
        set_changed(0);
        get_boot(CREATE_EMPTY_DOS);
 }
-#endif /* FEATURE_FDISK_WRITABLE */
+#endif
 
 static void
 get_sectorsize(void)
 
 static void
 get_sectorsize(void)
@@ -1185,7 +1221,7 @@ get_sectorsize(void)
                if (ioctl(dev_fd, BLKSSZGET, &arg) == 0)
                        sector_size = arg;
                if (sector_size != DEFAULT_SECTOR_SIZE)
                if (ioctl(dev_fd, BLKSSZGET, &arg) == 0)
                        sector_size = arg;
                if (sector_size != DEFAULT_SECTOR_SIZE)
-                       printf("Note: sector size is %d "
+                       printf("Note: sector size is %u "
                                "(not " DEFAULT_SECTOR_SIZE_STR ")\n",
                                sector_size);
        }
                                "(not " DEFAULT_SECTOR_SIZE_STR ")\n",
                                sector_size);
        }
@@ -1292,7 +1328,7 @@ static int get_boot(void)
                struct pte *pe = &ptes[i];
                pe->part_table = pt_offset(MBRbuffer, i);
                pe->ext_pointer = NULL;
                struct pte *pe = &ptes[i];
                pe->part_table = pt_offset(MBRbuffer, i);
                pe->ext_pointer = NULL;
-               pe->offset = 0;
+               pe->offset_from_dev_start = 0;
                pe->sectorbuffer = MBRbuffer;
 #if ENABLE_FEATURE_FDISK_WRITABLE
                pe->changed = (what == CREATE_EMPTY_DOS);
                pe->sectorbuffer = MBRbuffer;
 #if ENABLE_FEATURE_FDISK_WRITABLE
                pe->changed = (what == CREATE_EMPTY_DOS);
@@ -1396,7 +1432,7 @@ static int get_boot(void)
                if (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
                        if (g_partitions != 4)
                                printf("Ignoring extra extended "
                if (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
                        if (g_partitions != 4)
                                printf("Ignoring extra extended "
-                                       "partition %d\n", i + 1);
+                                       "partition %u\n", i + 1);
                        else
                                read_extended(i);
                }
                        else
                                read_extended(i);
                }
@@ -1406,7 +1442,7 @@ static int get_boot(void)
                struct pte *pe = &ptes[i];
                if (!valid_part_table_flag(pe->sectorbuffer)) {
                        printf("Warning: invalid flag 0x%02x,0x%02x of partition "
                struct pte *pe = &ptes[i];
                if (!valid_part_table_flag(pe->sectorbuffer)) {
                        printf("Warning: invalid flag 0x%02x,0x%02x of partition "
-                               "table %d will be corrected by w(rite)\n",
+                               "table %u will be corrected by w(rite)\n",
                                pe->sectorbuffer[510],
                                pe->sectorbuffer[511],
                                i + 1);
                                pe->sectorbuffer[510],
                                pe->sectorbuffer[511],
                                i + 1);
@@ -1425,10 +1461,10 @@ static int get_boot(void)
  *
  * There is no default if DFLT is not between LOW and HIGH.
  */
  *
  * There is no default if DFLT is not between LOW and HIGH.
  */
-static unsigned
-read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
+static sector_t
+read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg)
 {
 {
-       unsigned i;
+       sector_t value;
        int default_ok = 1;
        const char *fmt = "%s (%u-%u, default %u): ";
 
        int default_ok = 1;
        const char *fmt = "%s (%u-%u, default %u): ";
 
@@ -1451,8 +1487,10 @@ read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *
                        int minus = (*line_ptr == '-');
                        int absolute = 0;
 
                        int minus = (*line_ptr == '-');
                        int absolute = 0;
 
-                       i = atoi(line_ptr + 1);
+                       value = atoi(line_ptr + 1);
 
 
+                       /* (1) if 2nd char is digit, use_default = 0.
+                        * (2) move line_ptr to first non-digit. */
                        while (isdigit(*++line_ptr))
                                use_default = 0;
 
                        while (isdigit(*++line_ptr))
                                use_default = 0;
 
@@ -1460,7 +1498,7 @@ read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *
                        case 'c':
                        case 'C':
                                if (!display_in_cyl_units)
                        case 'c':
                        case 'C':
                                if (!display_in_cyl_units)
-                                       i *= g_heads * g_sectors;
+                                       value *= g_heads * g_sectors;
                                break;
                        case 'K':
                                absolute = 1024;
                                break;
                        case 'K':
                                absolute = 1024;
@@ -1483,38 +1521,38 @@ read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *
                                ullong bytes;
                                unsigned long unit;
 
                                ullong bytes;
                                unsigned long unit;
 
-                               bytes = (ullong) i * absolute;
+                               bytes = (ullong) value * absolute;
                                unit = sector_size * units_per_sector;
                                bytes += unit/2; /* round */
                                bytes /= unit;
                                unit = sector_size * units_per_sector;
                                bytes += unit/2; /* round */
                                bytes /= unit;
-                               i = bytes;
+                               value = bytes;
                        }
                        if (minus)
                        }
                        if (minus)
-                               i = -i;
-                       i += base;
+                               value = -value;
+                       value += base;
                } else {
                } else {
-                       i = atoi(line_ptr);
+                       value = atoi(line_ptr);
                        while (isdigit(*line_ptr)) {
                                line_ptr++;
                                use_default = 0;
                        }
                }
                if (use_default) {
                        while (isdigit(*line_ptr)) {
                                line_ptr++;
                                use_default = 0;
                        }
                }
                if (use_default) {
-                       i = dflt;
-                       printf("Using default value %u\n", i);
+                       value = dflt;
+                       printf("Using default value %u\n", value);
                }
                }
-               if (i >= low && i <= high)
+               if (value >= low && value <= high)
                        break;
                printf("Value is out of range\n");
        }
                        break;
                printf("Value is out of range\n");
        }
-       return i;
+       return value;
 }
 
 }
 
-static int
-get_partition(int warn, int max)
+static unsigned
+get_partition(int warn, unsigned max)
 {
        struct pte *pe;
 {
        struct pte *pe;
-       int i;
+       unsigned i;
 
        i = read_int(1, 0, max, 0, "Partition number") - 1;
        pe = &ptes[i];
 
        i = read_int(1, 0, max, 0, "Partition number") - 1;
        pe = &ptes[i];
@@ -1524,17 +1562,17 @@ get_partition(int warn, int max)
                 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
                 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
                ) {
                 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
                 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
                ) {
-                       printf("Warning: partition %d has empty type\n", i+1);
+                       printf("Warning: partition %u has empty type\n", i+1);
                }
        }
        return i;
 }
 
 static int
                }
        }
        return i;
 }
 
 static int
-get_existing_partition(int warn, int max)
+get_existing_partition(int warn, unsigned max)
 {
        int pno = -1;
 {
        int pno = -1;
-       int i;
+       unsigned i;
 
        for (i = 0; i < max; i++) {
                struct pte *pe = &ptes[i];
 
        for (i = 0; i < max; i++) {
                struct pte *pe = &ptes[i];
@@ -1547,7 +1585,7 @@ get_existing_partition(int warn, int max)
                }
        }
        if (pno >= 0) {
                }
        }
        if (pno >= 0) {
-               printf("Selected partition %d\n", pno+1);
+               printf("Selected partition %u\n", pno+1);
                return pno;
        }
        printf("No partition is defined yet!\n");
                return pno;
        }
        printf("No partition is defined yet!\n");
@@ -1558,10 +1596,10 @@ get_existing_partition(int warn, int max)
 }
 
 static int
 }
 
 static int
-get_nonexisting_partition(int warn, int max)
+get_nonexisting_partition(int warn, unsigned max)
 {
        int pno = -1;
 {
        int pno = -1;
-       int i;
+       unsigned i;
 
        for (i = 0; i < max; i++) {
                struct pte *pe = &ptes[i];
 
        for (i = 0; i < max; i++) {
                struct pte *pe = &ptes[i];
@@ -1574,7 +1612,7 @@ get_nonexisting_partition(int warn, int max)
                }
        }
        if (pno >= 0) {
                }
        }
        if (pno >= 0) {
-               printf("Selected partition %d\n", pno+1);
+               printf("Selected partition %u\n", pno+1);
                return pno;
        }
        printf("All primary partitions have been defined already!\n");
                return pno;
        }
        printf("All primary partitions have been defined already!\n");
@@ -1601,7 +1639,7 @@ toggle_active(int i)
        struct partition *p = pe->part_table;
 
        if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
        struct partition *p = pe->part_table;
 
        if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
-               printf("WARNING: Partition %d is an extended partition\n", i + 1);
+               printf("WARNING: Partition %u is an extended partition\n", i + 1);
        p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
        pe->changed = 1;
 }
        p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
        pe->changed = 1;
 }
@@ -1674,9 +1712,9 @@ delete_partition(int i)
 
                        if (pe->part_table) /* prevent SEGFAULT */
                                set_start_sect(pe->part_table,
 
                        if (pe->part_table) /* prevent SEGFAULT */
                                set_start_sect(pe->part_table,
-                                                  get_partition_start(pe) -
-                                                  extended_offset);
-                       pe->offset = extended_offset;
+                                               get_partition_start_from_dev_start(pe) -
+                                               extended_offset);
+                       pe->offset_from_dev_start = extended_offset;
                        pe->changed = 1;
                }
 
                        pe->changed = 1;
                }
 
@@ -1686,9 +1724,10 @@ delete_partition(int i)
                                ptes[i] = ptes[i+1];
                                i++;
                        }
                                ptes[i] = ptes[i+1];
                                i++;
                        }
-               } else
+               } else {
                        /* the only logical: clear only */
                        clear_partition(ptes[i].part_table);
                        /* the only logical: clear only */
                        clear_partition(ptes[i].part_table);
+               }
        }
 }
 
        }
 }
 
@@ -1714,7 +1753,7 @@ change_sysid(void)
        /* if changing types T to 0 is allowed, then
           the reverse change must be allowed, too */
        if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
        /* if changing types T to 0 is allowed, then
           the reverse change must be allowed, too */
        if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
-               printf("Partition %d does not exist yet!\n", i + 1);
+               printf("Partition %u does not exist yet!\n", i + 1);
                return;
        }
        while (1) {
                return;
        }
        while (1) {
@@ -1765,7 +1804,7 @@ change_sysid(void)
                        } else
                                p->sys_ind = sys;
 
                        } else
                                p->sys_ind = sys;
 
-                       printf("Changed system type of partition %d "
+                       printf("Changed system type of partition %u "
                                "to %x (%s)\n", i + 1, sys,
                                partition_type(sys));
                        ptes[i].changed = 1;
                                "to %x (%s)\n", i + 1, sys,
                                partition_type(sys));
                        ptes[i].changed = 1;
@@ -1823,23 +1862,23 @@ check_consistency(const struct partition *p, int partition)
 
 /* Same physical / logical beginning? */
        if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
 
 /* Same physical / logical beginning? */
        if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
-               printf("Partition %d has different physical/logical "
+               printf("Partition %u has different physical/logical "
                        "beginnings (non-Linux?):\n", partition + 1);
                        "beginnings (non-Linux?):\n", partition + 1);
-               printf("     phys=(%d, %d, %d) ", pbc, pbh, pbs);
-               printf("logical=(%d, %d, %d)\n", lbc, lbh, lbs);
+               printf("     phys=(%u, %u, %u) ", pbc, pbh, pbs);
+               printf("logical=(%u, %u, %u)\n", lbc, lbh, lbs);
        }
 
 /* Same physical / logical ending? */
        if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
        }
 
 /* Same physical / logical ending? */
        if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
-               printf("Partition %d has different physical/logical "
+               printf("Partition %u has different physical/logical "
                        "endings:\n", partition + 1);
                        "endings:\n", partition + 1);
-               printf("     phys=(%d, %d, %d) ", pec, peh, pes);
-               printf("logical=(%d, %d, %d)\n", lec, leh, les);
+               printf("     phys=(%u, %u, %u) ", pec, peh, pes);
+               printf("logical=(%u, %u, %u)\n", lec, leh, les);
        }
 
 /* Ending on cylinder boundary? */
        if (peh != (g_heads - 1) || pes != g_sectors) {
        }
 
 /* Ending on cylinder boundary? */
        if (peh != (g_heads - 1) || pes != g_sectors) {
-               printf("Partition %i does not end on cylinder boundary\n",
+               printf("Partition %u does not end on cylinder boundary\n",
                        partition + 1);
        }
 }
                        partition + 1);
        }
 }
@@ -1847,23 +1886,23 @@ check_consistency(const struct partition *p, int partition)
 static void
 list_disk_geometry(void)
 {
 static void
 list_disk_geometry(void)
 {
-       long long bytes = (total_number_of_sectors << 9);
-       long megabytes = bytes/1000000;
+       ullong bytes = ((ullong)total_number_of_sectors << 9);
+       long megabytes = bytes / 1000000;
 
        if (megabytes < 10000)
 
        if (megabytes < 10000)
-               printf("\nDisk %s: %ld MB, %lld bytes\n",
-                          disk_device, megabytes, bytes);
+               printf("\nDisk %s: %lu MB, %llu bytes\n",
+                       disk_device, megabytes, bytes);
        else
        else
-               printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
-                          disk_device, megabytes/1000, (megabytes/100)%10, bytes);
-       printf("%d heads, %d sectors/track, %d cylinders",
+               printf("\nDisk %s: %lu.%lu GB, %llu bytes\n",
+                       disk_device, megabytes/1000, (megabytes/100)%10, bytes);
+       printf("%u heads, %u sectors/track, %u cylinders",
                   g_heads, g_sectors, g_cylinders);
        if (units_per_sector == 1)
                   g_heads, g_sectors, g_cylinders);
        if (units_per_sector == 1)
-               printf(", total %llu sectors",
-                          total_number_of_sectors / (sector_size/512));
-       printf("\nUnits = %s of %d * %d = %d bytes\n\n",
-                  str_units(PLURAL),
-                  units_per_sector, sector_size, units_per_sector * sector_size);
+               printf(", total %"SECT_FMT"u sectors",
+                       total_number_of_sectors / (sector_size/512));
+       printf("\nUnits = %s of %u * %u = %u bytes\n\n",
+               str_units(PLURAL),
+               units_per_sector, sector_size, units_per_sector * sector_size);
 }
 
 /*
 }
 
 /*
@@ -1876,8 +1915,8 @@ wrong_p_order(int *prev)
 {
        const struct pte *pe;
        const struct partition *p;
 {
        const struct pte *pe;
        const struct partition *p;
-       ullong last_p_start_pos = 0, p_start_pos;
-       int i, last_i = 0;
+       sector_t last_p_start_pos = 0, p_start_pos;
+       unsigned i, last_i = 0;
 
        for (i = 0; i < g_partitions; i++) {
                if (i == 4) {
 
        for (i = 0; i < g_partitions; i++) {
                if (i == 4) {
@@ -1887,7 +1926,7 @@ wrong_p_order(int *prev)
                pe = &ptes[i];
                p = pe->part_table;
                if (p->sys_ind) {
                pe = &ptes[i];
                p = pe->part_table;
                if (p->sys_ind) {
-                       p_start_pos = get_partition_start(pe);
+                       p_start_pos = get_partition_start_from_dev_start(pe);
 
                        if (last_p_start_pos > p_start_pos) {
                                if (prev)
 
                        if (last_p_start_pos > p_start_pos) {
                                if (prev)
@@ -1926,11 +1965,11 @@ fix_chain_of_logicals(void)
        /* (Its sector is the global extended_offset.) */
  stage1:
        for (j = 5; j < g_partitions - 1; j++) {
        /* (Its sector is the global extended_offset.) */
  stage1:
        for (j = 5; j < g_partitions - 1; j++) {
-               oj = ptes[j].offset;
-               ojj = ptes[j+1].offset;
+               oj = ptes[j].offset_from_dev_start;
+               ojj = ptes[j+1].offset_from_dev_start;
                if (oj > ojj) {
                if (oj > ojj) {
-                       ptes[j].offset = ojj;
-                       ptes[j+1].offset = oj;
+                       ptes[j].offset_from_dev_start = ojj;
+                       ptes[j+1].offset_from_dev_start = oj;
                        pj = ptes[j].part_table;
                        set_start_sect(pj, get_start_sect(pj)+oj-ojj);
                        pjj = ptes[j+1].part_table;
                        pj = ptes[j].part_table;
                        set_start_sect(pj, get_start_sect(pj)+oj-ojj);
                        pjj = ptes[j+1].part_table;
@@ -1950,8 +1989,8 @@ fix_chain_of_logicals(void)
                pjj = ptes[j+1].part_table;
                sj = get_start_sect(pj);
                sjj = get_start_sect(pjj);
                pjj = ptes[j+1].part_table;
                sj = get_start_sect(pj);
                sjj = get_start_sect(pjj);
-               oj = ptes[j].offset;
-               ojj = ptes[j+1].offset;
+               oj = ptes[j].offset_from_dev_start;
+               ojj = ptes[j+1].offset_from_dev_start;
                if (oj+sj > ojj+sjj) {
                        tmp = *pj;
                        *pj = *pjj;
                if (oj+sj > ojj+sjj) {
                        tmp = *pj;
                        *pj = *pjj;
@@ -2045,8 +2084,8 @@ list_table(int xtra)
 
        for (i = 0; i < g_partitions; i++) {
                const struct pte *pe = &ptes[i];
 
        for (i = 0; i < g_partitions; i++) {
                const struct pte *pe = &ptes[i];
-               ullong psects;
-               ullong pblocks;
+               sector_t psects;
+               sector_t pblocks;
                unsigned podd;
 
                p = pe->part_table;
                unsigned podd;
 
                p = pe->part_table;
@@ -2064,14 +2103,14 @@ list_table(int xtra)
                if (sector_size > 1024)
                        pblocks *= (sector_size / 1024);
 
                if (sector_size > 1024)
                        pblocks *= (sector_size / 1024);
 
-               printf("%s  %c %11llu %11llu %11llu%c %2x %s\n",
+               printf("%s  %c %11"SECT_FMT"u %11"SECT_FMT"u %11"SECT_FMT"u%c %2x %s\n",
                        partname(disk_device, i+1, w+2),
                        !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
                                ? '*' : '?',
                        partname(disk_device, i+1, w+2),
                        !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
                                ? '*' : '?',
-                       (ullong) cround(get_partition_start(pe)),           /* start */
-                       (ullong) cround(get_partition_start(pe) + psects    /* end */
+                       cround(get_partition_start_from_dev_start(pe)),           /* start */
+                       cround(get_partition_start_from_dev_start(pe) + psects    /* end */
                                - (psects ? 1 : 0)),
                                - (psects ? 1 : 0)),
-                       (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
+                       pblocks, podd ? '+' : ' ', /* odd flag on end */
                        p->sys_ind,                                     /* type id */
                        partition_type(p->sys_ind));                    /* type name */
 
                        p->sys_ind,                                     /* type id */
                        partition_type(p->sys_ind));                    /* type name */
 
@@ -2079,8 +2118,8 @@ list_table(int xtra)
        }
 
        /* Is partition table in disk order? It need not be, but... */
        }
 
        /* Is partition table in disk order? It need not be, but... */
-       /* partition table entries are not checked for correct order if this
-          is a sgi, sun or aix labeled disk... */
+       /* partition table entries are not checked for correct order
+        * if this is a sgi, sun or aix labeled disk... */
        if (LABEL_IS_DOS && wrong_p_order(NULL)) {
                /* FIXME */
                printf("\nPartition table entries are not in disk order\n");
        if (LABEL_IS_DOS && wrong_p_order(NULL)) {
                /* FIXME */
                printf("\nPartition table entries are not in disk order\n");
@@ -2095,20 +2134,21 @@ x_list_table(int extend)
        const struct partition *p;
        int i;
 
        const struct partition *p;
        int i;
 
-       printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
+       printf("\nDisk %s: %u heads, %u sectors, %u cylinders\n\n",
                disk_device, g_heads, g_sectors, g_cylinders);
        printf("Nr AF  Hd Sec  Cyl  Hd Sec  Cyl      Start       Size ID\n");
        for (i = 0; i < g_partitions; i++) {
                pe = &ptes[i];
                p = (extend ? pe->ext_pointer : pe->part_table);
                if (p != NULL) {
                disk_device, g_heads, g_sectors, g_cylinders);
        printf("Nr AF  Hd Sec  Cyl  Hd Sec  Cyl      Start       Size ID\n");
        for (i = 0; i < g_partitions; i++) {
                pe = &ptes[i];
                p = (extend ? pe->ext_pointer : pe->part_table);
                if (p != NULL) {
-                       printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
+                       printf("%2u %02x%4u%4u%5u%4u%4u%5u%11"SECT_FMT"u%11"SECT_FMT"u %02x\n",
                                i + 1, p->boot_ind, p->head,
                                sector(p->sector),
                                cylinder(p->sector, p->cyl), p->end_head,
                                sector(p->end_sector),
                                cylinder(p->end_sector, p->end_cyl),
                                i + 1, p->boot_ind, p->head,
                                sector(p->sector),
                                cylinder(p->sector, p->cyl), p->end_head,
                                sector(p->end_sector),
                                cylinder(p->end_sector, p->end_cyl),
-                               get_start_sect(p), get_nr_sects(p), p->sys_ind);
+                               get_start_sect(p), get_nr_sects(p),
+                               p->sys_ind);
                        if (p->sys_ind)
                                check_consistency(p, i);
                }
                        if (p->sys_ind)
                                check_consistency(p, i);
                }
@@ -2118,9 +2158,9 @@ x_list_table(int extend)
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
 static void
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
 static void
-fill_bounds(ullong *first, ullong *last)
+fill_bounds(sector_t *first, sector_t *last)
 {
 {
-       int i;
+       unsigned i;
        const struct pte *pe = &ptes[0];
        const struct partition *p;
 
        const struct pte *pe = &ptes[0];
        const struct partition *p;
 
@@ -2130,42 +2170,42 @@ fill_bounds(ullong *first, ullong *last)
                        first[i] = 0xffffffff;
                        last[i] = 0;
                } else {
                        first[i] = 0xffffffff;
                        last[i] = 0;
                } else {
-                       first[i] = get_partition_start(pe);
+                       first[i] = get_partition_start_from_dev_start(pe);
                        last[i] = first[i] + get_nr_sects(p) - 1;
                }
        }
 }
 
 static void
                        last[i] = first[i] + get_nr_sects(p) - 1;
                }
        }
 }
 
 static void
-check(int n, unsigned h, unsigned s, unsigned c, ullong start)
+check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
 {
 {
-       ullong total, real_s, real_c;
+       sector_t total, real_s, real_c;
 
        real_s = sector(s) - 1;
        real_c = cylinder(s, c);
        total = (real_c * g_sectors + real_s) * g_heads + h;
        if (!total)
 
        real_s = sector(s) - 1;
        real_c = cylinder(s, c);
        total = (real_c * g_sectors + real_s) * g_heads + h;
        if (!total)
-               printf("Partition %d contains sector 0\n", n);
+               printf("Partition %u contains sector 0\n", n);
        if (h >= g_heads)
        if (h >= g_heads)
-               printf("Partition %d: head %d greater than maximum %d\n",
+               printf("Partition %u: head %u greater than maximum %u\n",
                        n, h + 1, g_heads);
        if (real_s >= g_sectors)
                        n, h + 1, g_heads);
        if (real_s >= g_sectors)
-               printf("Partition %d: sector %d greater than "
-                       "maximum %d\n", n, s, g_sectors);
+               printf("Partition %u: sector %u greater than "
+                       "maximum %u\n", n, s, g_sectors);
        if (real_c >= g_cylinders)
        if (real_c >= g_cylinders)
-               printf("Partition %d: cylinder %llu greater than "
-                       "maximum %d\n", n, real_c + 1, g_cylinders);
+               printf("Partition %u: cylinder %"SECT_FMT"u greater than "
+                       "maximum %u\n", n, real_c + 1, g_cylinders);
        if (g_cylinders <= 1024 && start != total)
        if (g_cylinders <= 1024 && start != total)
-               printf("Partition %d: previous sectors %llu disagrees with "
-                       "total %llu\n", n, start, total);
+               printf("Partition %u: previous sectors %"SECT_FMT"u disagrees with "
+                       "total %"SECT_FMT"u\n", n, start, total);
 }
 
 static void
 verify(void)
 {
        int i, j;
 }
 
 static void
 verify(void)
 {
        int i, j;
-       unsigned total = 1;
-       ullong first[g_partitions], last[g_partitions];
+       sector_t total = 1;
+       sector_t first[g_partitions], last[g_partitions];
        struct partition *p;
 
        if (warn_geometry())
        struct partition *p;
 
        if (warn_geometry())
@@ -2187,17 +2227,17 @@ verify(void)
                p = pe->part_table;
                if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
                        check_consistency(p, i);
                p = pe->part_table;
                if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
                        check_consistency(p, i);
-                       if (get_partition_start(pe) < first[i])
+                       if (get_partition_start_from_dev_start(pe) < first[i])
                                printf("Warning: bad start-of-data in "
                                printf("Warning: bad start-of-data in "
-                                       "partition %d\n", i + 1);
+                                       "partition %u\n", i + 1);
                        check(i + 1, p->end_head, p->end_sector, p->end_cyl,
                                last[i]);
                        total += last[i] + 1 - first[i];
                        for (j = 0; j < i; j++) {
                                if ((first[i] >= first[j] && first[i] <= last[j])
                                 || ((last[i] <= last[j] && last[i] >= first[j]))) {
                        check(i + 1, p->end_head, p->end_sector, p->end_cyl,
                                last[i]);
                        total += last[i] + 1 - first[i];
                        for (j = 0; j < i; j++) {
                                if ((first[i] >= first[j] && first[i] <= last[j])
                                 || ((last[i] <= last[j] && last[i] >= first[j]))) {
-                                       printf("Warning: partition %d overlaps "
-                                               "partition %d\n", j + 1, i + 1);
+                                       printf("Warning: partition %u overlaps "
+                                               "partition %u\n", j + 1, i + 1);
                                        total += first[i] >= first[j] ?
                                                first[i] : first[j];
                                        total -= last[i] <= last[j] ?
                                        total += first[i] >= first[j] ?
                                                first[i] : first[j];
                                        total -= last[i] <= last[j] ?
@@ -2209,7 +2249,7 @@ verify(void)
 
        if (extended_offset) {
                struct pte *pex = &ptes[ext_index];
 
        if (extended_offset) {
                struct pte *pex = &ptes[ext_index];
-               ullong e_last = get_start_sect(pex->part_table) +
+               sector_t e_last = get_start_sect(pex->part_table) +
                        get_nr_sects(pex->part_table) - 1;
 
                for (i = 4; i < g_partitions; i++) {
                        get_nr_sects(pex->part_table) - 1;
 
                for (i = 4; i < g_partitions; i++) {
@@ -2217,22 +2257,22 @@ verify(void)
                        p = ptes[i].part_table;
                        if (!p->sys_ind) {
                                if (i != 4 || i + 1 < g_partitions)
                        p = ptes[i].part_table;
                        if (!p->sys_ind) {
                                if (i != 4 || i + 1 < g_partitions)
-                                       printf("Warning: partition %d "
+                                       printf("Warning: partition %u "
                                                "is empty\n", i + 1);
                        } else if (first[i] < extended_offset || last[i] > e_last) {
                                                "is empty\n", i + 1);
                        } else if (first[i] < extended_offset || last[i] > e_last) {
-                               printf("Logical partition %d not entirely in "
-                                       "partition %d\n", i + 1, ext_index + 1);
+                               printf("Logical partition %u not entirely in "
+                                       "partition %u\n", i + 1, ext_index + 1);
                        }
                }
        }
 
        if (total > g_heads * g_sectors * g_cylinders)
                        }
                }
        }
 
        if (total > g_heads * g_sectors * g_cylinders)
-               printf("Total allocated sectors %d greater than the maximum "
-                       "%d\n", total, g_heads * g_sectors * g_cylinders);
+               printf("Total allocated sectors %u greater than the maximum "
+                       "%u\n", total, g_heads * g_sectors * g_cylinders);
        else {
                total = g_heads * g_sectors * g_cylinders - total;
                if (total != 0)
        else {
                total = g_heads * g_sectors * g_cylinders - total;
                if (total != 0)
-                       printf("%d unallocated sectors\n", total);
+                       printf("%"SECT_FMT"u unallocated sectors\n", total);
        }
 }
 
        }
 }
 
@@ -2243,9 +2283,9 @@ add_partition(int n, int sys)
        int i, num_read = 0;
        struct partition *p = ptes[n].part_table;
        struct partition *q = ptes[ext_index].part_table;
        int i, num_read = 0;
        struct partition *p = ptes[n].part_table;
        struct partition *q = ptes[ext_index].part_table;
-       ullong limit, temp;
-       ullong start, stop = 0;
-       ullong first[g_partitions], last[g_partitions];
+       sector_t limit, temp;
+       sector_t start, stop = 0;
+       sector_t first[g_partitions], last[g_partitions];
 
        if (p && p->sys_ind) {
                printf(msg_part_already_defined, n + 1);
 
        if (p && p->sys_ind) {
                printf(msg_part_already_defined, n + 1);
@@ -2255,7 +2295,7 @@ add_partition(int n, int sys)
        if (n < 4) {
                start = sector_offset;
                if (display_in_cyl_units || !total_number_of_sectors)
        if (n < 4) {
                start = sector_offset;
                if (display_in_cyl_units || !total_number_of_sectors)
-                       limit = (ullong) g_heads * g_sectors * g_cylinders - 1;
+                       limit = (sector_t) g_heads * g_sectors * g_cylinders - 1;
                else
                        limit = total_number_of_sectors - 1;
                if (extended_offset) {
                else
                        limit = total_number_of_sectors - 1;
                if (extended_offset) {
@@ -2277,7 +2317,7 @@ add_partition(int n, int sys)
                for (i = 0; i < g_partitions; i++) {
                        int lastplusoff;
 
                for (i = 0; i < g_partitions; i++) {
                        int lastplusoff;
 
-                       if (start == ptes[i].offset)
+                       if (start == ptes[i].offset_from_dev_start)
                                start += sector_offset;
                        lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
                        if (start >= first[i] && start <= lastplusoff)
                                start += sector_offset;
                        lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
                        if (start >= first[i] && start <= lastplusoff)
@@ -2286,19 +2326,19 @@ add_partition(int n, int sys)
                if (start > limit)
                        break;
                if (start >= temp+units_per_sector && num_read) {
                if (start > limit)
                        break;
                if (start >= temp+units_per_sector && num_read) {
-                       printf("Sector %lld is already allocated\n", temp);
+                       printf("Sector %"SECT_FMT"u is already allocated\n", temp);
                        temp = start;
                        num_read = 0;
                }
                if (!num_read && start == temp) {
                        temp = start;
                        num_read = 0;
                }
                if (!num_read && start == temp) {
-                       ullong saved_start;
+                       sector_t saved_start;
 
                        saved_start = start;
 
                        saved_start = start;
-                       start = read_int(cround(saved_start), cround(saved_start), cround(limit),
-                                        0, mesg);
+                       start = read_int(cround(saved_start), cround(saved_start), cround(limit), 0, mesg);
                        if (display_in_cyl_units) {
                                start = (start - 1) * units_per_sector;
                        if (display_in_cyl_units) {
                                start = (start - 1) * units_per_sector;
-                               if (start < saved_start) start = saved_start;
+                               if (start < saved_start)
+                                       start = saved_start;
                        }
                        num_read = 1;
                }
                        }
                        num_read = 1;
                }
@@ -2306,9 +2346,9 @@ add_partition(int n, int sys)
        if (n > 4) {                    /* NOT for fifth partition */
                struct pte *pe = &ptes[n];
 
        if (n > 4) {                    /* NOT for fifth partition */
                struct pte *pe = &ptes[n];
 
-               pe->offset = start - sector_offset;
-               if (pe->offset == extended_offset) { /* must be corrected */
-                       pe->offset++;
+               pe->offset_from_dev_start = start - sector_offset;
+               if (pe->offset_from_dev_start == extended_offset) { /* must be corrected */
+                       pe->offset_from_dev_start++;
                        if (sector_offset == 1)
                                start++;
                }
                        if (sector_offset == 1)
                                start++;
                }
@@ -2317,8 +2357,8 @@ add_partition(int n, int sys)
        for (i = 0; i < g_partitions; i++) {
                struct pte *pe = &ptes[i];
 
        for (i = 0; i < g_partitions; i++) {
                struct pte *pe = &ptes[i];
 
-               if (start < pe->offset && limit >= pe->offset)
-                       limit = pe->offset - 1;
+               if (start < pe->offset_from_dev_start && limit >= pe->offset_from_dev_start)
+                       limit = pe->offset_from_dev_start - 1;
                if (start < first[i] && limit >= first[i])
                        limit = first[i] - 1;
        }
                if (start < first[i] && limit >= first[i])
                        limit = first[i] - 1;
        }
@@ -2334,8 +2374,7 @@ add_partition(int n, int sys)
                snprintf(mesg, sizeof(mesg),
                         "Last %s or +size or +sizeM or +sizeK",
                         str_units(SINGULAR));
                snprintf(mesg, sizeof(mesg),
                         "Last %s or +size or +sizeM or +sizeK",
                         str_units(SINGULAR));
-               stop = read_int(cround(start), cround(limit), cround(limit),
-                               cround(start), mesg);
+               stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg);
                if (display_in_cyl_units) {
                        stop = stop * units_per_sector - 1;
                        if (stop >limit)
                if (display_in_cyl_units) {
                        stop = stop * units_per_sector - 1;
                        if (stop >limit)
@@ -2345,7 +2384,7 @@ add_partition(int n, int sys)
 
        set_partition(n, 0, start, stop, sys);
        if (n > 4)
 
        set_partition(n, 0, start, stop, sys);
        if (n > 4)
-               set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
+               set_partition(n - 1, 1, ptes[n].offset_from_dev_start, stop, EXTENDED);
 
        if (IS_EXTENDED(sys)) {
                struct pte *pe4 = &ptes[4];
 
        if (IS_EXTENDED(sys)) {
                struct pte *pe4 = &ptes[4];
@@ -2353,7 +2392,7 @@ add_partition(int n, int sys)
 
                ext_index = n;
                pen->ext_pointer = p;
 
                ext_index = n;
                pen->ext_pointer = p;
-               pe4->offset = extended_offset = start;
+               pe4->offset_from_dev_start = extended_offset = start;
                pe4->sectorbuffer = xzalloc(sector_size);
                pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
                pe4->ext_pointer = pe4->part_table + 1;
                pe4->sectorbuffer = xzalloc(sector_size);
                pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
                pe4->ext_pointer = pe4->part_table + 1;
@@ -2371,7 +2410,7 @@ add_logical(void)
                pe->sectorbuffer = xzalloc(sector_size);
                pe->part_table = pt_offset(pe->sectorbuffer, 0);
                pe->ext_pointer = pe->part_table + 1;
                pe->sectorbuffer = xzalloc(sector_size);
                pe->part_table = pt_offset(pe->sectorbuffer, 0);
                pe->ext_pointer = pe->part_table + 1;
-               pe->offset = 0;
+               pe->offset_from_dev_start = 0;
                pe->changed = 1;
                g_partitions++;
        }
                pe->changed = 1;
                g_partitions++;
        }
@@ -2425,7 +2464,7 @@ new_partition(void)
                        "l   logical (5 or over)" : "e   extended"));
                while (1) {
                        c = read_nonempty(line);
                        "l   logical (5 or over)" : "e   extended"));
                while (1) {
                        c = read_nonempty(line);
-                       if (c == 'p' || c == 'P') {
+                       if ((c | 0x20) == 'p') {
                                i = get_nonexisting_partition(0, 4);
                                if (i >= 0)
                                        add_partition(i, LINUX_NATIVE);
                                i = get_nonexisting_partition(0, 4);
                                if (i >= 0)
                                        add_partition(i, LINUX_NATIVE);
@@ -2461,7 +2500,7 @@ write_table(void)
 
                        if (pe->changed) {
                                write_part_table_flag(pe->sectorbuffer);
 
                        if (pe->changed) {
                                write_part_table_flag(pe->sectorbuffer);
-                               write_sector(pe->offset, pe->sectorbuffer);
+                               write_sector(pe->offset_from_dev_start, pe->sectorbuffer);
                        }
                }
        }
                        }
                }
        }
@@ -2546,26 +2585,29 @@ print_raw(void)
 }
 
 static void
 }
 
 static void
-move_begin(int i)
+move_begin(unsigned i)
 {
        struct pte *pe = &ptes[i];
        struct partition *p = pe->part_table;
 {
        struct pte *pe = &ptes[i];
        struct partition *p = pe->part_table;
-       ullong new, first;
+       sector_t new, first, nr_sects;
 
        if (warn_geometry())
                return;
 
        if (warn_geometry())
                return;
-       if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
-               printf("Partition %d has no data area\n", i + 1);
+       nr_sects = get_nr_sects(p);
+       if (!p->sys_ind || !nr_sects || IS_EXTENDED(p->sys_ind)) {
+               printf("Partition %u has no data area\n", i + 1);
                return;
        }
                return;
        }
-       first = get_partition_start(pe);
-       new = read_int(first, first, first + get_nr_sects(p) - 1, first,
-                          "New beginning of data") - pe->offset;
-
-       if (new != get_nr_sects(p)) {
-               first = get_nr_sects(p) + get_start_sect(p) - new;
-               set_nr_sects(p, first);
-               set_start_sect(p, new);
+       first = get_partition_start_from_dev_start(pe); /* == pe->offset_from_dev_start + get_start_sect(p) */
+       new = read_int(0 /*was:first*/, first, first + nr_sects - 1, first, "New beginning of data");
+       if (new != first) {
+               sector_t new_relative = new - pe->offset_from_dev_start;
+               nr_sects += (get_start_sect(p) - new_relative);
+               set_start_sect(p, new_relative);
+               set_nr_sects(p, nr_sects);
+               read_nonempty("Recalculate C/H/S values? (Y/N): ");
+               if ((line_ptr[0] | 0x20) == 'y')
+                       set_hsc_start_end(p, new, new + nr_sects - 1);
                pe->changed = 1;
        }
 }
                pe->changed = 1;
        }
 }
@@ -2577,7 +2619,7 @@ xselect(void)
 
        while (1) {
                bb_putchar('\n');
 
        while (1) {
                bb_putchar('\n');
-               c = tolower(read_nonempty("Expert command (m for help): "));
+               c = 0x20 | read_nonempty("Expert command (m for help): ");
                switch (c) {
                case 'a':
                        if (LABEL_IS_SUN)
                switch (c) {
                case 'a':
                        if (LABEL_IS_SUN)
@@ -2617,8 +2659,7 @@ xselect(void)
 #endif
                        break;
                case 'h':
 #endif
                        break;
                case 'h':
-                       user_heads = g_heads = read_int(1, g_heads, 256, 0,
-                                       "Number of heads");
+                       user_heads = g_heads = read_int(1, g_heads, 256, 0, "Number of heads");
                        update_units();
                        break;
                case 'i':
                        update_units();
                        break;
                case 'i':
@@ -2643,8 +2684,7 @@ xselect(void)
                case 'r':
                        return;
                case 's':
                case 'r':
                        return;
                case 's':
-                       user_sectors = g_sectors = read_int(1, g_sectors, 63, 0,
-                                          "Number of sectors");
+                       user_sectors = g_sectors = read_int(1, g_sectors, 63, 0, "Number of sectors");
                        if (dos_compatible_flag) {
                                sector_offset = g_sectors;
                                printf("Warning: setting sector offset for DOS "
                        if (dos_compatible_flag) {
                                sector_offset = g_sectors;
                                printf("Warning: setting sector offset for DOS "
@@ -2761,12 +2801,13 @@ list_devs_in_proc_partititons(void)
        procpt = fopen_or_warn("/proc/partitions", "r");
 
        while (fgets(line, sizeof(line), procpt)) {
        procpt = fopen_or_warn("/proc/partitions", "r");
 
        while (fgets(line, sizeof(line), procpt)) {
-               if (sscanf(line, " %d %d %d %[^\n ]",
+               if (sscanf(line, " %u %u %u %[^\n ]",
                                &ma, &mi, &sz, ptname) != 4)
                        continue;
                for (s = ptname; *s; s++)
                                &ma, &mi, &sz, ptname) != 4)
                        continue;
                for (s = ptname; *s; s++)
-                       continue;
-               if (isdigit(s[-1]))
+                       continue;
+               /* note: excluding '0': e.g. mmcblk0 is not a partition name! */
+               if (s[-1] >= '1' && s[-1] <= '9')
                        continue;
                sprintf(devname, "/dev/%s", ptname);
                open_list_and_close(devname, 0);
                        continue;
                sprintf(devname, "/dev/%s", ptname);
                open_list_and_close(devname, 0);
@@ -2785,7 +2826,7 @@ unknown_command(int c)
 #endif
 
 int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 #endif
 
 int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int fdisk_main(int argc, char **argv)
+int fdisk_main(int argc UNUSED_PARAM, char **argv)
 {
        unsigned opt;
        /*
 {
        unsigned opt;
        /*
@@ -2803,16 +2844,18 @@ int fdisk_main(int argc, char **argv)
        opt_complementary = "b+:C+:H+:S+"; /* numeric params */
        opt = getopt32(argv, "b:C:H:lS:u" IF_FEATURE_FDISK_BLKSIZE("s"),
                                &sector_size, &user_cylinders, &user_heads, &user_sectors);
        opt_complementary = "b+:C+:H+:S+"; /* numeric params */
        opt = getopt32(argv, "b:C:H:lS:u" IF_FEATURE_FDISK_BLKSIZE("s"),
                                &sector_size, &user_cylinders, &user_heads, &user_sectors);
-       argc -= optind;
        argv += optind;
        argv += optind;
-       if (opt & OPT_b) { // -b
+       if (opt & OPT_b) {
                /* Ugly: this sector size is really per device,
                /* Ugly: this sector size is really per device,
-                  so cannot be combined with multiple disks,
-                  and the same goes for the C/H/S options.
-               */
-               if (sector_size != 512 && sector_size != 1024
-                && sector_size != 2048)
+                * so cannot be combined with multiple disks,
+                * and the same goes for the C/H/S options.
+                */
+               if (sector_size < 512
+                || sector_size > 0x10000
+                || (sector_size & (sector_size-1)) /* not power of 2 */
+               ) {
                        bb_show_usage();
                        bb_show_usage();
+               }
                sector_offset = 2;
                user_set_sector_size = 1;
        }
                sector_offset = 2;
                user_set_sector_size = 1;
        }
@@ -2847,24 +2890,24 @@ int fdisk_main(int argc, char **argv)
                int j;
 
                nowarn = 1;
                int j;
 
                nowarn = 1;
-               if (argc <= 0)
+               if (!argv[0])
                        bb_show_usage();
                        bb_show_usage();
-               for (j = 0; j < argc; j++) {
+               for (j = 0; argv[j]; j++) {
                        unsigned long long size;
                        fd = xopen(argv[j], O_RDONLY);
                        size = bb_BLKGETSIZE_sectors(fd) / 2;
                        close(fd);
                        unsigned long long size;
                        fd = xopen(argv[j], O_RDONLY);
                        size = bb_BLKGETSIZE_sectors(fd) / 2;
                        close(fd);
-                       if (argc == 1)
-                               printf("%lld\n", size);
+                       if (argv[1])
+                               printf("%llu\n", size);
                        else
                        else
-                               printf("%s: %lld\n", argv[j], size);
+                               printf("%s: %llu\n", argv[j], size);
                }
                return 0;
        }
 #endif
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
                }
                return 0;
        }
 #endif
 
 #if ENABLE_FEATURE_FDISK_WRITABLE
-       if (argc != 1)
+       if (!argv[0] || argv[1])
                bb_show_usage();
 
        disk_device = argv[0];
                bb_show_usage();
 
        disk_device = argv[0];
@@ -2883,7 +2926,7 @@ int fdisk_main(int argc, char **argv)
        while (1) {
                int c;
                bb_putchar('\n');
        while (1) {
                int c;
                bb_putchar('\n');
-               c = tolower(read_nonempty("Command (m for help): "));
+               c = 0x20 | read_nonempty("Command (m for help): ");
                switch (c) {
                case 'a':
                        if (LABEL_IS_DOS)
                switch (c) {
                case 'a':
                        if (LABEL_IS_DOS)