libudev: udev_device - add attribute cache

This commit is contained in:
Kay Sievers 2008-09-13 21:09:28 +02:00
parent b2d9e4f200
commit 93b0f38458
11 changed files with 235 additions and 189 deletions

4
TODO
View file

@ -10,3 +10,7 @@ These things will change in future udev versions:
o "udevadm control" commands will only accept the --<command> syntax o "udevadm control" commands will only accept the --<command> syntax
o symlink names to udevadm will no longer be resolved to old command names o symlink names to udevadm will no longer be resolved to old command names
before next release:
o handle old "device" link in get_parent (CONFIG_SYSFS_DEPRECATED*=y)
o handle "subsystem", "driver", as device
o switch libudev API to syspath instead of devpath

View file

@ -34,6 +34,7 @@ common_files = \
lib/libudev.c \ lib/libudev.c \
lib/libudev-device.c \ lib/libudev-device.c \
lib/libudev-monitor.c \ lib/libudev-monitor.c \
lib/libudev-enumerate.c \
lib/libudev-util.c \ lib/libudev-util.c \
lib/libudev-ctrl.c lib/libudev-ctrl.c

View file

@ -22,6 +22,7 @@ udev_device_get_action
udev_device_get_driver udev_device_get_driver
udev_device_get_devnum udev_device_get_devnum
udev_device_get_seqnum udev_device_get_seqnum
udev_device_get_attr_value
udev_enumerate_devices udev_enumerate_devices
udev_monitor_new_from_socket udev_monitor_new_from_socket
udev_monitor_new_from_netlink udev_monitor_new_from_netlink

View file

@ -26,6 +26,7 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <dirent.h> #include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "libudev.h" #include "libudev.h"
@ -52,6 +53,7 @@ struct udev_device {
int num_fake_partitions; int num_fake_partitions;
int devlink_priority; int devlink_priority;
int ignore_remove; int ignore_remove;
struct list_head attr_list;
}; };
static size_t devpath_to_db_path(struct udev *udev, const char *devpath, char *filename, size_t len) static size_t devpath_to_db_path(struct udev *udev, const char *devpath, char *filename, size_t len)
@ -164,6 +166,7 @@ struct udev_device *device_init(struct udev *udev)
udev_device->udev = udev; udev_device->udev = udev;
INIT_LIST_HEAD(&udev_device->link_list); INIT_LIST_HEAD(&udev_device->link_list);
INIT_LIST_HEAD(&udev_device->env_list); INIT_LIST_HEAD(&udev_device->env_list);
INIT_LIST_HEAD(&udev_device->attr_list);
info(udev_device->udev, "udev_device: %p created\n", udev_device); info(udev_device->udev, "udev_device: %p created\n", udev_device);
return udev_device; return udev_device;
} }
@ -302,6 +305,7 @@ void udev_device_unref(struct udev_device *udev_device)
free(udev_device->driver); free(udev_device->driver);
free(udev_device->devpath_old); free(udev_device->devpath_old);
free(udev_device->physdevpath); free(udev_device->physdevpath);
util_name_list_cleanup(udev_device->udev, &udev_device->attr_list);
info(udev_device->udev, "udev_device: %p released\n", udev_device); info(udev_device->udev, "udev_device: %p released\n", udev_device);
free(udev_device); free(udev_device);
} }
@ -489,6 +493,72 @@ unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device)
return udev_device->seqnum; return udev_device->seqnum;
} }
const char *udev_device_get_attr_value(struct udev_device *udev_device, const char *attr)
{
char path[UTIL_PATH_SIZE];
char value[UTIL_NAME_SIZE];
struct stat statbuf;
int fd;
ssize_t size;
const char *val = NULL;
util_strlcpy(path, udev_device_get_syspath(udev_device), sizeof(path));
util_strlcat(path, "/", sizeof(path));
util_strlcat(path, attr, sizeof(path));
if (lstat(path, &statbuf) != 0) {
info(udev_device->udev, "stat '%s' failed: %s\n", path, strerror(errno));
goto out;
}
if (S_ISLNK(statbuf.st_mode)) {
/* links return the last element of the target path */
char target[UTIL_NAME_SIZE];
int len;
char *pos;
len = readlink(path, target, sizeof(target));
if (len > 0) {
target[len] = '\0';
pos = strrchr(target, '/');
if (pos != NULL) {
pos = &pos[1];
info(udev_device->udev, "cache '%s' with link value '%s'\n", attr, pos);
val = util_name_list_add(udev_device->udev, &udev_device->attr_list, attr, pos, 0)->value;
}
}
goto out;
}
/* skip directories */
if (S_ISDIR(statbuf.st_mode))
goto out;
/* skip non-readable files */
if ((statbuf.st_mode & S_IRUSR) == 0)
goto out;
/* read attribute value */
fd = open(path, O_RDONLY);
if (fd < 0) {
info(udev_device->udev, "attribute '%s' can not be opened\n", path);
goto out;
}
size = read(fd, value, sizeof(value));
close(fd);
if (size < 0)
goto out;
if (size == sizeof(value))
goto out;
/* got a valid value, store and return it */
value[size] = '\0';
util_remove_trailing_chars(value, '\n');
info(udev_device->udev, "'%s' has attribute value '%s'\n", path, value);
val = util_name_list_add(udev_device->udev, &udev_device->attr_list, attr, value, 0)->value;
out:
return val;
}
int device_set_devpath(struct udev_device *udev_device, const char *devpath) int device_set_devpath(struct udev_device *udev_device, const char *devpath)
{ {
if (asprintf(&udev_device->syspath, "%s%s", udev_get_sys_path(udev_device->udev), devpath) < 0) if (asprintf(&udev_device->syspath, "%s%s", udev_get_sys_path(udev_device->udev), devpath) < 0)
@ -518,14 +588,14 @@ int device_set_devname(struct udev_device *udev_device, const char *devname)
int device_add_devlink(struct udev_device *udev_device, const char *devlink) int device_add_devlink(struct udev_device *udev_device, const char *devlink)
{ {
if (util_name_list_add(udev_device->udev, &udev_device->link_list, devlink, 0) == NULL) if (util_name_list_add(udev_device->udev, &udev_device->link_list, devlink, NULL, 0) == NULL)
return -ENOMEM; return -ENOMEM;
return 0; return 0;
} }
int device_add_property(struct udev_device *udev_device, const char *property) int device_add_property(struct udev_device *udev_device, const char *property)
{ {
if (util_name_list_add(udev_device->udev, &udev_device->env_list, property, 0) == NULL) if (util_name_list_add(udev_device->udev, &udev_device->env_list, property, NULL, 0) == NULL)
return -ENOMEM; return -ENOMEM;
return 0; return 0;
} }

View file

@ -58,7 +58,7 @@ static int devices_scan_subsystem(struct udev *udev,
util_strlcat(devpath, "/", sizeof(devpath)); util_strlcat(devpath, "/", sizeof(devpath));
util_strlcat(devpath, dent->d_name, sizeof(devpath)); util_strlcat(devpath, dent->d_name, sizeof(devpath));
util_resolve_sys_link(udev, devpath, sizeof(devpath)); util_resolve_sys_link(udev, devpath, sizeof(devpath));
util_name_list_add(udev, device_list, devpath, 1); util_name_list_add(udev, device_list, devpath, NULL, 1);
} }
closedir(dir); closedir(dir);
return 0; return 0;

View file

@ -110,13 +110,14 @@ extern int udev_ctrl_get_set_max_childs(struct udev_ctrl_msg *ctrl_msg);
struct util_name_entry { struct util_name_entry {
struct list_head node; struct list_head node;
char *name; char *name;
char *value;
int *i; int *i;
}; };
extern ssize_t util_get_sys_subsystem(struct udev *udev, const char *devpath, char *subsystem, size_t size); extern ssize_t util_get_sys_subsystem(struct udev *udev, const char *devpath, char *subsystem, size_t size);
extern ssize_t util_get_sys_driver(struct udev *udev, const char *devpath, char *driver, size_t size); extern ssize_t util_get_sys_driver(struct udev *udev, const char *devpath, char *driver, size_t size);
extern int util_resolve_sys_link(struct udev *udev, char *devpath, size_t size); extern int util_resolve_sys_link(struct udev *udev, char *devpath, size_t size);
extern struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head *name_list, extern struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head *name_list,
const char *name, int sort); const char *name, const char *value, int sort);
extern void util_name_list_cleanup(struct udev *udev, struct list_head *name_list); extern void util_name_list_cleanup(struct udev *udev, struct list_head *name_list);
extern int util_log_priority(const char *priority); extern int util_log_priority(const char *priority);
extern size_t util_path_encode(char *s, size_t len); extern size_t util_path_encode(char *s, size_t len);
@ -125,4 +126,5 @@ extern void util_remove_trailing_chars(char *path, char c);
extern size_t util_strlcpy(char *dst, const char *src, size_t size); extern size_t util_strlcpy(char *dst, const char *src, size_t size);
extern size_t util_strlcat(char *dst, const char *src, size_t size); extern size_t util_strlcat(char *dst, const char *src, size_t size);
extern int util_replace_chars(char *str, const char *white); extern int util_replace_chars(char *str, const char *white);
extern char *util_sysattr_get_value(struct udev *udev, const char *devpath, const char *attr_name);
#endif #endif

View file

@ -27,6 +27,7 @@
#include <string.h> #include <string.h>
#include <dirent.h> #include <dirent.h>
#include <ctype.h> #include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "libudev.h" #include "libudev.h"
@ -97,7 +98,7 @@ int util_resolve_sys_link(struct udev *udev, char *devpath, size_t size)
} }
struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head *name_list, struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head *name_list,
const char *name, int sort) const char *name, const char *value, int sort)
{ {
struct util_name_entry *name_loop; struct util_name_entry *name_loop;
struct util_name_entry *name_new; struct util_name_entry *name_new;
@ -126,7 +127,14 @@ struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head *
free(name_new); free(name_new);
return NULL; return NULL;
} }
dbg(udev, "adding '%s'\n", name_new->name); if (value != NULL) {
name_new->value = strdup(value);
if (name_new->value == NULL) {
free(name_new);
return NULL;
}
}
dbg(udev, "adding '%s=%s'\n", name_new->name, name_new->value);
list_add_tail(&name_new->node, &name_loop->node); list_add_tail(&name_new->node, &name_loop->node);
return name_new; return name_new;
} }
@ -139,6 +147,7 @@ void util_name_list_cleanup(struct udev *udev, struct list_head *name_list)
list_for_each_entry_safe(name_loop, name_tmp, name_list, node) { list_for_each_entry_safe(name_loop, name_tmp, name_list, node) {
list_del(&name_loop->node); list_del(&name_loop->node);
free(name_loop->name); free(name_loop->name);
free(name_loop->value);
free(name_loop); free(name_loop);
} }
} }

View file

@ -67,6 +67,7 @@ extern const char *udev_device_get_driver(struct udev_device *udev_device);
extern dev_t udev_device_get_devnum(struct udev_device *udev_device); extern dev_t udev_device_get_devnum(struct udev_device *udev_device);
extern const char *udev_device_get_action(struct udev_device *udev_device); extern const char *udev_device_get_action(struct udev_device *udev_device);
extern unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device); extern unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device);
extern const char *udev_device_get_attr_value(struct udev_device *udev_device, const char *attr);
extern int udev_enumerate_devices(struct udev *udev, const char *subsystem, extern int udev_enumerate_devices(struct udev *udev, const char *subsystem,
int (*cb)(struct udev *udev, int (*cb)(struct udev *udev,

View file

@ -146,7 +146,6 @@ extern int udev_db_delete_device(struct udevice *udevice);
extern int udev_db_rename(struct udev *udev, const char *devpath_old, const char *devpath); extern int udev_db_rename(struct udev *udev, const char *devpath_old, const char *devpath);
extern int udev_db_get_device(struct udevice *udevice, const char *devpath); extern int udev_db_get_device(struct udevice *udevice, const char *devpath);
extern int udev_db_get_devices_by_name(struct udev *udev, const char *name, struct list_head *name_list); extern int udev_db_get_devices_by_name(struct udev *udev, const char *name, struct list_head *name_list);
extern int udev_db_get_all_entries(struct udev *udevconst, struct list_head *name_list);
/* udev_utils.c */ /* udev_utils.c */
struct name_entry { struct name_entry {

View file

@ -292,36 +292,3 @@ int udev_db_delete_device(struct udevice *udevice)
return 0; return 0;
} }
int udev_db_get_all_entries(struct udev *udev, struct list_head *name_list)
{
char dbpath[PATH_MAX];
DIR *dir;
util_strlcpy(dbpath, udev_get_dev_path(udev), sizeof(dbpath));
util_strlcat(dbpath, "/.udev/db", sizeof(dbpath));
dir = opendir(dbpath);
if (dir == NULL) {
info(udev, "no udev_db available '%s': %s\n", dbpath, strerror(errno));
return -1;
}
while (1) {
struct dirent *ent;
char device[UTIL_PATH_SIZE];
ent = readdir(dir);
if (ent == NULL || ent->d_name[0] == '\0')
break;
if (ent->d_name[0] == '.')
continue;
util_strlcpy(device, ent->d_name, sizeof(device));
util_path_decode(device);
name_list_add(udev, name_list, device, 1);
dbg(udev, "added '%s'\n", device);
}
closedir(dir);
return 0;
}

View file

@ -32,22 +32,17 @@
#include "udev.h" #include "udev.h"
static void print_all_attributes(struct udev *udev, const char *devpath, const char *key) static void print_all_attributes(struct udev_device *device, const char *key)
{ {
char path[UTIL_PATH_SIZE];
DIR *dir; DIR *dir;
struct dirent *dent; struct dirent *dent;
util_strlcpy(path, udev_get_sys_path(udev), sizeof(path)); dir = opendir(udev_device_get_syspath(device));
util_strlcat(path, devpath, sizeof(path));
dir = opendir(path);
if (dir != NULL) { if (dir != NULL) {
for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
struct stat statbuf; struct stat statbuf;
char filename[UTIL_PATH_SIZE]; char filename[UTIL_PATH_SIZE];
char *attr_value; const char *value;
char value[UTIL_NAME_SIZE];
size_t len; size_t len;
if (dent->d_name[0] == '.') if (dent->d_name[0] == '.')
@ -58,7 +53,7 @@ static void print_all_attributes(struct udev *udev, const char *devpath, const c
if (strcmp(dent->d_name, "dev") == 0) if (strcmp(dent->d_name, "dev") == 0)
continue; continue;
util_strlcpy(filename, path, sizeof(filename)); util_strlcpy(filename, udev_device_get_syspath(device), sizeof(filename));
util_strlcat(filename, "/", sizeof(filename)); util_strlcat(filename, "/", sizeof(filename));
util_strlcat(filename, dent->d_name, sizeof(filename)); util_strlcat(filename, dent->d_name, sizeof(filename));
if (lstat(filename, &statbuf) != 0) if (lstat(filename, &statbuf) != 0)
@ -66,19 +61,17 @@ static void print_all_attributes(struct udev *udev, const char *devpath, const c
if (S_ISLNK(statbuf.st_mode)) if (S_ISLNK(statbuf.st_mode))
continue; continue;
attr_value = sysfs_attr_get_value(udev, devpath, dent->d_name); value = udev_device_get_attr_value(device, dent->d_name);
if (attr_value == NULL) if (value == NULL)
continue; continue;
len = util_strlcpy(value, attr_value, sizeof(value));
if(len >= sizeof(value))
len = sizeof(value) - 1;
dbg(udev, "attr '%s'='%s'(%zi)\n", dent->d_name, value, len); dbg(udev, "attr '%s'='%s'(%zi)\n", dent->d_name, value, len);
/* skip nonprintable attributes */ /* skip nonprintable attributes */
while (len && isprint(value[len-1])) len = strlen(value);
while (len > 0 && isprint(value[len-1]))
len--; len--;
if (len) { if (len > 0) {
dbg(udev, "attribute value of '%s' non-printable, skip\n", dent->d_name); dbg(info, "attribute value of '%s' non-printable, skip\n", dent->d_name);
continue; continue;
} }
@ -89,16 +82,11 @@ static void print_all_attributes(struct udev *udev, const char *devpath, const c
printf("\n"); printf("\n");
} }
static int print_device_chain(struct udev *udev, const char *devpath) static int print_device_chain(struct udev_device *device)
{ {
struct udev_device *device;
struct udev_device *device_parent; struct udev_device *device_parent;
const char *str; const char *str;
device = udev_device_new_from_devpath(udev, devpath);
if (device == NULL)
return -1;
printf("\n" printf("\n"
"Udevinfo starts with the device specified by the devpath and then\n" "Udevinfo starts with the device specified by the devpath and then\n"
"walks up the chain of parent devices. It prints for every device\n" "walks up the chain of parent devices. It prints for every device\n"
@ -117,7 +105,7 @@ static int print_device_chain(struct udev *udev, const char *devpath)
if (str == NULL) if (str == NULL)
str = ""; str = "";
printf(" DRIVER==\"%s\"\n", str); printf(" DRIVER==\"%s\"\n", str);
print_all_attributes(udev, udev_device_get_devpath(device), "ATTR"); print_all_attributes(device, "ATTR");
device_parent = device; device_parent = device;
do { do {
@ -134,53 +122,68 @@ static int print_device_chain(struct udev *udev, const char *devpath)
if (str == NULL) if (str == NULL)
str = ""; str = "";
printf(" DRIVERS==\"%s\"\n", str); printf(" DRIVERS==\"%s\"\n", str);
print_all_attributes(udev, udev_device_get_devpath(device_parent), "ATTRS"); print_all_attributes(device_parent, "ATTRS");
} while (device_parent != NULL); } while (device_parent != NULL);
return 0;
}
static int print_record_devlinks_cb(struct udev_device *device, const char *value, void *data)
{
size_t len;
len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
printf("S: %s\n", &value[len+1]);
return 0;
}
static int print_record_properties_cb(struct udev_device *device, const char *key, const char *value, void *data)
{
printf("E: %s=%s\n", key, value);
return 0;
}
static void print_record(struct udev_device *device)
{
size_t len;
int i;
printf("P: %s\n", udev_device_get_devpath(device));
len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
printf("N: %s\n", &udev_device_get_devname(device)[len+1]);
i = device_get_devlink_priority(device);
if (i != 0)
printf("L: %i\n", i);
i = device_get_num_fake_partitions(device);
if (i != 0)
printf("A:%u\n", i);
i = device_get_ignore_remove(device);
if (i != 0)
printf("R:%u\n", i);
udev_device_get_devlinks(device, print_record_devlinks_cb, NULL);
udev_device_get_properties(device, print_record_properties_cb, NULL);
printf("\n");
}
static int export_all_cb(struct udev *udev,
const char *devpath, const char *subsystem, const char *name,
void *data)
{
struct udev_device *device;
device = udev_device_new_from_devpath(udev, devpath);
if (device == NULL)
return 0;
if (udev_device_get_devname(device) != NULL)
print_record(device);
udev_device_unref(device); udev_device_unref(device);
return 0; return 0;
} }
static void print_record(struct udevice *udevice) static struct udev_device *lookup_device_by_name(struct udev *udev, const char *name)
{
struct name_entry *name_loop;
printf("P: %s\n", udevice->dev->devpath);
printf("N: %s\n", udevice->name);
list_for_each_entry(name_loop, &udevice->symlink_list, node)
printf("S: %s\n", name_loop->name);
if (udevice->link_priority != 0)
printf("L: %i\n", udevice->link_priority);
if (udevice->partitions != 0)
printf("A:%u\n", udevice->partitions);
if (udevice->ignore_remove)
printf("R:%u\n", udevice->ignore_remove);
list_for_each_entry(name_loop, &udevice->env_list, node)
printf("E: %s\n", name_loop->name);
}
static void export_db(struct udev *udev)
{
LIST_HEAD(name_list);
struct name_entry *name_loop;
udev_db_get_all_entries(udev, &name_list);
list_for_each_entry(name_loop, &name_list, node) {
struct udevice *udevice_db;
udevice_db = udev_device_init(udev);
if (udevice_db == NULL)
continue;
if (udev_db_get_device(udevice_db, name_loop->name) == 0)
print_record(udevice_db);
printf("\n");
udev_device_cleanup(udevice_db);
}
name_list_cleanup(udev, &name_list);
}
static int lookup_device_by_name(struct udev *udev, struct udevice **udevice, const char *name)
{ {
#if 0
/* FIXME */
LIST_HEAD(name_list); LIST_HEAD(name_list);
int count; int count;
struct name_entry *device; struct name_entry *device;
@ -224,6 +227,39 @@ next:
out: out:
name_list_cleanup(udev, &name_list); name_list_cleanup(udev, &name_list);
return rc; return rc;
#endif
return NULL;
}
static int add_devlink_cb(struct udev_device *device, const char *value, void *data)
{
char **links = data;
if (*links == NULL) {
*links = strdup(value);
} else {
char *str;
asprintf(&str, "%s %s", *links, value);
free(*links);
*links = str;
}
return 0;
}
static int add_devlink_noroot_cb(struct udev_device *device, const char *value, void *data)
{
size_t len;
len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
value = &value[len+1];
return add_devlink_cb(device, value, data);
}
static int print_property_cb(struct udev_device *device, const char *key, const char *value, void *data)
{
printf("%s=%s\n", key, value);
return 0;
} }
static int stat_device(const char *name, int export, const char *prefix) static int stat_device(const char *name, int export, const char *prefix)
@ -247,10 +283,14 @@ static int stat_device(const char *name, int export, const char *prefix)
int udevadm_info(struct udev *udev, int argc, char *argv[]) int udevadm_info(struct udev *udev, int argc, char *argv[])
{ {
struct udevice *udevice = NULL; struct udev_device *device = NULL;
int root = 0; int root = 0;
int export = 0; int export = 0;
const char *export_prefix = NULL; const char *export_prefix = NULL;
char path[UTIL_PATH_SIZE];
char name[UTIL_PATH_SIZE];
char *links;
int rc = 0;
static const struct option options[] = { static const struct option options[] = {
{ "name", 1, NULL, 'n' }, { "name", 1, NULL, 'n' },
@ -284,11 +324,6 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
QUERY_ALL, QUERY_ALL,
} query = QUERY_NONE; } query = QUERY_NONE;
char path[UTIL_PATH_SIZE] = "";
char name[UTIL_PATH_SIZE] = "";
struct name_entry *name_loop;
int rc = 0;
while (1) { while (1) {
int option; int option;
@ -299,42 +334,32 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
dbg(udev, "option '%c'\n", option); dbg(udev, "option '%c'\n", option);
switch (option) { switch (option) {
case 'n': case 'n':
if (device != NULL) {
fprintf(stderr, "device already specified\n");
rc = 2;
goto exit;
}
/* remove /dev if given */ /* remove /dev if given */
if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) == 0) if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) == 0)
util_strlcpy(name, &optarg[strlen(udev_get_dev_path(udev))+1], sizeof(name)); util_strlcpy(name, &optarg[strlen(udev_get_dev_path(udev))+1], sizeof(name));
else else
util_strlcpy(name, optarg, sizeof(name)); util_strlcpy(name, optarg, sizeof(name));
util_remove_trailing_chars(name, '/'); util_remove_trailing_chars(name, '/');
dbg(udev, "name: %s\n", name); device = lookup_device_by_name(udev, name);
break; break;
case 'p': case 'p':
if (device != NULL) {
fprintf(stderr, "device already specified\n");
rc = 2;
goto exit;
}
/* remove /sys if given */ /* remove /sys if given */
if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) == 0) if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) == 0)
util_strlcpy(path, &optarg[strlen(udev_get_sys_path(udev))], sizeof(path)); util_strlcpy(path, &optarg[strlen(udev_get_sys_path(udev))], sizeof(path));
else else
util_strlcpy(path, optarg, sizeof(path)); util_strlcpy(path, optarg, sizeof(path));
util_remove_trailing_chars(path, '/'); util_remove_trailing_chars(path, '/');
device = udev_device_new_from_devpath(udev, path);
/* possibly resolve to real devpath */
if (util_resolve_sys_link(udev, path, sizeof(path)) != 0) {
char temp[UTIL_PATH_SIZE];
char *pos;
/* also check if the parent is a link */
util_strlcpy(temp, path, sizeof(temp));
pos = strrchr(temp, '/');
if (pos != 0) {
char tail[UTIL_PATH_SIZE];
util_strlcpy(tail, pos, sizeof(tail));
pos[0] = '\0';
if (util_resolve_sys_link(udev, temp, sizeof(temp)) == 0) {
util_strlcpy(path, temp, sizeof(path));
util_strlcat(path, tail, sizeof(path));
}
}
}
dbg(udev, "path: %s\n", path);
break; break;
case 'q': case 'q':
action = ACTION_QUERY; action = ACTION_QUERY;
@ -374,7 +399,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
action = ACTION_ATTRIBUTE_WALK; action = ACTION_ATTRIBUTE_WALK;
break; break;
case 'e': case 'e':
export_db(udev); udev_enumerate_devices(udev, NULL, export_all_cb, NULL);
goto exit; goto exit;
case 'x': case 'x':
export = 1; export = 1;
@ -411,59 +436,42 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
} }
} }
/* run action */
switch (action) { switch (action) {
case ACTION_QUERY: case ACTION_QUERY:
/* needs devpath or node/symlink name for query */ if (device == NULL) {
if (path[0] != '\0') { fprintf(stderr, "query needs --path= or node --name= specified\n");
udevice = udev_device_init(udev);
if (udevice == NULL) {
rc = 1;
goto exit;
}
if (udev_db_get_device(udevice, path) != 0) {
fprintf(stderr, "no record for '%s' in database\n", path);
rc = 3;
goto exit;
}
} else if (name[0] != '\0') {
if (lookup_device_by_name(udev, &udevice, name) != 0) {
fprintf(stderr, "node name not found\n");
rc = 4;
goto exit;
}
} else {
fprintf(stderr, "query needs --path or node --name specified\n");
rc = 4; rc = 4;
goto exit; goto exit;
} }
switch(query) { switch(query) {
case QUERY_NAME: case QUERY_NAME:
if (root) if (root) {
printf("%s/%s\n", udev_get_dev_path(udev), udevice->name); printf("%s\n", udev_device_get_devname(device));
else } else {
printf("%s\n", udevice->name); size_t len;
break;
case QUERY_SYMLINK:
list_for_each_entry(name_loop, &udevice->symlink_list, node) {
char c = name_loop->node.next != &udevice->symlink_list ? ' ' : '\n';
if (root) len = strlen(udev_get_dev_path(udev));
printf("%s/%s%c", udev_get_dev_path(udev), name_loop->name, c); printf("%s\n", &udev_device_get_devname(device)[len+1]);
else
printf("%s%c", name_loop->name, c);
} }
break; break;
case QUERY_SYMLINK:
links = NULL;
if (root)
udev_device_get_devlinks(device, add_devlink_cb, &links);
else
udev_device_get_devlinks(device, add_devlink_noroot_cb, &links);
printf("%s\n", links);
free(links);
break;
case QUERY_PATH: case QUERY_PATH:
printf("%s\n", udevice->dev->devpath); printf("%s\n", udev_device_get_devpath(device));
goto exit; goto exit;
case QUERY_ENV: case QUERY_ENV:
list_for_each_entry(name_loop, &udevice->env_list, node) udev_device_get_properties(device, print_property_cb, NULL);
printf("%s\n", name_loop->name);
break; break;
case QUERY_ALL: case QUERY_ALL:
print_record(udevice); print_record(device);
break; break;
default: default:
fprintf(stderr, "unknown query type\n"); fprintf(stderr, "unknown query type\n");
@ -471,28 +479,12 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
} }
break; break;
case ACTION_ATTRIBUTE_WALK: case ACTION_ATTRIBUTE_WALK:
if (path[0] != '\0') { if (device == NULL) {
if (print_device_chain(udev, path) != 0) {
fprintf(stderr, "no valid sysfs device found\n");
rc = 4;
goto exit;
}
} else if (name[0] != '\0') {
if (lookup_device_by_name(udev, &udevice, name) != 0) {
fprintf(stderr, "node name not found\n");
rc = 4;
goto exit;
}
if (print_device_chain(udev, udevice->dev->devpath) != 0) {
fprintf(stderr, "no valid sysfs device found\n");
rc = 4;
goto exit;
}
} else {
fprintf(stderr, "attribute walk needs --path or node --name specified\n"); fprintf(stderr, "attribute walk needs --path or node --name specified\n");
rc = 5; rc = 5;
goto exit; goto exit;
} }
print_device_chain(device);
break; break;
case ACTION_DEVICE_ID_FILE: case ACTION_DEVICE_ID_FILE:
if (stat_device(name, export, export_prefix) != 0) if (stat_device(name, export, export_prefix) != 0)
@ -508,6 +500,6 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
} }
exit: exit:
udev_device_cleanup(udevice); udev_device_unref(device);
return rc; return rc;
} }