summaryrefslogtreecommitdiffstats
path: root/libfdisk/src/dos.c
diff options
context:
space:
mode:
authorKarel Zak2014-09-08 16:13:42 +0200
committerKarel Zak2014-10-07 14:55:31 +0200
commitea987bb509054e962f1aeb322082f1080f7e0e8a (patch)
treedaf176767de7380a7b784955ccebcf1d4c98233b /libfdisk/src/dos.c
parentsfdisk: cleanup comments and command_activate() (diff)
downloadkernel-qcow2-util-linux-ea987bb509054e962f1aeb322082f1080f7e0e8a.tar.gz
kernel-qcow2-util-linux-ea987bb509054e962f1aeb322082f1080f7e0e8a.tar.xz
kernel-qcow2-util-linux-ea987bb509054e962f1aeb322082f1080f7e0e8a.zip
libfdisk: (dos) more carefully check for primary partitions
* check if there is space for primary partitions, if no and extended exists then create logical partitions * create extended if @pa->type is extended partition Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk/src/dos.c')
-rw-r--r--libfdisk/src/dos.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index 3cc156eee..76080c207 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -1379,7 +1379,8 @@ static int dos_verify_disklabel(struct fdisk_context *cxt)
static int dos_add_partition(struct fdisk_context *cxt,
struct fdisk_partition *pa)
{
- size_t i, free_primary = 0;
+ size_t i, free_primary = 0, free_sectors = 0;
+ sector_t last = 0, grain;
int rc = 0;
struct fdisk_dos_label *l;
struct pte *ext_pe;
@@ -1408,12 +1409,38 @@ static int dos_add_partition(struct fdisk_context *cxt,
goto done;
}
+ /* pa specifies that extended partition is wanted */
+ } else if (pa && pa->type && pa->type->code == MBR_DOS_EXTENDED_PARTITION) {
+ int j;
+
+ if (l->ext_offset) {
+ fdisk_warnx(cxt, _("Extended partition already exists."));
+ return -EINVAL;
+ }
+ j = get_partition_unused_primary(cxt, pa);
+ if (j >= 0) {
+ rc = add_partition(cxt, j, pa);
+ goto done;
+ }
}
+ /* check if there is space for primary partition */
+ grain = cxt->grain > cxt->sector_size ? cxt->grain / cxt->sector_size : 1;
+ last = cxt->first_lba;
+
for (i = 0; i < 4; i++) {
struct dos_partition *p = self_partition(cxt, i);
- free_primary += !is_used_partition(p);
+
+ if (is_used_partition(p)) {
+ sector_t start = dos_partition_get_start(p);
+ if (last + grain <= start)
+ free_sectors = 1;
+ last = start + dos_partition_get_size(p);
+ } else
+ free_primary++;
}
+ if (last + grain < cxt->total_sectors - 1)
+ free_sectors = 1;
if (!free_primary && cxt->label->nparts_max >= MAXIMUM_PARTS) {
fdisk_info(cxt, _("The maximum number of partitions has "
@@ -1422,16 +1449,20 @@ static int dos_add_partition(struct fdisk_context *cxt,
}
rc = 1;
- if (!free_primary) {
+ if (!free_primary || !free_sectors) {
if (l->ext_offset) {
- fdisk_info(cxt, _("All primary partitions are in use."));
+ if (!free_primary)
+ fdisk_info(cxt, _("All primary partitions are in use."));
+ else if (!free_sectors)
+ fdisk_info(cxt, _("All space for primary partitions are in use."));
rc = add_logical(cxt, pa);
- } else
+ } else {
fdisk_info(cxt, _("If you want to create more than "
"four partitions, you must replace a "
"primary partition with an extended "
"partition first."));
-
+ return -EINVAL;
+ }
} else if (cxt->label->nparts_max >= MAXIMUM_PARTS) {
int j;
@@ -1445,6 +1476,14 @@ static int dos_add_partition(struct fdisk_context *cxt,
struct fdisk_ask *ask;
int c;
+ /* the default layout for scripts is to create primary partitions */
+ if (cxt->script) {
+ int j = get_partition_unused_primary(cxt, pa);
+ if (j >= 0)
+ rc = add_partition(cxt, j, pa);
+ goto done;
+ }
+
ask = fdisk_new_ask();
if (!ask)
return -ENOMEM;