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>
This commit is contained in:
Kay Sievers 2005-06-26 18:55:24 +02:00
parent 208f6aba21
commit b8476286d6
11 changed files with 127 additions and 53 deletions

View file

@ -1,4 +1,4 @@
# Makefile for udev_volume_id
# Makefile for ata_id
#
# Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
#

View file

@ -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

View file

@ -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];

1
udev.h
View file

@ -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;

View file

@ -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);

View file

@ -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_ */

View file

@ -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");

View file

@ -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;

View file

@ -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);

View file

@ -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"

View file

@ -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,11 +339,15 @@ int main(int argc, char *argv[], char *envp[])
logging_init("udev");
udev_init_config();
/* disable all logging if not explicitely requested */
if (getenv("UDEV_LOG") == NULL)
udev_log_priority = 0;
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 (udev_log_str == NULL)
udev_log_priority = 0;
/* set signal handlers */
memset(&act, 0x00, sizeof(act));
act.sa_handler = (void (*) (int))sig_handler;
@ -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();