summaryrefslogtreecommitdiffstats
path: root/libfdisk/src/table.c
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/table.c
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/table.c')
-rw-r--r--libfdisk/src/table.c230
1 files changed, 229 insertions, 1 deletions
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;
+}