diff options
author | Karel Zak | 2014-01-30 12:21:11 +0100 |
---|---|---|
committer | Karel Zak | 2014-03-11 11:35:13 +0100 |
commit | 2cec7949947aa6d48112ea4f0928e6698174f342 (patch) | |
tree | cb3e63b0ef026c1f13bd7e9e99c8995aa817b8c8 /libfdisk | |
parent | cfdisk: add UI for linfdisk menus, ask for size (diff) | |
download | kernel-qcow2-util-linux-2cec7949947aa6d48112ea4f0928e6698174f342.tar.gz kernel-qcow2-util-linux-2cec7949947aa6d48112ea4f0928e6698174f342.tar.xz kernel-qcow2-util-linux-2cec7949947aa6d48112ea4f0928e6698174f342.zip |
libfdisk: rewrite freespace code
* use separate function to get free space
* allow to use label-specific get_freespace() function
(this is necessary for MBR extended partitions mess)
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk')
-rw-r--r-- | libfdisk/src/context.c | 22 | ||||
-rw-r--r-- | libfdisk/src/fdiskP.h | 10 | ||||
-rw-r--r-- | libfdisk/src/libfdisk.h | 6 | ||||
-rw-r--r-- | libfdisk/src/table.c | 149 |
4 files changed, 124 insertions, 63 deletions
diff --git a/libfdisk/src/context.c b/libfdisk/src/context.c index 0db21c81e..c4054034e 100644 --- a/libfdisk/src/context.c +++ b/libfdisk/src/context.c @@ -382,28 +382,6 @@ int fdisk_context_display_details(struct fdisk_context *cxt) } /** - * fdisk_context_enable_freespace - * cxt: context - * enable: true/flase - * - * Enables or disables "free space" in list() output - * - * Returns: 0 on success, < 0 on error. - */ -int fdisk_context_enable_freespace(struct fdisk_context *cxt, int enable) -{ - assert(cxt); - cxt->display_freespace = enable ? 1 : 0; - return 0; -} - -int fdisk_context_display_freespace(struct fdisk_context *cxt) -{ - assert(cxt); - return cxt->display_freespace == 1; -} - -/** * fdisk_context_enable_listonly: * cxt: context * enable: true/flase diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h index eb8b90bc9..46e6c430e 100644 --- a/libfdisk/src/fdiskP.h +++ b/libfdisk/src/fdiskP.h @@ -201,6 +201,13 @@ struct fdisk_table { size_t nents; /* number of partitions */ }; +extern int fdisk_table_add_freespace( + struct fdisk_context *cxt, + struct fdisk_table *tb, + uint64_t start, + uint64_t end, + int dosort); + /* * Legacy CHS based geometry */ @@ -253,6 +260,8 @@ struct fdisk_label_operations { int (*get_part)(struct fdisk_context *cxt, size_t n, struct fdisk_partition *pa); + /* add all gaps to table */ + int (*get_freespace)(struct fdisk_context *cxt, struct fdisk_table *tb); int (*part_toggle_flag)(struct fdisk_context *cxt, size_t i, unsigned long flag); @@ -388,7 +397,6 @@ struct fdisk_context { unsigned int display_in_cyl_units : 1, /* for obscure labels */ display_details : 1, /* expert display mode */ - display_freespace : 1, /* freesapce in list() output */ listonly : 1; /* list partition, nothing else */ /* alignment */ diff --git a/libfdisk/src/libfdisk.h b/libfdisk/src/libfdisk.h index fe1d290aa..d3f51c812 100644 --- a/libfdisk/src/libfdisk.h +++ b/libfdisk/src/libfdisk.h @@ -98,10 +98,8 @@ extern const char *fdisk_context_get_unit(struct fdisk_context *cxt, int n); extern unsigned int fdisk_context_get_units_per_sector(struct fdisk_context *cxt); extern int fdisk_context_enable_details(struct fdisk_context *cxt, int enable); -extern int fdisk_context_enable_freespace(struct fdisk_context *cxt, int enable); extern int fdisk_context_use_cylinders(struct fdisk_context *cxt); extern int fdisk_context_display_details(struct fdisk_context *cxt); -extern int fdisk_context_display_freespace(struct fdisk_context *cxt); /* parttype.c */ extern struct fdisk_parttype *fdisk_get_parttype_from_code(struct fdisk_context *cxt, @@ -224,7 +222,9 @@ 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_get_partitions(struct fdisk_context *cxt, struct fdisk_table **tb); +extern int fdisk_get_freespaces(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); diff --git a/libfdisk/src/table.c b/libfdisk/src/table.c index 88c6ebff7..af056da18 100644 --- a/libfdisk/src/table.c +++ b/libfdisk/src/table.c @@ -198,6 +198,28 @@ int fdisk_table_add_partition(struct fdisk_table *tb, struct fdisk_partition *pa return 0; } +/* inserts @pa after @poz */ +static int table_insert_partition( + struct fdisk_table *tb, + struct fdisk_partition *poz, + struct fdisk_partition *pa) +{ + assert(tb); + assert(pa); + + fdisk_ref_partition(pa); + if (poz) + list_add(&pa->parts, &poz->parts); + else + list_add(&pa->parts, &tb->parts); + tb->nents++; + + DBG(TAB, dbgprint("insert entry %p [start=%ju, end=%ju, size=%ju, freespace=%s]", + pa, pa->start, pa->end, pa->size, + pa->freespace ? "yes" : "no")); + return 0; +} + /** * fdisk_table_remove_partition * @tb: tab pointer @@ -228,88 +250,141 @@ int fdisk_table_remove_partition(struct fdisk_table *tb, struct fdisk_partition return 0; } -static int fdisk_table_add_freespace( +/** + * fdisk_get_partitions + * @cxt: fdisk context + * @tb: returns table + * + * This function adds partitions from disklabel to @table, it allocates a new + * table if if @table points to NULL. + * + * Returns 0 on success, otherwise, a corresponding error. + */ +int fdisk_get_partitions(struct fdisk_context *cxt, struct fdisk_table **tb) +{ + size_t i; + + if (!cxt || !cxt->label || !tb) + return -EINVAL; + if (!cxt->label->op->get_part) + return -ENOSYS; + + DBG(LABEL, dbgprint("get table")); + + if (!*tb && !(*tb = fdisk_new_table())) + return -ENOMEM; + + for (i = 0; i < cxt->label->nparts_max; i++) { + struct fdisk_partition *pa = NULL; + + if (fdisk_get_partition(cxt, i, &pa) != 0) + continue; + if (fdisk_partition_is_used(pa)) + fdisk_table_add_partition(*tb, pa); + fdisk_unref_partition(pa); + } + + return 0; +} + +int fdisk_table_add_freespace( struct fdisk_context *cxt, struct fdisk_table *tb, uint64_t start, - uint64_t end) + uint64_t end, + int dosort) { struct fdisk_partition *pa = fdisk_new_partition(); - int rc; - - if (!pa) - return -ENOMEM; + int rc = 0; assert(tb); + if (!pa) + return -ENOMEM; pa->freespace = 1; - pa->start = fdisk_align_lba_in_range(cxt, start, start, end); pa->end = end; pa->size = pa->end - pa->start + 1ULL; - rc = fdisk_table_add_partition(tb, pa); + if (!dosort) + rc = fdisk_table_add_partition(tb, pa); + else { + struct fdisk_partition *x, *best = NULL; + struct fdisk_iter itr; + + fdisk_reset_iter(&itr, FDISK_ITER_FORWARD); + while (fdisk_table_next_partition(tb, &itr, &x) == 0) { + if (x->end < pa->start && (!best || best->end < x->end)) + best = x; + } + rc = table_insert_partition(tb, best, pa); + } fdisk_unref_partition(pa); return rc; } + + /** - * fdisk_get_table + * fdisk_get_freespaces * @cxt: fdisk context - * @tb: returns table (allocate a new if not allocate yet) + * @tb: returns table * + * This function adds freespace (described by fdisk_partition) to @table, it + * allocates a new table if if @table points to NULL. + * Returns 0 on success, otherwise, a corresponding error. */ -int fdisk_get_table(struct fdisk_context *cxt, struct fdisk_table **tb) +int fdisk_get_freespaces(struct fdisk_context *cxt, struct fdisk_table **tb) { - struct fdisk_partition *pa = NULL; + int dosort, rc = 0; size_t i; uint64_t last, grain; + DBG(LABEL, dbgprint("get freespace")); + 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())) + return -ENOMEM; - if (!*tb) { - *tb = fdisk_new_table(); - if (!*tb) - return -ENOMEM; - } + /* label specific way */ + if (cxt->label->op->get_freespace) + return cxt->label->op->get_freespace(cxt, *tb); + /* generic way -- check for gaps betten partitions */ + dosort = !fdisk_table_is_empty(*tb); last = cxt->first_lba; grain = cxt->grain / cxt->sector_size; - for (i = 0; i < cxt->label->nparts_max; i++) { + for (i = 0; rc == 0 && i < cxt->label->nparts_max; i++) { + struct fdisk_partition *pa = NULL; + if (fdisk_get_partition(cxt, i, &pa)) continue; - if (!fdisk_partition_is_used(pa)) + if (!fdisk_partition_is_used(pa)) { + fdisk_unref_partition(pa); continue; + } /* add free-space (before partition) to the list */ - if (fdisk_context_display_freespace(cxt) && - last + grain < pa->start) { - fdisk_table_add_freespace(cxt, *tb, + if (last + grain < pa->start) { + rc = fdisk_table_add_freespace(cxt, *tb, last + (last > cxt->first_lba ? 1 : 0), - pa->start - 1); + pa->start - 1, + dosort); } + 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(cxt, *tb, + if (rc == 0 && last + grain < cxt->total_sectors - 1) + rc = fdisk_table_add_freespace(cxt, *tb, last + (last > cxt->first_lba ? 1 : 0), - cxt->last_lba); - } - - return 0; + cxt->last_lba, + dosort); + return rc; } /** |