summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Pitt <martin.pitt@ubuntu.com>2014-10-17 15:01:01 +0200
committerMartin Pitt <martin.pitt@ubuntu.com>2014-10-28 14:28:18 +0100
commit33488f19793dc0a86fdee27266c5319b5b78d695 (patch)
treebdadba036ac69b190d2ee2541c3f762da4698b66 /src
parent2f952a25772a690eb03b6af2ad5998086a03234c (diff)
udev hwdb: Support shipping pre-compiled database in system images
In some cases it is preferable to ship system images with a pre-generated binary hwdb database, to avoid having to build it at runtime, avoid shipping the source hwdb files, or avoid storing large binary files in /etc. So if hwdb.bin does not exist in /etc/udev/, fall back to looking for it in UDEVLIBEXECDIR. This keeps the possibility to add files to /etc/udev/hwdb.d/ and re-generating the database which trumps the one in /usr/lib. Add a new --usr flag to "udevadm hwdb --update" which puts the database into UDEVLIBEXECDIR. Adjust systemd-udev-hwdb-update.service to not generate the file in /etc if we already have it in /usr.
Diffstat (limited to 'src')
-rw-r--r--src/libudev/libudev-hwdb.c42
-rw-r--r--src/udev/udevadm-hwdb.c13
2 files changed, 48 insertions, 7 deletions
diff --git a/src/libudev/libudev-hwdb.c b/src/libudev/libudev-hwdb.c
index 8fb7240401..a1cfc0bd5a 100644
--- a/src/libudev/libudev-hwdb.c
+++ b/src/libudev/libudev-hwdb.c
@@ -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"
+ UDEVLIBEXECDIR "/hwdb.bin\0";
+
+
/**
* udev_hwdb_new:
* @udev: udev library context
@@ -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);
@@ -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("/etc/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 {
+ udev_dbg(udev, "error reading %s: %m", hwdb_bin_path);
+ udev_hwdb_unref(hwdb);
+ return NULL;
+ }
+ }
+
if (!hwdb->f) {
- udev_dbg(udev, "error reading /etc/udev/hwdb.bin: %m");
+ udev_err(udev, "hwdb.bin does not exist, please run udevadm hwdb --update");
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) {
- udev_dbg(udev, "error reading /etc/udev/hwdb.bin: %m");
+ udev_dbg(udev, "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) {
- udev_dbg(udev, "error mapping /etc/udev/hwdb.bin: %m");
+ udev_dbg(udev, "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)) {
- udev_dbg(udev, "error recognizing the format of /etc/udev/hwdb.bin");
+ udev_dbg(udev, "error recognizing the format of %s", hwdb_bin_path);
udev_hwdb_unref(hwdb);
return NULL;
}
@@ -352,14 +371,25 @@ _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))
return true;
return false;
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
index 64273fbe8d..3ca755e2ed 100644
--- a/src/udev/udevadm-hwdb.c
+++ b/src/udev/udevadm-hwdb.c
@@ -536,14 +536,20 @@ 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 " UDEVLIBEXECDIR " 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' },
@@ -551,6 +557,7 @@ 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;
@@ -561,6 +568,9 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
case 'u':
update = true;
break;
+ case ARG_USR:
+ hwdb_bin_dir = UDEVLIBEXECDIR;
+ break;
case 't':
test = optarg;
break;
@@ -634,7 +644,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/etc/udev/hwdb.bin", root) < 0) {
+ hwdb_bin = strjoin(root, "/", hwdb_bin_dir, "/hwdb.bin", NULL);
+ if (!hwdb_bin) {
rc = EXIT_FAILURE;
goto out;
}