int nowarn = 0; /* no warnings for fdisk -l/-s */
-/* when C/H/S specified on command line */
-static unsigned int user_cylinders, user_heads, user_sectors;
-
void toggle_units(struct fdisk_context *cxt)
{
fdisk_context_set_unit(cxt,
}
/* Print disk geometry and partition table of a specified device (-l option) */
-static void print_partition_table_from_option(struct fdisk_context *cxt,
- char *device, unsigned long sector_size)
+static void print_partition_table_from_option(
+ struct fdisk_context *cxt,
+ char *device)
{
if (fdisk_context_assign_device(cxt, device, 1) != 0) /* read-only */
err(EXIT_FAILURE, _("cannot open %s"), device);
- if (sector_size) /* passed -b option, override autodiscovery */
- fdisk_override_sector_size(cxt, sector_size);
-
- if (user_cylinders || user_heads || user_sectors)
- fdisk_override_geometry(cxt, user_cylinders,
- user_heads, user_sectors);
-
if (fdisk_dev_has_disklabel(cxt))
list_table(cxt, 0);
else
* try all things in /proc/partitions that look like a full disk
*/
static void
-print_all_partition_table_from_option(struct fdisk_context *cxt,
- unsigned long sector_size)
+print_all_partition_table_from_option(struct fdisk_context *cxt)
{
FILE *procpt;
char line[128 + 1], ptname[128 + 1], devname[256];
char *cn = canonicalize_path(devname);
if (cn) {
if (!is_ide_cdrom_or_tape(cn))
- print_partition_table_from_option(cxt, cn, sector_size);
+ print_partition_table_from_option(cxt, cn);
free(cn);
}
}
if (sector_size != 512 && sector_size != 1024 &&
sector_size != 2048 && sector_size != 4096)
usage(stderr);
+ fdisk_save_user_sector_size(cxt, sector_size, sector_size);
break;
case 'C':
- user_cylinders = strtou32_or_err(optarg, _("invalid cylinders argument"));
+ fdisk_save_user_geometry(cxt,
+ strtou32_or_err(optarg,
+ _("invalid cylinders argument")),
+ 0, 0);
break;
case 'c':
if (optarg) {
/* use default if no optarg specified */
break;
case 'H':
- user_heads = strtou32_or_err(optarg, _("invalid heads argument"));
- if (user_heads > 256)
- user_heads = 0;
+ fdisk_save_user_geometry(cxt, 0,
+ strtou32_or_err(optarg,
+ _("invalid heads argument")),
+ 0);
break;
case 'S':
- user_sectors = strtou32_or_err(optarg, _("invalid sectors argument"));
- if (user_sectors >= 64)
- user_sectors = 0;
+ fdisk_save_user_geometry(cxt, 0, 0,
+ strtou32_or_err(optarg,
+ _("invalid sectors argument")));
break;
case 'l':
optl = 1;
if (argc > optind) {
int k;
for (k = optind; k < argc; k++)
- print_partition_table_from_option(cxt, argv[k], sector_size);
+ print_partition_table_from_option(cxt, argv[k]);
} else
- print_all_partition_table_from_option(cxt, sector_size);
+ print_all_partition_table_from_option(cxt);
exit(EXIT_SUCCESS);
}
if (fdisk_context_assign_device(cxt, argv[optind], 0) != 0)
err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);
- if (sector_size) /* passed -b option, override autodiscovery */
- fdisk_override_sector_size(cxt, sector_size);
-
- if (user_cylinders || user_heads || user_sectors)
- fdisk_override_geometry(cxt, user_cylinders,
- user_heads, user_sectors);
-
print_welcome();
if (!fdisk_dev_has_disklabel(cxt)) {
}
}
+ if (lba != res)
+ DBG(TOPOLOGY, dbgprint("LBA %ju -aligned-to-> %ju",
+ (uintmax_t) lba,
+ (uintmax_t) res));
return res;
}
return DEFAULT_SECTOR_SIZE;
}
-/**
- * fdisk_override_sector_size:
- * @cxt: fdisk context
- * @s: required sector size
- *
- * Overwrites logical and physical sector size. Note that the default sector
- * size is discovered by fdisk_new_context_from_device() from device topology.
- *
- * Don't use this function, rely on the default behavioer is more safe.
- *
- * Returns: 0 on success, < 0 on error.
- */
-int fdisk_override_sector_size(struct fdisk_context *cxt, sector_t s)
-{
- if (!cxt)
- return -EINVAL;
-
- cxt->phy_sector_size = cxt->sector_size = s;
- cxt->min_io_size = cxt->io_size = s;
-
- fdisk_reset_alignment(cxt);
- return 0;
-}
-
static void recount_geometry(struct fdisk_context *cxt)
{
cxt->geom.cylinders = cxt->total_sectors /
* @heads: user specified heads
* @sectors: user specified sectors
*
- * Overrides autodiscovery and apply user specified geometry.
+ * Overrides autodiscovery and apply user specified geometry. The function
+ * fdisk_reset_device_properties() restores the original setting.
*
* Returns: 0 on success, < 0 on error.
*/
recount_geometry(cxt);
fdisk_reset_alignment(cxt);
+
+ DBG(GEOMETRY, dbgprint("override C/H/S: %u/%u/%u",
+ (unsigned) cxt->geom.cylinders,
+ (unsigned) cxt->geom.heads,
+ (unsigned) cxt->geom.sectors));
+
+ return 0;
+}
+
+int fdisk_save_user_geometry(struct fdisk_context *cxt,
+ unsigned int cylinders,
+ unsigned int heads,
+ unsigned int sectors)
+{
+ if (!cxt)
+ return -EINVAL;
+
+ cxt->user_geom.heads = heads > 256 ? 0 : heads;
+ cxt->user_geom.sectors = sectors >= 64 ? 0 : sectors;
+ cxt->user_geom.cylinders = cylinders;
+
+ DBG(GEOMETRY, dbgprint("user C/H/S: %u/%u/%u",
+ cylinders, heads, sectors));
+
+ return 0;
+}
+
+int fdisk_save_user_sector_size(struct fdisk_context *cxt,
+ unsigned int phy,
+ unsigned int log)
+{
+ if (!cxt)
+ return -EINVAL;
+
+ DBG(TOPOLOGY, dbgprint("user phy/log sector size: %u/%u", phy, log));
+
+ cxt->user_pyh_sector = phy;
+ cxt->user_log_sector = log;
+
+ return 0;
+}
+
+int fdisk_apply_user_device_properties(struct fdisk_context *cxt)
+{
+ if (!cxt)
+ return -EINVAL;
+
+ DBG(TOPOLOGY, dbgprint("appling user device properties"));
+
+ if (cxt->user_pyh_sector)
+ cxt->phy_sector_size = cxt->user_pyh_sector;
+ if (cxt->user_log_sector)
+ cxt->sector_size = cxt->min_io_size =
+ cxt->io_size = cxt->user_log_sector;
+
+ if (cxt->user_geom.heads)
+ cxt->geom.heads = cxt->user_geom.heads;
+ if (cxt->user_geom.sectors)
+ cxt->geom.sectors = cxt->user_geom.sectors;
+ if (cxt->user_geom.cylinders)
+ cxt->geom.cylinders = cxt->user_geom.cylinders;
+ else if (cxt->user_geom.heads || cxt->user_geom.sectors)
+ recount_geometry(cxt);
+
+ fdisk_reset_alignment(cxt);
+
+ DBG(GEOMETRY, dbgprint("new C/H/S: %u/%u/%u",
+ (unsigned) cxt->geom.cylinders,
+ (unsigned) cxt->geom.heads,
+ (unsigned) cxt->geom.sectors));
+ DBG(TOPOLOGY, dbgprint("new log/phy sector size: %u/%u",
+ (unsigned) cxt->sector_size,
+ (unsigned) cxt->phy_sector_size));
+
+ return 0;
+}
+
+void fdisk_zeroize_device_properties(struct fdisk_context *cxt)
+{
+ assert(cxt);
+
+ cxt->io_size = 0;
+ cxt->optimal_io_size = 0;
+ cxt->min_io_size = 0;
+ cxt->phy_sector_size = 0;
+ cxt->sector_size = 0;
+ cxt->alignment_offset = 0;
+ cxt->grain = 0;
+ cxt->first_lba = 0;
+ cxt->total_sectors = 0;
+
+ memset(&cxt->geom, 0, sizeof(struct fdisk_geometry));
+}
+
+int fdisk_reset_device_properties(struct fdisk_context *cxt)
+{
+ int rc;
+
+ if (!cxt)
+ return -EINVAL;
+
+ DBG(TOPOLOGY, dbgprint("*** reseting device properties"));
+
+ fdisk_zeroize_device_properties(cxt);
+ fdisk_discover_topology(cxt);
+ fdisk_discover_geometry(cxt);
+
+ rc = fdisk_read_firstsector(cxt);
+ if (rc)
+ return rc;
+
+ fdisk_apply_user_device_properties(cxt);
return 0;
}
assert(cxt);
assert(cxt->geom.heads == 0);
+ DBG(GEOMETRY, dbgprint("%s: discovering geometry...", cxt->dev_path));
+
/* get number of 512-byte sectors, and convert it the real sectors */
if (!blkdev_get_sectors(cxt->dev_fd, &nsects))
cxt->total_sectors = (nsects / (cxt->sector_size >> 9));
cxt->geom.sectors = s;
recount_geometry(cxt);
- DBG(GEOMETRY, dbgprint("geometry discovered for %s: C/H/S: %lld/%d/%lld",
- cxt->dev_path, cxt->geom.cylinders,
- cxt->geom.heads, cxt->geom.sectors));
+ DBG(GEOMETRY, dbgprint("result: C/H/S: %u/%u/%u",
+ (unsigned) cxt->geom.cylinders,
+ (unsigned) cxt->geom.heads,
+ (unsigned) cxt->geom.sectors));
return 0;
}
assert(cxt);
assert(cxt->sector_size == 0);
+ DBG(TOPOLOGY, dbgprint("%s: discovering topology...", cxt->dev_path));
#ifdef HAVE_LIBBLKID
DBG(TOPOLOGY, dbgprint("initialize libblkid prober"));
if (!cxt->io_size)
cxt->io_size = cxt->sector_size;
- DBG(TOPOLOGY, dbgprint("topology discovered for %s:\n"
- "\tlogical/physical sector sizes: %ld/%ld\n"
- "\tfdisk/minimal/optimal io sizes: %ld/%ld/%ld\n",
- cxt->dev_path, cxt->sector_size, cxt->phy_sector_size,
- cxt->io_size, cxt->optimal_io_size, cxt->min_io_size));
+ DBG(TOPOLOGY, dbgprint("result: log/phy sector size: %ld/%ld",
+ cxt->sector_size, cxt->phy_sector_size));
+ DBG(TOPOLOGY, dbgprint("result: fdisk/min/optimal io: %ld/%ld/%ld",
+ cxt->io_size, cxt->optimal_io_size, cxt->min_io_size));
return 0;
}
if (!cxt)
return -EINVAL;
+ DBG(TOPOLOGY, dbgprint("reseting alignment..."));
+
/* default */
cxt->grain = fdisk_topology_get_grain(cxt);
cxt->first_lba = fdisk_topology_get_first_lba(cxt);
{
size_t i;
- DBG(CONTEXT, dbgprint("\n-----\nresetting context %p", cxt));
+ DBG(CONTEXT, dbgprint("*** resetting context %p", cxt));
/* reset drives' private data */
for (i = 0; i < cxt->nlabels; i++)
cxt->dev_path = NULL;
cxt->firstsector = NULL;
- cxt->io_size = 0;
- cxt->optimal_io_size = 0;
- cxt->min_io_size = 0;
- cxt->phy_sector_size = 0;
- cxt->sector_size = 0;
- cxt->alignment_offset = 0;
- cxt->grain = 0;
- cxt->first_lba = 0;
- cxt->total_sectors = 0;
-
- memset(&cxt->geom, 0, sizeof(struct fdisk_geometry));
+ fdisk_zeroize_device_properties(cxt);
cxt->label = NULL;
}
/* detect labels and apply labes specific stuff (e.g geomery)
* to the context */
fdisk_probe_labels(cxt);
- fdisk_reset_alignment(cxt);
+
+ /* let's apply user geometry *after* label prober
+ * to make it possible to override in-label setting */
+ fdisk_apply_user_device_properties(cxt);
DBG(CONTEXT, dbgprint("context %p initialized for %s [%s]",
cxt, fname,
sector_t first_lba; /* recommended begin of the first partition */
/* geometry */
- sector_t total_sectors; /* in logical sectors */
+ sector_t total_sectors; /* in logical sectors */
struct fdisk_geometry geom;
+ /* user setting to overwrite device default */
+ struct fdisk_geometry user_geom;
+ unsigned long user_pyh_sector;
+ unsigned long user_log_sector;
+
struct fdisk_label *label; /* current label, pointer to labels[] */
size_t nlabels; /* number of initialized label drivers */
sector_t start, sector_t stop);
-extern int fdisk_override_sector_size(struct fdisk_context *cxt, sector_t s);
extern int fdisk_override_geometry(struct fdisk_context *cxt,
unsigned int cylinders, unsigned int heads,
unsigned int sectors);
extern int fdisk_discover_geometry(struct fdisk_context *cxt);
extern int fdisk_discover_topology(struct fdisk_context *cxt);
+extern int fdisk_apply_user_device_properties(struct fdisk_context *cxt);
+extern void fdisk_zeroize_device_properties(struct fdisk_context *cxt);
+
/* utils.c */
extern void fdisk_zeroize_firstsector(struct fdisk_context *cxt);
extern int fdisk_read_firstsector(struct fdisk_context *cxt);
*/
int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name)
{
+ int haslabel = 0;
+
if (!cxt)
return -EINVAL;
#endif
}
- if (cxt->label)
+ if (cxt->label) {
fdisk_deinit_label(cxt->label);
+ haslabel = 1;
+ }
cxt->label = fdisk_context_get_label(cxt, name);
if (!cxt->label)
if (!cxt->label->op->create)
return -ENOSYS;
- fdisk_reset_alignment(cxt);
+ if (haslabel)
+ fdisk_reset_device_properties(cxt);
return cxt->label->op->create(cxt);
}
/* alignment.c */
extern int fdisk_reset_alignment(struct fdisk_context *cxt);
+extern int fdisk_reset_device_properties(struct fdisk_context *cxt);
+
+extern int fdisk_save_user_geometry(struct fdisk_context *cxt,
+ unsigned int cylinders,
+ unsigned int heads,
+ unsigned int sectors);
+
+extern int fdisk_save_user_sector_size(struct fdisk_context *cxt,
+ unsigned int phy,
+ unsigned int log);
/* dos.c */