+
+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 (udev_device == NULL || name == NULL)
+ return -EINVAL;
+
+ dirname = dirname_malloc(udev_device->syspath);
+ if (!dirname)
+ return -ENOMEM;
+
+ 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;
+}
+
+struct udev_device *udev_device_shallow_clone(struct udev_device *old_device)
+{
+ struct udev_device *device;
+
+ if (old_device == NULL)
+ return NULL;
+
+ device = udev_device_new(old_device->udev);
+ if (!device) {
+ errno = ENOMEM;
+
+ return NULL;
+ }
+
+ udev_device_set_syspath(device, udev_device_get_syspath(old_device));
+ udev_device_set_subsystem(device, udev_device_get_subsystem(old_device));
+ udev_device_set_devnum(device, udev_device_get_devnum(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;
+
+ if (nulstr == NULL || buflen <= 0) {
+ errno = EINVAL;
+
+ return NULL;
+ }
+
+ device = udev_device_new(udev);
+ if (!device) {
+ errno = ENOMEM;
+
+ return NULL;
+ }
+
+ udev_device_set_info_loaded(device);
+
+ while (bufpos < buflen) {
+ char *key;
+ size_t keylen;
+
+ key = nulstr + bufpos;
+ keylen = strlen(key);
+ if (keylen == 0)
+ break;
+
+ bufpos += keylen + 1;
+ udev_device_add_property_from_string_parse(device, key);
+ }
+
+ if (udev_device_add_property_from_string_parse_finish(device) < 0) {
+ log_debug("missing values, invalid device");
+
+ udev_device_unref(device);
+
+ errno = EINVAL;
+
+ return NULL;
+ }
+
+ return device;
+}
+
+struct udev_device *udev_device_new_from_synthetic_event(struct udev *udev, const char *syspath, const char *action) {
+ struct udev_device *ret;
+ int r;
+
+ if (!action) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ ret = udev_device_new_from_syspath(udev, syspath);
+ if (!ret)
+ return NULL;
+
+ r = udev_device_read_uevent_file(ret);
+ if (r < 0) {
+ udev_device_unref(ret);
+ errno = -r;
+ return NULL;
+ }
+
+ r = udev_device_set_action(ret, action);
+ if (r < 0) {
+ udev_device_unref(ret);
+ errno = -r;
+ return NULL;
+ }
+
+ return ret;
+}
+
+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;
+}