diff options
-rw-r--r-- | libfdisk/src/gpt.c | 81 | ||||
-rw-r--r-- | libfdisk/src/script.c | 23 |
2 files changed, 94 insertions, 10 deletions
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c index 7a2997ccc..61b0a32e1 100644 --- a/libfdisk/src/gpt.c +++ b/libfdisk/src/gpt.c @@ -520,20 +520,82 @@ static struct gpt_header *gpt_copy_header(struct fdisk_context *cxt, return res; } -static void count_first_last_lba(struct fdisk_context *cxt, +static int get_script_u64(struct fdisk_context *cxt, uint64_t *num, const char *name) +{ + const char *str; + int pwr = 0, rc = 0; + + assert(cxt); + + *num = 0; + + if (!cxt->script) + return 1; + + str = fdisk_script_get_header(cxt->script, name); + if (!str) + return 1; + + rc = parse_size(str, (uintmax_t *) num, &pwr); + if (rc < 0) + return rc; + if (pwr) + *num /= cxt->sector_size; + return 0; +} + +static int count_first_last_lba(struct fdisk_context *cxt, uint64_t *first, uint64_t *last) { + int rc = 0; + uint64_t flba, llba; + uint64_t esz = 0; assert(cxt); + assert(first); + assert(last); + *first = *last = 0; + + /* UEFI default */ esz = sizeof(struct gpt_entry) * GPT_NPARTITIONS / cxt->sector_size; - *last = cxt->total_sectors - 2 - esz; - *first = esz + 2; + llba = cxt->total_sectors - 2 - esz; + flba = esz + 2; + + /* script default */ + if (cxt->script) { + rc = get_script_u64(cxt, first, "first-lba"); + if (rc < 0) + return rc; + + DBG(LABEL, ul_debug("FirstLBA: script=%ju, uefi=%ju, topology=%ju.", *first, flba, cxt->first_lba)); + + if (rc == 0 && (*first < flba || *first > llba)) { + fdisk_warnx(cxt, _("First LBA specified by script is out of range.")); + return -ERANGE; + } + + rc = get_script_u64(cxt, last, "last-lba"); + if (rc < 0) + return rc; + + DBG(LABEL, ul_debug("LastLBA: script=%ju, uefi=%ju, topology=%ju.", *last, llba, cxt->last_lba)); - if (*first < cxt->first_lba && cxt->first_lba < *last) - /* Align according to topology */ - *first = cxt->first_lba; + if (rc == 0 && (*last > llba || *last < flba)) { + fdisk_warnx(cxt, _("Last LBA specified by script is out of range.")); + return -ERANGE; + } + } + + if (!*last) + *last = llba; + + /* default by topology */ + if (!*first) + *first = flba < cxt->first_lba && + cxt->first_lba < *last ? cxt->first_lba : flba; + return 0; } /* @@ -548,7 +610,7 @@ static int gpt_mknew_header(struct fdisk_context *cxt, struct gpt_header *header, uint64_t lba) { uint64_t first, last; - int has_id = 0; + int has_id = 0, rc; if (!cxt || !header) return -ENOSYS; @@ -571,7 +633,10 @@ static int gpt_mknew_header(struct fdisk_context *cxt, header->npartition_entries = cpu_to_le32(GPT_NPARTITIONS); header->sizeof_partition_entry = cpu_to_le32(sizeof(struct gpt_entry)); - count_first_last_lba(cxt, &first, &last); + rc = count_first_last_lba(cxt, &first, &last); + if (rc) + return rc; + header->first_usable_lba = cpu_to_le64(first); header->last_usable_lba = cpu_to_le64(last); diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c index 5a89790d7..eb4e31d20 100644 --- a/libfdisk/src/script.c +++ b/libfdisk/src/script.c @@ -238,17 +238,22 @@ int fdisk_script_set_header(struct fdisk_script *dp, if (!dp || !name) return -EINVAL; + fi = script_get_header(dp, name); if (!fi && !data) return 0; /* want to remove header that does not exist, success */ if (!data) { + DBG(SCRIPT, ul_debugobj(dp, "freeing header %s", name)); + /* no data, remove the header */ fdisk_script_free_header(dp, fi); return 0; } if (!fi) { + DBG(SCRIPT, ul_debugobj(dp, "setting new header %s='%s'", name, data)); + /* new header */ fi = calloc(1, sizeof(*fi)); if (!fi) @@ -265,6 +270,8 @@ int fdisk_script_set_header(struct fdisk_script *dp, /* update existing */ char *x = strdup(data); + DBG(SCRIPT, ul_debugobj(dp, "update '%s' header '%s' -> '%s'", name, fi->data, data)); + if (!x) return -ENOMEM; free(fi->data); @@ -366,7 +373,17 @@ int fdisk_script_read_context(struct fdisk_script *dp, struct fdisk_context *cxt if (!rc) rc = fdisk_script_set_header(dp, "unit", "sectors"); - /* TODO: label specific headers (e.g. uuid for GPT) */ + if (!rc && fdisk_is_label(cxt, GPT)) { + char buf[64]; + + snprintf(buf, sizeof(buf), "%ju", cxt->first_lba); + rc = fdisk_script_set_header(dp, "first-lba", buf); + + if (!rc) { + snprintf(buf, sizeof(buf), "%ju", cxt->last_lba); + rc = fdisk_script_set_header(dp, "last-lba", buf); + } + } DBG(SCRIPT, ul_debugobj(dp, "read context done [rc=%d]", rc)); return rc; @@ -493,7 +510,9 @@ static int parse_header_line(struct fdisk_script *dp, char *s) if (strcmp(value, "sectors") != 0) goto done; /* only "sectors" supported */ } else if (strcmp(name, "label-id") == 0 - || strcmp(name, "device") == 0) { + || strcmp(name, "device") == 0 + || strcmp(name, "first-lba") == 0 + || strcmp(name, "last-lba") == 0) { ; /* whatever is posssible */ } else goto done; /* unknown header */ |