X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev_node.c;h=ee59d4ae7c74b0642a37d391a97d58005f26b285;hp=9d6e89cfa12772c3dd24a8baadb188d7440a43bf;hb=f566b05b572492e4e7a684a5b04231412d71d0bd;hpb=a4d5ca644ed8bc59274967c17981d7448a075c07 diff --git a/udev_node.c b/udev_node.c index 9d6e89cfa..ee59d4ae7 100644 --- a/udev_node.c +++ b/udev_node.c @@ -90,7 +90,37 @@ exit: return retval; } -int udev_node_add(struct udevice *udev) +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]; struct name_entry *name_loop; @@ -205,13 +235,8 @@ int udev_node_add(struct udevice *udev) 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)); @@ -226,15 +251,11 @@ exit: return retval; } -int udev_node_remove(struct udevice *udev) +void udev_node_remove_symlinks(struct udevice *udev) { char filename[PATH_SIZE]; - char partitionname[PATH_SIZE]; struct name_entry *name_loop; struct stat stats; - int retval; - int i; - int num; if (!list_empty(&udev->symlink_list)) { char symlinks[512] = ""; @@ -253,10 +274,12 @@ int udev_node_remove(struct udevice *udev) } info("removing symlink '%s'", filename); - unlink(filename); + if (!udev->test_run) { + unlink(filename); - if (strchr(filename, '/')) - delete_path(filename); + if (strchr(filename, '/')) + delete_path(filename); + } strlcat(symlinks, filename, sizeof(symlinks)); strlcat(symlinks, " ", sizeof(symlinks)); @@ -266,6 +289,17 @@ int udev_node_remove(struct udevice *udev) if (symlinks[0] != '\0') setenv("DEVLINKS", symlinks, 1); } +} + +int udev_node_remove(struct udevice *udev) +{ + char filename[PATH_SIZE]; + char partitionname[PATH_SIZE]; + struct stat stats; + int retval; + int num; + + udev_node_remove_symlinks(udev); snprintf(filename, sizeof(filename), "%s/%s", udev_root, udev->name); filename[sizeof(filename)-1] = '\0'; @@ -288,6 +322,8 @@ int udev_node_remove(struct udevice *udev) num = udev->partitions; if (num > 0) { + int i; + info("removing all_partitions '%s[1-%i]'", filename, num); if (num > 255) { info("garbage from udev database, skip all_partitions removal");