mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
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:
parent
208f6aba21
commit
b8476286d6
@ -1,4 +1,4 @@
|
||||
# Makefile for udev_volume_id
|
||||
# Makefile for ata_id
|
||||
#
|
||||
# Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
#
|
||||
|
@ -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
|
||||
|
@ -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
1
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;
|
||||
|
@ -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);
|
||||
|
@ -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_ */
|
||||
|
28
udev_rules.c
28
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");
|
||||
|
42
udev_utils.c
42
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;
|
||||
|
@ -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);
|
||||
|
45
udevinfo.c
45
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"
|
||||
|
26
udevstart.c
26
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,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();
|
||||
|
Loading…
Reference in New Issue
Block a user