]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev-builtin-blkid: add support for --hint offsets
authorKarel Zak <kzak@redhat.com>
Mon, 30 Nov 2020 10:38:21 +0000 (11:38 +0100)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 12 Jan 2021 15:58:43 +0000 (00:58 +0900)
The next libblkid v2.37 is going to support session offsets for
multi-session CD/DVDs. This feature is implemented by "hint offsets".

These offsets are optional and prober specific (e.g., iso, udf, ...).
For this purpose, the library provides a new function
blkid_probe_set_hint(), and blkid(8) provides a new command-line
option --hint <name>=<offset>. For CD/DVD, the offset name is
"session_offset".

The difference between classic --offset and the new --hint is that
--offset is very restrictive and defines the probing area and the rest
of the device is invisible to the library. The new --hint works
like a suggestion, it provides a hint where the user assumes the
filesystem, but the rest of the device is still readable for the
library (for example, to get some additional superblock information
etc.).

If the --hint is without a value then it defaults to zero.

The option --hint implementation in udev-builtin-blkid.c is backwardly
compatible. If compiled against old libblkid, then the option is used in
the same way as --offset.

Addresses: https://github.com/karelzak/util-linux/issues/1161
Addresses: https://github.com/systemd/systemd/pull/17424

meson.build
rules.d/60-persistent-storage.rules
src/udev/udev-builtin-blkid.c
test/fuzz/fuzz-udev-rules/60-persistent-storage.rules

index aedde9b94e9dc289b858650c04f3ccc00577bef0..841dd97003c83df8005d7091405a21012db008bf 100644 (file)
@@ -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 = []
index fc7f733e20058504635dbd8a32e5e645eb795d2b..35b4f2c6dc54cf0fff1e901ad5a4ebd8657f5811 100644 (file)
@@ -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"
index 8333eb4fc40f542decdc5d9e9ba64403c6c96aab..6a3b7cf18fd3a5d49566d3c8f83a2eafa13941cf 100644 (file)
@@ -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 <name>=<offset> 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)
index 1d8880ef0290137e29f9b416c347e8a08505ecf9..d4114bf29e9a5a1fd3015cb9066905bf69e01e09 100644 (file)
@@ -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"