mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
allow rules to be compiled to one binary file
All the rule files can be compiled into a single file, which can be mapped into the udev process to avoid parsing the rules with every event. Signed-off-by: Kay Sievers <kay.sievers@suse.de>
This commit is contained in:
parent
c9b8dbfb65
commit
6bf0ffe8fd
11
Makefile
11
Makefile
@ -44,6 +44,7 @@ V=false
|
||||
ROOT = udev
|
||||
DAEMON = udevd
|
||||
SENDER = udevsend
|
||||
COMPILE = udevrulescompile
|
||||
INITSENDER = udevinitsend
|
||||
RECORDER = udeveventrecorder
|
||||
CONTROL = udevcontrol
|
||||
@ -202,7 +203,8 @@ endif
|
||||
# config files automatically generated
|
||||
GEN_CONFIGS = $(LOCAL_CFG_DIR)/udev.conf
|
||||
|
||||
all: $(ROOT) $(SENDER) $(INITSENDER) $(RECORDER) $(CONTROL) $(DAEMON) $(INFO) $(TESTER) $(STARTER) $(GEN_CONFIGS) $(KLCC)
|
||||
all: $(ROOT) $(SENDER) $(COMPILE) $(INITSENDER) $(RECORDER) $(CONTROL) \
|
||||
$(DAEMON) $(COMPILE) $(INFO) $(TESTER) $(STARTER) $(GEN_CONFIGS) $(KLCC)
|
||||
@extras="$(EXTRAS)" ; for target in $$extras ; do \
|
||||
echo $$target ; \
|
||||
$(MAKE) prefix=$(prefix) \
|
||||
@ -268,6 +270,7 @@ $(TESTER).o: $(HEADERS) $(GEN_HEADERS) $(HOST_PROGS) $(KLCC)
|
||||
$(INFO).o: $(HEADERS) $(GEN_HEADERS) $(HOST_PROGS) $(KLCC)
|
||||
$(DAEMON).o: $(HEADERS) $(GEN_HEADERS) $(HOST_PROGS) $(KLCC)
|
||||
$(SENDER).o: $(HEADERS) $(GEN_HEADERS) $(HOST_PROGS) $(KLCC)
|
||||
$(COMPILE).o: $(HEADERS) $(GEN_HEADERS) $(HOST_PROGS) $(KLCC)
|
||||
$(INITSENDER).o: $(GEN_HEADERS) $(HOST_PROGS) $(KLCC)
|
||||
$(RECORDER).o: $(GEN_HEADERS) $(HOST_PROGS) $(KLCC)
|
||||
$(CONTROL).o: $(HEADERS) $( $(HEADERS)GEN_HEADERS) $(HOST_PROGS) $(KLCC)
|
||||
@ -293,6 +296,10 @@ $(SENDER): $(KLCC) $(SENDER).o $(OBJS) udevd.h
|
||||
$(QUIET) $(LD) $(LDFLAGS) -o $@ $(SENDER).o $(OBJS) $(LIB_OBJS)
|
||||
$(QUIET) $(STRIPCMD) $@
|
||||
|
||||
$(COMPILE): $(KLCC) $(COMPILE).o $(OBJS)
|
||||
$(QUIET) $(LD) $(LDFLAGS) -o $@ $(COMPILE).o $(OBJS) $(LIB_OBJS)
|
||||
$(QUIET) $(STRIPCMD) $@
|
||||
|
||||
$(INITSENDER): $(KLCC) $(INITSENDER).o $(OBJS) udevd.h
|
||||
$(QUIET) $(LD) $(LDFLAGS) -o $@ $(INITSENDER).o $(OBJS) $(LIB_OBJS)
|
||||
$(QUIET) $(STRIPCMD) $@
|
||||
@ -316,7 +323,7 @@ clean:
|
||||
-find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
|
||||
| xargs rm -f
|
||||
-rm -f core $(ROOT) $(GEN_HEADERS) $(GEN_CONFIGS) $(GEN_MANPAGES) $(INFO) $(DAEMON) \
|
||||
$(SENDER) $(INITSENDER) $(RECORDER) $(CONTROL) $(TESTER) $(STARTER)
|
||||
$(SENDER) $(COMPILE) $(INITSENDER) $(RECORDER) $(CONTROL) $(TESTER) $(STARTER)
|
||||
-rm -f ccdv
|
||||
$(MAKE) -C klibc SUBDIRS=klibc clean
|
||||
@extras="$(EXTRAS)" ; for target in $$extras ; do \
|
||||
|
0
test/devd_test
Normal file → Executable file
0
test/devd_test
Normal file → Executable file
0
test/net_test
Normal file → Executable file
0
test/net_test
Normal file → Executable file
0
test/replace_test
Normal file → Executable file
0
test/replace_test
Normal file → Executable file
0
test/show_all_devices.sh
Normal file → Executable file
0
test/show_all_devices.sh
Normal file → Executable file
0
test/test.all
Normal file → Executable file
0
test/test.all
Normal file → Executable file
0
test/test.block
Normal file → Executable file
0
test/test.block
Normal file → Executable file
0
test/test.tty
Normal file → Executable file
0
test/test.tty
Normal file → Executable file
0
test/testd.block
Normal file → Executable file
0
test/testd.block
Normal file → Executable file
15
udev_rules.c
15
udev_rules.c
@ -846,7 +846,12 @@ int udev_rules_get_name(struct udevice *udev, struct sysfs_class_device *class_d
|
||||
dbg("udev->kernel_name='%s'", udev->kernel_name);
|
||||
|
||||
/* look for a matching rule to apply */
|
||||
list_for_each_entry(rule, &udev_rule_list, node) {
|
||||
udev_rules_iter_init();
|
||||
while (1) {
|
||||
rule = udev_rules_iter_next();
|
||||
if (rule == NULL)
|
||||
break;
|
||||
|
||||
if (udev->name_set && rule->name_operation != KEY_OP_UNSET) {
|
||||
dbg("node name already set, rule ignored");
|
||||
continue;
|
||||
@ -1000,9 +1005,13 @@ int udev_rules_get_run(struct udevice *udev, struct sysfs_device *sysfs_device)
|
||||
struct udev_rule *rule;
|
||||
|
||||
/* look for a matching rule to apply */
|
||||
list_for_each_entry(rule, &udev_rule_list, node) {
|
||||
dbg("process rule");
|
||||
udev_rules_iter_init();
|
||||
while (1) {
|
||||
rule = udev_rules_iter_next();
|
||||
if (rule == NULL)
|
||||
break;
|
||||
|
||||
dbg("process rule");
|
||||
if (rule->run_operation == KEY_OP_UNSET)
|
||||
continue;
|
||||
|
||||
|
10
udev_rules.h
10
udev_rules.h
@ -123,11 +123,13 @@ struct udev_rule {
|
||||
int config_line;
|
||||
};
|
||||
|
||||
extern struct list_head udev_rule_list;
|
||||
|
||||
extern int udev_rules_init(void);
|
||||
extern int udev_rules_get_name(struct udevice *udev, struct sysfs_class_device *class_dev);
|
||||
extern int udev_rules_get_run(struct udevice *udev, struct sysfs_device *sysfs_device);
|
||||
extern void udev_rules_close(void);
|
||||
|
||||
extern int udev_rules_iter_init(void);
|
||||
extern struct udev_rule *udev_rules_iter_next(void);
|
||||
|
||||
extern int udev_rules_get_name(struct udevice *udev, struct sysfs_class_device *class_dev);
|
||||
extern int udev_rules_get_run(struct udevice *udev, struct sysfs_device *sysfs_device);
|
||||
|
||||
#endif
|
||||
|
@ -37,9 +37,45 @@
|
||||
#include "logging.h"
|
||||
#include "udev_rules.h"
|
||||
|
||||
LIST_HEAD(udev_rule_list);
|
||||
/* rules parsed from .rules files*/
|
||||
static LIST_HEAD(rules_list);
|
||||
static struct list_head *rules_list_current;
|
||||
|
||||
static int add_config_dev(struct udev_rule *rule)
|
||||
/* mapped compiled rules stored on disk */
|
||||
static struct udev_rule *rules_array = NULL;
|
||||
static size_t rules_array_current;
|
||||
static size_t rules_array_size = 0;
|
||||
|
||||
static size_t rules_count = 0;
|
||||
|
||||
int udev_rules_iter_init(void)
|
||||
{
|
||||
rules_list_current = rules_list.next;
|
||||
rules_array_current = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct udev_rule *udev_rules_iter_next(void)
|
||||
{
|
||||
static struct udev_rule *rule;
|
||||
|
||||
if (rules_array) {
|
||||
if (rules_array_current >= rules_count)
|
||||
return NULL;
|
||||
rule = &rules_array[rules_array_current];
|
||||
rules_array_current++;
|
||||
} else {
|
||||
dbg("head=%p current=%p next=%p", &rules_list, rules_list_current, rules_list_current->next);
|
||||
if (rules_list_current == &rules_list)
|
||||
return NULL;
|
||||
rule = list_entry(rules_list_current, struct udev_rule, node);
|
||||
rules_list_current = rules_list_current->next;
|
||||
}
|
||||
return rule;
|
||||
}
|
||||
|
||||
static int add_rule_to_list(struct udev_rule *rule)
|
||||
{
|
||||
struct udev_rule *tmp_rule;
|
||||
|
||||
@ -47,7 +83,7 @@ static int add_config_dev(struct udev_rule *rule)
|
||||
if (tmp_rule == NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(tmp_rule, rule, sizeof(struct udev_rule));
|
||||
list_add_tail(&tmp_rule->node, &udev_rule_list);
|
||||
list_add_tail(&tmp_rule->node, &rules_list);
|
||||
|
||||
dbg("name='%s', symlink='%s', bus='%s', id='%s', "
|
||||
"sysfs_file[0]='%s', sysfs_value[0]='%s', "
|
||||
@ -451,9 +487,9 @@ static int rules_parse(const char *filename)
|
||||
|
||||
rule.config_line = lineno;
|
||||
strlcpy(rule.config_file, filename, sizeof(rule.config_file));
|
||||
retval = add_config_dev(&rule);
|
||||
retval = add_rule_to_list(&rule);
|
||||
if (retval) {
|
||||
dbg("add_config_dev returned with error %d", retval);
|
||||
dbg("add_rule_to_list returned with error %d", retval);
|
||||
continue;
|
||||
error:
|
||||
err("parse error %s, line %d:%d, rule skipped",
|
||||
@ -465,20 +501,47 @@ error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int rules_map(const char *filename)
|
||||
{
|
||||
char *buf;
|
||||
size_t size;
|
||||
|
||||
if (file_map(filename, &buf, &size))
|
||||
return -1;
|
||||
if (size == 0)
|
||||
return -1;
|
||||
rules_array = (struct udev_rule *) buf;
|
||||
rules_array_size = size;
|
||||
rules_count = size / sizeof(struct udev_rule);
|
||||
dbg("found %zi compiled rules", rules_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int udev_rules_init(void)
|
||||
{
|
||||
char comp[PATH_SIZE];
|
||||
struct stat stats;
|
||||
int retval;
|
||||
|
||||
strlcpy(comp, udev_rules_filename, sizeof(comp));
|
||||
strlcat(comp, ".compiled", sizeof(comp));
|
||||
if (stat(comp, &stats) == 0) {
|
||||
dbg("parse compiled rules '%s'", comp);
|
||||
return rules_map(comp);
|
||||
}
|
||||
|
||||
if (stat(udev_rules_filename, &stats) != 0)
|
||||
return -1;
|
||||
|
||||
if ((stats.st_mode & S_IFMT) != S_IFDIR)
|
||||
if ((stats.st_mode & S_IFMT) != S_IFDIR) {
|
||||
dbg("parse single rules file '%s'", udev_rules_filename);
|
||||
retval = rules_parse(udev_rules_filename);
|
||||
else {
|
||||
} else {
|
||||
struct name_entry *name_loop, *name_tmp;
|
||||
LIST_HEAD(name_list);
|
||||
|
||||
dbg("parse rules directory '%s'", udev_rules_filename);
|
||||
retval = add_matching_files(&name_list, udev_rules_filename, RULEFILE_SUFFIX);
|
||||
|
||||
list_for_each_entry_safe(name_loop, name_tmp, &name_list, node) {
|
||||
@ -495,9 +558,11 @@ void udev_rules_close(void)
|
||||
struct udev_rule *rule;
|
||||
struct udev_rule *temp_rule;
|
||||
|
||||
list_for_each_entry_safe(rule, temp_rule, &udev_rule_list, node) {
|
||||
list_del(&rule->node);
|
||||
free(rule);
|
||||
}
|
||||
if (rules_array)
|
||||
file_unmap(rules_array, rules_array_size);
|
||||
else
|
||||
list_for_each_entry_safe(rule, temp_rule, &rules_list, node) {
|
||||
list_del(&rule->node);
|
||||
free(rule);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,7 +247,7 @@ int file_map(const char *filename, char **buf, size_t *bufsize)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void file_unmap(char *buf, size_t bufsize)
|
||||
void file_unmap(void *buf, size_t bufsize)
|
||||
{
|
||||
munmap(buf, bufsize);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ extern int string_is_true(const char *str);
|
||||
extern int parse_get_pair(char **orig_string, char **left, char **right);
|
||||
extern int unlink_secure(const char *filename);
|
||||
extern int file_map(const char *filename, char **buf, size_t *bufsize);
|
||||
extern void file_unmap(char *buf, size_t bufsize);
|
||||
extern void file_unmap(void *buf, size_t bufsize);
|
||||
extern size_t buf_get_line(const char *buf, size_t buflen, size_t cur);
|
||||
extern void remove_trailing_char(char *path, char c);
|
||||
extern void replace_untrusted_chars(char *string);
|
||||
|
127
udevrulescompile.c
Normal file
127
udevrulescompile.c
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* udevrulescompile.c - store already parsed config on disk
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "udev_libc_wrapper.h"
|
||||
#include "udev_sysfs.h"
|
||||
#include "udev.h"
|
||||
#include "udev_version.h"
|
||||
#include "logging.h"
|
||||
#include "udev_rules.h"
|
||||
#include "udev_utils.h"
|
||||
#include "list.h"
|
||||
|
||||
#ifdef USE_LOG
|
||||
void log_message(int priority, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (priority > udev_log_priority)
|
||||
return;
|
||||
|
||||
va_start(args, format);
|
||||
vsyslog(priority, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
struct udev_rule *rule;
|
||||
FILE *f;
|
||||
char comp[PATH_SIZE];
|
||||
char comp_tmp[PATH_SIZE];
|
||||
int retval = 0;
|
||||
|
||||
logging_init("udevrulescompile");
|
||||
udev_init_config();
|
||||
dbg("version %s", UDEV_VERSION);
|
||||
|
||||
strlcpy(comp, udev_rules_filename, sizeof(comp));
|
||||
strlcat(comp, ".compiled", sizeof(comp));
|
||||
strlcpy(comp_tmp, comp, sizeof(comp_tmp));
|
||||
strlcat(comp_tmp, ".tmp", sizeof(comp_tmp));
|
||||
|
||||
/* remove old version, otherwise we would read it
|
||||
* instead of the real rules */
|
||||
unlink(comp);
|
||||
unlink(comp_tmp);
|
||||
|
||||
udev_rules_init();
|
||||
|
||||
f = fopen(comp_tmp, "w");
|
||||
if (f == NULL) {
|
||||
err("unable to create db file '%s'", comp_tmp);
|
||||
unlink(comp_tmp);
|
||||
retval = 1;
|
||||
goto exit;
|
||||
}
|
||||
dbg("storing compiled rules in '%s'", comp_tmp);
|
||||
|
||||
udev_rules_iter_init();
|
||||
while (1) {
|
||||
char *endptr;
|
||||
unsigned long id;
|
||||
|
||||
rule = udev_rules_iter_next();
|
||||
if (rule == NULL)
|
||||
break;
|
||||
|
||||
id = strtoul(rule->owner, &endptr, 10);
|
||||
if (endptr[0] != '\0') {
|
||||
uid_t uid;
|
||||
|
||||
uid = lookup_user(rule->owner);
|
||||
dbg("replacing username='%s' by id=%i", rule->owner, uid);
|
||||
sprintf(rule->owner, "%li", uid);
|
||||
}
|
||||
|
||||
id = strtoul(rule->group, &endptr, 10);
|
||||
if (endptr[0] != '\0') {
|
||||
gid_t gid;
|
||||
|
||||
gid = lookup_group(rule->group);
|
||||
dbg("replacing groupname='%s' by id=%i", rule->group, gid);
|
||||
sprintf(rule->group, "%li", gid);
|
||||
}
|
||||
|
||||
dbg("kernel='%s' name='%s'", rule->kernel, rule->name);
|
||||
fwrite(rule, sizeof(struct udev_rule), 1, f);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dbg("activating compiled rules in '%s'", comp);
|
||||
if (rename(comp_tmp, comp) != 0) {
|
||||
err("unable to write file");
|
||||
unlink(comp);
|
||||
unlink(comp_tmp);
|
||||
retval = 2;
|
||||
}
|
||||
|
||||
exit:
|
||||
logging_close();
|
||||
return retval;
|
||||
}
|
Loading…
Reference in New Issue
Block a user