diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | rules/60-persistent-storage.rules | 8 | ||||
-rw-r--r-- | src/test/Makefile.am | 1 | ||||
-rw-r--r-- | src/udev/Makefile.am | 7 | ||||
-rw-r--r-- | src/udev/udev-builtin-blkid.c | 204 | ||||
-rw-r--r-- | src/udev/udev-builtin.c | 1 | ||||
-rw-r--r-- | src/udev/udev.h | 2 |
7 files changed, 220 insertions, 5 deletions
diff --git a/configure.ac b/configure.ac index d609ef2604..492d5e33d6 100644 --- a/configure.ac +++ b/configure.ac @@ -39,6 +39,8 @@ if test -z "$GPERF" ; then AC_MSG_ERROR([*** gperf not found]) fi +PKG_CHECK_MODULES(BLKID,[blkid >= 2.20]) + # Checks for header files. AC_CHECK_HEADERS( [arpa/inet.h fcntl.h inttypes.h langinfo.h limits.h locale.h malloc.h \ diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules index 5ca7c314fc..b74821edd4 100644 --- a/rules/60-persistent-storage.rules +++ b/rules/60-persistent-storage.rules @@ -62,12 +62,14 @@ ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PA ENV{DEVTYPE}=="disk", KERNEL!="sd*|sr*", ATTR{removable}=="1", GOTO="persistent_storage_end" # 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{program}="@sbindir@/blkid -o udev -p -u noraid -O $env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET} $tempnode" +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}" # 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{program}="@sbindir@/blkid -o udev -p -u noraid $tempnode" +KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="", \ + IMPORT{builtin}="blkid --noraid" # probe filesystem metadata of disks -KERNEL!="sr*", IMPORT{program}="@sbindir@/blkid -o udev -p $tempnode" +KERNEL!="sr*", IMPORT{builtin}="blkid" # watch metadata changes by tools closing the device after writing KERNEL!="sr*", OPTIONS+="watch" diff --git a/src/test/Makefile.am b/src/test/Makefile.am index ff45517cdf..ca7fde035c 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -27,6 +27,7 @@ test_udev_SOURCES = \ test_udev_LDADD = \ $(top_builddir)/src/libudev/libudev-private.la \ $(top_builddir)/src/udev/libudev-core.la \ + $(BLKID_LIBS) \ $(SELINUX_LIBS) test_udev_CPPFLAGS = \ diff --git a/src/udev/Makefile.am b/src/udev/Makefile.am index e373ce2183..1dc738c51c 100644 --- a/src/udev/Makefile.am +++ b/src/udev/Makefile.am @@ -44,6 +44,7 @@ libudev_core_la_SOURCES = \ udev-rules.c \ udev-ctrl.c \ udev-builtin.c \ + udev-builtin-blkid.c \ udev-builtin-btrfs.c \ udev-builtin-firmware.c \ udev-builtin-hwdb.c \ @@ -98,10 +99,12 @@ include_HEADERS = \ udev.h libudev_core_la_CFLAGS = \ - $(AM_CFLAGS) + $(AM_CFLAGS) \ + $(BLKID_CFLAGS) libudev_core_la_LIBADD = \ - $(top_builddir)/src/libudev/libudev-private.la + $(top_builddir)/src/libudev/libudev-private.la \ + $(BLKID_LIBS) if HAVE_ACL libudev_core_la_SOURCES += \ diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c new file mode 100644 index 0000000000..4293103046 --- /dev/null +++ b/src/udev/udev-builtin-blkid.c @@ -0,0 +1,204 @@ +/* + * probe disks for filesystems and partitions + * + * Copyright (C) 2011 Kay Sievers <kay@vrfy.org> + * Copyright (C) 2011 Karel Zak <kzak@redhat.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <getopt.h> +#include <sys/stat.h> +#include <blkid/blkid.h> + +#include "udev.h" + +static void print_property(struct udev_device *dev, bool test, const char *name, const char *value) +{ + char s[265]; + + s[0] = '\0'; + + if (streq(name, "TYPE")) { + udev_builtin_add_property(dev, test, "ID_FS_TYPE", value); + + } else if (streq(name, "USAGE")) { + udev_builtin_add_property(dev, test, "ID_FS_USAGE", value); + + } else if (streq(name, "VERSION")) { + udev_builtin_add_property(dev, test, "ID_FS_VERSION", value); + + } else if (streq(name, "UUID")) { + blkid_safe_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_UUID", s); + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s); + + } else if (streq(name, "UUID_SUB")) { + blkid_safe_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s); + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s); + + } else if (streq(name, "LABEL")) { + blkid_safe_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_LABEL", s); + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s); + + } else if (streq(name, "PTTYPE")) { + udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value); + + } else if (streq(name, "PART_ENTRY_NAME")) { + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s); + + } else if (streq(name, "PART_ENTRY_TYPE")) { + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_PART_ENTRY_TYPE", s); + + } else if (startswith(name, "PART_ENTRY_")) { + util_strscpyl(s, sizeof(s), "ID_", name, NULL); + udev_builtin_add_property(dev, test, s, value); + } +} + +static int probe_superblocks(blkid_probe pr) +{ + struct stat st; + int rc; + + if (fstat(blkid_probe_get_fd(pr), &st)) + return -1; + + blkid_probe_enable_partitions(pr, 1); + + if (!S_ISCHR(st.st_mode) && blkid_probe_get_size(pr) <= 1024 * 1440 && + blkid_probe_is_wholedisk(pr)) { + /* + * check if the small disk is partitioned, if yes then + * don't probe for filesystems. + */ + blkid_probe_enable_superblocks(pr, 0); + + rc = blkid_do_fullprobe(pr); + if (rc < 0) + return rc; /* -1 = error, 1 = nothing, 0 = succes */ + + if (blkid_probe_lookup_value(pr, "PTTYPE", NULL, NULL) == 0) + return 0; /* partition table detected */ + } + + blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS); + blkid_probe_enable_superblocks(pr, 1); + + return blkid_do_safeprobe(pr); +} + +static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool test) +{ + int64_t offset = 0; + bool noraid = false; + int fd = -1; + blkid_probe pr; + const char *data; + const char *name; + int nvals; + int i; + size_t len; + int err = 0; + + static const struct option options[] = { + { "offset", optional_argument, NULL, 'o' }, + { "noraid", no_argument, NULL, 'R' }, + {} + }; + + for (;;) { + int option; + + option = getopt_long(argc, argv, "oR", options, NULL); + if (option == -1) + break; + + switch (option) { + case 'o': + offset = strtoull(optarg, NULL, 0); + break; + case 'R': + noraid = true; + break; + } + } + + pr = blkid_new_probe(); + if (!pr) + return EXIT_FAILURE; + + blkid_probe_set_superblocks_flags(pr, + BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | + BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | + BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); + + if (noraid) + blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); + + fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC); + if (fd < 0) { + fprintf(stderr, "error: %s: %m\n", udev_device_get_devnode(dev)); + goto out; + } + + err = blkid_probe_set_device(pr, fd, offset, 0); + if (err < 0) + goto out; + + log_debug("probe %s %sraid offset=%llu\n", + udev_device_get_devnode(dev), + noraid ? "no" : "", (unsigned long long) offset); + + err = probe_superblocks(pr); + if (err < 0) + goto out; + + nvals = blkid_probe_numof_values(pr); + for (i = 0; i < nvals; i++) { + if (blkid_probe_get_value(pr, i, &name, &data, &len)) + continue; + len = strnlen((char *) data, len); + print_property(dev, test, name, (char *) data); + } + + blkid_free_probe(pr); +out: + if (fd > 0) + close(fd); + if (err < 0) + return EXIT_FAILURE; + return EXIT_SUCCESS; +} + +const struct udev_builtin udev_builtin_blkid = { + .name = "blkid", + .cmd = builtin_blkid, + .help = "filesystem and partition probing", + .run_once = true, +}; diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c index d56b2237c9..e0e18d4ee9 100644 --- a/src/udev/udev-builtin.c +++ b/src/udev/udev-builtin.c @@ -30,6 +30,7 @@ static bool initialized; static const struct udev_builtin *builtins[] = { + [UDEV_BUILTIN_BLKID] = &udev_builtin_blkid, [UDEV_BUILTIN_BTRFS] = &udev_builtin_btrfs, [UDEV_BUILTIN_FIRMWARE] = &udev_builtin_firmware, [UDEV_BUILTIN_HWDB] = &udev_builtin_hwdb, diff --git a/src/udev/udev.h b/src/udev/udev.h index 23a04f766c..c10610ea27 100644 --- a/src/udev/udev.h +++ b/src/udev/udev.h @@ -134,6 +134,7 @@ int udev_ctrl_get_set_children_max(struct udev_ctrl_msg *ctrl_msg); /* built-in commands */ enum udev_builtin_cmd { + UDEV_BUILTIN_BLKID, UDEV_BUILTIN_BTRFS, UDEV_BUILTIN_FIRMWARE, UDEV_BUILTIN_HWDB, @@ -155,6 +156,7 @@ struct udev_builtin { bool (*validate)(struct udev *udev); bool run_once; }; +extern const struct udev_builtin udev_builtin_blkid; extern const struct udev_builtin udev_builtin_btrfs; extern const struct udev_builtin udev_builtin_firmware; extern const struct udev_builtin udev_builtin_hwdb; |