diff options
-rw-r--r-- | Makefile.am | 19 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | udev/udev-builtin-blkid.c | 171 | ||||
-rw-r--r-- | udev/udev-builtin-input_id.c | 2 | ||||
-rw-r--r-- | udev/udev-builtin-kmod.c | 42 | ||||
-rw-r--r-- | udev/udev-builtin-path_id.c | 3 | ||||
-rw-r--r-- | udev/udev-builtin-usb_id.c | 3 | ||||
-rw-r--r-- | udev/udev-builtin.c | 19 | ||||
-rw-r--r-- | udev/udev-rules.c | 48 | ||||
-rw-r--r-- | udev/udev.h | 13 | ||||
-rw-r--r-- | udev/udevadm-test-builtin.c | 2 |
11 files changed, 285 insertions, 39 deletions
diff --git a/Makefile.am b/Makefile.am index 178685ea22..3ac85b95cc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/configure.ac b/configure.ac index 863aad86d4..86389fc410 100644 --- a/configure.ac +++ b/configure.ac @@ -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 index 0000000000..a787bf2f6c --- /dev/null +++ b/udev/udev-builtin-blkid.c @@ -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, +}; diff --git a/udev/udev-builtin-input_id.c b/udev/udev-builtin-input_id.c index 84ca0f75e4..420a872662 100644 --- a/udev/udev-builtin-input_id.c +++ b/udev/udev-builtin-input_id.c @@ -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 index 0000000000..df057735d7 --- /dev/null +++ b/udev/udev-builtin-kmod.c @@ -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, +}; diff --git a/udev/udev-builtin-path_id.c b/udev/udev-builtin-path_id.c index 61c50d77bd..97a9ace5c1 100644 --- a/udev/udev-builtin-path_id.c +++ b/udev/udev-builtin-path_id.c @@ -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, }; diff --git a/udev/udev-builtin-usb_id.c b/udev/udev-builtin-usb_id.c index 587c21667b..9a519179c8 100644 --- a/udev/udev-builtin-usb_id.c +++ b/udev/udev-builtin-usb_id.c @@ -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, }; diff --git a/udev/udev-builtin.c b/udev/udev-builtin.c index eeec6e990d..36821702c1 100644 --- a/udev/udev-builtin.c +++ b/udev/udev-builtin.c @@ -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, ...) diff --git a/udev/udev-rules.c b/udev/udev-rules.c index f3e248eb4f..0de44054b7 100644 --- a/udev/udev-rules.c +++ b/udev/udev-rules.c @@ -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)); diff --git a/udev/udev.h b/udev/udev.h index eaba4ed341..0a3d7c4506 100644 --- a/udev/udev.h +++ b/udev/udev.h @@ -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 diff --git a/udev/udevadm-test-builtin.c b/udev/udevadm-test-builtin.c index a2be77683a..f8af8992d0 100644 --- a/udev/udevadm-test-builtin.c +++ b/udev/udevadm-test-builtin.c @@ -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; } |