Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Precompiled hwdb #223

Merged
merged 1 commit into from
May 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions man/udevadm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,15 @@
notified about it.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--usr</option></term>
<listitem>
<para>Put the compiled database into <filename>/usr/lib/udev/hwdb.bin</filename> instead.
Use this if you want to ship a pre-compiled database in immutable system images, or
don't use <filename>/etc/udev/hwdb.d</filename> and want to avoid large binary files in
<filename>/etc</filename>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-t</option></term>
<term><option>--test=<replaceable>string</replaceable></option></term>
Expand Down
1 change: 1 addition & 0 deletions src/libudev/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ AM_CPPFLAGS = \
-DUDEV_CONF_FILE=\"$(udevconffile)\" \
-DUDEV_HWDB_BIN=\"$(udevhwdbbin)\" \
-DUDEV_VERSION=$(UDEV_VERSION) \
-DUDEV_LIBEXEC_DIR=\"$(udevlibexecdir)\" \
-I $(top_srcdir)/src/shared

lib_LTLIBRARIES = \
Expand Down
42 changes: 36 additions & 6 deletions src/libudev/libudev-hwdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ 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";


/**
* udev_hwdb_new:
* @udev: udev library context
Expand All @@ -266,6 +271,7 @@ static int trie_search_f(struct udev_hwdb *hwdb, const char *search) {
**/
_public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
struct udev_hwdb *hwdb;
const char *hwdb_bin_path;
const char sig[] = HWDB_SIG;

hwdb = new0(struct udev_hwdb, 1);
Expand All @@ -275,30 +281,43 @@ _public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) {
hwdb->refcount = 1;
udev_list_init(udev, &hwdb->properties_list, true);

hwdb->f = fopen(UDEV_HWDB_BIN, "re");
/* find hwdb.bin in hwdb_bin_paths */
NULSTR_FOREACH(hwdb_bin_path, hwdb_bin_paths) {
hwdb->f = fopen(hwdb_bin_path, "re");
if (hwdb->f)
break;
else if (errno == ENOENT)
continue;
else {
log_debug("error reading %s", hwdb_bin_path);
udev_hwdb_unref(hwdb);
return NULL;
}
}

if (!hwdb->f) {
log_debug(UDEV_HWDB_BIN " does not exist, please run udevadm hwdb --update");
log_debug("%s does not exist, please run udevadm hwdb --update", hwdb_bin_path);
udev_hwdb_unref(hwdb);
return NULL;
}

if (fstat(fileno(hwdb->f), &hwdb->st) < 0 ||
(size_t)hwdb->st.st_size < offsetof(struct trie_header_f, strings_len) + 8) {
log_debug_errno(errno, "error reading " UDEV_HWDB_BIN ": %m");
log_debug_errno(errno, "error reading %s: %m", hwdb_bin_path);
udev_hwdb_unref(hwdb);
return NULL;
}

hwdb->map = mmap(0, hwdb->st.st_size, PROT_READ, MAP_SHARED, fileno(hwdb->f), 0);
if (hwdb->map == MAP_FAILED) {
log_debug_errno(errno, "error mapping " UDEV_HWDB_BIN ": %m");
log_debug_errno(errno, "error mapping %s: %m", hwdb_bin_path);
udev_hwdb_unref(hwdb);
return NULL;
}

if (memcmp(hwdb->map, sig, sizeof(hwdb->head->signature)) != 0 ||
(size_t)hwdb->st.st_size != le64toh(hwdb->head->file_size)) {
log_debug("error recognizing the format of " UDEV_HWDB_BIN);
log_debug("error recognizing the format of %s", hwdb_bin_path);
udev_hwdb_unref(hwdb);
return NULL;
}
Expand Down Expand Up @@ -352,13 +371,24 @@ _public_ struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb) {
}

bool udev_hwdb_validate(struct udev_hwdb *hwdb) {
bool found = false;
const char* p;
struct stat st;

if (!hwdb)
return false;
if (!hwdb->f)
return false;
if (stat("/etc/udev/hwdb.bin", &st) < 0)

/* if hwdb.bin doesn't exist anywhere, we need to update */
NULSTR_FOREACH(p, hwdb_bin_paths) {
if (stat(p, &st) >= 0) {
found = true;
break;
}
}

if (!found)
return true;

if (timespec_load(&hwdb->st.st_mtim) != timespec_load(&st.st_mtim))
Expand Down
13 changes: 12 additions & 1 deletion src/udev/udevadm-hwdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,21 +564,28 @@ 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"
" --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");
}

static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
enum {
ARG_USR = 0x100,
};

static const struct option options[] = {
{ "update", no_argument, NULL, 'u' },
{ "usr", no_argument, NULL, ARG_USR },
{ "test", required_argument, NULL, 't' },
{ "root", required_argument, NULL, 'r' },
{ "help", no_argument, NULL, 'h' },
{}
};
const char *test = NULL;
const char *root = "";
const char *hwdb_bin_dir = "/etc/udev";
bool update = false;
struct trie *trie = NULL;
int err, c;
Expand All @@ -589,6 +596,9 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
case 'u':
update = true;
break;
case ARG_USR:
hwdb_bin_dir = UDEV_LIBEXEC_DIR;
break;
case 't':
test = optarg;
break;
Expand Down Expand Up @@ -662,7 +672,8 @@ 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);

if (asprintf(&hwdb_bin, "%s/%s", root, hwdb_bin) < 0) {
hwdb_bin = strjoin(root, "/", hwdb_bin_dir, "/hwdb.bin", NULL);
if (!hwdb_bin) {
rc = EXIT_FAILURE;
goto out;
}
Expand Down