fdisk: make it work with big disks (read: typical today's disks) even if CONFIG_LFS is unset.
No binary (build failed)
—
(log yok)
| @@ -7,6 +7,10 @@ | |
| * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | |
| */ | |
| + | #ifndef _LARGEFILE64_SOURCE |
| + | /* For lseek64 */ |
| + | #define _LARGEFILE64_SOURCE |
| + | #endif |
| #include <assert.h> /* assert */ | |
| #include "libbb.h" | |
| @@ -34,6 +38,9 @@ | |
| #define LINUX_LVM 0x8e | |
| #define LINUX_RAID 0xfd | |
| + | /* Used for sector numbers. Today's disk sizes make it necessary */ |
| + | typedef unsigned long long ullong; |
| + | |
| struct hd_geometry { | |
| unsigned char heads; | |
| unsigned char sectors; | |
| @@ -77,10 +84,12 @@ struct partition { | |
| unsigned char size4[4]; /* nr of sectors in partition */ | |
| } ATTRIBUTE_PACKED; | |
| - | enum failure { |
| - | ioctl_error, unable_to_open, unable_to_read, unable_to_seek, |
| - | unable_to_write |
| - | }; |
| + | static const char unable_to_open[] = "cannot open %s"; |
| + | static const char unable_to_read[] = "cannot read from %s"; |
| + | static const char unable_to_seek[] = "cannot seek on %s"; |
| + | static const char unable_to_write[] = "cannot write to %s"; |
| + | static const char ioctl_error[] = "BLKGETSIZE ioctl failed on %s"; |
| + | static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN; |
| enum label_type { | |
| label_dos, label_sun, label_sgi, label_aix, label_osf | |
| @@ -138,7 +147,6 @@ static void list_types(const char *const *sys); | |
| static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const 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); | |
| @@ -159,7 +167,7 @@ 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 */ | |
| - | off_t offset; /* disk sector number */ |
| + | ullong offset; /* disk sector number */ |
| char *sectorbuffer; /* disk sector contents */ | |
| #if ENABLE_FEATURE_FDISK_WRITABLE | |
| char changed; /* boolean */ | |
| @@ -604,69 +612,41 @@ get_nr_sects(const struct partition *p) | |
| /* normally O_RDWR, -l option gives O_RDONLY */ | |
| static int type_open = O_RDWR; | |
| - | |
| static int ext_index; /* the prime extended partition */ | |
| - | static int listing; /* no aborts for fdisk -l */ |
| + | static int listing; /* no aborts for fdisk -l */ |
| static int dos_compatible_flag = ~0; | |
| #if ENABLE_FEATURE_FDISK_WRITABLE | |
| static int dos_changed; | |
| static int nowarn; /* no warnings for fdisk -l/-s */ | |
| #endif | |
| - | |
| - | |
| static unsigned user_cylinders, user_heads, user_sectors; | |
| static unsigned pt_heads, pt_sectors; | |
| static unsigned kern_heads, kern_sectors; | |
| - | static off_t extended_offset; /* offset of link pointers */ |
| - | |
| - | static unsigned long long total_number_of_sectors; |
| + | static ullong extended_offset; /* offset of link pointers */ |
| + | static ullong total_number_of_sectors; |
| - | |
| - | static void fdisk_fatal(enum failure why) |
| + | static void fdisk_fatal(const char *why) |
| { | |
| - | const char *message; |
| - | |
| if (listing) { | |
| close(fd); | |
| longjmp(listingbuf, 1); | |
| } | |
| - | |
| - | switch (why) { |
| - | case unable_to_open: |
| - | message = "cannot open %s"; |
| - | break; |
| - | case unable_to_read: |
| - | message = "cannot read from %s"; |
| - | break; |
| - | case unable_to_seek: |
| - | message = "cannot seek on %s"; |
| - | break; |
| - | case unable_to_write: |
| - | message = "cannot write to %s"; |
| - | break; |
| - | case ioctl_error: |
| - | message = "BLKGETSIZE ioctl failed on %s"; |
| - | break; |
| - | default: |
| - | message = "fatal error"; |
| - | } |
| - | |
| - | bb_error_msg_and_die(message, disk_device); |
| + | bb_error_msg_and_die(why, disk_device); |
| } | |
| static void | |
| - | seek_sector(off_t secno) |
| + | seek_sector(ullong secno) |
| { | |
| - | off_t offset = secno * sector_size; |
| - | if (lseek(fd, offset, SEEK_SET) == (off_t) -1) |
| + | secno *= sector_size; |
| + | if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1) |
| fdisk_fatal(unable_to_seek); | |
| } | |
| #if ENABLE_FEATURE_FDISK_WRITABLE | |
| static void | |
| - | write_sector(off_t secno, char *buf) |
| + | write_sector(ullong secno, char *buf) |
| { | |
| seek_sector(secno); | |
| if (write(fd, buf, sector_size) != sector_size) | |
| @@ -676,7 +656,7 @@ write_sector(off_t secno, char *buf) | |
| /* Allocate a buffer and read a partition table sector */ | |
| static void | |
| - | read_pte(struct pte *pe, off_t offset) |
| + | read_pte(struct pte *pe, ullong offset) |
| { | |
| pe->offset = offset; | |
| pe->sectorbuffer = xmalloc(sector_size); | |
| @@ -928,10 +908,10 @@ clear_partition(struct partition *p) | |
| #if ENABLE_FEATURE_FDISK_WRITABLE | |
| static void | |
| - | set_partition(int i, int doext, off_t start, off_t stop, int sysid) |
| + | set_partition(int i, int doext, ullong start, ullong stop, int sysid) |
| { | |
| struct partition *p; | |
| - | off_t offset; |
| + | ullong offset; |
| if (doext) { | |
| p = ptes[i].ext_pointer; | |
| @@ -1182,7 +1162,7 @@ static void | |
| get_geometry(void) | |
| { | |
| int sec_fac; | |
| - | unsigned long long bytes; /* really u64 */ |
| + | uint64_t v64; |
| get_sectorsize(); | |
| sec_fac = sector_size / 512; | |
| @@ -1202,18 +1182,16 @@ get_geometry(void) | |
| sectors = user_sectors ? user_sectors : | |
| pt_sectors ? pt_sectors : | |
| kern_sectors ? kern_sectors : 63; | |
| - | if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) { |
| - | /* got bytes */ |
| + | if (ioctl(fd, BLKGETSIZE64, &v64) == 0) { |
| + | /* got bytes, convert to 512 byte sectors */ |
| + | total_number_of_sectors = (v64 >> 9); |
| } else { | |
| - | unsigned long longsectors; |
| - | |
| - | if (ioctl(fd, BLKGETSIZE, &longsectors)) |
| - | longsectors = 0; |
| - | bytes = ((unsigned long long) longsectors) << 9; |
| + | unsigned long longsectors; /* need temp of type long */ |
| + | if (ioctl(fd, BLKGETSIZE, &longsectors)) |
| + | longsectors = 0; |
| + | total_number_of_sectors = longsectors; |
| } | |
| - | total_number_of_sectors = (bytes >> 9); |
| - | |
| sector_offset = 1; | |
| if (dos_compatible_flag) | |
| sector_offset = sectors; | |
| @@ -1447,10 +1425,10 @@ read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char * | |
| break; | |
| } | |
| if (absolute) { | |
| - | unsigned long long bytes; |
| + | ullong bytes; |
| unsigned long unit; | |
| - | bytes = (unsigned long long) i * absolute; |
| + | bytes = (ullong) i * absolute; |
| unit = sector_size * units_per_sector; | |
| bytes += unit/2; /* round */ | |
| bytes /= unit; | |
| @@ -1844,7 +1822,7 @@ wrong_p_order(int *prev) | |
| { | |
| const struct pte *pe; | |
| const struct partition *p; | |
| - | off_t last_p_start_pos = 0, p_start_pos; |
| + | ullong last_p_start_pos = 0, p_start_pos; |
| int i, last_i = 0; | |
| for (i = 0 ; i < partitions; i++) { | |
| @@ -2012,8 +1990,8 @@ list_table(int xtra) | |
| for (i = 0; i < partitions; i++) { | |
| const struct pte *pe = &ptes[i]; | |
| - | off_t psects; |
| - | off_t pblocks; |
| + | ullong psects; |
| + | ullong pblocks; |
| unsigned podd; | |
| p = pe->part_table; | |
| @@ -2035,10 +2013,10 @@ list_table(int xtra) | |
| partname(disk_device, i+1, w+2), | |
| !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */ | |
| ? '*' : '?', | |
| - | (unsigned long long) cround(get_partition_start(pe)), /* start */ |
| - | (unsigned long long) cround(get_partition_start(pe) + psects /* end */ |
| + | (ullong) cround(get_partition_start(pe)), /* start */ |
| + | (ullong) cround(get_partition_start(pe) + psects /* end */ |
| - (psects ? 1 : 0)), | |
| - | (unsigned long long) pblocks, podd ? '+' : ' ', /* odd flag on end */ |
| + | (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */ |
| p->sys_ind, /* type id */ | |
| partition_type(p->sys_ind)); /* type name */ | |
| @@ -2085,7 +2063,7 @@ x_list_table(int extend) | |
| #if ENABLE_FEATURE_FDISK_WRITABLE | |
| static void | |
| - | fill_bounds(off_t *first, off_t *last) |
| + | fill_bounds(ullong *first, ullong *last) |
| { | |
| int i; | |
| const struct pte *pe = &ptes[0]; | |
| @@ -2104,9 +2082,9 @@ fill_bounds(off_t *first, off_t *last) | |
| } | |
| static void | |
| - | check(int n, unsigned h, unsigned s, unsigned c, off_t start) |
| + | check(int n, unsigned h, unsigned s, unsigned c, ullong start) |
| { | |
| - | off_t total, real_s, real_c; |
| + | ullong total, real_s, real_c; |
| real_s = sector(s) - 1; | |
| real_c = cylinder(s, c); | |
| @@ -2120,11 +2098,11 @@ check(int n, unsigned h, unsigned s, unsigned c, off_t start) | |
| printf("Partition %d: sector %d greater than " | |
| "maximum %d\n", n, s, sectors); | |
| if (real_c >= cylinders) | |
| - | printf("Partition %d: cylinder %"OFF_FMT"u greater than " |
| + | printf("Partition %d: cylinder %llu greater than " |
| "maximum %d\n", n, real_c + 1, cylinders); | |
| if (cylinders <= 1024 && start != total) | |
| - | printf("Partition %d: previous sectors %"OFF_FMT"u disagrees with " |
| - | "total %"OFF_FMT"u\n", n, start, total); |
| + | printf("Partition %d: previous sectors %llu disagrees with " |
| + | "total %llu\n", n, start, total); |
| } | |
| static void | |
| @@ -2132,7 +2110,7 @@ verify(void) | |
| { | |
| int i, j; | |
| unsigned total = 1; | |
| - | off_t first[partitions], last[partitions]; |
| + | ullong first[partitions], last[partitions]; |
| struct partition *p; | |
| if (warn_geometry()) | |
| @@ -2176,7 +2154,7 @@ verify(void) | |
| if (extended_offset) { | |
| struct pte *pex = &ptes[ext_index]; | |
| - | off_t e_last = get_start_sect(pex->part_table) + |
| + | ullong e_last = get_start_sect(pex->part_table) + |
| get_nr_sects(pex->part_table) - 1; | |
| for (i = 4; i < partitions; i++) { | |
| @@ -2210,9 +2188,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; | |
| - | long long llimit; |
| - | off_t start, stop = 0, limit, temp, |
| - | first[partitions], last[partitions]; |
| + | ullong limit, temp; |
| + | ullong start, stop = 0; |
| + | ullong first[partitions], last[partitions]; |
| if (p && p->sys_ind) { | |
| printf(msg_part_already_defined, n + 1); | |
| @@ -2222,12 +2200,9 @@ add_partition(int n, int sys) | |
| if (n < 4) { | |
| start = sector_offset; | |
| if (display_in_cyl_units || !total_number_of_sectors) | |
| - | llimit = heads * sectors * cylinders - 1; |
| + | limit = (ullong) heads * sectors * cylinders - 1; |
| else | |
| - | llimit = total_number_of_sectors - 1; |
| - | limit = llimit; |
| - | if (limit != llimit) |
| - | limit = 0x7fffffff; |
| + | limit = total_number_of_sectors - 1; |
| if (extended_offset) { | |
| first[ext_index] = extended_offset; | |
| last[ext_index] = get_start_sect(q) + | |
| @@ -2256,12 +2231,12 @@ add_partition(int n, int sys) | |
| if (start > limit) | |
| break; | |
| if (start >= temp+units_per_sector && num_read) { | |
| - | printf("Sector %"OFF_FMT"d is already allocated\n", temp); |
| + | printf("Sector %lld is already allocated\n", temp); |
| temp = start; | |
| num_read = 0; | |
| } | |
| if (!num_read && start == temp) { | |
| - | off_t saved_start; |
| + | ullong saved_start; |
| saved_start = start; | |
| start = read_int(cround(saved_start), cround(saved_start), cround(limit), | |
| @@ -2534,7 +2509,7 @@ move_begin(int i) | |
| { | |
| struct pte *pe = &ptes[i]; | |
| struct partition *p = pe->part_table; | |
| - | off_t new, first; |
| + | ullong new, first; |
| if (warn_geometry()) | |
| return; | |