From f49af0b03bd94d2137d2d9938e23d81475287958 Mon Sep 17 00:00:00 2001 From: Boian Bonev Date: Thu, 31 Aug 2023 23:46:56 +0000 Subject: [PATCH 1/5] Fix := not preventing further assignments to RUN Closes #256 Suggested by: Aksel Lunde Aase --- src/udev/udev-rules.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 198875bc9..32df8b9cb 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -2601,6 +2601,10 @@ int udev_rules_apply_to_event(struct udev_rules *rules, case TK_A_RUN_PROGRAM: { struct udev_list_entry *entry; + if (event->run_final) + break; + if (cur->key.op == OP_ASSIGN_FINAL) + event->run_final = true; if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL) udev_list_cleanup(&event->run_list); log_debug("RUN '%s' %s:%u", From e5e4013cb7a5c1b192a044414793f341604d1881 Mon Sep 17 00:00:00 2001 From: Boian Bonev Date: Sat, 30 Sep 2023 16:52:12 +0000 Subject: [PATCH 2/5] Move the changes from udev.7 to udev.xml Commit 0cf14fb changed only the generated udev.7 without touching the source file udev.xml --- man/udev.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/man/udev.xml b/man/udev.xml index 98bfaed2a..eb6d38c3e 100644 --- a/man/udev.xml +++ b/man/udev.xml @@ -55,15 +55,17 @@ Rules Files - The udev rules are read from the files located in the - system rules directory /lib/udev/rules.d, + The udev rules are read from the files located in the system rules + directory /lib/udev/rules.d (additionally + /usr/lib/udev/rules.d when built with --enable-split-usr), the volatile runtime directory /run/udev/rules.d and the local administration directory /etc/udev/rules.d. All rules files are collectively sorted and processed in lexical order, regardless of the directories in which they live. However, files with identical filenames replace each other. Files in /etc have the highest priority, files in /run take precedence - over files with the same name in /lib. This can be + over files with the same name in /lib (or + /usr/lib). This can be used to override a system-supplied rules file with a local file if needed; a symlink in /etc with the same name as a rules file in /lib, pointing to /dev/null, From 19aa81d9bfeea4e062a65a44cd627d5c5581f974 Mon Sep 17 00:00:00 2001 From: Boian Bonev Date: Sat, 30 Sep 2023 16:55:44 +0000 Subject: [PATCH 3/5] Regenerate according to 0cf14fb and e5e4013 --- man/udev.7 | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/man/udev.7 b/man/udev.7 index 3322676d6..1561878ab 100644 --- a/man/udev.7 +++ b/man/udev.7 @@ -34,7 +34,10 @@ All device information udev processes is stored in the udev database and sent ou .SH "RULES FILES" .PP The udev rules are read from the files located in the system rules directory -/lib/udev/rules\&.d (additionally /usr/lib/udev/rules\&.d when built with --enable-split-usr), the volatile runtime directory +/lib/udev/rules\&.d +(additionally +/usr/lib/udev/rules\&.d +when built with \-\-enable\-split\-usr), the volatile runtime directory /run/udev/rules\&.d and the local administration directory /etc/udev/rules\&.d\&. All rules files are collectively sorted and processed in lexical order, regardless of the directories in which they live\&. However, files with identical filenames replace each other\&. Files in @@ -42,7 +45,9 @@ and the local administration directory have the highest priority, files in /run take precedence over files with the same name in -/lib (or /usr/lib)\&. This can be used to override a system\-supplied rules file with a local file if needed; a symlink in +/lib +(or +/usr/lib)\&. This can be used to override a system\-supplied rules file with a local file if needed; a symlink in /etc with the same name as a rules file in /lib, pointing to From c7da117e5cfb5e1de4dc519cd892f9bb27c721ce Mon Sep 17 00:00:00 2001 From: Vivien Kraus Date: Sat, 30 Sep 2023 09:08:48 +0200 Subject: [PATCH 4/5] Let libudev find hwdb.bin under UDEV_HWDB_BIN * src/libudev/libudev-hwdb.c (get_hwdb_bin_paths): New function, replacing hwdb_bin_paths. (struct udev_hwdb): New bin_paths field. (udev_hwdb_new): Initialize it with get_hwdb_bin_paths. (udev_hwdb_validate): Use the bin_paths field to find hwdb.bin. (udev_hwdb_unref): Free the bin_paths field. * src/libudev/libudev.h: Warn about UDEV_HWDB_BIN. * man/udev.xml: Mention run-time UDEV_HWDB_BIN. * man/udev.7: Re-generate. --- man/udev.7 | 8 +++++--- man/udev.xml | 4 +++- src/libudev/libudev-hwdb.c | 37 +++++++++++++++++++++++++++++++------ src/libudev/libudev.h | 4 +++- 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/man/udev.7 b/man/udev.7 index 3322676d6..370c4becd 100644 --- a/man/udev.7 +++ b/man/udev.7 @@ -34,7 +34,7 @@ All device information udev processes is stored in the udev database and sent ou .SH "RULES FILES" .PP The udev rules are read from the files located in the system rules directory -/lib/udev/rules\&.d (additionally /usr/lib/udev/rules\&.d when built with --enable-split-usr), the volatile runtime directory +/lib/udev/rules\&.d, the volatile runtime directory /run/udev/rules\&.d and the local administration directory /etc/udev/rules\&.d\&. All rules files are collectively sorted and processed in lexical order, regardless of the directories in which they live\&. However, files with identical filenames replace each other\&. Files in @@ -42,7 +42,7 @@ and the local administration directory have the highest priority, files in /run take precedence over files with the same name in -/lib (or /usr/lib)\&. This can be used to override a system\-supplied rules file with a local file if needed; a symlink in +/lib\&. This can be used to override a system\-supplied rules file with a local file if needed; a symlink in /etc with the same name as a rules file in /lib, pointing to @@ -560,7 +560,9 @@ The content of all hwdb files is read by and compiled to a binary database located at /etc/udev/hwdb\&.bin, or alternatively /usr/lib/udev/hwdb\&.bin -if you want ship the compiled database in an immutable image\&. During runtime only the binary database is used\&. +if you want ship the compiled database in an immutable image\&. If +\fBUDEV_HWDB_BIN\fR +is set at run\-time, and its value identifies a file in the file system, then the binary database located under this name will be used\&. During runtime only the binary database is used\&. .SH "SEE ALSO" .PP \fBudevd\fR(8), diff --git a/man/udev.xml b/man/udev.xml index 98bfaed2a..aa6667542 100644 --- a/man/udev.xml +++ b/man/udev.xml @@ -765,7 +765,9 @@ udevadm8 and compiled to a binary database located at /etc/udev/hwdb.bin, or alternatively /usr/lib/udev/hwdb.bin if you want ship the compiled - database in an immutable image. + database in an immutable image. If UDEV_HWDB_BIN + is set at run-time, and its value identifies a file in the file system, then the binary + database located under this name will be used. During runtime only the binary database is used. diff --git a/src/libudev/libudev-hwdb.c b/src/libudev/libudev-hwdb.c index 62029e2b2..f7212c519 100644 --- a/src/libudev/libudev-hwdb.c +++ b/src/libudev/libudev-hwdb.c @@ -47,6 +47,7 @@ struct udev_hwdb { struct udev *udev; int refcount; + char *bin_paths; FILE *f; struct stat st; union { @@ -256,10 +257,28 @@ static int trie_search_f(struct udev_hwdb *hwdb, const char *search) { return 0; } -static const char hwdb_bin_paths[] = - "/etc/udev/hwdb.bin\0" - UDEV_LIBEXEC_DIR "/hwdb.bin\0"; - +static char *get_hwdb_bin_paths (void) { + static const char default_locations[] = + "/etc/udev/hwdb.bin\0" + UDEV_LIBEXEC_DIR "/hwdb.bin\0"; + const char *by_env = getenv("UDEV_HWDB_BIN"); + if (by_env != NULL) { + char *path = malloc(strlen(by_env) + 1 + + sizeof (default_locations)); + if (path != NULL) { + memcpy(path, by_env, strlen(by_env) + 1); + memcpy(path + strlen(by_env) + 1, + default_locations, + sizeof (default_locations)); + } + return path; + } + char *path = malloc(sizeof (default_locations)); + if (path != NULL) { + memcpy(path, default_locations, sizeof (default_locations)); + } + return path; +} /** * udev_hwdb_new: @@ -282,7 +301,12 @@ _public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) { udev_list_init(udev, &hwdb->properties_list, true); /* find hwdb.bin in hwdb_bin_paths */ - NULSTR_FOREACH(hwdb_bin_path, hwdb_bin_paths) { + hwdb->bin_paths = get_hwdb_bin_paths(); + if (hwdb->bin_paths == NULL) { + udev_hwdb_unref(hwdb); + return NULL; + } + NULSTR_FOREACH(hwdb_bin_path, hwdb->bin_paths) { hwdb->f = fopen(hwdb_bin_path, "re"); if (hwdb->f) break; @@ -363,6 +387,7 @@ _public_ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) { return NULL; if (hwdb->map) munmap((void *)hwdb->map, hwdb->st.st_size); + free(hwdb->bin_paths); if (hwdb->f) fclose(hwdb->f); udev_list_cleanup(&hwdb->properties_list); @@ -381,7 +406,7 @@ bool udev_hwdb_validate(struct udev_hwdb *hwdb) { return false; /* if hwdb.bin doesn't exist anywhere, we need to update */ - NULSTR_FOREACH(p, hwdb_bin_paths) { + NULSTR_FOREACH(p, hwdb->bin_paths) { if (stat(p, &st) >= 0) { found = true; break; diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h index 8491d2b81..e4bc18970 100644 --- a/src/libudev/libudev.h +++ b/src/libudev/libudev.h @@ -185,7 +185,9 @@ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev /* * udev_hwdb * - * access to the static hardware properties database + * access to the static hardware properties database; the database to + * use can be overriden by setting the UDEV_HWDB_BIN environment + * variable to its file name */ struct udev_hwdb; struct udev_hwdb *udev_hwdb_new(struct udev *udev); From 1eca0ef6c4f97067adcb68fde1cb675bf15a7ec3 Mon Sep 17 00:00:00 2001 From: Vivien Kraus Date: Wed, 27 Sep 2023 17:58:01 +0200 Subject: [PATCH 5/5] Add a generic --output argument to udevadm hwdb Instead of always writing /etc/udev/hwdb.bin or UDEV_LIBEXEC_DIR /hwdb.bin, let the user specify a full file name. * src/udev/udevadm-hwdb.c (adm_hwdb): New option "output". Construct hwdb_bin when processing options, and prepend root after processing options. * man/udev.xml: Mention --output. * man/udevadm.xml: Document --output. * man/udev.7: Regenerate. * man/udevadm.8: Same. --- man/udev.7 | 8 +++++--- man/udev.xml | 2 +- man/udevadm.8 | 5 +++++ man/udevadm.xml | 7 +++++++ src/udev/udevadm-hwdb.c | 42 ++++++++++++++++++++++++++++++++++++----- 5 files changed, 55 insertions(+), 9 deletions(-) diff --git a/man/udev.7 b/man/udev.7 index 3322676d6..7686fe444 100644 --- a/man/udev.7 +++ b/man/udev.7 @@ -34,7 +34,7 @@ All device information udev processes is stored in the udev database and sent ou .SH "RULES FILES" .PP The udev rules are read from the files located in the system rules directory -/lib/udev/rules\&.d (additionally /usr/lib/udev/rules\&.d when built with --enable-split-usr), the volatile runtime directory +/lib/udev/rules\&.d, the volatile runtime directory /run/udev/rules\&.d and the local administration directory /etc/udev/rules\&.d\&. All rules files are collectively sorted and processed in lexical order, regardless of the directories in which they live\&. However, files with identical filenames replace each other\&. Files in @@ -42,7 +42,7 @@ and the local administration directory have the highest priority, files in /run take precedence over files with the same name in -/lib (or /usr/lib)\&. This can be used to override a system\-supplied rules file with a local file if needed; a symlink in +/lib\&. This can be used to override a system\-supplied rules file with a local file if needed; a symlink in /etc with the same name as a rules file in /lib, pointing to @@ -560,7 +560,9 @@ The content of all hwdb files is read by and compiled to a binary database located at /etc/udev/hwdb\&.bin, or alternatively /usr/lib/udev/hwdb\&.bin -if you want ship the compiled database in an immutable image\&. During runtime only the binary database is used\&. +if you want ship the compiled database in an immutable image by using +\fB\-\-usr\fR, or anywhere on the system by using +\fB\-\-output\fR\&. During runtime only the binary database is used\&. .SH "SEE ALSO" .PP \fBudevd\fR(8), diff --git a/man/udev.xml b/man/udev.xml index 98bfaed2a..ec2624057 100644 --- a/man/udev.xml +++ b/man/udev.xml @@ -765,7 +765,7 @@ udevadm8 and compiled to a binary database located at /etc/udev/hwdb.bin, or alternatively /usr/lib/udev/hwdb.bin if you want ship the compiled - database in an immutable image. + database in an immutable image by using , or anywhere on the system by using . During runtime only the binary database is used. diff --git a/man/udevadm.8 b/man/udevadm.8 index f6e2cfc39..3f201597f 100644 --- a/man/udevadm.8 +++ b/man/udevadm.8 @@ -380,6 +380,11 @@ Query the database with a modalias string, and print the retrieved properties\&. Alternative root path in the file system for reading and writing files\&. .RE .PP +\fB\-o\fR, \fB\-\-output=\fR\fB\fIstring\fR\fR +.RS 4 +Specify the exact location where to write the compiled database\&. +.RE +.PP \fB\-h\fR, \fB\-\-help\fR .RS 4 Print help text\&. diff --git a/man/udevadm.xml b/man/udevadm.xml index efd01118f..7da0eef20 100644 --- a/man/udevadm.xml +++ b/man/udevadm.xml @@ -552,6 +552,13 @@ Alternative root path in the file system for reading and writing files. + + + + + Specify the exact location where to write the compiled database. + + diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c index d14a3434f..9dde04460 100644 --- a/src/udev/udevadm-hwdb.c +++ b/src/udev/udevadm-hwdb.c @@ -564,6 +564,7 @@ static int import_file(struct udev *udev, struct trie *trie, const char *filenam static void help(void) { printf("Usage: udevadm hwdb OPTIONS\n" " -u,--update update the hardware database\n" + " -o,--output=.../hwdb.bin generate in .../hwdb.bin instead of /etc/udev/hwdb.bin\n" " --usr generate in " UDEV_LIBEXEC_DIR " instead of /etc/udev\n" " -t,--test=MODALIAS query database and print result\n" " -r,--root=PATH alternative root path in the filesystem\n" @@ -578,6 +579,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { static const struct option options[] = { { "update", no_argument, NULL, 'u' }, { "usr", no_argument, NULL, ARG_USR }, + { "output", required_argument, NULL, 'o' }, { "test", required_argument, NULL, 't' }, { "root", required_argument, NULL, 'r' }, { "help", no_argument, NULL, 'h' }, @@ -585,19 +587,37 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { }; const char *test = NULL; const char *root = ""; - const char *hwdb_bin_dir = "/etc/udev"; bool update = false; struct trie *trie = NULL; int err, c; int rc = EXIT_SUCCESS; - while ((c = getopt_long(argc, argv, "ut:r:h", options, NULL)) >= 0) + _cleanup_free_ char *hwdb_bin = strdup("/etc/udev/hwdb.bin"); + if (hwdb_bin == NULL) { + rc = EXIT_FAILURE; + goto out; + } + + while ((c = getopt_long(argc, argv, "uo:t:r:h", options, NULL)) >= 0) switch(c) { case 'u': update = true; break; case ARG_USR: - hwdb_bin_dir = UDEV_LIBEXEC_DIR; + free(hwdb_bin); + hwdb_bin = strdup(UDEV_LIBEXEC_DIR "/hwdb.bin"); + if (hwdb_bin == NULL) { + rc = EXIT_FAILURE; + goto out; + } + break; + case 'o': + free(hwdb_bin); + hwdb_bin = strdup(optarg); + if (hwdb_bin == NULL) { + rc = EXIT_FAILURE; + goto out; + } break; case 't': test = optarg; @@ -621,7 +641,20 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { if (update) { char **files, **f; - _cleanup_free_ char *hwdb_bin = NULL; + + if (strlen(root)) { + /* --root has been specified, prepend it to + the hwdb.bin destination file. */ + char *full_hwdb_bin = strjoin(root, "/", hwdb_bin, NULL); + /* Do nothing if no --root, so that hwdb_bin + may still be relative. */ + if (full_hwdb_bin == NULL) { + rc = EXIT_FAILURE; + goto out; + } + free (hwdb_bin); + hwdb_bin = full_hwdb_bin; + } trie = new0(struct trie, 1); if (!trie) { @@ -672,7 +705,6 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { log_debug("strings dedup'ed: %8zu bytes (%8zu)", trie->strings->dedup_len, trie->strings->dedup_count); - hwdb_bin = strjoin(root, "/", hwdb_bin_dir, "/hwdb.bin", NULL); if (!hwdb_bin) { rc = EXIT_FAILURE; goto out;