diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-06-02 12:46:55 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-06-02 12:46:55 +0000 |
commit | 95a9140eceb43d5dba205e171d7a5e09f67331ff (patch) | |
tree | e23f7695f19b8a57a5482656d8930a0b842de692 | |
parent | ff570eb12ef446c0e85ab81697e6a81771c7d6da (diff) | |
download | busybox-w32-95a9140eceb43d5dba205e171d7a5e09f67331ff.tar.gz busybox-w32-95a9140eceb43d5dba205e171d7a5e09f67331ff.tar.bz2 busybox-w32-95a9140eceb43d5dba205e171d7a5e09f67331ff.zip |
fdisk: make it work with big disks (read: typical today's disks)
even if CONFIG_LFS is unset.
git-svn-id: svn://busybox.net/trunk/busybox@18727 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r-- | util-linux/fdisk.c | 141 |
1 files changed, 58 insertions, 83 deletions
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index a1893c66e..ed5abe956 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c | |||
@@ -7,6 +7,10 @@ | |||
7 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | 7 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #ifndef _LARGEFILE64_SOURCE | ||
11 | /* For lseek64 */ | ||
12 | #define _LARGEFILE64_SOURCE | ||
13 | #endif | ||
10 | #include <assert.h> /* assert */ | 14 | #include <assert.h> /* assert */ |
11 | #include "libbb.h" | 15 | #include "libbb.h" |
12 | 16 | ||
@@ -34,6 +38,9 @@ | |||
34 | #define LINUX_LVM 0x8e | 38 | #define LINUX_LVM 0x8e |
35 | #define LINUX_RAID 0xfd | 39 | #define LINUX_RAID 0xfd |
36 | 40 | ||
41 | /* Used for sector numbers. Today's disk sizes make it necessary */ | ||
42 | typedef unsigned long long ullong; | ||
43 | |||
37 | struct hd_geometry { | 44 | struct hd_geometry { |
38 | unsigned char heads; | 45 | unsigned char heads; |
39 | unsigned char sectors; | 46 | unsigned char sectors; |
@@ -77,10 +84,12 @@ struct partition { | |||
77 | unsigned char size4[4]; /* nr of sectors in partition */ | 84 | unsigned char size4[4]; /* nr of sectors in partition */ |
78 | } ATTRIBUTE_PACKED; | 85 | } ATTRIBUTE_PACKED; |
79 | 86 | ||
80 | enum failure { | 87 | static const char unable_to_open[] = "cannot open %s"; |
81 | ioctl_error, unable_to_open, unable_to_read, unable_to_seek, | 88 | static const char unable_to_read[] = "cannot read from %s"; |
82 | unable_to_write | 89 | static const char unable_to_seek[] = "cannot seek on %s"; |
83 | }; | 90 | static const char unable_to_write[] = "cannot write to %s"; |
91 | static const char ioctl_error[] = "BLKGETSIZE ioctl failed on %s"; | ||
92 | static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN; | ||
84 | 93 | ||
85 | enum label_type { | 94 | enum label_type { |
86 | label_dos, label_sun, label_sgi, label_aix, label_osf | 95 | label_dos, label_sun, label_sgi, label_aix, label_osf |
@@ -138,7 +147,6 @@ static void list_types(const char *const *sys); | |||
138 | static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg); | 147 | static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg); |
139 | #endif | 148 | #endif |
140 | static const char *partition_type(unsigned char type); | 149 | static const char *partition_type(unsigned char type); |
141 | static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN; | ||
142 | static void get_geometry(void); | 150 | static void get_geometry(void); |
143 | static int get_boot(enum action what); | 151 | static int get_boot(enum action what); |
144 | 152 | ||
@@ -159,7 +167,7 @@ static unsigned get_nr_sects(const struct partition *p); | |||
159 | struct pte { | 167 | struct pte { |
160 | struct partition *part_table; /* points into sectorbuffer */ | 168 | struct partition *part_table; /* points into sectorbuffer */ |
161 | struct partition *ext_pointer; /* points into sectorbuffer */ | 169 | struct partition *ext_pointer; /* points into sectorbuffer */ |
162 | off_t offset; /* disk sector number */ | 170 | ullong offset; /* disk sector number */ |
163 | char *sectorbuffer; /* disk sector contents */ | 171 | char *sectorbuffer; /* disk sector contents */ |
164 | #if ENABLE_FEATURE_FDISK_WRITABLE | 172 | #if ENABLE_FEATURE_FDISK_WRITABLE |
165 | char changed; /* boolean */ | 173 | char changed; /* boolean */ |
@@ -604,69 +612,41 @@ get_nr_sects(const struct partition *p) | |||
604 | /* normally O_RDWR, -l option gives O_RDONLY */ | 612 | /* normally O_RDWR, -l option gives O_RDONLY */ |
605 | static int type_open = O_RDWR; | 613 | static int type_open = O_RDWR; |
606 | 614 | ||
607 | |||
608 | static int ext_index; /* the prime extended partition */ | 615 | static int ext_index; /* the prime extended partition */ |
609 | static int listing; /* no aborts for fdisk -l */ | 616 | static int listing; /* no aborts for fdisk -l */ |
610 | static int dos_compatible_flag = ~0; | 617 | static int dos_compatible_flag = ~0; |
611 | #if ENABLE_FEATURE_FDISK_WRITABLE | 618 | #if ENABLE_FEATURE_FDISK_WRITABLE |
612 | static int dos_changed; | 619 | static int dos_changed; |
613 | static int nowarn; /* no warnings for fdisk -l/-s */ | 620 | static int nowarn; /* no warnings for fdisk -l/-s */ |
614 | #endif | 621 | #endif |
615 | 622 | ||
616 | |||
617 | |||
618 | static unsigned user_cylinders, user_heads, user_sectors; | 623 | static unsigned user_cylinders, user_heads, user_sectors; |
619 | static unsigned pt_heads, pt_sectors; | 624 | static unsigned pt_heads, pt_sectors; |
620 | static unsigned kern_heads, kern_sectors; | 625 | static unsigned kern_heads, kern_sectors; |
621 | 626 | ||
622 | static off_t extended_offset; /* offset of link pointers */ | 627 | static ullong extended_offset; /* offset of link pointers */ |
623 | 628 | static ullong total_number_of_sectors; | |
624 | static unsigned long long total_number_of_sectors; | ||
625 | 629 | ||
626 | 630 | static void fdisk_fatal(const char *why) | |
627 | static void fdisk_fatal(enum failure why) | ||
628 | { | 631 | { |
629 | const char *message; | ||
630 | |||
631 | if (listing) { | 632 | if (listing) { |
632 | close(fd); | 633 | close(fd); |
633 | longjmp(listingbuf, 1); | 634 | longjmp(listingbuf, 1); |
634 | } | 635 | } |
635 | 636 | bb_error_msg_and_die(why, disk_device); | |
636 | switch (why) { | ||
637 | case unable_to_open: | ||
638 | message = "cannot open %s"; | ||
639 | break; | ||
640 | case unable_to_read: | ||
641 | message = "cannot read from %s"; | ||
642 | break; | ||
643 | case unable_to_seek: | ||
644 | message = "cannot seek on %s"; | ||
645 | break; | ||
646 | case unable_to_write: | ||
647 | message = "cannot write to %s"; | ||
648 | break; | ||
649 | case ioctl_error: | ||
650 | message = "BLKGETSIZE ioctl failed on %s"; | ||
651 | break; | ||
652 | default: | ||
653 | message = "fatal error"; | ||
654 | } | ||
655 | |||
656 | bb_error_msg_and_die(message, disk_device); | ||
657 | } | 637 | } |
658 | 638 | ||
659 | static void | 639 | static void |
660 | seek_sector(off_t secno) | 640 | seek_sector(ullong secno) |
661 | { | 641 | { |
662 | off_t offset = secno * sector_size; | 642 | secno *= sector_size; |
663 | if (lseek(fd, offset, SEEK_SET) == (off_t) -1) | 643 | if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1) |
664 | fdisk_fatal(unable_to_seek); | 644 | fdisk_fatal(unable_to_seek); |
665 | } | 645 | } |
666 | 646 | ||
667 | #if ENABLE_FEATURE_FDISK_WRITABLE | 647 | #if ENABLE_FEATURE_FDISK_WRITABLE |
668 | static void | 648 | static void |
669 | write_sector(off_t secno, char *buf) | 649 | write_sector(ullong secno, char *buf) |
670 | { | 650 | { |
671 | seek_sector(secno); | 651 | seek_sector(secno); |
672 | if (write(fd, buf, sector_size) != sector_size) | 652 | if (write(fd, buf, sector_size) != sector_size) |
@@ -676,7 +656,7 @@ write_sector(off_t secno, char *buf) | |||
676 | 656 | ||
677 | /* Allocate a buffer and read a partition table sector */ | 657 | /* Allocate a buffer and read a partition table sector */ |
678 | static void | 658 | static void |
679 | read_pte(struct pte *pe, off_t offset) | 659 | read_pte(struct pte *pe, ullong offset) |
680 | { | 660 | { |
681 | pe->offset = offset; | 661 | pe->offset = offset; |
682 | pe->sectorbuffer = xmalloc(sector_size); | 662 | pe->sectorbuffer = xmalloc(sector_size); |
@@ -928,10 +908,10 @@ clear_partition(struct partition *p) | |||
928 | 908 | ||
929 | #if ENABLE_FEATURE_FDISK_WRITABLE | 909 | #if ENABLE_FEATURE_FDISK_WRITABLE |
930 | static void | 910 | static void |
931 | set_partition(int i, int doext, off_t start, off_t stop, int sysid) | 911 | set_partition(int i, int doext, ullong start, ullong stop, int sysid) |
932 | { | 912 | { |
933 | struct partition *p; | 913 | struct partition *p; |
934 | off_t offset; | 914 | ullong offset; |
935 | 915 | ||
936 | if (doext) { | 916 | if (doext) { |
937 | p = ptes[i].ext_pointer; | 917 | p = ptes[i].ext_pointer; |
@@ -1182,7 +1162,7 @@ static void | |||
1182 | get_geometry(void) | 1162 | get_geometry(void) |
1183 | { | 1163 | { |
1184 | int sec_fac; | 1164 | int sec_fac; |
1185 | unsigned long long bytes; /* really u64 */ | 1165 | uint64_t v64; |
1186 | 1166 | ||
1187 | get_sectorsize(); | 1167 | get_sectorsize(); |
1188 | sec_fac = sector_size / 512; | 1168 | sec_fac = sector_size / 512; |
@@ -1202,18 +1182,16 @@ get_geometry(void) | |||
1202 | sectors = user_sectors ? user_sectors : | 1182 | sectors = user_sectors ? user_sectors : |
1203 | pt_sectors ? pt_sectors : | 1183 | pt_sectors ? pt_sectors : |
1204 | kern_sectors ? kern_sectors : 63; | 1184 | kern_sectors ? kern_sectors : 63; |
1205 | if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) { | 1185 | if (ioctl(fd, BLKGETSIZE64, &v64) == 0) { |
1206 | /* got bytes */ | 1186 | /* got bytes, convert to 512 byte sectors */ |
1187 | total_number_of_sectors = (v64 >> 9); | ||
1207 | } else { | 1188 | } else { |
1208 | unsigned long longsectors; | 1189 | unsigned long longsectors; /* need temp of type long */ |
1209 | 1190 | if (ioctl(fd, BLKGETSIZE, &longsectors)) | |
1210 | if (ioctl(fd, BLKGETSIZE, &longsectors)) | 1191 | longsectors = 0; |
1211 | longsectors = 0; | 1192 | total_number_of_sectors = longsectors; |
1212 | bytes = ((unsigned long long) longsectors) << 9; | ||
1213 | } | 1193 | } |
1214 | 1194 | ||
1215 | total_number_of_sectors = (bytes >> 9); | ||
1216 | |||
1217 | sector_offset = 1; | 1195 | sector_offset = 1; |
1218 | if (dos_compatible_flag) | 1196 | if (dos_compatible_flag) |
1219 | sector_offset = sectors; | 1197 | sector_offset = sectors; |
@@ -1447,10 +1425,10 @@ read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char * | |||
1447 | break; | 1425 | break; |
1448 | } | 1426 | } |
1449 | if (absolute) { | 1427 | if (absolute) { |
1450 | unsigned long long bytes; | 1428 | ullong bytes; |
1451 | unsigned long unit; | 1429 | unsigned long unit; |
1452 | 1430 | ||
1453 | bytes = (unsigned long long) i * absolute; | 1431 | bytes = (ullong) i * absolute; |
1454 | unit = sector_size * units_per_sector; | 1432 | unit = sector_size * units_per_sector; |
1455 | bytes += unit/2; /* round */ | 1433 | bytes += unit/2; /* round */ |
1456 | bytes /= unit; | 1434 | bytes /= unit; |
@@ -1844,7 +1822,7 @@ wrong_p_order(int *prev) | |||
1844 | { | 1822 | { |
1845 | const struct pte *pe; | 1823 | const struct pte *pe; |
1846 | const struct partition *p; | 1824 | const struct partition *p; |
1847 | off_t last_p_start_pos = 0, p_start_pos; | 1825 | ullong last_p_start_pos = 0, p_start_pos; |
1848 | int i, last_i = 0; | 1826 | int i, last_i = 0; |
1849 | 1827 | ||
1850 | for (i = 0 ; i < partitions; i++) { | 1828 | for (i = 0 ; i < partitions; i++) { |
@@ -2012,8 +1990,8 @@ list_table(int xtra) | |||
2012 | 1990 | ||
2013 | for (i = 0; i < partitions; i++) { | 1991 | for (i = 0; i < partitions; i++) { |
2014 | const struct pte *pe = &ptes[i]; | 1992 | const struct pte *pe = &ptes[i]; |
2015 | off_t psects; | 1993 | ullong psects; |
2016 | off_t pblocks; | 1994 | ullong pblocks; |
2017 | unsigned podd; | 1995 | unsigned podd; |
2018 | 1996 | ||
2019 | p = pe->part_table; | 1997 | p = pe->part_table; |
@@ -2035,10 +2013,10 @@ list_table(int xtra) | |||
2035 | partname(disk_device, i+1, w+2), | 2013 | partname(disk_device, i+1, w+2), |
2036 | !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */ | 2014 | !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */ |
2037 | ? '*' : '?', | 2015 | ? '*' : '?', |
2038 | (unsigned long long) cround(get_partition_start(pe)), /* start */ | 2016 | (ullong) cround(get_partition_start(pe)), /* start */ |
2039 | (unsigned long long) cround(get_partition_start(pe) + psects /* end */ | 2017 | (ullong) cround(get_partition_start(pe) + psects /* end */ |
2040 | - (psects ? 1 : 0)), | 2018 | - (psects ? 1 : 0)), |
2041 | (unsigned long long) pblocks, podd ? '+' : ' ', /* odd flag on end */ | 2019 | (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */ |
2042 | p->sys_ind, /* type id */ | 2020 | p->sys_ind, /* type id */ |
2043 | partition_type(p->sys_ind)); /* type name */ | 2021 | partition_type(p->sys_ind)); /* type name */ |
2044 | 2022 | ||
@@ -2085,7 +2063,7 @@ x_list_table(int extend) | |||
2085 | 2063 | ||
2086 | #if ENABLE_FEATURE_FDISK_WRITABLE | 2064 | #if ENABLE_FEATURE_FDISK_WRITABLE |
2087 | static void | 2065 | static void |
2088 | fill_bounds(off_t *first, off_t *last) | 2066 | fill_bounds(ullong *first, ullong *last) |
2089 | { | 2067 | { |
2090 | int i; | 2068 | int i; |
2091 | const struct pte *pe = &ptes[0]; | 2069 | const struct pte *pe = &ptes[0]; |
@@ -2104,9 +2082,9 @@ fill_bounds(off_t *first, off_t *last) | |||
2104 | } | 2082 | } |
2105 | 2083 | ||
2106 | static void | 2084 | static void |
2107 | check(int n, unsigned h, unsigned s, unsigned c, off_t start) | 2085 | check(int n, unsigned h, unsigned s, unsigned c, ullong start) |
2108 | { | 2086 | { |
2109 | off_t total, real_s, real_c; | 2087 | ullong total, real_s, real_c; |
2110 | 2088 | ||
2111 | real_s = sector(s) - 1; | 2089 | real_s = sector(s) - 1; |
2112 | real_c = cylinder(s, c); | 2090 | real_c = cylinder(s, c); |
@@ -2120,11 +2098,11 @@ check(int n, unsigned h, unsigned s, unsigned c, off_t start) | |||
2120 | printf("Partition %d: sector %d greater than " | 2098 | printf("Partition %d: sector %d greater than " |
2121 | "maximum %d\n", n, s, sectors); | 2099 | "maximum %d\n", n, s, sectors); |
2122 | if (real_c >= cylinders) | 2100 | if (real_c >= cylinders) |
2123 | printf("Partition %d: cylinder %"OFF_FMT"u greater than " | 2101 | printf("Partition %d: cylinder %llu greater than " |
2124 | "maximum %d\n", n, real_c + 1, cylinders); | 2102 | "maximum %d\n", n, real_c + 1, cylinders); |
2125 | if (cylinders <= 1024 && start != total) | 2103 | if (cylinders <= 1024 && start != total) |
2126 | printf("Partition %d: previous sectors %"OFF_FMT"u disagrees with " | 2104 | printf("Partition %d: previous sectors %llu disagrees with " |
2127 | "total %"OFF_FMT"u\n", n, start, total); | 2105 | "total %llu\n", n, start, total); |
2128 | } | 2106 | } |
2129 | 2107 | ||
2130 | static void | 2108 | static void |
@@ -2132,7 +2110,7 @@ verify(void) | |||
2132 | { | 2110 | { |
2133 | int i, j; | 2111 | int i, j; |
2134 | unsigned total = 1; | 2112 | unsigned total = 1; |
2135 | off_t first[partitions], last[partitions]; | 2113 | ullong first[partitions], last[partitions]; |
2136 | struct partition *p; | 2114 | struct partition *p; |
2137 | 2115 | ||
2138 | if (warn_geometry()) | 2116 | if (warn_geometry()) |
@@ -2176,7 +2154,7 @@ verify(void) | |||
2176 | 2154 | ||
2177 | if (extended_offset) { | 2155 | if (extended_offset) { |
2178 | struct pte *pex = &ptes[ext_index]; | 2156 | struct pte *pex = &ptes[ext_index]; |
2179 | off_t e_last = get_start_sect(pex->part_table) + | 2157 | ullong e_last = get_start_sect(pex->part_table) + |
2180 | get_nr_sects(pex->part_table) - 1; | 2158 | get_nr_sects(pex->part_table) - 1; |
2181 | 2159 | ||
2182 | for (i = 4; i < partitions; i++) { | 2160 | for (i = 4; i < partitions; i++) { |
@@ -2210,9 +2188,9 @@ add_partition(int n, int sys) | |||
2210 | int i, num_read = 0; | 2188 | int i, num_read = 0; |
2211 | struct partition *p = ptes[n].part_table; | 2189 | struct partition *p = ptes[n].part_table; |
2212 | struct partition *q = ptes[ext_index].part_table; | 2190 | struct partition *q = ptes[ext_index].part_table; |
2213 | long long llimit; | 2191 | ullong limit, temp; |
2214 | off_t start, stop = 0, limit, temp, | 2192 | ullong start, stop = 0; |
2215 | first[partitions], last[partitions]; | 2193 | ullong first[partitions], last[partitions]; |
2216 | 2194 | ||
2217 | if (p && p->sys_ind) { | 2195 | if (p && p->sys_ind) { |
2218 | printf(msg_part_already_defined, n + 1); | 2196 | printf(msg_part_already_defined, n + 1); |
@@ -2222,12 +2200,9 @@ add_partition(int n, int sys) | |||
2222 | if (n < 4) { | 2200 | if (n < 4) { |
2223 | start = sector_offset; | 2201 | start = sector_offset; |
2224 | if (display_in_cyl_units || !total_number_of_sectors) | 2202 | if (display_in_cyl_units || !total_number_of_sectors) |
2225 | llimit = heads * sectors * cylinders - 1; | 2203 | limit = (ullong) heads * sectors * cylinders - 1; |
2226 | else | 2204 | else |
2227 | llimit = total_number_of_sectors - 1; | 2205 | limit = total_number_of_sectors - 1; |
2228 | limit = llimit; | ||
2229 | if (limit != llimit) | ||
2230 | limit = 0x7fffffff; | ||
2231 | if (extended_offset) { | 2206 | if (extended_offset) { |
2232 | first[ext_index] = extended_offset; | 2207 | first[ext_index] = extended_offset; |
2233 | last[ext_index] = get_start_sect(q) + | 2208 | last[ext_index] = get_start_sect(q) + |
@@ -2256,12 +2231,12 @@ add_partition(int n, int sys) | |||
2256 | if (start > limit) | 2231 | if (start > limit) |
2257 | break; | 2232 | break; |
2258 | if (start >= temp+units_per_sector && num_read) { | 2233 | if (start >= temp+units_per_sector && num_read) { |
2259 | printf("Sector %"OFF_FMT"d is already allocated\n", temp); | 2234 | printf("Sector %lld is already allocated\n", temp); |
2260 | temp = start; | 2235 | temp = start; |
2261 | num_read = 0; | 2236 | num_read = 0; |
2262 | } | 2237 | } |
2263 | if (!num_read && start == temp) { | 2238 | if (!num_read && start == temp) { |
2264 | off_t saved_start; | 2239 | ullong saved_start; |
2265 | 2240 | ||
2266 | saved_start = start; | 2241 | saved_start = start; |
2267 | start = read_int(cround(saved_start), cround(saved_start), cround(limit), | 2242 | start = read_int(cround(saved_start), cround(saved_start), cround(limit), |
@@ -2534,7 +2509,7 @@ move_begin(int i) | |||
2534 | { | 2509 | { |
2535 | struct pte *pe = &ptes[i]; | 2510 | struct pte *pe = &ptes[i]; |
2536 | struct partition *p = pe->part_table; | 2511 | struct partition *p = pe->part_table; |
2537 | off_t new, first; | 2512 | ullong new, first; |
2538 | 2513 | ||
2539 | if (warn_geometry()) | 2514 | if (warn_geometry()) |
2540 | return; | 2515 | return; |