+static int device_process_new_device(Manager *m, struct udev_device *dev, bool update_state) {
+ const char *sysfs, *dn;
+ struct udev_list_entry *item = NULL, *first = NULL;
+
+ assert(m);
+
+ if (!(sysfs = udev_device_get_syspath(dev)))
+ return -ENOMEM;
+
+ /* Add the main unit named after the sysfs path */
+ device_update_unit(m, dev, sysfs, true);
+
+ /* Add an additional unit for the device node */
+ if ((dn = udev_device_get_devnode(dev)))
+ device_update_unit(m, dev, dn, false);
+
+ /* Add additional units for all symlinks */
+ first = udev_device_get_devlinks_list_entry(dev);
+ udev_list_entry_foreach(item, first) {
+ const char *p;
+ struct stat st;
+
+ /* Don't bother with the /dev/block links */
+ p = udev_list_entry_get_name(item);
+
+ if (path_startswith(p, "/dev/block/") ||
+ path_startswith(p, "/dev/char/"))
+ continue;
+
+ /* Verify that the symlink in the FS actually belongs
+ * to this device. This is useful to deal with
+ * conflicting devices, e.g. when two disks want the
+ * same /dev/disk/by-label/xxx link because they have
+ * the same label. We want to make sure that the same
+ * device that won the symlink wins in systemd, so we
+ * check the device node major/minor*/
+ if (stat(p, &st) >= 0)
+ if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
+ st.st_rdev != udev_device_get_devnum(dev))
+ continue;
+
+ device_update_unit(m, dev, p, false);
+ }
+
+ if (update_state) {
+ Device *d, *l;
+
+ manager_dispatch_load_queue(m);
+
+ l = hashmap_get(m->devices_by_sysfs, sysfs);
+ LIST_FOREACH(same_sysfs, d, l)
+ device_set_state(d, DEVICE_PLUGGED);
+ }
+
+ return 0;
+}
+