diff options
Diffstat (limited to 'src/shared/fdisk-util.c')
-rw-r--r-- | src/shared/fdisk-util.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/shared/fdisk-util.c b/src/shared/fdisk-util.c new file mode 100644 index 0000000..20f32d1 --- /dev/null +++ b/src/shared/fdisk-util.c @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "dissect-image.h" +#include "extract-word.h" +#include "fd-util.h" +#include "fdisk-util.h" +#include "parse-util.h" + +#if HAVE_LIBFDISK + +int fdisk_new_context_at( + int dir_fd, + const char *path, + bool read_only, + uint32_t sector_size, + struct fdisk_context **ret) { + + _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL; + _cleanup_close_ int fd = -EBADF; + int r; + + assert(dir_fd >= 0 || dir_fd == AT_FDCWD); + assert(ret); + + if (!isempty(path)) { + fd = openat(dir_fd, path, (read_only ? O_RDONLY : O_RDWR)|O_CLOEXEC); + if (fd < 0) + return -errno; + + dir_fd = fd; + } + + c = fdisk_new_context(); + if (!c) + return -ENOMEM; + + if (sector_size == UINT32_MAX) { + r = probe_sector_size_prefer_ioctl(dir_fd, §or_size); + if (r < 0) + return r; + } + + if (sector_size != 0) { + r = fdisk_save_user_sector_size(c, /* phy= */ 0, sector_size); + if (r < 0) + return r; + } + + r = fdisk_assign_device(c, FORMAT_PROC_FD_PATH(dir_fd), read_only); + if (r < 0) + return r; + + *ret = TAKE_PTR(c); + return 0; +} + +int fdisk_partition_get_uuid_as_id128(struct fdisk_partition *p, sd_id128_t *ret) { + const char *ids; + + assert(p); + assert(ret); + + ids = fdisk_partition_get_uuid(p); + if (!ids) + return -ENXIO; + + return sd_id128_from_string(ids, ret); +} + +int fdisk_partition_get_type_as_id128(struct fdisk_partition *p, sd_id128_t *ret) { + struct fdisk_parttype *pt; + const char *pts; + + assert(p); + assert(ret); + + pt = fdisk_partition_get_type(p); + if (!pt) + return -ENXIO; + + pts = fdisk_parttype_get_string(pt); + if (!pts) + return -ENXIO; + + return sd_id128_from_string(pts, ret); +} + +int fdisk_partition_get_attrs_as_uint64(struct fdisk_partition *pa, uint64_t *ret) { + uint64_t flags = 0; + const char *a; + int r; + + assert(pa); + assert(ret); + + /* Retrieve current flags as uint64_t mask */ + + a = fdisk_partition_get_attrs(pa); + if (!a) { + *ret = 0; + return 0; + } + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&a, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + if (r == 0) + break; + + if (streq(word, "RequiredPartition")) + flags |= SD_GPT_FLAG_REQUIRED_PARTITION; + else if (streq(word, "NoBlockIOProtocol")) + flags |= SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL; + else if (streq(word, "LegacyBIOSBootable")) + flags |= SD_GPT_FLAG_LEGACY_BIOS_BOOTABLE; + else { + const char *e; + unsigned u; + + /* Drop "GUID" prefix if specified */ + e = startswith(word, "GUID:") ?: word; + + if (safe_atou(e, &u) < 0) { + log_debug("Unknown partition flag '%s', ignoring.", word); + continue; + } + + if (u >= sizeof(flags)*8) { /* partition flags on GPT are 64-bit. Let's ignore any further + bits should libfdisk report them */ + log_debug("Partition flag above bit 63 (%s), ignoring.", word); + continue; + } + + flags |= UINT64_C(1) << u; + } + } + + *ret = flags; + return 0; +} + +int fdisk_partition_set_attrs_as_uint64(struct fdisk_partition *pa, uint64_t flags) { + _cleanup_free_ char *attrs = NULL; + int r; + + assert(pa); + + for (unsigned i = 0; i < sizeof(flags) * 8; i++) { + if (!FLAGS_SET(flags, UINT64_C(1) << i)) + continue; + + r = strextendf_with_separator(&attrs, ",", "%u", i); + if (r < 0) + return r; + } + + return fdisk_partition_set_attrs(pa, strempty(attrs)); +} + +#endif |