From b8476286d62c82a1a0bd8de318aa3f7d835222a0 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sun, 26 Jun 2005 18:55:24 +0200 Subject: [PATCH] store the imported device information in the udevdb Any program can query with udevinfo for persistent device attributes evaluated on device discovery now. Signed-off-by: Kay Sievers --- extras/ata_id/Makefile | 2 +- extras/run_directory/Makefile | 4 ++-- extras/volume_id/vol_id.c | 9 +++---- udev.h | 1 + udev_db.c | 9 ++++++- udev_libc_wrapper.h | 13 ++++++---- udev_rules.c | 28 +++++++++++++--------- udev_utils.c | 42 ++++++++++++++++++++++++++++++-- udev_utils.h | 1 + udevinfo.c | 45 +++++++++++++++++++++-------------- udevstart.c | 24 ++++++++++++++----- 11 files changed, 126 insertions(+), 52 deletions(-) diff --git a/extras/ata_id/Makefile b/extras/ata_id/Makefile index ad79a0d8..a19c4b22 100644 --- a/extras/ata_id/Makefile +++ b/extras/ata_id/Makefile @@ -1,4 +1,4 @@ -# Makefile for udev_volume_id +# Makefile for ata_id # # Copyright (C) 2004 Kay Sievers # diff --git a/extras/run_directory/Makefile b/extras/run_directory/Makefile index 12dccf07..0562073c 100644 --- a/extras/run_directory/Makefile +++ b/extras/run_directory/Makefile @@ -1,6 +1,6 @@ -# Makefile for udev_volume_id +# Makefile for run_directory # -# Copyright (C) 2004 Kay Sievers +# Copyright (C) 2005 Kay Sievers # # 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 diff --git a/extras/volume_id/vol_id.c b/extras/volume_id/vol_id.c index 3048fd80..451fd355 100644 --- a/extras/volume_id/vol_id.c +++ b/extras/volume_id/vol_id.c @@ -1,11 +1,8 @@ /* - * udev_volume_id - udev callout to read filesystem label and uuid + * vol_id - udev callout to read filesystem label and uuid * * Copyright (C) 2005 Kay Sievers * - * sample udev rule for creation of a symlink with the filsystem uuid: - * KERNEL="sd*", PROGRAM="/sbin/udev_volume_id -u %N", SYMLINK="%c" - * * 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. @@ -95,7 +92,7 @@ static void set_str(char *to, const unsigned char *from, int count) int main(int argc, char *argv[]) { - const char help[] = "usage: udev_volume_id [--export|-t|-l|-u] \n" + const char help[] = "usage: vol_id [--export|-t|-l|-u] \n" " --export\n" " -t filesystem type\n" " -l filesystem label\n" @@ -114,7 +111,7 @@ int main(int argc, char *argv[]) const char *node = NULL; int rc = 0; - logging_init("udev_volume_id"); + logging_init("vol_id"); for (i = 1 ; i < argc; i++) { char *arg = argv[i]; diff --git a/udev.h b/udev.h index 11fbe024..b5287bb5 100644 --- a/udev.h +++ b/udev.h @@ -69,6 +69,7 @@ struct udevice { dev_t devt; struct list_head run_list; int run_final; + struct list_head env_list; char tmp_node[PATH_SIZE]; int partitions; diff --git a/udev_db.c b/udev_db.c index afbd50e5..264af79d 100644 --- a/udev_db.c +++ b/udev_db.c @@ -86,7 +86,8 @@ int udev_db_add_device(struct udevice *udev) fprintf(f, "M:%u:%u\n", major(udev->devt), minor(udev->devt)); fprintf(f, "A:%u\n", udev->partitions); fprintf(f, "R:%u\n", udev->ignore_remove); - + list_for_each_entry(name_loop, &udev->env_list, node) + fprintf(f, "E:%s\n", name_loop->name); fclose(f); return 0; @@ -149,6 +150,12 @@ static int parse_db_file(struct udevice *udev, const char *filename) strlcpy(line, &bufline[2], count-1); udev->ignore_remove = atoi(line); break; + case 'E': + if (count > sizeof(line)) + count = sizeof(line); + strlcpy(line, &bufline[2], count-1); + name_list_add(&udev->env_list, line, 0); + break; } } file_unmap(buf, bufsize); diff --git a/udev_libc_wrapper.h b/udev_libc_wrapper.h index 4d6d332c..4bb68913 100644 --- a/udev_libc_wrapper.h +++ b/udev_libc_wrapper.h @@ -44,15 +44,18 @@ #include +#ifdef __KLIBC__ +static inline int clearenv(void) +{ + environ[0] = NULL; + return 0; +} +#endif + extern uid_t lookup_user(const char *user); extern gid_t lookup_group(const char *group); -#ifndef strlcat extern size_t strlcpy(char *dst, const char *src, size_t size); -#endif - -#ifndef strlcat extern size_t strlcat(char *dst, const char *src, size_t size); -#endif #endif /* _UDEV_LIBC_WRAPPER_H_ */ diff --git a/udev_rules.c b/udev_rules.c index b81943a1..9b9454e8 100644 --- a/udev_rules.c +++ b/udev_rules.c @@ -174,21 +174,26 @@ static int get_key(char **line, char **key, char **value) linepos++; /* get the value*/ - if (linepos[0] == '\0') - return -1; - if (linepos[0] == '"') { linepos++; temp = strchr(linepos, '"'); - if (!temp) + if (!temp) { + dbg("missing closing quote"); return -1; + } + dbg("value is quoted"); temp[0] = '\0'; } else if (linepos[0] == '\'') { linepos++; temp = strchr(linepos, '\''); - if (!temp) + if (!temp) { + dbg("missing closing quote"); return -1; + } + dbg("value is quoted"); temp[0] = '\0'; + } else if (linepos[0] == '\0') { + dbg("value is empty"); } else { temp = linepos; while (temp[0] && !isspace(temp[0])) @@ -200,7 +205,7 @@ static int get_key(char **line, char **key, char **value) return 0; } -static int import_keys_into_env(const char *buf, size_t bufsize) +static int import_keys_into_env(struct udevice *udev, const char *buf, size_t bufsize) { char line[LINE_SIZE]; const char *bufline; @@ -211,7 +216,7 @@ static int import_keys_into_env(const char *buf, size_t bufsize) size_t count; int lineno; - /* loop through the whole file */ + /* loop through the whole buffer */ lineno = 0; cur = 0; while (cur < bufsize) { @@ -242,6 +247,7 @@ static int import_keys_into_env(const char *buf, size_t bufsize) linepos = line; if (get_key(&linepos, &variable, &value) == 0) { dbg("import '%s=%s'", variable, value); + name_list_key_add(&udev->env_list, variable, value); setenv(variable, value, 1); } } @@ -249,7 +255,7 @@ static int import_keys_into_env(const char *buf, size_t bufsize) return 0; } -static int import_file_into_env(const char *filename) +static int import_file_into_env(struct udevice *udev, const char *filename) { char *buf; size_t bufsize; @@ -258,7 +264,7 @@ static int import_file_into_env(const char *filename) err("can't open '%s'", filename); return -1; } - import_keys_into_env(buf, bufsize); + import_keys_into_env(udev, buf, bufsize); file_unmap(buf, bufsize); return 0; @@ -271,7 +277,7 @@ static int import_program_into_env(struct udevice *udev, const char *program) if (execute_program(program, udev->subsystem, result, sizeof(result), &reslen) != 0) return -1; - return import_keys_into_env(result, reslen); + return import_keys_into_env(udev, result, reslen); } /* finds the lowest positive N such that N isn't present in the udevdb @@ -828,7 +834,7 @@ try_parent: rc = import_program_into_env(udev, import); } else { dbg("import file import='%s'", import); - rc = import_file_into_env(import); + rc = import_file_into_env(udev, import); } if (rc) { dbg(KEY_IMPORT " failed"); diff --git a/udev_utils.c b/udev_utils.c index 9e2e1527..3ab9e433 100644 --- a/udev_utils.c +++ b/udev_utils.c @@ -47,6 +47,7 @@ int udev_init_device(struct udevice *udev, const char* devpath, const char *subs memset(udev, 0x00, sizeof(struct udevice)); INIT_LIST_HEAD(&udev->symlink_list); INIT_LIST_HEAD(&udev->run_list); + INIT_LIST_HEAD(&udev->env_list); if (subsystem) strlcpy(udev->subsystem, subsystem, sizeof(udev->subsystem)); @@ -112,6 +113,10 @@ void udev_cleanup_device(struct udevice *udev) list_del(&name_loop->node); free(name_loop); } + list_for_each_entry_safe(name_loop, temp_loop, &udev->env_list, node) { + list_del(&name_loop->node); + free(name_loop); + } } int string_is_true(const char *str) @@ -303,10 +308,14 @@ int name_list_add(struct list_head *name_list, const char *name, int sort) dbg("'%s' is already in the list", name); return 0; } - if (sort && strcmp(loop_name->name, name) > 0) - break; } + if (sort) + list_for_each_entry(loop_name, name_list, node) { + if (sort && strcmp(loop_name->name, name) > 0) + break; + } + new_name = malloc(sizeof(struct name_entry)); if (new_name == NULL) { dbg("error malloc"); @@ -314,6 +323,35 @@ int name_list_add(struct list_head *name_list, const char *name, int sort) } strlcpy(new_name->name, name, sizeof(new_name->name)); + dbg("adding '%s'", new_name->name); + list_add_tail(&new_name->node, &loop_name->node); + + return 0; +} + +int name_list_key_add(struct list_head *name_list, const char *key, const char *value) +{ + struct name_entry *loop_name; + struct name_entry *new_name; + + list_for_each_entry(loop_name, name_list, node) { + if (strncmp(loop_name->name, key, strlen(key)) == 0) { + dbg("key already present '%s', replace it", loop_name->name); + snprintf(loop_name->name, sizeof(loop_name->name), "%s=%s", key, value); + loop_name->name[sizeof(loop_name->name)-1] = '\0'; + return 0; + } + } + + new_name = malloc(sizeof(struct name_entry)); + if (new_name == NULL) { + dbg("error malloc"); + return -ENOMEM; + } + + snprintf(new_name->name, sizeof(new_name->name), "%s=%s", key, value); + new_name->name[sizeof(new_name->name)-1] = '\0'; + dbg("adding '%s'", new_name->name); list_add_tail(&new_name->node, &loop_name->node); return 0; diff --git a/udev_utils.h b/udev_utils.h index 999a4fcf..655c764f 100644 --- a/udev_utils.h +++ b/udev_utils.h @@ -44,6 +44,7 @@ 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); extern int name_list_add(struct list_head *name_list, const char *name, int sort); +extern int name_list_key_add(struct list_head *name_list, const char *key, const char *value); extern int add_matching_files(struct list_head *name_list, const char *dirname, const char *suffix); extern int execute_program(const char *command, const char *subsystem, char *result, size_t ressize, size_t *reslen); diff --git a/udevinfo.c b/udevinfo.c index 69e5335b..db562eee 100644 --- a/udevinfo.c +++ b/udevinfo.c @@ -92,14 +92,6 @@ static int print_record(struct udevice *udev) return 0; } -enum query_type { - NONE, - NAME, - PATH, - SYMLINK, - ALL, -}; - static int print_device_chain(const char *path) { struct sysfs_class_device *class_dev; @@ -185,7 +177,14 @@ int main(int argc, char *argv[], char *envp[]) struct udevice udev; int root = 0; int attributes = 0; - enum query_type query = NONE; + enum query_type { + QUERY_NONE, + QUERY_NAME, + QUERY_PATH, + QUERY_SYMLINK, + QUERY_ENV, + QUERY_ALL, + } query = QUERY_NONE; char path[PATH_SIZE] = ""; char name[PATH_SIZE] = ""; char temp[PATH_SIZE]; @@ -220,22 +219,27 @@ int main(int argc, char *argv[], char *envp[]) dbg("udev query: %s\n", optarg); if (strcmp(optarg, "name") == 0) { - query = NAME; + query = QUERY_NAME; break; } if (strcmp(optarg, "symlink") == 0) { - query = SYMLINK; + query = QUERY_SYMLINK; break; } if (strcmp(optarg, "path") == 0) { - query = PATH; + query = QUERY_PATH; + break; + } + + if (strcmp(optarg, "env") == 0) { + query = QUERY_ENV; break; } if (strcmp(optarg, "all") == 0) { - query = ALL; + query = QUERY_ALL; break; } @@ -268,7 +272,7 @@ int main(int argc, char *argv[], char *envp[]) } /* process options */ - if (query != NONE) { + if (query != QUERY_NONE) { if (path[0] != '\0') { /* remove sysfs_path if given */ if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) { @@ -317,13 +321,13 @@ int main(int argc, char *argv[], char *envp[]) print: switch(query) { - case NAME: + case QUERY_NAME: if (root) printf("%s/%s\n", udev_root, udev.name); else printf("%s\n", udev.name); goto exit; - case SYMLINK: + case QUERY_SYMLINK: if (list_empty(&udev.symlink_list)) break; if (root) @@ -334,10 +338,14 @@ print: printf("%s ", name_loop->name); printf("\n"); goto exit; - case PATH: + case QUERY_PATH: printf("%s\n", udev.devpath); goto exit; - case ALL: + case QUERY_ENV: + list_for_each_entry(name_loop, &udev.env_list, node) + printf("%s\n", name_loop->name); + goto exit; + case QUERY_ALL: print_record(&udev); goto exit; default: @@ -373,6 +381,7 @@ help: " 'name' name of device node\n" " 'symlink' pointing to node\n" " 'path' sysfs device path\n" + " 'env' the device related imported environment\n" " 'all' all values\n" "\n" " -p PATH sysfs device path used for query or chain\n" diff --git a/udevstart.c b/udevstart.c index b65a28aa..4e922bb7 100644 --- a/udevstart.c +++ b/udevstart.c @@ -45,6 +45,9 @@ #include "udev_utils.h" #include "list.h" +static const char *udev_run_str; +static const char *udev_log_str; + #ifdef USE_LOG void log_message(int priority, const char *format, ...) { @@ -111,8 +114,17 @@ static int add_device(const char *path, const char *subsystem) const char *devpath; devpath = &path[strlen(sysfs_path)]; + + /* clear and set environment for next event */ + clearenv(); + setenv("ACTION", "add", 1); setenv("DEVPATH", devpath, 1); setenv("SUBSYSTEM", subsystem, 1); + setenv("UDEV_START", "1", 1); + if (udev_log_str) + setenv("UDEV_LOG", udev_log_str, 1); + if (udev_run_str) + setenv("UDEV_RUN", udev_run_str, 1); dbg("exec: '%s' (%s)\n", devpath, path); class_dev = sysfs_open_class_device_path(path); @@ -327,10 +339,14 @@ int main(int argc, char *argv[], char *envp[]) logging_init("udev"); udev_init_config(); + dbg("version %s", UDEV_VERSION); + + udev_run_str = getenv("UDEV_RUN"); + udev_log_str = getenv("UDEV_LOG"); + /* disable all logging if not explicitely requested */ - if (getenv("UDEV_LOG") == NULL) + if (udev_log_str == NULL) udev_log_priority = 0; - dbg("version %s", UDEV_VERSION); /* set signal handlers */ memset(&act, 0x00, sizeof(act)); @@ -344,10 +360,6 @@ int main(int argc, char *argv[], char *envp[]) /* trigger timeout to prevent hanging processes */ alarm(ALARM_TIMEOUT); - /* set environment for executed programs */ - setenv("ACTION", "add", 1); - setenv("UDEV_START", "1", 1); - udev_rules_init(); udev_scan_block(); -- 2.39.5