uint32_t size; /* in bytes */
uint32_t crc32; /* header CRC checksum */
uint32_t reserved1; /* must be 0 */
- uint64_t my_lba; /* LBA that contains this struct (LBA 1) */
+ uint64_t my_lba; /* LBA of block that contains this struct (LBA 1) */
uint64_t alternative_lba; /* backup GPT header */
uint64_t first_usable_lba; /* first usable logical block for partitions */
uint64_t last_usable_lba; /* last usable logical block for partitions */
struct gpt_guid disk_guid; /* unique disk identifier */
- uint64_t partition_entry_lba; /* stat LBA of the partition entry array */
+ uint64_t partition_entry_lba; /* LBA of start of partition entries array */
uint32_t npartition_entries; /* total partition entries - normally 128 */
uint32_t sizeof_partition_entry; /* bytes for each GUID pt */
uint32_t partition_entry_array_crc32; /* partition CRC checksum */
- uint8_t reserved2[512 - 92]; /* must be 0 */
+ uint8_t reserved2[512 - 92]; /* must all be 0 */
} __attribute__ ((packed));
struct gpt_record {
return 0;
}
+static int gpt_entry_attrs_from_string(
+ struct fdisk_context *cxt,
+ struct gpt_entry *e,
+ const char *str)
+{
+ const char *p = str;
+ uint64_t attrs = 0;
+ char *bits;
+
+ assert(e);
+ assert(p);
+
+ DBG(LABEL, ul_debug("GPT: parsing string attributes '%s'", p));
+
+ bits = (char *) &attrs;
+
+ while (p && *p) {
+ int bit = -1;
+
+ while (isblank(*p)) p++;
+ if (!*p)
+ break;
+
+ DBG(LABEL, ul_debug(" parsing item '%s'", p));
+
+ if (strncmp(p, "GUID:", 5) == 0) {
+ p += 5;
+ continue;
+ } else if (strncmp(p, GPT_ATTRSTR_REQ,
+ sizeof(GPT_ATTRSTR_REQ) - 1) == 0) {
+ bit = GPT_ATTRBIT_REQ;
+ p += sizeof(GPT_ATTRSTR_REQ) - 1;
+ } else if (strncmp(p, GPT_ATTRSTR_LEGACY,
+ sizeof(GPT_ATTRSTR_LEGACY) - 1) == 0) {
+ bit = GPT_ATTRBIT_LEGACY;
+ p += sizeof(GPT_ATTRSTR_LEGACY) - 1;
+ } else if (strncmp(p, GPT_ATTRSTR_NOBLOCK,
+ sizeof(GPT_ATTRSTR_NOBLOCK) - 1) == 0) {
+ bit = GPT_ATTRBIT_NOBLOCK;
+ p += sizeof(GPT_ATTRSTR_NOBLOCK) - 1;
+ } else if (isdigit((unsigned int) *p)) {
+ char *end = NULL;
+
+ errno = 0;
+ bit = strtol(p, &end, 0);
+ if (errno || !end || end == str
+ || bit < GPT_ATTRBIT_GUID_FIRST
+ || bit >= GPT_ATTRBIT_GUID_FIRST + GPT_ATTRBIT_GUID_COUNT)
+ bit = -1;
+ else
+ p = end;
+ }
+
+ if (bit < 0) {
+ fdisk_warnx(cxt, _("unssuported GPT attribute bit '%s'"), p);
+ return -EINVAL;
+ }
+
+ setbit(bits, bit);
+
+ while (isblank(*p)) p++;
+ if (*p == ',')
+ p++;
+ }
+
+ e->attrs = cpu_to_le64(attrs);
+ return 0;
+}
+
static int gpt_get_partition(struct fdisk_context *cxt, size_t n,
struct fdisk_partition *pa)
{
return rc;
gpt_entry_set_type(e, &typeid);
}
+ if (pa->attrs) {
+ rc = gpt_entry_attrs_from_string(cxt, e, pa->attrs);
+ if (rc)
+ 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);
fdisk_info(cxt, _("First LBA: %ju"), h->first_usable_lba);
fdisk_info(cxt, _("Last LBA: %ju"), h->last_usable_lba);
+ /* TRANSLATORS: The LBA (Logical Block Address) of the backup GPT header. */
fdisk_info(cxt, _("Alternative LBA: %ju"), h->alternative_lba);
- fdisk_info(cxt, _("Partitions entries LBA: %ju"), h->partition_entry_lba);
+ /* TRANSLATORS: The start of the array of partition entries. */
+ fdisk_info(cxt, _("Partition entries LBA: %ju"), h->partition_entry_lba);
fdisk_info(cxt, _("Allocated partition entries: %u"), h->npartition_entries);
}
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 (;;) {
/* 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)
+ 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)
if (user_l + (cxt->grain / cxt->sector_size) > dflt_l)
user_l = dflt_l;
*/
- } if (user_l > user_f && user_l <= disk_l)
+ }
+
+ if (user_l > user_f && user_l <= disk_l)
break;
}
}
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);
if (pa && pa->name && *pa->name)
gpt_entry_set_name(e, pa->name);
+ if (pa && pa->attrs)
+ gpt_entry_attrs_from_string(cxt, e, pa->attrs);
DBG(LABEL, ul_debug("GPT new partition: partno=%zu, start=%ju, end=%ju, size=%ju",
partnum,
return 0;
}
-static int gpt_set_partition_type(
- struct fdisk_context *cxt,
- size_t i,
- struct fdisk_parttype *t)
-{
- struct gpt_guid uuid;
- struct fdisk_gpt_label *gpt;
-
- assert(cxt);
- assert(cxt->label);
- assert(fdisk_is_label(cxt, GPT));
-
- gpt = self_label(cxt);
- if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries)
- || !t || !t->typestr || string_to_guid(t->typestr, &uuid) != 0)
- return -EINVAL;
-
- gpt_entry_set_type(&gpt->ents[i], &uuid);
- gpt_recompute_crc(gpt->pheader, gpt->ents);
- gpt_recompute_crc(gpt->bheader, gpt->ents);
-
- fdisk_label_set_changed(cxt->label, 1);
- return 0;
-}
-
static int gpt_part_is_used(struct fdisk_context *cxt, size_t i)
{
struct fdisk_gpt_label *gpt;
.del_part = gpt_delete_partition,
.part_is_used = gpt_part_is_used,
- .part_set_type = gpt_set_partition_type,
.part_toggle_flag = gpt_toggle_partition_flag,
.deinit = gpt_deinit,
{ FDISK_FIELD_START, N_("Start"), 5, FDISK_FIELDFL_NUMBER },
{ FDISK_FIELD_END, N_("End"), 5, FDISK_FIELDFL_NUMBER },
{ FDISK_FIELD_SECTORS, N_("Sectors"), 5, FDISK_FIELDFL_NUMBER },
- { FDISK_FIELD_CYLINDERS,N_("Cylinders"), 5, FDISK_FIELDFL_NUMBER },
{ FDISK_FIELD_SIZE, N_("Size"), 5, FDISK_FIELDFL_NUMBER | FDISK_FIELDFL_EYECANDY },
{ FDISK_FIELD_TYPE, N_("Type"), 0.1, FDISK_FIELDFL_EYECANDY },
/* expert */