fdisk-util: load libfdisk via dlopen

Convert fdisk-util to the dlopen pattern used by other optional shared
libraries in libshared. Declare the libfdisk API entry points with
DLSYM_PROTOTYPE, resolve them in a dlopen_fdisk() helper, and call the
sym_* wrappers from the homework, sysupdate and repart binaries that
use them.

With this in place fdisk-util can live in libshared itself, linked only
against libfdisk's headers (via libfdisk_cflags). The libshared_fdisk
convenience library and the libfdisk link dependency on systemd-homework,
systemd-sysupdate, systemd-repart and systemd-repart.standalone go away.

Also add a dlopen_fdisk() check to test-dlopen-so.
This commit is contained in:
Daan De Meyer
2026-04-21 07:53:53 +02:00
committed by Daan De Meyer
parent db3bfa0c4c
commit a066396fbc
13 changed files with 441 additions and 217 deletions
+1 -5
View File
@@ -27,12 +27,8 @@ executables += [
'conditions' : ['ENABLE_SYSUPDATE'],
'sources' : systemd_sysupdate_sources,
'extract' : systemd_sysupdate_extract_sources,
'link_with' : [
libshared,
libshared_fdisk,
],
'dependencies' : [
libfdisk,
libfdisk_cflags,
libopenssl,
threads,
],
+32 -24
View File
@@ -77,32 +77,32 @@ int read_partition_info(
assert(t);
assert(ret);
p = fdisk_table_get_partition(t, i);
p = sym_fdisk_table_get_partition(t, i);
if (!p)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata.");
if (fdisk_partition_is_used(p) <= 0) {
if (sym_fdisk_partition_is_used(p) <= 0) {
*ret = (PartitionInfo) PARTITION_INFO_NULL;
return 0; /* not found! */
}
if (fdisk_partition_has_partno(p) <= 0 ||
fdisk_partition_has_start(p) <= 0 ||
fdisk_partition_has_size(p) <= 0)
if (sym_fdisk_partition_has_partno(p) <= 0 ||
sym_fdisk_partition_has_start(p) <= 0 ||
sym_fdisk_partition_has_size(p) <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a number, position or size.");
partno = fdisk_partition_get_partno(p);
partno = sym_fdisk_partition_get_partno(p);
start = fdisk_partition_get_start(p);
ssz = fdisk_get_sector_size(c);
start = sym_fdisk_partition_get_start(p);
ssz = sym_fdisk_get_sector_size(c);
assert(start <= UINT64_MAX / ssz);
start *= ssz;
size = fdisk_partition_get_size(p);
size = sym_fdisk_partition_get_size(p);
assert(size <= UINT64_MAX / ssz);
size *= ssz;
label = fdisk_partition_get_name(p);
label = sym_fdisk_partition_get_name(p);
if (!label)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a label.");
@@ -118,7 +118,7 @@ int read_partition_info(
if (r < 0)
return log_error_errno(r, "Failed to get partition flags: %m");
r = fdisk_partition_to_string(p, c, FDISK_FIELD_DEVICE, &device);
r = sym_fdisk_partition_to_string(p, c, FDISK_FIELD_DEVICE, &device);
if (r != 0)
return log_error_errno(r, "Failed to get partition device name: %m");
@@ -161,18 +161,22 @@ int find_suitable_partition(
POINTER_MAY_BE_NULL(partition_type);
assert(ret);
r = dlopen_fdisk();
if (r < 0)
return r;
r = fdisk_new_context_at(AT_FDCWD, device, /* read_only= */ true, /* sector_size= */ UINT32_MAX, &c);
if (r < 0)
return log_error_errno(r, "Failed to create fdisk context from '%s': %m", device);
if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
if (!sym_fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not suitable.", device);
r = fdisk_get_partitions(c, &t);
r = sym_fdisk_get_partitions(c, &t);
if (r < 0)
return log_error_errno(r, "Failed to acquire partition table: %m");
n_partitions = fdisk_table_get_nents(t);
n_partitions = sym_fdisk_table_get_nents(t);
for (size_t i = 0; i < n_partitions; i++) {
_cleanup_(partition_info_destroy) PartitionInfo pinfo = PARTITION_INFO_NULL;
@@ -226,11 +230,15 @@ int patch_partition(
if (change == 0) /* Nothing to do */
return 0;
r = dlopen_fdisk();
if (r < 0)
return r;
r = fdisk_new_context_at(AT_FDCWD, device, /* read_only= */ false, /* sector_size= */ UINT32_MAX, &c);
if (r < 0)
return log_error_errno(r, "Failed to create fdisk context from '%s': %m", device);
assert_se((fd = fdisk_get_devfd(c)) >= 0);
assert_se((fd = sym_fdisk_get_devfd(c)) >= 0);
/* Make sure udev doesn't read the device while we make changes (this lock is released automatically
* by the kernel when the fd is closed, i.e. when the fdisk context is freed, hence no explicit
@@ -238,21 +246,21 @@ int patch_partition(
if (flock(fd, LOCK_EX) < 0)
return log_error_errno(errno, "Failed to lock block device '%s': %m", device);
if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
if (!sym_fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not suitable.", device);
r = fdisk_get_partition(c, info->partno, &pa);
r = sym_fdisk_get_partition(c, info->partno, &pa);
if (r < 0)
return log_error_errno(r, "Failed to read partition %zu of GPT label of '%s': %m", info->partno, device);
if (change & PARTITION_LABEL) {
r = fdisk_partition_set_name(pa, info->label);
r = sym_fdisk_partition_set_name(pa, info->label);
if (r < 0)
return log_error_errno(r, "Failed to update partition label: %m");
}
if (change & PARTITION_UUID) {
r = fdisk_partition_set_uuid(pa, SD_ID128_TO_UUID_STRING(info->uuid));
r = sym_fdisk_partition_set_uuid(pa, SD_ID128_TO_UUID_STRING(info->uuid));
if (r < 0)
return log_error_errno(r, "Failed to update partition UUID: %m");
}
@@ -260,15 +268,15 @@ int patch_partition(
if (change & PARTITION_TYPE) {
_cleanup_(fdisk_unref_parttypep) struct fdisk_parttype *pt = NULL;
pt = fdisk_new_parttype();
pt = sym_fdisk_new_parttype();
if (!pt)
return log_oom();
r = fdisk_parttype_set_typestr(pt, SD_ID128_TO_UUID_STRING(info->type));
r = sym_fdisk_parttype_set_typestr(pt, SD_ID128_TO_UUID_STRING(info->type));
if (r < 0)
return log_error_errno(r, "Failed to initialize partition type: %m");
r = fdisk_partition_set_type(pa, pt);
r = sym_fdisk_partition_set_type(pa, pt);
if (r < 0)
return log_error_errno(r, "Failed to update partition type: %m");
}
@@ -328,11 +336,11 @@ int patch_partition(
}
}
r = fdisk_set_partition(c, info->partno, pa);
r = sym_fdisk_set_partition(c, info->partno, pa);
if (r < 0)
return log_error_errno(r, "Failed to update partition: %m");
r = fdisk_write_disklabel(c);
r = sym_fdisk_write_disklabel(c);
if (r < 0)
return log_error_errno(r, "Failed to write updated partition table: %m");
+7 -3
View File
@@ -229,18 +229,22 @@ static int resource_load_from_blockdev(Resource *rr) {
assert(rr);
r = dlopen_fdisk();
if (r < 0)
return r;
r = fdisk_new_context_at(AT_FDCWD, rr->path, /* read_only= */ true, /* sector_size= */ UINT32_MAX, &c);
if (r < 0)
return log_error_errno(r, "Failed to create fdisk context from '%s': %m", rr->path);
if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
if (!sym_fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not suitable.", rr->path);
r = fdisk_get_partitions(c, &t);
r = sym_fdisk_get_partitions(c, &t);
if (r < 0)
return log_error_errno(r, "Failed to acquire partition table: %m");
n_partitions = fdisk_table_get_nents(t);
n_partitions = sym_fdisk_table_get_nents(t);
for (size_t i = 0; i < n_partitions; i++) {
_cleanup_(instance_metadata_destroy) InstanceMetadata extracted_fields = INSTANCE_METADATA_NULL;
_cleanup_(partition_info_destroy) PartitionInfo pinfo = PARTITION_INFO_NULL;