Skip to content

Commit

Permalink
Merge pull request #223 from bbonev/precompiled_hwdb
Browse files Browse the repository at this point in the history
Precompiled hwdb
  • Loading branch information
bbonev authored May 31, 2022
2 parents 68fd2f5 + b11e438 commit cd61841
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 7 deletions.
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

0 comments on commit cd61841

Please sign in to comment.