chiark / gitweb /
prepare builtins for blkid and kmod
authorKay Sievers <kay.sievers@vrfy.org>
Wed, 21 Dec 2011 21:30:48 +0000 (22:30 +0100)
committerKay Sievers <kay.sievers@vrfy.org>
Wed, 21 Dec 2011 21:30:48 +0000 (22:30 +0100)
Makefile.am
configure.ac
udev/udev-builtin-blkid.c [new file with mode: 0644]
udev/udev-builtin-input_id.c
udev/udev-builtin-kmod.c [new file with mode: 0644]
udev/udev-builtin-path_id.c
udev/udev-builtin-usb_id.c
udev/udev-builtin.c
udev/udev-rules.c
udev/udev.h
udev/udevadm-test-builtin.c

index 178685e..3ac85b9 100644 (file)
@@ -203,7 +203,7 @@ bin_PROGRAMS = \
 libexec_PROGRAMS = \
        udev/udevd
 
-udev_common_sources =\
+udev_common_sources = \
        udev/udev.h \
        udev/udev-event.c \
        udev/udev-watch.c \
@@ -213,14 +213,24 @@ udev_common_sources =\
        udev/udev-builtin.c \
        udev/udev-builtin-path_id.c \
        udev/udev-builtin-usb_id.c \
-       udev/udev-builtin-input_id.c
+       udev/udev-builtin-input_id.c \
+       udev/udev-builtin-blkid.c \
+       udev/udev-builtin-kmod.c
+
+udev_common_CFLAGS = \
+       $(BLKID_CFLAGS)
+
+udev_common_LDADD = \
+       libudev/libudev-private.la \
+       $(BLKID_LIBS)
 
 udev_udevd_SOURCES = \
        $(udev_common_sources) \
        udev/udevd.c \
        udev/sd-daemon.h \
        udev/sd-daemon.c
-udev_udevd_LDADD = libudev/libudev-private.la
+udev_udevd_CFLAGS = $(udev_common_CFLAGS)
+udev_udevd_LDADD = $(udev_common_LDADD)
 
 udev_udevadm_SOURCES = \
        $(udev_common_sources) \
@@ -232,7 +242,8 @@ udev_udevadm_SOURCES = \
        udev/udevadm-trigger.c \
        udev/udevadm-test.c \
        udev/udevadm-test-builtin.c
-udev_udevadm_LDADD = libudev/libudev-private.la
+udev_udevadm_CFLAGS = $(udev_common_CFLAGS)
+udev_udevadm_LDADD = $(udev_common_LDADD)
 
 # ------------------------------------------------------------------------------
 # udev man pages
index 863aad8..86389fc 100644 (file)
@@ -73,6 +73,8 @@ AC_ARG_WITH([systemdsystemunitdir],
 AS_IF([test "x$with_systemdsystemunitdir" != "xno"], [ AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) ])
 AM_CONDITIONAL(WITH_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != "xno" ])
 
+PKG_CHECK_MODULES(BLKID, blkid >= 2.20)
+
 # ------------------------------------------------------------------------------
 # GUdev - libudev gobject interface
 # ------------------------------------------------------------------------------
diff --git a/udev/udev-builtin-blkid.c b/udev/udev-builtin-blkid.c
new file mode 100644 (file)
index 0000000..a787bf2
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * probe disks for filesystems and partitions
+ *
+ * Copyright (C) 2011 Kay Sievers <kay.sievers@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 <sys/stat.h>
+#include <blkid/blkid.h>
+
+#include "udev.h"
+
+static void print_property(const char *name, const char *value)
+{
+       char enc[265], safe[256];
+       size_t namelen = strlen(name);
+
+       enc[0] = '\0';
+       safe[0] = '\0';
+
+       if (!strcmp(name, "TYPE") || !strcmp(name, "VERSION")) {
+               blkid_encode_string(value, enc, sizeof(enc));
+               printf("ID_FS_%s=%s\n", name, enc);
+
+       } else if (!strcmp(name, "UUID") ||
+                !strcmp(name, "LABEL") ||
+                !strcmp(name, "UUID_SUB")) {
+
+               blkid_safe_string(value, safe, sizeof(safe));
+               printf("ID_FS_%s=%s\n", name, safe);
+
+               blkid_encode_string(value, enc, sizeof(enc));
+               printf("ID_FS_%s_ENC=%s\n", name, enc);
+
+       } else if (!strcmp(name, "PTTYPE")) {
+               printf("ID_PART_TABLE_TYPE=%s\n", value);
+
+       } else if (!strcmp(name, "PART_ENTRY_NAME") ||
+                 !strcmp(name, "PART_ENTRY_TYPE")) {
+
+               blkid_encode_string(value, enc, sizeof(enc));
+               printf("ID_%s=%s\n", name, enc);
+
+       } else if (!strncmp(name, "PART_ENTRY_", 11))
+               printf("ID_%s=%s\n", name, value);
+
+       else if (namelen >= 15 && (
+                  !strcmp(name + (namelen - 12), "_SECTOR_SIZE") ||
+                  !strcmp(name + (namelen - 8), "_IO_SIZE") ||
+                  !strcmp(name, "ALIGNMENT_OFFSET")))
+                       printf("ID_IOLIMIT_%s=%s\n", name, value);
+       else
+               printf("ID_FS_%s=%s\n", name, 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, const char *command, bool test)
+{
+       char *device = "/dev/sda3";
+       int64_t offset = 0;
+       //int noraid = 0;
+       int fd = -1;
+       blkid_probe pr;
+       const char *data;
+       const char *name;
+       int nvals;
+       int i;
+       size_t len;
+       int err = 0;
+
+       //FIXME: read offset, read noraid
+
+       pr = blkid_new_probe();
+       if (!pr) {
+               err = -ENOMEM;
+               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);
+
+       fd = open(device, O_RDONLY|O_CLOEXEC);
+       if (fd < 0) {
+               fprintf(stderr, "error: %s: %m\n", device);
+               goto out;
+       }
+
+       err = blkid_probe_set_device(pr, fd, offset, 0);
+       if (err < 0)
+               goto out;
+
+       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(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 = false,
+};
index 84ca0f7..420a872 100644 (file)
@@ -181,7 +181,7 @@ static void test_key (struct udev_device *dev,
                udev_builtin_add_property(dev, test, "ID_INPUT_KEYBOARD", "1");
 }
 
-static int builtin_input_id(struct udev_device *dev, bool test)
+static int builtin_input_id(struct udev_device *dev, const char *command, bool test)
 {
        struct udev_device *pdev;
        unsigned long bitmask_ev[NBITS(EV_MAX)];
diff --git a/udev/udev-builtin-kmod.c b/udev/udev-builtin-kmod.c
new file mode 100644 (file)
index 0000000..df05773
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * probe disks for filesystems and partitions
+ *
+ * Copyright (C) 2011 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * 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 <sys/stat.h>
+
+#include "udev.h"
+
+static int builtin_kmod(struct udev_device *dev, const char *command, bool test)
+{
+       printf("soon we load a module here: '%s'\n", command);
+       return EXIT_SUCCESS;
+}
+
+const struct udev_builtin udev_builtin_kmod = {
+       .name = "kmod",
+       .cmd = builtin_kmod,
+       .help = "kernel module loader",
+       .run_once = false,
+};
index 61c50d7..97a9ace 100644 (file)
@@ -390,7 +390,7 @@ out:
        return parent;
 }
 
-static int builtin_path_id(struct udev_device *dev, bool test)
+static int builtin_path_id(struct udev_device *dev, const char *command, bool test)
 {
        struct udev_device *parent;
        char *path = NULL;
@@ -483,4 +483,5 @@ const struct udev_builtin udev_builtin_path_id = {
        .name = "path_id",
        .cmd = builtin_path_id,
        .help = "compose persistent device path",
+       .run_once = true,
 };
index 587c216..9a51917 100644 (file)
@@ -239,7 +239,7 @@ out:
  * 6.) If the device supplies a serial number, this number
  *     is concatenated with the identification with an underscore '_'.
  */
-static int builtin_usb_id(struct udev_device *dev, bool test)
+static int builtin_usb_id(struct udev_device *dev, const char *command, bool test)
 {
        char vendor_str[64];
        char vendor_str_enc[256];
@@ -478,4 +478,5 @@ const struct udev_builtin udev_builtin_usb_id = {
        .name = "usb_id",
        .cmd = builtin_usb_id,
        .help = "usb device properties",
+       .run_once = true,
 };
index eeec6e9..3682170 100644 (file)
@@ -29,6 +29,8 @@ static const struct udev_builtin *builtins[] = {
        [UDEV_BUILTIN_PATH_ID] = &udev_builtin_path_id,
        [UDEV_BUILTIN_USB_ID] = &udev_builtin_usb_id,
        [UDEV_BUILTIN_INPUT_ID] = &udev_builtin_input_id,
+       [UDEV_BUILTIN_BLKID] = &udev_builtin_blkid,
+       [UDEV_BUILTIN_KMOD] = &udev_builtin_kmod,
 };
 
 int udev_builtin_list(struct udev *udev)
@@ -45,19 +47,30 @@ const char *udev_builtin_name(enum udev_builtin_cmd cmd)
        return builtins[cmd]->name;
 }
 
-enum udev_builtin_cmd udev_builtin_lookup(const char *name)
+bool udev_builtin_run_once(enum udev_builtin_cmd cmd)
 {
+       return builtins[cmd]->run_once;
+}
+
+enum udev_builtin_cmd udev_builtin_lookup(const char *command)
+{
+       char name[UTIL_PATH_SIZE];
        enum udev_builtin_cmd i;
+       char *pos;
 
+       util_strscpy(name, sizeof(name), command);
+       pos = strchr(name, ' ');
+       if (pos)
+               pos[0] = '\0';
        for (i = 0; i < ARRAY_SIZE(builtins); i++)
                if (strcmp(builtins[i]->name, name) == 0)
                        return i;
        return UDEV_BUILTIN_MAX;
 }
 
-int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, bool test)
+int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, const char *command, bool test)
 {
-       return builtins[cmd]->cmd(dev, test);
+       return builtins[cmd]->cmd(dev, command, test);
 }
 
 int udev_builtin_add_property(struct udev_device *dev, bool test, const char *key, const char *val, ...)
index f3e248e..0de4405 100644 (file)
@@ -364,7 +364,7 @@ static void dump_token(struct udev_rules *rules, struct token *token)
                    token_str(type), operation_str(op), value, string_glob_str(glob));
                break;
        case TK_M_IMPORT_BUILTIN:
-               dbg(rules->udev, "%s %i\n", token_str(type), token->key.builtin_cmd);
+               dbg(rules->udev, "%s %i '%s'\n", token_str(type), token->key.builtin_cmd, value);
                break;
        case TK_M_ATTR:
        case TK_M_ATTRS:
@@ -1039,6 +1039,7 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
                token->key.value_off = add_string(rule_tmp->rules, value);
                break;
        case TK_M_IMPORT_BUILTIN:
+               token->key.value_off = add_string(rule_tmp->rules, value);
                token->key.builtin_cmd = *(enum udev_builtin_cmd *)data;
                break;
        case TK_M_ENV:
@@ -1396,18 +1397,13 @@ static int add_rule(struct udev_rules *rules, char *line,
                        if (strstr(attr, "program")) {
                                /* find known built-in command */
                                if (value[0] != '/') {
-                                       char file[UTIL_PATH_SIZE];
-                                       char *pos;
                                        enum udev_builtin_cmd cmd;
 
-                                       util_strscpy(file, sizeof(file), value);
-                                       pos = strchr(file, ' ');
-                                       if (pos)
-                                               pos[0] = '\0';
-                                       cmd = udev_builtin_lookup(file);
+                                       cmd = udev_builtin_lookup(value);
                                        if (cmd < UDEV_BUILTIN_MAX) {
-                                               info(rules->udev, "IMPORT found builtin '%s', replacing %s:%u\n", file, filename, lineno);
-                                               rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, NULL, &cmd);
+                                               info(rules->udev, "IMPORT found builtin '%s', replacing %s:%u\n",
+                                                    value, filename, lineno);
+                                               rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
                                                continue;
                                        }
                                }
@@ -1418,7 +1414,7 @@ static int add_rule(struct udev_rules *rules, char *line,
 
                                dbg(rules->udev, "IMPORT execute builtin\n");
                                if (cmd < UDEV_BUILTIN_MAX)
-                                       rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, NULL, &cmd);
+                                       rule_add_key(&rule_tmp, TK_M_IMPORT_BUILTIN, op, value, &cmd);
                                else
                                        err(rules->udev, "IMPORT{builtin}: '%s' unknown %s:%u\n", value, filename, lineno);
                        } else if (strstr(attr, "file")) {
@@ -2308,25 +2304,29 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                        break;
                }
                case TK_M_IMPORT_BUILTIN: {
-                       /* check if we ran already */
-                       if (event->builtin_run & (1 << cur->key.builtin_cmd)) {
-                               info(event->udev, "IMPORT builtin skip '%s' %s:%u\n",
-                                    udev_builtin_name(cur->key.builtin_cmd),
-                                    &rules->buf[rule->rule.filename_off],
-                                    rule->rule.filename_line);
-                               /* return the result from earlier run */
-                               if (event->builtin_ret & (1 << cur->key.builtin_cmd))
+                       const char *command = &rules->buf[cur->key.value_off];
+
+                       if (udev_builtin_run_once(cur->key.builtin_cmd)) {
+                               /* check if we ran already */
+                               if (event->builtin_run & (1 << cur->key.builtin_cmd)) {
+                                       info(event->udev, "IMPORT builtin skip '%s' %s:%u\n",
+                                            udev_builtin_name(cur->key.builtin_cmd),
+                                            &rules->buf[rule->rule.filename_off],
+                                            rule->rule.filename_line);
+                                       /* return the result from earlier run */
+                                       if (event->builtin_ret & (1 << cur->key.builtin_cmd))
                                        if (cur->key.op != OP_NOMATCH)
-                                               goto nomatch;
-                               break;
+                                                       goto nomatch;
+                                       break;
+                               }
+                               /* mark as ran */
+                               event->builtin_run |= (1 << cur->key.builtin_cmd);
                        }
-                       /* mark as ran */
-                       event->builtin_run |= (1 << cur->key.builtin_cmd);
                        info(event->udev, "IMPORT builtin '%s' %s:%u\n",
                             udev_builtin_name(cur->key.builtin_cmd),
                             &rules->buf[rule->rule.filename_off],
                             rule->rule.filename_line);
-                       if (udev_builtin_run(event->dev, cur->key.builtin_cmd, false) != 0) {
+                       if (udev_builtin_run(event->dev, cur->key.builtin_cmd, command, false) != 0) {
                                /* remember failure */
                                info(rules->udev, "IMPORT builtin '%s' returned non-zero\n",
                                     udev_builtin_name(cur->key.builtin_cmd));
index eaba4ed..0a3d7c4 100644 (file)
@@ -150,20 +150,25 @@ enum udev_builtin_cmd {
        UDEV_BUILTIN_PATH_ID,
        UDEV_BUILTIN_USB_ID,
        UDEV_BUILTIN_INPUT_ID,
-       UDEV_BUILTIN_MODALIAS_MATCH,
+       UDEV_BUILTIN_BLKID,
+       UDEV_BUILTIN_KMOD,
        UDEV_BUILTIN_MAX
 };
 struct udev_builtin {
        const char *name;
-       int (*cmd)(struct udev_device *dev, bool test);
+       int (*cmd)(struct udev_device *dev, const char *command, bool test);
        const char *help;
+       bool run_once;
 };
 extern const struct udev_builtin udev_builtin_path_id;
 extern const struct udev_builtin udev_builtin_usb_id;
 extern const struct udev_builtin udev_builtin_input_id;
-enum udev_builtin_cmd udev_builtin_lookup(const char *name);
+extern const struct udev_builtin udev_builtin_blkid;
+extern const struct udev_builtin udev_builtin_kmod;
+enum udev_builtin_cmd udev_builtin_lookup(const char *command);
 const char *udev_builtin_name(enum udev_builtin_cmd cmd);
-int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, bool test);
+bool udev_builtin_run_once(enum udev_builtin_cmd cmd);
+int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, const char *command, bool test);
 int udev_builtin_list(struct udev *udev);
 int udev_builtin_add_property(struct udev_device *dev, bool test, const char *key, const char *val, ...);
 #endif
index a2be776..f8af899 100644 (file)
@@ -107,7 +107,7 @@ static int adm_builtin(struct udev *udev, int argc, char *argv[])
                goto out;
        }
 
-       if (udev_builtin_run(dev, cmd, true) < 0) {
+       if (udev_builtin_run(dev, cmd, command, true) < 0) {
                fprintf(stderr, "error executing '%s'\n\n", command);
                rc = 6;
        }