summaryrefslogtreecommitdiffstats
path: root/libfdisk/src
diff options
context:
space:
mode:
authorKarel Zak2013-12-18 10:28:55 +0100
committerKarel Zak2014-03-11 11:35:12 +0100
commit6c89f750d28d2c554b4bebb8d617f4202d36bbb6 (patch)
treeff9e8fdb1d69b7e0f6a24f712a3438b5d2d6b247 /libfdisk/src
parentinclude/tt: add function to convert table to string (diff)
downloadkernel-qcow2-util-linux-6c89f750d28d2c554b4bebb8d617f4202d36bbb6.tar.gz
kernel-qcow2-util-linux-6c89f750d28d2c554b4bebb8d617f4202d36bbb6.tar.xz
kernel-qcow2-util-linux-6c89f750d28d2c554b4bebb8d617f4202d36bbb6.zip
libfdisk: use fdisk_table to generate output
* 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>
Diffstat (limited to 'libfdisk/src')
-rw-r--r--libfdisk/src/Makemodule.am1
-rw-r--r--libfdisk/src/bsd.c4
-rw-r--r--libfdisk/src/dos.c89
-rw-r--r--libfdisk/src/fdiskP.h32
-rw-r--r--libfdisk/src/gpt.c4
-rw-r--r--libfdisk/src/iter.c73
-rw-r--r--libfdisk/src/label.c167
-rw-r--r--libfdisk/src/libfdisk.h28
-rw-r--r--libfdisk/src/partition.c45
-rw-r--r--libfdisk/src/sgi.c14
-rw-r--r--libfdisk/src/sun.c4
-rw-r--r--libfdisk/src/table.c230
12 files changed, 401 insertions, 290 deletions
diff --git a/libfdisk/src/Makemodule.am b/libfdisk/src/Makemodule.am
index a87b2efcc..d8cbffbe3 100644
--- a/libfdisk/src/Makemodule.am
+++ b/libfdisk/src/Makemodule.am
@@ -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 \
diff --git a/libfdisk/src/bsd.c b/libfdisk/src/bsd.c
index 4ee31b6dd..849536328 100644
--- a/libfdisk/src/bsd.c
+++ b/libfdisk/src/bsd.c
@@ -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,
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index e23470f65..63072fc3f 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -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,
diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h
index 6459b3635..1cd8b4874 100644
--- a/libfdisk/src/fdiskP.h
+++ b/libfdisk/src/fdiskP.h
@@ -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);
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c
index 14aafc472..c9917cf56 100644
--- a/libfdisk/src/gpt.c
+++ b/libfdisk/src/gpt.c
@@ -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
index 000000000..8e2f34202
--- /dev/null
+++ b/libfdisk/src/iter.c
@@ -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;
+}
diff --git a/libfdisk/src/label.c b/libfdisk/src/label.c
index 99571232c..00b25ee29 100644
--- a/libfdisk/src/label.c
+++ b/libfdisk/src/label.c
@@ -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
diff --git a/libfdisk/src/libfdisk.h b/libfdisk/src/libfdisk.h
index 0d30df8d6..8d03990a0 100644
--- a/libfdisk/src/libfdisk.h
+++ b/libfdisk/src/libfdisk.h
@@ -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
diff --git a/libfdisk/src/partition.c b/libfdisk/src/partition.c
index 513af4f0a..fb9908e8b 100644
--- a/libfdisk/src/partition.c
+++ b/libfdisk/src/partition.c
@@ -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;
}
diff --git a/libfdisk/src/sgi.c b/libfdisk/src/sgi.c
index aa03d0319..33a13c8b7 100644
--- a/libfdisk/src/sgi.c
+++ b/libfdisk/src/sgi.c
@@ -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)
diff --git a/libfdisk/src/sun.c b/libfdisk/src/sun.c
index f7e07b46f..9c064f28e 100644
--- a/libfdisk/src/sun.c
+++ b/libfdisk/src/sun.c
@@ -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(
diff --git a/libfdisk/src/table.c b/libfdisk/src/table.c
index 34d8fbb8c..1d034d428 100644
--- a/libfdisk/src/table.c
+++ b/libfdisk/src/table.c
@@ -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;
+}