summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--rules/60-persistent-storage.rules8
-rw-r--r--src/test/Makefile.am1
-rw-r--r--src/udev/Makefile.am7
-rw-r--r--src/udev/udev-builtin-blkid.c204
-rw-r--r--src/udev/udev-builtin.c1
-rw-r--r--src/udev/udev.h2
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;