mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 00:47:10 +09:00
168 lines
4.6 KiB
C
168 lines
4.6 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
|
#include "alloc-util.h"
|
|
#include "bitfield.h"
|
|
#include "dissect-image.h"
|
|
#include "extract-word.h"
|
|
#include "fd-util.h"
|
|
#include "fdisk-util.h"
|
|
#include "log.h"
|
|
#include "parse-util.h"
|
|
#include "string-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 (!BIT_SET(flags, i))
|
|
continue;
|
|
|
|
r = strextendf_with_separator(&attrs, ",", "%u", i);
|
|
if (r < 0)
|
|
return r;
|
|
}
|
|
|
|
return fdisk_partition_set_attrs(pa, strempty(attrs));
|
|
}
|
|
|
|
#endif
|