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 | |
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')
-rw-r--r-- | libfdisk/src/Makemodule.am | 1 | ||||
-rw-r--r-- | libfdisk/src/bsd.c | 4 | ||||
-rw-r--r-- | libfdisk/src/dos.c | 89 | ||||
-rw-r--r-- | libfdisk/src/fdiskP.h | 32 | ||||
-rw-r--r-- | libfdisk/src/gpt.c | 4 | ||||
-rw-r--r-- | libfdisk/src/iter.c | 73 | ||||
-rw-r--r-- | libfdisk/src/label.c | 167 | ||||
-rw-r--r-- | libfdisk/src/libfdisk.h | 28 | ||||
-rw-r--r-- | libfdisk/src/partition.c | 45 | ||||
-rw-r--r-- | libfdisk/src/sgi.c | 14 | ||||
-rw-r--r-- | libfdisk/src/sun.c | 4 | ||||
-rw-r--r-- | libfdisk/src/table.c | 230 |
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; +} |