From: Kay Sievers Date: Wed, 14 Jun 2006 14:32:52 +0000 (+0200) Subject: don't remove symlinks if they are already there X-Git-Tag: 174~2244 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=fa33d857e2cdd65d3de2f88021ecacf167fc21f0 don't remove symlinks if they are already there Consecutive "add" events will not remove and recreate the same symlinks anymore. No longer valid links, like after changing a filesystem label, will still be removed. --- diff --git a/test/udev-test.pl b/test/udev-test.pl index 33da68a38..fafaa96ab 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -862,6 +862,7 @@ EOF devpath => "/class/tty/tty0", exp_name => "link", exp_target => "link", + exp_add_error => "yes", exp_rem_error => "yes", option => "clean", rules => <dev->devpath) == 0) { - info("device '%s' already known, remove possible symlinks", udev->dev->devpath); - udev_node_remove_symlinks(udev_old); - } - udev_device_cleanup(udev_old); + if (udev_db_get_device(udev_old, udev->dev->devpath) != 0) { + udev_device_cleanup(udev_old); + udev_old = NULL; + } else + info("device '%s' already in database, validate currently present symlinks", + udev->dev->devpath); } - /* create node and symlinks, store record in database */ + /* create node and symlinks */ retval = udev_node_add(udev, udev_old); - if (retval == 0) + if (retval == 0) { + /* store record in database */ udev_db_add_device(udev); + + /* remove possibly left-over symlinks */ + if (udev_old != NULL) { + struct name_entry *link_loop; + struct name_entry *link_old_loop; + struct name_entry *link_old_tmp_loop; + + /* remove still valid symlinks from old list */ + list_for_each_entry_safe(link_old_loop, link_old_tmp_loop, &udev_old->symlink_list, node) + list_for_each_entry(link_loop, &udev->symlink_list, node) + if (strcmp(link_old_loop->name, link_loop->name) == 0) { + dbg("symlink '%s' still valid, keep it", link_old_loop->name); + list_del(&link_old_loop->node); + free(link_old_loop); + } + udev_node_remove_symlinks(udev_old); + udev_device_cleanup(udev_old); + } + } goto exit; } diff --git a/udev_node.c b/udev_node.c index 2a30fe322..ee59d4ae7 100644 --- a/udev_node.c +++ b/udev_node.c @@ -90,6 +90,36 @@ exit: return retval; } +static int udev_node_symlink(struct udevice *udev, const char *linktarget, const char *filename) +{ + char target[PATH_SIZE]; + int len; + + /* look if symlink already exists */ + len = readlink(filename, target, sizeof(target)); + if (len > 0) { + target[len] = '\0'; + if (strcmp(linktarget, target) == 0) { + info("preserving symlink '%s' to '%s'", filename, linktarget); + selinux_setfilecon(filename, NULL, S_IFLNK); + goto exit; + } else { + info("link '%s' points to different target '%s', delete it", filename, target); + unlink(filename); + } + } + + /* create link */ + info("creating symlink '%s' to '%s'", filename, linktarget); + selinux_setfscreatecon(filename, NULL, S_IFLNK); + if (symlink(linktarget, filename) != 0) + err("symlink(%s, %s) failed: %s", linktarget, filename, strerror(errno)); + selinux_resetfscreatecon(); + +exit: + return 0; +} + int udev_node_add(struct udevice *udev, struct udevice *udev_old) { char filename[PATH_SIZE]; @@ -205,13 +235,8 @@ int udev_node_add(struct udevice *udev, struct udevice *udev_old) strlcat(linktarget, &udev->name[tail], sizeof(linktarget)); info("creating symlink '%s' to '%s'", filename, linktarget); - if (!udev->test_run) { - unlink(filename); - selinux_setfscreatecon(filename, NULL, S_IFLNK); - if (symlink(linktarget, filename) != 0) - err("symlink(%s, %s) failed: %s", linktarget, filename, strerror(errno)); - selinux_resetfscreatecon(); - } + if (!udev->test_run) + udev_node_symlink(udev, linktarget, filename); strlcat(symlinks, filename, sizeof(symlinks)); strlcat(symlinks, " ", sizeof(symlinks));