[PATCH] udev - reverse user query options

Here we get the ability to query with the name of the node instead of
the device path. It uses a linear search over the whole database.

  kay@pim:~/src/udev.kay$ ./udev -q path -n video/webcam0
  /class/video4linux/video0


New version, with better function return codes for error handling.
This commit is contained in:
kay.sievers@vrfy.org 2004-01-19 19:40:32 -08:00 committed by Greg KH
parent 7780509143
commit b2a21a3547
4 changed files with 120 additions and 43 deletions

7
udev.8
View File

@ -50,10 +50,13 @@ will be prepended.
.BI -q " query_type"
Query the database for specified value of a created device node.
Valid types are:
.BR name ", " symlink ", " owner " or " group .
.BR name ", " symlink ", " owner " , " group " or " path.
.TP
.BI -p " sysfs_path"
Specify the sysfs path needed for the query.
Specify the sysfs path of the device to query.
.TP
.BI -n " name"
Specify the name of the node for the device to query.
.TP
.B -d
Dump the whole database.

104
udev.c
View File

@ -83,7 +83,8 @@ static inline char *get_seqnum(void)
return seqnum;
}
static void print_record(char *path, struct udevice *dev)
/* callback for database dump */
static int print_record(char *path, struct udevice *dev)
{
printf("P: %s\n", path);
printf("N: %s\n", dev->name);
@ -91,11 +92,13 @@ static void print_record(char *path, struct udevice *dev)
printf("O: %s\n", dev->owner);
printf("G: %s\n", dev->group);
printf("\n");
return 0;
}
enum query_type {
NONE,
NAME,
PATH,
SYMLINK,
OWNER,
GROUP
@ -103,7 +106,7 @@ enum query_type {
static inline int udev_user(int argc, char **argv)
{
static const char short_options[] = "dp:q:rVh";
static const char short_options[] = "dn:p:q:rVh";
int option;
int retval = -EINVAL;
struct udevice dev;
@ -111,6 +114,7 @@ static inline int udev_user(int argc, char **argv)
enum query_type query = NONE;
char result[NAME_SIZE] = "";
char path[NAME_SIZE] = "";
char name[NAME_SIZE] = "";
/* get command line options */
while (1) {
@ -120,6 +124,11 @@ static inline int udev_user(int argc, char **argv)
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);
@ -148,6 +157,11 @@ static inline int udev_user(int argc, char **argv)
break;
}
if (strcmp(optarg, "path") == 0) {
query = PATH;
break;
}
printf("unknown query type\n");
return -EINVAL;
@ -161,7 +175,7 @@ static inline int udev_user(int argc, char **argv)
printf("unable to open udev database\n");
return -EACCES;
}
retval = udevdb_dump(print_record);
retval = udevdb_call_foreach(print_record);
udevdb_exit();
return retval;
@ -179,44 +193,63 @@ static inline int udev_user(int argc, char **argv)
/* process options */
if (query != NONE) {
if (path[0] == '\0') {
printf("query needs device path specified\n");
return -EINVAL;
}
retval = udevdb_open_ro();
if (retval != 0) {
printf("unable to open udev database\n");
return -EACCES;
}
retval = udevdb_get_dev(path, &dev);
if (retval == 0) {
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 GROUP:
strfieldcpy(result, dev.group);
break;
case OWNER:
strfieldcpy(result, dev.owner);
break;
default:
break;
if (path[0] != '\0') {
retval = udevdb_get_dev(path, &dev);
if (retval != 0) {
printf("device not found in database\n");
goto exit;
}
printf("%s\n", result);
} else {
printf("device not found in udev database\n");
goto print;
}
if (name[0] != '\0') {
retval = udevdb_get_dev_byname(name, 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 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;
}
@ -227,13 +260,16 @@ static inline int udev_user(int argc, char **argv)
}
help:
printf("Usage: [-pqrdVh]\n"
printf("Usage: [-npqrdVh]\n"
" -q TYPE query database for the specified value:\n"
" 'name' name of device node\n"
" 'symlink' pointing to node\n"
" 'owner' of node\n"
" 'group' of node\n"
" 'path' sysfs device path\n"
" -p PATH sysfs device path used for query\n"
" -n NAME node name used for query\n"
"\n"
" -r print udev root\n"
" -d dump whole database\n"
" -V print udev version\n"

View File

@ -143,25 +143,62 @@ int udevdb_open_ro(void)
return 0;
}
void (*user_record_callback) (char *path, struct udevice *dev);
static int (*user_record_callback) (char *path, struct udevice *dev);
static int traverse_callback(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
{
user_record_callback((char*) key.dptr, (struct udevice*) dbuf.dptr);
return 0;
return user_record_callback((char*) key.dptr, (struct udevice*) dbuf.dptr);
}
/**
* udevdb_dump: dumps whole database by passing record data to user function
* udevdb_call_foreach: dumps whole database by passing record data to user function
* @user_record_handler: user function called for every record in the database
*/
int udevdb_dump(void (*user_record_handler) (char *path, struct udevice *dev))
int udevdb_call_foreach(int (*user_record_handler) (char *path, struct udevice *dev))
{
int retval = 0;
if (user_record_handler == NULL) {
dbg("invalid user record handling function");
return -EINVAL;
}
user_record_callback = user_record_handler;
tdb_traverse(udevdb, traverse_callback, NULL);
retval = tdb_traverse(udevdb, traverse_callback, NULL);
if (retval < 0)
return -ENODEV;
else
return 0;
}
static struct udevice *find_dev;
static char *find_path;
static const char *find_name;
static int find_found;
static int find_device_by_name(char *path, struct udevice *dev)
{
if (strncmp(dev->name, find_name, sizeof(dev->name)) == 0) {
memcpy(find_dev, dev, sizeof(*find_dev));
strncpy(find_path, path, NAME_SIZE);
find_found = 1;
/* stop search */
return 1;
}
return 0;
}
/**
* udevdb_get_dev_byname: search device with given name by traversing the whole database
*/
int udevdb_get_dev_byname(const char *name, char *path, struct udevice *dev)
{
find_found = 0;
find_path = path;
find_dev = dev;
find_name = name;
udevdb_call_foreach(find_device_by_name);
if (find_found == 1)
return 0;
else
return -1;
}

View File

@ -12,10 +12,11 @@
extern void udevdb_exit(void);
extern int udevdb_init(int init_flag);
extern int udevdb_open_ro(void);
extern int udevdb_dump(void (*user_record_handler) (char *path, struct udevice *dev));
extern int udevdb_call_foreach(int (*user_record_handler) (char *path, struct udevice *dev));
extern int udevdb_add_dev(const char *path, const struct udevice *dev);
extern int udevdb_get_dev(const char *path, struct udevice *dev);
extern int udevdb_delete_dev(const char *path);
extern int udevdb_get_dev_byname(const char *name, char *path, struct udevice *dev);
#endif /* _UDEVDB_H_ */