chiark / gitweb /
[PATCH] udevinfo - now a real program :)
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Tue, 27 Jan 2004 02:20:12 +0000 (18:20 -0800)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:13:18 +0000 (21:13 -0700)
I want to make udevinfo the standard query interface, so all the user
features of the main udev are copied in here. It is now capable to:

  o query the database for a given value
  o dump the whole database
  o extract all possible device attributes for a sysfs_device

In addition to the known options of udev it supports the query for the
mode of the device node, and it includes the mode in the database dump:

  udevinfo -d
  P: /class/video4linux/video0
  N: video/webcam0
  M: 0666
  S: camera0 kamera0
  O: 500
  G: 500

It is also a bit more friendly with the pathnames specified for devices or nodes.
We remove the absolute path or add it if neccessary:

  udevinfo -q mode -n video/webcam0
  udevinfo -q mode -n /udev/video/webcam0
  0666

  udevinfo -q mode -p /sys/class/video4linux/video0
  udevinfo -q mode -p /class/video4linux/video0
  udevinfo -q mode -p class/video4linux/video0
  0666

extras/udevinfo/Makefile
extras/udevinfo/udevinfo.c

index f31c8c11e97bb8872f8f2dc8c94180af9ea77112..b740b253319fc0281809ea66aceed41d1e6a76f8 100644 (file)
@@ -1,14 +1,28 @@
 PROG=udevinfo
-LD=$(CC)
-OBJS=udevinfo.o
+OBJS=  ../../udev_config.o \
+       ../../udev-add.o \
+       ../../udev-remove.o \
+       ../../udevdb.o \
+       ../../logging.o \
+       ../../namedev.o  \
+       ../../namedev_parse.o \
+       ../../libsysfs/sysfs_bus.o \
+       ../../libsysfs/sysfs_class.o \
+       ../../libsysfs/sysfs_device.o \
+       ../../libsysfs/sysfs_dir.o \
+       ../../libsysfs/sysfs_driver.o \
+       ../../libsysfs/sysfs_utils.o \
+       ../../libsysfs/dlist.o \
+       ../../tdb/tdb.o \
+       ../../tdb/spinlock.o \
 
-all:   $(PROG)
+all: $(PROG)
 
-clean:
-       rm -f $(PROG) $(OBJS)
+$(PROG): $(PROG).o
+       $(LD) $(LDFLAGS) -o $(PROG) $(PROG).o $(OBJS) -lc
 
-$(PROG):       $(OBJS)
-       $(LD) $(LDFLAGS) -o $(PROG) $(CRT0) $(OBJS) $(SYSFS)
+clean:
+       rm -f $(PROG) $(OBJS) $(PROG).o
 
 me:
        cd ../..; make EXTRAS=extras/udevinfo
index c5934be2d43244eda0bc1816e576d78b16b105ae..3f03901f49451d15fa74f73c46577c4c6a97451d 100644 (file)
 #include <string.h>
 #include <stdio.h>
 #include <ctype.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
 
-#include "libsysfs.h"
+#include "../../udev.h"
+#include "../../udev_version.h"
+#include "../../logging.h"
+#include "../../udevdb.h"
+#include "../../libsysfs/libsysfs.h"
 
 
-# define VALUE_SIZE 200
+# define SYSFS_VALUE_MAX 200
 
 char **main_argv;
+int main_argc;
 char **main_envp;
 
-static int print_all_attributes(char *path)
+static int print_all_attributes(const char *path)
 {
        struct dlist *attributes;
        struct sysfs_attribute *attr;
        struct sysfs_directory *sysfs_dir;
-       char value[VALUE_SIZE];
+       char value[SYSFS_VALUE_MAX];
        int len;
        int retval = 0;
 
@@ -53,7 +61,7 @@ static int print_all_attributes(char *path)
 
        dlist_for_each_data(attributes, attr, struct sysfs_attribute) {
                if (attr->value != NULL) {
-                       strncpy(value, attr->value, VALUE_SIZE);
+                       strncpy(value, attr->value, SYSFS_VALUE_MAX);
                        len = strlen(value);
                        if (len == 0)
                                continue;
@@ -82,24 +90,38 @@ exit:
        return retval;
 }
 
-int main(int argc, char **argv, char **envp)
+/* callback for database dump */
+static int print_record(char *path, struct udevice *dev)
+{
+       printf("P: %s\n", path);
+       printf("N: %s\n", dev->name);
+       printf("M: %#o\n", dev->mode);
+       printf("S: %s\n", dev->symlink);
+       printf("O: %s\n", dev->owner);
+       printf("G: %s\n", dev->group);
+       printf("\n");
+       return 0;
+}
+
+enum query_type {
+       NONE,
+       NAME,
+       PATH,
+       SYMLINK,
+       MODE,
+       OWNER,
+       GROUP
+};
+
+static int print_device_chain(const char *path)
 {
-       main_argv = argv;
-       main_envp = envp;
        struct sysfs_class_device *class_dev;
        struct sysfs_class_device *class_dev_parent;
        struct sysfs_attribute *attr;
        struct sysfs_device *sysfs_dev;
        struct sysfs_device *sysfs_dev_parent;
-       char *path;
        int retval = 0;
 
-       if (argc != 2) {
-               printf("Usage: udevinfo <sysfs_device_path>\n");
-               return -1;
-       }
-       path = argv[1];
-
        /*  get the class dev */
        class_dev = sysfs_open_class_device_path(path);
        if (class_dev == NULL) {
@@ -157,3 +179,246 @@ exit:
        //sysfs_close_class_device(class_dev);
        return retval;
 }
+
+static int process_options(void)
+{
+       static const char short_options[] = "adn:p:q:rVh";
+       int option;
+       int retval = 1;
+       struct udevice dev;
+       int root = 0;
+       int attributes = 0;
+       enum query_type query = NONE;
+       char result[NAME_SIZE] = "";
+       char path[NAME_SIZE] = "";
+       char name[NAME_SIZE] = "";
+       char temp[NAME_SIZE];
+       char *pos;
+
+       /* get command line options */
+       while (1) {
+               option = getopt(main_argc, main_argv, short_options);
+               if (option == -1)
+                       break;
+
+               dbg("option '%c'", option);
+               switch (option) {
+               case 'n':
+                       dbg("udev name: %s\n", optarg);
+                       strfieldcpy(name, optarg);
+                       break;
+
+               case 'p':
+                       dbg("udev path: %s\n", optarg);
+                       strfieldcpy(path, optarg);
+                       break;
+
+               case 'q':
+                       dbg("udev query: %s\n", optarg);
+
+                       if (strcmp(optarg, "name") == 0) {
+                               query = NAME;
+                               break;
+                       }
+
+                       if (strcmp(optarg, "symlink") == 0) {
+                               query = SYMLINK;
+                               break;
+                       }
+
+                       if (strcmp(optarg, "mode") == 0) {
+                               query = MODE;
+                               break;
+                       }
+
+                       if (strcmp(optarg, "owner") == 0) {
+                               query = OWNER;
+                               break;
+                       }
+
+                       if (strcmp(optarg, "group") == 0) {
+                               query = GROUP;
+                               break;
+                       }
+
+                       if (strcmp(optarg, "path") == 0) {
+                               query = PATH;
+                               break;
+                       }
+
+                       printf("unknown query type\n");
+                       exit(1);
+
+               case 'r':
+                       root = 1;
+                       break;
+
+               case 'a':
+                       attributes = 1;
+                       break;
+
+               case 'd':
+                       retval = udevdb_open_ro();
+                       if (retval != 0) {
+                               printf("unable to open udev database\n");
+                               exit(2);
+                       }
+                       udevdb_call_foreach(print_record);
+                       udevdb_exit();
+                       exit(0);
+
+               case 'V':
+                       printf("udev, version %s\n", UDEV_VERSION);
+                       exit(0);
+
+               case 'h':
+                       retval = 0;
+               case '?':
+               default:
+                       goto help;
+               }
+       }
+
+       /* process options */
+       if (query != NONE) {
+               retval = udevdb_open_ro();
+               if (retval != 0) {
+                       printf("unable to open udev database\n");
+                       return -EACCES;
+               }
+
+               if (path[0] != '\0') {
+                       /* remove sysfs_path if given */
+                       if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
+                               pos = path + strlen(sysfs_path);
+                       } else {
+                               if (path[0] != '/') {
+                                       /* prepend '/' if missing */
+                                       strcat(temp, "/");
+                                       strncat(temp, path, sizeof(path));
+                                       pos = temp;
+                               } else {
+                                       pos = path;
+                               }
+                       }
+                       retval = udevdb_get_dev(pos, &dev);
+                       if (retval != 0) {
+                               printf("device not found in database\n");
+                               goto exit;
+                       }
+                       goto print;
+               }
+
+               if (name[0] != '\0') {
+                       /* remove udev_root if given */
+                       if (strncmp(name, udev_root, strlen(udev_root)) == 0) {
+                               pos = name + strlen(udev_root);
+                       } else
+                               pos = name;
+                       retval = udevdb_get_dev_byname(pos, path, &dev);
+                       if (retval != 0) {
+                               printf("device not found in database\n");
+                               goto exit;
+                       }
+                       goto print;
+               }
+
+               printf("query needs device path(-p) or node name(-n) specified\n");
+               goto exit;
+
+print:
+               switch(query) {
+               case NAME:
+                       if (root)
+                               strfieldcpy(result, udev_root);
+                       strncat(result, dev.name, sizeof(result));
+                       break;
+
+               case SYMLINK:
+                       strfieldcpy(result, dev.symlink);
+                       break;
+
+               case MODE:
+                       sprintf(result, "%#o", dev.mode);
+                       break;
+
+               case GROUP:
+                       strfieldcpy(result, dev.group);
+                       break;
+
+               case OWNER:
+                       strfieldcpy(result, dev.owner);
+                       break;
+
+               case PATH:
+                       strfieldcpy(result, path);
+                       break;
+
+               default:
+                       goto exit;
+               }
+               printf("%s\n", result);
+
+exit:
+               udevdb_exit();
+               return retval;
+       }
+
+       if (attributes) {
+               if (path[0] == '\0') {
+                       printf("attribute walk on device chain needs path(-p) specified\n");
+                       return -EINVAL;
+               } else {
+                       if (strncmp(path, sysfs_path, strlen(sysfs_path)) != 0) {
+                               /* prepend sysfs mountpoint if not given */
+                               strfieldcpy(temp, path);
+                               strfieldcpy(path, sysfs_path);
+                               strncat(path, temp, sizeof(path));
+                       }
+                       print_device_chain(path);
+                       return 0;
+               }
+       }
+
+       if (root) {
+               printf("%s\n", udev_root);
+               return 0;
+       }
+
+help:
+       printf("Usage: [-anpqrdVh]\n"
+              "  -q TYPE  query database for the specified value:\n"
+              "             'name'    name of device node\n"
+              "             'symlink' pointing to node\n"
+              "             'mode'    permissions of node\n"
+              "             'owner'   of node\n"
+              "             'group'   of node\n"
+              "             'path'    sysfs device path\n"
+              "  -p PATH  sysfs device path used for query or chain\n"
+              "  -n NAME  node name used for query\n"
+              "\n"
+              "  -r       print udev root\n"
+              "  -a       print all attributes along the chain of the device\n"
+              "  -d       dump whole database\n"
+              "  -V       print udev version\n"
+              "  -h       print this help text\n"
+              "\n");
+       return retval;
+}
+
+int main(int argc, char *argv[], char *envp[])
+{
+       int retval;
+
+       main_argv = argv;
+       main_argc = argc;
+       main_envp = envp;
+
+       /* initialize our configuration */
+       udev_init_config();
+
+       retval = process_options();
+       if (retval != 0)
+               exit(1);
+       exit(0);
+}