]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: (dos) cleanup template based partitioning
authorKarel Zak <kzak@redhat.com>
Tue, 11 Jul 2017 10:25:02 +0000 (12:25 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 14 Jul 2017 09:46:35 +0000 (11:46 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
libfdisk/src/dos.c
libfdisk/src/partition.c

index 588635f00d79d830288791669cccbdd3249d0ecb..da21b0956a227ab35873da6059382fb2439e7c82 100644 (file)
@@ -1561,59 +1561,67 @@ static int dos_add_partition(struct fdisk_context *cxt,
         * partition template (@pa) based partitioning
         */
 
-       /* pa specifies start within extended partition, add logical */
+       /* A) template specifies start within extended partition; add logical */
        if (pa && fdisk_partition_has_start(pa) && ext_pe
            && pa->start >= l->ext_offset
            && pa->start <= get_abs_partition_end(ext_pe)) {
-               DBG(LABEL, ul_debug("DOS: pa template %p: add logical", pa));
+               DBG(LABEL, ul_debug("DOS: pa template %p: add logical (by offset)", pa));
+
+               if (fdisk_partition_has_partno(pa) && fdisk_partition_get_partno(pa) < 4) {
+                       DBG(LABEL, ul_debug("DOS: pa template specifies partno<4 for logical partition"));
+                       return -EINVAL;
+               }
                rc = add_logical(cxt, pa, &res);
                goto done;
 
-       /* pa specifies that extended partition is wanted */
-       } else if (pa && pa->type && IS_EXTENDED(pa->type->code)) {
-               DBG(LABEL, ul_debug("DOS: pa template %p: add extended", pa));
-               if (l->ext_offset) {
-                       fdisk_warnx(cxt, _("Extended partition already exists."));
+       /* B) template specifies start out of extended partition; add primary */
+       } else if (pa && fdisk_partition_has_start(pa) && ext_pe) {
+               DBG(LABEL, ul_debug("DOS: pa template %p: add primary (by offset)", pa));
+
+               if (fdisk_partition_has_partno(pa) && fdisk_partition_get_partno(pa) >= 4) {
+                       DBG(LABEL, ul_debug("DOS: pa template specifies partno>=4 for primary partition"));
                        return -EINVAL;
                }
-               rc = get_partition_unused_primary(cxt, pa, &res);
-               if (rc == 0) {
-                       rc = add_partition(cxt, res, pa);
-                       goto done;
+               if (pa->type && IS_EXTENDED(pa->type->code)) {
+                       fdisk_warnx(cxt, _("Extended partition already exists."));
+                       return -EINVAL;
                }
-
-       /* pa specifies start, but outside extended partition */
-       } else if (pa && fdisk_partition_has_start(pa) && l->ext_offset) {
-               DBG(LABEL, ul_debug("DOS: pa template %p: add primary", pa));
                rc = get_partition_unused_primary(cxt, pa, &res);
                if (rc == 0)
                        rc = add_partition(cxt, res, pa);
                goto done;
 
-       /* pa follows default, but partno < 4, it means primary partition */
-       } else if (pa && fdisk_partition_start_is_default(pa)
+       /* C) template specifies start (or default), partno < 4; add primary */
+       } else if (pa && (fdisk_partition_start_is_default(pa) || fdisk_partition_has_start(pa))
                   && fdisk_partition_has_partno(pa)
                   && pa->partno < 4) {
-               DBG(LABEL, ul_debug("DOS: pa template %p: add primary (partno < 4)", pa));
+               DBG(LABEL, ul_debug("DOS: pa template %p: add primary (by partno)", pa));
+
+               if (ext_pe && pa->type && IS_EXTENDED(pa->type->code)) {
+                       fdisk_warnx(cxt, _("Extended partition already exists."));
+                       return -EINVAL;
+               }
                rc = get_partition_unused_primary(cxt, pa, &res);
                if (rc == 0)
                        rc = add_partition(cxt, res, pa);
                goto done;
 
-       /* pa follows default, but partno >= 4, it means logical partition */
+       /* D) template specifies default start, partno >= 4; add logical */
        } else if (pa && fdisk_partition_start_is_default(pa)
-                  && ext_pe
                   && fdisk_partition_has_partno(pa)
                   && pa->partno >= 4) {
-               DBG(LABEL, ul_debug("DOS: pa template %p: add logical (partno >= 4)", pa));
+               DBG(LABEL, ul_debug("DOS: pa template %p: add logical (by partno)", pa));
+
+               if (!ext_pe) {
+                       fdisk_warnx(cxt, _("Extended partition does not exists. Failed to add logical partition"));
+                       return -EINVAL;
+               }
                rc = add_logical(cxt, pa, &res);
                goto done;
        }
 
-       /*
-        * dialog driven partitioning (it does not mean that @pa template is
-        * completely ignored!)
-        */
+       DBG(LABEL, ul_debug("DOS: dialog driven partitioning"));
+       /* Note @pa may be still used for things like partition type, etc */
 
        /* check if there is space for primary partition */
        grain = cxt->grain > cxt->sector_size ? cxt->grain / cxt->sector_size : 1;
index 95baea0c21b07f35021ff8983f6f372bd7eeb9b0..6d996e7d7b8ed2399d2464bf4cbfcecd21062499 100644 (file)
@@ -1337,6 +1337,18 @@ int fdisk_partition_has_wipe(struct fdisk_context *cxt, struct fdisk_partition *
  * If @pa is not specified or any @pa item is missing the libfdisk will ask by
  * fdisk_ask_ API.
  *
+ * The @pa template is is important for non-interactive partitioning,
+ * especially for MBR where is necessary to differentiate between
+ * primary/logical; this is done by start offset or/and partno.
+ * The rules for MBR:
+ *
+ *   A) template specifies start within extended partition: add logical
+ *   B) template specifies start out of extended partition: add primary
+ *   C) template specifies start (or default), partno < 4: add primary
+ *   D) template specifies default start, partno >= 4: add logical
+ *
+ * otherwise MBR driver uses Ask-API to get missing information.
+ *
  * Adds a new partition to disklabel.
  *
  * Returns: 0 on success, <0 on error.