From 49747bdc374d6f98846e86d57016d8009aacb1cb Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Fri, 2 Apr 2004 22:16:38 -0800 Subject: [PATCH] tweak node unlink handling 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 | 62 +++++++++++++++++++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 33 deletions(-) (limited to 'udev-add.c') diff --git a/udev-add.c b/udev-add.c index 20599822d3..5dc46cf2a7 100644 --- a/udev-add.c +++ b/udev-add.c @@ -105,29 +105,46 @@ static int create_path(char *file) 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'", - filename, mode, major, minor, strerror(errno)); + file, mode, major, minor, strerror(errno)); 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) { - 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'", - filename, uid, gid, strerror(errno)); + file, uid, gid, strerror(errno)); goto exit; } } @@ -167,23 +184,6 @@ static void set_to_local_user(char *user) 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]; @@ -253,7 +253,6 @@ static int create_node(struct udevice *dev, int 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; @@ -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); - unlink_entry(partitionname); 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]); - if (!fake) - unlink_entry(filename); - 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)); -- cgit v1.2.1