diff options
author | Karel Zak | 2014-10-15 12:17:40 +0200 |
---|---|---|
committer | Karel Zak | 2014-10-15 12:17:40 +0200 |
commit | ecf40cda764496d3d1b29435ea64a65335ae0acf (patch) | |
tree | 9ef1d00a3906fd495194b88ca5023c9729353df0 | |
parent | tests: check for wipefs and helpers in fdisk tests (diff) | |
download | kernel-qcow2-util-linux-ecf40cda764496d3d1b29435ea64a65335ae0acf.tar.gz kernel-qcow2-util-linux-ecf40cda764496d3d1b29435ea64a65335ae0acf.tar.xz kernel-qcow2-util-linux-ecf40cda764496d3d1b29435ea64a65335ae0acf.zip |
libfdisk: make it possible to use zero for size and start
The zero may be valid size and start of the partition. This patch
introduces:
fdisk_partition_has_start()
fdisk_partition_has_size()
fdisk_partition_unset_size()
fdisk_partition_unset_start()
to make it possible to work with zero. The feature is internally
implemented by magic constant ((type) -1) for undefined sizes and
offsets.
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r-- | disk-utils/cfdisk.c | 3 | ||||
-rw-r--r-- | disk-utils/fdisk-list.c | 2 | ||||
-rw-r--r-- | disk-utils/sfdisk.c | 2 | ||||
-rw-r--r-- | libfdisk/src/bsd.c | 16 | ||||
-rw-r--r-- | libfdisk/src/dos.c | 56 | ||||
-rw-r--r-- | libfdisk/src/fdiskP.h | 24 | ||||
-rw-r--r-- | libfdisk/src/gpt.c | 23 | ||||
-rw-r--r-- | libfdisk/src/label.c | 11 | ||||
-rw-r--r-- | libfdisk/src/libfdisk.h | 22 | ||||
-rw-r--r-- | libfdisk/src/partition.c | 263 | ||||
-rw-r--r-- | libfdisk/src/script.c | 6 | ||||
-rw-r--r-- | libfdisk/src/sgi.c | 8 | ||||
-rw-r--r-- | libfdisk/src/sun.c | 8 | ||||
-rw-r--r-- | libfdisk/src/table.c | 11 |
14 files changed, 277 insertions, 178 deletions
diff --git a/disk-utils/cfdisk.c b/disk-utils/cfdisk.c index 1f2ad7c49..496871311 100644 --- a/disk-utils/cfdisk.c +++ b/disk-utils/cfdisk.c @@ -1812,7 +1812,8 @@ static int main_menu_action(struct cfdisk *cf, int key) struct fdisk_partition *npa; /* the new partition */ int expsize = 0; /* size specified explicitly in sectors */ - if (!pa || !fdisk_partition_is_freespace(pa)) + if (!pa || !fdisk_partition_is_freespace(pa) + || !fdisk_partition_has_start(pa)) return -EINVAL; npa = fdisk_new_partition(); if (!npa) diff --git a/disk-utils/fdisk-list.c b/disk-utils/fdisk-list.c index 46d50a7f3..d0d752ef6 100644 --- a/disk-utils/fdisk-list.c +++ b/disk-utils/fdisk-list.c @@ -171,6 +171,8 @@ void list_disklabel(struct fdisk_context *cxt) /* print warnings */ while (itr && fdisk_table_next_partition(tb, itr, &pa) == 0) { + if (!fdisk_partition_has_start(pa)) + continue; if (!fdisk_lba_is_phy_aligned(cxt, fdisk_partition_get_start(pa))) fdisk_warnx(cxt, _("Partition %zu does not start on physical sector boundary."), fdisk_partition_get_partno(pa) + 1); diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c index 68df57c0d..821b5ed15 100644 --- a/disk-utils/sfdisk.c +++ b/disk-utils/sfdisk.c @@ -1230,7 +1230,7 @@ static int command_fdisk(struct sfdisk *sf, int argc, char **argv) assert(pa); - if (!fdisk_partition_get_start(pa) && + if (!fdisk_partition_has_start(pa) && !fdisk_partition_start_is_default(pa)) { fdisk_info(sf->cxt, _("Ignore partition %zu"), next_partno + 1); continue; diff --git a/libfdisk/src/bsd.c b/libfdisk/src/bsd.c index dfc47bda0..c92c893bb 100644 --- a/libfdisk/src/bsd.c +++ b/libfdisk/src/bsd.c @@ -238,7 +238,7 @@ static int bsd_add_partition(struct fdisk_context *cxt, */ if (pa && pa->start_follow_default) ; - else if (pa && pa->start) { + else if (pa && fdisk_partition_has_start(pa)) { if (pa->start < begin || pa->start > end) return -ERANGE; begin = pa->start; @@ -269,7 +269,7 @@ static int bsd_add_partition(struct fdisk_context *cxt, */ if (pa && pa->end_follow_default) ; - else if (pa && pa->size) { + else if (pa && fdisk_partition_has_size(pa)) { if (begin + pa->size > end) return -ERANGE; end = begin + pa->size - 1ULL; @@ -335,11 +335,13 @@ static int bsd_set_partition(struct fdisk_context *cxt, size_t n, p = &d->d_partitions[n]; /* we have to stay within parental DOS partition */ - if (l->dos_part && (pa->start || pa->size)) { + if (l->dos_part && (fdisk_partition_has_start(pa) || + fdisk_partition_has_size(pa))) { + sector_t dosbegin = dos_partition_get_start(l->dos_part); sector_t dosend = dosbegin + dos_partition_get_size(l->dos_part) - 1; - sector_t begin = pa->start ? pa->start : p->p_offset; - sector_t end = begin + (pa->size ? pa->size : p->p_size) - 1; + sector_t begin = fdisk_partition_has_start(pa) ? pa->start : p->p_offset; + sector_t end = begin + (fdisk_partition_has_size(pa) ? pa->size : p->p_size) - 1; if (begin < dosbegin || begin > dosend) return -ERANGE; @@ -353,9 +355,9 @@ static int bsd_set_partition(struct fdisk_context *cxt, size_t n, return rc; } - if (pa->start) + if (fdisk_partition_has_start(pa)) d->d_partitions[n].p_offset = pa->start; - if (pa->size) + if (fdisk_partition_has_size(pa)) d->d_partitions[n].p_size = pa->size; fdisk_label_set_changed(cxt->label, 1); diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c index 0ae0615a2..bcfacfc7d 100644 --- a/libfdisk/src/dos.c +++ b/libfdisk/src/dos.c @@ -819,6 +819,8 @@ static void set_partition(struct fdisk_context *cxt, struct dos_partition *p; sector_t offset; + assert(!FDISK_IS_UNDEF(start)); + assert(!FDISK_IS_UNDEF(stop)); if (doext) { struct fdisk_dos_label *l = self_label(cxt); @@ -902,7 +904,7 @@ static int get_start_from_user( struct fdisk_context *cxt, if (pa && pa->start_follow_default) *start = dflt; - else if (pa && pa->start) { + else if (pa && fdisk_partition_has_start(pa)) { DBG(LABEL, ul_debug("DOS: start: wanted=%ju, low=%ju, limit=%ju", (uintmax_t) pa->start, (uintmax_t) low, (uintmax_t) limit)); *start = pa->start; @@ -971,7 +973,8 @@ static int add_partition(struct fdisk_context *cxt, size_t n, if (cxt->parent && fdisk_is_label(cxt->parent, GPT)) start = 1; /* Bad boy modifies hybrid MBR */ else { - if (cxt->script && pa && pa->start && pa->start < cxt->first_lba + if (cxt->script && pa && fdisk_partition_has_start(pa) + && pa->start < cxt->first_lba && pa->start >= 1) fdisk_set_first_lba(cxt, 1); @@ -995,7 +998,8 @@ static int add_partition(struct fdisk_context *cxt, size_t n, assert(ext_pe); limit = get_abs_partition_end(ext_pe); - if (cxt->script && pa && pa->start && pa->start >= l->ext_offset + if (cxt->script && pa && fdisk_partition_has_start(pa) + && pa->start >= l->ext_offset && pa->start < l->ext_offset + cxt->first_lba) fdisk_set_first_lba(cxt, 1); @@ -1017,7 +1021,7 @@ static int add_partition(struct fdisk_context *cxt, size_t n, temp = start; dflt = start = get_unused_start(cxt, n, start, first, last); - if (n >= 4 && pa && pa->start && cxt->script + if (n >= 4 && pa && fdisk_partition_has_start(pa) && cxt->script && cxt->first_lba > 1 && temp == start - cxt->first_lba) { fdisk_set_first_lba(cxt, 1); @@ -1040,7 +1044,8 @@ static int add_partition(struct fdisk_context *cxt, size_t n, temp); temp = start; read = 0; - if (pa && (pa->start || pa->start_follow_default)) + if (pa && (fdisk_partition_has_start(pa) || + pa->start_follow_default)) break; } @@ -1091,7 +1096,7 @@ static int add_partition(struct fdisk_context *cxt, size_t n, stop = limit; else if (pa && pa->end_follow_default) stop = limit; - else if (pa && pa->size) { + else if (pa && fdisk_partition_has_size(pa)) { stop = start + pa->size - 1; isrel = pa->size_explicit ? 0 : 1; } else { @@ -1148,7 +1153,7 @@ static int add_partition(struct fdisk_context *cxt, size_t n, } } - set_partition(cxt, n, 0, start, stop, sys, pa && pa->boot ? 1 : 0); + set_partition(cxt, n, 0, start, stop, sys, pa && pa->boot == 1 ? 1 : 0); if (n > 4) { struct pte *pe = self_pte(cxt, n); set_partition(cxt, n - 1, 1, pe->offset, stop, @@ -1445,7 +1450,7 @@ static int dos_add_partition(struct fdisk_context *cxt, */ /* pa specifies start within extended partition, add logical */ - if (pa && pa->start && ext_pe + if (pa && fdisk_partition_has_start(pa) && ext_pe && pa->start >= l->ext_offset && pa->start <= get_abs_partition_end(ext_pe)) { DBG(LABEL, ul_debug("DOS: pa template %p: add logical", pa)); @@ -1466,7 +1471,7 @@ static int dos_add_partition(struct fdisk_context *cxt, } /* pa specifies start, but outside extended partition */ - } else if (pa && pa->start && l->ext_offset) { + } else if (pa && fdisk_partition_has_start(pa) && l->ext_offset) { DBG(LABEL, ul_debug("DOS: pa template %p: add primary", pa)); res = get_partition_unused_primary(cxt, pa); if (res >= 0) { @@ -1508,7 +1513,7 @@ static int dos_add_partition(struct fdisk_context *cxt, if (!free_primary || !free_sectors) { DBG(LABEL, ul_debug("DOS: primary impossible, add logical")); if (l->ext_offset) { - if (!pa || pa->start) { + if (!pa || fdisk_partition_has_start(pa)) { if (!free_primary) fdisk_info(cxt, _("All primary partitions are in use.")); else if (!free_sectors) @@ -1578,15 +1583,22 @@ static int dos_add_partition(struct fdisk_context *cxt, } else if (c == 'e' && !l->ext_offset) { res = get_partition_unused_primary(cxt, pa); if (res >= 0) { - struct fdisk_partition xpa = { .type = NULL }; + struct fdisk_partition *xpa = NULL; struct fdisk_parttype *t; t = fdisk_label_get_parttype_from_code(cxt->label, MBR_DOS_EXTENDED_PARTITION); - if (!pa) - pa = &xpa; + if (!pa) { + pa = xpa = fdisk_new_partition(); + if (!xpa) + return -ENOMEM; + } fdisk_partition_set_type(pa, t); rc = add_partition(cxt, res, pa); + if (xpa) { + fdisk_unref_partition(xpa); + pa = NULL; + } } goto done; } else @@ -1787,14 +1799,14 @@ static int dos_get_partition(struct fdisk_context *cxt, size_t n, return -ENOMEM; /* start C/H/S */ - if (asprintf(&pa->start_addr, "%d/%d/%d", + if (asprintf(&pa->start_chs, "%d/%d/%d", cylinder(p->bs, p->bc), sector(p->bs), p->bh) < 0) return -ENOMEM; /* end C/H/S */ - if (asprintf(&pa->end_addr, "%d/%d/%d", + if (asprintf(&pa->end_chs, "%d/%d/%d", cylinder(p->es, p->ec), sector(p->es), p->eh) < 0) @@ -1829,22 +1841,25 @@ static int dos_set_partition(struct fdisk_context *cxt, size_t n, p = self_partition(cxt, n); - if (pa->start || pa->size) { + if (fdisk_partition_has_start(pa) || fdisk_partition_has_size(pa)) { sector_t start, size; + DBG(LABEL, ul_debug("DOS: resize partition")); + pe = self_pte(cxt, n); - start = pa->start ? pa->start : get_abs_partition_start(pe); - size = pa->size ? pa->size : dos_partition_get_size(p); + start = fdisk_partition_has_start(pa) ? pa->start : get_abs_partition_start(pe); + size = fdisk_partition_has_size(pa) ? pa->size : dos_partition_get_size(p); set_partition(cxt, n, 0, start, start + size - 1, pa->type ? pa->type->code : p->sys_ind, - pa->boot); + pa->boot == 1); } else { + DBG(LABEL, ul_debug("DOS: keep size, modify properties")); if (pa->type) p->sys_ind = pa->type->code; - if (pa->boot != FDISK_EMPTY_BOOTFLAG) + if (!FDISK_IS_UNDEF(pa->boot)) p->boot_ind = pa->boot == 1 ? ACTIVE_FLAG : 0; } @@ -2006,6 +2021,7 @@ static int dos_reorder(struct fdisk_context *cxt) return 0; } +/* TODO: use fdisk_set_partition() API */ int fdisk_dos_move_begin(struct fdisk_context *cxt, size_t i) { struct pte *pe; diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h index 253c515f8..7822466a2 100644 --- a/libfdisk/src/fdiskP.h +++ b/libfdisk/src/fdiskP.h @@ -113,6 +113,7 @@ enum { struct fdisk_partition { int refcount; /* reference counter */ + size_t partno; /* partition number */ size_t parent_partno; /* for logical partitions */ @@ -136,24 +137,23 @@ struct fdisk_partition { uint64_t bsize; uint64_t cpg; - char *start_addr; /* start C/H/S in string */ - char *end_addr; /* end C/H/S in string */ + char *start_chs; /* start C/H/S in string */ + char *end_chs; /* end C/H/S in string */ - int boot; /* MBR only: 1 = yes, 0 = no, -1 undefined */ + unsigned int boot; /* MBR: bootable */ - unsigned int partno_follow_default : 1, /* use default partno */ - start_follow_default : 1, /* use default start */ + unsigned int container : 1, /* container partition (e.g. extended partition) */ end_follow_default : 1, /* use default end */ + freespace : 1, /* this is free space */ + partno_follow_default : 1, /* use default partno */ size_explicit : 1, /* don't align the size */ - freespace : 1, /* this is free space */ - container : 1, /* container partition (e.g. extended partition) */ - wholedisk : 1, /* special system partition */ - used : 1; /* partition already used */ + start_follow_default : 1, /* use default start */ + used : 1, /* partition already used */ + wholedisk : 1; /* special system partition */ }; -#define FDISK_EMPTY_PARTNO ((size_t) -1) -#define FDISK_EMPTY_PARTITION { .partno = FDISK_EMPTY_PARTNO } -#define FDISK_EMPTY_BOOTFLAG (-1) +#define FDISK_INIT_UNDEF(_x) ((_x) = (__typeof__(_x)) -1) +#define FDISK_IS_UNDEF(_x) ((_x) == (__typeof__(_x)) -1) struct fdisk_table { struct list_head parts; /* partitions */ diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c index e695bea9d..ec6dbd664 100644 --- a/libfdisk/src/gpt.c +++ b/libfdisk/src/gpt.c @@ -1545,13 +1545,11 @@ static int gpt_set_partition(struct fdisk_context *cxt, size_t n, return rc; } - if (pa->start) + if (fdisk_partition_has_start(pa)) e->lba_start = cpu_to_le64(pa->start); - if (pa->size) + if (fdisk_partition_has_size(pa)) e->lba_end = cpu_to_le64(gpt_partition_start(e) + pa->size - 1ULL); - /* TODO: pa->attrs */ - gpt_recompute_crc(gpt->pheader, gpt->ents); gpt_recompute_crc(gpt->bheader, gpt->ents); @@ -1954,15 +1952,16 @@ static int gpt_add_partition( dflt_f = fdisk_align_lba_in_range(cxt, dflt_f, dflt_f, dflt_l); /* first sector */ - if (pa && pa->start) { + if (pa && pa->start_follow_default) { + user_f = dflt_f; + + } else if (pa && fdisk_partition_has_start(pa)) { DBG(LABEL, ul_debug("first sector defined: %ju", pa->start)); if (pa->start != find_first_available(pheader, ents, pa->start)) { fdisk_warnx(cxt, _("Sector %ju already used."), pa->start); return -ERANGE; } user_f = pa->start; - } else if (pa && pa->start_follow_default) { - user_f = dflt_f; } else { /* ask by dialog */ for (;;) { @@ -1995,15 +1994,16 @@ static int gpt_add_partition( /* Last sector */ dflt_l = find_last_free(pheader, ents, user_f); - if (pa && pa->size) { + if (pa && pa->end_follow_default) { + user_l = dflt_l; + + } else if (pa && fdisk_partition_has_size(pa)) { user_l = user_f + pa->size - 1; DBG(LABEL, ul_debug("size defined: %ju, end: %ju (last possible: %ju)", pa->size, user_l, dflt_l)); if (user_l != dflt_l && !pa->size_explicit) user_l = fdisk_align_lba_in_range(cxt, user_l, user_f, dflt_l) - 1; - } else if (pa && pa->end_follow_default) { - user_l = dflt_l; } else { for (;;) { if (!ask) @@ -2045,6 +2045,9 @@ static int gpt_add_partition( goto done; } + assert(!FDISK_IS_UNDEF(user_l)); + assert(!FDISK_IS_UNDEF(user_f)); + e = &ents[partnum]; e->lba_end = cpu_to_le64(user_l); e->lba_start = cpu_to_le64(user_f); diff --git a/libfdisk/src/label.c b/libfdisk/src/label.c index a3a4e8812..12ad1dc30 100644 --- a/libfdisk/src/label.c +++ b/libfdisk/src/label.c @@ -434,10 +434,17 @@ int fdisk_set_partition_type(struct fdisk_context *cxt, if (cxt->label->op->set_part) { - struct fdisk_partition pa = { .type = t }; + struct fdisk_partition *pa = fdisk_new_partition(); + int rc; + + if (!pa) + return -ENOMEM; + fdisk_partition_set_type(pa, t); DBG(CXT, ul_debugobj(cxt, "partition: %zd: set type", partnum)); - return cxt->label->op->set_part(cxt, partnum, &pa); + rc = cxt->label->op->set_part(cxt, partnum, pa); + fdisk_unref_partition(pa); + return rc; } return -ENOSYS; diff --git a/libfdisk/src/libfdisk.h b/libfdisk/src/libfdisk.h index 047119983..260f90839 100644 --- a/libfdisk/src/libfdisk.h +++ b/libfdisk/src/libfdisk.h @@ -247,16 +247,20 @@ extern void fdisk_ref_partition(struct fdisk_partition *pa); extern void fdisk_unref_partition(struct fdisk_partition *pa); extern int fdisk_partition_is_freespace(struct fdisk_partition *pa); -extern int fdisk_partition_set_start(struct fdisk_partition *pa, uint64_t off); -extern uint64_t fdisk_partition_get_start(struct fdisk_partition *pa); -extern int fdisk_partition_cmp_start(struct fdisk_partition *a, +int fdisk_partition_set_start(struct fdisk_partition *pa, uint64_t off); +int fdisk_partition_unset_start(struct fdisk_partition *pa); +uint64_t fdisk_partition_get_start(struct fdisk_partition *pa); +int fdisk_partition_has_start(struct fdisk_partition *pa); +int fdisk_partition_cmp_start(struct fdisk_partition *a, struct fdisk_partition *b); +int fdisk_partition_start_follow_default(struct fdisk_partition *pa, int enable); +int fdisk_partition_start_is_default(struct fdisk_partition *pa); -extern int fdisk_partition_set_end(struct fdisk_partition *pa, uint64_t off); -extern uint64_t fdisk_partition_get_end(struct fdisk_partition *pa); -extern int fdisk_partition_set_size(struct fdisk_partition *pa, uint64_t size); -extern int fdisk_partition_size_explicit(struct fdisk_partition *pa, int enable); -extern uint64_t fdisk_partition_get_size(struct fdisk_partition *pa); +int fdisk_partition_set_size(struct fdisk_partition *pa, uint64_t sz); +int fdisk_partition_unset_size(struct fdisk_partition *pa); +uint64_t fdisk_partition_get_size(struct fdisk_partition *pa); +int fdisk_partition_has_size(struct fdisk_partition *pa); +int fdisk_partition_size_explicit(struct fdisk_partition *pa, int enable); extern int fdisk_partition_set_partno(struct fdisk_partition *pa, size_t n); extern size_t fdisk_partition_get_partno(struct fdisk_partition *pa); @@ -285,10 +289,8 @@ extern int fdisk_partition_next_partno(struct fdisk_partition *pa, size_t *n); extern int fdisk_partition_partno_follow_default(struct fdisk_partition *pa, int enable); -extern int fdisk_partition_start_follow_default(struct fdisk_partition *pa, int enable); extern int fdisk_partition_end_follow_default(struct fdisk_partition *pa, int enable); extern int fdisk_partition_end_is_default(struct fdisk_partition *pa); -extern int fdisk_partition_start_is_default(struct fdisk_partition *pa); extern int fdisk_reorder_partitions(struct fdisk_context *cxt); diff --git a/libfdisk/src/partition.c b/libfdisk/src/partition.c index cad4214ed..e510c649d 100644 --- a/libfdisk/src/partition.c +++ b/libfdisk/src/partition.c @@ -4,6 +4,19 @@ #include "fdiskP.h" + +static void init_partition(struct fdisk_partition *pa) +{ + FDISK_INIT_UNDEF(pa->size); + FDISK_INIT_UNDEF(pa->start); + FDISK_INIT_UNDEF(pa->end); + FDISK_INIT_UNDEF(pa->partno); + FDISK_INIT_UNDEF(pa->parent_partno); + FDISK_INIT_UNDEF(pa->boot); + + INIT_LIST_HEAD(&pa->parts); +} + /** * fdisk_new_partition: * @@ -14,10 +27,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; - pa->parent_partno = FDISK_EMPTY_PARTNO; - pa->boot = FDISK_EMPTY_BOOTFLAG; + init_partition(pa); DBG(PART, ul_debugobj(pa, "alloc")); return pa; } @@ -37,16 +47,16 @@ void fdisk_reset_partition(struct fdisk_partition *pa) DBG(PART, ul_debugobj(pa, "reset")); ref = pa->refcount; + fdisk_free_parttype(pa->type); free(pa->name); free(pa->uuid); free(pa->attrs); + memset(pa, 0, sizeof(*pa)); - pa->partno = FDISK_EMPTY_PARTNO; - pa->parent_partno = FDISK_EMPTY_PARTNO; - pa->boot = FDISK_EMPTY_BOOTFLAG; pa->refcount = ref; - INIT_LIST_HEAD(&pa->parts); + + init_partition(pa); } /** @@ -85,7 +95,10 @@ void fdisk_unref_partition(struct fdisk_partition *pa) /** * fdisk_partition_set_start: * @pa: partition - * @off: offset in sectors + * @off: offset in sectors, maximal is UINT64_MAX-1 + * + * Note that zero is valid offset too. Use fdisk_partition_unset_start() to + * undefine the offset. * * Returns: 0 on success, <0 on error. */ @@ -93,26 +106,64 @@ int fdisk_partition_set_start(struct fdisk_partition *pa, uint64_t off) { if (!pa) return -EINVAL; + if (FDISK_IS_UNDEF(off)) + return -ERANGE; pa->start = off; return 0; } /** + * fdisk_partition_unset_start: + * @pa: partition + * + * Sets the size as undefined. See fdisk_partition_has_start(). + * + * Returns: 0 on success, <0 on error. + */ +int fdisk_partition_unset_start(struct fdisk_partition *pa) +{ + if (!pa) + return -EINVAL; + FDISK_INIT_UNDEF(pa->start); + return 0; +} + +/** * fdisk_partition_get_start: * @pa: partition * + * The zero is also valid offset. The function may return random undefined + * value when start offset is undefined (for example after + * fdisk_partition_unset_start()). Always use fdisk_partition_has_start() to be + * sure that you work with valid numbers. + * * Returns: start offset in sectors */ uint64_t fdisk_partition_get_start(struct fdisk_partition *pa) { - return pa ? pa->start : 0; + return pa->start; +} + +/** + * fdisk_partition_has_start: + * @pa: partition + * + * Returns: 1 or 0 + */ +int fdisk_partition_has_start(struct fdisk_partition *pa) +{ + return pa && !FDISK_IS_UNDEF(pa->start); } + /** * fdisk_partition_cmp_start: * @a: partition * @b: partition - * See fdisk_sort_table(). + * + * Compares partitons according to start offset, See fdisk_sort_table(). + * + * Return: 0 if the same, <0 if @b greater, >0 if @a greater. */ int fdisk_partition_cmp_start(struct fdisk_partition *a, struct fdisk_partition *b) @@ -121,69 +172,125 @@ int fdisk_partition_cmp_start(struct fdisk_partition *a, } /** - * fdisk_partition_set_end: + * fdisk_partition_start_follow_default * @pa: partition - * @off: offset in sectors - * - * Sets end offset, and zeroize size. + * @enable: 0|1 * - * The usual way is to address end of the partition by fdisk_partition_set_size(). + * When @pa used as a tempalate for fdisk_add_partition() when force label driver + * to use the first possible space for the new partition. * * Returns: 0 on success, <0 on error. */ -int fdisk_partition_set_end(struct fdisk_partition *pa, uint64_t off) +int fdisk_partition_start_follow_default(struct fdisk_partition *pa, int enable) { if (!pa) return -EINVAL; - pa->end = off; - pa->size = 0; + pa->start_follow_default = enable ? 1 : 0; return 0; } /** - * fdisk_partition_get_start: + * fdisk_partition_start_is_default: * @pa: partition * - * Returns: start offset in sectors + * See fdisk_partition_start_follow_default(). + * + * Returns: 1 if the partition follows default */ -uint64_t fdisk_partition_get_end(struct fdisk_partition *pa) +int fdisk_partition_start_is_default(struct fdisk_partition *pa) { - return pa ? pa->end : 0; + assert(pa); + return pa->start_follow_default; } + /** - * fdisk_partition_set_size + * fdisk_partition_set_size: * @pa: partition - * @size: in bytes + * @sz: size in sectors, maximal is UIN64_MAX-1 * - * Sets size, zeroize end offset. See also fdisk_partition_set_end(). + * Note that zero is valid size too. Use fdisk_partition_unset_size() to + * undefine the size. * * Returns: 0 on success, <0 on error. */ -int fdisk_partition_set_size(struct fdisk_partition *pa, uint64_t size) +int fdisk_partition_set_size(struct fdisk_partition *pa, uint64_t sz) { if (!pa) return -EINVAL; - pa->size = size; - pa->end = 0; + if (FDISK_IS_UNDEF(sz)) + return -ERANGE; + pa->size = sz; return 0; } /** - * fdisk_partition_get_start: + * fdisk_partition_unset_size: + * @pa: partition + * + * Sets the size as undefined. See fdisk_partition_has_size(). + * + * Returns: 0 on success, <0 on error. + */ +int fdisk_partition_unset_size(struct fdisk_partition *pa) +{ + if (!pa) + return -EINVAL; + FDISK_INIT_UNDEF(pa->size); + return 0; +} + +/** + * fdisk_partition_get_size: * @pa: partition * - * Returns: size in sectors + * The zero is also valid size. The function may return random undefined + * value when size is undefined (for example after fdisk_partition_unset_size()). + * Always use fdisk_partition_has_size() to be sure that you work with valid + * numbers. + * + * Returns: size offset in sectors */ uint64_t fdisk_partition_get_size(struct fdisk_partition *pa) { - return pa ? pa->size : 0; + return pa->size; } /** + * fdisk_partition_has_size: + * @pa: partition + * + * Returns: 1 or 0 + */ +int fdisk_partition_has_size(struct fdisk_partition *pa) +{ + return pa && !FDISK_IS_UNDEF(pa->size); +} + +/** + * fdisk_partition_size_explicit: + * @pa: partition + * @enable: 0|1 + * + * By default libfdisk aligns the size when add the new partition (by + * fdisk_add_partrition()). If you want to disable this functionality use + * @enable = 1. + * + * Returns: 0 on success, <0 on error. + */ +int fdisk_partition_size_explicit(struct fdisk_partition *pa, int enable) +{ + if (!pa) + return -EINVAL; + pa->size_explicit = enable ? 1 : 0; + return 0; +} + + +/** * fdisk_partition_set_partno * @pa: partition - * @n: partitiion number + * @n: partition number * * When @pa used as a tempalate for fdisk_add_partition() when infor label driver * about wanted partition position. @@ -279,35 +386,6 @@ int fdisk_partition_partno_follow_default(struct fdisk_partition *pa, int enable return 0; } -/** - * fdisk_partition_start_follow_default - * @pa: partition - * @enable: 0|1 - * - * When @pa used as a tempalate for fdisk_add_partition() when force label driver - * to use the first possible space for the new partition. - * - * Returns: 0 on success, <0 on error. - */ -int fdisk_partition_start_follow_default(struct fdisk_partition *pa, int enable) -{ - if (!pa) - return -EINVAL; - pa->start_follow_default = enable ? 1 : 0; - return 0; -} - -/** - * fdisk_partition_start_is_default: - * @pa: partition - * - * Returns: 1 if the partition follows default - */ -int fdisk_partition_start_is_default(struct fdisk_partition *pa) -{ - assert(pa); - return pa->start_follow_default; -} /** * fdisk_partition_start_follow_default @@ -339,25 +417,6 @@ int fdisk_partition_end_is_default(struct fdisk_partition *pa) return pa->end_follow_default; } -/** - * fdisk_partition_size_explicit: - * @pa: partition - * @enable: 0|1 - * - * By default libfdisk aligns the size when add the new partition (by - * fdisk_add_partrition()). If you want to disable this functionality use - * @enable = 1. - * - * Returns: 0 on success, <0 on error. - */ -int fdisk_partition_size_explicit(struct fdisk_partition *pa, int enable) -{ - if (!pa) - return -EINVAL; - pa->size_explicit = enable ? 1 : 0; - return 0; -} - const char *fdisk_partition_get_uuid(struct fdisk_partition *pa) { return pa ? pa->uuid : NULL; @@ -386,7 +445,7 @@ int fdisk_partition_set_attrs(struct fdisk_partition *pa, const char *attrs) int fdisk_partition_is_nested(struct fdisk_partition *pa) { - return pa && pa->parent_partno != FDISK_EMPTY_PARTNO; + return pa && !FDISK_IS_UNDEF(pa->parent_partno); } int fdisk_partition_is_container(struct fdisk_partition *pa) @@ -439,7 +498,7 @@ int fdisk_partition_next_partno( } return -ERANGE; - } else if (pa && pa->partno != FDISK_EMPTY_PARTNO) { + } else if (pa && !FDISK_IS_UNDEF(pa->partno)) { DBG(PART, ul_debugobj(pa, "next partno (specified=%zu)", pa->partno)); @@ -500,10 +559,12 @@ int fdisk_partition_to_string(struct fdisk_partition *pa, rc = asprintf(&p, "%c", pa->boot ? '*' : ' '); break; case FDISK_FIELD_START: - x = fdisk_cround(cxt, pa->start); - rc = pa->start_post ? + if (fdisk_partition_has_start(pa)) { + 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_FIELD_END: x = fdisk_cround(cxt, pa->end); @@ -512,26 +573,26 @@ int fdisk_partition_to_string(struct fdisk_partition *pa, asprintf(&p, "%ju", x); break; case FDISK_FIELD_SIZE: - { - uint64_t sz = pa->size * cxt->sector_size; - - if (fdisk_is_details(cxt)) { - rc = pa->size_post ? - asprintf(&p, "%ju%c", sz, pa->size_post) : - asprintf(&p, "%ju", sz); - } else { - p = size_to_human_string(SIZE_SUFFIX_1LETTER, sz); - if (!p) - rc = -ENOMEM; + if (fdisk_partition_has_size(pa)) { + uint64_t sz = pa->size * cxt->sector_size; + + if (fdisk_is_details(cxt)) { + rc = pa->size_post ? + asprintf(&p, "%ju%c", sz, pa->size_post) : + asprintf(&p, "%ju", sz); + } else { + p = size_to_human_string(SIZE_SUFFIX_1LETTER, sz); + if (!p) + rc = -ENOMEM; + } } break; - } case FDISK_FIELD_CYLINDERS: rc = asprintf(&p, "%ju", (uintmax_t) - fdisk_cround(cxt, pa->size)); + fdisk_cround(cxt, fdisk_partition_has_size(pa) ? pa->size : 0)); break; case FDISK_FIELD_SECTORS: - rc = asprintf(&p, "%ju", pa->size); + rc = asprintf(&p, "%ju", fdisk_partition_has_size(pa) ? pa->size : 0); break; case FDISK_FIELD_BSIZE: rc = asprintf(&p, "%ju", pa->bsize); @@ -561,10 +622,10 @@ int fdisk_partition_to_string(struct fdisk_partition *pa, p = pa->attrs ? strdup(pa->attrs) : NULL; break; case FDISK_FIELD_SADDR: - p = pa->start_addr ? strdup(pa->start_addr) : NULL; + p = pa->start_chs ? strdup(pa->start_chs) : NULL; break; case FDISK_FIELD_EADDR: - p = pa->end_addr ? strdup(pa->end_addr) : NULL; + p = pa->end_chs ? strdup(pa->end_chs) : NULL; break; default: return -EINVAL; diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c index d6b47a696..97b5e4d26 100644 --- a/libfdisk/src/script.c +++ b/libfdisk/src/script.c @@ -398,9 +398,9 @@ int fdisk_script_write_file(struct fdisk_script *dp, FILE *f) else fprintf(f, "%zu :", pa->partno + 1); - if (pa->start) + if (fdisk_partition_has_start(pa)) fprintf(f, " start=%12ju", pa->start); - if (pa->size) + if (fdisk_partition_has_size(pa)) fprintf(f, ", size=%12ju", pa->size); if (pa->type && fdisk_parttype_get_string(pa->type)) @@ -420,7 +420,7 @@ int fdisk_script_write_file(struct fdisk_script *dp, FILE *f) if (!lb || fdisk_label_get_type(lb) != FDISK_DISKLABEL_DOS) fprintf(f, ", attrs=\"%s\"", pa->attrs); } - if (pa->boot) + if (fdisk_partition_is_bootable(pa)) fprintf(f, ", bootable"); fputc('\n', f); } diff --git a/libfdisk/src/sgi.c b/libfdisk/src/sgi.c index 20ae59c03..e2eff9bb4 100644 --- a/libfdisk/src/sgi.c +++ b/libfdisk/src/sgi.c @@ -816,7 +816,7 @@ static int sgi_add_partition(struct fdisk_context *cxt, /* first sector */ if (pa && pa->start_follow_default) ; - else if (pa && pa->start) { + else if (pa && fdisk_partition_has_start(pa)) { first = pa->start; last = is_in_freelist(cxt, first); @@ -856,7 +856,7 @@ static int sgi_add_partition(struct fdisk_context *cxt, /* last sector */ if (pa && pa->end_follow_default) last -= 1ULL; - else if (pa && pa->size) { + else if (pa && fdisk_partition_has_size(pa)) { if (first + pa->size - 1ULL > last) return -ERANGE; last = first + pa->size - 1ULL; @@ -1050,9 +1050,9 @@ static int sgi_set_partition(struct fdisk_context *cxt, sgilabel->partitions[i].type = cpu_to_be32(t->code); } - if (pa->start) + if (fdisk_partition_has_start(pa)) sgilabel->partitions[i].first_block = cpu_to_be32(pa->start); - if (pa->size) + if (fdisk_partition_has_size(pa)) sgilabel->partitions[i].num_blocks = cpu_to_be32(pa->size); fdisk_label_set_changed(cxt->label, 1); diff --git a/libfdisk/src/sun.c b/libfdisk/src/sun.c index f9f1d472f..dcde5d7af 100644 --- a/libfdisk/src/sun.c +++ b/libfdisk/src/sun.c @@ -521,7 +521,7 @@ static int sun_add_partition( if (pa && pa->start_follow_default) first = start; - else if (pa && pa->start) { + else if (pa && fdisk_partition_has_start(pa)) { first = pa->start; if (!whole_disk && !is_free_sector(cxt, first, starts, lens)) @@ -612,7 +612,7 @@ static int sun_add_partition( /* last */ if (pa && pa->end_follow_default) last = whole_disk || (n == 2 && !first) ? stop2 : stop; - else if (pa && pa->size) { + else if (pa && fdisk_partition_has_size(pa)) { last = first + pa->size - 1ULL; if (!whole_disk && last > stop) @@ -983,10 +983,10 @@ static int sun_set_partition( info->id = cpu_to_be16(t->code); } - if (pa->start) + if (fdisk_partition_has_start(pa)) sunlabel->partitions[i].start_cylinder = cpu_to_be32(pa->start / (cxt->geom.heads * cxt->geom.sectors)); - if (pa->size) + if (fdisk_partition_has_size(pa)) sunlabel->partitions[i].num_sectors = cpu_to_be32(pa->size); fdisk_label_set_changed(cxt->label, 1); diff --git a/libfdisk/src/table.c b/libfdisk/src/table.c index fb8f52c7e..ea392d900 100644 --- a/libfdisk/src/table.c +++ b/libfdisk/src/table.c @@ -413,13 +413,15 @@ static int check_container_freespace(struct fdisk_context *cxt, assert(parts); assert(tb); assert(cont); + assert(fdisk_partition_has_start(cont)); last = fdisk_partition_get_start(cont); grain = cxt->grain > cxt->sector_size ? cxt->grain / cxt->sector_size : 1; fdisk_reset_iter(&itr, FDISK_ITER_FORWARD); while (fdisk_table_next_partition(parts, &itr, &pa) == 0) { - if (!pa->used || !fdisk_partition_is_nested(pa)) + if (!pa->used || !fdisk_partition_is_nested(pa) + || !fdisk_partition_has_start(pa)) continue; lastplusoff = last + cxt->first_lba; @@ -476,7 +478,8 @@ int fdisk_get_freespaces(struct fdisk_context *cxt, struct fdisk_table **tb) /* analyze gaps between partitions */ while (rc == 0 && fdisk_table_next_partition(parts, &itr, &pa) == 0) { - if (!pa->used || pa->wholedisk || fdisk_partition_is_nested(pa)) + if (!pa->used || pa->wholedisk || fdisk_partition_is_nested(pa) + || !fdisk_partition_has_start(pa)) continue; DBG(CXT, ul_debugobj(cxt, "freespace analyze: partno=%zu, start=%ju, end=%ju", pa->partno, pa->start, pa->end)); @@ -524,6 +527,8 @@ int fdisk_table_wrong_order(struct fdisk_table *tb) fdisk_reset_iter(&itr, FDISK_ITER_FORWARD); while (tb && fdisk_table_next_partition(tb, &itr, &pa) == 0) { + if (!fdisk_partition_has_start(pa)) + continue; if (pa->start < last) return 1; last = pa->start; @@ -556,7 +561,7 @@ int fdisk_apply_table(struct fdisk_context *cxt, struct fdisk_table *tb) fdisk_reset_iter(&itr, FDISK_ITER_FORWARD); while (tb && fdisk_table_next_partition(tb, &itr, &pa) == 0) { - if (!pa->start && !pa->start_follow_default) + if (!fdisk_partition_has_start(pa) && !pa->start_follow_default) continue; rc = fdisk_add_partition(cxt, pa, NULL); if (rc) |