]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
sfdisk: support -N for primary partitions
authorKarel Zak <kzak@redhat.com>
Wed, 10 Sep 2014 12:31:28 +0000 (14:31 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 7 Oct 2014 12:55:31 +0000 (14:55 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
disk-utils/sfdisk.c

index 3357ed2aaeb54b3eaeb4c2e15eed1516a3f61c40..c845c2d8ecbfd92985875e5d020c3a14dba4a8cb 100644 (file)
@@ -360,8 +360,88 @@ static int command_dump(struct sfdisk *sf, int argc, char **argv)
        return 0;
 }
 
+/* appply things from @tpl template to the on-disk partition @n */
+static int sfdisk_modify_partition(struct sfdisk *sf,
+                              struct fdisk_partition *tpl,
+                              size_t n)
+{
+       struct fdisk_partition *pa = NULL;
+       const struct fdisk_parttype *type;
+       const char *data;
+       sector_t num;
+       size_t new_partno = 0;
+       int rc = 0;
+
+       /* get the current partition */
+       rc = fdisk_get_partition(sf->cxt, n, &pa);
+       if (rc)
+               goto done;
+
+       assert(n == fdisk_partition_get_partno(pa));
+
+       /* uuid */
+       data = fdisk_partition_get_uuid(tpl);
+       if (data) {
+               rc = fdisk_partition_set_uuid(pa, data);
+               if (rc)
+                       goto done;
+       }
+
+       /* name */
+       data = fdisk_partition_get_name(tpl);
+       if (data) {
+               rc = fdisk_partition_set_name(pa, data);
+               if (rc)
+                       goto done;
+       }
+
+       /* attributes
+       data = fdisk_partition_get_attrs(tpl);
+       if (data) {
+               rc = fdisk_partition_set_attrs(pa, data);
+               if (rc)
+                       goto done;
+       }*/
+
+       /* type */
+       type = fdisk_partition_get_type(tpl);
+       if (type) {
+               rc = fdisk_partition_set_type(pa, type);
+               if (rc)
+                       goto done;
+       }
 
-static void sfdisk_print_partition(struct sfdisk *sf, int n)
+       /* size */
+       num = fdisk_partition_get_size(tpl);
+       if (num) {
+               rc = fdisk_partition_set_size(pa, num);
+               if (rc)
+                       goto done;
+       }
+
+       /* start */
+       num = fdisk_partition_get_start(tpl);
+       if (num) {
+               rc = fdisk_partition_set_start(pa, num);
+               if (rc)
+                       goto done;
+       }
+
+       /* drop the old partition */
+       rc = fdisk_delete_partition(sf->cxt, n);
+       if (rc)
+               goto done;
+
+       /* add a new partition */
+       rc = fdisk_add_partition(sf->cxt, pa, &new_partno);
+       assert(new_partno == n);
+done:
+       fdisk_unref_partition(pa);
+       return rc;
+}
+
+
+static void sfdisk_print_partition(struct sfdisk *sf, size_t n)
 {
        struct fdisk_partition *pa = NULL;
        char *data;
@@ -495,6 +575,7 @@ static int command_fdisk(struct sfdisk *sf, int argc, char **argv)
        if (!devname)
                errx(EXIT_FAILURE, _("no disk device specified"));
 
+
        dp = fdisk_new_script(sf->cxt);
        if (!dp)
                err(EXIT_FAILURE, _("failed to allocate script handler"));
@@ -503,6 +584,25 @@ static int command_fdisk(struct sfdisk *sf, int argc, char **argv)
        if (rc)
                err(EXIT_FAILURE, _("cannot open %s"), devname);
 
+       /*
+        * Don't create a new disklabel when [-N] <partno> specified. In this
+        * case reuse already specified disklabel. Let's check that the disk
+        * really contains the partition.
+        */
+       if (partno >= 0) {
+               size_t n;
+               if (!fdisk_has_label(sf->cxt))
+                       errx(EXIT_FAILURE, _("cannot modify partition %d, "
+                                            "not found partition table."), partno);
+               n = fdisk_get_npartitions(sf->cxt);
+               if ((size_t) partno > n)
+                       errx(EXIT_FAILURE, _("cannot modify partition %d, "
+                                            "partition table contains %zu "
+                                            "partitions only."), partno, n);
+               created = 1;
+               next_partno = partno;
+       }
+
        if (isatty(STDIN_FILENO)) {
                color_scheme_enable("welcome", UL_COLOR_GREEN);
                fdisk_info(sf->cxt, _("\nWelcome to sfdisk (%s)."), PACKAGE_STRING);
@@ -580,11 +680,16 @@ static int command_fdisk(struct sfdisk *sf, int argc, char **argv)
                                fdisk_info(sf->cxt, _("Ignore partition %zu"), next_partno + 1);
                                continue;
                        }
-                       if (!created) {         /* create a disklabel */
+                       if (!created) {         /* create a new disklabel */
                                rc = fdisk_apply_script_headers(sf->cxt, dp);
                                created = !rc;
                        }
-                       if (!rc)                /* cretate partition */
+                       if (!rc && partno >= 0) {       /* -N <partno>, modify partition */
+                               rc = sfdisk_modify_partition(sf, pa, partno);
+                               if (rc == 0)
+                                       rc = SFDISK_DONE_ASK;
+                               break;
+                       } else if (!rc)         /* add partition */
                                rc = fdisk_add_partition(sf->cxt, pa, &cur_partno);
 
                        if (!rc) {              /* success, print reult */
@@ -622,6 +727,7 @@ static int command_fdisk(struct sfdisk *sf, int argc, char **argv)
                }
                break;
        case SFDISK_DONE_ABORT:
+       default:                                /* rc < 0 on error */
                printf(_("Leaving.\n"));
                break;
        }
@@ -695,7 +801,7 @@ int main(int argc, char *argv[])
                        sf->act = ACT_DUMP;
                        break;
                case 'N':
-                       sf->partno = strtou32_or_err(optarg, _("failed to parse partition number"));
+                       sf->partno = strtou32_or_err(optarg, _("failed to parse partition number")) - 1;
                        break;
                case 'X':
                        sf->label = optarg;