]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: use fdisk_table to generate output
authorKarel Zak <kzak@redhat.com>
Wed, 18 Dec 2013 09:28:55 +0000 (10:28 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 11 Mar 2014 10:35:12 +0000 (11:35 +0100)
 * add generic fdisk_iter iterator
 * use fdisk_table to convert partition table to human readable output
 * clean up partition.c API (don't use reference to fdisk_context in
   fdisk_partition struct)
 * extern table.c API to use fdisk_iter iterator
 * remove old fdisk_list_partitions()

Signed-off-by: Karel Zak <kzak@redhat.com>
12 files changed:
libfdisk/src/Makemodule.am
libfdisk/src/bsd.c
libfdisk/src/dos.c
libfdisk/src/fdiskP.h
libfdisk/src/gpt.c
libfdisk/src/iter.c [new file with mode: 0644]
libfdisk/src/label.c
libfdisk/src/libfdisk.h
libfdisk/src/partition.c
libfdisk/src/sgi.c
libfdisk/src/sun.c
libfdisk/src/table.c

index a87b2efcc461e1f8107b4aa4fab1165f08600fd1..d8cbffbe37df3798f89c99c0d6d6c953e5a182fc 100644 (file)
@@ -19,6 +19,7 @@ libfdisk_la_SOURCES = \
        libfdisk/src/parttype.c \
        libfdisk/src/partition.c \
        libfdisk/src/table.c \
+       libfdisk/src/iter.c \
        \
        libfdisk/src/sun.c \
        libfdisk/src/sgi.c \
index 4ee31b6dd5aa472e9fee68182143ae70bb5ceea5..8495363286591a19e2d323cd437284c3b006c166 100644 (file)
@@ -202,7 +202,7 @@ static int bsd_add_partition(struct fdisk_context *cxt,
        unsigned int begin = 0, end;
        int rc = 0;
 
-       rc = fdisk_partition_next_partno(cxt, pa, &i);
+       rc = fdisk_partition_next_partno(pa, cxt, &i);
        if (rc)
                return rc;
        if (i >= BSD_MAXPARTITIONS)
@@ -398,7 +398,7 @@ static int bsd_list_disklabel(struct fdisk_context *cxt)
 
        fdisk_colon(cxt, _("partitions: %d"), d->d_npartitions);
 
-       return fdisk_list_partitions(cxt, NULL, 0);
+       return 0;
 }
 
 static int bsd_get_partition(struct fdisk_context *cxt, size_t n,
index e23470f655265f336d5dd86e514d3d8462e0ce30..63072fc3f11e7e71d610cb9a6ee83d0d9e0cf1a0 100644 (file)
@@ -180,7 +180,7 @@ static int get_partition_unused_primary(struct fdisk_context *cxt,
        int rc;
 
        cxt->label->nparts_max = 4;
-       rc = fdisk_partition_next_partno(cxt, pa, &n);
+       rc = fdisk_partition_next_partno(pa, cxt, &n);
        cxt->label->nparts_max = org;
 
        switch (rc) {
@@ -1549,98 +1549,13 @@ static int wrong_p_order(struct fdisk_context *cxt, size_t *prev)
        return 0;
 }
 
-/*
- * This is so crazy that it's exported by separate function and not exported by
- * regular fdisk_list_disable() libfdisk API.
- */
-int fdisk_dos_list_extended(struct fdisk_context *cxt)
-{
-       int rc;
-       size_t i;
-       struct tt *tb = NULL;
-
-       assert(cxt);
-       assert(cxt->label);
-       assert(fdisk_is_disklabel(cxt, DOS));
-
-       tb = tt_new_table(TT_FL_FREEDATA);
-       if (!tb)
-               return -ENOMEM;
-
-       tt_define_column(tb, _("Nr"), 2, TT_FL_RIGHT);
-       tt_define_column(tb, _("AF"), 2, TT_FL_RIGHT);
-
-       tt_define_column(tb, _("Hd"),  4, TT_FL_RIGHT);
-       tt_define_column(tb, _("Sec"), 4, TT_FL_RIGHT);
-       tt_define_column(tb, _("Cyl"), 5, TT_FL_RIGHT);
-
-       tt_define_column(tb, _("Hd"),  4, TT_FL_RIGHT);
-       tt_define_column(tb, _("Sec"), 4, TT_FL_RIGHT);
-       tt_define_column(tb, _("Cyl"), 5, TT_FL_RIGHT);
-
-       tt_define_column(tb, _("Start"), 9, TT_FL_RIGHT);
-       tt_define_column(tb, _("Size"),  9, TT_FL_RIGHT);
-       tt_define_column(tb, _("Id"),    2, TT_FL_RIGHT);
-
-       for (i = 0 ; i < cxt->label->nparts_max; i++) {
-               struct pte *pe = self_pte(cxt, i);
-               struct dos_partition *p;
-               struct tt_line *ln;
-               char *str;
-
-               p = pe->ex_entry;
-               if (!p)
-                       continue;
-               ln = tt_add_line(tb, NULL);
-               if (!ln)
-                       continue;
-
-               if (asprintf(&str, "%zu",  i + 1) > 0)
-                       tt_line_set_data(ln, 0, str);           /* Nr */
-               if (asprintf(&str, "%02x", p->boot_ind) > 0)
-                       tt_line_set_data(ln, 1, str);           /* AF */
-
-               if (asprintf(&str, "%d", p->bh) > 0)
-                       tt_line_set_data(ln, 2, str);           /* Hd */
-               if (asprintf(&str, "%d", sector(p->bs)) > 0)
-                       tt_line_set_data(ln, 3, str);           /* Sec */
-               if (asprintf(&str, "%d", cylinder(p->bs, p->bc)) > 0)
-                       tt_line_set_data(ln, 4, str);           /* Cyl */
-
-               if (asprintf(&str, "%d", p->eh) > 0)
-                       tt_line_set_data(ln, 5, str);           /* Hd */
-               if (asprintf(&str, "%d", sector(p->es)) > 0)
-                       tt_line_set_data(ln, 6, str);           /* Sec */
-               if (asprintf(&str, "%d", cylinder(p->es, p->ec)) > 0)
-                       tt_line_set_data(ln, 7, str);           /* Cyl */
-
-               if (asprintf(&str, "%lu",
-                       (unsigned long) dos_partition_get_start(p)) > 0)
-                       tt_line_set_data(ln, 8, str);           /* Start */
-               if (asprintf(&str, "%lu",
-                       (unsigned long) dos_partition_get_size(p)) > 0)
-                       tt_line_set_data(ln, 9, str);           /* End */
-
-               if (asprintf(&str, "%02x", p->sys_ind) > 0)
-                       tt_line_set_data(ln, 10, str);          /* Id */
-
-               check_consistency(cxt, p, i);
-               fdisk_warn_alignment(cxt, get_abs_partition_start(pe), i);
-       }
-
-       rc = fdisk_print_table(cxt, tb);
-       tt_free_table(tb);
-
-       return rc;
-}
-
 static int dos_list_disklabel(struct fdisk_context *cxt)
 {
        assert(cxt);
        assert(cxt->label);
        assert(fdisk_is_disklabel(cxt, DOS));
 
-       return fdisk_list_partitions(cxt, NULL, 0);
+       return 0;
 }
 
 static int dos_get_partition(struct fdisk_context *cxt, size_t n,
index 6459b3635291c29e787202fc0223909a0533487f..1cd8b48742b41c39cfb741961ad65e81906f9345 100644 (file)
@@ -107,6 +107,33 @@ extern int fdisk_run_test(struct fdisk_test *tests, int argc, char *argv[]);
 
 typedef unsigned long long sector_t;
 
+
+/*
+ * Generic iterator
+ */
+struct fdisk_iter {
+        struct list_head        *p;            /* current position */
+        struct list_head        *head;         /* start position */
+       int                     direction;      /* FDISK_ITER_{FOR,BACK}WARD */
+};
+
+#define IS_ITER_FORWARD(_i)    ((_i)->direction == FDISK_ITER_FORWARD)
+#define IS_ITER_BACKWARD(_i)   ((_i)->direction == FDISK_ITER_BACKWARD)
+
+#define FDISK_ITER_INIT(itr, list) \
+       do { \
+               (itr)->p = IS_ITER_FORWARD(itr) ? \
+                               (list)->next : (list)->prev; \
+               (itr)->head = (list); \
+       } while(0)
+
+#define FDISK_ITER_ITERATE(itr, res, restype, member) \
+       do { \
+               res = list_entry((itr)->p, restype, member); \
+               (itr)->p = IS_ITER_FORWARD(itr) ? \
+                               (itr)->p->next : (itr)->p->prev; \
+       } while(0)
+
 /*
  * Partition types
  */
@@ -129,8 +156,6 @@ enum {
 #define fdisk_parttype_is_allocated(_x)        ((_x) && ((_x)->flags & FDISK_PARTTYPE_ALLOCATED))
 
 struct fdisk_partition {
-       struct fdisk_context    *cxt;           /* the current context */
-
        int             refcount;               /* reference counter */
        size_t          partno;                 /* partition number */
 
@@ -424,7 +449,8 @@ extern char *fdisk_partname(const char *dev, size_t partno);
 /* label.c */
 extern int fdisk_probe_labels(struct fdisk_context *cxt);
 extern void fdisk_deinit_label(struct fdisk_label *lb);
-
+extern const struct fdisk_column *fdisk_label_get_column(
+                                       struct fdisk_label *lb, int id);
 
 /* ask.c */
 extern int fdisk_ask_partnum(struct fdisk_context *cxt, size_t *partnum, int wantnew);
index 14aafc47246511e75f2e3cd295490eae1d7586c6..c9917cf56d52da1b716bf13187d68b5f0e22bdf9 100644 (file)
@@ -1345,7 +1345,7 @@ static int gpt_list_disklabel(struct fdisk_context *cxt)
                fdisk_colon(cxt, _("Allocated partition entries: %u"), h->npartition_entries);
        }
 
-       return fdisk_list_partitions(cxt, NULL, 0);
+       return 0;
 }
 
 /*
@@ -1734,7 +1734,7 @@ static int gpt_add_partition(
        pheader = gpt->pheader;
        ents = gpt->ents;
 
-       rc = fdisk_partition_next_partno(cxt, pa, &partnum);
+       rc = fdisk_partition_next_partno(pa, cxt, &partnum);
        if (rc)
                return rc;
 
diff --git a/libfdisk/src/iter.c b/libfdisk/src/iter.c
new file mode 100644 (file)
index 0000000..8e2f342
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+/**
+ * SECTION: iter
+ * @title: Iterator
+ * @short_description: unified iterator
+ *
+ * The iterator keeps the direction and the last position
+ * for access to the internal library tables/lists.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "fdiskP.h"
+
+/**
+ * fdisk_new_iter:
+ * @direction: FDISK_INTER_{FOR,BACK}WARD direction
+ *
+ * Returns: newly allocated generic libmount iterator.
+ */
+struct fdisk_iter *fdisk_new_iter(int direction)
+{
+       struct fdisk_iter *itr = calloc(1, sizeof(*itr));
+       if (!itr)
+               return NULL;
+       itr->direction = direction;
+       return itr;
+}
+
+/**
+ * fdisk_free_iter:
+ * @itr: iterator pointer
+ *
+ * Deallocates the iterator.
+ */
+void fdisk_free_iter(struct fdisk_iter *itr)
+{
+       free(itr);
+}
+
+/**
+ * fdisk_reset_iter:
+ * @itr: iterator pointer
+ * @direction: FDISK_INTER_{FOR,BACK}WARD or -1 to keep the direction unchanged
+ *
+ * Resets the iterator.
+ */
+void fdisk_reset_iter(struct fdisk_iter *itr, int direction)
+{
+       if (direction == -1)
+               direction = itr->direction;
+
+       memset(itr, 0, sizeof(*itr));
+       itr->direction = direction;
+}
+
+/**
+ * fdisk_iter_get_direction:
+ * @itr: iterator pointer
+ *
+ * Returns: FDISK_INTER_{FOR,BACK}WARD
+ */
+int fdisk_iter_get_direction(struct fdisk_iter *itr)
+{
+       return itr->direction;
+}
index 99571232cbbf4c7cf2c3ea476a06cc458f58c22a..00b25ee2935d32d3c0c2f563e958b6d64ef629ff 100644 (file)
@@ -152,7 +152,7 @@ int fdisk_get_columns(struct fdisk_context *cxt, int all, int **cols, size_t *nc
        return 0;
 }
 
-static const struct fdisk_column *fdisk_label_get_column(
+const struct fdisk_column *fdisk_label_get_column(
                                        struct fdisk_label *lb, int id)
 {
        size_t i;
@@ -194,11 +194,10 @@ int fdisk_verify_disklabel(struct fdisk_context *cxt)
  * fdisk_list_disklabel:
  * @cxt: fdisk context
  *
- * Lists in-memory partition table and all related details.
+ * Lists details about disklabel, but no partitions.
  *
  * This function uses libfdisk ASK interface to print data. The details about
- * partitions table are printed by FDISK_ASKTYPE_INFO and partitions by
- * FDISK_ASKTYPE_TABLE. The default columns are printed.
+ * partitions table are printed by FDISK_ASKTYPE_INFO.
  *
  * Returns 0 on success, otherwise, a corresponding error.
  */
@@ -212,166 +211,6 @@ int fdisk_list_disklabel(struct fdisk_context *cxt)
        return cxt->label->op->list(cxt);
 }
 
-static int add_partition_to_tt(struct fdisk_context *cxt,
-                                struct tt *tb,
-                                int *cols,
-                                size_t ncols,
-                                struct fdisk_partition *pa)
-{
-       size_t j;
-       struct tt_line *ln = tt_add_line(tb, NULL);
-       const struct fdisk_column *col;
-
-       if (!ln)
-               return -ENOMEM;
-
-       /* set data for the columns */
-       for (j = 0; j < ncols; j++) {
-               char *data = NULL;
-               int id;
-
-               col = fdisk_label_get_column(cxt->label, cols[j]);
-               if (!col)
-                       continue;
-               id = (col->id == FDISK_COL_SECTORS &&
-                     fdisk_context_use_cylinders(cxt)) ?
-                               FDISK_COL_CYLINDERS :
-                               col->id;
-
-               if (fdisk_partition_to_string(pa, id, &data))
-                       continue;
-               tt_line_set_data(ln, j, data);
-       }
-
-       return 0;
-}
-
-static void gap_to_freespace(
-                       struct fdisk_context *cxt,
-                       struct tt *tb,
-                       int *cols,
-                       size_t ncols,
-                       uint64_t start,
-                       uint64_t end)
-{
-       struct fdisk_partition pa = FDISK_EMPTY_PARTITION;
-
-       pa.freespace = 1;
-       pa.cxt = cxt;
-
-       pa.start = start;
-       pa.end = end;
-       pa.size = pa.end - pa.start + 1ULL;
-
-       DBG(LABEL, dbgprint("gap->freespace [%ju, size=%ju]",
-                       pa.start, pa.size));
-
-       add_partition_to_tt(cxt, tb, cols, ncols, &pa);
-}
-
-
-/**
- * fdisk_list_partitions
- * @cxt: fdisk context
- * @cols: array with wanted FDISK_COL_* columns
- * @ncols: number of items in the cols array
- *
- * This is subset of fdisk_list_disklabel(), this function lists really
- * only partitons by FDISK_ASKTYPE_TABLE interface.
- *
- * If no @cols are specified then the default is printed (see
- * fdisk_get_columns() for the default columns).
-
- * Returns 0 on success, otherwise, a corresponding error.
- */
-
-int fdisk_list_partitions(struct fdisk_context *cxt, int *cols, size_t ncols)
-{
-       int *org = cols, rc = 0;
-       struct tt *tb = NULL;
-       const struct fdisk_column *col;
-       struct fdisk_partition *pa = NULL;
-       size_t i, j;
-       uint64_t last, grain;
-
-       if (!cxt || !cxt->label)
-               return -EINVAL;
-       if (!cxt->label->op->get_part)
-               return -ENOSYS;
-
-       DBG(LABEL, dbgprint("list partitions%s",
-               fdisk_context_display_freespace(cxt) ? " and free-space" : ""));
-
-       if (!cols || !ncols) {
-               rc = fdisk_get_columns(cxt, 0, &cols, &ncols);
-               if (rc)
-                       return rc;
-       }
-
-       tb = tt_new_table(TT_FL_FREEDATA);
-       if (!tb) {
-               rc = -ENOMEM;
-               goto done;
-       }
-
-       last = cxt->first_lba;
-       grain = cxt->grain / cxt->sector_size;
-
-       /* define table columns */
-       for (j = 0; j < ncols; j++) {
-               col = fdisk_label_get_column(cxt->label, cols[j]);
-               if (!col)
-                       continue;
-               tt_define_column(tb,
-                       col->id == FDISK_COL_SECTORS &&
-                       fdisk_context_use_cylinders(cxt) ?
-                               _("Cylinders") : col->name,
-                       col->width, col->tt_flags);
-       }
-
-       /* generate per-partition lines into table */
-       for (i = 0; i < cxt->label->nparts_max; i++) {
-               rc = fdisk_get_partition(cxt, i, &pa);
-               if (rc)
-                       continue;
-               if (!fdisk_partition_is_used(pa))
-                       continue;
-
-               /* add free-space (before partition) to the list */
-               if (fdisk_context_display_freespace(cxt) &&
-                   last + grain < pa->start) {
-                       gap_to_freespace(cxt, tb, cols, ncols,
-                               last + (last > cxt->first_lba ? 1 : 0),
-                               pa->start - 1);
-               }
-               last = pa->end;
-
-               /* add partition to the list */
-               add_partition_to_tt(cxt, tb, cols, ncols, pa);
-       }
-
-       /* add free-space (behind last partition) to the list */
-       if (fdisk_context_display_freespace(cxt) &&
-           last + grain < cxt->total_sectors - 1) {
-               gap_to_freespace(cxt, tb, cols, ncols,
-                       last + (last > cxt->first_lba ? 1 : 0),
-                       cxt->total_sectors - 1);
-       }
-
-       if (!tt_is_empty(tb))
-               rc = fdisk_print_table(cxt, tb);
-       else
-               DBG(LABEL, dbgprint("table empty, not list"));
-done:
-       if (org != cols)
-               free(cols);
-       tt_free_table(tb);
-       fdisk_unref_partition(pa);
-       return rc;
-}
-
-
-
 /**
  * fdisk_create_disklabel:
  * @cxt: fdisk context
index 0d30df8d6c08972dd71c5f3000457bf1378cbc12..8d03990a06550eeff4d2f8532e06c77248f3fc2c 100644 (file)
@@ -33,6 +33,7 @@ struct fdisk_label;
 struct fdisk_parttype;
 struct fdisk_partition;
 struct fdisk_ask;
+struct libfdisk_iter;
 struct tt;
 
 /*
@@ -167,7 +168,6 @@ extern int fdisk_set_partition_type(struct fdisk_context *cxt, size_t partnum,
                             struct fdisk_parttype *t);
 
 extern int fdisk_get_columns(struct fdisk_context *cxt, int all, int **cols, size_t *ncols);
-extern int fdisk_list_partitions(struct fdisk_context *cxt, int *cols, size_t ncols);
 
 extern void fdisk_label_set_changed(struct fdisk_label *lb, int changed);
 extern int fdisk_label_is_changed(struct fdisk_label *lb);
@@ -202,10 +202,13 @@ extern const char *fdisk_partition_get_attrs(struct fdisk_partition *pa);
 extern int fdisk_partition_set_nested(struct fdisk_partition *pa, int nested);
 extern int fdisk_partition_is_nested(struct fdisk_partition *pa);
 extern int fdisk_partition_is_used(struct fdisk_partition *pa);
-extern int fdisk_partition_to_string(struct fdisk_partition *pa, int id, char **data);
+extern int fdisk_partition_to_string(struct fdisk_partition *pa,
+                                    struct fdisk_context *cxt,
+                                    int id, char **data);
 
-extern int fdisk_partition_next_partno(        struct fdisk_context *cxt,
-                       struct fdisk_partition *pa, size_t *n);
+extern int fdisk_partition_next_partno(struct fdisk_partition *pa,
+                                      struct fdisk_context *cxt,
+                                      size_t *n);
 
 /* table.c */
 extern struct fdisk_table *fdisk_new_table(void);
@@ -216,6 +219,10 @@ extern int fdisk_table_is_empty(struct fdisk_table *tb);
 extern int fdisk_table_add_partition(struct fdisk_table *tb, struct fdisk_partition *pa);
 extern int fdisk_table_remove_partition(struct fdisk_table *tb, struct fdisk_partition *pa);
 
+extern int fdisk_get_table(struct fdisk_context *cxt, struct fdisk_table **tb);
+extern int fdisk_table_to_string(struct fdisk_table *tb,
+                         struct fdisk_context *cxt,
+                         int *cols, size_t ncols,  char **data);
 
 /* alignment.c */
 extern int fdisk_reset_alignment(struct fdisk_context *cxt);
@@ -234,6 +241,18 @@ extern int fdisk_has_user_device_properties(struct fdisk_context *cxt);
 
 extern int fdisk_reread_partition_table(struct fdisk_context *cxt);
 
+/* iter.c */
+enum {
+
+       FDISK_ITER_FORWARD = 0,
+       FDISK_ITER_BACKWARD
+};
+extern struct fdisk_iter *fdisk_new_iter(int direction);
+extern void fdisk_free_iter(struct fdisk_iter *itr);
+extern void fdisk_reset_iter(struct fdisk_iter *itr, int direction);
+extern int fdisk_iter_get_direction(struct fdisk_iter *itr);
+
+
 /* dos.c */
 extern int fdisk_dos_enable_compatible(struct fdisk_label *lb, int enable);
 extern int fdisk_dos_is_compatible(struct fdisk_label *lb);
@@ -275,7 +294,6 @@ extern struct dos_partition *fdisk_dos_get_partition(
 
 extern int fdisk_dos_fix_order(struct fdisk_context *cxt);
 extern int fdisk_dos_move_begin(struct fdisk_context *cxt, size_t i);
-extern int fdisk_dos_list_extended(struct fdisk_context *cxt);
 
 #define DOS_FLAG_ACTIVE        1
 
index 513af4f0a5c1fc26b2bc557f83d0bb8f082c9f98..fb9908e8be22e7ee44cc7106a14683d4dd603c9f 100644 (file)
@@ -9,6 +9,7 @@ struct fdisk_partition *fdisk_new_partition(void)
        struct fdisk_partition *pa = calloc(1, sizeof(*pa));
 
        pa->refcount = 1;
+       INIT_LIST_HEAD(&pa->parts);
        pa->partno = FDISK_EMPTY_PARTNO;
        DBG(PART, dbgprint("new %p", pa));
        return pa;
@@ -29,6 +30,7 @@ void fdisk_reset_partition(struct fdisk_partition *pa)
        memset(pa, 0, sizeof(*pa));
        pa->partno = FDISK_EMPTY_PARTNO;
        pa->refcount = ref;
+       INIT_LIST_HEAD(&pa->parts);
 }
 
 void fdisk_ref_partition(struct fdisk_partition *pa)
@@ -44,8 +46,9 @@ void fdisk_unref_partition(struct fdisk_partition *pa)
 
        pa->refcount--;
        if (pa->refcount <= 0) {
-               fdisk_reset_partition(pa);
                DBG(PART, dbgprint("free %p", pa));
+               fdisk_reset_partition(pa);
+               list_del(&pa->parts);
                free(pa);
        }
 }
@@ -192,8 +195,8 @@ int fdisk_partition_is_freespace(struct fdisk_partition *pa)
 }
 
 int fdisk_partition_next_partno(
-               struct fdisk_context *cxt,
                struct fdisk_partition *pa,
+               struct fdisk_context *cxt,
                size_t *n)
 {
        assert(cxt);
@@ -202,14 +205,14 @@ int fdisk_partition_next_partno(
        if (pa && pa->partno_follow_default) {
                size_t i;
 
-               for (i = 0; i < pa->cxt->label->nparts_max; i++) {
+               for (i = 0; i < cxt->label->nparts_max; i++) {
                        if (!fdisk_is_partition_used(cxt, i)) {
                                *n = i;
                                break;
                        }
                }
        } else if (pa && pa->partno != FDISK_EMPTY_PARTNO) {
-               if (pa->partno >= pa->cxt->label->nparts_max)
+               if (pa->partno >= cxt->label->nparts_max)
                        return -ERANGE;
                *n = pa->partno;
        } else
@@ -242,6 +245,7 @@ int fdisk_partition_next_partno(
  */
 
 int fdisk_partition_to_string(struct fdisk_partition *pa,
+                             struct fdisk_context *cxt,
                              int id,
                              char **data)
 {
@@ -249,38 +253,38 @@ int fdisk_partition_to_string(struct fdisk_partition *pa,
        int rc = 0;
        uint64_t x;
 
-       if (!pa || !pa->cxt)
+       if (!pa || !cxt)
                return -EINVAL;
 
        switch (id) {
        case FDISK_COL_DEVICE:
                if (pa->freespace)
                        p = strdup(_("Free space"));
-               else if (pa->cxt->label->flags & FDISK_LABEL_FL_INCHARS_PARTNO)
+               else if (cxt->label->flags & FDISK_LABEL_FL_INCHARS_PARTNO)
                        rc = asprintf(&p, "%c", (int) pa->partno + 'a');
                else
-                       p = fdisk_partname(pa->cxt->dev_path, pa->partno + 1);
+                       p = fdisk_partname(cxt->dev_path, pa->partno + 1);
                break;
        case FDISK_COL_BOOT:
                rc = asprintf(&p, "%c", pa->boot);
                break;
        case FDISK_COL_START:
-               x = fdisk_cround(pa->cxt, pa->start);
+               x = fdisk_cround(cxt, pa->start);
                rc = pa->start_post ?
                                asprintf(&p, "%ju%c", x, pa->start_post) :
                                asprintf(&p, "%ju", x);
                break;
        case FDISK_COL_END:
-               x = fdisk_cround(pa->cxt, pa->end);
+               x = fdisk_cround(cxt, pa->end);
                rc = pa->end_post ?
                                asprintf(&p, "%ju%c", x, pa->end_post) :
                                asprintf(&p, "%ju", x);
                break;
        case FDISK_COL_SIZE:
        {
-               uint64_t sz = pa->size * pa->cxt->sector_size;
+               uint64_t sz = pa->size * cxt->sector_size;
 
-               if (fdisk_context_display_details(pa->cxt)) {
+               if (fdisk_context_display_details(cxt)) {
                        rc = pa->size_post ?
                                        asprintf(&p, "%ju%c", sz, pa->size_post) :
                                        asprintf(&p, "%ju", sz);
@@ -293,7 +297,7 @@ int fdisk_partition_to_string(struct fdisk_partition *pa,
        }
        case FDISK_COL_CYLINDERS:
                rc = asprintf(&p, "%ju", (uintmax_t)
-                               fdisk_cround(pa->cxt, pa->size));
+                               fdisk_cround(cxt, pa->size));
                break;
        case FDISK_COL_SECTORS:
                rc = asprintf(&p, "%ju", pa->size);
@@ -359,23 +363,32 @@ int fdisk_get_partition(struct fdisk_context *cxt, size_t partno,
                        struct fdisk_partition **pa)
 {
        int rc;
+       struct fdisk_partition *np = NULL;
 
        if (!cxt || !cxt->label || !pa)
                return -EINVAL;
        if (!cxt->label->op->get_part)
                return -ENOSYS;
+       if (!fdisk_is_partition_used(cxt, partno))
+               return -EINVAL;
 
        if (!*pa) {
-               *pa = fdisk_new_partition();
+               np = *pa = fdisk_new_partition();
                if (!*pa)
                        return -ENOMEM;
        } else
                fdisk_reset_partition(*pa);
-       (*pa)->cxt = cxt;
+
        (*pa)->partno = partno;
        rc = cxt->label->op->get_part(cxt, partno, *pa);
-       if (rc == 0 && fdisk_partition_is_used(*pa))
-               DBG(PART, dbgprint("get partition %zu", partno));
+
+       if (rc) {
+               if (np) {
+                       fdisk_unref_partition(np);
+                       *pa = NULL;
+               } else
+                       fdisk_reset_partition(*pa);
+       }
        return rc;
 }
 
index aa03d0319aaf3292417b93c474c6d606f2601a83..33a13c8b7654876480f1f09919e640f3e551aebc 100644 (file)
@@ -248,11 +248,8 @@ static int sgi_probe_label(struct fdisk_context *cxt)
 
 static int sgi_list_table(struct fdisk_context *cxt)
 {
-       struct tt *tb = NULL;
        struct sgi_disklabel *sgilabel = self_disklabel(cxt);
        struct sgi_device_parameter *sgiparam = &sgilabel->devparam;
-       size_t i, used;
-       char *p;
        int rc = 0;
 
        if (fdisk_context_display_details(cxt))
@@ -264,8 +261,10 @@ static int sgi_list_table(struct fdisk_context *cxt)
                        cxt->geom.cylinders, be16_to_cpu(sgiparam->pcylcount),
                        (int) sgiparam->sparecyl, be16_to_cpu(sgiparam->ilfact));
 
-
-       fdisk_list_partitions(cxt, NULL, 0);
+#ifdef UNWANTED
+       char *p;
+       size_t i, used;
+       struct tt *tb = NULL;
 
        /*
         * Volumes
@@ -304,9 +303,8 @@ static int sgi_list_table(struct fdisk_context *cxt)
        if (used)
                rc = fdisk_print_table(cxt, tb);
        tt_free_table(tb);
-
+#endif
        fdisk_colon(cxt, _("Bootfile: %s"), sgilabel->boot_file);
-
        return rc;
 }
 
@@ -813,7 +811,7 @@ static int sgi_add_partition(struct fdisk_context *cxt,
        assert(cxt->label);
        assert(fdisk_is_disklabel(cxt, SGI));
 
-       rc = fdisk_partition_next_partno(cxt, pa, &n);
+       rc = fdisk_partition_next_partno(pa, cxt, &n);
        if (rc)
                return rc;
        if (n == 10)
index f7e07b46ff146dd69a40ba77074398896dd1bdc7..9c064f28efaede916adb22179bdc88428b4843d3 100644 (file)
@@ -480,7 +480,7 @@ static int sun_add_partition(
        size_t i;
        unsigned int first, last;
 
-       rc = fdisk_partition_next_partno(cxt, pa, &n);
+       rc = fdisk_partition_next_partno(pa, cxt, &n);
        if (rc)
                return rc;
 
@@ -731,7 +731,7 @@ static int sun_list_disklabel(struct fdisk_context *cxt)
                       *sunlabel->vtoc.volume_id ? sunlabel->vtoc.volume_id : _("<none>"));
        }
 
-       return fdisk_list_partitions(cxt, NULL, 0);
+       return 0;
 }
 
 static struct fdisk_parttype *sun_get_parttype(
index 34d8fbb8c90667c1657acc21e789e09b331955a8..1d034d42806372e01c12e56e04d4996fd9cf8da0 100644 (file)
@@ -94,6 +94,49 @@ int fdisk_table_is_empty(struct fdisk_table *tb)
        return tb == NULL || list_empty(&tb->parts) ? 1 : 0;
 }
 
+
+/**
+ * fdisk_table_next_partition:
+ * @tb: tab pointer
+ * @itr: iterator
+ * @pa: returns the next tab entry
+ *
+ * Returns: 0 on success, negative number in case of error or 1 at the end of list.
+ *
+ * Example:
+ * <informalexample>
+ *   <programlisting>
+ *     while(fdisk_table_next_partition(tb, itr, &pa) == 0) {
+ *             ...
+ *     }
+ *   </programlisting>
+ * </informalexample>
+ */
+int fdisk_table_next_partition(
+                       struct fdisk_table *tb,
+                       struct fdisk_iter *itr,
+                       struct fdisk_partition **pa)
+{
+       int rc = 1;
+
+       assert(tb);
+       assert(itr);
+       assert(pa);
+
+       if (!tb || !itr || !pa)
+               return -EINVAL;
+       *pa = NULL;
+
+       if (!itr->head)
+               FDISK_ITER_INIT(itr, &tb->parts);
+       if (itr->p != itr->head) {
+               FDISK_ITER_ITERATE(itr, *pa, struct fdisk_partition, parts);
+               rc = 0;
+       }
+
+       return rc;
+}
+
 /**
  * fdisk_table_add_partition
  * @tb: tab pointer
@@ -116,7 +159,9 @@ int fdisk_table_add_partition(struct fdisk_table *tb, struct fdisk_partition *pa
        fdisk_ref_partition(pa);
        list_add_tail(&pa->parts, &tb->parts);
 
-       DBG(TAB, dbgprint("add entry %p", pa));
+       DBG(TAB, dbgprint("add entry %p [start=%ju, size=%ju, freespace=%s]",
+                               pa, pa->start, pa->size,
+                               pa->freespace ? "yes" : "no"));
        return 0;
 }
 
@@ -147,3 +192,186 @@ int fdisk_table_remove_partition(struct fdisk_table *tb, struct fdisk_partition
        fdisk_unref_partition(pa);
        return 0;
 }
+
+static int fdisk_table_add_freespace(
+                       struct fdisk_table *tb,
+                       uint64_t start,
+                       uint64_t end)
+{
+       struct fdisk_partition *pa = fdisk_new_partition();
+       int rc;
+
+       if (!pa)
+               return -ENOMEM;
+
+       assert(tb);
+
+       pa->freespace = 1;
+
+       pa->start = start;
+       pa->end = end;
+       pa->size = pa->end - pa->start + 1ULL;
+
+       rc = fdisk_table_add_partition(tb, pa);
+       fdisk_unref_partition(pa);
+       return rc;
+}
+/**
+ * fdisk_get_table
+ * @cxt: fdisk context
+ * @tb: returns table (allocate a new if not allocate yet)
+ *
+ * Returns 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_get_table(struct fdisk_context *cxt, struct fdisk_table **tb)
+{
+       struct fdisk_partition *pa = NULL;
+       size_t i;
+       uint64_t last, grain;
+
+       if (!cxt || !cxt->label || !tb)
+               return -EINVAL;
+       if (!cxt->label->op->get_part)
+               return -ENOSYS;
+
+       DBG(LABEL, dbgprint("get table [freespace=%s]",
+               fdisk_context_display_freespace(cxt) ? "yes" : "no"));
+
+       if (!*tb) {
+               *tb = fdisk_new_table();
+               if (!*tb)
+                       return -ENOMEM;
+       }
+
+       last = cxt->first_lba;
+       grain = cxt->grain / cxt->sector_size;
+
+       for (i = 0; i < cxt->label->nparts_max; i++) {
+               if (fdisk_get_partition(cxt, i, &pa))
+                       continue;
+               if (!fdisk_partition_is_used(pa))
+                       continue;
+
+               /* add free-space (before partition) to the list */
+               if (fdisk_context_display_freespace(cxt) &&
+                   last + grain < pa->start) {
+                       fdisk_table_add_freespace(*tb,
+                               last + (last > cxt->first_lba ? 1 : 0),
+                               pa->start - 1);
+               }
+               last = pa->end;
+               fdisk_table_add_partition(*tb, pa);
+               fdisk_unref_partition(pa);
+               pa = NULL;
+       }
+
+       /* add free-space (behind last partition) to the list */
+       if (fdisk_context_display_freespace(cxt) &&
+           last + grain < cxt->total_sectors - 1) {
+               fdisk_table_add_freespace(*tb,
+                       last + (last > cxt->first_lba ? 1 : 0),
+                       cxt->total_sectors - 1);
+       }
+
+       return 0;
+}
+
+/**
+ * fdisk_table_to_string
+ * @tb: table
+ * @cxt: fdisk context
+ * @cols: array with wanted FDISK_COL_* columns
+ * @ncols: number of items in the cols array
+ * @data: returns table as a newlly allocated string
+ *
+ * If no @cols are specified then the default is printed (see
+ * fdisk_get_columns() for the default columns).
+
+ * Returns 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_table_to_string(struct fdisk_table *tb,
+                         struct fdisk_context *cxt,
+                         int *cols,
+                         size_t ncols,
+                         char **data)
+{
+       int *org_cols = cols, rc = 0;
+       struct tt *tt = NULL;
+       const struct fdisk_column *col;
+       struct fdisk_partition *pa = NULL;
+       struct fdisk_iter itr;
+       size_t j;
+
+       if (!cxt || !tb || !data)
+               return -EINVAL;
+
+       DBG(TAB, dbgprint("generate string"));
+
+       if (!cols || !ncols) {
+               rc = fdisk_get_columns(cxt, 0, &cols, &ncols);
+               if (rc)
+                       return rc;
+       }
+
+       tt = tt_new_table(TT_FL_FREEDATA);
+       if (!tt) {
+               rc = -ENOMEM;
+               goto done;
+       }
+
+       /* define columns */
+       for (j = 0; j < ncols; j++) {
+               col = fdisk_label_get_column(cxt->label, cols[j]);
+               if (!col)
+                       continue;
+               tt_define_column(tt,
+                       col->id == FDISK_COL_SECTORS &&
+                       fdisk_context_use_cylinders(cxt) ?
+                               _("Cylinders") : col->name,
+                       col->width, col->tt_flags);
+       }
+
+       fdisk_reset_iter(&itr, FDISK_ITER_FORWARD);
+
+       /* convert partition to string and add to tt */
+       while (fdisk_table_next_partition(tb, &itr, &pa) == 0) {
+               struct tt_line *ln = tt_add_line(tt, NULL);
+               if (!ln) {
+                       rc = -ENOMEM;
+                       goto done;
+               }
+
+               DBG(TAB, dbgprint("  string from part #%zu", pa->partno + 1));
+
+               /* set data for the columns */
+               for (j = 0; j < ncols; j++) {
+                       const struct fdisk_column *col;
+                       char *cdata = NULL;
+                       int id;
+
+                       col = fdisk_label_get_column(cxt->label, cols[j]);
+                       if (!col)
+                               continue;
+                       id = (col->id == FDISK_COL_SECTORS &&
+                             fdisk_context_use_cylinders(cxt)) ?
+                                       FDISK_COL_CYLINDERS :
+                                       col->id;
+
+                       if (fdisk_partition_to_string(pa, cxt, id, &cdata))
+                               continue;
+                       tt_line_set_data(ln, j, cdata);
+               }
+       }
+
+       rc = 0;
+       *data = NULL;
+       if (!tt_is_empty(tt))
+               rc = tt_print_table_to_string(tt, data);
+       else
+               DBG(TAB, dbgprint("tt empty"));
+done:
+       if (org_cols != cols)
+               free(cols);
+       tt_free_table(tt);
+       return rc;
+}