summaryrefslogtreecommitdiffstats
path: root/libfdisk
diff options
context:
space:
mode:
authorKarel Zak2017-04-05 14:19:13 +0200
committerKarel Zak2017-04-05 14:19:13 +0200
commitb28df75eece3b65b79b2e56f1c197c2f128ac3d9 (patch)
tree24cb7247f30d3391792d2eebe86e19a7b8bce563 /libfdisk
parentagetty: fix login-options desc in man page (diff)
downloadkernel-qcow2-util-linux-b28df75eece3b65b79b2e56f1c197c2f128ac3d9.tar.gz
kernel-qcow2-util-linux-b28df75eece3b65b79b2e56f1c197c2f128ac3d9.tar.xz
kernel-qcow2-util-linux-b28df75eece3b65b79b2e56f1c197c2f128ac3d9.zip
libfdisk: (gpt) don't access entries array directly
We blindly assume that our sizeof(struct gpt_entry) is the same on-disk stored header->sizeof_partition_entry. It seems more correct would be to use sizeof specified by header to access the entries array items. This patch introduces gpt_get_entry() to avoid direct access to gpt->ents[]. Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk')
-rw-r--r--libfdisk/src/gpt.c312
1 files changed, 183 insertions, 129 deletions
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c
index c99b16f12..e15f8decd 100644
--- a/libfdisk/src/gpt.c
+++ b/libfdisk/src/gpt.c
@@ -294,7 +294,8 @@ struct fdisk_gpt_label {
/* gpt specific part */
struct gpt_header *pheader; /* primary header */
struct gpt_header *bheader; /* backup header */
- struct gpt_entry *ents; /* entries (partitions) */
+
+ unsigned char *ents; /* entries (partitions) */
};
static void gpt_deinit(struct fdisk_label *lb);
@@ -428,6 +429,22 @@ unknown:
return "unknown";
}
+static inline unsigned char *gpt_get_entry_ptr(struct fdisk_gpt_label *gpt, size_t i)
+{
+ return gpt->ents + le32_to_cpu(gpt->pheader->sizeof_partition_entry) * i;
+}
+
+static inline struct gpt_entry *gpt_get_entry(struct fdisk_gpt_label *gpt, size_t i)
+{
+ return (struct gpt_entry *) gpt_get_entry_ptr(gpt, i);
+}
+
+static inline struct gpt_entry *gpt_zeroize_entry(struct fdisk_gpt_label *gpt, size_t i)
+{
+ return (struct gpt_entry *) memset(gpt_get_entry_ptr(gpt, i),
+ 0, le32_to_cpu(gpt->pheader->sizeof_partition_entry));
+}
+
static inline int partition_unused(const struct gpt_entry *e)
{
return !memcmp(&e->type, &GPT_UNUSED_ENTRY_GUID,
@@ -817,11 +834,11 @@ static ssize_t read_lba(struct fdisk_context *cxt, uint64_t lba,
/* Returns the GPT entry array */
-static struct gpt_entry *gpt_read_entries(struct fdisk_context *cxt,
+static unsigned char *gpt_read_entries(struct fdisk_context *cxt,
struct gpt_header *header)
{
ssize_t sz;
- struct gpt_entry *ret = NULL;
+ unsigned char *ret = NULL;
off_t offset;
assert(cxt);
@@ -868,14 +885,14 @@ static inline uint32_t gpt_header_count_crc32(struct gpt_header *header)
sizeof(header->crc32)); /* size of excluded area */
}
-static inline uint32_t gpt_entryarr_count_crc32(struct gpt_header *header, struct gpt_entry *ents)
+static inline uint32_t gpt_entryarr_count_crc32(struct gpt_header *header, unsigned char *ents)
{
size_t arysz = 0;
arysz = (size_t) le32_to_cpu(header->npartition_entries) *
le32_to_cpu(header->sizeof_partition_entry);
- return count_crc32((unsigned char *) ents, arysz, 0, 0);
+ return count_crc32(ents, arysz, 0, 0);
}
@@ -884,7 +901,7 @@ static inline uint32_t gpt_entryarr_count_crc32(struct gpt_header *header, struc
* This function does not fail - if there's corruption, then it
* will be reported when checksumming it again (ie: probing or verify).
*/
-static void gpt_recompute_crc(struct gpt_header *header, struct gpt_entry *ents)
+static void gpt_recompute_crc(struct gpt_header *header, unsigned char *ents)
{
if (!header)
return;
@@ -899,7 +916,7 @@ static void gpt_recompute_crc(struct gpt_header *header, struct gpt_entry *ents)
* Compute the 32bit CRC checksum of the partition table header.
* Returns 1 if it is valid, otherwise 0.
*/
-static int gpt_check_header_crc(struct gpt_header *header, struct gpt_entry *ents)
+static int gpt_check_header_crc(struct gpt_header *header, unsigned char *ents)
{
uint32_t orgcrc = le32_to_cpu(header->crc32),
crc = gpt_header_count_crc32(header);
@@ -924,8 +941,7 @@ static int gpt_check_header_crc(struct gpt_header *header, struct gpt_entry *ent
* It initializes the partition entry array.
* Returns 1 if the checksum is valid, otherwise 0.
*/
-static int gpt_check_entryarr_crc(struct gpt_header *header,
- struct gpt_entry *ents)
+static int gpt_check_entryarr_crc(struct gpt_header *header, unsigned char *ents)
{
if (!header || !ents)
return 0;
@@ -979,10 +995,10 @@ static int gpt_check_signature(struct gpt_header *header)
*/
static struct gpt_header *gpt_read_header(struct fdisk_context *cxt,
uint64_t lba,
- struct gpt_entry **_ents)
+ unsigned char **_ents)
{
struct gpt_header *header = NULL;
- struct gpt_entry *ents = NULL;
+ unsigned char *ents = NULL;
uint32_t hsz;
if (!cxt)
@@ -1026,7 +1042,6 @@ static struct gpt_header *gpt_read_header(struct fdisk_context *cxt,
if (le64_to_cpu(header->my_lba) != lba)
goto invalid;
-
if (_ents)
*_ents = ents;
else
@@ -1140,17 +1155,20 @@ static int gpt_get_disklabel_item(struct fdisk_context *cxt, struct fdisk_labeli
/*
* Returns the number of partitions that are in use.
*/
-static unsigned partitions_in_use(struct gpt_header *header,
- struct gpt_entry *ents)
+static unsigned partitions_in_use(struct fdisk_gpt_label *gpt)
{
uint32_t i, used = 0;
- if (!header || ! ents)
- return 0;
+ assert(gpt);
+ assert(gpt->pheader);
+ assert(gpt->ents);
+
+ for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
+ struct gpt_entry *e = gpt_get_entry(gpt, i);
- for (i = 0; i < le32_to_cpu(header->npartition_entries); i++)
- if (!partition_unused(&ents[i]))
+ if (!partition_unused(e))
used++;
+ }
return used;
}
@@ -1159,15 +1177,20 @@ static unsigned partitions_in_use(struct gpt_header *header,
* Check if a partition is too big for the disk (sectors).
* Returns the faulting partition number, otherwise 0.
*/
-static uint32_t check_too_big_partitions(struct gpt_header *header,
- struct gpt_entry *ents, uint64_t sectors)
+static uint32_t check_too_big_partitions(struct fdisk_gpt_label *gpt, uint64_t sectors)
{
uint32_t i;
- for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
- if (partition_unused(&ents[i]))
+ assert(gpt);
+ assert(gpt->pheader);
+ assert(gpt->ents);
+
+ for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
+ struct gpt_entry *e = gpt_get_entry(gpt, i);
+
+ if (partition_unused(e))
continue;
- if (gpt_partition_end(&ents[i]) >= sectors)
+ if (gpt_partition_end(e) >= sectors)
return i + 1;
}
@@ -1178,15 +1201,20 @@ static uint32_t check_too_big_partitions(struct gpt_header *header,
* Check if a partition ends before it begins
* Returns the faulting partition number, otherwise 0.
*/
-static uint32_t check_start_after_end_partitions(struct gpt_header *header,
- struct gpt_entry *ents)
+static uint32_t check_start_after_end_partitions(struct fdisk_gpt_label *gpt)
{
uint32_t i;
- for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
- if (partition_unused(&ents[i]))
+ assert(gpt);
+ assert(gpt->pheader);
+ assert(gpt->ents);
+
+ for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
+ struct gpt_entry *e = gpt_get_entry(gpt, i);
+
+ if (partition_unused(e))
continue;
- if (gpt_partition_start(&ents[i]) > gpt_partition_end(&ents[i]))
+ if (gpt_partition_start(e) > gpt_partition_end(e))
return i + 1;
}
@@ -1209,17 +1237,22 @@ static inline int partition_overlap(struct gpt_entry *e1, struct gpt_entry *e2)
/*
* Find any partitions that overlap.
*/
-static uint32_t check_overlap_partitions(struct gpt_header *header,
- struct gpt_entry *ents)
+static uint32_t check_overlap_partitions(struct fdisk_gpt_label *gpt)
{
uint32_t i, j;
- for (i = 0; i < le32_to_cpu(header->npartition_entries); i++)
+ assert(gpt);
+ assert(gpt->pheader);
+ assert(gpt->ents);
+
+ for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++)
for (j = 0; j < i; j++) {
- if (partition_unused(&ents[i]) ||
- partition_unused(&ents[j]))
+ struct gpt_entry *ei = gpt_get_entry(gpt, i);
+ struct gpt_entry *ej = gpt_get_entry(gpt, j);
+
+ if (partition_unused(ei) || partition_unused(ej))
continue;
- if (partition_overlap(&ents[i], &ents[j])) {
+ if (partition_overlap(ei, ej)) {
DBG(LABEL, ul_debug("GPT partitions overlap detected [%u vs. %u]", i, j));
return i + 1;
}
@@ -1232,19 +1265,18 @@ static uint32_t check_overlap_partitions(struct gpt_header *header,
* Find the first available block after the starting point; returns 0 if
* there are no available blocks left, or error. From gdisk.
*/
-static uint64_t find_first_available(struct gpt_header *header,
- struct gpt_entry *ents, uint64_t start)
+static uint64_t find_first_available(struct fdisk_gpt_label *gpt, uint64_t start)
{
uint64_t first;
uint32_t i, first_moved = 0;
-
uint64_t fu, lu;
- if (!header || !ents)
- return 0;
+ assert(gpt);
+ assert(gpt->pheader);
+ assert(gpt->ents);
- fu = le64_to_cpu(header->first_usable_lba);
- lu = le64_to_cpu(header->last_usable_lba);
+ fu = le64_to_cpu(gpt->pheader->first_usable_lba);
+ lu = le64_to_cpu(gpt->pheader->last_usable_lba);
/*
* Begin from the specified starting point or from the first usable
@@ -1261,13 +1293,15 @@ static uint64_t find_first_available(struct gpt_header *header,
*/
do {
first_moved = 0;
- for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
- if (partition_unused(&ents[i]))
+ for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
+ struct gpt_entry *e = gpt_get_entry(gpt, i);
+
+ if (partition_unused(e))
continue;
- if (first < gpt_partition_start(&ents[i]))
+ if (first < gpt_partition_start(e))
continue;
- if (first <= gpt_partition_end(&ents[i])) {
- first = gpt_partition_end(&ents[i]) + 1;
+ if (first <= gpt_partition_end(e)) {
+ first = gpt_partition_end(e) + 1;
first_moved = 1;
}
}
@@ -1281,19 +1315,20 @@ static uint64_t find_first_available(struct gpt_header *header,
/* Returns last available sector in the free space pointed to by start. From gdisk. */
-static uint64_t find_last_free(struct gpt_header *header,
- struct gpt_entry *ents, uint64_t start)
+static uint64_t find_last_free(struct fdisk_gpt_label *gpt, uint64_t start)
{
uint32_t i;
uint64_t nearest_start;
- if (!header || !ents)
- return 0;
+ assert(gpt);
+ assert(gpt->pheader);
+ assert(gpt->ents);
- nearest_start = le64_to_cpu(header->last_usable_lba);
+ nearest_start = le64_to_cpu(gpt->pheader->last_usable_lba);
- for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
- uint64_t ps = gpt_partition_start(&ents[i]);
+ for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
+ struct gpt_entry *e = gpt_get_entry(gpt, i);
+ uint64_t ps = gpt_partition_start(e);
if (nearest_start > ps && ps > start)
nearest_start = ps - 1ULL;
@@ -1303,28 +1338,30 @@ static uint64_t find_last_free(struct gpt_header *header,
}
/* Returns the last free sector on the disk. From gdisk. */
-static uint64_t find_last_free_sector(struct gpt_header *header,
- struct gpt_entry *ents)
+static uint64_t find_last_free_sector(struct fdisk_gpt_label *gpt)
{
uint32_t i, last_moved;
uint64_t last = 0;
- if (!header || !ents)
- goto done;
+ assert(gpt);
+ assert(gpt->pheader);
+ assert(gpt->ents);
/* start by assuming the last usable LBA is available */
- last = le64_to_cpu(header->last_usable_lba);
+ last = le64_to_cpu(gpt->pheader->last_usable_lba);
do {
last_moved = 0;
- for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
- if ((last >= gpt_partition_start(&ents[i])) &&
- (last <= gpt_partition_end(&ents[i]))) {
- last = gpt_partition_start(&ents[i]) - 1ULL;
+ for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
+ struct gpt_entry *e = gpt_get_entry(gpt, i);
+
+ if (last >= gpt_partition_start(e) &&
+ last <= gpt_partition_end(e)) {
+ last = gpt_partition_start(e) - 1ULL;
last_moved = 1;
}
}
} while (last_moved == 1);
-done:
+
return last;
}
@@ -1333,19 +1370,19 @@ done:
* space on the disk. Returns 0 if there are no available blocks left.
* From gdisk.
*/
-static uint64_t find_first_in_largest(struct gpt_header *header,
- struct gpt_entry *ents)
+static uint64_t find_first_in_largest(struct fdisk_gpt_label *gpt)
{
uint64_t start = 0, first_sect, last_sect;
uint64_t segment_size, selected_size = 0, selected_segment = 0;
- if (!header || !ents)
- goto done;
+ assert(gpt);
+ assert(gpt->pheader);
+ assert(gpt->ents);
do {
- first_sect = find_first_available(header, ents, start);
+ first_sect = find_first_available(gpt, start);
if (first_sect != 0) {
- last_sect = find_last_free(header, ents, first_sect);
+ last_sect = find_last_free(gpt, first_sect);
segment_size = last_sect - first_sect + 1ULL;
if (segment_size > selected_size) {
@@ -1356,7 +1393,6 @@ static uint64_t find_first_in_largest(struct gpt_header *header,
}
} while (first_sect != 0);
-done:
return selected_segment;
}
@@ -1364,8 +1400,9 @@ done:
* Find the total number of free sectors, the number of segments in which
* they reside, and the size of the largest of those segments. From gdisk.
*/
-static uint64_t get_free_sectors(struct fdisk_context *cxt, struct gpt_header *header,
- struct gpt_entry *ents, uint32_t *nsegments,
+static uint64_t get_free_sectors(struct fdisk_context *cxt,
+ struct fdisk_gpt_label *gpt,
+ uint32_t *nsegments,
uint64_t *largest_segment)
{
uint32_t num = 0;
@@ -1376,10 +1413,14 @@ static uint64_t get_free_sectors(struct fdisk_context *cxt, struct gpt_header *h
if (!cxt->total_sectors)
goto done;
+ assert(gpt);
+ assert(gpt->pheader);
+ assert(gpt->ents);
+
do {
- first_sect = find_first_available(header, ents, start);
+ first_sect = find_first_available(gpt, start);
if (first_sect) {
- last_sect = find_last_free(header, ents, first_sect);
+ last_sect = find_last_free(gpt, first_sect);
segment_sz = last_sect - first_sect + 1;
if (segment_sz > largest_seg)
@@ -1455,7 +1496,7 @@ static int gpt_probe_label(struct fdisk_context *cxt)
}
cxt->label->nparts_max = le32_to_cpu(gpt->pheader->npartition_entries);
- cxt->label->nparts_cur = partitions_in_use(gpt->pheader, gpt->ents);
+ cxt->label->nparts_cur = partitions_in_use(gpt);
return 1;
failed:
DBG(LABEL, ul_debug("GPT probe failed"));
@@ -1666,7 +1707,7 @@ static int gpt_get_partition(struct fdisk_context *cxt, size_t n,
return -EINVAL;
gpt = self_label(cxt);
- e = &gpt->ents[n];
+ e = gpt_get_entry(gpt, n);
pa->used = !partition_unused(e) || gpt_partition_start(e);
if (!pa->used)
@@ -1718,7 +1759,7 @@ static int gpt_set_partition(struct fdisk_context *cxt, size_t n,
FDISK_INIT_UNDEF(end);
gpt = self_label(cxt);
- e = &gpt->ents[n];
+ e = gpt_get_entry(gpt, n);
if (pa->uuid) {
char new_u[37], old_u[37];
@@ -1791,7 +1832,7 @@ static int gpt_set_partition(struct fdisk_context *cxt, size_t n,
* Returns 0 on success, or corresponding error otherwise.
*/
static int gpt_write_partitions(struct fdisk_context *cxt,
- struct gpt_header *header, struct gpt_entry *ents)
+ struct gpt_header *header, unsigned char *ents)
{
off_t offset = (off_t) le64_to_cpu(header->partition_entry_lba) * cxt->sector_size;
uint32_t nparts = le32_to_cpu(header->npartition_entries);
@@ -1903,7 +1944,7 @@ static int gpt_write_disklabel(struct fdisk_context *cxt)
/* TODO: correct this (with user authorization) and write */
goto err0;
- if (check_overlap_partitions(gpt->pheader, gpt->ents))
+ if (check_overlap_partitions(gpt))
goto err0;
/* recompute CRCs for both headers */
@@ -2018,21 +2059,21 @@ static int gpt_verify_disklabel(struct fdisk_context *cxt)
fdisk_warnx(cxt, _("Primary and backup header mismatch."));
}
- ptnum = check_overlap_partitions(gpt->pheader, gpt->ents);
+ ptnum = check_overlap_partitions(gpt);
if (ptnum) {
nerror++;
fdisk_warnx(cxt, _("Partition %u overlaps with partition %u."),
ptnum, ptnum+1);
}
- ptnum = check_too_big_partitions(gpt->pheader, gpt->ents, cxt->total_sectors);
+ ptnum = check_too_big_partitions(gpt, cxt->total_sectors);
if (ptnum) {
nerror++;
fdisk_warnx(cxt, _("Partition %u is too big for the disk."),
ptnum);
}
- ptnum = check_start_after_end_partitions(gpt->pheader, gpt->ents);
+ ptnum = check_start_after_end_partitions(gpt);
if (ptnum) {
nerror++;
fdisk_warnx(cxt, _("Partition %u ends before it starts."),
@@ -2047,11 +2088,10 @@ static int gpt_verify_disklabel(struct fdisk_context *cxt)
fdisk_info(cxt, _("No errors detected."));
fdisk_info(cxt, _("Header version: %s"), gpt_get_header_revstr(gpt->pheader));
fdisk_info(cxt, _("Using %u out of %d partitions."),
- partitions_in_use(gpt->pheader, gpt->ents),
+ partitions_in_use(gpt),
le32_to_cpu(gpt->pheader->npartition_entries));
- free_sectors = get_free_sectors(cxt, gpt->pheader, gpt->ents,
- &nsegments, &largest_segment);
+ free_sectors = get_free_sectors(cxt, gpt, &nsegments, &largest_segment);
if (largest_segment)
strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER,
largest_segment * cxt->sector_size);
@@ -2083,20 +2123,19 @@ static int gpt_delete_partition(struct fdisk_context *cxt,
gpt = self_label(cxt);
- if (partnum >= cxt->label->nparts_max
- || partition_unused(&gpt->ents[partnum]))
+ if (partnum >= cxt->label->nparts_max)
return -EINVAL;
- /* hasta la vista, baby! */
- memset(&gpt->ents[partnum], 0, sizeof(struct gpt_entry));
- if (!partition_unused(&gpt->ents[partnum]))
+ if (partition_unused(gpt_get_entry(gpt, partnum)))
return -EINVAL;
- else {
- gpt_recompute_crc(gpt->pheader, gpt->ents);
- gpt_recompute_crc(gpt->bheader, gpt->ents);
- cxt->label->nparts_cur--;
- fdisk_label_set_changed(cxt->label, 1);
- }
+
+ /* hasta la vista, baby! */
+ gpt_zeroize_entry(gpt, partnum);
+
+ gpt_recompute_crc(gpt->pheader, gpt->ents);
+ gpt_recompute_crc(gpt->bheader, gpt->ents);
+ cxt->label->nparts_cur--;
+ fdisk_label_set_changed(cxt->label, 1);
return 0;
}
@@ -2114,7 +2153,7 @@ static int gpt_add_partition(
struct gpt_guid typeid;
struct fdisk_gpt_label *gpt;
struct gpt_header *pheader;
- struct gpt_entry *e, *ents;
+ struct gpt_entry *e;
struct fdisk_ask *ask = NULL;
size_t partnum;
int rc;
@@ -2124,25 +2163,31 @@ static int gpt_add_partition(
assert(fdisk_is_label(cxt, GPT));
gpt = self_label(cxt);
+
+ assert(gpt);
+ assert(gpt->pheader);
+ assert(gpt->ents);
+
pheader = gpt->pheader;
- ents = gpt->ents;
rc = fdisk_partition_next_partno(pa, cxt, &partnum);
if (rc) {
DBG(LABEL, ul_debug("GPT failed to get next partno"));
return rc;
}
- if (!partition_unused(&ents[partnum])) {
+
+ assert(partnum < le32_to_cpu(pheader->npartition_entries));
+
+ if (!partition_unused(gpt_get_entry(gpt, partnum))) {
fdisk_warnx(cxt, _("Partition %zu is already defined. "
"Delete it before re-adding it."), partnum +1);
return -ERANGE;
}
- if (le32_to_cpu(pheader->npartition_entries) ==
- partitions_in_use(pheader, ents)) {
+ if (le32_to_cpu(pheader->npartition_entries) == partitions_in_use(gpt)) {
fdisk_warnx(cxt, _("All partitions are already in use."));
return -ENOSPC;
}
- if (!get_free_sectors(cxt, pheader, ents, NULL, NULL)) {
+ if (!get_free_sectors(cxt, gpt, NULL, NULL)) {
fdisk_warnx(cxt, _("No free sectors available."));
return -ENOSPC;
}
@@ -2153,21 +2198,22 @@ static int gpt_add_partition(
if (rc)
return rc;
- disk_f = find_first_available(pheader, ents, le64_to_cpu(pheader->first_usable_lba));
+ disk_f = find_first_available(gpt, le64_to_cpu(pheader->first_usable_lba));
+ e = gpt_get_entry(gpt, 0);
/* if first sector no explicitly defined then ignore small gaps before
* the first partition */
if ((!pa || !fdisk_partition_has_start(pa))
- && !partition_unused(&ents[0])
- && disk_f < gpt_partition_start(&ents[0])) {
+ && !partition_unused(e)
+ && disk_f < gpt_partition_start(e)) {
do {
uint64_t x;
DBG(LABEL, ul_debug("testing first sector %"PRIu64"", disk_f));
- disk_f = find_first_available(pheader, ents, disk_f);
+ disk_f = find_first_available(gpt, disk_f);
if (!disk_f)
break;
- x = find_last_free(pheader, ents, disk_f);
+ x = find_last_free(gpt, disk_f);
if (x - disk_f >= cxt->grain / cxt->sector_size)
break;
DBG(LABEL, ul_debug("first sector %"PRIu64" addresses to small space, continue...", disk_f));
@@ -2175,14 +2221,15 @@ static int gpt_add_partition(
} while(1);
if (disk_f == 0)
- disk_f = find_first_available(pheader, ents, le64_to_cpu(pheader->first_usable_lba));
+ disk_f = find_first_available(gpt, le64_to_cpu(pheader->first_usable_lba));
}
- disk_l = find_last_free_sector(pheader, ents);
+ e = NULL;
+ disk_l = find_last_free_sector(gpt);
/* the default is the largest free space */
- dflt_f = find_first_in_largest(pheader, ents);
- dflt_l = find_last_free(pheader, ents, dflt_f);
+ dflt_f = find_first_in_largest(gpt);
+ dflt_l = find_last_free(gpt, dflt_f);
/* align the default in range <dflt_f,dflt_l>*/
dflt_f = fdisk_align_lba_in_range(cxt, dflt_f, dflt_f, dflt_l);
@@ -2193,7 +2240,7 @@ static int gpt_add_partition(
} else if (pa && fdisk_partition_has_start(pa)) {
DBG(LABEL, ul_debug("first sector defined: %ju", (uintmax_t)pa->start));
- if (pa->start != find_first_available(pheader, ents, pa->start)) {
+ if (pa->start != find_first_available(gpt, pa->start)) {
fdisk_warnx(cxt, _("Sector %ju already used."), (uintmax_t)pa->start);
return -ERANGE;
}
@@ -2218,7 +2265,7 @@ static int gpt_add_partition(
goto done;
user_f = fdisk_ask_number_get_result(ask);
- if (user_f != find_first_available(pheader, ents, user_f)) {
+ if (user_f != find_first_available(gpt, user_f)) {
fdisk_warnx(cxt, _("Sector %ju already used."), user_f);
continue;
}
@@ -2228,7 +2275,7 @@ static int gpt_add_partition(
/* Last sector */
- dflt_l = find_last_free(pheader, ents, user_f);
+ dflt_l = find_last_free(gpt, user_f);
if (pa && pa->end_follow_default) {
user_l = dflt_l;
@@ -2302,8 +2349,9 @@ static int gpt_add_partition(
assert(!FDISK_IS_UNDEF(user_l));
assert(!FDISK_IS_UNDEF(user_f));
+ assert(partnum < le32_to_cpu(pheader->npartition_entries));
- e = &ents[partnum];
+ e = gpt_get_entry(gpt, partnum);
e->lba_end = cpu_to_le64(user_l);
e->lba_start = cpu_to_le64(user_f);
@@ -2336,8 +2384,8 @@ static int gpt_add_partition(
gpt_partition_end(e),
gpt_partition_size(e)));
- gpt_recompute_crc(gpt->pheader, ents);
- gpt_recompute_crc(gpt->bheader, ents);
+ gpt_recompute_crc(gpt->pheader, gpt->ents);
+ gpt_recompute_crc(gpt->bheader, gpt->ents);
/* report result */
{
@@ -2346,7 +2394,7 @@ static int gpt_add_partition(
cxt->label->nparts_cur++;
fdisk_label_set_changed(cxt->label, 1);
- t = gpt_partition_parttype(cxt, &ents[partnum]);
+ t = gpt_partition_parttype(cxt, e);
fdisk_info_new_partition(cxt, partnum + 1, user_f, user_l, t);
fdisk_unref_parttype(t);
}
@@ -2491,14 +2539,16 @@ static int gpt_check_table_overlap(struct fdisk_context *cxt,
/* check that all partitions fit in the remaining space */
for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
- if (partition_unused(&gpt->ents[i]))
+ struct gpt_entry *e = gpt_get_entry(gpt, i);
+
+ if (partition_unused(e))
continue;
- if (gpt_partition_start(&gpt->ents[i]) < first_usable) {
+ if (gpt_partition_start(e) < first_usable) {
fdisk_warnx(cxt, _("Partition #%u out of range (minimal start is %"PRIu64" sectors)"),
i + 1, first_usable);
rc = -EINVAL;
}
- if (gpt_partition_end(&gpt->ents[i]) > last_usable) {
+ if (gpt_partition_end(e) > last_usable) {
fdisk_warnx(cxt, _("Partition #%u out of range (maximal end is %"PRIu64" sectors)"),
i + 1, last_usable - 1ULL);
rc = -EINVAL;
@@ -2524,7 +2574,6 @@ int fdisk_gpt_set_npartitions(struct fdisk_context *cxt, uint32_t entries)
struct fdisk_gpt_label *gpt;
size_t old_size, new_size;
uint32_t old;
- struct gpt_entry *ents;
uint64_t first_usable, last_usable;
int rc;
@@ -2557,6 +2606,8 @@ int fdisk_gpt_set_npartitions(struct fdisk_context *cxt, uint32_t entries)
/* if expanding the table, first check that everything fits,
* then allocate more memory and zero. */
if (entries > old) {
+ unsigned char *ents;
+
rc = gpt_check_table_overlap(cxt, first_usable, last_usable);
if (rc)
return rc;
@@ -2608,7 +2659,8 @@ static int gpt_part_is_used(struct fdisk_context *cxt, size_t i)
if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
return 0;
- e = &gpt->ents[i];
+
+ e = gpt_get_entry(gpt, i);
return !partition_unused(e) || gpt_partition_start(e);
}
@@ -2663,7 +2715,7 @@ int fdisk_gpt_get_partition_attrs(
if ((uint32_t) partnum >= le32_to_cpu(gpt->pheader->npartition_entries))
return -EINVAL;
- *attrs = le64_to_cpu(gpt->ents[partnum].attrs);
+ *attrs = le64_to_cpu(gpt_get_entry(gpt, partnum)->attrs);
return 0;
}
@@ -2696,7 +2748,7 @@ int fdisk_gpt_set_partition_attrs(
if ((uint32_t) partnum >= le32_to_cpu(gpt->pheader->npartition_entries))
return -EINVAL;
- gpt->ents[partnum].attrs = cpu_to_le64(attrs);
+ gpt_get_entry(gpt, partnum)->attrs = cpu_to_le64(attrs);
fdisk_info(cxt, _("The attributes on partition %zu changed to 0x%016" PRIx64 "."),
partnum + 1, attrs);
@@ -2712,6 +2764,7 @@ static int gpt_toggle_partition_flag(
unsigned long flag)
{
struct fdisk_gpt_label *gpt;
+ struct gpt_entry *e;
uint64_t attrs;
uintmax_t tmp;
char *bits;
@@ -2728,7 +2781,8 @@ static int gpt_toggle_partition_flag(
if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
return -EINVAL;
- attrs = gpt->ents[i].attrs;
+ e = gpt_get_entry(gpt, i);
+ attrs = e->attrs;
bits = (char *) &attrs;
switch (flag) {
@@ -2769,7 +2823,7 @@ static int gpt_toggle_partition_flag(
else
clrbit(bits, bit);
- gpt->ents[i].attrs = attrs;
+ e->attrs = attrs;
if (flag == GPT_FLAG_GUIDSPECIFIC)
fdisk_info(cxt, isset(bits, bit) ?
@@ -2820,8 +2874,8 @@ static int gpt_reorder(struct fdisk_context *cxt)
for (i = 0, mess = 0; mess == 0 && i + 1 < nparts; i++)
mess = gpt_entry_cmp_start(
- (const void *) &gpt->ents[i],
- (const void *) &gpt->ents[i + 1]) > 0;
+ (const void *) gpt_get_entry(gpt, i),
+ (const void *) gpt_get_entry(gpt, i + 1)) > 0;
if (!mess) {
fdisk_info(cxt, _("Nothing to do. Ordering is correct already."));