summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@suse.de>2005-06-26 18:55:24 +0200
committerKay Sievers <kay.sievers@suse.de>2005-06-26 18:55:24 +0200
commitb8476286d62c82a1a0bd8de318aa3f7d835222a0 (patch)
tree37d3071c2767f819440083e34c5e68efde584b60
parent208f6aba21199ff4f93002eeb948d564f76843e6 (diff)
downloadsystemd-b8476286d62c82a1a0bd8de318aa3f7d835222a0.tar.gz
systemd-b8476286d62c82a1a0bd8de318aa3f7d835222a0.tar.bz2
systemd-b8476286d62c82a1a0bd8de318aa3f7d835222a0.zip
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 <kay.sievers@suse.de>
-rw-r--r--extras/ata_id/Makefile2
-rw-r--r--extras/run_directory/Makefile4
-rw-r--r--extras/volume_id/vol_id.c9
-rw-r--r--udev.h1
-rw-r--r--udev_db.c9
-rw-r--r--udev_libc_wrapper.h13
-rw-r--r--udev_rules.c28
-rw-r--r--udev_utils.c42
-rw-r--r--udev_utils.h1
-rw-r--r--udevinfo.c45
-rw-r--r--udevstart.c24
11 files changed, 126 insertions, 52 deletions
diff --git a/extras/ata_id/Makefile b/extras/ata_id/Makefile
index ad79a0d836..a19c4b2289 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 <kay.sievers@vrfy.org>
#
diff --git a/extras/run_directory/Makefile b/extras/run_directory/Makefile
index 12dccf0749..0562073c8f 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 <kay.sievers@vrfy.org>
+# 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
diff --git a/extras/volume_id/vol_id.c b/extras/volume_id/vol_id.c
index 3048fd8062..451fd355c1 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 <kay.sievers@vrfy.org>
*
- * 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] <device>\n"
+ const char help[] = "usage: vol_id [--export|-t|-l|-u] <device>\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 11fbe02460..b5287bb53f 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 afbd50e50f..264af79d06 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 4d6d332c69..4bb68913a9 100644
--- a/udev_libc_wrapper.h
+++ b/udev_libc_wrapper.h
@@ -44,15 +44,18 @@
#include <string.h>
+#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 b81943a17c..9b9454e8fb 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 <name>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 9e2e152763..3ab9e43348 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 999a4fcf55..655c764fc8 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 69e5335b7c..db562eee49 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 b65a28aab6..4e922bb716 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();