diff options
author | Karel Zak | 2013-12-18 10:28:55 +0100 |
---|---|---|
committer | Karel Zak | 2014-03-11 11:35:12 +0100 |
commit | 6c89f750d28d2c554b4bebb8d617f4202d36bbb6 (patch) | |
tree | ff9e8fdb1d69b7e0f6a24f712a3438b5d2d6b247 /libfdisk/src/table.c | |
parent | include/tt: add function to convert table to string (diff) | |
download | kernel-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.c | 230 |
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; +} |