From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kay Sievers Date: Mon, 26 Jan 2004 01:49:01 +0000 Subject: [patch] udevinfo - now a real program :) Message-Id: <20040126014901.GA9078@vrfy.org> MIME-Version: 1 Content-Type: multipart/mixed; boundary="ctP54qlpMx3WjD+/" List-Id: To: linux-hotplug@vger.kernel.org --ctP54qlpMx3WjD+/ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 Greg, I want to move the program out of extras/udevinfo to the root folder and include it in the install target. Then we may remove the user mode code from the main udev program and update the man page. What do you think? thanks, Kay --ctP54qlpMx3WjD+/ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline; filename="02-udevinfo.patch" diff -Nru a/extras/udevinfo/Makefile b/extras/udevinfo/Makefile --- a/extras/udevinfo/Makefile Mon Jan 26 02:22:35 2004 +++ b/extras/udevinfo/Makefile Mon Jan 26 02:22:35 2004 @@ -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 diff -Nru a/extras/udevinfo/udevinfo.c b/extras/udevinfo/udevinfo.c --- a/extras/udevinfo/udevinfo.c Mon Jan 26 02:22:35 2004 +++ b/extras/udevinfo/udevinfo.c Mon Jan 26 02:22:35 2004 @@ -23,21 +23,29 @@ #include #include #include +#include +#include +#include + +#include "../../udev.h" +#include "../../udev_version.h" +#include "../../logging.h" +#include "../../udevdb.h" +#include "../../libsysfs/libsysfs.h" -#include "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 @@ 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 @@ 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 \n"); - return -1; - } - path = argv[1]; - /* get the class dev */ class_dev = sysfs_open_class_device_path(path); if (class_dev == NULL) { @@ -156,4 +178,247 @@ 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); } --ctP54qlpMx3WjD+/-- ------------------------------------------------------- The SF.Net email is sponsored by EclipseCon 2004 Premiere Conference on Open Tools Development and Integration See the breadth of Eclipse activity. February 3-5 in Anaheim, CA. http://www.eclipsecon.org/osdn _______________________________________________ Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net Linux-hotplug-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel