chiark / gitweb /
[PATCH] tweak node unlink handling
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Sat, 3 Apr 2004 06:16:38 +0000 (22:16 -0800)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:35:14 +0000 (21:35 -0700)
Based on a patch from Olaf Hering we remove the node now only if the
requested dev_t is different from the already existing node, so any
run of udevstart should preserve the inode number of the node file.

syslog while the right node is already there:
  creating device node '/udev/hda'
  make_node: preserve file '/udev/hda', cause it has correct dev_t
  make_node: chmod(/udev/hda, 060600)

syslog for wrong file already there:
  creating device node '/udev/hda'
  make_node: already present file '/udev/hda' unlinked
  make_node: chmod(/udev/hda, 060600)

syslog for directory with same name already there:
  creating device node '/udev/hda'
  make_node: unlink(/udev/hda) failed with error '21'

udev-add.c

index 20599822d354db0dc56784587d434c1313a3273c..5dc46cf2a71ecf87d15512b475b29fab9e293a19 100644 (file)
@@ -105,29 +105,46 @@ static int create_path(char *file)
        return 0;
 }
 
        return 0;
 }
 
-static int make_node(char *filename, int major, int minor, unsigned int mode, uid_t uid, gid_t gid)
+static int make_node(char *file, int major, int minor, unsigned int mode, uid_t uid, gid_t gid)
 {
 {
-       int retval;
+       struct stat stats;
+       int retval = 0;
+
+       if (stat(file, &stats) != 0)
+               goto create;
+
+       /* preserve node with already correct numbers, to not change the inode number */
+       if (((stats.st_mode & S_IFMT) == S_IFBLK || (stats.st_mode & S_IFMT) == S_IFCHR) &&
+           (stats.st_rdev == makedev(major, minor))) {
+               dbg("preserve file '%s', cause it has correct dev_t", file);
+               goto perms;
+       }
+
+       if (unlink(file) != 0)
+               dbg("unlink(%s) failed with error '%s'", file, strerror(errno));
+       else
+               dbg("already present file '%s' unlinked", file);
 
 
-       retval = mknod(filename, mode, makedev(major, minor));
+create:
+       retval = mknod(file, mode, makedev(major, minor));
        if (retval != 0) {
                dbg("mknod(%s, %#o, %u, %u) failed with error '%s'",
        if (retval != 0) {
                dbg("mknod(%s, %#o, %u, %u) failed with error '%s'",
-                   filename, mode, major, minor, strerror(errno));
+                   file, mode, major, minor, strerror(errno));
                goto exit;
        }
 
                goto exit;
        }
 
-       dbg("chmod(%s, %#o)", filename, mode);
-       if (chmod(filename, mode) != 0) {
-               dbg("chmod(%s, %#o) failed with error '%s'",
-                   filename, mode, strerror(errno));
+perms:
+       dbg("chmod(%s, %#o)", file, mode);
+       if (chmod(file, mode) != 0) {
+               dbg("chmod(%s, %#o) failed with error '%s'", file, mode, strerror(errno));
                goto exit;
        }
 
        if (uid != 0 || gid != 0) {
                goto exit;
        }
 
        if (uid != 0 || gid != 0) {
-               dbg("chown(%s, %u, %u)", filename, uid, gid);
-               if (chown(filename, uid, gid) != 0) {
+               dbg("chown(%s, %u, %u)", file, uid, gid);
+               if (chown(file, uid, gid) != 0) {
                        dbg("chown(%s, %u, %u) failed with error '%s'",
                        dbg("chown(%s, %u, %u) failed with error '%s'",
-                           filename, uid, gid, strerror(errno));
+                           file, uid, gid, strerror(errno));
                        goto exit;
                }
        }
                        goto exit;
                }
        }
@@ -167,23 +184,6 @@ static void set_to_local_user(char *user)
        endutent();
 }
 
        endutent();
 }
 
-static int unlink_entry(char *filename)
-{
-       struct stat stats;
-       int retval = 0;
-       
-       if (lstat(filename, &stats) == 0) {
-               if ((stats.st_mode & S_IFMT) != S_IFDIR) {
-                       retval = unlink(filename);
-                       if (retval) {
-                               dbg("unlink(%s) failed with error '%s'",
-                                   filename, strerror(errno));
-                       }
-               }
-       }
-       return retval;
-}
-
 static int create_node(struct udevice *dev, int fake)
 {
        char filename[NAME_SIZE];
 static int create_node(struct udevice *dev, int fake)
 {
        char filename[NAME_SIZE];
@@ -253,7 +253,6 @@ static int create_node(struct udevice *dev, int fake)
        }
 
        if (!fake) {
        }
 
        if (!fake) {
-               unlink_entry(filename);
                info("creating device node '%s'", filename);
                if (make_node(filename, dev->major, dev->minor, dev->mode, uid, gid) != 0)
                        goto error;
                info("creating device node '%s'", filename);
                if (make_node(filename, dev->major, dev->minor, dev->mode, uid, gid) != 0)
                        goto error;
@@ -270,7 +269,6 @@ static int create_node(struct udevice *dev, int fake)
                        for (i = 1; i <= dev->partitions; i++) {
                                strfieldcpy(partitionname, filename);
                                strintcat(partitionname, i);
                        for (i = 1; i <= dev->partitions; i++) {
                                strfieldcpy(partitionname, filename);
                                strintcat(partitionname, i);
-                               unlink_entry(partitionname);
                                make_node(partitionname, dev->major,
                                          dev->minor + i, dev->mode, uid, gid);
                        }
                                make_node(partitionname, dev->major,
                                          dev->minor + i, dev->mode, uid, gid);
                        }
@@ -304,11 +302,9 @@ static int create_node(struct udevice *dev, int fake)
 
                strfieldcat(linktarget, &dev->name[tail]);
 
 
                strfieldcat(linktarget, &dev->name[tail]);
 
-               if (!fake)
-                       unlink_entry(filename);
-
                dbg("symlink(%s, %s)", linktarget, filename);
                if (!fake) {
                dbg("symlink(%s, %s)", linktarget, filename);
                if (!fake) {
+                       unlink(filename);
                        if (symlink(linktarget, filename) != 0)
                                dbg("symlink(%s, %s) failed with error '%s'",
                                    linktarget, filename, strerror(errno));
                        if (symlink(linktarget, filename) != 0)
                                dbg("symlink(%s, %s) failed with error '%s'",
                                    linktarget, filename, strerror(errno));