summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fdisk/fdisk.c309
-rw-r--r--fdisk/fdisk.h34
-rw-r--r--fdisk/fdiskbsdlabel.c18
-rw-r--r--fdisk/fdiskdoslabel.c75
-rw-r--r--fdisk/fdiskdoslabel.h8
-rw-r--r--fdisk/fdisksgilabel.c49
-rw-r--r--fdisk/fdisksgilabel.h4
-rw-r--r--fdisk/fdisksunlabel.c53
-rw-r--r--fdisk/fdisksunlabel.h12
-rw-r--r--fdisk/utils.c73
10 files changed, 329 insertions, 306 deletions
diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c
index 1143b2f2a..47c5d6720 100644
--- a/fdisk/fdisk.c
+++ b/fdisk/fdisk.c
@@ -47,9 +47,6 @@
#ifdef HAVE_LINUX_BLKPG_H
#include <linux/blkpg.h>
#endif
-#ifdef HAVE_LIBBLKID
-#include <blkid.h>
-#endif
#include "gpt.h"
@@ -144,19 +141,12 @@ sector_t sector_offset = 1, sectors;
unsigned int heads,
cylinders,
- sector_size = DEFAULT_SECTOR_SIZE,
user_set_sector_size = 0,
units_per_sector = 1,
display_in_cyl_units = 0;
sector_t total_number_of_sectors; /* in logical 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;
-
+unsigned long grain = DEFAULT_SECTOR_SIZE;
enum labeltype disklabel; /* Current disklabel */
static void __attribute__ ((__noreturn__)) usage(FILE *out)
@@ -318,22 +308,22 @@ test_c(char **m, char *mesg) {
}
static int
-lba_is_aligned(sector_t lba)
+lba_is_aligned(struct fdisk_context *cxt, sector_t lba)
{
- unsigned int granularity = max(phy_sector_size, min_io_size);
- sector_t offset = (lba * sector_size) & (granularity - 1);
+ unsigned int granularity = max(cxt->phy_sector_size, cxt->min_io_size);
+ sector_t offset = (lba * cxt->sector_size) & (granularity - 1);
- return !((granularity + alignment_offset - offset) & (granularity - 1));
+ return !((granularity + cxt->alignment_offset - offset) & (granularity - 1));
}
-sector_t align_lba(sector_t lba, int direction)
+sector_t align_lba(struct fdisk_context *cxt, sector_t lba, int direction)
{
sector_t res;
- if (lba_is_aligned(lba))
+ if (lba_is_aligned(cxt, lba))
res = lba;
else {
- sector_t sects_in_phy = grain / sector_size;
+ sector_t sects_in_phy = grain / cxt->sector_size;
if (lba < sector_offset)
res = sector_offset;
@@ -347,8 +337,8 @@ sector_t align_lba(sector_t lba, int direction)
else /* ALIGN_NEAREST */
res = ((lba + sects_in_phy / 2) / sects_in_phy) * sects_in_phy;
- if (alignment_offset && !lba_is_aligned(res) &&
- res > alignment_offset / sector_size) {
+ if (cxt->alignment_offset && !lba_is_aligned(cxt, res) &&
+ res > cxt->alignment_offset / cxt->sector_size) {
/*
* apply alignment_offset
*
@@ -357,8 +347,8 @@ sector_t align_lba(sector_t lba, int direction)
* 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;
+ res -= (max(cxt->phy_sector_size, cxt->min_io_size) -
+ cxt->alignment_offset) / cxt->sector_size;
if (direction == ALIGN_UP && res < lba)
res += sects_in_phy;
@@ -408,31 +398,31 @@ void update_units(void)
units_per_sector = 1; /* in sectors */
}
-void warn_limits(void)
+void warn_limits(struct fdisk_context *cxt)
{
if (total_number_of_sectors > UINT_MAX && !nowarn) {
- unsigned long long bytes = total_number_of_sectors * sector_size;
+ unsigned long long bytes = total_number_of_sectors * cxt->sector_size;
int giga = bytes / 1000000000;
int hectogiga = (giga + 50) / 100;
fprintf(stderr, _("\n"
"WARNING: The size of this disk is %d.%d TB (%llu bytes).\n"
"DOS partition table format can not be used on drives for volumes\n"
-"larger than (%llu bytes) for %d-byte sectors. Use parted(1) and GUID \n"
+"larger than (%llu bytes) for %ld-byte sectors. Use parted(1) and GUID \n"
"partition table format (GPT).\n\n"),
hectogiga / 10, hectogiga % 10,
bytes,
- (sector_t ) UINT_MAX * sector_size,
- sector_size);
+ (sector_t ) UINT_MAX * cxt->sector_size,
+ cxt->sector_size);
}
}
-void warn_alignment(void)
+void warn_alignment(struct fdisk_context *cxt)
{
if (nowarn)
return;
- if (sector_size != phy_sector_size)
+ if (cxt->sector_size != cxt->phy_sector_size)
fprintf(stderr, _("\n"
"The device presents a logical sector size that is smaller than\n"
"the physical sector size. Aligning to a physical sector (or optimal\n"
@@ -451,64 +441,6 @@ void warn_alignment(void)
}
static void
-get_topology(struct fdisk_context *cxt) {
- int arg;
-#ifdef HAVE_LIBBLKID
- blkid_probe pr;
-
- pr = blkid_new_probe();
- if (pr && blkid_probe_set_device(pr, cxt->dev_fd, 0, 0) == 0) {
- 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);
- 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);
-#endif
-
- if (user_set_sector_size)
- /* fdisk since 2.17 differentiate between logical and physical
- * sectors size. For backward compatibility the
- * fdisk -b <sectorsize>
- * changes both, logical and physical sector size.
- */
- phy_sector_size = sector_size;
-
- else if (blkdev_get_sector_size(cxt->dev_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 = min_io_size;
-
- if (sector_size != DEFAULT_SECTOR_SIZE)
- printf(_("Note: sector size is %d (not %d)\n"),
- sector_size, DEFAULT_SECTOR_SIZE);
-}
-
-static void
get_partition_table_geometry(void) {
unsigned char *bufp = MBRbuffer;
struct partition *p;
@@ -544,9 +476,9 @@ get_partition_table_geometry(void) {
* Sets LBA of the first partition
*/
void
-update_sector_offset(void)
+update_sector_offset(struct fdisk_context *cxt)
{
- grain = io_size;
+ grain = cxt->io_size;
if (dos_compatible_flag)
sector_offset = sectors; /* usually 63 sectors */
@@ -564,29 +496,29 @@ update_sector_offset(void)
*/
sector_t x = 0;
- if (has_topology) {
- if (alignment_offset)
- x = alignment_offset;
- else if (io_size > 2048 * 512)
- x = io_size;
+ if (fdisk_dev_has_topology(cxt)) {
+ if (cxt->alignment_offset)
+ x = cxt->alignment_offset;
+ else if (cxt->io_size > 2048 * 512)
+ x = cxt->io_size;
}
/* default to 1MiB */
if (!x)
x = 2048 * 512;
- sector_offset = x / sector_size;
+ sector_offset = x / cxt->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;
+ sector_offset = cxt->phy_sector_size / cxt->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;
+ if (total_number_of_sectors <= (grain * 4 / cxt->sector_size))
+ grain = cxt->phy_sector_size;
}
}
@@ -595,7 +527,6 @@ get_geometry(struct fdisk_context *cxt, struct geom *g) {
sector_t llcyls, nsects = 0;
unsigned int kern_heads = 0, kern_sectors = 0;
- get_topology(cxt);
heads = cylinders = sectors = 0;
pt_heads = pt_sectors = 0;
@@ -611,9 +542,9 @@ get_geometry(struct fdisk_context *cxt, struct geom *g) {
/* get number of 512-byte sectors, and convert it the real sectors */
if (blkdev_get_sectors(cxt->dev_fd, &nsects) == 0)
- total_number_of_sectors = (nsects / (sector_size >> 9));
+ total_number_of_sectors = (nsects / (cxt->sector_size >> 9));
- update_sector_offset();
+ update_sector_offset(cxt);
llcyls = total_number_of_sectors / (heads * sectors);
cylinders = llcyls;
@@ -676,7 +607,7 @@ static int get_boot(struct fdisk_context *cxt, int try_only) {
if (check_osf_label(cxt)) {
/* intialize partitions for BSD as well */
- dos_init();
+ dos_init(cxt);
if (!valid_part_table_flag(MBRbuffer)) {
disklabel = OSF_LABEL;
return 0;
@@ -695,7 +626,7 @@ static int get_boot(struct fdisk_context *cxt, int try_only) {
#ifdef __sparc__
create_sunlabel(cxt);
#else
- create_doslabel();
+ create_doslabel(cxt);
#endif
}
return 0;
@@ -796,7 +727,8 @@ read_hex(struct systypes *sys)
}
unsigned int
-read_int_with_suffix(unsigned int low, unsigned int dflt, unsigned int high,
+read_int_with_suffix(struct fdisk_context *cxt,
+ unsigned int low, unsigned int dflt, unsigned int high,
unsigned int base, char *mesg, int *is_suffix_used)
{
unsigned int res;
@@ -895,7 +827,7 @@ read_int_with_suffix(unsigned int low, unsigned int dflt, unsigned int high,
unsigned long unit;
bytes = (unsigned long long) res * absolute;
- unit = sector_size * units_per_sector;
+ unit = cxt->sector_size * units_per_sector;
bytes += unit/2; /* round */
bytes /= unit;
res = bytes;
@@ -932,18 +864,19 @@ read_int_with_suffix(unsigned int low, unsigned int dflt, unsigned int high,
* There is no default if DFLT is not between LOW and HIGH.
*/
unsigned int
-read_int(unsigned int low, unsigned int dflt, unsigned int high,
+read_int(struct fdisk_context *cxt,
+ unsigned int low, unsigned int dflt, unsigned int high,
unsigned int base, char *mesg)
{
- return read_int_with_suffix(low, dflt, high, base, mesg, NULL);
+ return read_int_with_suffix(cxt, low, dflt, high, base, mesg, NULL);
}
int
-get_partition_dflt(int warn, int max, int dflt) {
+get_partition_dflt(struct fdisk_context *cxt, int warn, int max, int dflt) {
struct pte *pe;
int i;
- i = read_int(1, dflt, max, 0, _("Partition number")) - 1;
+ i = read_int(cxt, 1, dflt, max, 0, _("Partition number")) - 1;
pe = &ptes[i];
if (warn) {
@@ -961,14 +894,14 @@ get_partition_dflt(int warn, int max, int dflt) {
}
int
-get_partition(int warn, int max) {
- return get_partition_dflt(warn, max, 0);
+get_partition(struct fdisk_context *cxt, int warn, int max) {
+ return get_partition_dflt(cxt, warn, max, 0);
}
/* User partition selection unless one partition only is available */
static int
-get_existing_partition(int warn, int max) {
+get_existing_partition(struct fdisk_context *cxt, int warn, int max) {
int pno = -1;
int i;
@@ -995,7 +928,7 @@ get_existing_partition(int warn, int max) {
not_implemented:
not_unique:
- return get_partition(warn, max);
+ return get_partition(cxt, warn, max);
}
const char *
@@ -1031,18 +964,18 @@ toggle_active(int i) {
}
static void
-toggle_dos_compatibility_flag(void) {
+toggle_dos_compatibility_flag(struct fdisk_context *cxt) {
dos_compatible_flag = ~dos_compatible_flag;
if (dos_compatible_flag)
printf(_("DOS Compatibility flag is set (DEPRECATED!)\n"));
else
printf(_("DOS Compatibility flag is not set\n"));
- update_sector_offset();
+ update_sector_offset(cxt);
}
static void
-delete_partition(int i)
+delete_partition(struct fdisk_context *cxt, int i)
{
if (i < 0)
return;
@@ -1057,18 +990,18 @@ delete_partition(int i)
else if (disklabel == SUN_LABEL)
sun_delete_partition(i);
else if (disklabel == SGI_LABEL)
- sgi_delete_partition(i);
+ sgi_delete_partition(cxt, i);
printf(_("Partition %d is deleted\n"), i + 1);
}
-static void
-change_sysid(void) {
+static void change_sysid(struct fdisk_context *cxt)
+{
char *temp;
int i, sys, origsys;
struct partition *p;
- i = get_existing_partition(0, partitions);
+ i = get_existing_partition(cxt, 0, partitions);
if (i == -1)
return;
@@ -1204,16 +1137,16 @@ static void check_consistency(struct partition *p, int partition) {
}
static void
-check_alignment(sector_t lba, int partition)
+check_alignment(struct fdisk_context *cxt, sector_t lba, int partition)
{
- if (!lba_is_aligned(lba))
+ if (!lba_is_aligned(cxt, lba))
printf(_("Partition %i does not start on physical sector boundary.\n"),
partition + 1);
}
static void
list_disk_geometry(struct fdisk_context *cxt) {
- unsigned long long bytes = total_number_of_sectors * sector_size;
+ unsigned long long bytes = total_number_of_sectors * cxt->sector_size;
long megabytes = bytes/1000000;
if (megabytes < 10000)
@@ -1229,16 +1162,16 @@ list_disk_geometry(struct fdisk_context *cxt) {
if (units_per_sector == 1)
printf(_(", total %llu sectors"), total_number_of_sectors);
printf("\n");
- printf(_("Units = %s of %d * %d = %d bytes\n"),
+ printf(_("Units = %s of %d * %ld = %ld bytes\n"),
str_units(PLURAL),
- units_per_sector, sector_size, units_per_sector * sector_size);
+ units_per_sector, cxt->sector_size, units_per_sector * cxt->sector_size);
- printf(_("Sector size (logical/physical): %u bytes / %lu bytes\n"),
- sector_size, phy_sector_size);
+ printf(_("Sector size (logical/physical): %lu bytes / %lu bytes\n"),
+ cxt->sector_size, cxt->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);
+ cxt->min_io_size, cxt->io_size);
+ if (cxt->alignment_offset)
+ printf(_("Alignment offset: %lu bytes\n"), cxt->alignment_offset);
if (disklabel == DOS_LABEL)
dos_print_mbr_id();
printf("\n");
@@ -1428,12 +1361,12 @@ list_table(struct fdisk_context *cxt, int xtra) {
unsigned int pblocks = psects;
unsigned int podd = 0;
- if (sector_size < 1024) {
- pblocks /= (1024 / sector_size);
- podd = psects % (1024 / sector_size);
+ if (cxt->sector_size < 1024) {
+ pblocks /= (1024 / cxt->sector_size);
+ podd = psects % (1024 / cxt->sector_size);
}
- if (sector_size > 1024)
- pblocks *= (sector_size / 1024);
+ if (cxt->sector_size > 1024)
+ pblocks *= (cxt->sector_size / 1024);
printf(
"%s %c %11lu %11lu %11lu%c %2x %s\n",
partname(cxt->dev_path, i+1, w+2),
@@ -1447,7 +1380,7 @@ list_table(struct fdisk_context *cxt, int xtra) {
/* type name */ (type = partition_type(p->sys_ind)) ?
type : _("Unknown"));
check_consistency(p, i);
- check_alignment(get_partition_start(pe), i);
+ check_alignment(cxt, get_partition_start(pe), i);
}
}
@@ -1482,7 +1415,7 @@ x_list_table(struct fdisk_context *cxt, int extend) {
(unsigned long) get_nr_sects(p), p->sys_ind);
if (p->sys_ind) {
check_consistency(p, i);
- check_alignment(get_partition_start(pe), i);
+ check_alignment(cxt, get_partition_start(pe), i);
}
}
}
@@ -1533,7 +1466,7 @@ check(int n, unsigned int h, unsigned int s, unsigned int c,
}
static void
-verify(void) {
+verify(struct fdisk_context *cxt) {
int i, j;
sector_t total = 1, n_sectors = total_number_of_sectors;
unsigned long long first[partitions], last[partitions];
@@ -1559,7 +1492,7 @@ verify(void) {
p = pe->part_table;
if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
check_consistency(p, i);
- check_alignment(get_partition_start(pe), i);
+ check_alignment(cxt, get_partition_start(pe), i);
if (get_partition_start(pe) < first[i])
printf(_("Warning: bad start-of-data in "
"partition %d\n"), i + 1);
@@ -1603,30 +1536,31 @@ verify(void) {
printf(_("Total allocated sectors %llu greater than the maximum"
" %llu\n"), total, n_sectors);
else if (total < n_sectors)
- printf(_("Remaining %lld unallocated %d-byte sectors\n"),
- n_sectors - total, sector_size);
+ printf(_("Remaining %lld unallocated %ld-byte sectors\n"),
+ n_sectors - total, cxt->sector_size);
}
-void print_partition_size(int num, sector_t start, sector_t stop, int sysid)
+void print_partition_size(struct fdisk_context *cxt,
+ int num, sector_t start, sector_t stop, int sysid)
{
char *str = size_to_human_string(SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE,
- (stop - start + 1) * sector_size);
+ (stop - start + 1) * cxt->sector_size);
printf(_("Partition %d of type %s and of size %s is set\n"), num, partition_type(sysid), str);
free(str);
}
-static void new_partition(void)
+static void new_partition(struct fdisk_context *cxt)
{
if (warn_geometry())
return;
if (disklabel == SUN_LABEL) {
- add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
+ add_sun_partition(cxt, get_partition(cxt, 0, partitions), LINUX_NATIVE);
return;
}
if (disklabel == SGI_LABEL) {
- sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
+ sgi_add_partition(cxt, get_partition(cxt, 0, partitions), LINUX_NATIVE);
return;
}
@@ -1649,7 +1583,7 @@ static void new_partition(void)
}
/* default to DOS/BSD */
- dos_new_partition();
+ dos_new_partition(cxt);
}
static void
@@ -1719,10 +1653,10 @@ reread_partition_table(struct fdisk_context *cxt, int leave) {
#define MAX_PER_LINE 16
static void
-print_buffer(unsigned char pbuffer[]) {
+print_buffer(struct fdisk_context *cxt, unsigned char pbuffer[]) {
unsigned int i, l;
- for (i = 0, l = 0; i < sector_size; i++, l++) {
+ for (i = 0, l = 0; i < cxt->sector_size; i++, l++) {
if (l == 0)
printf("0x%03X:", i);
printf(" %02X", pbuffer[i]);
@@ -1736,19 +1670,19 @@ print_buffer(unsigned char pbuffer[]) {
printf("\n");
}
-static void
-print_raw(char *dev) {
+static void print_raw(struct fdisk_context *cxt)
+{
int i;
- printf(_("Device: %s\n"), dev);
+ printf(_("Device: %s\n"), cxt->dev_path);
if (disklabel == SUN_LABEL || disklabel == SGI_LABEL)
- print_buffer(MBRbuffer);
+ print_buffer(cxt, MBRbuffer);
else for (i = 3; i < partitions; i++)
- print_buffer(ptes[i].sectorbuffer);
+ print_buffer(cxt, ptes[i].sectorbuffer);
}
static void
-move_begin(int i) {
+move_begin(struct fdisk_context *cxt, int i) {
struct pte *pe = &ptes[i];
struct partition *p = pe->part_table;
unsigned int new, free_start, curr_start, last;
@@ -1785,7 +1719,7 @@ move_begin(int i) {
last = get_partition_start(pe) + get_nr_sects(p) - 1;
- new = read_int(free_start, curr_start, last, free_start,
+ new = read_int(cxt, free_start, curr_start, last, free_start,
_("New beginning of data")) - pe->offset;
if (new != get_nr_sects(p)) {
@@ -1814,27 +1748,27 @@ expert_command_prompt(struct fdisk_context *cxt)
switch (c) {
case 'a':
if (disklabel == SUN_LABEL)
- sun_set_alt_cyl();
+ sun_set_alt_cyl(cxt);
break;
case 'b':
if (disklabel == DOS_LABEL)
- move_begin(get_partition(0, partitions));
+ move_begin(cxt, get_partition(cxt, 0, partitions));
break;
case 'c':
user_cylinders = cylinders =
- read_int(1, cylinders, 1048576, 0,
+ read_int(cxt, 1, cylinders, 1048576, 0,
_("Number of cylinders"));
if (disklabel == SUN_LABEL)
sun_set_ncyl(cylinders);
break;
case 'd':
- print_raw(cxt->dev_path);
+ print_raw(cxt);
break;
case 'e':
if (disklabel == SGI_LABEL)
sgi_set_xcyl();
else if (disklabel == SUN_LABEL)
- sun_set_xcyl();
+ sun_set_xcyl(cxt);
else
if (disklabel == DOS_LABEL)
x_list_table(cxt, 1);
@@ -1847,19 +1781,19 @@ expert_command_prompt(struct fdisk_context *cxt)
create_sgilabel(cxt);
break;
case 'h':
- user_heads = heads = read_int(1, heads, 256, 0,
+ user_heads = heads = read_int(cxt, 1, heads, 256, 0,
_("Number of heads"));
update_units();
break;
case 'i':
if (disklabel == SUN_LABEL)
- sun_set_ilfact();
+ sun_set_ilfact(cxt);
else if (disklabel == DOS_LABEL)
dos_set_mbr_id();
break;
case 'o':
if (disklabel == SUN_LABEL)
- sun_set_rspeed();
+ sun_set_rspeed(cxt);
break;
case 'p':
if (disklabel == SUN_LABEL)
@@ -1872,24 +1806,24 @@ expert_command_prompt(struct fdisk_context *cxt)
case 'r':
return;
case 's':
- user_sectors = sectors = read_int(1, sectors, 63, 0,
+ user_sectors = sectors = read_int(cxt, 1, sectors, 63, 0,
_("Number of sectors"));
if (dos_compatible_flag)
fprintf(stderr, _("Warning: setting "
"sector offset for DOS "
"compatiblity\n"));
- update_sector_offset();
+ update_sector_offset(cxt);
update_units();
break;
case 'v':
- verify();
+ verify(cxt);
break;
case 'w':
write_table(cxt);
break;
case 'y':
if (disklabel == SUN_LABEL)
- sun_set_pcylcount();
+ sun_set_pcylcount(cxt);
break;
default:
print_menu(EXPERT_MENU);
@@ -1918,15 +1852,15 @@ gpt_warning(char *dev)
}
/* Print disk geometry and partition table of a specified device (-l option) */
-
-static void
-print_partition_table_from_option(char *device)
+static void print_partition_table_from_option(char *device, unsigned long sector_size)
{
int gb;
struct fdisk_context *cxt = fdisk_new_context_from_filename(device, 1); /* read-only */
if (!cxt)
err(EXIT_FAILURE, _("unable to open %s"), device);
+ if (sector_size) /* passed -b option, override autodiscovery */
+ cxt->phy_sector_size = cxt->sector_size = sector_size;
gpt_warning(device);
gb = get_boot(cxt, 1);
@@ -1946,7 +1880,7 @@ print_partition_table_from_option(char *device)
* try all things in /proc/partitions that look like a full disk
*/
static void
-print_all_partition_table_from_option(void)
+print_all_partition_table_from_option(unsigned long sector_size)
{
FILE *procpt;
char line[128], ptname[128], devname[256];
@@ -1968,7 +1902,7 @@ print_all_partition_table_from_option(void)
char *cn = canonicalize_path(devname);
if (cn) {
if (!is_ide_cdrom_or_tape(cn))
- print_partition_table_from_option(cn);
+ print_partition_table_from_option(cn, sector_size);
free(cn);
}
}
@@ -2011,13 +1945,13 @@ static void command_prompt(struct fdisk_context *cxt)
switch (c) {
case 'a':
if (disklabel == DOS_LABEL)
- toggle_active(get_partition(1, partitions));
+ toggle_active(get_partition(cxt, 1, partitions));
else if (disklabel == SUN_LABEL)
- toggle_sunflags(get_partition(1, partitions),
+ toggle_sunflags(get_partition(cxt, 1, partitions),
SUN_FLAG_UNMNT);
else if (disklabel == SGI_LABEL)
sgi_set_bootpartition(
- get_partition(1, partitions));
+ get_partition(cxt, 1, partitions));
else
unknown_command(c);
break;
@@ -2033,18 +1967,18 @@ static void command_prompt(struct fdisk_context *cxt)
break;
case 'c':
if (disklabel == DOS_LABEL)
- toggle_dos_compatibility_flag();
+ toggle_dos_compatibility_flag(cxt);
else if (disklabel == SUN_LABEL)
- toggle_sunflags(get_partition(1, partitions),
+ toggle_sunflags(get_partition(cxt, 1, partitions),
SUN_FLAG_RONLY);
else if (disklabel == SGI_LABEL)
sgi_set_swappartition(
- get_partition(1, partitions));
+ get_partition(cxt, 1, partitions));
else
unknown_command(c);
break;
case 'd':
- delete_partition(get_existing_partition(1, partitions));
+ delete_partition(cxt, get_existing_partition(cxt, 1, partitions));
break;
case 'i':
if (disklabel == SGI_LABEL)
@@ -2059,10 +1993,10 @@ static void command_prompt(struct fdisk_context *cxt)
print_menu(MAIN_MENU);
break;
case 'n':
- new_partition();
+ new_partition(cxt);
break;
case 'o':
- create_doslabel();
+ create_doslabel(cxt);
break;
case 'p':
list_table(cxt, 0);
@@ -2073,13 +2007,13 @@ static void command_prompt(struct fdisk_context *cxt)
create_sunlabel(cxt);
break;
case 't':
- change_sysid();
+ change_sysid(cxt);
break;
case 'u':
change_units();
break;
case 'v':
- verify();
+ verify(cxt);
break;
case 'w':
write_table(cxt);
@@ -2112,6 +2046,7 @@ static sector_t get_dev_blocks(char *dev)
int main(int argc, char **argv)
{
int c, optl = 0, opts = 0;
+ unsigned long sector_size = 0;
struct fdisk_context *cxt = NULL;
setlocale(LC_ALL, "");
@@ -2191,9 +2126,9 @@ int main(int argc, char **argv)
if (argc > optind) {
int k;
for (k = optind; k < argc; k++)
- print_partition_table_from_option(argv[k]);
+ print_partition_table_from_option(argv[k], sector_size);
} else
- print_all_partition_table_from_option();
+ print_all_partition_table_from_option(sector_size);
exit(0);
}
@@ -2216,6 +2151,8 @@ int main(int argc, char **argv)
cxt = fdisk_new_context_from_filename(argv[optind], 0);
if (!cxt)
err(EXIT_FAILURE, _("unable to open %s"), argv[optind]);
+ if (user_set_sector_size) /* passed -b option, override autodiscovery */
+ cxt->phy_sector_size = cxt->sector_size = sector_size;
}
else
usage(stderr);
diff --git a/fdisk/fdisk.h b/fdisk/fdisk.h
index 31129e86c..a24fa2056 100644
--- a/fdisk/fdisk.h
+++ b/fdisk/fdisk.h
@@ -105,9 +105,17 @@ typedef unsigned long long sector_t;
struct fdisk_context {
int dev_fd; /* device descriptor */
char *dev_path; /* device path */
+
+ /* topology */
+ unsigned long io_size;
+ unsigned long min_io_size;
+ unsigned long phy_sector_size; /* physical size */
+ unsigned long sector_size; /* logical size */
+ unsigned long alignment_offset;
};
extern struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int readonly);
+extern int fdisk_dev_has_topology(struct fdisk_context *cxt);
extern void fdisk_free_context(struct fdisk_context *cxt);
/* prototypes for fdisk.c */
@@ -117,7 +125,7 @@ extern unsigned int display_in_cyl_units, units_per_sector;
extern void change_units(void);
extern void fatal(struct fdisk_context *cxt, enum failure why);
extern void get_geometry(struct fdisk_context *, struct geom *);
-extern int get_partition(int warn, int max);
+extern int get_partition(struct fdisk_context *cxt, int warn, int max);
extern void list_types(struct systypes *sys);
extern int read_line (int *asked);
extern char read_char(char *mesg);
@@ -125,14 +133,15 @@ extern int read_hex(struct systypes *sys);
extern void reread_partition_table(struct fdisk_context *cxt, int leave);
extern struct partition *get_part_table(int);
extern int valid_part_table_flag(unsigned char *b);
-extern unsigned int read_int(unsigned int low, unsigned int dflt,
+extern unsigned int read_int(struct fdisk_context *cxt,
+ unsigned int low, unsigned int dflt,
unsigned int high, unsigned int base, char *mesg);
extern void print_menu(enum menutype);
-extern void print_partition_size(int num, sector_t start, sector_t stop, int sysid);
+extern void print_partition_size(struct fdisk_context *cxt, int num, sector_t start, sector_t stop, int sysid);
extern void zeroize_mbr_buffer(void);
extern void fill_bounds(sector_t *first, sector_t *last);
-extern unsigned int heads, cylinders, sector_size;
+extern unsigned int heads, cylinders;
extern sector_t sectors;
extern char *partition_type(unsigned char type);
extern void update_units(void);
@@ -140,12 +149,13 @@ extern char read_chars(char *mesg);
extern void set_changed(int);
extern void set_all_unchanged(void);
extern int warn_geometry(void);
-extern void warn_limits(void);
-extern void warn_alignment(void);
-extern unsigned int read_int_with_suffix(unsigned int low, unsigned int dflt, unsigned int high,
+extern void warn_limits(struct fdisk_context *cxt);
+extern void warn_alignment(struct fdisk_context *cxt);
+extern unsigned int read_int_with_suffix(struct fdisk_context *cxt,
+ unsigned int low, unsigned int dflt, unsigned int high,
unsigned int base, char *mesg, int *is_suffix_used);
-extern sector_t align_lba(sector_t lba, int direction);
-extern int get_partition_dflt(int warn, int max, int dflt);
+extern sector_t align_lba(struct fdisk_context *cxt, sector_t lba, int direction);
+extern int get_partition_dflt(struct fdisk_context *cxt, int warn, int max, int dflt);
#define PLURAL 0
#define SINGULAR 1
@@ -202,7 +212,7 @@ static inline void set_start_sect(struct partition *p, unsigned int start_sect)
static inline void seek_sector(struct fdisk_context *cxt, sector_t secno)
{
- off_t offset = (off_t) secno * sector_size;
+ off_t offset = (off_t) secno * cxt->sector_size;
if (lseek(cxt->dev_fd, offset, SEEK_SET) == (off_t) -1)
fatal(cxt, unable_to_seek);
}
@@ -210,14 +220,14 @@ static inline void seek_sector(struct fdisk_context *cxt, sector_t secno)
static inline void read_sector(struct fdisk_context *cxt, sector_t secno, unsigned char *buf)
{
seek_sector(cxt, secno);
- if (read(cxt->dev_fd, buf, sector_size) != sector_size)
+ if (read(cxt->dev_fd, buf, cxt->sector_size) != cxt->sector_size)
fatal(cxt, unable_to_read);
}
static inline void write_sector(struct fdisk_context *cxt, sector_t secno, unsigned char *buf)
{
seek_sector(cxt, secno);
- if (write(cxt->dev_fd, buf, sector_size) != sector_size)
+ if (write(cxt->dev_fd, buf, cxt->sector_size) != cxt->sector_size)
fatal(cxt, unable_to_write);
}
diff --git a/fdisk/fdiskbsdlabel.c b/fdisk/fdiskbsdlabel.c
index a2a0532cf..b92530f50 100644
--- a/fdisk/fdiskbsdlabel.c
+++ b/fdisk/fdiskbsdlabel.c
@@ -62,7 +62,7 @@
#include "fdiskbsdlabel.h"
static void xbsd_delete_part (void);
-static void xbsd_new_part (void);
+static void xbsd_new_part (struct fdisk_context *cxt);
static void xbsd_write_disklabel (struct fdisk_context *cxt);
static int xbsd_create_disklabel (struct fdisk_context *cxt);
static void xbsd_edit_disklabel (void);
@@ -86,7 +86,7 @@ void alpha_bootblock_checksum (char *boot);
#if !defined (__alpha__)
static int xbsd_translate_fstype (int linux_type);
-static void xbsd_link_part (void);
+static void xbsd_link_part (struct fdisk_context *cxt);
static struct partition *xbsd_part;
static int xbsd_part_index;
#endif
@@ -196,7 +196,7 @@ bsd_command_prompt (struct fdisk_context *cxt)
xbsd_list_types ();
break;
case 'n':
- xbsd_new_part ();
+ xbsd_new_part (cxt);
break;
case 'p':
xbsd_print_disklabel (cxt, 0);
@@ -220,7 +220,7 @@ bsd_command_prompt (struct fdisk_context *cxt)
break;
#if !defined (__alpha__)
case 'x':
- xbsd_link_part ();
+ xbsd_link_part (cxt);
break;
#endif
default:
@@ -245,7 +245,7 @@ xbsd_delete_part (void)
}
static void
-xbsd_new_part (void)
+xbsd_new_part (struct fdisk_context *cxt)
{
unsigned int begin, end;
char mesg[256];
@@ -263,7 +263,7 @@ xbsd_new_part (void)
#endif
snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
- begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
+ begin = read_int (cxt, bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
0, mesg);
if (display_in_cyl_units)
@@ -271,7 +271,7 @@ xbsd_new_part (void)
snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
str_units(SINGULAR));
- end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
+ end = read_int (cxt, bsd_cround (begin), bsd_cround (end), bsd_cround (end),
bsd_cround (begin), mesg);
if (display_in_cyl_units)
@@ -810,12 +810,12 @@ xbsd_translate_fstype (int linux_type)
}
static void
-xbsd_link_part (void)
+xbsd_link_part (struct fdisk_context *cxt)
{
int k, i;
struct partition *p;
- k = get_partition (1, partitions);
+ k = get_partition (cxt, 1, partitions);
if (!xbsd_check_new_partition (&i))
return;
diff --git a/fdisk/fdiskdoslabel.c b/fdisk/fdiskdoslabel.c
index 382909c45..8ee35666c 100644
--- a/fdisk/fdiskdoslabel.c
+++ b/fdisk/fdiskdoslabel.c
@@ -22,13 +22,13 @@
s |= (sector >> 2) & 0xc0; \
}
-#define alignment_required (grain != sector_size)
+#define alignment_required (grain != cxt->sector_size)
struct pte ptes[MAXIMUM_PARTS];
sector_t extended_offset;
int ext_index;
-static int get_nonexisting_partition(int warn, int max)
+static int get_nonexisting_partition(struct fdisk_context *cxt, int warn, int max)
{
int pno = -1;
int i;
@@ -54,7 +54,7 @@ static int get_nonexisting_partition(int warn, int max)
return -1;
not_unique:
- return get_partition_dflt(warn, max, dflt);
+ return get_partition_dflt(cxt, warn, max, dflt);
}
@@ -64,7 +64,7 @@ static void read_pte(struct fdisk_context *cxt, int pno, sector_t offset)
struct pte *pe = &ptes[pno];
pe->offset = offset;
- pe->sectorbuffer = xmalloc(sector_size);
+ pe->sectorbuffer = xmalloc(cxt->sector_size);
read_sector(cxt, offset, pe->sectorbuffer);
pe->changed = 0;
pe->part_table = pe->ext_pointer = NULL;
@@ -96,7 +96,7 @@ static void clear_partition(struct partition *p)
set_nr_sects(p,0);
}
-void dos_init(void)
+void dos_init(struct fdisk_context *cxt)
{
int i;
@@ -116,8 +116,8 @@ void dos_init(void)
}
warn_geometry();
- warn_limits();
- warn_alignment();
+ warn_limits(cxt);
+ warn_alignment(cxt);
}
static void read_extended(struct fdisk_context *cxt, int ext)
@@ -219,7 +219,7 @@ void dos_print_mbr_id(void)
printf(_("Disk identifier: 0x%08x\n"), dos_read_mbr_id(MBRbuffer));
}
-void create_doslabel(void)
+void create_doslabel(struct fdisk_context *cxt)
{
unsigned int id;
@@ -228,7 +228,7 @@ void create_doslabel(void)
fprintf(stderr, _("Building a new DOS disklabel with disk identifier 0x%08x.\n"), id);
- dos_init();
+ dos_init(cxt);
zeroize_mbr_buffer();
set_all_unchanged();
@@ -324,7 +324,7 @@ int check_dos_label(struct fdisk_context *cxt)
if (!valid_part_table_flag(MBRbuffer))
return 0;
- dos_init();
+ dos_init(cxt);
for (i = 0; i < 4; i++) {
struct pte *pe = &ptes[i];
@@ -368,7 +368,8 @@ int is_dos_partition(int t)
t == 0xc1 || t == 0xc4 || t == 0xc6);
}
-static void set_partition(int i, int doext, sector_t start,
+static void set_partition(struct fdisk_context *cxt,
+ int i, int doext, sector_t start,
sector_t stop, int sysid)
{
struct partition *p;
@@ -387,7 +388,7 @@ static void set_partition(int i, int doext, sector_t start,
set_nr_sects(p, stop - start + 1);
if (!doext)
- print_partition_size(i + 1, start, stop, sysid);
+ print_partition_size(cxt, i + 1, start, stop, sysid);
if (dos_compatible_flag && (start/(sectors*heads) > 1023))
start = heads*sectors*1024 - 1;
@@ -416,12 +417,13 @@ static sector_t get_unused_start(int part_n, sector_t start,
return start;
}
-static sector_t align_lba_in_range(sector_t lba, sector_t start, sector_t stop)
+static sector_t align_lba_in_range(struct fdisk_context *cxt,
+ sector_t lba, sector_t start, sector_t stop)
{
- start = align_lba(start, ALIGN_UP);
- stop = align_lba(stop, ALIGN_DOWN);
+ start = align_lba(cxt, start, ALIGN_UP);
+ stop = align_lba(cxt, stop, ALIGN_DOWN);
- lba = align_lba(lba, ALIGN_NEAREST);
+ lba = align_lba(cxt, lba, ALIGN_NEAREST);
if (lba < start)
return start;
@@ -430,7 +432,7 @@ static sector_t align_lba_in_range(sector_t lba, sector_t start, sector_t stop)
return lba;
}
-void dos_add_partition(int n, int sys)
+void dos_add_partition(struct fdisk_context *cxt, int n, int sys)
{
char mesg[256]; /* 48 does not suffice in Japanese */
int i, read = 0;
@@ -477,7 +479,7 @@ void dos_add_partition(int n, int sys)
/* the default sector should be aligned and unused */
do {
- aligned = align_lba_in_range(dflt, dflt, limit);
+ aligned = align_lba_in_range(cxt, dflt, dflt, limit);
dflt = get_unused_start(n, aligned, first, last);
} while (dflt != aligned && dflt > aligned && dflt < limit);
@@ -493,7 +495,7 @@ void dos_add_partition(int n, int sys)
if (!read && start == temp) {
sector_t i = start;
- start = read_int(cround(i), cround(dflt), cround(limit),
+ start = read_int(cxt, cround(i), cround(dflt), cround(limit),
0, mesg);
if (display_in_cyl_units) {
start = (start - 1) * units_per_sector;
@@ -536,8 +538,9 @@ void dos_add_partition(int n, int sys)
_("Last %1$s, +%2$s or +size{K,M,G}"),
str_units(SINGULAR), str_units(PLURAL));
- stop = read_int_with_suffix(cround(start), cround(limit), cround(limit),
- cround(start), mesg, &is_suffix_used);
+ stop = read_int_with_suffix(cxt,
+ cround(start), cround(limit), cround(limit),
+ cround(start), mesg, &is_suffix_used);
if (display_in_cyl_units) {
stop = stop * units_per_sector - 1;
if (stop >limit)
@@ -550,15 +553,15 @@ void dos_add_partition(int n, int sys)
* and align the end of the partition. The next
* partition will start at phy.block boundary.
*/
- stop = align_lba_in_range(stop, start, limit) - 1;
+ stop = align_lba_in_range(cxt, stop, start, limit) - 1;
if (stop > limit)
stop = limit;
}
}
- set_partition(n, 0, start, stop, sys);
+ set_partition(cxt, n, 0, start, stop, sys);
if (n > 4)
- set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
+ set_partition(cxt, n - 1, 1, ptes[n].offset, stop, EXTENDED);
if (IS_EXTENDED (sys)) {
struct pte *pe4 = &ptes[4];
@@ -567,7 +570,7 @@ void dos_add_partition(int n, int sys)
ext_index = n;
pen->ext_pointer = p;
pe4->offset = extended_offset = start;
- pe4->sectorbuffer = xcalloc(1, sector_size);
+ pe4->sectorbuffer = xcalloc(1, cxt->sector_size);
pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
pe4->ext_pointer = pe4->part_table + 1;
pe4->changed = 1;
@@ -575,12 +578,12 @@ void dos_add_partition(int n, int sys)
}
}
-static void add_logical(void)
+static void add_logical(struct fdisk_context *cxt)
{
if (partitions > 5 || ptes[4].part_table->sys_ind) {
struct pte *pe = &ptes[partitions];
- pe->sectorbuffer = xcalloc(1, sector_size);
+ pe->sectorbuffer = xcalloc(1, cxt->sector_size);
pe->part_table = pt_offset(pe->sectorbuffer, 0);
pe->ext_pointer = pe->part_table + 1;
pe->offset = 0;
@@ -588,14 +591,14 @@ static void add_logical(void)
partitions++;
}
printf(_("Adding logical partition %d\n"), partitions);
- dos_add_partition(partitions - 1, LINUX_NATIVE);
+ dos_add_partition(cxt, partitions - 1, LINUX_NATIVE);
}
/*
* Ask the user for new partition type information (logical, extended).
* This function calls the actual partition adding logic - dos_add_partition.
*/
-void dos_new_partition(void)
+void dos_new_partition(struct fdisk_context *cxt)
{
int i, free_primary = 0;
@@ -610,14 +613,14 @@ void dos_new_partition(void)
if (!free_primary) {
if (extended_offset) {
printf(_("All primary partitions are in use\n"));
- add_logical();
+ add_logical(cxt);
} else
printf(_("If you want to create more than four partitions, you must replace a\n"
"primary partition with an extended partition first.\n"));
} else if (partitions >= MAXIMUM_PARTS) {
printf(_("All logical partitions are in use\n"));
printf(_("Adding a primary partition\n"));
- dos_add_partition(get_partition(0, 4), LINUX_NATIVE);
+ dos_add_partition(cxt, get_partition(cxt, 0, 4), LINUX_NATIVE);
} else {
char c, dflt, line[LINE_LENGTH];
@@ -637,17 +640,17 @@ void dos_new_partition(void)
printf(_("Using default response %c\n"), c);
}
if (c == 'p') {
- int i = get_nonexisting_partition(0, 4);
+ int i = get_nonexisting_partition(cxt, 0, 4);
if (i >= 0)
- dos_add_partition(i, LINUX_NATIVE);
+ dos_add_partition(cxt, i, LINUX_NATIVE);
return;
} else if (c == 'l' && extended_offset) {
- add_logical();
+ add_logical(cxt);
return;
} else if (c == 'e' && !extended_offset) {
- int i = get_nonexisting_partition(0, 4);
+ int i = get_nonexisting_partition(cxt, 0, 4);
if (i >= 0)
- dos_add_partition(i, EXTENDED);
+ dos_add_partition(cxt, i, EXTENDED);
return;
} else
printf(_("Invalid partition type `%c'\n"), c);
diff --git a/fdisk/fdiskdoslabel.h b/fdisk/fdiskdoslabel.h
index a436e53b9..8d62d52e8 100644
--- a/fdisk/fdiskdoslabel.h
+++ b/fdisk/fdiskdoslabel.h
@@ -43,15 +43,15 @@ static inline sector_t get_partition_start(struct pte *pe)
return pe->offset + get_start_sect(pe->part_table);
}
-extern void create_doslabel(void);
+extern void create_doslabel(struct fdisk_context *cxt);
extern void dos_print_mbr_id(void);
extern void dos_set_mbr_id(void);
extern void dos_delete_partition(int i);
extern int check_dos_label(struct fdisk_context *cxt);
extern int is_dos_partition(int t);
-extern void dos_init(void);
-extern void dos_add_partition(int n, int sys);
-extern void dos_new_partition(void);
+extern void dos_init(struct fdisk_context *cxt);
+extern void dos_add_partition(struct fdisk_context *cxt, int n, int sys);
+extern void dos_new_partition(struct fdisk_context *cxt);
extern void dos_write_table(struct fdisk_context *cxt);
#endif
diff --git a/fdisk/fdisksgilabel.c b/fdisk/fdisksgilabel.c
index 14e3443cf..9c425b393 100644
--- a/fdisk/fdisksgilabel.c
+++ b/fdisk/fdisksgilabel.c
@@ -190,20 +190,20 @@ sgi_list_table(struct fdisk_context *cxt, int xtra) {
"%d cylinders, %d physical cylinders\n"
"%d extra sects/cyl, interleave %d:1\n"
"%s\n"
- "Units = %s of %d * %d bytes\n\n"),
+ "Units = %s of %d * %ld bytes\n\n"),
cxt->dev_path, heads, sectors, cylinders,
SSWAP16(sgiparam.pcylcount),
(int) sgiparam.sparecyl, SSWAP16(sgiparam.ilfact),
(char *)sgilabel,
str_units(PLURAL), units_per_sector,
- sector_size);
+ cxt->sector_size);
} else {
printf(_("\nDisk %s (SGI disk label): "
"%d heads, %llu sectors, %d cylinders\n"
- "Units = %s of %d * %d bytes\n\n"),
+ "Units = %s of %d * %ld bytes\n\n"),
cxt->dev_path, heads, sectors, cylinders,
str_units(PLURAL), units_per_sector,
- sector_size);
+ cxt->sector_size);
}
printf(_("----- partitions -----\n"
"Pt# %*s Info Start End Sectors Id System\n"),
@@ -563,7 +563,8 @@ sgi_entire(void) {
}
static void
-sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
+sgi_set_partition(struct fdisk_context *cxt,
+ int i, unsigned int start, unsigned int length, int sys) {
sgilabel->partitions[i].id = SSWAP32(sys);
sgilabel->partitions[i].num_sectors = SSWAP32(length);
sgilabel->partitions[i].start_sector = SSWAP32(start);
@@ -571,16 +572,16 @@ sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
if (sgi_gaps() < 0) /* rebuild freelist */
printf(_("Partition overlap on the disk.\n"));
if (length)
- print_partition_size(i + 1, start, start + length, sys);
+ print_partition_size(cxt, i + 1, start, start + length, sys);
}
static void
-sgi_set_entire(void) {
+sgi_set_entire(struct fdisk_context *cxt) {
int n;
for (n=10; n<partitions; n++) {
if (!sgi_get_num_sectors(n)) {
- sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
+ sgi_set_partition(cxt, n, 0, sgi_get_lastblock(), SGI_VOLUME);
break;
}
}
@@ -588,7 +589,7 @@ sgi_set_entire(void) {
static
void
-sgi_set_volhdr(void)
+sgi_set_volhdr(struct fdisk_context *cxt)
{
int n;
@@ -599,20 +600,20 @@ sgi_set_volhdr(void)
* as IRIX fx uses.
*/
if (4096 < sgi_get_lastblock())
- sgi_set_partition(n, 0, 4096, SGI_VOLHDR);
+ sgi_set_partition(cxt, n, 0, 4096, SGI_VOLHDR);
break;
}
}
}
void
-sgi_delete_partition(int i)
+sgi_delete_partition(struct fdisk_context *cxt, int i)
{
- sgi_set_partition(i, 0, 0, 0);
+ sgi_set_partition(cxt, i, 0, 0, 0);
}
void
-sgi_add_partition(int n, int sys)
+sgi_add_partition(struct fdisk_context *cxt, int n, int sys)
{
char mesg[256];
unsigned int first=0, last=0;
@@ -630,8 +631,8 @@ sgi_add_partition(int n, int sys)
if ((sgi_entire() == -1)
&& (sys != SGI_VOLUME)) {
printf(_("Attempting to generate entire disk entry automatically.\n"));
- sgi_set_entire();
- sgi_set_volhdr();
+ sgi_set_entire(cxt);
+ sgi_set_volhdr(cxt);
}
if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
printf(_("The entire disk is already covered with partitions.\n"));
@@ -645,7 +646,7 @@ sgi_add_partition(int n, int sys)
for (;;) {
if (sys == SGI_VOLUME) {
last = sgi_get_lastblock();
- first = read_int(0, 0, last-1, 0, mesg);
+ first = read_int(cxt, 0, 0, last-1, 0, mesg);
if (first != 0) {
printf(_("It is highly recommended that eleventh partition\n"
"covers the entire disk and is of type `SGI volume'\n"));
@@ -653,7 +654,7 @@ sgi_add_partition(int n, int sys)
} else {
first = freelist[0].first;
last = freelist[0].last;
- first = read_int(scround(first), scround(first), scround(last)-1,
+ first = read_int(cxt, scround(first), scround(first), scround(last)-1,
0, mesg);
}
if (display_in_cyl_units)
@@ -669,7 +670,7 @@ sgi_add_partition(int n, int sys)
break;
}
snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
- last = read_int(scround(first), scround(last)-1, scround(last)-1,
+ last = read_int(cxt, scround(first), scround(last)-1, scround(last)-1,
scround(first), mesg)+1;
if (display_in_cyl_units)
last *= units_per_sector;
@@ -678,7 +679,7 @@ sgi_add_partition(int n, int sys)
if ((sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock()))
printf(_("It is highly recommended that eleventh partition\n"
"covers the entire disk and is of type `SGI volume'\n"));
- sgi_set_partition(n, first, last-first, sys);
+ sgi_set_partition(cxt, n, first, last-first, sys);
}
void
@@ -695,7 +696,7 @@ create_sgilabel(struct fdisk_context *cxt)
int res; /* the result from the ioctl */
int sec_fac; /* the sector factor */
- sec_fac = sector_size / 512; /* determine the sector factor */
+ sec_fac = cxt->sector_size / 512; /* determine the sector factor */
fprintf(stderr,
_("Building a new SGI disklabel.\n"));
@@ -769,7 +770,7 @@ create_sgilabel(struct fdisk_context *cxt)
sgilabel->devparam.unused1 = SSWAP16(0);
sgilabel->devparam.nsect = SSWAP16(geometry.sectors);
/* sectors/track */
- sgilabel->devparam.bytes = SSWAP16(sector_size);
+ sgilabel->devparam.bytes = SSWAP16(cxt->sector_size);
sgilabel->devparam.ilfact = SSWAP16(1);
sgilabel->devparam.flags = SSWAP32(TRACK_FWD|\
IGNORE_ERRORS|RESEEK);
@@ -787,11 +788,11 @@ create_sgilabel(struct fdisk_context *cxt)
disklabel = SGI_LABEL;
partitions = 16;
volumes = 15;
- sgi_set_entire();
- sgi_set_volhdr();
+ sgi_set_entire(cxt);
+ sgi_set_volhdr(cxt);
for (i = 0; i < 4; i++) {
if (old[i].sysid) {
- sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
+ sgi_set_partition(cxt, i, old[i].start, old[i].nsect, old[i].sysid);
}
}
}
diff --git a/fdisk/fdisksgilabel.h b/fdisk/fdisksgilabel.h
index 3a11499ad..7611d327a 100644
--- a/fdisk/fdisksgilabel.h
+++ b/fdisk/fdisksgilabel.h
@@ -118,8 +118,8 @@ extern int sgi_change_sysid( int i, int sys );
extern unsigned int sgi_get_start_sector( int i );
extern unsigned int sgi_get_num_sectors( int i );
extern int sgi_get_sysid( int i );
-extern void sgi_delete_partition( int i );
-extern void sgi_add_partition( int n, int sys );
+extern void sgi_delete_partition( struct fdisk_context *cxt, int i );
+extern void sgi_add_partition( struct fdisk_context *cxt, int n, int sys );
extern void create_sgilabel( struct fdisk_context *cxt );
extern void create_sgiinfo( void );
extern int verify_sgi( int verbose );
diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c
index 9d5b3e8d2..ae24e1611 100644
--- a/fdisk/fdisksunlabel.c
+++ b/fdisk/fdisksunlabel.c
@@ -59,7 +59,8 @@ static inline uint32_t __swap32(uint32_t x) {
#define SSWAP32(x) (other_endian ? __swap32(x) \
: (uint32_t)(x))
-static void set_sun_partition(int i, uint32_t start, uint32_t stop, uint16_t sysid)
+static void set_sun_partition(struct fdisk_context *cxt,
+ int i, uint32_t start, uint32_t stop, uint16_t sysid)
{
sunlabel->part_tags[i].tag = SSWAP16(sysid);
sunlabel->part_tags[i].flag = SSWAP16(0);
@@ -68,7 +69,7 @@ static void set_sun_partition(int i, uint32_t start, uint32_t stop, uint16_t sys
sunlabel->partitions[i].num_sectors =
SSWAP32(stop - start);
set_changed(i);
- print_partition_size(i + 1, start, stop, sysid);
+ print_partition_size(cxt, i + 1, start, stop, sysid);
}
static void init(void)
@@ -173,7 +174,7 @@ void create_sunlabel(struct fdisk_context *cxt)
sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS);
res = blkdev_get_sectors(cxt->dev_fd, &llsectors);
- sec_fac = sector_size / 512;
+ sec_fac = cxt->sector_size / 512;
#ifdef HDIO_GETGEO
if (!ioctl(cxt->dev_fd, HDIO_GETGEO, &geometry)) {
@@ -195,9 +196,9 @@ void create_sunlabel(struct fdisk_context *cxt)
} else
#endif
{
- heads = read_int(1,1,1024,0,_("Heads"));
- sectors = read_int(1,1,1024,0,_("Sectors/track"));
- cylinders = read_int(1,1,65535,0,_("Cylinders"));
+ heads = read_int(cxt, 1,1,1024,0,_("Heads"));
+ sectors = read_int(cxt, 1,1,1024,0,_("Sectors/track"));
+ cylinders = read_int(cxt, 1,1,65535,0,_("Cylinders"));
}
sunlabel->acyl = SSWAP16(2);
@@ -220,14 +221,14 @@ void create_sunlabel(struct fdisk_context *cxt)
} else
ndiv = cylinders * 2 / 3;
- set_sun_partition(0, 0, ndiv * heads * sectors,
+ set_sun_partition(cxt, 0, 0, ndiv * heads * sectors,
SUN_TAG_LINUX_NATIVE);
- set_sun_partition(1, ndiv * heads * sectors,
+ set_sun_partition(cxt, 1, ndiv * heads * sectors,
cylinders * heads * sectors,
SUN_TAG_LINUX_SWAP);
sunlabel->part_tags[1].flag |= SSWAP16(SUN_FLAG_UNMNT);
- set_sun_partition(2, 0, cylinders * heads * sectors, SUN_TAG_BACKUP);
+ set_sun_partition(cxt, 2, 0, cylinders * heads * sectors, SUN_TAG_BACKUP);
{
unsigned short *ush = (unsigned short *)sunlabel;
@@ -363,7 +364,7 @@ void verify_sun(void)
printf(_("Unused gap - sectors %d-%d\n"), start, stop);
}
-void add_sun_partition(int n, int sys)
+void add_sun_partition(struct fdisk_context *cxt, int n, int sys)
{
uint32_t starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS];
struct sun_partition *part = &sunlabel->partitions[n];
@@ -394,9 +395,9 @@ void add_sun_partition(int n, int sys)
snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
for (;;) {
if (whole_disk)
- first = read_int(0, 0, 0, 0, mesg);
+ first = read_int(cxt, 0, 0, 0, 0, mesg);
else
- first = read_int(scround(start), scround(stop)+1,
+ first = read_int(cxt, scround(start), scround(stop)+1,
scround(stop), 0, mesg);
if (display_in_cyl_units)
first *= units_per_sector;
@@ -451,13 +452,13 @@ and is of type `Whole disk'\n"));
_("Last %s or +size or +sizeM or +sizeK"),
str_units(SINGULAR));
if (whole_disk)
- last = read_int(scround(stop2), scround(stop2), scround(stop2),
+ last = read_int(cxt, scround(stop2), scround(stop2), scround(stop2),
0, mesg);
else if (n == 2 && !first)
- last = read_int(scround(first), scround(stop2), scround(stop2),
+ last = read_int(cxt, scround(first), scround(stop2), scround(stop2),
scround(first), mesg);
else
- last = read_int(scround(first), scround(stop), scround(stop),
+ last = read_int(cxt, scround(first), scround(stop), scround(stop),
scround(first), mesg);
if (display_in_cyl_units)
last *= units_per_sector;
@@ -480,7 +481,7 @@ and is of type `Whole disk'\n"));
if (whole_disk)
sys = SUN_TAG_BACKUP;
- set_sun_partition(n, first, last, sys);
+ set_sun_partition(cxt, n, first, last, sys);
}
void sun_delete_partition(int i)
@@ -586,10 +587,10 @@ void sun_list_table(struct fdisk_context *cxt, int xtra)
}
}
-void sun_set_alt_cyl(void)
+void sun_set_alt_cyl(struct fdisk_context *cxt)
{
sunlabel->acyl =
- SSWAP16(read_int(0,SSWAP16(sunlabel->acyl), 65535, 0,
+ SSWAP16(read_int(cxt, 0,SSWAP16(sunlabel->acyl), 65535, 0,
_("Number of alternate cylinders")));
}
@@ -598,31 +599,31 @@ void sun_set_ncyl(int cyl)
sunlabel->ncyl = SSWAP16(cyl);
}
-void sun_set_xcyl(void)
+void sun_set_xcyl(struct fdisk_context *cxt)
{
sunlabel->apc =
- SSWAP16(read_int(0, SSWAP16(sunlabel->apc), sectors, 0,
+ SSWAP16(read_int(cxt, 0, SSWAP16(sunlabel->apc), sectors, 0,
_("Extra sectors per cylinder")));
}
-void sun_set_ilfact(void)
+void sun_set_ilfact(struct fdisk_context *cxt)
{
sunlabel->intrlv =
- SSWAP16(read_int(1, SSWAP16(sunlabel->intrlv), 32, 0,
+ SSWAP16(read_int(cxt, 1, SSWAP16(sunlabel->intrlv), 32, 0,
_("Interleave factor")));
}
-void sun_set_rspeed(void)
+void sun_set_rspeed(struct fdisk_context *cxt)
{
sunlabel->rpm =
- SSWAP16(read_int(1, SSWAP16(sunlabel->rpm), 100000, 0,
+ SSWAP16(read_int(cxt, 1, SSWAP16(sunlabel->rpm), 100000, 0,
_("Rotation speed (rpm)")));
}
-void sun_set_pcylcount(void)
+void sun_set_pcylcount(struct fdisk_context *cxt)
{
sunlabel->pcyl =
- SSWAP16(read_int(0, SSWAP16(sunlabel->pcyl), 65535, 0,
+ SSWAP16(read_int(cxt, 0, SSWAP16(sunlabel->pcyl), 65535, 0,
_("Number of physical cylinders")));
}
diff --git a/fdisk/fdisksunlabel.h b/fdisk/fdisksunlabel.h
index f33fe1cf5..8cb13ec17 100644
--- a/fdisk/fdisksunlabel.h
+++ b/fdisk/fdisksunlabel.h
@@ -84,14 +84,14 @@ extern void sun_delete_partition(int i);
extern int sun_change_sysid(int i, uint16_t sys);
extern void sun_list_table(struct fdisk_context *cxt, int xtra);
extern void verify_sun(void);
-extern void add_sun_partition(int n, int sys);
+extern void add_sun_partition(struct fdisk_context *cxt, int n, int sys);
extern void sun_write_table(struct fdisk_context *cxt);
-extern void sun_set_alt_cyl(void);
+extern void sun_set_alt_cyl(struct fdisk_context *cxt);
extern void sun_set_ncyl(int cyl);
-extern void sun_set_xcyl(void);
-extern void sun_set_ilfact(void);
-extern void sun_set_rspeed(void);
-extern void sun_set_pcylcount(void);
+extern void sun_set_xcyl(struct fdisk_context *cxt);
+extern void sun_set_ilfact(struct fdisk_context *cxt);
+extern void sun_set_rspeed(struct fdisk_context *cxt);
+extern void sun_set_pcylcount(struct fdisk_context *cxt);
extern void toggle_sunflags(int i, uint16_t mask);
extern int sun_get_sysid(int i);
diff --git a/fdisk/utils.c b/fdisk/utils.c
index 3a12e2e28..5de4cab02 100644
--- a/fdisk/utils.c
+++ b/fdisk/utils.c
@@ -20,12 +20,82 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#ifdef HAVE_LIBBLKID
+#include <blkid.h>
+#endif
+#include "nls.h"
+#include "blkdev.h"
#include "common.h"
#include "fdisk.h"
int fdisk_debug_mask;
+static unsigned long __get_sector_size(int fd)
+{
+ unsigned int sect_sz;
+
+ if (!blkdev_get_sector_size(fd, &sect_sz))
+ return (unsigned long) sect_sz;
+ return DEFAULT_SECTOR_SIZE;
+}
+
+static int __discover_topology(struct fdisk_context *cxt)
+{
+#ifdef HAVE_LIBBLKID
+ blkid_probe pr;
+
+ pr = blkid_new_probe();
+ if (pr && blkid_probe_set_device(pr, cxt->dev_fd, 0, 0) == 0) {
+ blkid_topology tp = blkid_probe_get_topology(pr);
+
+ if (tp) {
+ cxt->min_io_size = blkid_topology_get_minimum_io_size(tp);
+ cxt->io_size = blkid_topology_get_optimal_io_size(tp);
+ cxt->phy_sector_size = blkid_topology_get_physical_sector_size(tp);
+ cxt->alignment_offset = blkid_topology_get_alignment_offset(tp);
+
+ if (!cxt->io_size)
+ /* optimal IO is optional, default to minimum IO */
+ cxt->io_size = cxt->min_io_size;
+ }
+ }
+ blkid_free_probe(pr);
+#endif
+
+ /* no blkid or error, use default values */
+ if (!cxt->min_io_size) cxt->min_io_size = DEFAULT_SECTOR_SIZE;
+ if (!cxt->io_size) cxt->io_size = DEFAULT_SECTOR_SIZE;
+
+ cxt->sector_size = __get_sector_size(cxt->dev_fd);
+ if (!cxt->phy_sector_size) /* could not discover physical size */
+ cxt->phy_sector_size = cxt->sector_size;
+ if (cxt->sector_size != DEFAULT_SECTOR_SIZE)
+ printf(_("Note: sector size is %ld (not %d)\n"),
+ cxt->sector_size, DEFAULT_SECTOR_SIZE);
+
+ return 0;
+}
+
+/**
+ * fdisk_dev_has_topology:
+ * @cxt: fdisk context
+ *
+ * Returns 1 if the device provides topology information, otherwise 0.
+ */
+int fdisk_dev_has_topology(struct fdisk_context *cxt)
+{
+ /*
+ * 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.
+ */
+ if (cxt->io_size || cxt->alignment_offset ||
+ (cxt->min_io_size & (cxt->min_io_size - 1)))
+ return 1;
+ return 0;
+}
+
/**
* fdisk_init_debug:
* @mask: debug mask (0xffff to enable full debuging)
@@ -81,9 +151,10 @@ struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int rea
cxt->dev_path = strdup(fname);
if (!cxt->dev_path)
goto fail;
+ __discover_topology(cxt);
DBG(CONTEXT, dbgprint("context initialized for %s [%s]",
- fname, readonly ? "READ-ONLY" : "READ-WRITE"));
+ fname, readonly ? "READ-ONLY" : "READ-WRITE"));
return cxt;
fail:
errsv = errno;