chiark / gitweb /
rules: switch to built-in blkid
[elogind.git] / udev / udev-node.c
index 5e791ffb6c50753783018240f6d13866f845868d..44d3686db61a75f37d6994c2f98377644b5db039 100644 (file)
@@ -52,7 +52,9 @@ int udev_node_mknod(struct udev_device *dev, const char *file, mode_t mode, uid_
        if (lstat(file, &stats) == 0) {
                if (((stats.st_mode & S_IFMT) == (mode & S_IFMT)) && (stats.st_rdev == devnum)) {
                        info(udev, "preserve file '%s', because it has correct dev_t\n", file);
-                       if (stats.st_mode != mode || stats.st_uid != uid || stats.st_gid != gid) {
+                       if ((stats.st_mode & 0777) != (mode & 0777) || stats.st_uid != uid || stats.st_gid != gid) {
+                               /* preserve 'sticky' bit, if already set */
+                               mode |= stats.st_mode & 01000;
                                info(udev, "set permissions %s, %#o, uid=%u, gid=%u\n", file, mode, uid, gid);
                                chmod(file, mode);
                                chown(file, uid, gid);
@@ -105,7 +107,7 @@ int udev_node_mknod(struct udev_device *dev, const char *file, mode_t mode, uid_
                                err = -errno;
                        udev_selinux_resetfscreatecon(udev);
                } while (err == -ENOENT);
-               if (err != 0)
+               if (err != 0 && err != -EEXIST)
                        err(udev, "mknod '%s' %u:%u %#o' failed: %m\n", file, major(devnum), minor(devnum), mode);
                info(udev, "set permissions '%s' %#o uid=%u gid=%u\n", file, mode, uid, gid);
                chmod(file, mode);
@@ -386,7 +388,7 @@ int udev_node_add(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid)
 
        /* create/update symlinks, add symlinks to name index */
        udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
-               if (udev_list_entry_get_flags(list_entry))
+               if (udev_list_entry_get_num(list_entry))
                        /* simple unmanaged link name */
                        node_symlink(udev, udev_device_get_devnode(dev), udev_list_entry_get_name(list_entry));
                else
@@ -414,15 +416,19 @@ int udev_node_remove(struct udev_device *dev)
        if (devnode == NULL)
                goto out;
 
-       if (stat(devnode, &stats) != 0) {
-               info(udev, "device node '%s' not found\n", devnode);
-               goto out;
-       }
+       if (stat(devnode, &stats) == 0) {
+               if (stats.st_rdev != udev_device_get_devnum(dev)) {
+                       info(udev, "device node '%s' points to a different device, skip removal\n", devnode);
+                       err = -1;
+                       goto out;
+               }
 
-       if (stats.st_rdev != udev_device_get_devnum(dev)) {
-               info(udev, "device node '%s' points to a different device, skip removal\n", devnode);
-               err = -1;
-               goto out;
+               if (stats.st_mode & 01000) {
+                       info(udev, "device node '%s' has sticky bit set, skip removal\n", devnode);
+                       goto out;
+               }
+       } else {
+               info(udev, "device node '%s' not found\n", devnode);
        }
 
        dev_check = udev_device_new_from_syspath(udev, udev_device_get_syspath(dev));