#include "libudev-private.h"
static int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode);
+static struct udev_list_entry *udev_device_add_property_internal(struct udev_device *udev_device, const char *key, const char *value);
/**
* SECTION:libudev-device
udev_device->seqnum = seqnum;
snprintf(num, sizeof(num), "%llu", seqnum);
- udev_device_add_property(udev_device, "SEQNUM", num);
+ udev_device_add_property_internal(udev_device, "SEQNUM", num);
return 0;
}
udev_device->ifindex = ifindex;
snprintf(num, sizeof(num), "%d", ifindex);
- udev_device_add_property(udev_device, "IFINDEX", num);
+ udev_device_add_property_internal(udev_device, "IFINDEX", num);
return 0;
}
return udev_device->devnum;
}
-int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
+static int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
{
char num[32];
udev_device->devnum = devnum;
snprintf(num, sizeof(num), "%u", major(devnum));
- udev_device_add_property(udev_device, "MAJOR", num);
+ udev_device_add_property_internal(udev_device, "MAJOR", num);
snprintf(num, sizeof(num), "%u", minor(devnum));
- udev_device_add_property(udev_device, "MINOR", num);
+ udev_device_add_property_internal(udev_device, "MINOR", num);
return 0;
}
udev_device->devpath_old = strdup(devpath_old);
if (udev_device->devpath_old == NULL)
return -ENOMEM;
- udev_device_add_property(udev_device, "DEVPATH_OLD", udev_device->devpath_old);
+ udev_device_add_property_internal(udev_device, "DEVPATH_OLD", udev_device->devpath_old);
pos = strrchr(udev_device->devpath_old, '/');
if (pos == NULL)
if (udev_device->driver == NULL)
return -ENOMEM;
udev_device->driver_set = true;
- udev_device_add_property(udev_device, "DRIVER", udev_device->driver);
+ udev_device_add_property_internal(udev_device, "DRIVER", udev_device->driver);
return 0;
}
if (udev_device->devtype == NULL)
return -ENOMEM;
udev_device->devtype_set = true;
- udev_device_add_property(udev_device, "DEVTYPE", udev_device->devtype);
+ udev_device_add_property_internal(udev_device, "DEVTYPE", udev_device->devtype);
return 0;
}
-int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
+static int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
{
free(udev_device->subsystem);
udev_device->subsystem = strdup(subsystem);
if (udev_device->subsystem == NULL)
return -ENOMEM;
udev_device->subsystem_set = true;
- udev_device_add_property(udev_device, "SUBSYSTEM", udev_device->subsystem);
+ udev_device_add_property_internal(udev_device, "SUBSYSTEM", udev_device->subsystem);
return 0;
}
udev_device->devnode_mode = mode;
snprintf(num, sizeof(num), "%#o", mode);
- udev_device_add_property(udev_device, "DEVMODE", num);
+ udev_device_add_property_internal(udev_device, "DEVMODE", num);
return 0;
}
udev_device->devnode_uid = uid;
snprintf(num, sizeof(num), "%u", uid);
- udev_device_add_property(udev_device, "DEVUID", num);
+ udev_device_add_property_internal(udev_device, "DEVUID", num);
return 0;
}
udev_device->devnode_gid = gid;
snprintf(num, sizeof(num), "%u", gid);
- udev_device_add_property(udev_device, "DEVGID", num);
+ udev_device_add_property_internal(udev_device, "DEVGID", num);
return 0;
}
-struct udev_list_entry *udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value)
+static struct udev_list_entry *udev_device_add_property_internal(struct udev_device *udev_device, const char *key, const char *value)
{
udev_device->envp_uptodate = false;
if (value == NULL) {
return udev_list_entry_add(&udev_device->properties_list, key, value);
}
+
+int udev_device_add_property(struct udev_device *udev_device, const char *key, const char *value)
+{
+ struct udev_list_entry *property;
+
+ property = udev_device_add_property_internal(udev_device, key, value);
+
+ /* store in db, skip private keys */
+ if (key[0] != '.')
+ udev_list_entry_set_num(property, true);
+
+ return 0;
+}
+
static struct udev_list_entry *udev_device_add_property_from_string(struct udev_device *udev_device, const char *property)
{
char name[UTIL_LINE_SIZE];
val = &val[1];
if (val[0] == '\0')
val = NULL;
- return udev_device_add_property(udev_device, name, val);
+ return udev_device_add_property_internal(udev_device, name, val);
+}
+
+static int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath)
+{
+ const char *pos;
+ size_t len;
+
+ free(udev_device->syspath);
+ udev_device->syspath = strdup(syspath);
+ if (udev_device->syspath == NULL)
+ return -ENOMEM;
+ udev_device->devpath = udev_device->syspath + strlen("/sys");
+ udev_device_add_property_internal(udev_device, "DEVPATH", udev_device->devpath);
+
+ pos = strrchr(udev_device->syspath, '/');
+ if (pos == NULL)
+ return -EINVAL;
+ udev_device->sysname = strdup(&pos[1]);
+ if (udev_device->sysname == NULL)
+ return -ENOMEM;
+
+ /* some devices have '!' in their name, change that to '/' */
+ len = 0;
+ while (udev_device->sysname[len] != '\0') {
+ if (udev_device->sysname[len] == '!')
+ udev_device->sysname[len] = '/';
+ len++;
+ }
+
+ /* trailing number */
+ while (len > 0 && isdigit(udev_device->sysname[--len]))
+ udev_device->sysnum = &udev_device->sysname[len];
+
+ /* sysname is completely numeric */
+ if (len == 0)
+ udev_device->sysnum = NULL;
+
+ return 0;
}
/*
* udev_device_set_info_loaded() needs to be set, to avoid trying
* to use a device without a DEVPATH set
*/
-void udev_device_add_property_from_string_parse(struct udev_device *udev_device, const char *property)
+static void udev_device_add_property_from_string_parse(struct udev_device *udev_device, const char *property)
{
if (startswith(property, "DEVPATH=")) {
char path[UTIL_PATH_SIZE];
}
}
-int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device)
+static int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device)
{
if (udev_device->maj > 0)
udev_device_set_devnum(udev_device, makedev(udev_device->maj, udev_device->min));
return udev_list_entry_get_value(list_entry);
}
-int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
+int udev_device_read_db(struct udev_device *udev_device)
{
char filename[UTIL_PATH_SIZE];
char line[UTIL_LINE_SIZE];
+ const char *id;
FILE *f;
- /* providing a database file will always force-load it */
- if (dbfile == NULL) {
- const char *id;
+ if (udev_device->db_loaded)
+ return 0;
- if (udev_device->db_loaded)
- return 0;
- udev_device->db_loaded = true;
+ udev_device->db_loaded = true;
- id = udev_device_get_id_filename(udev_device);
- if (id == NULL)
- return -1;
- strscpyl(filename, sizeof(filename), "/run/udev/data/", id, NULL);
- dbfile = filename;
- }
+ id = udev_device_get_id_filename(udev_device);
+ if (id == NULL)
+ return -1;
- f = fopen(dbfile, "re");
+ strscpyl(filename, sizeof(filename), "/run/udev/data/", id, NULL);
+
+ f = fopen(filename, "re");
if (f == NULL)
- return log_debug_errno(errno, "no db file to read %s: %m", dbfile);
+ return log_debug_errno(errno, "no db file to read %s: %m", filename);
/* devices with a database entry are initialized */
udev_device->is_initialized = true;
device->info_loaded = true;
}
-struct udev_device *udev_device_new(struct udev *udev)
+static struct udev_device *udev_device_new(struct udev *udev)
{
struct udev_device *udev_device;
if (udev_device == NULL)
return NULL;
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device, NULL);
+ udev_device_read_db(udev_device);
return udev_list_get_entry(&udev_device->devlinks_list);
}
return NULL;
if (!udev_device->info_loaded) {
udev_device_read_uevent_file(udev_device);
- udev_device_read_db(udev_device, NULL);
+ udev_device_read_db(udev_device);
}
if (!udev_device->devlinks_uptodate) {
char symlinks[UTIL_PATH_SIZE];
l = strpcpyl(&s, sizeof(symlinks), udev_list_entry_get_name(list_entry), NULL);
udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))
l = strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry), NULL);
- udev_device_add_property(udev_device, "DEVLINKS", symlinks);
+ udev_device_add_property_internal(udev_device, "DEVLINKS", symlinks);
}
}
if (!udev_device->tags_uptodate) {
l = strpcpyl(&s, sizeof(tags), ":", NULL);
udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
l = strpcpyl(&s, l, udev_list_entry_get_name(list_entry), ":", NULL);
- udev_device_add_property(udev_device, "TAGS", tags);
+ udev_device_add_property_internal(udev_device, "TAGS", tags);
}
}
return udev_list_get_entry(&udev_device->properties_list);
if (udev_device == NULL)
return 0;
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device, NULL);
+ udev_device_read_db(udev_device);
if (udev_device->usec_initialized == 0)
return 0;
now_ts = now(CLOCK_MONOTONIC);
udev_device->usec_initialized = usec_initialized;
snprintf(num, sizeof(num), USEC_FMT, usec_initialized);
- udev_device_add_property(udev_device, "USEC_INITIALIZED", num);
+ udev_device_add_property_internal(udev_device, "USEC_INITIALIZED", num);
}
/**
return udev_list_get_entry(&udev_device->sysattr_list);
}
-int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath)
-{
- const char *pos;
- size_t len;
-
- free(udev_device->syspath);
- udev_device->syspath = strdup(syspath);
- if (udev_device->syspath == NULL)
- return -ENOMEM;
- udev_device->devpath = udev_device->syspath + strlen("/sys");
- udev_device_add_property(udev_device, "DEVPATH", udev_device->devpath);
-
- pos = strrchr(udev_device->syspath, '/');
- if (pos == NULL)
- return -EINVAL;
- udev_device->sysname = strdup(&pos[1]);
- if (udev_device->sysname == NULL)
- return -ENOMEM;
-
- /* some devices have '!' in their name, change that to '/' */
- len = 0;
- while (udev_device->sysname[len] != '\0') {
- if (udev_device->sysname[len] == '!')
- udev_device->sysname[len] = '/';
- len++;
- }
-
- /* trailing number */
- while (len > 0 && isdigit(udev_device->sysname[--len]))
- udev_device->sysnum = &udev_device->sysname[len];
-
- /* sysname is completely numeric */
- if (len == 0)
- udev_device->sysnum = NULL;
-
- return 0;
-}
-
static int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode)
{
free(udev_device->devnode);
}
if (udev_device->devnode == NULL)
return -ENOMEM;
- udev_device_add_property(udev_device, "DEVNAME", udev_device->devnode);
+ udev_device_add_property_internal(udev_device, "DEVNAME", udev_device->devnode);
return 0;
}
_public_ int udev_device_get_is_initialized(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device, NULL);
+ udev_device_read_db(udev_device);
return udev_device->is_initialized;
}
if (udev_device == NULL)
return NULL;
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device, NULL);
+ udev_device_read_db(udev_device);
return udev_list_get_entry(&udev_device->tags_list);
}
if (udev_device == NULL)
return false;
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device, NULL);
+ udev_device_read_db(udev_device);
list_entry = udev_device_get_tags_list_entry(udev_device);
if (udev_list_entry_get_by_name(list_entry, tag) != NULL)
return true;
udev_device->action = strdup(action);
if (udev_device->action == NULL)
return -ENOMEM;
- udev_device_add_property(udev_device, "ACTION", udev_device->action);
+ udev_device_add_property_internal(udev_device, "ACTION", udev_device->action);
return 0;
}
int udev_device_get_devlink_priority(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device, NULL);
+ udev_device_read_db(udev_device);
return udev_device->devlink_priority;
}
int udev_device_get_watch_handle(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device, NULL);
+ udev_device_read_db(udev_device);
return udev_device->watch_handle;
}
int udev_device_rename(struct udev_device *udev_device, const char *name)
{
_cleanup_free_ char *dirname = NULL;
+ const char *interface;
char *new_syspath;
int r;
if (!dirname)
return -ENOMEM;
- new_syspath = strappenda(dirname, "/", name);
+ new_syspath = strjoina(dirname, "/", name);
r = udev_device_set_syspath(udev_device, new_syspath);
if (r < 0)
return r;
+ interface = udev_device_get_property_value(udev_device, "INTERFACE");
+ if (interface) {
+ /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
+ udev_device_add_property_internal(udev_device, "INTERFACE_OLD", interface);
+ udev_device_add_property_internal(udev_device, "INTERFACE", name);
+ }
+
return 0;
}