From 2b9e638a0f2bd869e33ecdadab442c0a1591ecb0 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 8 Feb 2010 17:45:42 +0100 Subject: fdisk: don't check alignment_offset against geometry The alignment_offset is compensation for DOS compatible partitioning. It usually matches with disk geometry (e.g. 63 sectors), but the offset is also exported from phy.disks to RAIDs there the geometry don't match with the offset. So.. don't print unnecessary warning. Signed-off-by: Karel Zak --- fdisk/fdisk.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index cc573646..469cf0d8 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -1041,18 +1041,9 @@ get_partition_table_geometry(void) { void update_sector_offset(void) { - if (dos_compatible_flag) { - /* usually 63 sectors for classic geometry */ - sector_offset = sectors; - - /* On the disks with alignment_offset the default geo.sectors - * has to be aligned to physical block boundary. Check it! - */ - if (sectors && alignment_offset && !lba_is_aligned(sectors)) - fprintf(stderr, _( - "\nWARNING: the device provides alignment_offset, but the offset does not\n" - "match with device geometry.\n\n")); - } else { + if (dos_compatible_flag) + sector_offset = sectors; /* usually 63 sectors */ + else { /* * Align the begin of the first partition to the physical block */ -- cgit v1.2.3 From 1d07e336cadc6963f3d46f1db9105cda0f210321 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 9 Feb 2010 10:32:29 +0100 Subject: fdisk: fix check_alignment() The old version of check_alignment() does not work with extended partitions. Signed-off-by: Karel Zak --- fdisk/fdisk.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 469cf0d8..9fd9bd9d 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -1800,9 +1800,9 @@ static void check_consistency(struct partition *p, int partition) { } static void -check_alignment(struct partition *p, int partition) +check_alignment(unsigned long long lba, int partition) { - if (!lba_is_aligned(get_start_sect(p))) + if (!lba_is_aligned(lba)) printf(_("Partition %i does not start on optimal I/O size boundary.\n"), partition + 1); } @@ -2042,7 +2042,7 @@ list_table(int xtra) { /* type name */ (type = partition_type(p->sys_ind)) ? type : _("Unknown")); check_consistency(p, i); - check_alignment(p, i); + check_alignment(get_partition_start(pe), i); } } @@ -2077,7 +2077,7 @@ x_list_table(int extend) { (unsigned long) get_nr_sects(p), p->sys_ind); if (p->sys_ind) { check_consistency(p, i); - check_alignment(p, i); + check_alignment(get_partition_start(pe), i); } } } @@ -2155,7 +2155,7 @@ verify(void) { p = pe->part_table; if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) { check_consistency(p, i); - check_alignment(p, i); + check_alignment(get_partition_start(pe), i); if (get_partition_start(pe) < first[i]) printf(_("Warning: bad start-of-data in " "partition %d\n"), i + 1); -- cgit v1.2.3 From 40c7aaf3958c28b38772f38ee245b20afe3c1373 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 4 Feb 2010 13:43:37 +0100 Subject: fdisk: cleanup alignment, default to 1MiB offset * add heuristic to detect that the device does not provide topology information. We can use topology if: - alignment_offset is not 0 - or optimal_io_size is not 0 - or minimal_io_size is not power of 2 * default to 1MiB offset for the start of the first partition if topology is unknown. This (2048 512-byte sectors) is Windows Vista default. * use optimal_io_size, minimal_io_size or 1MiB as a grain for partitions alignment Note that this all is used when DOS-compatible mode is disabled. Signed-off-by: Karel Zak --- fdisk/fdisk.c | 87 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 21 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 9fd9bd9d..dc5dfb9d 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -215,6 +215,7 @@ unsigned long long sector_offset = 1, extended_offset = 0, sectors; unsigned int heads, cylinders, + phy_sector_size = DEFAULT_SECTOR_SIZE, sector_size = DEFAULT_SECTOR_SIZE, sector_factor = 1, user_set_sector_size = 0, @@ -222,7 +223,11 @@ unsigned int heads, display_in_cyl_units = 1; unsigned long long total_number_of_sectors; /* (!) 512-byte sectors */ -unsigned long io_size, alignment_offset; +unsigned long grain = DEFAULT_SECTOR_SIZE, + io_size = DEFAULT_SECTOR_SIZE, + min_io_size = DEFAULT_SECTOR_SIZE, + alignment_offset; +int has_topology; #define dos_label (!sun_label && !sgi_label && !aix_label && !mac_label && !osf_label) int sun_label = 0; /* looking at sun disklabel */ @@ -637,7 +642,7 @@ test_c(char **m, char *mesg) { return val; } -#define alignment_required (io_size != sector_size) +#define alignment_required (grain != sector_size) static int lba_is_aligned(unsigned long long lba) @@ -645,9 +650,9 @@ lba_is_aligned(unsigned long long lba) unsigned long long bytes, phy_sectors; bytes = lba * sector_size; - phy_sectors = bytes / io_size; + phy_sectors = bytes / phy_sector_size; - return (alignment_offset + (phy_sectors * io_size) == bytes); + return (alignment_offset + (phy_sectors * phy_sector_size) == bytes); } #define ALIGN_UP 1 @@ -659,14 +664,16 @@ align_lba(unsigned long long lba, int direction) { unsigned long long sects_in_phy, res; - if (lba_is_aligned(lba)) - return lba; + sects_in_phy = grain / sector_size; - sects_in_phy = io_size / sector_size; + if (lba == sector_offset) + res = lba; /* the offset should be aligned */ - if (lba < sects_in_phy) - /* align to the first physical sector */ - res = sects_in_phy; + else if (lba < sects_in_phy) + res = sects_in_phy; /* align to the first physical sector */ + + else if (lba % sects_in_phy == 0) + res = lba; /* already aligned to the grain */ else if (direction == ALIGN_UP) res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy; @@ -677,7 +684,7 @@ align_lba(unsigned long long lba, int direction) else /* ALIGN_NEAREST */ res = ((lba + sects_in_phy/2) / sects_in_phy) * sects_in_phy; - if (alignment_offset) + if (alignment_offset && res > alignment_offset / sector_size) /* * apply alignment_offset * @@ -685,11 +692,16 @@ align_lba(unsigned long long lba, int direction) * at LBA < 0 (usually LBA -1). It means we have to move LBA * according the offset to be on the physical boundary. */ - res -= (io_size - alignment_offset) / sector_size; - - /* fprintf(stderr, "LBA %llu -align-> %llu (%s)\n", lba, res, - * lba_is_aligned(res) ? "OK" : "FALSE"); - */ + res -= (phy_sector_size - alignment_offset) / sector_size; + + /*** + fprintf(stderr, "LBA %llu --align-(%s)--> %llu (%s)\n", + lba, + direction == ALIGN_UP ? "UP " : + direction == ALIGN_DOWN ? "DOWN " : "NEAREST", + res, + lba_is_aligned(res) ? "OK" : "FALSE"); + ***/ return res; } @@ -968,10 +980,23 @@ get_topology(int fd) { blkid_topology tp = blkid_probe_get_topology(pr); if (tp) { + min_io_size = blkid_topology_get_minimum_io_size(tp); io_size = blkid_topology_get_optimal_io_size(tp); - if (!io_size) - io_size = blkid_topology_get_minimum_io_size(tp); + phy_sector_size = blkid_topology_get_physical_sector_size(tp); alignment_offset = blkid_topology_get_alignment_offset(tp); + + /* We assume that the device provides topology info if + * optimal_io_size is set or alignment_offset is set or + * minimum_io_size is not power of 2. + * + * See also update_sector_offset(). + */ + if (io_size || alignment_offset || + (min_io_size & (min_io_size - 1))) + has_topology = 1; + if (!io_size) + /* optimal IO is optional, default to minimum IO */ + io_size = min_io_size; } } blkid_free_probe(pr); @@ -1041,15 +1066,35 @@ get_partition_table_geometry(void) { void update_sector_offset(void) { + grain = io_size; + if (dos_compatible_flag) sector_offset = sectors; /* usually 63 sectors */ else { /* - * Align the begin of the first partition to the physical block + * Align the begin of partitions to: + * + * a) topology + * a2) alignment offset + * a1) or physical sector (minimal_io_size, aka "grain") + * + * b) or default to 1MiB (2048 sectrors, Windows Vista default) + * + * c) or for very small devices use 1 phy.sector (small device = + * device where the offset is quarter of of whole size + * of the device). */ - unsigned long long x = io_size / sector_size; + unsigned long long x; + + if (has_topology) + x = alignment_offset ? alignment_offset : io_size; + else + x = grain = 2048 * 512; + + sector_offset = x / sector_size; - sector_offset = align_lba(x, ALIGN_UP); + if (total_number_of_sectors <= sector_offset * 4) + sector_offset = phy_sector_size / sector_size; } } -- cgit v1.2.3 From 7ded5afc571b39ba15cf9f649506a986b00c1af1 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 9 Feb 2010 11:06:42 +0100 Subject: fdisk: fix default first sector The previous release 2.17 introduces aligned defaults for the first and last sectors on the partition. Unfortunately, there is endless loop when the code looks for first unused aligned sector. Signed-off-by: Karel Zak --- fdisk/fdisk.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index dc5dfb9d..ddfd24d1 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -2309,17 +2309,16 @@ add_partition(int n, int sys) { snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); do { - unsigned long long dflt, dflt_tmp; + unsigned long long dflt, aligned; temp = start; - dflt = start = get_unused_start(n, start, first, last); /* the default sector should be aligned and unused */ do { - dflt_tmp = align_lba_in_range(dflt, start, limit); - dflt = get_unused_start(n, dflt_tmp, first, last); - } while (dflt != dflt_tmp && dflt > dflt_tmp && dflt < limit); + aligned = align_lba_in_range(dflt, dflt, limit); + dflt = get_unused_start(n, aligned, first, last); + } while (dflt != aligned && dflt > aligned && dflt < limit); if (dflt >= limit) dflt = start; -- cgit v1.2.3 From a8a86a1c5e13d64a668c6b4347addc61be24b54b Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 4 Feb 2010 15:02:16 +0100 Subject: fdisk: cleanup warnings * don't print: The number of cylinders for this disk is set to 12161. There is nothing wrong with that, but this is larger than 1024, and could in certain setups cause problems with: 1) software that runs at boot time (e.g., old versions of LILO) 2) booting and partitioning software from other OSs (e.g., DOS FDISK, OS/2 FDISK) we really don't care about MS-DOS or extremely old LILO. * inform users that DOS-compatible mode is bad and deprecated thing (It's difficult to use 2048 sectors grain or 4KiB sectors or alignment_offset in DOS mode where all is based on cylinders...) * don't check for cylinders boundary in non-DOS mode * inform about sector and I/O sizes Signed-off-by: Karel Zak --- fdisk/fdisk.c | 60 +++++++++++++++++++++++------------------------------------ 1 file changed, 23 insertions(+), 37 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index ddfd24d1..c1868c01 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -753,19 +753,6 @@ void update_units(void) units_per_sector = 1; /* in sectors */ } -static void -warn_cylinders(void) { - if (dos_label && cylinders > 1024 && !nowarn) - fprintf(stderr, _("\n" -"The number of cylinders for this disk is set to %d.\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" -"2) booting and partitioning software from other OSs\n" -" (e.g., DOS FDISK, OS/2 FDISK)\n"), - cylinders); -} - static void warn_limits(void) { if (total_number_of_sectors > UINT_MAX && !nowarn) { @@ -786,29 +773,26 @@ warn_limits(void) { static void warn_alignment(void) { - if (nowarn || !alignment_required) + if (nowarn) return; - fprintf(stderr, _("\n" + if (sector_size != phy_sector_size) + fprintf(stderr, _("\n" "The device presents a logical sector size that is smaller than\n" -"the optimal I/O size (often physical sector size). Aligning to a optimal\n" -"I/O size boundary is recommended, or performance may be impacted.\n\n")); - - /* - * Print warning when sector_offset is not aligned for DOS mode - */ - if (alignment_offset == 0 && dos_compatible_flag && - !lba_is_aligned(sector_offset)) +"the physical sector size. Aligning to a physical sector (or optimal\n" +"I/O) size boundary is recommended, or performance may be impacted.\n")); - fprintf(stderr, _( -"WARNING: The device does not provide compensation (alignment_offset)\n" -"for DOS-compatible partitioning, but DOS-compatible mode is enabled.\n" -"Use command 'c' to switch-off DOS mode.\n\n")); - - if (display_in_cyl_units) - fprintf(stderr, _( -"It's recommended to change display units to sectors (command 'u').\n\n")); + if (dos_compatible_flag) { + fprintf(stderr, _("\n" +"WARNING: DOS-compatible mode is deprecated. It's strongly recommended to\n" +" switch off the mode (command 'c')")); + if (display_in_cyl_units) + fprintf(stderr, _(" and change display units to\n" +" sectors (command 'u').\n")); + else + fprintf(stderr, ".\n"); + } } static void @@ -1285,7 +1269,6 @@ got_dos_table: } } - warn_cylinders(); warn_geometry(); warn_limits(); warn_alignment(); @@ -1787,6 +1770,9 @@ static void check_consistency(struct partition *p, int partition) { unsigned int lbc, lbh, lbs; /* logical beginning c, h, s */ unsigned int lec, leh, les; /* logical ending c, h, s */ + if (!dos_compatible_flag) + return; + if (!heads || !sectors || (partition >= 4)) return; /* do not check extended partitions */ @@ -1848,7 +1834,7 @@ static void check_alignment(unsigned long long lba, int partition) { if (!lba_is_aligned(lba)) - printf(_("Partition %i does not start on optimal I/O size boundary.\n"), + printf(_("Partition %i does not start on physical sector boundary.\n"), partition + 1); } @@ -1875,8 +1861,10 @@ list_disk_geometry(void) { str_units(PLURAL), units_per_sector, sector_size, units_per_sector * sector_size); - printf(_("Sector size (logical / optimal IO): %u bytes / %lu bytes\n"), - sector_size, io_size); + printf(_("Sector size (logical/physical): %u bytes / %u bytes\n"), + sector_size, phy_sector_size); + printf(_("I/O size (minimum/optimal): %lu bytes / %lu bytes\n"), + min_io_size, io_size); if (alignment_offset) printf(_("Alignment offset: %lu bytes\n"), alignment_offset); if (dos_label) @@ -2667,8 +2655,6 @@ xselect(void) { _("Number of cylinders")); if (sun_label) sun_set_ncyl(cylinders); - if (dos_label) - warn_cylinders(); break; case 'd': print_raw(); -- cgit v1.2.3 From f4bf2458f608b639cfa5ff6f0bfe836bcdf81a9c Mon Sep 17 00:00:00 2001 From: Francesco Cosoleto Date: Wed, 10 Feb 2010 12:42:26 +0100 Subject: cfdisk: set '[Quit]' as default menu item on first run instead of '[Bootable]'. Signed-off-by: Francesco Cosoleto --- fdisk/cfdisk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fdisk') diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c index eaf766c8..f871cc46 100644 --- a/fdisk/cfdisk.c +++ b/fdisk/cfdisk.c @@ -2584,6 +2584,7 @@ static void do_curses_fdisk(void) { int done = FALSE; char command; + int is_first_run = TRUE; static struct MenuItem menuMain[] = { { 'b', N_("Bootable"), N_("Toggle bootable flag of the current partition") }, @@ -2630,12 +2631,13 @@ do_curses_fdisk(void) { } else if (p_info[cur_part].id > 0) { s = ((opentype == O_RDWR) ? "bdhmpqtuW" : "bdhmpqtu"); command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10, - s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0); + s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, is_first_run ? 7 : 0); } else { s = ((opentype == O_RDWR) ? "hpquW" : "hpqu"); command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10, s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0); } + is_first_run = FALSE; switch ( command ) { case 'B': case 'b': -- cgit v1.2.3 From 7929b548cc8ea8d4ec1ba8668954b79708195ad9 Mon Sep 17 00:00:00 2001 From: Francesco Cosoleto Date: Fri, 12 Feb 2010 18:51:29 +0100 Subject: cfdisk: set '[New]' as default item on menu for non allocated space instead of '[Help]'. Signed-off-by: Francesco Cosoleto --- fdisk/cfdisk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fdisk') diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c index f871cc46..8de285b4 100644 --- a/fdisk/cfdisk.c +++ b/fdisk/cfdisk.c @@ -2627,7 +2627,7 @@ do_curses_fdisk(void) { if (p_info[cur_part].id == FREE_SPACE) { s = ((opentype == O_RDWR) ? "hnpquW" : "hnpqu"); command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10, - s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0); + s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 5); } else if (p_info[cur_part].id > 0) { s = ((opentype == O_RDWR) ? "bdhmpqtuW" : "bdhmpqtu"); command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10, -- cgit v1.2.3 From 99bdcd5fbded1d41c714223b608e6f1953561f39 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 12 Feb 2010 21:43:03 +0100 Subject: fdisk: use more elegant way to count and check alignment Signed-off-by: Karel Zak --- fdisk/fdisk.c | 67 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index c1868c01..affea090 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -215,7 +215,6 @@ unsigned long long sector_offset = 1, extended_offset = 0, sectors; unsigned int heads, cylinders, - phy_sector_size = DEFAULT_SECTOR_SIZE, sector_size = DEFAULT_SECTOR_SIZE, sector_factor = 1, user_set_sector_size = 0, @@ -226,6 +225,7 @@ unsigned long long total_number_of_sectors; /* (!) 512-byte sectors */ unsigned long grain = DEFAULT_SECTOR_SIZE, io_size = DEFAULT_SECTOR_SIZE, min_io_size = DEFAULT_SECTOR_SIZE, + phy_sector_size = DEFAULT_SECTOR_SIZE, alignment_offset; int has_topology; @@ -647,12 +647,10 @@ test_c(char **m, char *mesg) { static int lba_is_aligned(unsigned long long lba) { - unsigned long long bytes, phy_sectors; + unsigned int granularity = max(phy_sector_size, min_io_size); + unsigned long long offset = (lba << 9) & (granularity - 1); - bytes = lba * sector_size; - phy_sectors = bytes / phy_sector_size; - - return (alignment_offset + (phy_sectors * phy_sector_size) == bytes); + return !((granularity + alignment_offset - offset) & (granularity - 1)); } #define ALIGN_UP 1 @@ -662,41 +660,44 @@ lba_is_aligned(unsigned long long lba) static unsigned long long align_lba(unsigned long long lba, int direction) { - unsigned long long sects_in_phy, res; - - sects_in_phy = grain / sector_size; - - if (lba == sector_offset) - res = lba; /* the offset should be aligned */ + unsigned long long res; - else if (lba < sects_in_phy) - res = sects_in_phy; /* align to the first physical sector */ + if (lba_is_aligned(lba)) + res = lba; + else { + unsigned long long sects_in_phy = grain / sector_size; - else if (lba % sects_in_phy == 0) - res = lba; /* already aligned to the grain */ + if (lba < sector_offset) + res = sector_offset; - else if (direction == ALIGN_UP) - res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy; + else if (direction == ALIGN_UP) + res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy; - else if (direction == ALIGN_DOWN) - res = (lba / sects_in_phy) * sects_in_phy; + else if (direction == ALIGN_DOWN) + res = (lba / sects_in_phy) * sects_in_phy; - else /* ALIGN_NEAREST */ - res = ((lba + sects_in_phy/2) / sects_in_phy) * sects_in_phy; + else /* ALIGN_NEAREST */ + res = ((lba + sects_in_phy / 2) / sects_in_phy) * sects_in_phy; - if (alignment_offset && res > alignment_offset / sector_size) - /* - * apply alignment_offset - * - * On disk with alignment compensation physical blocks start - * at LBA < 0 (usually LBA -1). It means we have to move LBA - * according the offset to be on the physical boundary. - */ - res -= (phy_sector_size - alignment_offset) / sector_size; + if (alignment_offset && !lba_is_aligned(res) && + res > alignment_offset / sector_size) { + /* + * apply alignment_offset + * + * On disk with alignment compensation physical blocks starts + * at LBA < 0 (usually LBA -1). It means we have to move LBA + * according the offset to be on the physical boundary. + */ + /* fprintf(stderr, "LBA: %llu apply alignment_offset\n", res); */ + res -= (max(phy_sector_size, min_io_size) - + alignment_offset) / sector_size; + } + } /*** - fprintf(stderr, "LBA %llu --align-(%s)--> %llu (%s)\n", + fprintf(stderr, "LBA %llu (%s) --align-(%s)--> %llu (%s)\n", lba, + lba_is_aligned(lba) ? "OK" : "FALSE", direction == ALIGN_UP ? "UP " : direction == ALIGN_DOWN ? "DOWN " : "NEAREST", res, @@ -1861,7 +1862,7 @@ list_disk_geometry(void) { str_units(PLURAL), units_per_sector, sector_size, units_per_sector * sector_size); - printf(_("Sector size (logical/physical): %u bytes / %u bytes\n"), + printf(_("Sector size (logical/physical): %u bytes / %lu bytes\n"), sector_size, phy_sector_size); printf(_("I/O size (minimum/optimal): %lu bytes / %lu bytes\n"), min_io_size, io_size); -- cgit v1.2.3 From 3b19e88dab4d4e5b969eb63fdf26f642dbb4bdcf Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Feb 2010 10:08:03 +0100 Subject: fdisk: cleanup help, add -h option Signed-off-by: Karel Zak --- fdisk/fdisk.8 | 5 +++++ fdisk/fdisk.c | 55 ++++++++++++++++++++++--------------------------------- fdisk/fdisk.h | 2 +- 3 files changed, 28 insertions(+), 34 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.8 b/fdisk/fdisk.8 index c04972f6..2d93f1f8 100644 --- a/fdisk/fdisk.8 +++ b/fdisk/fdisk.8 @@ -25,6 +25,8 @@ fdisk \- Partition table manipulator for Linux .IR partition ... .sp .B fdisk \-v +.sp +.B fdisk \-h .SH DESCRIPTION Hard disks can be divided into one or more logical disks called .IR partitions . @@ -182,6 +184,9 @@ Specify the sector size of the disk. Valid values are 512, 1024, 2048 or 4096. (Recent kernels know the sector size. Use this only on old kernels or to override the kernel's ideas.) .TP +.BI \-h +Print help and then exit. +.TP .BI "\-C " cyls Specify the number of cylinders of the disk. I have no idea why anybody would want to do so. diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index affea090..0a402bb4 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -242,6 +242,7 @@ jmp_buf listingbuf; void fatal(enum failure why) { char error[LINE_LENGTH], *message = error; + int rc = EXIT_FAILURE; if (listing) { close(fd); @@ -249,25 +250,22 @@ void fatal(enum failure why) { } switch (why) { + case help: + rc = EXIT_SUCCESS; case usage: message = _( -"Usage: fdisk [-b SSZ] [-u] DISK Change partition table\n" -" fdisk -l [-b SSZ] [-u] DISK List partition table(s)\n" -" fdisk -s PARTITION Give partition size(s) in blocks\n" -" fdisk -v Give fdisk version\n" -"Here DISK is something like /dev/hdb or /dev/sda\n" -"and PARTITION is something like /dev/hda7\n" -"-u: give Start and End in sector (instead of cylinder) units\n" -"-b 2048: (for certain MO disks) use 2048-byte sectors\n"); - break; - case usage2: - /* msg in cases where fdisk used to probe */ - message = _( -"Usage: fdisk [-l] [-b SSZ] [-u] device\n" -"E.g.: fdisk /dev/hda (for the first IDE disk)\n" -" or: fdisk /dev/sdc (for the third SCSI disk)\n" -" or: fdisk /dev/eda (for the first PS/2 ESDI drive)\n" -" or: fdisk /dev/rd/c0d0 or: fdisk /dev/ida/c0d0 (for RAID devices)\n" -" ...\n"); +"Usage:\n" +" fdisk [options] change partition table\n" +" fdisk [options] -l list partition table(s)\n" +" fdisk -s give partition size(s) in blocks\n" +"\nOptions:\n" +" -b sector size (512, 1024, 2048 or 4096)\n" +" -h print help\n" +" -u give sizes in sectors instead of cylinders\n" +" -v print version\n" +" -C specify the number of cylinders\n" +" -H specify the number of heads\n" +" -S specify the number of sectors per track\n" +"\n"); break; case unable_to_open: snprintf(error, sizeof(error), @@ -299,7 +297,7 @@ void fatal(enum failure why) { fputc('\n', stderr); fputs(message, stderr); - exit(1); + exit(rc); } static void @@ -2852,17 +2850,7 @@ main(int argc, char **argv) { bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - /* - * Calls: - * fdisk -v - * fdisk -l [-b sectorsize] [-u] device ... - * fdisk -s [partition] ... - * fdisk [-b sectorsize] [-u] device - * - * Options -C, -H, -S set the geometry. - * - */ - while ((c = getopt(argc, argv, "b:C:H:lsS:uvV")) != -1) { + while ((c = getopt(argc, argv, "b:C:hH:lsS:uvV")) != -1) { switch (c) { case 'b': /* Ugly: this sector size is really per device, @@ -2879,6 +2867,9 @@ main(int argc, char **argv) { case 'C': user_cylinders = atoi(optarg); break; + case 'h': + fatal(help); + break; case 'H': user_heads = atoi(optarg); if (user_heads <= 0 || user_heads > 256) @@ -2964,10 +2955,8 @@ main(int argc, char **argv) { if (argc-optind == 1) disk_device = argv[optind]; - else if (argc-optind != 0) - fatal(usage); else - fatal(usage2); + fatal(usage); gpt_warning(disk_device); get_boot(fdisk); diff --git a/fdisk/fdisk.h b/fdisk/fdisk.h index 0286ce0a..1a89beb9 100644 --- a/fdisk/fdisk.h +++ b/fdisk/fdisk.h @@ -45,7 +45,7 @@ struct partition { unsigned char size4[4]; /* nr of sectors in partition */ } PACKED; -enum failure {usage, usage2, ioctl_error, +enum failure {help, usage, ioctl_error, unable_to_open, unable_to_read, unable_to_seek, unable_to_write, out_of_memory}; -- cgit v1.2.3 From e57fb0dec057be41530dc51436f470a5310ea9c9 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Feb 2010 13:29:04 +0100 Subject: fdisk: fallback for topology values Signed-off-by: Karel Zak --- fdisk/fdisk.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 0a402bb4..655bf0c6 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -990,8 +990,12 @@ get_topology(int fd) { else if (blkdev_get_sector_size(fd, &arg) == 0) sector_size = arg; + if (!phy_sector_size) + phy_sector_size = sector_size; + if (!min_io_size) + min_io_size = phy_sector_size; if (!io_size) - io_size = sector_size; + io_size = min_io_size; if (sector_size != DEFAULT_SECTOR_SIZE) printf(_("Note: sector size is %d (not %d)\n"), -- cgit v1.2.3 From d42ef322d04dbd7618455364b6c38c0150e40804 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Feb 2010 14:06:56 +0100 Subject: fdisk: fix ALIGN_UP Signed-off-by: Karel Zak --- fdisk/fdisk.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 655bf0c6..55caa0c2 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -689,6 +689,9 @@ align_lba(unsigned long long lba, int direction) /* fprintf(stderr, "LBA: %llu apply alignment_offset\n", res); */ res -= (max(phy_sector_size, min_io_size) - alignment_offset) / sector_size; + + if (direction == ALIGN_UP && res < lba) + res += sects_in_phy; } } -- cgit v1.2.3 From 78498b7b90cfae7d45912a3c3f80cfca57df95ec Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Feb 2010 14:39:30 +0100 Subject: fdisk: add -c option (switch off DOS mode) * add -c to allows to switch off DOS mode from command line * recommend sectors (command 'u' or option -u) Signed-off-by: Karel Zak --- fdisk/fdisk.8 | 5 ++++- fdisk/fdisk.c | 13 +++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.8 b/fdisk/fdisk.8 index 2d93f1f8..367837d9 100644 --- a/fdisk/fdisk.8 +++ b/fdisk/fdisk.8 @@ -6,7 +6,7 @@ fdisk \- Partition table manipulator for Linux .SH SYNOPSIS .B fdisk -.RB [ \-u ] +.RB [ \-uc ] .RB [ \-b .IR sectorsize ] .RB [ \-C @@ -187,6 +187,9 @@ to override the kernel's ideas.) .BI \-h Print help and then exit. .TP +.BI \-c +Switch off DOS-compatible mode. (Recommended) +.TP .BI "\-C " cyls Specify the number of cylinders of the disk. I have no idea why anybody would want to do so. diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 55caa0c2..b752d9b9 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -259,6 +259,7 @@ void fatal(enum failure why) { " fdisk -s give partition size(s) in blocks\n" "\nOptions:\n" " -b sector size (512, 1024, 2048 or 4096)\n" +" -c switch off DOS-compatible mode\n" " -h print help\n" " -u give sizes in sectors instead of cylinders\n" " -v print version\n" @@ -794,7 +795,12 @@ warn_alignment(void) { " sectors (command 'u').\n")); else fprintf(stderr, ".\n"); - } + + } else if (display_in_cyl_units) + fprintf(stderr, _("\n" +"WARNING: cylinders as display units are deprecated. Use command 'u' to\n" +" change units to sectors.\n")); + } static void @@ -2857,7 +2863,7 @@ main(int argc, char **argv) { bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - while ((c = getopt(argc, argv, "b:C:hH:lsS:uvV")) != -1) { + while ((c = getopt(argc, argv, "b:cC:hH:lsS:uvV")) != -1) { switch (c) { case 'b': /* Ugly: this sector size is really per device, @@ -2874,6 +2880,9 @@ main(int argc, char **argv) { case 'C': user_cylinders = atoi(optarg); break; + case 'c': + dos_compatible_flag = 0; + break; case 'h': fatal(help); break; -- cgit v1.2.3 From 9b15ea8048110dcfea8fff5e1acf5321fb737f51 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Feb 2010 15:55:22 +0100 Subject: fdisk: use 1MiB offset and grain always when possible It would be nice to minimize dependence between the disk layout and disk topology. We have to follow disk topology for alignment_offset and huge (> 1MiB) I/O sizes only. For all others disks we can use 1MiB grain and 1MiB offset. Reported-by: "H. Peter Anvin" Signed-off-by: Karel Zak --- fdisk/fdisk.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index b752d9b9..196f76d4 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -1080,17 +1080,26 @@ update_sector_offset(void) * device where the offset is quarter of of whole size * of the device). */ - unsigned long long x; + unsigned long long x = 0; - if (has_topology) - x = alignment_offset ? alignment_offset : io_size; - else - x = grain = 2048 * 512; + if (has_topology) { + if (alignment_offset) + x = alignment_offset; + else if (io_size > 2048 * 512) + x = io_size; + } + /* default to 1MiB */ + if (!x) + x = 2048 * 512; sector_offset = x / sector_size; if (total_number_of_sectors <= sector_offset * 4) sector_offset = phy_sector_size / sector_size; + + /* use 1MiB grain always when possible */ + if (grain < 2048 * 512) + grain = 2048 * 512; } } -- cgit v1.2.3 From a47e839cd7b5e3c032c3a6b8a96343d3ab8e1906 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Feb 2010 16:46:05 +0100 Subject: fdisk: don't use 1MiB grain on small devices Signed-off-by: Karel Zak --- fdisk/fdisk.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 196f76d4..09efd1cc 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -1076,9 +1076,7 @@ update_sector_offset(void) * * b) or default to 1MiB (2048 sectrors, Windows Vista default) * - * c) or for very small devices use 1 phy.sector (small device = - * device where the offset is quarter of of whole size - * of the device). + * c) or for very small devices use 1 phy.sector */ unsigned long long x = 0; @@ -1094,12 +1092,17 @@ update_sector_offset(void) sector_offset = x / sector_size; + /* don't use huge offset on small devices */ if (total_number_of_sectors <= sector_offset * 4) sector_offset = phy_sector_size / sector_size; /* use 1MiB grain always when possible */ if (grain < 2048 * 512) grain = 2048 * 512; + + /* don't use huge grain on small devices */ + if (total_number_of_sectors <= (grain * 4 / sector_size)) + grain = phy_sector_size; } } -- cgit v1.2.3 From 5ac78ead3c02660a894ca7e7a4887ce80ebe2b50 Mon Sep 17 00:00:00 2001 From: "Bryn M. Reeves" Date: Thu, 18 Feb 2010 21:39:22 +0100 Subject: sfdisk: make sure writes make it to disk in write_partitions() Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=565946 Signed-off-by: Bryn M. Reeves Signed-off-by: Karel Zak --- fdisk/sfdisk.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fdisk') diff --git a/fdisk/sfdisk.c b/fdisk/sfdisk.c index 6ac91f07..6432b25c 100644 --- a/fdisk/sfdisk.c +++ b/fdisk/sfdisk.c @@ -1637,6 +1637,11 @@ write_partitions(char *dev, int fd, struct disk_desc *z) { error(_("Failed writing the partition on %s\n"), dev); return 0; } + if (fsync(fd)) { + perror(dev); + error(_("Failed writing the partition on %s\n"), dev); + return 0; + } return 1; } -- cgit v1.2.3 From aae63de9efd5e7643edf1180f7055bef22f1ebc3 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 19 Feb 2010 16:11:49 +0100 Subject: fdisk: swap VTOC values for warning messages Signed-off-by: Karel Zak --- fdisk/fdisksunlabel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c index 670a15a5..fad9d4f3 100644 --- a/fdisk/fdisksunlabel.c +++ b/fdisk/fdisksunlabel.c @@ -146,17 +146,17 @@ int check_sun_label(void) if (sunlabel->version != SSWAP32(SUN_LABEL_VERSION)) { fprintf(stderr,_("Detected sun disklabel with wrong version [0x%08x].\n"), - sunlabel->version); + SSWAP32(sunlabel->version)); need_fixing = 1; } if (sunlabel->sanity != SSWAP32(SUN_LABEL_SANE)) { fprintf(stderr,_("Detected sun disklabel with wrong sanity [0x%08x].\n"), - sunlabel->sanity); + SSWAP32(sunlabel->sanity)); need_fixing = 1; } if (sunlabel->num_partitions != SSWAP16(SUN_NUM_PARTITIONS)) { fprintf(stderr,_("Detected sun disklabel with wrong num_partitions [%u].\n"), - sunlabel->num_partitions); + SSWAP16(sunlabel->num_partitions)); need_fixing = 1; } if (need_fixing) { -- cgit v1.2.3 From 4d6cb488084388c90f3f45a0eaf3db83c764e0fb Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 26 Feb 2010 16:06:18 +0100 Subject: fdisk: fix 'p' output for sun label Signed-off-by: Karel Zak --- TODO | 5 +++++ fdisk/fdisksunlabel.c | 18 +++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'fdisk') diff --git a/TODO b/TODO index d802bfb8..b9786f92 100644 --- a/TODO +++ b/TODO @@ -39,6 +39,11 @@ wipefs fdisk(s) -------- + * Sun label support is completely useless for large disks, it uses number of + cylinders from on-disk-label where the geometry is stored by int16 values. + It seems better to completely ignore this stuff from the label and always + use geometry + BLKGETSIZE64 from kernel. + * use off_t instead "long long" * catch SIGINT (Ctrl-C) and return to main menu. diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c index fad9d4f3..68596eea 100644 --- a/fdisk/fdisksunlabel.c +++ b/fdisk/fdisksunlabel.c @@ -186,8 +186,8 @@ void create_sunlabel(void) { struct hd_geometry geometry; unsigned long long llsectors, llcyls; - unsigned int ndiv; - int res, sec_fac; + unsigned int ndiv, sec_fac; + int res; fprintf(stderr, _("Building a new sun disklabel. Changes will remain in memory only,\n" @@ -573,8 +573,8 @@ void sun_list_table(int xtra) w = strlen(disk_device); if (xtra) printf( - _("\nDisk %s (Sun disk label): %d heads, %llu sectors, %d rpm\n" - "%d cylinders, %d alternate cylinders, %d physical cylinders\n" + _("\nDisk %s (Sun disk label): %u heads, %llu sectors, %d rpm\n" + "%u cylinders, %d alternate cylinders, %d physical cylinders\n" "%d extra sects/cyl, interleave %d:1\n" "Label ID: %s\n" "Volume ID: %s\n" @@ -589,7 +589,7 @@ void sun_list_table(int xtra) str_units(PLURAL), units_per_sector); else printf( - _("\nDisk %s (Sun disk label): %d heads, %llu sectors, %d cylinders\n" + _("\nDisk %s (Sun disk label): %u heads, %llu sectors, %u cylinders\n" "Units = %s of %d * 512 bytes\n\n"), disk_device, heads, sectors, cylinders, str_units(PLURAL), units_per_sector); @@ -604,13 +604,13 @@ void sun_list_table(int xtra) uint32_t start = SSWAP32(part->start_cylinder) * heads * sectors; uint32_t len = SSWAP32(part->num_sectors); printf( - "%s %c%c %9ld %9ld %9ld%c %2x %s\n", + "%s %c%c %9lu %9lu %9lu%c %2x %s\n", /* device */ partname(disk_device, i+1, w), /* flags */ (tag->flag & SSWAP16(SUN_FLAG_UNMNT)) ? 'u' : ' ', (tag->flag & SSWAP16(SUN_FLAG_RONLY)) ? 'r' : ' ', -/* start */ (long) scround(start), -/* end */ (long) scround(start+len), -/* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ', +/* start */ (unsigned long) scround(start), +/* end */ (unsigned long) scround(start+len), +/* odd flag on end */ (unsigned long) len / 2, len & 1 ? '+' : ' ', /* type id */ SSWAP16(tag->tag), /* type name */ (type = partition_type(SSWAP16(tag->tag))) ? type : _("Unknown")); -- cgit v1.2.3 From b8d22034f1b393a48ce7af9e15d910bf0e29df0b Mon Sep 17 00:00:00 2001 From: Pádraig Brady Date: Tue, 9 Mar 2010 08:21:35 +0000 Subject: fdisk: correctly truncate and align translated partition names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fdisk/Makefile.am: Depend on the mbsalign module. * fdisk/fdisk.c: Align using mbsalign rather than printf. [kzak@redhat.com: - use size_t for width to fix gcc warning] Reported-by: Makoto Kato Signed-off-by: Pádraig Brady Signed-off-by: Karel Zak --- fdisk/Makefile.am | 2 +- fdisk/fdisk.c | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'fdisk') diff --git a/fdisk/Makefile.am b/fdisk/Makefile.am index 50f1dbe8..862fa016 100644 --- a/fdisk/Makefile.am +++ b/fdisk/Makefile.am @@ -3,7 +3,7 @@ include $(top_srcdir)/config/include-Makefile.am EXTRA_DIST = README.fdisk README.cfdisk sfdisk.examples partitiontype.c fdisk_common = i386_sys_types.c common.h gpt.c gpt.h \ - ../lib/blkdev.c ../lib/wholedisk.c + ../lib/blkdev.c ../lib/wholedisk.c ../lib/mbsalign.c if LINUX fdisk_common += ../lib/linux_version.c diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 09efd1cc..2a6d419f 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -25,6 +25,7 @@ #include "nls.h" #include "blkdev.h" #include "common.h" +#include "mbsalign.h" #include "fdisk.h" #include "wholedisk.h" @@ -568,9 +569,19 @@ void list_types(struct systypes *sys) i = done = 0; do { - printf("%c%2x %-15.15s", i ? ' ' : '\n', - sys[next].type, _(sys[next].name)); - next = last[i++] + done; + #define NAME_WIDTH 15 + char name[NAME_WIDTH * MB_LEN_MAX]; + size_t width = NAME_WIDTH; + + printf("%c%2x ", i ? ' ' : '\n', sys[next].type); + size_t ret = mbsalign(_(sys[next].name), name, sizeof(name), + &width, MBS_ALIGN_LEFT, 0); + if (ret == (size_t)-1 || ret >= sizeof(name)) + printf("%-15.15s", _(sys[next].name)); + else + fputs(name, stdout); + + next = last[i++] + done; if (i > 3 || next >= last[i]) { i = 0; next = ++done; -- cgit v1.2.3 From 7f152745c33567f49807019fd4f5f72eadfd4fd4 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 19 Mar 2010 15:56:27 +0100 Subject: fdisk: fix -b The old fdisk (<2.17) does not differentiate between logical and physical sector size, it uses the for everything. Now, we have logical and physical sectors size, but the -b option changes the logical size only. The second bug is that "fdisk -b " does not read topology information (it means that all I/O limits and physical sector size are 512 (default). The backwardly compatible bug fix is to override both sizes, logical and physical if "-b" is used. In future we can add a special option for physical size only. Signed-off-by: Karel Zak --- fdisk/fdisk.8 | 4 +++- fdisk/fdisk.c | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.8 b/fdisk/fdisk.8 index 367837d9..30dc9678 100644 --- a/fdisk/fdisk.8 +++ b/fdisk/fdisk.8 @@ -182,7 +182,9 @@ program and Linux partitions with the Linux fdisk or Linux cfdisk program. .BI "\-b " sectorsize Specify the sector size of the disk. Valid values are 512, 1024, 2048 or 4096. (Recent kernels know the sector size. Use this only on old kernels or -to override the kernel's ideas.) +to override the kernel's ideas.) Since util-linux-ng 2.17 fdisk differentiates +between logical and physical sector size. This option changes both sector sizes to +.IB sectorsize . .TP .BI \-h Print help and then exit. diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 2a6d419f..f5c67904 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -976,8 +976,6 @@ get_topology(int fd) { #ifdef HAVE_LIBBLKID_INTERNAL blkid_probe pr; - if (user_set_sector_size) - return; pr = blkid_new_probe(); if (pr && blkid_probe_set_device(pr, fd, 0, 0) == 0) { blkid_topology tp = blkid_probe_get_topology(pr); @@ -1006,12 +1004,20 @@ get_topology(int fd) { #endif if (user_set_sector_size) - ; - else if (blkdev_get_sector_size(fd, &arg) == 0) + /* fdisk since 2.17 differentiate between logical and physical + * sectors size. For backward compatibility the + * fdisk -b + * changes both, logical and physical sector size. + */ + phy_sector_size = sector_size; + + else if (blkdev_get_sector_size(fd, &arg) == 0) { sector_size = arg; - if (!phy_sector_size) - phy_sector_size = sector_size; + if (!phy_sector_size) + phy_sector_size = sector_size; + } + if (!min_io_size) min_io_size = phy_sector_size; if (!io_size) -- cgit v1.2.3 From 56054a79fa3c37894a9f1ab4d7b50d8b5ff82fc4 Mon Sep 17 00:00:00 2001 From: Jon Ringle Date: Thu, 25 Mar 2010 22:42:52 -0400 Subject: fdisk: replace bzero with memset Work on this was done in commit c0f19ccff73aa0ec5e9f3b61b932ea4a8bf4e6ed, however a couple of bzero call sites were missed Signed-off-by: Jon Ringle --- fdisk/fdiskbsdlabel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdiskbsdlabel.c b/fdisk/fdiskbsdlabel.c index 2f415616..9c092524 100644 --- a/fdisk/fdiskbsdlabel.c +++ b/fdisk/fdiskbsdlabel.c @@ -540,7 +540,7 @@ xbsd_write_bootstrap (void) memmove (&dl, d, sizeof (struct xbsd_disklabel)); /* The disklabel will be overwritten by 0's from bootxx anyway */ - bzero (d, sizeof (struct xbsd_disklabel)); + memset (d, 0, sizeof (struct xbsd_disklabel)); snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename); if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize], @@ -656,7 +656,7 @@ xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) { struct geom g; get_geometry (fd, &g); - bzero (d, sizeof (struct xbsd_disklabel)); + memset (d, 0, sizeof (struct xbsd_disklabel)); d -> d_magic = BSD_DISKMAGIC; -- cgit v1.2.3 From 147e1e73c9af693b025b386f68f14f08dc30a4a9 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 28 Apr 2010 10:10:39 +0200 Subject: fdisk: improve add partition dialog old version: Partition number (1-4): new version: Partition number (1-4, default 1): where the default value is the first non-used primary partition. Signed-off-by: Karel Zak --- fdisk/fdisk.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index f5c67904..f2e69dd9 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -1522,11 +1522,11 @@ read_int(unsigned int low, unsigned int dflt, unsigned int high, int -get_partition(int warn, int max) { +get_partition_dflt(int warn, int max, int dflt) { struct pte *pe; int i; - i = read_int(1, 0, max, 0, _("Partition number")) - 1; + i = read_int(1, dflt, max, 0, _("Partition number")) - 1; pe = &ptes[i]; if (warn) { @@ -1543,6 +1543,11 @@ get_partition(int warn, int max) { return i; } +int +get_partition(int warn, int max) { + return get_partition_dflt(warn, max, 0); +} + static int get_existing_partition(int warn, int max) { int pno = -1; @@ -1573,14 +1578,17 @@ static int get_nonexisting_partition(int warn, int max) { int pno = -1; int i; + int dflt = 0; for (i = 0; i < max; i++) { struct pte *pe = &ptes[i]; struct partition *p = pe->part_table; if (p && is_cleared_partition(p)) { - if (pno >= 0) + if (pno >= 0) { + dflt = pno + 1; goto not_unique; + } pno = i; } } @@ -1592,7 +1600,7 @@ get_nonexisting_partition(int warn, int max) { return -1; not_unique: - return get_partition(warn, max); + return get_partition_dflt(warn, max, dflt); } const char * -- cgit v1.2.3 From 6a2de3f13134dfd49eb93c7b15552de81b868c8a Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 28 Apr 2010 14:40:46 +0200 Subject: fdisk: improve 'move begin of partition' command The 'b' command ("move beginning of data in a partition") implementation is too restricted. For example: Device Boot Start End Blocks Id System /dev/sdb1 2048 22527 10240 83 Linux .... Partition number (1-4): 1 New beginning of data (2048-22527, default 2048): ^^^^^^^^^^ the range is defined by the current partition size. New version: Partition number (1-4): 1 New beginning of data (1-22527, default 2048): ^^^^^^^ allows to move the begin to arbitrary place if the place is not allocated by any other partition. This is useful for people who don't want to use the default partitioning (1MiB offset, 1MiB grain). The 'b' command is expert command and does not force users to use an aligned LBA (fdisk(8) still prints warning (in 'p' command) if any partition is not aligned to the physical sector boundary). Signed-off-by: Karel Zak --- fdisk/fdisk.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'fdisk') diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index f2e69dd9..0126e67b 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -2662,7 +2662,8 @@ static void move_begin(int i) { struct pte *pe = &ptes[i]; struct partition *p = pe->part_table; - unsigned int new, first; + unsigned int new, free_start, curr_start, last; + int x; if (warn_geometry()) return; @@ -2670,13 +2671,37 @@ move_begin(int i) { printf(_("Partition %d has no data area\n"), i + 1); return; } - first = get_partition_start(pe); - new = read_int(first, first, first + get_nr_sects(p) - 1, first, + + /* the default start is at the second sector of the disk or at the + * second sector of the extended partition + */ + free_start = pe->offset ? pe->offset + 1 : 1; + + curr_start = get_partition_start(pe); + + /* look for a free space before the current start of the partition */ + for (x = 0; x < partitions; x++) { + unsigned int end; + struct pte *prev_pe = &ptes[x]; + struct partition *prev_p = prev_pe->part_table; + + if (!prev_p) + continue; + end = get_partition_start(prev_pe) + get_nr_sects(prev_p); + + if (!is_cleared_partition(prev_p) && + end > free_start && end <= curr_start) + free_start = end; + } + + last = get_partition_start(pe) + get_nr_sects(p) - 1; + + new = read_int(free_start, curr_start, last, free_start, _("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); + unsigned int sects = get_nr_sects(p) + get_start_sect(p) - new; + set_nr_sects(p, sects); set_start_sect(p, new); pe->changed = 1; } -- cgit v1.2.3 From 5f94ca33cf7772e0c36b5b3e5b1cf1ab01f60180 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 7 May 2010 14:12:26 +0200 Subject: cfdisk: support non-ascii characters in input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Sat, Apr 03, 2010 at 12:58:48PM +0000, Jorge wrote: > When you want to write changes to disk you're asked for a > confirmation, like this one: > > Are you sure you want to write the partition table to disk? (yes > or no) > > There is no problem on the English version, but when you launch the > program in Spanish you get this: > > ¿Está seguro de que desea escribir la tabla de particiones en el > disco? > (sí o no): > > You can't type the "í" character. Trying to do so will end in no > input at all. That is, typing in my keyboard "´" then "i" leads to > nothing. So you can't write changes to disk, and you must launch the > program in English for it to operate. Reported-by: Jorge Addresses: https://bugs.launchpad.net/ubuntu/+source/util-linux/+bug/205327 Signed-off-by: Karel Zak --- fdisk/Makefile.am | 2 +- fdisk/cfdisk.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++-------- include/mbsalign.h | 8 +++++--- lib/mbsalign.c | 34 +++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 12 deletions(-) (limited to 'fdisk') diff --git a/fdisk/Makefile.am b/fdisk/Makefile.am index 862fa016..7b87d6cf 100644 --- a/fdisk/Makefile.am +++ b/fdisk/Makefile.am @@ -53,7 +53,7 @@ endif if USE_SLANG sbin_PROGRAMS += cfdisk dist_man_MANS += cfdisk.8 -cfdisk_SOURCES = cfdisk.c $(fdisk_common) +cfdisk_SOURCES = cfdisk.c $(fdisk_common) ../lib/mbsalign.c cfdisk_CFLAGS = $(cflags_blkid) cfdisk_LDADD = -lslang $(ldadd_blkid) else diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c index 8de285b4..b1eaceeb 100644 --- a/fdisk/cfdisk.c +++ b/fdisk/cfdisk.c @@ -83,11 +83,16 @@ #include #endif +#ifdef HAVE_WIDECHAR +#include +#endif + #include "nls.h" #include "blkdev.h" #include "xstrncpy.h" #include "common.h" #include "gpt.h" +#include "mbsalign.h" #ifdef __GNU__ #define DEFAULT_DEVICE "/dev/hd0" @@ -407,10 +412,10 @@ fdexit(int ret) { static int get_string(char *str, int len, char *def) { - unsigned char c; - int i = 0; - int x, y; + size_t cells = 0, i = 0; + int x, y, key; int use_def = FALSE; + wint_t c; getyx(stdscr, y, x); clrtoeol(); @@ -424,7 +429,13 @@ get_string(char *str, int len, char *def) { } refresh(); + +#if defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR) + while ((key = get_wch(&c)) != ERR && + c != '\r' && c != '\n' && c != KEY_ENTER) { +#else while ((c = getch()) != '\n' && c != CR) { +#endif switch (c) { case ESC: move(y, x); @@ -433,10 +444,14 @@ get_string(char *str, int len, char *def) { return GS_ESCAPE; case DEL: case '\b': + case KEY_BACKSPACE: if (i > 0) { - str[--i] = 0; - mvaddch(y, x+i, ' '); - move(y, x+i); + cells--; + i = mbs_truncate(str, &cells); + if (i < 0) + return GS_ESCAPE; + mvaddch(y, x + cells, ' '); + move(y, x + cells); } else if (use_def) { clrtoeol(); use_def = FALSE; @@ -444,15 +459,39 @@ get_string(char *str, int len, char *def) { putchar(BELL); break; default: +#if defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR) + if (i < len && iswprint(c)) { + wchar_t wc = (wchar_t) c; + char s[MB_CUR_MAX + 1]; + int sz = wctomb(s, wc); + + if (sz + i < len) { + s[sz] = '\0'; + mvaddnstr(y, x + cells, s, sz); + if (use_def) { + clrtoeol(); + use_def = FALSE; + } + memcpy(str + i, s, sz); + i += sz; + str[i] = '\0'; + cells += wcwidth(wc); + } else + putchar(BELL); + } +#else if (i < len && isprint(c)) { - mvaddch(y, x+i, c); + mvaddch(y, x + cells, c); if (use_def) { clrtoeol(); use_def = FALSE; } str[i++] = c; str[i] = 0; - } else + cells++; + } +#endif + else putchar(BELL); } refresh(); diff --git a/include/mbsalign.h b/include/mbsalign.h index b8a588c2..fd957b39 100644 --- a/include/mbsalign.h +++ b/include/mbsalign.h @@ -38,6 +38,8 @@ enum { #endif }; -size_t -mbsalign (const char *src, char *dest, size_t dest_size, - size_t *width, mbs_align_t align, int flags); +extern size_t mbs_truncate(char *str, size_t *width); + +extern size_t mbsalign (const char *src, char *dest, + size_t dest_size, size_t *width, + mbs_align_t align, int flags); diff --git a/lib/mbsalign.c b/lib/mbsalign.c index c1a5472e..82ffc09c 100644 --- a/lib/mbsalign.c +++ b/lib/mbsalign.c @@ -99,6 +99,40 @@ rpl_wcswidth (const wchar_t *s, size_t n) } #endif +/* Truncate multi-byte string to @width and returns number of + * bytes of the new string @str, and in @width returns number + * of cells. + */ +size_t +mbs_truncate(char *str, size_t *width) +{ + size_t bytes = strlen(str); +#ifdef HAVE_WIDECHAR + size_t sz = mbstowcs(NULL, str, 0); + wchar_t *wcs = NULL; + + if (sz == (size_t) -1) + goto done; + + wcs = malloc((sz + 1) * sizeof(wchar_t)); + if (!wcs) + goto done; + + if (!mbstowcs(wcs, str, sz)) + goto done; + *width = wc_truncate(wcs, *width); + bytes = wcstombs(str, wcs, bytes); +done: + free(wcs); +#else + if (*width < bytes) + bytes = *width; +#endif + if (bytes >= 0) + str[bytes] = '\0'; + return bytes; +} + /* Write N_SPACES space characters to DEST while ensuring nothing is written beyond DEST_END. A terminating NUL is always added to DEST. -- cgit v1.2.3