chiark / gitweb /
libudev: udev_device - add attribute cache
authorKay Sievers <kay.sievers@vrfy.org>
Sat, 13 Sep 2008 19:09:28 +0000 (21:09 +0200)
committerKay Sievers <kay.sievers@vrfy.org>
Sat, 13 Sep 2008 19:09:28 +0000 (21:09 +0200)
TODO
udev/Makefile.am
udev/lib/exported_symbols
udev/lib/libudev-device.c
udev/lib/libudev-enumerate.c
udev/lib/libudev-private.h
udev/lib/libudev-util.c
udev/lib/libudev.h
udev/udev.h
udev/udev_db.c
udev/udevadm-info.c

diff --git a/TODO b/TODO
index 6c8ef8be782104d45c14fd5f06e4a1c9fb2f19d1..763bcd1fcc1c6153dd3704d9b1ac6c9bc030c351 100644 (file)
--- a/TODO
+++ b/TODO
@@ -10,3 +10,7 @@ These things will change in future udev versions:
   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 "udevadm control" commands will only accept the --<command> syntax
   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
index 62739c05d99bd50c3cb51a9d0525ec3587fe6508..5d47baa0b36e9bc3389c64441b7c766042ad8a7d 100644 (file)
@@ -34,6 +34,7 @@ common_files = \
        lib/libudev.c \
        lib/libudev-device.c \
        lib/libudev-monitor.c \
        lib/libudev.c \
        lib/libudev-device.c \
        lib/libudev-monitor.c \
+       lib/libudev-enumerate.c \
        lib/libudev-util.c \
        lib/libudev-ctrl.c
 
        lib/libudev-util.c \
        lib/libudev-ctrl.c
 
index f53165d810ba94d7a1224c6dd23fb3f5ba433817..aa3854d2aa9876ecc0fc9bb17f8d494d5b7fa46b 100644 (file)
@@ -22,6 +22,7 @@ udev_device_get_action
 udev_device_get_driver
 udev_device_get_devnum
 udev_device_get_seqnum
 udev_device_get_driver
 udev_device_get_devnum
 udev_device_get_seqnum
+udev_device_get_attr_value
 udev_enumerate_devices
 udev_monitor_new_from_socket
 udev_monitor_new_from_netlink
 udev_enumerate_devices
 udev_monitor_new_from_socket
 udev_monitor_new_from_netlink
index f400b621b7e10d611de2f08b5ccca96d2fc91241..cda2de7490e6ef309d94b65a59c4e8c9800b2cdf 100644 (file)
@@ -26,6 +26,7 @@
 #include <errno.h>
 #include <string.h>
 #include <dirent.h>
 #include <errno.h>
 #include <string.h>
 #include <dirent.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 
 #include "libudev.h"
 #include <sys/stat.h>
 
 #include "libudev.h"
@@ -52,6 +53,7 @@ struct udev_device {
        int num_fake_partitions;
        int devlink_priority;
        int ignore_remove;
        int num_fake_partitions;
        int devlink_priority;
        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;
        INIT_LIST_HEAD(&udev_device->link_list);
        INIT_LIST_HEAD(&udev_device->env_list);
        udev_device->udev = udev;
        INIT_LIST_HEAD(&udev_device->link_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);
        return udev_device;
 }
        info(udev_device->udev, "udev_device: %p created\n", 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->devpath_old);
        free(udev_device->physdevpath);
        free(udev_device->driver);
        free(udev_device->devpath_old);
        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);
        free(udev_device);
 }
        info(udev_device->udev, "udev_device: %p released\n", 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)
 {
        if (asprintf(&udev_device->syspath, "%s%s", udev_get_sys_path(udev_device->udev), devpath) < 0)
 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)
@@ -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 0;
 }
 
 int device_add_property(struct udev_device *udev_device, const char *property)
 {
                return -ENOMEM;
        return 0;
 }
 
 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 0;
 }
                return -ENOMEM;
        return 0;
 }
index 9bd910105260dc900b6bad87891e4975971f7c76..95a407652ae1e5b062517a53af38b9d83fd6ec32 100644 (file)
@@ -58,7 +58,7 @@ static int devices_scan_subsystem(struct udev *udev,
                util_strlcat(devpath, "/", sizeof(devpath));
                util_strlcat(devpath, dent->d_name, sizeof(devpath));
                util_resolve_sys_link(udev, devpath, sizeof(devpath));
                util_strlcat(devpath, "/", sizeof(devpath));
                util_strlcat(devpath, dent->d_name, 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);
        return 0;
        }
        closedir(dir);
        return 0;
index 8ca441639fba0ee057ddd629eef61b21a43221c6..c2a32680385712cba06ce3f6c04d34f5d01715f2 100644 (file)
@@ -110,13 +110,14 @@ extern int udev_ctrl_get_set_max_childs(struct udev_ctrl_msg *ctrl_msg);
 struct util_name_entry {
        struct list_head node;
        char *name;
 struct util_name_entry {
        struct list_head node;
        char *name;
+       char *value;
        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_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 struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head *name_list,
        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_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 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 int util_log_priority(const char *priority);
 extern size_t util_path_encode(char *s, size_t len);
 extern void util_name_list_cleanup(struct udev *udev, struct list_head *name_list);
 extern int util_log_priority(const char *priority);
 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_strlcat(char *dst, const char *src, size_t size);
 extern int util_replace_chars(char *str, const char *white);
 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 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
index 7aea8c67fba38ad464895b4889f5bbf397a90403..50eacdd37d760c402b56a1462a8f4708f9b45095 100644 (file)
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <dirent.h>
 #include <ctype.h>
 #include <string.h>
 #include <dirent.h>
 #include <ctype.h>
+#include <fcntl.h>
 #include <sys/stat.h>
 
 #include "libudev.h"
 #include <sys/stat.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_new;
 {
        struct util_name_entry *name_loop;
        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);
                return NULL;
        }
                free(name_new);
                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);
        return name_new;
 }
        list_add_tail(&name_new->node, &name_loop->node);
        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_del(&name_loop->node);
                free(name_loop->name);
        list_for_each_entry_safe(name_loop, name_tmp, name_list, node) {
                list_del(&name_loop->node);
                free(name_loop->name);
+               free(name_loop->value);
                free(name_loop);
        }
 }
                free(name_loop);
        }
 }
index 703364380b081e7b84310a49aa1de5d26fc6768e..05f23e1705211fc655f9461cd19c7292d70a66f9 100644 (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 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 dev_t udev_device_get_devnum(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 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,
                                  int (*cb)(struct udev *udev,
 
 extern int udev_enumerate_devices(struct udev *udev, const char *subsystem,
                                  int (*cb)(struct udev *udev,
index ae50213fd849fd0fbb0971b41cc2f30c8bcb6b1d..55814cee0e7974e8c3f44780859a6aec6db44078 100644 (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_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_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_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 */
 struct name_entry {
 
 /* udev_utils.c */
 struct name_entry {
index 432aa6cbb825bafcc798a539b777be48aeab5f21..4f3dc606e4d12da4336b9e138600720d6821f410 100644 (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;
-}
index 6f0678e9322571bf4e792b2ce2d1837c3dafd816..4a9ebcd014b1d7770272ec53a7983d23d1da5d67 100644 (file)
 
 #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;
        struct dirent *dent;
 
        DIR *dir;
        struct dirent *dent;
 
-       util_strlcpy(path, udev_get_sys_path(udev), sizeof(path));
-       util_strlcat(path, devpath, sizeof(path));
-
-       dir = opendir(path);
+       dir = opendir(udev_device_get_syspath(device));
        if (dir != NULL) {
                for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
                        struct stat statbuf;
                        char filename[UTIL_PATH_SIZE];
        if (dir != NULL) {
                for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
                        struct stat statbuf;
                        char filename[UTIL_PATH_SIZE];
-                       char *attr_value;
-                       char value[UTIL_NAME_SIZE];
+                       const char *value;
                        size_t len;
 
                        if (dent->d_name[0] == '.')
                        size_t len;
 
                        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)
                                continue;
 
                        if (strcmp(dent->d_name, "dev") == 0)
                                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, dent->d_name, sizeof(filename));
                        if (lstat(filename, &statbuf) != 0)
                        util_strlcat(filename, "/", sizeof(filename));
                        util_strlcat(filename, dent->d_name, sizeof(filename));
                        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))
                                continue;
 
                        if (S_ISLNK(statbuf.st_mode))
                                continue;
 
-                       attr_value = sysfs_attr_get_value(udev, devpath, dent->d_name);
-                       if (attr_value == NULL)
+                       value = udev_device_get_attr_value(device, dent->d_name);
+                       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);
 
                        /* skip nonprintable attributes */
                        dbg(udev, "attr '%s'='%s'(%zi)\n", dent->d_name, value, len);
 
                        /* skip nonprintable attributes */
-                       while (len && isprint(value[len-1]))
+                       len = strlen(value);
+                       while (len > 0 && isprint(value[len-1]))
                                len--;
                                len--;
-                       if (len) {
-                               dbg(udev, "attribute value of '%s' non-printable, skip\n", dent->d_name);
+                       if (len > 0) {
+                               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;
        const char *str;
 
        struct udev_device *device_parent;
        const char *str;
 
-       device = udev_device_new_from_devpath(udev, devpath);
-       if (device == NULL)
-               return -1;
-
        printf("\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"
        printf("\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"
@@ -117,7 +105,7 @@ static int print_device_chain(struct udev *udev, const char *devpath)
        if (str == NULL)
                str = "";
        printf("    DRIVER==\"%s\"\n", str);
        if (str == NULL)
                str = "";
        printf("    DRIVER==\"%s\"\n", str);
-       print_all_attributes(udev, udev_device_get_devpath(device), "ATTR");
+       print_all_attributes(device, "ATTR");
 
        device_parent = device;
        do {
 
        device_parent = device;
        do {
@@ -134,53 +122,68 @@ static int print_device_chain(struct udev *udev, const char *devpath)
                if (str == NULL)
                        str = "";
                printf("    DRIVERS==\"%s\"\n", str);
                if (str == NULL)
                        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);
 
-       udev_device_unref(device);
        return 0;
 }
 
        return 0;
 }
 
-static void print_record(struct udevice *udevice)
+static int print_record_devlinks_cb(struct udev_device *device, const char *value, void *data)
 {
 {
-       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);
+       size_t len;
+
+       len = strlen(udev_get_dev_path(udev_device_get_udev(device)));
+       printf("S: %s\n", &value[len+1]);
+       return 0;
 }
 
 }
 
-static void export_db(struct udev *udev)
+static int print_record_properties_cb(struct udev_device *device, const char *key, const char *value, void *data)
 {
 {
-       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);
+       printf("E: %s=%s\n", key, value);
+       return 0;
 }
 
 }
 
-static int lookup_device_by_name(struct udev *udev, struct udevice **udevice, const char *name)
+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);
+       return 0;
+}
+
+static struct udev_device *lookup_device_by_name(struct udev *udev, const char *name)
+{
+#if 0
+       /* FIXME */
        LIST_HEAD(name_list);
        int count;
        struct name_entry *device;
        LIST_HEAD(name_list);
        int count;
        struct name_entry *device;
@@ -224,6 +227,39 @@ next:
 out:
        name_list_cleanup(udev, &name_list);
        return rc;
 out:
        name_list_cleanup(udev, &name_list);
        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 export = 0;
        const char *export_prefix = NULL;
        int root = 0;
        int export = 0;
        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[] = {
                { "name", 1, NULL, 'n' },
 
        static const struct option options[] = {
                { "name", 1, NULL, 'n' },
@@ -284,11 +324,6 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                QUERY_ALL,
        } query = QUERY_NONE;
 
                QUERY_ALL,
        } query = QUERY_NONE;
 
-       char path[UTIL_PATH_SIZE] = "";
-       char name[UTIL_PATH_SIZE] = "";
-       struct name_entry *name_loop;
-       int rc = 0;
-
        while (1) {
                int option;
 
        while (1) {
                int option;
 
@@ -299,42 +334,32 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                dbg(udev, "option '%c'\n", option);
                switch (option) {
                case 'n':
                dbg(udev, "option '%c'\n", option);
                switch (option) {
                case 'n':
+                       if (device != NULL) {
+                               fprintf(stderr, "device already specified\n");
+                               rc = 2;
+                               goto exit;
+                       }
                        /* remove /dev if given */
                        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));
                        else
                                util_strlcpy(name, optarg, sizeof(name));
                        util_remove_trailing_chars(name, '/');
                        /* remove /dev if given */
                        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));
                        else
                                util_strlcpy(name, optarg, sizeof(name));
                        util_remove_trailing_chars(name, '/');
-                       dbg(udev, "name: %s\n", name);
+                       device = lookup_device_by_name(udev, name);
                        break;
                case 'p':
                        break;
                case 'p':
+                       if (device != NULL) {
+                               fprintf(stderr, "device already specified\n");
+                               rc = 2;
+                               goto exit;
+                       }
                        /* remove /sys if given */
                        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));
                        else
                                util_strlcpy(path, optarg, sizeof(path));
                        util_remove_trailing_chars(path, '/');
                        /* remove /sys if given */
                        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));
                        else
                                util_strlcpy(path, optarg, sizeof(path));
                        util_remove_trailing_chars(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);
+                       device = udev_device_new_from_devpath(udev, path);
                        break;
                case 'q':
                        action = ACTION_QUERY;
                        break;
                case 'q':
                        action = ACTION_QUERY;
@@ -374,7 +399,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                        action = ACTION_ATTRIBUTE_WALK;
                        break;
                case 'e':
                        action = ACTION_ATTRIBUTE_WALK;
                        break;
                case 'e':
-                       export_db(udev);
+                       udev_enumerate_devices(udev, NULL, export_all_cb, NULL);
                        goto exit;
                case 'x':
                        export = 1;
                        goto exit;
                case 'x':
                        export = 1;
@@ -411,59 +436,42 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                }
        }
 
                }
        }
 
-       /* run action */
        switch (action) {
        case ACTION_QUERY:
        switch (action) {
        case ACTION_QUERY:
-               /* needs devpath or node/symlink name for query */
-               if (path[0] != '\0') {
-                       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");
+               if (device == NULL) {
+                       fprintf(stderr, "query needs --path= or node --name= specified\n");
                        rc = 4;
                        goto exit;
                }
 
                switch(query) {
                case QUERY_NAME:
                        rc = 4;
                        goto exit;
                }
 
                switch(query) {
                case QUERY_NAME:
-                       if (root)
-                               printf("%s/%s\n", udev_get_dev_path(udev), udevice->name);
-                       else
-                               printf("%s\n", udevice->name);
-                       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) {
+                               printf("%s\n", udev_device_get_devname(device));
+                       } else {
+                               size_t len;
 
 
-                               if (root)
-                                       printf("%s/%s%c", udev_get_dev_path(udev), name_loop->name, c);
-                               else
-                                       printf("%s%c", name_loop->name, c);
+                               len = strlen(udev_get_dev_path(udev));
+                               printf("%s\n", &udev_device_get_devname(device)[len+1]);
                        }
                        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;
                case QUERY_ENV:
                        goto exit;
                case QUERY_ENV:
-                       list_for_each_entry(name_loop, &udevice->env_list, node)
-                               printf("%s\n", name_loop->name);
+                       udev_device_get_properties(device, print_property_cb, NULL);
                        break;
                case QUERY_ALL:
                        break;
                case QUERY_ALL:
-                       print_record(udevice);
+                       print_record(device);
                        break;
                default:
                        fprintf(stderr, "unknown query type\n");
                        break;
                default:
                        fprintf(stderr, "unknown query type\n");
@@ -471,28 +479,12 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
                }
                break;
        case ACTION_ATTRIBUTE_WALK:
                }
                break;
        case ACTION_ATTRIBUTE_WALK:
-               if (path[0] != '\0') {
-                       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 {
+               if (device == NULL) {
                        fprintf(stderr, "attribute walk needs --path or node --name specified\n");
                        rc = 5;
                        goto exit;
                }
                        fprintf(stderr, "attribute walk needs --path or node --name specified\n");
                        rc = 5;
                        goto exit;
                }
+               print_device_chain(device);
                break;
        case ACTION_DEVICE_ID_FILE:
                if (stat_device(name, export, export_prefix) != 0)
                break;
        case ACTION_DEVICE_ID_FILE:
                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;
 }