diff --git a/meson.build b/meson.build index aedde9b94e9..841dd97003c 100644 --- a/meson.build +++ b/meson.build @@ -1003,6 +1003,9 @@ want_blkid = get_option('blkid') if want_blkid != 'false' and not skip_deps libblkid = dependency('blkid', required : want_blkid == 'true') have = libblkid.found() + + conf.set10('HAVE_BLKID_PROBE_SET_HINT', + have and cc.has_function('blkid_probe_set_hint', dependencies : libblkid)) else have = false libblkid = [] diff --git a/rules.d/60-persistent-storage.rules b/rules.d/60-persistent-storage.rules index fc7f733e200..35b4f2c6dc5 100644 --- a/rules.d/60-persistent-storage.rules +++ b/rules.d/60-persistent-storage.rules @@ -104,7 +104,7 @@ KERNEL=="vd*[0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID # probe filesystem metadata of optical drives which have a media inserted KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="?*", \ - IMPORT{builtin}="blkid --offset=$env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}" + IMPORT{builtin}="blkid --hint=session_offset=$env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}" # single-session CDs do not have ID_CDROM_MEDIA_SESSION_LAST_OFFSET KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="", \ IMPORT{builtin}="blkid --noraid" diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c index 8333eb4fc40..6a3b7cf18fd 100644 --- a/src/udev/udev-builtin-blkid.c +++ b/src/udev/udev-builtin-blkid.c @@ -238,10 +238,16 @@ static int builtin_blkid(sd_device *dev, int argc, char *argv[], bool test) { static const struct option options[] = { { "offset", required_argument, NULL, 'o' }, + { "hint", required_argument, NULL, 'H' }, { "noraid", no_argument, NULL, 'R' }, {} }; + errno = 0; + pr = blkid_new_probe(); + if (!pr) + return log_device_debug_errno(dev, errno_or_else(ENOMEM), "Failed to create blkid prober: %m"); + for (;;) { int option; @@ -250,12 +256,28 @@ static int builtin_blkid(sd_device *dev, int argc, char *argv[], bool test) { break; switch (option) { + case 'H': +#if HAVE_BLKID_PROBE_SET_HINT + errno = 0; + r = blkid_probe_set_hint(pr, optarg, 0); + if (r < 0) + return log_device_error_errno(dev, errno_or_else(ENOMEM), "Failed to use '%s' probing hint: %m", optarg); + break; +#else + /* Use the hint = as probing offset for old versions */ + optarg = strchr(optarg, '='); + if (!optarg) + /* no value means 0, do nothing for old versions */ + break; + ++optarg; + _fallthrough_; +#endif case 'o': r = safe_atoi64(optarg, &offset); if (r < 0) return log_device_error_errno(dev, r, "Failed to parse '%s' as an integer: %m", optarg); if (offset < 0) - return log_device_error_errno(dev, SYNTHETIC_ERRNO(ERANGE), "Invalid offset %"PRIi64": %m", offset); + return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid offset %"PRIi64": %m", offset); break; case 'R': noraid = true; @@ -263,11 +285,6 @@ static int builtin_blkid(sd_device *dev, int argc, char *argv[], bool test) { } } - errno = 0; - pr = blkid_new_probe(); - if (!pr) - return log_device_debug_errno(dev, errno > 0 ? errno : ENOMEM, "Failed to create blkid prober: %m"); - blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | @@ -287,7 +304,7 @@ static int builtin_blkid(sd_device *dev, int argc, char *argv[], bool test) { errno = 0; r = blkid_probe_set_device(pr, fd, offset, 0); if (r < 0) - return log_device_debug_errno(dev, errno > 0 ? errno : ENOMEM, "Failed to set device to blkid prober: %m"); + return log_device_debug_errno(dev, errno_or_else(ENOMEM), "Failed to set device to blkid prober: %m"); log_device_debug(dev, "Probe %s with %sraid and offset=%"PRIi64, devnode, noraid ? "no" : "", offset); @@ -301,7 +318,7 @@ static int builtin_blkid(sd_device *dev, int argc, char *argv[], bool test) { errno = 0; nvals = blkid_probe_numof_values(pr); if (nvals < 0) - return log_device_debug_errno(dev, errno > 0 ? errno : ENOMEM, "Failed to get number of probed values: %m"); + return log_device_debug_errno(dev, errno_or_else(ENOMEM), "Failed to get number of probed values: %m"); for (i = 0; i < nvals; i++) { if (blkid_probe_get_value(pr, i, &name, &data, NULL) < 0) diff --git a/test/fuzz/fuzz-udev-rules/60-persistent-storage.rules b/test/fuzz/fuzz-udev-rules/60-persistent-storage.rules index 1d8880ef029..d4114bf29e9 100644 --- a/test/fuzz/fuzz-udev-rules/60-persistent-storage.rules +++ b/test/fuzz/fuzz-udev-rules/60-persistent-storage.rules @@ -86,7 +86,7 @@ KERNEL=="vd*[0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID # probe filesystem metadata of optical drives which have a media inserted KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="?*", \ - IMPORT{builtin}="blkid --offset=$env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}" + IMPORT{builtin}="blkid --hint=session_offset=$env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}" # single-session CDs do not have ID_CDROM_MEDIA_SESSION_LAST_OFFSET KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="", \ IMPORT{builtin}="blkid --noraid"