diff options
author | Karel Zak | 2017-04-05 14:19:13 +0200 |
---|---|---|
committer | Karel Zak | 2017-04-05 14:19:13 +0200 |
commit | b28df75eece3b65b79b2e56f1c197c2f128ac3d9 (patch) | |
tree | 24cb7247f30d3391792d2eebe86e19a7b8bce563 /libfdisk | |
parent | agetty: fix login-options desc in man page (diff) | |
download | kernel-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.c | 312 |
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.")); |