-# Makefile for udev_volume_id
+# Makefile for ata_id
#
# Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
#
-# 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
/*
- * 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.
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"
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];
dev_t devt;
struct list_head run_list;
int run_final;
+ struct list_head env_list;
char tmp_node[PATH_SIZE];
int partitions;
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;
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);
#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_ */
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]))
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;
size_t count;
int lineno;
- /* loop through the whole file */
+ /* loop through the whole buffer */
lineno = 0;
cur = 0;
while (cur < 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);
}
}
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;
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;
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
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");
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));
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)
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");
}
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;
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);
return 0;
}
-enum query_type {
- NONE,
- NAME,
- PATH,
- SYMLINK,
- ALL,
-};
-
static int print_device_chain(const char *path)
{
struct sysfs_class_device *class_dev;
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];
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;
}
}
/* 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) {
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)
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:
" '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"
#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, ...)
{
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);
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));
/* 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();