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>
This commit is contained in:
parent
6311e17845
commit
ecf40cda76
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
* @enable: 0|1
|
||||
*
|
||||
* Sets end offset, and zeroize size.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Returns: size in sectors
|
||||
* 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
|
||||
*
|
||||
* 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_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;
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue