chiark / gitweb /
libudev: introduce clone_with_db()
[elogind.git] / src / libudev / libudev-device.c
index d0296b7ccb5be1ad136a0849cf24675e4845a99c..c0a061af6c808d6d505fc13f0182fcf41d4145c9 100644 (file)
@@ -37,6 +37,7 @@
 #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
@@ -123,7 +124,7 @@ static int udev_device_set_seqnum(struct udev_device *udev_device, unsigned long
 
         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;
 }
 
@@ -140,7 +141,7 @@ static int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
 
         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;
 }
 
@@ -168,9 +169,9 @@ static int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
         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;
 }
 
@@ -187,7 +188,7 @@ static int udev_device_set_devpath_old(struct udev_device *udev_device, const ch
         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)
@@ -224,7 +225,7 @@ static int udev_device_set_driver(struct udev_device *udev_device, const char *d
         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;
 }
 
@@ -254,7 +255,7 @@ static int udev_device_set_devtype(struct udev_device *udev_device, const char *
         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;
 }
 
@@ -265,7 +266,7 @@ static int udev_device_set_subsystem(struct udev_device *udev_device, const char
         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;
 }
 
@@ -323,7 +324,7 @@ static int udev_device_set_devnode_mode(struct udev_device *udev_device, mode_t
 
         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;
 }
 
@@ -340,7 +341,7 @@ static int udev_device_set_devnode_uid(struct udev_device *udev_device, uid_t ui
 
         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;
 }
 
@@ -357,11 +358,11 @@ static int udev_device_set_devnode_gid(struct udev_device *udev_device, gid_t gi
 
         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) {
@@ -376,6 +377,20 @@ struct udev_list_entry *udev_device_add_property(struct udev_device *udev_device
         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];
@@ -389,7 +404,7 @@ static struct udev_list_entry *udev_device_add_property_from_string(struct udev_
         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)
@@ -402,7 +417,7 @@ static int udev_device_set_syspath(struct udev_device *udev_device, const char *
         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);
+        udev_device_add_property_internal(udev_device, "DEVPATH", udev_device->devpath);
 
         pos = strrchr(udev_device->syspath, '/');
         if (pos == NULL)
@@ -550,30 +565,27 @@ _public_ const char *udev_device_get_property_value(struct udev_device *udev_dev
         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;
@@ -1291,7 +1303,7 @@ _public_ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev
         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);
 }
 
@@ -1319,7 +1331,7 @@ _public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct ud
                 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];
@@ -1335,7 +1347,7 @@ _public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct ud
                         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) {
@@ -1350,7 +1362,7 @@ _public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct ud
                         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);
@@ -1392,7 +1404,7 @@ _public_ unsigned long long int udev_device_get_usec_since_initialized(struct ud
         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);
@@ -1412,7 +1424,7 @@ void udev_device_set_usec_initialized(struct udev_device *udev_device, usec_t us
 
         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);
 }
 
 /**
@@ -1656,7 +1668,7 @@ static int udev_device_set_devnode(struct udev_device *udev_device, const char *
         }
         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;
 }
 
@@ -1721,7 +1733,7 @@ const char *udev_device_get_id_filename(struct udev_device *udev_device)
 _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;
 }
 
@@ -1781,7 +1793,7 @@ _public_ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_dev
         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);
 }
 
@@ -1801,7 +1813,7 @@ _public_ int udev_device_has_tag(struct udev_device *udev_device, const char *ta
         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;
@@ -1883,14 +1895,14 @@ int udev_device_set_action(struct udev_device *udev_device, const char *action)
         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;
 }
 
@@ -1903,7 +1915,7 @@ int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio)
 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;
 }
 
@@ -1926,6 +1938,7 @@ void udev_device_set_db_persist(struct udev_device *udev_device)
 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;
 
@@ -1942,6 +1955,13 @@ int udev_device_rename(struct udev_device *udev_device, const char *name)
         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;
 }
 
@@ -1966,6 +1986,20 @@ struct udev_device *udev_device_shallow_clone(struct udev_device *old_device)
         return device;
 }
 
+struct udev_device *udev_device_clone_with_db(struct udev_device *old_device)
+{
+        struct udev_device *device;
+
+        device = udev_device_shallow_clone(old_device);
+        if (!device)
+                return NULL;
+
+        udev_device_read_db(device);
+        udev_device_set_info_loaded(device);
+
+        return device;
+}
+
 struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr, ssize_t buflen) {
         struct udev_device *device;
         ssize_t bufpos = 0;
@@ -2010,3 +2044,18 @@ struct udev_device *udev_device_new_from_nulstr(struct udev *udev, char *nulstr,
 
         return device;
 }
+
+int udev_device_copy_properties(struct udev_device *dst, struct udev_device *src) {
+        struct udev_list_entry *entry;
+
+        for ((entry = udev_device_get_properties_list_entry(src)); entry; entry = udev_list_entry_get_next(entry)) {
+                const char *key, *value;
+
+                key = udev_list_entry_get_name(entry);
+                value = udev_list_entry_get_value(entry);
+
+                udev_device_add_property(dst, key, value);
+        }
+
+        return 0;
+}