/** * udev_unref: * @udev: udev library context * * Drop a reference of the udev library context. If the refcount * reaches zero, the resources of the context will be released. * **/ void udev_unref(struct udev *udev) { if (udev == NULL) return; udev->refcount--; if (udev->refcount > 0) return; udev_list_cleanup_entries(udev, &udev->properties_list); free(udev->dev_path); free(udev->sys_path); free(udev->rules_path); dbg(udev, "context %p released\n", udev); free(udev); }
static int update_link(struct udev_device *dev, const char *slink, int test) { struct udev *udev = udev_device_get_udev(dev); struct udev_list_node dev_list; struct udev_list_entry *dev_entry; char target[UTIL_PATH_SIZE]; int count; int priority = 0; int rc = 0; dbg(udev, "update symlink '%s' of '%s'\n", slink, udev_device_get_syspath(dev)); udev_list_init(&dev_list); count = name_index_get_devices(udev, slink, &dev_list); if (count > 1) info(udev, "found %i devices with name '%s'\n", count, slink); /* if we don't have a reference, delete it */ if (count <= 0) { info(udev, "no reference left, remove '%s'\n", slink); if (!test) { unlink(slink); util_delete_path(udev, slink); } goto out; } /* find the device with the highest priority */ target[0] = '\0'; udev_list_entry_foreach(dev_entry, udev_list_get_entry(&dev_list)) { const char *syspath; struct udev_device *dev_db; const char *devnode; syspath = udev_list_entry_get_name(dev_entry); dbg(udev, "found '%s' for '%s'\n", syspath, slink); /* did we find ourself? we win, if we have the same priority */ if (strcmp(udev_device_get_syspath(dev), syspath) == 0) { dbg(udev, "compare (our own) priority of '%s' %i >= %i\n", udev_device_get_devpath(dev), udev_device_get_devlink_priority(dev), priority); if (strcmp(udev_device_get_devnode(dev), slink) == 0) { info(udev, "'%s' is our device node, database inconsistent, skip link update\n", udev_device_get_devnode(dev)); } else if (target[0] == '\0' || udev_device_get_devlink_priority(dev) >= priority) { priority = udev_device_get_devlink_priority(dev); util_strlcpy(target, udev_device_get_devnode(dev), sizeof(target)); } continue; } /* another device, read priority from database */ dev_db = udev_device_new_from_syspath(udev, syspath); if (dev_db == NULL) continue; devnode = udev_device_get_devnode(dev_db); if (devnode != NULL) { if (strcmp(devnode, slink) == 0) { info(udev, "'%s' is a device node of '%s', skip link update\n", devnode, syspath); } else { dbg(udev, "compare priority of '%s' %i > %i\n", udev_device_get_devpath(dev_db), udev_device_get_devlink_priority(dev_db), priority); if (target[0] == '\0' || udev_device_get_devlink_priority(dev_db) > priority) { priority = udev_device_get_devlink_priority(dev_db); util_strlcpy(target, devnode, sizeof(target)); } } } udev_device_unref(dev_db); } udev_list_cleanup_entries(udev, &dev_list); if (target[0] == '\0') { info(udev, "no current target for '%s' found\n", slink); rc = 1; goto out; } /* create symlink to the target with the highest priority */ info(udev, "'%s' with target '%s' has the highest priority %i, create it\n", slink, target, priority); if (!test) { util_create_path(udev, slink); node_symlink(udev, target, slink); } out: return rc; }