]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: return partno when add new partition
authorKarel Zak <kzak@redhat.com>
Tue, 9 Sep 2014 11:04:57 +0000 (13:04 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 7 Oct 2014 12:55:31 +0000 (14:55 +0200)
 * improve the way how sfdisk report results
 * the API change simplify applications

Signed-off-by: Karel Zak <kzak@redhat.com>
13 files changed:
disk-utils/cfdisk.c
disk-utils/fdisk-menu.c
disk-utils/sfdisk.c
libfdisk/src/bsd.c
libfdisk/src/dos.c
libfdisk/src/fdiskP.h
libfdisk/src/gpt.c
libfdisk/src/libfdisk.h
libfdisk/src/partition.c
libfdisk/src/script.c
libfdisk/src/sgi.c
libfdisk/src/sun.c
libfdisk/src/table.c

index 13e98b4b214df6a941382d524f56d4df0dda48cf..4101827f1e41b9454c54066c2cf01a0a36bb97aa 100644 (file)
@@ -1829,7 +1829,7 @@ static int main_menu_action(struct cfdisk *cf, int key)
                fdisk_partition_set_start(npa, start);
                                fdisk_partition_partno_follow_default(npa, 1);
                /* add to disk label -- libfdisk will ask for missing details */
-               rc = fdisk_add_partition(cf->cxt, npa);
+               rc = fdisk_add_partition(cf->cxt, npa, NULL);
                fdisk_unref_partition(npa);
                if (rc == 0)
                        ref = 1;
index efd8dc1c60cdd9e64f05f75a815d406cd42348ef..e9bdc45542679aa91c11236f3bf0d7833670419a 100644 (file)
@@ -520,7 +520,7 @@ static int generic_menu_cb(struct fdisk_context **cxt0,
                list_partition_types(cxt);
                break;
        case 'n':
-               rc = fdisk_add_partition(cxt, NULL);
+               rc = fdisk_add_partition(cxt, NULL, NULL);
                break;
        case 't':
                change_partition_type(cxt);
index 8dc102506353bd732e369eac11014a367143beaf..5381d43dc2f57f9a39fa56d5222daee7e7f0725c 100644 (file)
@@ -317,7 +317,7 @@ static int command_dump(struct sfdisk *sf, int argc, char **argv)
 
 static void sfdisk_print_partition(struct sfdisk *sf, int n)
 {
-       struct fdisk_partition *pa;
+       struct fdisk_partition *pa = NULL;
        char *data;
 
        assert(sf);
@@ -355,6 +355,7 @@ static int command_fdisk(struct sfdisk *sf, int argc, char **argv)
        struct fdisk_table *tb = NULL;
        const char *devname = NULL, *label;
        char buf[BUFSIZ];
+       size_t next_partno = (size_t) -1;
 
        if (argc)
                devname = argv[0];
@@ -387,27 +388,38 @@ static int command_fdisk(struct sfdisk *sf, int argc, char **argv)
 
        printf(_("\nInput in the following format; absent fields get a default value.\n"
                 "<start> <size> <type [uuid, hex or E,S,L,X]> <bootable [-,*]>\n"
-                "Usually you only need to specify <start> and <size>\n"));
+                "Usually you only need to specify <start> and <size>\n\n"));
 
        if (!fdisk_has_label(sf->cxt))
-               printf(_("\nsfdisk is going to create a new '%s' disk label.\n"
+               printf(_("sfdisk is going to create a new '%s' disk label.\n"
                         "Use 'label: <name>' before you define a first partition\n"
-                        "to override the default.\n"), label);
+                        "to override the default.\n\n"), label);
 
        tb = fdisk_script_get_table(dp);
+       assert(tb);
 
        do {
-               size_t nparts = fdisk_table_get_nents(tb);
+               size_t nparts;
                char *partname;
 
-               partname = fdisk_partname(devname, nparts + 1);
+               DBG(PARSE, ul_debug("<---next-line--->"));
+               if (next_partno == (size_t) -1)
+                       next_partno = fdisk_table_get_nents(tb);
+
+               partname = fdisk_partname(devname, next_partno + 1);
                if (!partname)
                        err(EXIT_FAILURE, _("failed to allocate partition name"));
+               fflush(stdout);
                printf("%s: ", partname);
                free(partname);
 
                rc = fdisk_script_read_line(dp, stdin, buf, sizeof(buf));
-               if (rc) {
+
+               if (rc == 1) {          /* end of file */
+                       rc = 0;
+                       break;
+               } else if (rc < 0) {
+                       DBG(PARSE, ul_debug("script parsing failed, trying sfdisk specific commands"));
                        buf[sizeof(buf) - 1] = '\0';
 
                        if (strcmp(buf, "print") == 0)
@@ -424,18 +436,23 @@ static int command_fdisk(struct sfdisk *sf, int argc, char **argv)
 
                nparts = fdisk_table_get_nents(tb);
                if (nparts) {
+                       size_t cur_partno;
                        struct fdisk_partition *pa = fdisk_table_get_partition(tb, nparts - 1);
 
+                       fputc('\n', stdout);
+
+                       assert(pa);
                        if (!created) {         /* create a disklabel */
                                rc = fdisk_apply_script_headers(sf->cxt, dp);
                                created = !rc;
                        }
                        if (!rc)                /* cretate partition */
-                               rc = fdisk_add_partition(sf->cxt, pa);
+                               rc = fdisk_add_partition(sf->cxt, pa, &cur_partno);
 
-                       if (!rc)                /* sucess, print reult */
-                               sfdisk_print_partition(sf, nparts - 1);
-                       else if (pa)            /* error, drop partition from script */
+                       if (!rc) {              /* success, print reult */
+                               sfdisk_print_partition(sf, cur_partno);
+                               next_partno = cur_partno + 1;
+                       } else if (pa)          /* error, drop partition from script */
                                fdisk_table_remove_partition(tb, pa);
                } else
                        printf(_("OK\n"));      /* probably added script header */
index 6dddd3d71ec1167dc5de4b90d7b99c7525895e90..093925ef2f8e451bd63672207f4bbe15bcb504fa 100644 (file)
@@ -194,7 +194,8 @@ static int bsd_probe_label(struct fdisk_context *cxt)
 }
 
 static int bsd_add_partition(struct fdisk_context *cxt,
-                            struct fdisk_partition *pa)
+                            struct fdisk_partition *pa,
+                            size_t *partno)
 {
        struct fdisk_bsd_label *l = self_label(cxt);
        struct bsd_disklabel *d = self_disklabel(cxt);
@@ -297,6 +298,8 @@ static int bsd_add_partition(struct fdisk_context *cxt,
                bsd_set_parttype(cxt, i, pa->type);
 
        fdisk_label_set_changed(cxt->label, 1);
+       if (partno)
+               *partno = i;
        return 0;
 }
 
index 76080c2076c16ede964943c2b0e091b3a80c20c2..b90a01f5ba1007955cca2676878318dcccc693ac 100644 (file)
@@ -946,6 +946,7 @@ static int get_start_from_user(     struct fdisk_context *cxt,
                }
        }
 
+       DBG(LABEL, ul_debug("DOS: start is %ju", (uintmax_t) *start));
        return 0;
 }
 
@@ -1151,11 +1152,14 @@ static int add_partition(struct fdisk_context *cxt, size_t n,
        return 0;
 }
 
-static int add_logical(struct fdisk_context *cxt, struct fdisk_partition *pa)
+static int add_logical(struct fdisk_context *cxt,
+                      struct fdisk_partition *pa,
+                      size_t *partno)
 {
        struct pte *pe;
 
        assert(cxt);
+       assert(partno);
        assert(cxt->label);
        assert(self_label(cxt)->ext_offset);
 
@@ -1179,7 +1183,8 @@ static int add_logical(struct fdisk_context *cxt, struct fdisk_partition *pa)
 
        fdisk_info(cxt, _("Adding logical partition %zu"),
                        cxt->label->nparts_max);
-       return add_partition(cxt, cxt->label->nparts_max - 1, pa);
+       *partno = cxt->label->nparts_max - 1;
+       return add_partition(cxt, *partno, pa);
 }
 
 static void check(struct fdisk_context *cxt, size_t n,
@@ -1377,53 +1382,65 @@ static int dos_verify_disklabel(struct fdisk_context *cxt)
  * API callback.
  */
 static int dos_add_partition(struct fdisk_context *cxt,
-                            struct fdisk_partition *pa)
+                            struct fdisk_partition *pa,
+                            size_t *partno)
 {
        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;
+       size_t res;             /* partno */
 
        assert(cxt);
        assert(cxt->label);
        assert(fdisk_is_label(cxt, DOS));
 
+       DBG(LABEL, ul_debug("DOS: new partition wanted"));
+
        l = self_label(cxt);
        ext_pe = l->ext_offset ? self_pte(cxt, l->ext_index) : NULL;
 
+       /*
+        * partition template (@pa) based partitioning
+        */
+
        /* pa specifies start within extended partition, add logical */
        if (pa && pa->start && ext_pe
            && pa->start >= l->ext_offset
            && pa->start <= get_abs_partition_end(ext_pe)) {
-               rc = add_logical(cxt, pa);
+               DBG(LABEL, ul_debug("DOS: pa template %p: add logical", pa));
+               rc = add_logical(cxt, pa, &res);
                goto done;
 
-       /* pa specifies start, but outside extended partition */
-       } else if (pa && pa->start && l->ext_offset) {
-               int j;
-
-               j = get_partition_unused_primary(cxt, pa);
-               if (j >= 0) {
-                       rc = add_partition(cxt, j, pa);
-                       goto done;
-               }
-
        /* pa specifies that extended partition is wanted */
        } else if (pa && pa->type && pa->type->code == MBR_DOS_EXTENDED_PARTITION) {
-               int j;
-
+               DBG(LABEL, ul_debug("DOS: pa template %p: add extened", pa));
                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);
+               res = get_partition_unused_primary(cxt, pa);
+               if (res >= 0) {
+                       rc = add_partition(cxt, res, pa);
+                       goto done;
+               }
+
+       /* pa specifies start, but outside extended partition */
+       } else if (pa && pa->start && l->ext_offset) {
+               DBG(LABEL, ul_debug("DOS: pa template %p: add primary", pa));
+               res = get_partition_unused_primary(cxt, pa);
+               if (res >= 0) {
+                       rc = add_partition(cxt, res, pa);
                        goto done;
                }
        }
 
+       /*
+        * dialog driven partitioning (it does not mean that @pa template is
+        * completely ignored!)
+        */
+
        /* check if there is space for primary partition */
        grain = cxt->grain > cxt->sector_size ? cxt->grain / cxt->sector_size : 1;
        last = cxt->first_lba;
@@ -1450,27 +1467,29 @@ static int dos_add_partition(struct fdisk_context *cxt,
        rc = 1;
 
        if (!free_primary || !free_sectors) {
+               DBG(LABEL, ul_debug("DOS: primary impossible, add logical"));
                if (l->ext_offset) {
-                       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);
+                       if (!pa || pa->start) {
+                               if (!free_primary)
+                                       fdisk_info(cxt, _("All primary partitions are in use."));
+                               else if (!free_sectors)
+                                       fdisk_info(cxt, _("All space for primary partitions is in use."));
+                       }
+                       rc = add_logical(cxt, pa, &res);
                } else {
-                       fdisk_info(cxt, _("If you want to create more than "
-                               "four partitions, you must replace a "
-                               "primary partition with an extended "
+                       fdisk_info(cxt,
+                            _( "Impossible to create another primary partition. "
+                               "If you want to create more partitions, you must "
+                               "replace a primary partition with an extended "
                                "partition first."));
                        return -EINVAL;
                }
        } else if (cxt->label->nparts_max >= MAXIMUM_PARTS) {
-               int j;
-
                fdisk_info(cxt, _("All logical partitions are in use. "
                                  "Adding a primary partition."));
-               j = get_partition_unused_primary(cxt, pa);
-               if (j >= 0)
-                       rc = add_partition(cxt, j, pa);
+               res = get_partition_unused_primary(cxt, pa);
+               if (res >= 0)
+                       rc = add_partition(cxt, res, pa);
        } else {
                char hint[BUFSIZ];
                struct fdisk_ask *ask;
@@ -1478,9 +1497,9 @@ static int dos_add_partition(struct fdisk_context *cxt,
 
                /* 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);
+                       res = get_partition_unused_primary(cxt, pa);
+                       if (res >= 0)
+                               rc = add_partition(cxt, res, pa);
                        goto done;
                }
 
@@ -1510,16 +1529,16 @@ static int dos_add_partition(struct fdisk_context *cxt,
                fdisk_free_ask(ask);
 
                if (c == 'p') {
-                       int j = get_partition_unused_primary(cxt, pa);
-                       if (j >= 0)
-                               rc = add_partition(cxt, j, pa);
+                       res = get_partition_unused_primary(cxt, pa);
+                       if (res >= 0)
+                               rc = add_partition(cxt, res, pa);
                        goto done;
                } else if (c == 'l' && l->ext_offset) {
-                       rc = add_logical(cxt, pa);
+                       rc = add_logical(cxt, pa, &res);
                        goto done;
                } else if (c == 'e' && !l->ext_offset) {
-                       int j = get_partition_unused_primary(cxt, pa);
-                       if (j >= 0) {
+                       res = get_partition_unused_primary(cxt, pa);
+                       if (res >= 0) {
                                struct fdisk_partition xpa = { .type = NULL };
                                struct fdisk_parttype *t;
 
@@ -1528,15 +1547,18 @@ static int dos_add_partition(struct fdisk_context *cxt,
                                if (!pa)
                                        pa = &xpa;
                                fdisk_partition_set_type(pa, t);
-                               rc = add_partition(cxt, j, pa);
+                               rc = add_partition(cxt, res, pa);
                        }
                        goto done;
                } else
                        fdisk_warnx(cxt, _("Invalid partition type `%c'."), c);
        }
 done:
-       if (rc == 0)
+       if (rc == 0) {
                cxt->label->nparts_cur++;
+               if (partno && res >= 0)
+                       *partno = res;
+       }
        return rc;
 }
 
index 15f394cfe5ecb172b7934eab1d52144691057913..05ce28293b5d78f2e8e4e0999c13face36de5cdb 100644 (file)
@@ -192,7 +192,7 @@ struct fdisk_label_operations {
        int (*set_id)(struct fdisk_context *cxt);
 
        /* new partition */
-       int (*add_part)(struct fdisk_context *cxt, struct fdisk_partition *pa);
+       int (*add_part)(struct fdisk_context *cxt, struct fdisk_partition *pa, size_t *partno);
 
        /* delete partition */
        int (*part_delete)(struct fdisk_context *cxt,
index 082dcadce7923f04e933717e0c1cdad048e995df..8a3c8c6bddfc217bb4ffcd1005ab62ef6d61f494 100644 (file)
@@ -1755,7 +1755,8 @@ static int gpt_entry_set_uuid(struct gpt_entry *e, char *str)
 /* Performs logical checks to add a new partition entry */
 static int gpt_add_partition(
                struct fdisk_context *cxt,
-               struct fdisk_partition *pa)
+               struct fdisk_partition *pa,
+               size_t *partno)
 {
        uint64_t user_f, user_l;        /* user input ranges for first and last sectors */
        uint64_t disk_f, disk_l;        /* first and last available sector ranges on device*/
@@ -1947,6 +1948,8 @@ static int gpt_add_partition(
        }
 
        rc = 0;
+       if (partno)
+               *partno = partnum;
 done:
        fdisk_free_ask(ask);
        return rc;
index 6abae04b584d4d038b1bf9ead301375c8afca46f..b806b349b0ccc1c45994e55b32b921a13762999a 100644 (file)
@@ -197,7 +197,7 @@ extern int fdisk_set_disklabel_id(struct fdisk_context *cxt);
 
 extern int fdisk_get_partition(struct fdisk_context *cxt, size_t partno, struct fdisk_partition **pa);
 
-extern int fdisk_add_partition(struct fdisk_context *cxt, struct fdisk_partition *pa);
+extern int fdisk_add_partition(struct fdisk_context *cxt, struct fdisk_partition *pa, size_t *partno);
 extern int fdisk_delete_partition(struct fdisk_context *cxt, size_t partnum);
 extern int fdisk_delete_all_partitions(struct fdisk_context *cxt);
 
index c60e064fbb75e4a07db7ff40091b9e9cd6ce703c..717eea7115db16638876c890a258c55ba7358c18 100644 (file)
@@ -73,9 +73,9 @@ void fdisk_unref_partition(struct fdisk_partition *pa)
 
        pa->refcount--;
        if (pa->refcount <= 0) {
-               DBG(PART, ul_debugobj(pa, "free"));
                fdisk_reset_partition(pa);
                list_del(&pa->parts);
+               DBG(PART, ul_debugobj(pa, "free"));
                free(pa);
        }
 }
@@ -548,7 +548,9 @@ int fdisk_partition_to_string(struct fdisk_partition *pa,
  * @partno:
  * @pa: pointer to partition struct
  *
- * Fills in @pa with data about partition @n.
+ * Fills in @pa with data about partition @n. Note that partno may address
+ * unused partition and then this function does not fill anything to @pa.
+ * See fdisk_is_partition_used().
  *
  * Returns: 0 on success, otherwise, a corresponding error.
  */
@@ -601,7 +603,8 @@ int fdisk_is_partition_used(struct fdisk_context *cxt, size_t n)
 /**
  * fdisk_add_partition:
  * @cxt: fdisk context
- * @pa: template for the partition
+ * @pa: template for the partition (or NULL)
+ * @partno: returns new partition number (optional)
  *
  * If @pa is not specified or any @pa item is missiong the libfdisk will ask by
  * fdisk_ask_ API.
@@ -611,7 +614,8 @@ int fdisk_is_partition_used(struct fdisk_context *cxt, size_t n)
  * Returns 0.
  */
 int fdisk_add_partition(struct fdisk_context *cxt,
-                       struct fdisk_partition *pa)
+                       struct fdisk_partition *pa,
+                       size_t *partno)
 {
        int rc;
 
@@ -625,16 +629,20 @@ int fdisk_add_partition(struct fdisk_context *cxt,
        if (fdisk_missing_geometry(cxt))
                return -EINVAL;
 
-       DBG(CXT, ul_debugobj(cxt, "adding new partition (start=%ju, end=%ju, size=%ju, "
+       if (pa)
+               DBG(CXT, ul_debugobj(cxt, "adding new partition %p (start=%ju, end=%ju, size=%ju, "
                            "defaults(start=%s, end=%s, partno=%s)",
-                           pa ? pa->start : 0,
-                           pa ? pa->end : 0,
-                           pa ? pa->size : 0,
-                           pa && pa->start_follow_default ? "yes" : "no",
-                           pa && pa->end_follow_default ? "yes" : "no",
-                           pa && pa->partno_follow_default ? "yes" : "no"));
-
-       rc = cxt->label->op->add_part(cxt, pa);
+                           pa,
+                           pa->start,
+                           pa->end,
+                           pa->size,
+                           pa->start_follow_default ? "yes" : "no",
+                           pa->end_follow_default ? "yes" : "no",
+                           pa->partno_follow_default ? "yes" : "no"));
+       else
+               DBG(CXT, ul_debugobj(cxt, "adding partition"));
+
+       rc = cxt->label->op->add_part(cxt, pa, partno);
 
        DBG(CXT, ul_debugobj(cxt, "add partition done (rc=%d)", rc));
        return rc;
index 7d6f5eec32005af98c936dc02e4a2c6775d1ad7e..e0e2d5387c0a1cbd30b3591bc0c133ddf36b6e9d 100644 (file)
@@ -865,7 +865,7 @@ int fdisk_script_read_buffer(struct fdisk_script *dp, char *s)
  *
  * Reads next line into dump.
  *
- * Returns: 0 on success, <0 on error.
+ * Returns: 0 on success, <0 on error, 1 when nothing to read.
  */
 int fdisk_script_read_line(struct fdisk_script *dp, FILE *f, char *buf, size_t bufsz)
 {
@@ -879,7 +879,7 @@ int fdisk_script_read_line(struct fdisk_script *dp, FILE *f, char *buf, size_t b
        /* read the next non-blank non-comment line */
        do {
                if (fgets(buf, bufsz, f) == NULL)
-                       return -errno;
+                       return 1;
                dp->nlines++;
                s = strchr(buf, '\n');
                if (!s) {
@@ -993,6 +993,7 @@ int fdisk_apply_script_headers(struct fdisk_context *cxt, struct fdisk_script *d
        assert(cxt);
        assert(dp);
 
+       DBG(SCRIPT, ul_debugobj(dp, "applying script headers"));
        fdisk_set_script(cxt, dp);
 
        /* create empty label */
@@ -1098,10 +1099,12 @@ int test_stdin(struct fdisk_test *ts, int argc, char *argv[])
                printf(" #%zu :\n", n + 1);
                rc = fdisk_script_read_line(dp, stdin);
 
-               pa = fdisk_table_get_partition(dp->table, n);
-               printf(" #%zu  %12ju %12ju\n",  n + 1,
+               if (rc == 0) {
+                       pa = fdisk_table_get_partition(dp->table, n);
+                       printf(" #%zu  %12ju %12ju\n",  n + 1,
                                                fdisk_partition_get_start(pa),
                                                fdisk_partition_get_size(pa));
+               }
        } while (rc == 0);
 
        if (!rc)
index 10e5b5672810c0bb7bdb647f21252b535a179f09..c0c6e33cbfb517a4066efcfb33cd8c86076b9bf1 100644 (file)
@@ -759,7 +759,8 @@ static int sgi_delete_partition(struct fdisk_context *cxt, size_t partnum)
 }
 
 static int sgi_add_partition(struct fdisk_context *cxt,
-                            struct fdisk_partition *pa)
+                            struct fdisk_partition *pa,
+                            size_t *partno)
 {
        struct fdisk_sgi_label *sgi;
        char mesg[256];
@@ -900,7 +901,8 @@ static int sgi_add_partition(struct fdisk_context *cxt,
 
        sgi_set_partition(cxt, n, first, last - first, sys);
        cxt->label->nparts_cur = count_used_partitions(cxt);
-
+       if (partno)
+               *partno = n;
        return 0;
 }
 
index 7148e4f68090c6bef52b67a89206fe25839a44fb..68ad11eece8280bc4fd66fae3edfb7f610ce32b6 100644 (file)
@@ -474,7 +474,8 @@ static int is_free_sector(struct fdisk_context *cxt,
 
 static int sun_add_partition(
                struct fdisk_context *cxt,
-               struct fdisk_partition *pa)
+               struct fdisk_partition *pa,
+               size_t *partno)
 {
        struct sun_disklabel *sunlabel = self_disklabel(cxt);
        uint32_t starts[SUN_MAXPARTITIONS], lens[SUN_MAXPARTITIONS];
@@ -681,6 +682,8 @@ static int sun_add_partition(
 
        set_sun_partition(cxt, n, first, last, sys);
        cxt->label->nparts_cur = count_used_partitions(cxt);
+       if (partno)
+               *partno = n;
        return 0;
 }
 
index c6c51c837ee2cc3644448907e099b91c4bb660f8..e5cc79aa303d009dd6ba5c213433d3b6fb1c2f4f 100644 (file)
@@ -554,7 +554,7 @@ int fdisk_apply_table(struct fdisk_context *cxt, struct fdisk_table *tb)
 
        fdisk_reset_iter(&itr, FDISK_ITER_FORWARD);
        while (tb && fdisk_table_next_partition(tb, &itr, &pa) == 0) {
-               rc = fdisk_add_partition(cxt, pa);
+               rc = fdisk_add_partition(cxt, pa, NULL);
                if (rc)
                        break;
        }