aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@suse.de>2006-04-05 22:29:33 +0200
committerKay Sievers <kay.sievers@suse.de>2006-04-05 22:29:33 +0200
commita4d5ca644ed8bc59274967c17981d7448a075c07 (patch)
treedab1bf1e0604a4469ca0d55a972b070e6b55b368
parent1017f139b311d7185f57f803c176f191e6d0ce3b (diff)
downloadudev-a4d5ca644ed8bc59274967c17981d7448a075c07.tar.gz
merge device event handling and make database content available on "remove"
-rw-r--r--Makefile3
-rw-r--r--udev.h10
-rw-r--r--udev_device.c117
-rw-r--r--udev_node.c (renamed from udev_add.c)151
-rw-r--r--udev_remove.c135
-rw-r--r--udev_rules.c2
-rw-r--r--udevstart.c3
7 files changed, 183 insertions, 238 deletions
diff --git a/Makefile b/Makefile
index 1ce1abea..42c2bf23 100644
--- a/Makefile
+++ b/Makefile
@@ -69,8 +69,7 @@ HEADERS = \
UDEV_OBJS = \
udev_device.o \
udev_config.o \
- udev_add.o \
- udev_remove.o \
+ udev_node.o \
udev_db.o \
udev_sysfs.o \
udev_rules.o \
diff --git a/udev.h b/udev.h
index 2652d46a..615253a5 100644
--- a/udev.h
+++ b/udev.h
@@ -117,12 +117,10 @@ extern struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev);
extern struct sysfs_device *sysfs_device_get_parent_with_subsystem(struct sysfs_device *dev, const char *subsystem);
extern char *sysfs_attr_get_value(const char *devpath, const char *attr_name);
-/* udev_add.c */
-extern int udev_make_node(struct udevice *udev, const char *file, dev_t devt, mode_t mode, uid_t uid, gid_t gid);
-extern int udev_add_device(struct udevice *udev);
-
-/* udev_remove.c */
-extern int udev_remove_device(struct udevice *udev);
+/* udev_node.c */
+extern int udev_node_mknod(struct udevice *udev, const char *file, dev_t devt, mode_t mode, uid_t uid, gid_t gid);
+extern int udev_node_add(struct udevice *udev);
+extern int udev_node_remove(struct udevice *udev);
/* udev_db.c */
extern int udev_db_add_device(struct udevice *dev);
diff --git a/udev_device.c b/udev_device.c
index 5db27093..14c8d39c 100644
--- a/udev_device.c
+++ b/udev_device.c
@@ -1,7 +1,7 @@
/*
- * udev_utils.c - generic stuff used by udev
+ * udev_device.c - main udev data object
*
- * Copyright (C) 2004, 2005 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2004-2006 Kay Sievers <kay.sievers@vrfy.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -26,6 +26,9 @@
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
+#include <stropts.h>
+#include <net/if.h>
+#include <linux/sockios.h>
#include "udev.h"
#include "udev_rules.h"
@@ -77,48 +80,122 @@ dev_t udev_device_get_devt(struct udevice *udev)
return makedev(0, 0);
}
+static int rename_net_if(struct udevice *udev)
+{
+ int sk;
+ struct ifreq ifr;
+ int retval;
+
+ info("changing net interface name from '%s' to '%s'", udev->dev->kernel_name, udev->name);
+ if (udev->test_run)
+ return 0;
+
+ sk = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sk < 0) {
+ err("error opening socket: %s", strerror(errno));
+ return -1;
+ }
+
+ memset(&ifr, 0x00, sizeof(struct ifreq));
+ strlcpy(ifr.ifr_name, udev->dev->kernel_name, IFNAMSIZ);
+ strlcpy(ifr.ifr_newname, udev->name, IFNAMSIZ);
+
+ retval = ioctl(sk, SIOCSIFNAME, &ifr);
+ if (retval != 0)
+ err("error changing net interface name: %s", strerror(errno));
+ close(sk);
+
+ return retval;
+}
+
int udev_device_event(struct udev_rules *rules, struct udevice *udev)
{
int retval = 0;
- /* device node or netif */
- if ((major(udev->devt) != 0 || strcmp(udev->dev->subsystem, "net") == 0) &&
- strcmp(udev->action, "add") == 0) {
- dbg("device node or netif add '%s'", udev->dev->devpath);
+ /* add device node */
+ if (major(udev->devt) != 0 && strcmp(udev->action, "add") == 0) {
+ dbg("device node add '%s'", udev->dev->devpath);
udev_rules_get_name(rules, udev);
if (udev->ignore_device) {
info("device event will be ignored");
- return 0;
+ goto exit;
}
- /* create node, store in db */
- if (udev->name[0] != '\0')
- retval = udev_add_device(udev);
- else
+ if (udev->name[0] == '\0') {
info("device node creation supressed");
- return retval;
+ goto exit;
+ }
+ /* create node, store in db */
+ retval = udev_node_add(udev);
+ if (retval == 0)
+ udev_db_add_device(udev);
+ goto exit;
}
+ /* add netif */
+ if (strcmp(udev->dev->subsystem, "net") == 0 && strcmp(udev->action, "add") == 0) {
+ dbg("netif add '%s'", udev->dev->devpath);
+ udev_rules_get_name(rules, udev);
+ if (udev->ignore_device) {
+ info("device event will be ignored");
+ goto exit;
+ }
+
+ /* look if we want to change the name of the netif */
+ if (strcmp(udev->name, udev->dev->kernel_name) != 0) {
+ char *pos;
+
+ retval = rename_net_if(udev);
+ if (retval != 0)
+ goto exit;
+ info("renamed netif to '%s'", udev->name);
+
+ /* now fake the devpath, because the kernel name changed silently */
+ pos = strrchr(udev->dev->devpath, '/');
+ if (pos != NULL) {
+ pos[1] = '\0';
+ strlcat(udev->dev->devpath, udev->name, sizeof(udev->dev->devpath));
+ strlcpy(udev->dev->kernel_name, udev->name, sizeof(udev->dev->kernel_name));
+ setenv("DEVPATH", udev->dev->devpath, 1);
+ setenv("INTERFACE", udev->name, 1);
+ }
+ }
+ goto exit;
+ }
+
+ /* remove device node */
if (major(udev->devt) != 0 && strcmp(udev->action, "remove") == 0) {
struct name_entry *name_loop;
+ /* import and delete database entry */
+ if (udev_db_get_device(udev, udev->dev->devpath) == 0) {
+ udev_db_delete_device(udev);
+ if (udev->ignore_remove) {
+ dbg("remove event for '%s' requested to be ignored by rule", udev->name);
+ return 0;
+ }
+ /* restore stored persistent data */
+ list_for_each_entry(name_loop, &udev->env_list, node)
+ putenv(name_loop->name);
+ } else {
+ dbg("'%s' not found in database, using kernel name '%s'", udev->dev->devpath, udev->dev->kernel_name);
+ strlcpy(udev->name, udev->dev->kernel_name, sizeof(udev->name));
+ }
+
udev_rules_get_run(rules, udev);
if (udev->ignore_device) {
info("device event will be ignored");
- return 0;
+ goto exit;
}
- /* get data from db, remove db-entry, delete node */
- retval = udev_remove_device(udev);
- /* restore stored persistent data */
- list_for_each_entry(name_loop, &udev->env_list, node)
- putenv(name_loop->name);
- return retval;
+ retval = udev_node_remove(udev);
+ goto exit;
}
- /* default devices without a node */
+ /* default devices */
udev_rules_get_run(rules, udev);
if (udev->ignore_device)
info("device event will be ignored");
+exit:
return retval;
}
diff --git a/udev_add.c b/udev_node.c
index 6c023ab9..9d6e89cf 100644
--- a/udev_add.c
+++ b/udev_node.c
@@ -1,5 +1,5 @@
/*
- * udev-add.c
+ * udev-node.c - device node handling
*
* Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
@@ -29,17 +29,13 @@
#include <grp.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <linux/sockios.h>
#include "udev.h"
#include "udev_rules.h"
#include "udev_selinux.h"
-int udev_make_node(struct udevice *udev, const char *file, dev_t devt, mode_t mode, uid_t uid, gid_t gid)
+int udev_node_mknod(struct udevice *udev, const char *file, dev_t devt, mode_t mode, uid_t uid, gid_t gid)
{
struct stat stats;
int retval = 0;
@@ -94,7 +90,7 @@ exit:
return retval;
}
-static int create_node(struct udevice *udev)
+int udev_node_add(struct udevice *udev)
{
char filename[PATH_SIZE];
struct name_entry *name_loop;
@@ -102,6 +98,9 @@ static int create_node(struct udevice *udev)
gid_t gid;
int tail;
int i;
+ int retval = 0;
+
+ selinux_init();
snprintf(filename, sizeof(filename), "%s/%s", udev_root, udev->name);
filename[sizeof(filename)-1] = '\0';
@@ -140,8 +139,10 @@ static int create_node(struct udevice *udev)
filename, major(udev->devt), minor(udev->devt), udev->mode, uid, gid);
if (!udev->test_run)
- if (udev_make_node(udev, filename, udev->devt, udev->mode, uid, gid) != 0)
- goto error;
+ if (udev_node_mknod(udev, filename, udev->devt, udev->mode, uid, gid) != 0) {
+ retval = -1;
+ goto exit;
+ }
setenv("DEVNAME", filename, 1);
@@ -166,7 +167,7 @@ static int create_node(struct udevice *udev)
snprintf(partitionname, sizeof(partitionname), "%s%d", filename, i);
partitionname[sizeof(partitionname)-1] = '\0';
part_devt = makedev(major(udev->devt), minor(udev->devt) + i);
- udev_make_node(udev, partitionname, part_devt, udev->mode, uid, gid);
+ udev_node_mknod(udev, partitionname, part_devt, udev->mode, uid, gid);
}
}
}
@@ -176,7 +177,6 @@ static int create_node(struct udevice *udev)
char symlinks[512] = "";
list_for_each_entry(name_loop, &udev->symlink_list, node) {
- int retval;
char linktarget[PATH_SIZE];
snprintf(filename, sizeof(filename), "%s/%s", udev_root, name_loop->name);
@@ -208,11 +208,9 @@ static int create_node(struct udevice *udev)
if (!udev->test_run) {
unlink(filename);
selinux_setfscreatecon(filename, NULL, S_IFLNK);
- retval = symlink(linktarget, filename);
+ if (symlink(linktarget, filename) != 0)
+ err("symlink(%s, %s) failed: %s", linktarget, filename, strerror(errno));
selinux_resetfscreatecon();
- if (retval != 0)
- err("symlink(%s, %s) failed: %s",
- linktarget, filename, strerror(errno));
}
strlcat(symlinks, filename, sizeof(symlinks));
@@ -223,78 +221,87 @@ static int create_node(struct udevice *udev)
setenv("DEVLINKS", symlinks, 1);
}
- return 0;
-error:
- return -1;
+exit:
+ selinux_exit();
+ return retval;
}
-static int rename_net_if(struct udevice *udev)
+int udev_node_remove(struct udevice *udev)
{
- int sk;
- struct ifreq ifr;
+ char filename[PATH_SIZE];
+ char partitionname[PATH_SIZE];
+ struct name_entry *name_loop;
+ struct stat stats;
int retval;
+ int i;
+ int num;
- info("changing net interface name from '%s' to '%s'", udev->dev->kernel_name, udev->name);
- if (udev->test_run)
- return 0;
+ if (!list_empty(&udev->symlink_list)) {
+ char symlinks[512] = "";
- sk = socket(PF_INET, SOCK_DGRAM, 0);
- if (sk < 0) {
- err("error opening socket: %s", strerror(errno));
- return -1;
- }
+ list_for_each_entry(name_loop, &udev->symlink_list, node) {
+ snprintf(filename, sizeof(filename), "%s/%s", udev_root, name_loop->name);
+ filename[sizeof(filename)-1] = '\0';
- memset(&ifr, 0x00, sizeof(struct ifreq));
- strlcpy(ifr.ifr_name, udev->dev->kernel_name, IFNAMSIZ);
- strlcpy(ifr.ifr_newname, udev->name, IFNAMSIZ);
+ if (stat(filename, &stats) != 0) {
+ dbg("symlink '%s' not found", filename);
+ continue;
+ }
+ if (udev->devt && stats.st_rdev != udev->devt) {
+ info("symlink '%s' points to a different device, skip removal", filename);
+ continue;
+ }
- retval = ioctl(sk, SIOCSIFNAME, &ifr);
- if (retval != 0)
- err("error changing net interface name: %s", strerror(errno));
- close(sk);
+ info("removing symlink '%s'", filename);
+ unlink(filename);
- return retval;
-}
+ if (strchr(filename, '/'))
+ delete_path(filename);
-int udev_add_device(struct udevice *udev)
-{
- char *pos;
- int retval = 0;
+ strlcat(symlinks, filename, sizeof(symlinks));
+ strlcat(symlinks, " ", sizeof(symlinks));
+ }
- dbg("adding name='%s'", udev->name);
- selinux_init();
+ remove_trailing_chars(symlinks, ' ');
+ if (symlinks[0] != '\0')
+ setenv("DEVLINKS", symlinks, 1);
+ }
- if (major(udev->devt)) {
- retval = create_node(udev);
- if (retval != 0)
- goto exit;
+ snprintf(filename, sizeof(filename), "%s/%s", udev_root, udev->name);
+ filename[sizeof(filename)-1] = '\0';
- if (udev_db_add_device(udev) != 0)
- dbg("udev_db_add_dev failed, remove might not work for custom names");
- } else if (strcmp(udev->dev->subsystem, "net") == 0) {
- /* look if we want to change the name of the netif */
- if (strcmp(udev->name, udev->dev->kernel_name) != 0) {
- retval = rename_net_if(udev);
- if (retval != 0)
- goto exit;
-
- info("renamed netif to '%s'", udev->name);
- /* we've changed the name, now fake the devpath, because the
- * original kernel name sleeps with the fishes and we don't
- * get an event from the kernel with the new name
- */
- pos = strrchr(udev->dev->devpath, '/');
- if (pos != NULL) {
- pos[1] = '\0';
- strlcat(udev->dev->devpath, udev->name, sizeof(udev->dev->devpath));
- strlcpy(udev->dev->kernel_name, udev->name, sizeof(udev->dev->kernel_name));
- setenv("DEVPATH", udev->dev->devpath, 1);
- setenv("INTERFACE", udev->name, 1);
- }
+ if (stat(filename, &stats) != 0) {
+ dbg("device node '%s' not found", filename);
+ return -1;
+ }
+ if (udev->devt && stats.st_rdev != udev->devt) {
+ info("device node '%s' points to a different device, skip removal", filename);
+ return -1;
+ }
+
+ info("removing device node '%s'", filename);
+ retval = unlink_secure(filename);
+ if (retval)
+ return retval;
+
+ setenv("DEVNAME", filename, 1);
+
+ num = udev->partitions;
+ if (num > 0) {
+ info("removing all_partitions '%s[1-%i]'", filename, num);
+ if (num > 255) {
+ info("garbage from udev database, skip all_partitions removal");
+ return -1;
+ }
+ for (i = 1; i <= num; i++) {
+ snprintf(partitionname, sizeof(partitionname), "%s%d", filename, i);
+ partitionname[sizeof(partitionname)-1] = '\0';
+ unlink_secure(partitionname);
}
}
-exit:
- selinux_exit();
+ if (strchr(udev->name, '/'))
+ delete_path(filename);
+
return retval;
}
diff --git a/udev_remove.c b/udev_remove.c
deleted file mode 100644
index 6de6cf59..00000000
--- a/udev_remove.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * udev-remove.c
- *
- * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/stat.h>
-
-#include "udev.h"
-
-static int delete_node(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] = "";
-
- list_for_each_entry(name_loop, &udev->symlink_list, node) {
- snprintf(filename, sizeof(filename), "%s/%s", udev_root, name_loop->name);
- filename[sizeof(filename)-1] = '\0';
-
- if (stat(filename, &stats) != 0) {
- dbg("symlink '%s' not found", filename);
- continue;
- }
- if (udev->devt && stats.st_rdev != udev->devt) {
- info("symlink '%s' points to a different device, skip removal", filename);
- continue;
- }
-
- info("removing symlink '%s'", filename);
- unlink(filename);
-
- if (strchr(filename, '/'))
- delete_path(filename);
-
- strlcat(symlinks, filename, sizeof(symlinks));
- strlcat(symlinks, " ", sizeof(symlinks));
- }
-
- remove_trailing_chars(symlinks, ' ');
- if (symlinks[0] != '\0')
- setenv("DEVLINKS", symlinks, 1);
- }
-
- snprintf(filename, sizeof(filename), "%s/%s", udev_root, udev->name);
- filename[sizeof(filename)-1] = '\0';
-
- if (stat(filename, &stats) != 0) {
- dbg("device node '%s' not found", filename);
- return -1;
- }
- if (udev->devt && stats.st_rdev != udev->devt) {
- info("device node '%s' points to a different device, skip removal", filename);
- return -1;
- }
-
- info("removing device node '%s'", filename);
- retval = unlink_secure(filename);
- if (retval)
- return retval;
-
- setenv("DEVNAME", filename, 1);
-
- num = udev->partitions;
- if (num > 0) {
- info("removing all_partitions '%s[1-%i]'", filename, num);
- if (num > 255) {
- info("garbage from udev database, skip all_partitions removal");
- return -1;
- }
- for (i = 1; i <= num; i++) {
- snprintf(partitionname, sizeof(partitionname), "%s%d", filename, i);
- partitionname[sizeof(partitionname)-1] = '\0';
- unlink_secure(partitionname);
- }
- }
-
- if (strchr(udev->name, '/'))
- delete_path(filename);
-
- return retval;
-}
-
-/*
- * look up the sysfs path in the database to get the node name to remove
- * If we can't find it, use kernel name for lack of anything else to know to do
- */
-int udev_remove_device(struct udevice *udev)
-{
- if (major(udev->devt) == 0)
- return 0;
-
- if (udev_db_get_device(udev, udev->dev->devpath) == 0) {
- if (udev->ignore_remove) {
- dbg("remove event for '%s' requested to be ignored by rule", udev->name);
- return 0;
- }
- dbg("remove name='%s'", udev->name);
- udev_db_delete_device(udev);
- } else {
- dbg("'%s' not found in database, using kernel name '%s'", udev->dev->devpath, udev->dev->kernel_name);
- strlcpy(udev->name, udev->dev->kernel_name, sizeof(udev->name));
- }
-
- return delete_node(udev);
-}
diff --git a/udev_rules.c b/udev_rules.c
index 1aedb111..09a299f2 100644
--- a/udev_rules.c
+++ b/udev_rules.c
@@ -610,7 +610,7 @@ found:
snprintf(udev->tmp_node, sizeof(udev->tmp_node), "%s/.tmp-%u-%u",
udev_root, major(udev->devt), minor(udev->devt));
udev->tmp_node[sizeof(udev->tmp_node)-1] = '\0';
- udev_make_node(udev, udev->tmp_node, udev->devt, 0600, 0, 0);
+ udev_node_mknod(udev, udev->tmp_node, udev->devt, 0600, 0, 0);
}
strlcat(string, udev->tmp_node, maxsize);
dbg("substitute temporary device node name '%s'", udev->tmp_node);
diff --git a/udevstart.c b/udevstart.c
index e5ce7af0..0d9b4f40 100644
--- a/udevstart.c
+++ b/udevstart.c
@@ -130,7 +130,6 @@ static int add_device(const char *devpath)
/* override built-in sysfs device */
udev->dev = dev;
strcpy(udev->action, "add");
- udev->devt = udev_device_get_devt(udev);
if (strcmp(udev->dev->subsystem, "net") != 0) {
udev->devt = udev_device_get_devt(udev);
@@ -148,7 +147,7 @@ static int add_device(const char *devpath)
goto exit;
}
if (udev->name[0] != '\0')
- retval = udev_add_device(udev);
+ retval = udev_device_event(&rules, udev);
else
info("device node creation supressed");