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>
This commit is contained in:
parent
4739b6fd3e
commit
b28df75eec
|
@ -294,7 +294,8 @@ struct fdisk_gpt_label {
|
||||||
/* gpt specific part */
|
/* gpt specific part */
|
||||||
struct gpt_header *pheader; /* primary header */
|
struct gpt_header *pheader; /* primary header */
|
||||||
struct gpt_header *bheader; /* backup 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);
|
static void gpt_deinit(struct fdisk_label *lb);
|
||||||
|
@ -428,6 +429,22 @@ unknown:
|
||||||
return "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)
|
static inline int partition_unused(const struct gpt_entry *e)
|
||||||
{
|
{
|
||||||
return !memcmp(&e->type, &GPT_UNUSED_ENTRY_GUID,
|
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 */
|
/* 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)
|
struct gpt_header *header)
|
||||||
{
|
{
|
||||||
ssize_t sz;
|
ssize_t sz;
|
||||||
struct gpt_entry *ret = NULL;
|
unsigned char *ret = NULL;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
|
|
||||||
assert(cxt);
|
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 */
|
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;
|
size_t arysz = 0;
|
||||||
|
|
||||||
arysz = (size_t) le32_to_cpu(header->npartition_entries) *
|
arysz = (size_t) le32_to_cpu(header->npartition_entries) *
|
||||||
le32_to_cpu(header->sizeof_partition_entry);
|
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
|
* This function does not fail - if there's corruption, then it
|
||||||
* will be reported when checksumming it again (ie: probing or verify).
|
* 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)
|
if (!header)
|
||||||
return;
|
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.
|
* Compute the 32bit CRC checksum of the partition table header.
|
||||||
* Returns 1 if it is valid, otherwise 0.
|
* 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),
|
uint32_t orgcrc = le32_to_cpu(header->crc32),
|
||||||
crc = gpt_header_count_crc32(header);
|
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.
|
* It initializes the partition entry array.
|
||||||
* Returns 1 if the checksum is valid, otherwise 0.
|
* Returns 1 if the checksum is valid, otherwise 0.
|
||||||
*/
|
*/
|
||||||
static int gpt_check_entryarr_crc(struct gpt_header *header,
|
static int gpt_check_entryarr_crc(struct gpt_header *header, unsigned char *ents)
|
||||||
struct gpt_entry *ents)
|
|
||||||
{
|
{
|
||||||
if (!header || !ents)
|
if (!header || !ents)
|
||||||
return 0;
|
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,
|
static struct gpt_header *gpt_read_header(struct fdisk_context *cxt,
|
||||||
uint64_t lba,
|
uint64_t lba,
|
||||||
struct gpt_entry **_ents)
|
unsigned char **_ents)
|
||||||
{
|
{
|
||||||
struct gpt_header *header = NULL;
|
struct gpt_header *header = NULL;
|
||||||
struct gpt_entry *ents = NULL;
|
unsigned char *ents = NULL;
|
||||||
uint32_t hsz;
|
uint32_t hsz;
|
||||||
|
|
||||||
if (!cxt)
|
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)
|
if (le64_to_cpu(header->my_lba) != lba)
|
||||||
goto invalid;
|
goto invalid;
|
||||||
|
|
||||||
|
|
||||||
if (_ents)
|
if (_ents)
|
||||||
*_ents = ents;
|
*_ents = ents;
|
||||||
else
|
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.
|
* Returns the number of partitions that are in use.
|
||||||
*/
|
*/
|
||||||
static unsigned partitions_in_use(struct gpt_header *header,
|
static unsigned partitions_in_use(struct fdisk_gpt_label *gpt)
|
||||||
struct gpt_entry *ents)
|
|
||||||
{
|
{
|
||||||
uint32_t i, used = 0;
|
uint32_t i, used = 0;
|
||||||
|
|
||||||
if (!header || ! ents)
|
assert(gpt);
|
||||||
return 0;
|
assert(gpt->pheader);
|
||||||
|
assert(gpt->ents);
|
||||||
|
|
||||||
for (i = 0; i < le32_to_cpu(header->npartition_entries); i++)
|
for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
|
||||||
if (!partition_unused(&ents[i]))
|
struct gpt_entry *e = gpt_get_entry(gpt, i);
|
||||||
|
|
||||||
|
if (!partition_unused(e))
|
||||||
used++;
|
used++;
|
||||||
|
}
|
||||||
return 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).
|
* Check if a partition is too big for the disk (sectors).
|
||||||
* Returns the faulting partition number, otherwise 0.
|
* Returns the faulting partition number, otherwise 0.
|
||||||
*/
|
*/
|
||||||
static uint32_t check_too_big_partitions(struct gpt_header *header,
|
static uint32_t check_too_big_partitions(struct fdisk_gpt_label *gpt, uint64_t sectors)
|
||||||
struct gpt_entry *ents, uint64_t sectors)
|
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
|
assert(gpt);
|
||||||
if (partition_unused(&ents[i]))
|
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;
|
continue;
|
||||||
if (gpt_partition_end(&ents[i]) >= sectors)
|
if (gpt_partition_end(e) >= sectors)
|
||||||
return i + 1;
|
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
|
* Check if a partition ends before it begins
|
||||||
* Returns the faulting partition number, otherwise 0.
|
* Returns the faulting partition number, otherwise 0.
|
||||||
*/
|
*/
|
||||||
static uint32_t check_start_after_end_partitions(struct gpt_header *header,
|
static uint32_t check_start_after_end_partitions(struct fdisk_gpt_label *gpt)
|
||||||
struct gpt_entry *ents)
|
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
|
assert(gpt);
|
||||||
if (partition_unused(&ents[i]))
|
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;
|
continue;
|
||||||
if (gpt_partition_start(&ents[i]) > gpt_partition_end(&ents[i]))
|
if (gpt_partition_start(e) > gpt_partition_end(e))
|
||||||
return i + 1;
|
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.
|
* Find any partitions that overlap.
|
||||||
*/
|
*/
|
||||||
static uint32_t check_overlap_partitions(struct gpt_header *header,
|
static uint32_t check_overlap_partitions(struct fdisk_gpt_label *gpt)
|
||||||
struct gpt_entry *ents)
|
|
||||||
{
|
{
|
||||||
uint32_t i, j;
|
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++) {
|
for (j = 0; j < i; j++) {
|
||||||
if (partition_unused(&ents[i]) ||
|
struct gpt_entry *ei = gpt_get_entry(gpt, i);
|
||||||
partition_unused(&ents[j]))
|
struct gpt_entry *ej = gpt_get_entry(gpt, j);
|
||||||
|
|
||||||
|
if (partition_unused(ei) || partition_unused(ej))
|
||||||
continue;
|
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));
|
DBG(LABEL, ul_debug("GPT partitions overlap detected [%u vs. %u]", i, j));
|
||||||
return i + 1;
|
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
|
* Find the first available block after the starting point; returns 0 if
|
||||||
* there are no available blocks left, or error. From gdisk.
|
* there are no available blocks left, or error. From gdisk.
|
||||||
*/
|
*/
|
||||||
static uint64_t find_first_available(struct gpt_header *header,
|
static uint64_t find_first_available(struct fdisk_gpt_label *gpt, uint64_t start)
|
||||||
struct gpt_entry *ents, uint64_t start)
|
|
||||||
{
|
{
|
||||||
uint64_t first;
|
uint64_t first;
|
||||||
uint32_t i, first_moved = 0;
|
uint32_t i, first_moved = 0;
|
||||||
|
|
||||||
uint64_t fu, lu;
|
uint64_t fu, lu;
|
||||||
|
|
||||||
if (!header || !ents)
|
assert(gpt);
|
||||||
return 0;
|
assert(gpt->pheader);
|
||||||
|
assert(gpt->ents);
|
||||||
|
|
||||||
fu = le64_to_cpu(header->first_usable_lba);
|
fu = le64_to_cpu(gpt->pheader->first_usable_lba);
|
||||||
lu = le64_to_cpu(header->last_usable_lba);
|
lu = le64_to_cpu(gpt->pheader->last_usable_lba);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Begin from the specified starting point or from the first usable
|
* 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 {
|
do {
|
||||||
first_moved = 0;
|
first_moved = 0;
|
||||||
for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
|
for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
|
||||||
if (partition_unused(&ents[i]))
|
struct gpt_entry *e = gpt_get_entry(gpt, i);
|
||||||
|
|
||||||
|
if (partition_unused(e))
|
||||||
continue;
|
continue;
|
||||||
if (first < gpt_partition_start(&ents[i]))
|
if (first < gpt_partition_start(e))
|
||||||
continue;
|
continue;
|
||||||
if (first <= gpt_partition_end(&ents[i])) {
|
if (first <= gpt_partition_end(e)) {
|
||||||
first = gpt_partition_end(&ents[i]) + 1;
|
first = gpt_partition_end(e) + 1;
|
||||||
first_moved = 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. */
|
/* Returns last available sector in the free space pointed to by start. From gdisk. */
|
||||||
static uint64_t find_last_free(struct gpt_header *header,
|
static uint64_t find_last_free(struct fdisk_gpt_label *gpt, uint64_t start)
|
||||||
struct gpt_entry *ents, uint64_t start)
|
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint64_t nearest_start;
|
uint64_t nearest_start;
|
||||||
|
|
||||||
if (!header || !ents)
|
assert(gpt);
|
||||||
return 0;
|
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++) {
|
for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
|
||||||
uint64_t ps = gpt_partition_start(&ents[i]);
|
struct gpt_entry *e = gpt_get_entry(gpt, i);
|
||||||
|
uint64_t ps = gpt_partition_start(e);
|
||||||
|
|
||||||
if (nearest_start > ps && ps > start)
|
if (nearest_start > ps && ps > start)
|
||||||
nearest_start = ps - 1ULL;
|
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. */
|
/* Returns the last free sector on the disk. From gdisk. */
|
||||||
static uint64_t find_last_free_sector(struct gpt_header *header,
|
static uint64_t find_last_free_sector(struct fdisk_gpt_label *gpt)
|
||||||
struct gpt_entry *ents)
|
|
||||||
{
|
{
|
||||||
uint32_t i, last_moved;
|
uint32_t i, last_moved;
|
||||||
uint64_t last = 0;
|
uint64_t last = 0;
|
||||||
|
|
||||||
if (!header || !ents)
|
assert(gpt);
|
||||||
goto done;
|
assert(gpt->pheader);
|
||||||
|
assert(gpt->ents);
|
||||||
|
|
||||||
/* start by assuming the last usable LBA is available */
|
/* 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 {
|
do {
|
||||||
last_moved = 0;
|
last_moved = 0;
|
||||||
for (i = 0; i < le32_to_cpu(header->npartition_entries); i++) {
|
for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
|
||||||
if ((last >= gpt_partition_start(&ents[i])) &&
|
struct gpt_entry *e = gpt_get_entry(gpt, i);
|
||||||
(last <= gpt_partition_end(&ents[i]))) {
|
|
||||||
last = gpt_partition_start(&ents[i]) - 1ULL;
|
if (last >= gpt_partition_start(e) &&
|
||||||
|
last <= gpt_partition_end(e)) {
|
||||||
|
last = gpt_partition_start(e) - 1ULL;
|
||||||
last_moved = 1;
|
last_moved = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (last_moved == 1);
|
} while (last_moved == 1);
|
||||||
done:
|
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1333,19 +1370,19 @@ done:
|
||||||
* space on the disk. Returns 0 if there are no available blocks left.
|
* space on the disk. Returns 0 if there are no available blocks left.
|
||||||
* From gdisk.
|
* From gdisk.
|
||||||
*/
|
*/
|
||||||
static uint64_t find_first_in_largest(struct gpt_header *header,
|
static uint64_t find_first_in_largest(struct fdisk_gpt_label *gpt)
|
||||||
struct gpt_entry *ents)
|
|
||||||
{
|
{
|
||||||
uint64_t start = 0, first_sect, last_sect;
|
uint64_t start = 0, first_sect, last_sect;
|
||||||
uint64_t segment_size, selected_size = 0, selected_segment = 0;
|
uint64_t segment_size, selected_size = 0, selected_segment = 0;
|
||||||
|
|
||||||
if (!header || !ents)
|
assert(gpt);
|
||||||
goto done;
|
assert(gpt->pheader);
|
||||||
|
assert(gpt->ents);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
first_sect = find_first_available(header, ents, start);
|
first_sect = find_first_available(gpt, start);
|
||||||
if (first_sect != 0) {
|
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;
|
segment_size = last_sect - first_sect + 1ULL;
|
||||||
|
|
||||||
if (segment_size > selected_size) {
|
if (segment_size > selected_size) {
|
||||||
|
@ -1356,7 +1393,6 @@ static uint64_t find_first_in_largest(struct gpt_header *header,
|
||||||
}
|
}
|
||||||
} while (first_sect != 0);
|
} while (first_sect != 0);
|
||||||
|
|
||||||
done:
|
|
||||||
return selected_segment;
|
return selected_segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1364,8 +1400,9 @@ done:
|
||||||
* Find the total number of free sectors, the number of segments in which
|
* 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.
|
* 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,
|
static uint64_t get_free_sectors(struct fdisk_context *cxt,
|
||||||
struct gpt_entry *ents, uint32_t *nsegments,
|
struct fdisk_gpt_label *gpt,
|
||||||
|
uint32_t *nsegments,
|
||||||
uint64_t *largest_segment)
|
uint64_t *largest_segment)
|
||||||
{
|
{
|
||||||
uint32_t num = 0;
|
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)
|
if (!cxt->total_sectors)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
assert(gpt);
|
||||||
|
assert(gpt->pheader);
|
||||||
|
assert(gpt->ents);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
first_sect = find_first_available(header, ents, start);
|
first_sect = find_first_available(gpt, start);
|
||||||
if (first_sect) {
|
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;
|
segment_sz = last_sect - first_sect + 1;
|
||||||
|
|
||||||
if (segment_sz > largest_seg)
|
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_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;
|
return 1;
|
||||||
failed:
|
failed:
|
||||||
DBG(LABEL, ul_debug("GPT probe 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;
|
return -EINVAL;
|
||||||
|
|
||||||
gpt = self_label(cxt);
|
gpt = self_label(cxt);
|
||||||
e = &gpt->ents[n];
|
e = gpt_get_entry(gpt, n);
|
||||||
|
|
||||||
pa->used = !partition_unused(e) || gpt_partition_start(e);
|
pa->used = !partition_unused(e) || gpt_partition_start(e);
|
||||||
if (!pa->used)
|
if (!pa->used)
|
||||||
|
@ -1718,7 +1759,7 @@ static int gpt_set_partition(struct fdisk_context *cxt, size_t n,
|
||||||
FDISK_INIT_UNDEF(end);
|
FDISK_INIT_UNDEF(end);
|
||||||
|
|
||||||
gpt = self_label(cxt);
|
gpt = self_label(cxt);
|
||||||
e = &gpt->ents[n];
|
e = gpt_get_entry(gpt, n);
|
||||||
|
|
||||||
if (pa->uuid) {
|
if (pa->uuid) {
|
||||||
char new_u[37], old_u[37];
|
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.
|
* Returns 0 on success, or corresponding error otherwise.
|
||||||
*/
|
*/
|
||||||
static int gpt_write_partitions(struct fdisk_context *cxt,
|
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;
|
off_t offset = (off_t) le64_to_cpu(header->partition_entry_lba) * cxt->sector_size;
|
||||||
uint32_t nparts = le32_to_cpu(header->npartition_entries);
|
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 */
|
/* TODO: correct this (with user authorization) and write */
|
||||||
goto err0;
|
goto err0;
|
||||||
|
|
||||||
if (check_overlap_partitions(gpt->pheader, gpt->ents))
|
if (check_overlap_partitions(gpt))
|
||||||
goto err0;
|
goto err0;
|
||||||
|
|
||||||
/* recompute CRCs for both headers */
|
/* 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."));
|
fdisk_warnx(cxt, _("Primary and backup header mismatch."));
|
||||||
}
|
}
|
||||||
|
|
||||||
ptnum = check_overlap_partitions(gpt->pheader, gpt->ents);
|
ptnum = check_overlap_partitions(gpt);
|
||||||
if (ptnum) {
|
if (ptnum) {
|
||||||
nerror++;
|
nerror++;
|
||||||
fdisk_warnx(cxt, _("Partition %u overlaps with partition %u."),
|
fdisk_warnx(cxt, _("Partition %u overlaps with partition %u."),
|
||||||
ptnum, ptnum+1);
|
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) {
|
if (ptnum) {
|
||||||
nerror++;
|
nerror++;
|
||||||
fdisk_warnx(cxt, _("Partition %u is too big for the disk."),
|
fdisk_warnx(cxt, _("Partition %u is too big for the disk."),
|
||||||
ptnum);
|
ptnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptnum = check_start_after_end_partitions(gpt->pheader, gpt->ents);
|
ptnum = check_start_after_end_partitions(gpt);
|
||||||
if (ptnum) {
|
if (ptnum) {
|
||||||
nerror++;
|
nerror++;
|
||||||
fdisk_warnx(cxt, _("Partition %u ends before it starts."),
|
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, _("No errors detected."));
|
||||||
fdisk_info(cxt, _("Header version: %s"), gpt_get_header_revstr(gpt->pheader));
|
fdisk_info(cxt, _("Header version: %s"), gpt_get_header_revstr(gpt->pheader));
|
||||||
fdisk_info(cxt, _("Using %u out of %d partitions."),
|
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));
|
le32_to_cpu(gpt->pheader->npartition_entries));
|
||||||
|
|
||||||
free_sectors = get_free_sectors(cxt, gpt->pheader, gpt->ents,
|
free_sectors = get_free_sectors(cxt, gpt, &nsegments, &largest_segment);
|
||||||
&nsegments, &largest_segment);
|
|
||||||
if (largest_segment)
|
if (largest_segment)
|
||||||
strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER,
|
strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER,
|
||||||
largest_segment * cxt->sector_size);
|
largest_segment * cxt->sector_size);
|
||||||
|
@ -2083,20 +2123,19 @@ static int gpt_delete_partition(struct fdisk_context *cxt,
|
||||||
|
|
||||||
gpt = self_label(cxt);
|
gpt = self_label(cxt);
|
||||||
|
|
||||||
if (partnum >= cxt->label->nparts_max
|
if (partnum >= cxt->label->nparts_max)
|
||||||
|| partition_unused(&gpt->ents[partnum]))
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (partition_unused(gpt_get_entry(gpt, partnum)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* hasta la vista, baby! */
|
/* hasta la vista, baby! */
|
||||||
memset(&gpt->ents[partnum], 0, sizeof(struct gpt_entry));
|
gpt_zeroize_entry(gpt, partnum);
|
||||||
if (!partition_unused(&gpt->ents[partnum]))
|
|
||||||
return -EINVAL;
|
|
||||||
else {
|
|
||||||
gpt_recompute_crc(gpt->pheader, gpt->ents);
|
gpt_recompute_crc(gpt->pheader, gpt->ents);
|
||||||
gpt_recompute_crc(gpt->bheader, gpt->ents);
|
gpt_recompute_crc(gpt->bheader, gpt->ents);
|
||||||
cxt->label->nparts_cur--;
|
cxt->label->nparts_cur--;
|
||||||
fdisk_label_set_changed(cxt->label, 1);
|
fdisk_label_set_changed(cxt->label, 1);
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2114,7 +2153,7 @@ static int gpt_add_partition(
|
||||||
struct gpt_guid typeid;
|
struct gpt_guid typeid;
|
||||||
struct fdisk_gpt_label *gpt;
|
struct fdisk_gpt_label *gpt;
|
||||||
struct gpt_header *pheader;
|
struct gpt_header *pheader;
|
||||||
struct gpt_entry *e, *ents;
|
struct gpt_entry *e;
|
||||||
struct fdisk_ask *ask = NULL;
|
struct fdisk_ask *ask = NULL;
|
||||||
size_t partnum;
|
size_t partnum;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -2124,25 +2163,31 @@ static int gpt_add_partition(
|
||||||
assert(fdisk_is_label(cxt, GPT));
|
assert(fdisk_is_label(cxt, GPT));
|
||||||
|
|
||||||
gpt = self_label(cxt);
|
gpt = self_label(cxt);
|
||||||
|
|
||||||
|
assert(gpt);
|
||||||
|
assert(gpt->pheader);
|
||||||
|
assert(gpt->ents);
|
||||||
|
|
||||||
pheader = gpt->pheader;
|
pheader = gpt->pheader;
|
||||||
ents = gpt->ents;
|
|
||||||
|
|
||||||
rc = fdisk_partition_next_partno(pa, cxt, &partnum);
|
rc = fdisk_partition_next_partno(pa, cxt, &partnum);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DBG(LABEL, ul_debug("GPT failed to get next partno"));
|
DBG(LABEL, ul_debug("GPT failed to get next partno"));
|
||||||
return rc;
|
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. "
|
fdisk_warnx(cxt, _("Partition %zu is already defined. "
|
||||||
"Delete it before re-adding it."), partnum +1);
|
"Delete it before re-adding it."), partnum +1);
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
if (le32_to_cpu(pheader->npartition_entries) ==
|
if (le32_to_cpu(pheader->npartition_entries) == partitions_in_use(gpt)) {
|
||||||
partitions_in_use(pheader, ents)) {
|
|
||||||
fdisk_warnx(cxt, _("All partitions are already in use."));
|
fdisk_warnx(cxt, _("All partitions are already in use."));
|
||||||
return -ENOSPC;
|
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."));
|
fdisk_warnx(cxt, _("No free sectors available."));
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
|
@ -2153,21 +2198,22 @@ static int gpt_add_partition(
|
||||||
if (rc)
|
if (rc)
|
||||||
return 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
|
/* if first sector no explicitly defined then ignore small gaps before
|
||||||
* the first partition */
|
* the first partition */
|
||||||
if ((!pa || !fdisk_partition_has_start(pa))
|
if ((!pa || !fdisk_partition_has_start(pa))
|
||||||
&& !partition_unused(&ents[0])
|
&& !partition_unused(e)
|
||||||
&& disk_f < gpt_partition_start(&ents[0])) {
|
&& disk_f < gpt_partition_start(e)) {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
uint64_t x;
|
uint64_t x;
|
||||||
DBG(LABEL, ul_debug("testing first sector %"PRIu64"", disk_f));
|
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)
|
if (!disk_f)
|
||||||
break;
|
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)
|
if (x - disk_f >= cxt->grain / cxt->sector_size)
|
||||||
break;
|
break;
|
||||||
DBG(LABEL, ul_debug("first sector %"PRIu64" addresses to small space, continue...", disk_f));
|
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);
|
} while(1);
|
||||||
|
|
||||||
if (disk_f == 0)
|
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 */
|
/* the default is the largest free space */
|
||||||
dflt_f = find_first_in_largest(pheader, ents);
|
dflt_f = find_first_in_largest(gpt);
|
||||||
dflt_l = find_last_free(pheader, ents, dflt_f);
|
dflt_l = find_last_free(gpt, dflt_f);
|
||||||
|
|
||||||
/* align the default in range <dflt_f,dflt_l>*/
|
/* align the default in range <dflt_f,dflt_l>*/
|
||||||
dflt_f = fdisk_align_lba_in_range(cxt, dflt_f, 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)) {
|
} else if (pa && fdisk_partition_has_start(pa)) {
|
||||||
DBG(LABEL, ul_debug("first sector defined: %ju", (uintmax_t)pa->start));
|
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);
|
fdisk_warnx(cxt, _("Sector %ju already used."), (uintmax_t)pa->start);
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
|
@ -2218,7 +2265,7 @@ static int gpt_add_partition(
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
user_f = fdisk_ask_number_get_result(ask);
|
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);
|
fdisk_warnx(cxt, _("Sector %ju already used."), user_f);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2228,7 +2275,7 @@ static int gpt_add_partition(
|
||||||
|
|
||||||
|
|
||||||
/* Last sector */
|
/* 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) {
|
if (pa && pa->end_follow_default) {
|
||||||
user_l = dflt_l;
|
user_l = dflt_l;
|
||||||
|
@ -2302,8 +2349,9 @@ static int gpt_add_partition(
|
||||||
|
|
||||||
assert(!FDISK_IS_UNDEF(user_l));
|
assert(!FDISK_IS_UNDEF(user_l));
|
||||||
assert(!FDISK_IS_UNDEF(user_f));
|
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_end = cpu_to_le64(user_l);
|
||||||
e->lba_start = cpu_to_le64(user_f);
|
e->lba_start = cpu_to_le64(user_f);
|
||||||
|
|
||||||
|
@ -2336,8 +2384,8 @@ static int gpt_add_partition(
|
||||||
gpt_partition_end(e),
|
gpt_partition_end(e),
|
||||||
gpt_partition_size(e)));
|
gpt_partition_size(e)));
|
||||||
|
|
||||||
gpt_recompute_crc(gpt->pheader, ents);
|
gpt_recompute_crc(gpt->pheader, gpt->ents);
|
||||||
gpt_recompute_crc(gpt->bheader, ents);
|
gpt_recompute_crc(gpt->bheader, gpt->ents);
|
||||||
|
|
||||||
/* report result */
|
/* report result */
|
||||||
{
|
{
|
||||||
|
@ -2346,7 +2394,7 @@ static int gpt_add_partition(
|
||||||
cxt->label->nparts_cur++;
|
cxt->label->nparts_cur++;
|
||||||
fdisk_label_set_changed(cxt->label, 1);
|
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_info_new_partition(cxt, partnum + 1, user_f, user_l, t);
|
||||||
fdisk_unref_parttype(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 */
|
/* check that all partitions fit in the remaining space */
|
||||||
for (i = 0; i < le32_to_cpu(gpt->pheader->npartition_entries); i++) {
|
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;
|
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)"),
|
fdisk_warnx(cxt, _("Partition #%u out of range (minimal start is %"PRIu64" sectors)"),
|
||||||
i + 1, first_usable);
|
i + 1, first_usable);
|
||||||
rc = -EINVAL;
|
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)"),
|
fdisk_warnx(cxt, _("Partition #%u out of range (maximal end is %"PRIu64" sectors)"),
|
||||||
i + 1, last_usable - 1ULL);
|
i + 1, last_usable - 1ULL);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
|
@ -2524,7 +2574,6 @@ int fdisk_gpt_set_npartitions(struct fdisk_context *cxt, uint32_t entries)
|
||||||
struct fdisk_gpt_label *gpt;
|
struct fdisk_gpt_label *gpt;
|
||||||
size_t old_size, new_size;
|
size_t old_size, new_size;
|
||||||
uint32_t old;
|
uint32_t old;
|
||||||
struct gpt_entry *ents;
|
|
||||||
uint64_t first_usable, last_usable;
|
uint64_t first_usable, last_usable;
|
||||||
int rc;
|
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,
|
/* if expanding the table, first check that everything fits,
|
||||||
* then allocate more memory and zero. */
|
* then allocate more memory and zero. */
|
||||||
if (entries > old) {
|
if (entries > old) {
|
||||||
|
unsigned char *ents;
|
||||||
|
|
||||||
rc = gpt_check_table_overlap(cxt, first_usable, last_usable);
|
rc = gpt_check_table_overlap(cxt, first_usable, last_usable);
|
||||||
if (rc)
|
if (rc)
|
||||||
return 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))
|
if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
|
||||||
return 0;
|
return 0;
|
||||||
e = &gpt->ents[i];
|
|
||||||
|
e = gpt_get_entry(gpt, i);
|
||||||
|
|
||||||
return !partition_unused(e) || gpt_partition_start(e);
|
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))
|
if ((uint32_t) partnum >= le32_to_cpu(gpt->pheader->npartition_entries))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
*attrs = le64_to_cpu(gpt->ents[partnum].attrs);
|
*attrs = le64_to_cpu(gpt_get_entry(gpt, partnum)->attrs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2696,7 +2748,7 @@ int fdisk_gpt_set_partition_attrs(
|
||||||
if ((uint32_t) partnum >= le32_to_cpu(gpt->pheader->npartition_entries))
|
if ((uint32_t) partnum >= le32_to_cpu(gpt->pheader->npartition_entries))
|
||||||
return -EINVAL;
|
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 "."),
|
fdisk_info(cxt, _("The attributes on partition %zu changed to 0x%016" PRIx64 "."),
|
||||||
partnum + 1, attrs);
|
partnum + 1, attrs);
|
||||||
|
|
||||||
|
@ -2712,6 +2764,7 @@ static int gpt_toggle_partition_flag(
|
||||||
unsigned long flag)
|
unsigned long flag)
|
||||||
{
|
{
|
||||||
struct fdisk_gpt_label *gpt;
|
struct fdisk_gpt_label *gpt;
|
||||||
|
struct gpt_entry *e;
|
||||||
uint64_t attrs;
|
uint64_t attrs;
|
||||||
uintmax_t tmp;
|
uintmax_t tmp;
|
||||||
char *bits;
|
char *bits;
|
||||||
|
@ -2728,7 +2781,8 @@ static int gpt_toggle_partition_flag(
|
||||||
if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
|
if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
attrs = gpt->ents[i].attrs;
|
e = gpt_get_entry(gpt, i);
|
||||||
|
attrs = e->attrs;
|
||||||
bits = (char *) &attrs;
|
bits = (char *) &attrs;
|
||||||
|
|
||||||
switch (flag) {
|
switch (flag) {
|
||||||
|
@ -2769,7 +2823,7 @@ static int gpt_toggle_partition_flag(
|
||||||
else
|
else
|
||||||
clrbit(bits, bit);
|
clrbit(bits, bit);
|
||||||
|
|
||||||
gpt->ents[i].attrs = attrs;
|
e->attrs = attrs;
|
||||||
|
|
||||||
if (flag == GPT_FLAG_GUIDSPECIFIC)
|
if (flag == GPT_FLAG_GUIDSPECIFIC)
|
||||||
fdisk_info(cxt, isset(bits, bit) ?
|
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++)
|
for (i = 0, mess = 0; mess == 0 && i + 1 < nparts; i++)
|
||||||
mess = gpt_entry_cmp_start(
|
mess = gpt_entry_cmp_start(
|
||||||
(const void *) &gpt->ents[i],
|
(const void *) gpt_get_entry(gpt, i),
|
||||||
(const void *) &gpt->ents[i + 1]) > 0;
|
(const void *) gpt_get_entry(gpt, i + 1)) > 0;
|
||||||
|
|
||||||
if (!mess) {
|
if (!mess) {
|
||||||
fdisk_info(cxt, _("Nothing to do. Ordering is correct already."));
|
fdisk_info(cxt, _("Nothing to do. Ordering is correct already."));
|
||||||
|
|
Loading…
Reference in New Issue