From: Kay Sievers Date: Wed, 5 Apr 2006 20:29:33 +0000 (+0200) Subject: merge device event handling and make database content available on "remove" X-Git-Tag: 174~2296 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=a4d5ca644ed8bc59274967c17981d7448a075c07 merge device event handling and make database content available on "remove" --- diff --git a/Makefile b/Makefile index 1ce1abeab..42c2bf23d 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 2652d46ad..615253a52 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 5db27093d..14c8d39cf 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 + * Copyright (C) 2004-2006 Kay Sievers * * 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 #include #include +#include +#include +#include #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 similarity index 69% rename from udev_add.c rename to udev_node.c index 6c023ab96..9d6e89cfa 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 * Copyright (C) 2004 Kay Sievers @@ -29,17 +29,13 @@ #include #include #include -#include -#include -#include -#include #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 6de6cf596..000000000 --- a/udev_remove.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * udev-remove.c - * - * Copyright (C) 2003 Greg Kroah-Hartman - * Copyright (C) 2004 Kay Sievers - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#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 1aedb1111..09a299f22 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 e5ce7af03..0d9b4f400 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");