libexec_PROGRAMS = \
udev/udevd
-udev_common_sources =\
+udev_common_sources = \
udev/udev.h \
udev/udev-event.c \
udev/udev-watch.c \
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) \
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
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
# ------------------------------------------------------------------------------
--- /dev/null
+/*
+ * 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,
+};
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)];
--- /dev/null
+/*
+ * 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,
+};
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;
.name = "path_id",
.cmd = builtin_path_id,
.help = "compose persistent device path",
+ .run_once = true,
};
* 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];
.name = "usb_id",
.cmd = builtin_usb_id,
.help = "usb device properties",
+ .run_once = true,
};
[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)
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, ...)
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:
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:
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;
}
}
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")) {
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));
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
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;
}