const char *sysnum;
char *devnode;
char *subsystem;
+ char *devtype;
char *driver;
char *action;
char *devpath_old;
dev_t devnum;
unsigned int parent_set:1;
unsigned int subsystem_set:1;
+ unsigned int devtype_set:1;
unsigned int devlinks_uptodate:1;
unsigned int envp_uptodate:1;
unsigned int driver_set:1;
devpath_to_db_path(udev_device->udev, udev_device->devpath, filename, sizeof(filename));
if (lstat(filename, &stats) != 0) {
- info(udev_device->udev, "no db file to read %s: %m\n", filename);
+ dbg(udev_device->udev, "no db file to read %s: %m\n", filename);
return -1;
}
if ((stats.st_mode & S_IFMT) == S_IFLNK) {
if (target_len > 0)
target[target_len] = '\0';
else {
- info(udev_device->udev, "error reading db link %s: %m\n", filename);
+ dbg(udev_device->udev, "error reading db link %s: %m\n", filename);
return -1;
}
f = fopen(filename, "r");
if (f == NULL) {
- info(udev_device->udev, "error reading db file %s: %m\n", filename);
+ dbg(udev_device->udev, "error reading db file %s: %m\n", filename);
return -1;
}
while (fgets(line, sizeof(line), f)) {
continue;
pos[0] = '\0';
- if (strncmp(line, "MAJOR=", 6) == 0)
+ if (strncmp(line, "DEVTYPE=", 8) == 0)
+ udev_device_set_devtype(udev_device, &line[8]);
+ else if (strncmp(line, "MAJOR=", 6) == 0)
maj = strtoull(&line[6], NULL, 10);
else if (strncmp(line, "MINOR=", 6) == 0)
min = strtoull(&line[6], NULL, 10);
udev_device_add_property(udev_device,
udev_list_entry_get_name(list_entry),
udev_list_entry_get_value(list_entry));
- info(udev_device->udev, "udev_device: %p created\n", udev_device);
+ dbg(udev_device->udev, "udev_device: %p created\n", udev_device);
return udev_device;
}
subdir = &syspath[len+1];
pos = strrchr(subdir, '/');
if (pos == NULL || pos < &subdir[2]) {
- info(udev, "not a subdir :%s\n", syspath);
+ dbg(udev, "not a subdir :%s\n", syspath);
return NULL;
}
util_strlcpy(file, path, sizeof(file));
util_strlcat(file, "/uevent", sizeof(file));
if (stat(file, &statbuf) != 0) {
- info(udev, "not a device: %s\n", syspath);
+ dbg(udev, "not a device: %s\n", syspath);
return NULL;
}
} else {
/* everything else just needs to be a directory */
if (stat(path, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) {
- info(udev, "directory not found: %s\n", syspath);
+ dbg(udev, "directory not found: %s\n", syspath);
return NULL;
}
}
strncmp(udev_device->devpath, "/block/", 7) == 0) {
util_strlcpy(path, udev_device->syspath, sizeof(path));
util_strlcat(path, "/device", sizeof(path));
- if (util_resolve_sys_link(udev_device->udev, path, sizeof(path)) == 0)
+ if (util_resolve_sys_link(udev_device->udev, path, sizeof(path)) == 0) {
udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path);
- return udev_device_parent;
+ if (udev_device_parent != NULL)
+ return udev_device_parent;
+ }
}
util_strlcpy(path, udev_device->syspath, sizeof(path));
udev_device->parent_device = device_new_from_parent(udev_device);
}
if (udev_device->parent_device != NULL)
- info(udev_device->udev, "returning existing parent %p\n", udev_device->parent_device);
+ dbg(udev_device->udev, "returning existing parent %p\n", udev_device->parent_device);
return udev_device->parent_device;
}
-struct udev_device *udev_device_get_parent_with_subsystem(struct udev_device *udev_device, const char *subsystem)
+struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype)
{
struct udev_device *parent;
+ if (subsystem == NULL)
+ return NULL;
+
parent = udev_device_get_parent(udev_device);
while (parent != NULL) {
const char *parent_subsystem;
+ const char *parent_devtype;
parent_subsystem = udev_device_get_subsystem(parent);
- if (parent_subsystem != NULL && strcmp(parent_subsystem, subsystem) == 0)
- break;
+ if (parent_subsystem != NULL && strcmp(parent_subsystem, subsystem) == 0) {
+ if (devtype == NULL)
+ break;
+ parent_devtype = udev_device_get_devtype(parent);
+ if (parent_devtype != NULL && strcmp(parent_devtype, devtype) == 0)
+ break;
+ }
parent = udev_device_get_parent(parent);
}
return parent;
free(udev_device->sysname);
free(udev_device->devnode);
free(udev_device->subsystem);
+ free(udev_device->devtype);
udev_list_cleanup_entries(udev_device->udev, &udev_device->devlinks_list);
udev_list_cleanup_entries(udev_device->udev, &udev_device->properties_list);
free(udev_device->action);
udev_list_cleanup_entries(udev_device->udev, &udev_device->sysattr_list);
free(udev_device->envp);
free(udev_device->monitor_buf);
- info(udev_device->udev, "udev_device: %p released\n", udev_device);
+ dbg(udev_device->udev, "udev_device: %p released\n", udev_device);
free(udev_device);
}
return udev_device->subsystem;
}
+/**
+ * udev_device_get_devtype:
+ * @udev_device: udev device
+ *
+ * Retrieve the devtype string of the udev device.
+ *
+ * Returns: the devtype name of the udev device, or #NULL if it can not be determined
+ **/
+const char *udev_device_get_devtype(struct udev_device *udev_device)
+{
+ if (udev_device == NULL)
+ return NULL;
+ if (!udev_device->devtype_set) {
+ udev_device->devtype_set = 1;
+ if (!udev_device->info_loaded)
+ udev_device_read_uevent_file(udev_device);
+ }
+ return udev_device->devtype;
+}
+
/**
* udev_device_get_devlinks_list_entry:
* @udev_device: udev device
/* look for possibly already cached result */
udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_device->sysattr_list)) {
if (strcmp(udev_list_entry_get_name(list_entry), sysattr) == 0) {
- info(udev_device->udev, "got '%s' (%s) from cache\n",
- sysattr, udev_list_entry_get_value(list_entry));
+ dbg(udev_device->udev, "got '%s' (%s) from cache\n",
+ sysattr, udev_list_entry_get_value(list_entry));
return udev_list_entry_get_value(list_entry);
}
}
util_strlcat(path, sysattr, sizeof(path));
if (lstat(path, &statbuf) != 0) {
- info(udev_device->udev, "no attribute '%s', keep negative entry\n", path);
+ dbg(udev_device->udev, "no attribute '%s', keep negative entry\n", path);
udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, sysattr, NULL, 0, 0);
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;
+ /* some core links return the last element of the target path */
+ if (strcmp(sysattr, "driver") != 0 &&
+ strcmp(sysattr, "subsystem") != 0 &&
+ strcmp(sysattr, "module") != 0)
+ goto out;
+
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", sysattr, pos);
+ dbg(udev_device->udev, "cache '%s' with link value '%s'\n", sysattr, pos);
list_entry = udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, sysattr, pos, 0, 0);
val = udev_list_entry_get_value(list_entry);
}
/* read attribute value */
fd = open(path, O_RDONLY);
if (fd < 0) {
- info(udev_device->udev, "attribute '%s' can not be opened\n", path);
+ dbg(udev_device->udev, "attribute '%s' can not be opened\n", path);
goto out;
}
size = read(fd, value, sizeof(value));
/* got a valid value, store it in cache and return it */
value[size] = '\0';
util_remove_trailing_chars(value, '\n');
- info(udev_device->udev, "'%s' has attribute value '%s'\n", path, value);
+ dbg(udev_device->udev, "'%s' has attribute value '%s'\n", path, value);
list_entry = udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, sysattr, value, 0, 0);
val = udev_list_entry_get_value(list_entry);
out:
return 0;
}
+int udev_device_set_devtype(struct udev_device *udev_device, const char *devtype)
+{
+ free(udev_device->devtype);
+ udev_device->devtype = strdup(devtype);
+ if (udev_device->devtype == NULL)
+ return -ENOMEM;
+ udev_device->devtype_set = 1;
+ udev_device_add_property(udev_device, "DEVTYPE", udev_device->devtype);
+ return 0;
+}
+
int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode)
{
free(udev_device->devnode);
list_entry = udev_device_get_properties_list_entry(udev_device);
list_entry = udev_list_entry_get_by_name(list_entry, key);
if (list_entry != NULL)
- udev_list_entry_remove(list_entry);
+ udev_list_entry_delete(list_entry);
return NULL;
}
return udev_list_entry_add(udev_device->udev, &udev_device->properties_list, key, value, 1, 0);
return udev_device_add_property(udev_device, name, val);
}
+const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key)
+{
+ struct udev_list_entry *list_entry;
+
+ if (udev_device == NULL)
+ return NULL;
+ if (key == NULL)
+ return NULL;
+
+ list_entry = udev_device_get_properties_list_entry(udev_device);
+ list_entry = udev_list_entry_get_by_name(list_entry, key);
+ return udev_list_entry_get_value(list_entry);
+}
+
#define ENVP_SIZE 128
#define MONITOR_BUF_SIZE 4096
static int update_envp_monitor_buf(struct udev_device *udev_device)
udev_device->envp[i] = NULL;
udev_device->monitor_buf_len = bufpos;
udev_device->envp_uptodate = 1;
- info(udev_device->udev, "filled envp/monitor buffer, %u properties, %zu bytes\n", i, bufpos);
+ dbg(udev_device->udev, "filled envp/monitor buffer, %u properties, %zu bytes\n", i, bufpos);
return 0;
}