Sometimes the administrator wants to override the relevant file in (on Debian:) /lib/udev/keymaps/. It would be convenient if this could be done by creating a separate file under SYSCONFDIR, i.e., under /etc, which would contain only the entries that the admin wants to change. For example, /lib/udev/keymaps/module-lenovo contains 16 lines. Suppose the admin wants to change 0x13 zoom to 0x13 search If he changes /lib/udev/keymaps directly then his changes will be overwritten by his packaging system on the next upgrade of the udev package. So that is not a reasonable course of action. He does have the alternative of adding a udev rules file to (on Debian) /etc/udev/rules.d but this is much less convenient since it has to duplicate significant amounts of udev code from (on Debian) /lib/udev/rules.d/95-keymap.rules. As an example of how support for a "keymap override" file could be added I attach a patch. It has been tested and works on my Ubuntu 11.04 system but I don't know how well it conforms to applicable coding standards. Should "keymap override" support be added to udev? And is my patch anything like the right way to do it? Comments most welcome. -- Thomas Hood
--- extras/keymap/keymap.c_ORIG 2011-07-21 15:01:08.830054279 +0200 +++ extras/keymap/keymap.c 2011-07-21 14:48:45.322209254 +0200 @@ -184,14 +184,15 @@ scancode, k->id); } -static int merge_table(int fd, const char *filename) { +static int merge_table(int fd, const char *filename, int report_fopen_fail) { int r = 0; int line = 0; FILE* f; f = fopen(filename, "r"); if (!f) { - perror(filename); + if (report_fopen_fail) + perror(filename); r = -1; goto fail; } @@ -250,7 +251,7 @@ { static char result[PATH_MAX]; - /* If keymap file is given without a path, assume udev directory; must end with '/' * */ + /* If keymap file is given without a path, assume udev default directory; must end with '/' * */ if (!strchr(path, '/')) { snprintf(result, sizeof(result), "%s%s", LIBEXECDIR "/keymaps/", path); return result; @@ -258,6 +259,18 @@ return path; } +static const char* override_keymap_path(const char* path) +{ + static char result[PATH_MAX]; + + /* If keymap file is given without a path, assume udev override directory; must end with '/' * */ + if (!strchr(path, '/')) { + snprintf(result, sizeof(result), "%s%s", SYSCONFDIR "/udev/keymaps/", path); + return result; + } + return path; +} + /* read one event; return 1 if valid */ static int read_event(int fd, struct input_event* ev) { @@ -424,7 +437,8 @@ /* two arguments (device, mapfile): set map file */ if (argc == optind+2) { - merge_table(fd, default_keymap_path(argv[optind+1])); + merge_table(fd, default_keymap_path(argv[optind+1]), 1); + merge_table(fd, override_keymap_path(argv[optind+1]), 0); return 0; }