Skip to content

Commit

Permalink
Merge pull request #262 from vivien-consider-dropping-github/master
Browse files Browse the repository at this point in the history
Dynamically get the udevadm hwdb files with a path variable
  • Loading branch information
bbonev authored Sep 30, 2023
2 parents 0c8f002 + 92ab29e commit 805c07a
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 19 deletions.
10 changes: 7 additions & 3 deletions man/udev.7
Original file line number Diff line number Diff line change
Expand Up @@ -540,13 +540,17 @@ character itself\&.
The hwdb files are read from the files located in the system hwdb directory
/usr/lib/udev/hwdb\&.d, the volatile runtime directory
/run/udev/hwdb\&.d
and the local administration directory
/etc/udev/hwdb\&.d\&. All hwdb 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
the local administration directory
/etc/udev/hwdb\&.d, and any other directory in the
\fBUDEV_HWDB_PATH\fR
search path variable\&. All hwdb 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
/usr/lib\&. This can be used to override a system\-supplied hwdb file with a local file if needed; a symlink in
/usr/lib, and the content of
\fBUDEV_HWDB_PATH\fR
comes last\&. This order can be used to override a system\-supplied hwdb file with a local file if needed; a symlink in
/etc
with the same name as a hwdb file in
/usr/lib, pointing to
Expand Down
9 changes: 6 additions & 3 deletions man/udev.xml
Original file line number Diff line number Diff line change
Expand Up @@ -738,12 +738,15 @@
<para>The hwdb files are read from the files located in the
system hwdb directory <filename>/usr/lib/udev/hwdb.d</filename>,
the volatile runtime directory <filename>/run/udev/hwdb.d</filename>
and the local administration directory <filename>/etc/udev/hwdb.d</filename>.
the local administration directory <filename>/etc/udev/hwdb.d</filename>,
and any other directory in the <envar>UDEV_HWDB_PATH</envar> search path variable.
All hwdb 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 <filename>/etc</filename>
have the highest priority, files in <filename>/run</filename> take precedence
over files with the same name in <filename>/usr/lib</filename>. This can be
have the highest priority, files in <filename>/run</filename>
take precedence over files with the same name in
<filename>/usr/lib</filename>, and the content of
<envar>UDEV_HWDB_PATH</envar> comes last. This order can be
used to override a system-supplied hwdb file with a local file if needed;
a symlink in <filename>/etc</filename> with the same name as a hwdb file in
<filename>/usr/lib</filename>, pointing to <filename>/dev/null</filename>,
Expand Down
6 changes: 5 additions & 1 deletion man/udevadm.8
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,11 @@ Maintain the hardware database index in
.PP
\fB\-u\fR, \fB\-\-update\fR
.RS 4
Compile the hardware database information located in /usr/lib/udev/hwdb\&.d/, /etc/udev/hwdb\&.d/ and store it in
Compile the hardware database information located in
/etc/udev/hwdb\&.d/,
/usr/lib/udev/hwdb\&.d/, and under the
\fBUDEV_HWDB_PATH\fR
path environment variable, and store it in
/etc/udev/hwdb\&.bin\&. This should be done after any update to the source files; it will not be called automatically\&. The running udev daemon will detect a new database on its own and does not need to be notified about it\&.
.RE
.PP
Expand Down
15 changes: 10 additions & 5 deletions man/udevadm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -521,11 +521,16 @@
<term><option>-u</option></term>
<term><option>--update</option></term>
<listitem>
<para>Compile the hardware database information located in /usr/lib/udev/hwdb.d/,
/etc/udev/hwdb.d/ and store it in <filename>/etc/udev/hwdb.bin</filename>. This should be done after
any update to the source files; it will not be called automatically. The running
udev daemon will detect a new database on its own and does not need to be
notified about it.</para>
<para>Compile the hardware database information located in
<filename>/etc/udev/hwdb.d/</filename>,
<filename>/usr/lib/udev/hwdb.d/</filename>, and under the
<envar>UDEV_HWDB_PATH</envar> path environment variable,
and store it in
<filename>/etc/udev/hwdb.bin</filename>. This should be
done after any update to the source files; it will not be
called automatically. The running udev daemon will detect
a new database on its own and does not need to be notified
about it.</para>
</listitem>
</varlistentry>
<varlistentry>
Expand Down
61 changes: 61 additions & 0 deletions src/shared/conf-files.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,64 @@ int conf_files_list_strv(char ***strv, const char *suffix, const char *root, con

return conf_files_list_strv_internal(strv, suffix, root, copy);
}

/* Copy every non-empty path element from path_variable to
destination, and add a final NULL pointer. If destination is NULL,
then only count the number of non-empty path elements. Return
-ENOMEM if the copy failed, or the number of elements. */
static ssize_t conf_files_list_follow_path (const char *path_variable, char **destination) {
/* This function is not using strtok_r, because two passes are
required: the first one to count the number of elements,
the second one to actually copy them once an array of the
correct size has been allocated. */
size_t n = 0;
if (path_variable != NULL) {
while (path_variable[0] == ':') {
path_variable++;
}
while (path_variable[0] != '\0') {
const char *end = strchr(path_variable, ':');
if (end == NULL) {
end = path_variable + strlen(path_variable);
}
if (destination != NULL) {
destination[n] = strndup(path_variable, end - path_variable);
if (destination[n] == NULL) {
return -ENOMEM;
}
}
n++;
path_variable = end;
while (path_variable[0] == ':') {
path_variable++;
}
}
}
if (destination != NULL) {
destination[n] = NULL;
}
return n;
}

/* path is a colon-separated list of directories. */
int conf_files_list_strv_path(char ***strv, const char *suffix, const char *root, const char* path) {
_cleanup_strv_free_ char **copy = NULL;

assert(strv);
assert(suffix);

ssize_t path_length = conf_files_list_follow_path(path, NULL);
if (path_length < 0)
return -ENOMEM;

copy = new0(char *, path_length + 1);
if (!copy)
return -ENOMEM;
ssize_t error = conf_files_list_follow_path(path, copy);
if (error < 0)
return -ENOMEM;

assert (error == path_length);

return conf_files_list_strv_internal(strv, suffix, root, copy);
}
1 change: 1 addition & 0 deletions src/shared/conf-files.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@
#include "macro.h"

int conf_files_list_strv(char ***strv, const char *suffix, const char *root, const char* const* dirs);
int conf_files_list_strv_path(char ***strv, const char *suffix, const char *root, const char* path);
31 changes: 24 additions & 7 deletions src/udev/udevadm-hwdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,17 @@
* Uses a Patricia/radix trie to index all matches for efficient lookup.
*/

static const char * const conf_file_dirs[] = {
UDEV_HWDB_DIR,
UDEV_LIBEXEC_DIR "/hwdb.d",
NULL
};
static char *list_conf_file_path (void) {
static const char *main_hwdb_dir = UDEV_HWDB_DIR;
static const char *libexec_dir = UDEV_LIBEXEC_DIR "/hwdb.d";
const char *path_variable = getenv ("UDEV_HWDB_PATH");
/* UDEV_HWDB_PATH comes last, so that it cannot override
system settings. */
/* System settings can be overriden by putting the files in
/etc. */
/* path_variable may be NULL, strjoin works either way. */
return strjoin(main_hwdb_dir, ":", libexec_dir, ":", path_variable, NULL);
}

/* in-memory trie objects */
struct trie {
Expand Down Expand Up @@ -568,7 +574,12 @@ static void help(void) {
" --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"
" -h,--help\n\n");
" -h,--help\n"
"\n"
"The HWDB is searched in "
UDEV_HWDB_DIR ", " UDEV_LIBEXEC_DIR "/hwdb.d, "
"and the UDEV_HWDB_PATH search path.\n"
"\n");
}

static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
Expand Down Expand Up @@ -677,7 +688,13 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
}
trie->nodes_count++;

err = conf_files_list_strv(&files, ".hwdb", root, conf_file_dirs);
_cleanup_free_ char *conf_file_path = list_conf_file_path ();
if (conf_file_path == NULL) {
rc = EXIT_FAILURE;
goto out;
}
err = conf_files_list_strv_path(&files, ".hwdb", root,
conf_file_path);
if (err < 0) {
log_error_errno(err, "failed to enumerate hwdb files: %m");
rc = EXIT_FAILURE;
Expand Down

0 comments on commit 805c07a

Please sign in to comment.