chiark / gitweb /
[PATCH] netdev - udevdb+dev.d changes
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Thu, 1 Apr 2004 07:12:57 +0000 (23:12 -0800)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:35:13 +0000 (21:35 -0700)
Here is a patch to change the netdev handling in the database and for
the dev.d/ calls. I applies on top of the udevd.patch, cause klibc has
no sysinfo().

 o netdev's are also put into our database now. I want this for the
   udevruler gui to get a list of all handled devices.
   All devices in the db are stamped with the system uptime value at
   the creation time. 'udevinfo -d' prints it.

 o the DEVPATH value is the key for udevdb, but if we rename
   a netdev, the name is replaced in the kernel, so we add
   the changed name to the db to match with the remove event.

   NOTE: The dev.d/ scripts still get the original name from the
   hotplug call. Should we replace DEVPATH with the new name too?

 o We now only add a device to the db, if we have successfully created
   the main node or successfully renamed a netdev. This is the main part
   of the patch, cause I needed to clean the retval passing trough all
   the functions used for node creation.

 o DEVNODE sounds a bit ugly for netdev's so I exported DEVNAME too.
   Can we change the name?

 o I've added a UDEV_NO_DEVD to possibly skip the script execution
   and used it in udev-test.pl.
   udevstart is the same horror now, if you have scripts with logging
   statements in dev.d/ it takes minutes to finish, can we skip the
   scripts here too?

 o The get_device_type() function is changed to be more strict, cause
   'udevinfo -a -p /block/' gets a class device for it and tries to
   print the major/minor values.

 o bugfix, the RESULT value has now a working newline removal and a test
   for this case.

dev_d.c
namedev.c
test/udev-test.pl
udev-add.c
udev-remove.c
udev.h
udev_config.c
udevdb.c
udevinfo.c
udevruler.c

diff --git a/dev_d.c b/dev_d.c
index 9bb9507b9b3d95701cb456c51964e61a4cdea6ab..0910e4d323e344246b590f93d7a4799355645ff6 100644 (file)
--- a/dev_d.c
+++ b/dev_d.c
@@ -64,11 +64,20 @@ static int run_program(char *name)
 void dev_d_send(struct udevice *dev, char *subsystem)
 {
        char dirname[256];
-       char devnode[NAME_SIZE];
+       char devname[NAME_SIZE];
 
-       strfieldcpy(devnode, udev_root);
-       strfieldcat(devnode, dev->name);
-       setenv("DEVNODE", devnode, 1);
+       if (udev_dev_d == 0)
+               return;
+
+       if (dev->type == 'b' || dev->type == 'c') {
+               strfieldcpy(devname, udev_root);
+               strfieldcat(devname, dev->name);
+       } else if (dev->type == 'n') {
+               strfieldcpy(devname, dev->name);
+       }
+       setenv("DEVNODE", devname, 1); /* FIXME: bad name for netif */
+       setenv("DEVNAME", devname, 1);
+       dbg("DEVNAME='%s'", devname);
 
        strcpy(dirname, DEVD_DIR);
        strfieldcat(dirname, dev->name);
@@ -81,4 +90,3 @@ void dev_d_send(struct udevice *dev, char *subsystem)
        strcpy(dirname, DEVD_DIR "default");
        call_foreach_file(run_program, dirname, DEVD_SUFFIX);
 }
-
index 7b70f8bcdfd40dea8f19dd23e23fe01a655d8666..a3ae1d36b3f9786ca04d6c9abde4e97e8110c310 100644 (file)
--- a/namedev.c
+++ b/namedev.c
@@ -32,6 +32,9 @@
 #include <time.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#ifndef __KLIBC__
+#include <sys/sysinfo.h>
+#endif
 
 #include "libsysfs/sysfs/libsysfs.h"
 #include "list.h"
@@ -454,7 +457,7 @@ static int execute_program(char *path, char *value, int len)
                        retval = -1;
                }
 
-               if (i > 0 && value[i] == '\n')
+               if (i > 0 && value[i-1] == '\n')
                        i--;
                value[i] = '\0';
                dbg("result is '%s'", value);
@@ -776,6 +779,7 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud
        struct sysfs_device *sysfs_device = NULL;
        struct config_device *dev;
        struct perm_device *perm;
+       struct sysinfo info;
        char *pos;
 
        udev->mode = 0;
@@ -837,22 +841,18 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud
                        }
                }
        }
-
-       /* no rule was found for the net device */
-       if (udev->type == 'n') {
-               dbg("no name for net device '%s' configured", udev->kernel_name);
-               return -1;
-       }
-
        /* no rule was found so we use the kernel name */
        strfieldcpy(udev->name, udev->kernel_name);
-       goto done;
+       if (udev->type == 'n')
+               goto done;
+       else
+               goto perms;
 
 found:
        apply_format(udev, udev->name, sizeof(udev->name), class_dev, sysfs_device);
 
        if (udev->type == 'n')
-               return 0;
+               goto done;
 
        udev->partitions = dev->partitions;
        strfieldcpy(udev->config_file, dev->config_file);
@@ -863,7 +863,7 @@ found:
                              dev->owner,
                              dev->group);
 
-done:
+perms:
        /* get permissions given in config file or set defaults */
        perm = find_perm(udev->name);
        if (perm != NULL) {
@@ -879,8 +879,10 @@ done:
        dbg("name, '%s' is going to have owner='%s', group='%s', mode = %#o",
            udev->name, udev->owner, udev->group, udev->mode);
 
+done:
        /* store time of action */
-       udev->config_time = time(NULL);
+       sysinfo(&info);
+       udev->config_uptime = info.uptime;
 
        return 0;
 }
index 8ae01c31d4f346efe13391792f41671fa64ceca9..31bc990b813e3ce39b987210e71c5c47239b127f 100644 (file)
@@ -232,6 +232,15 @@ BUS="scsi", PROGRAM="/bin/echo -n special-device", RESULT="special--*", NAME="%c
 BUS="scsi", PROGRAM="/bin/echo -n special-device", RESULT="special-device-", NAME="%c-3-%n"
 BUS="scsi", PROGRAM="/bin/echo -n special-device", RESULT="special-devic", NAME="%c-4-%n"
 BUS="scsi", PROGRAM="/bin/echo -n special-device", RESULT="special-*", NAME="%c-%n"
+EOF
+       },
+       {
+               desc            => "program result substitution (newline removal)",
+               subsys          => "block",
+               devpath         => "/block/sda/sda3",
+               exp_name        => "newline_removed" ,
+               conf            => <<EOF
+BUS="scsi", PROGRAM="/bin/echo test", RESULT="test", NAME="newline_removed"
 EOF
        },
        {
@@ -580,6 +589,8 @@ EOF
 $ENV{UDEV_TEST} = "yes";
 $ENV{SYSFS_PATH} = $sysfs;
 $ENV{UDEV_CONFIG_FILE} = $main_conf;
+$ENV{UDEV_NO_SLEEP} = "yes";
+$ENV{UDEV_NO_DEVD} = "yes";
 
 
 sub udev {
index 6dfd059105ffbb9c6e60242c88069d3ca67fd646..1f17f50bc3de8a372b6a80d9595518fad05a9e4d 100644 (file)
  */
 static int get_major_minor(struct sysfs_class_device *class_dev, struct udevice *udev)
 {
-       int retval = -ENODEV;
        struct sysfs_attribute *attr = NULL;
 
        attr = sysfs_get_classdev_attr(class_dev, "dev");
        if (attr == NULL)
-               goto exit;
+               goto error;
        dbg("dev='%s'", attr->value);
 
        if (sscanf(attr->value, "%u:%u", &udev->major, &udev->minor) != 2)
-               goto exit;
+               goto error;
        dbg("found major=%d, minor=%d", udev->major, udev->minor);
 
-       retval = 0;
-exit:
-       return retval;
+       return 0;
+error:
+       return -1;
 }
 
 static int create_path(char *file)
@@ -114,28 +113,27 @@ static int make_node(char *filename, int major, int minor, unsigned int mode, ui
        if (retval != 0) {
                dbg("mknod(%s, %#o, %u, %u) failed with error '%s'",
                    filename, mode, major, minor, strerror(errno));
-               return retval;
+               goto exit;
        }
 
        dbg("chmod(%s, %#o)", filename, mode);
-       retval = chmod(filename, mode);
-       if (retval != 0) {
+       if (chmod(filename, mode) != 0) {
                dbg("chmod(%s, %#o) failed with error '%s'",
                    filename, mode, strerror(errno));
-               return retval;
+               goto exit;
        }
 
        if (uid != 0 || gid != 0) {
                dbg("chown(%s, %u, %u)", filename, uid, gid);
-               retval = chown(filename, uid, gid);
-               if (retval != 0) {
+               if (chown(filename, uid, gid) != 0) {
                        dbg("chown(%s, %u, %u) failed with error '%s'",
                            filename, uid, gid, strerror(errno));
-                       return retval;
+                       goto exit;
                }
        }
 
-       return 0;
+exit:
+       return retval;
 }
 
 /* get the local logged in user */
@@ -169,7 +167,6 @@ static void set_to_local_user(char *user)
        endutent();
 }
 
-/* Used to unlink existing files to ensure that our new file/symlink is created */
 static int unlink_entry(char *filename)
 {
        struct stat stats;
@@ -193,7 +190,6 @@ static int create_node(struct udevice *dev, int fake)
        char linkname[NAME_SIZE];
        char linktarget[NAME_SIZE];
        char partitionname[NAME_SIZE];
-       int retval = 0;
        uid_t uid = 0;
        gid_t gid = 0;
        int i;
@@ -259,14 +255,15 @@ static int create_node(struct udevice *dev, int fake)
        if (!fake) {
                unlink_entry(filename);
                info("creating device node '%s'", filename);
-               make_node(filename, dev->major, dev->minor, dev->mode, uid, gid);
+               if (make_node(filename, dev->major, dev->minor, dev->mode, uid, gid) != 0)
+                       goto error;
        } else {
                info("creating device node '%s', major = '%d', minor = '%d', "
                     "mode = '%#o', uid = '%d', gid = '%d'", filename,
                     dev->major, dev->minor, (mode_t)dev->mode, uid, gid);
        }
 
-       /* create partitions if requested */
+       /* create all_partitions if requested */
        if (dev->partitions > 0) {
                info("creating device partition nodes '%s[1-%i]'", filename, dev->partitions);
                if (!fake) {
@@ -280,7 +277,7 @@ static int create_node(struct udevice *dev, int fake)
                }
        }
 
-       /* create symlink if requested */
+       /* create symlink(s) if requested */
        foreach_strpart(dev->symlink, " ", pos, len) {
                strfieldcpymax(linkname, pos, len+1);
                strfieldcpy(filename, udev_root);
@@ -312,14 +309,15 @@ static int create_node(struct udevice *dev, int fake)
 
                dbg("symlink(%s, %s)", linktarget, filename);
                if (!fake) {
-                       retval = symlink(linktarget, filename);
-                       if (retval != 0)
+                       if (symlink(linktarget, filename) != 0)
                                dbg("symlink(%s, %s) failed with error '%s'",
                                    linktarget, filename, strerror(errno));
                }
        }
 
-       return retval;
+       return 0;
+error:
+       return -1;
 }
 
 static struct sysfs_class_device *get_class_dev(char *device_name)
@@ -373,12 +371,16 @@ exit:
        return retval;
 }
 
-static int rename_net_if(struct udevice *dev)
+static int rename_net_if(struct udevice *dev, int fake)
 {
        int sk;
        struct ifreq ifr;
        int retval;
 
+       dbg("changing net interface name from '%s' to '%s'", dev->kernel_name, dev->name);
+       if (fake)
+               return 0;
+
        sk = socket(PF_INET, SOCK_DGRAM, 0);
        if (sk < 0) {
                dbg("error opening socket");
@@ -389,7 +391,6 @@ static int rename_net_if(struct udevice *dev)
        strfieldcpy(ifr.ifr_name, dev->kernel_name);
        strfieldcpy(ifr.ifr_newname, dev->name);
 
-       dbg("changing net interface name from '%s' to '%s'", dev->kernel_name, dev->name);
        retval = ioctl(sk, SIOCSIFNAME, &ifr);
        if (retval != 0)
                dbg("error changing net interface name");
@@ -400,16 +401,15 @@ static int rename_net_if(struct udevice *dev)
 
 int udev_add_device(char *path, char *subsystem, int fake)
 {
-       struct sysfs_class_device *class_dev = NULL;
+       struct sysfs_class_device *class_dev;
        struct udevice dev;
-       int retval = -EINVAL;
+       char key[DEVPATH_SIZE];
+       char *pos;
+       int retval;
 
        memset(&dev, 0x00, sizeof(dev));
 
-       /* for now, the block layer is the only place where block devices are */
-
        dev.type = get_device_type(path, subsystem);
-
        switch (dev.type) {
        case 'b':
        case 'c':
@@ -422,12 +422,12 @@ int udev_add_device(char *path, char *subsystem, int fake)
 
        default:
                dbg("unknown device type '%c'", dev.type);
-               retval = -EINVAL;
+               return -1;
        }
 
        class_dev = get_class_dev(path);
        if (class_dev == NULL)
-               goto exit;
+               return -1;
 
        if (dev.type == 'b' || dev.type == 'c') {
                retval = get_major_minor(class_dev, &dev);
@@ -437,37 +437,48 @@ int udev_add_device(char *path, char *subsystem, int fake)
                }
        }
 
-       retval = namedev_name_device(class_dev, &dev);
-       if (retval != 0)
+       if (namedev_name_device(class_dev, &dev) != 0)
                goto exit;
 
-       if (!fake && (dev.type == 'b' || dev.type == 'c')) {
-               retval = udevdb_add_dev(path, &dev);
-               if (retval != 0)
-                       dbg("udevdb_add_dev failed, but we are going to try "
-                           "to create the node anyway. But remove might not "
-                           "work properly for this device.");
-       }
-
        dbg("name='%s'", dev.name);
+
        switch (dev.type) {
        case 'b':
        case 'c':
                retval = create_node(&dev, fake);
-               if ((retval == 0) && (!fake))
-                       dev_d_send(&dev, subsystem);
+               if (fake || retval != 0)
+                       goto exit;
+               if (udevdb_add_dev(path, &dev) != 0)
+                       dbg("udevdb_add_dev failed, but we are going to try "
+                           "to create the node anyway. But remove might not "
+                           "work properly for this device.");
                break;
 
        case 'n':
-               retval = rename_net_if(&dev);
-               if (retval != 0)
-                       dbg("net device naming failed");
+               strfieldcpy(key, path);
+               if (strcmp(dev.name, dev.kernel_name) != 0) {
+                       retval = rename_net_if(&dev, fake);
+                       if (fake || retval != 0)
+                               goto exit;
+                       /* netif's are keyed with the configured name, cause
+                        * the original kernel name sleeps with the fishes
+                        */
+                       pos = strrchr(key, '/');
+                       if (pos != NULL) {
+                               pos[1] = '\0';
+                               strfieldcat(key, dev.name);
+                       }
+               }
+               if (udevdb_add_dev(key, &dev) != 0)
+                       dbg("udevdb_add_dev failed");
                break;
        }
 
+       /* execute programs in dev.d/ with the name in the environment */
+       dev_d_send(&dev, subsystem);
+
 exit:
-       if (class_dev)
-               sysfs_close_class_device(class_dev);
+       sysfs_close_class_device(class_dev);
 
        return retval;
 }
index 98c45d6c333650ff4ebb381ad6508e49568cad7b..c838f15ce3521a6510a128320db658b6afef47a2 100644 (file)
@@ -137,36 +137,24 @@ int udev_remove_device(char *path, char *subsystem)
 
        memset(&dev, 0x00, sizeof(dev));
 
-       dev.type = get_device_type(path, subsystem);
-
-       switch (dev.type) {
-       case 'b':
-       case 'c':
-               retval = udevdb_get_dev(path, &dev);
-               if (retval) {
-                       dbg("'%s' not found in database, falling back on default name", path);
-                       temp = strrchr(path, '/');
-                       if (temp == NULL)
-                               return -ENODEV;
-                       strfieldcpy(dev.name, &temp[1]);
-               }
-
-               dbg("name='%s'", dev.name);
-               udevdb_delete_dev(path);
+       retval = udevdb_get_dev(path, &dev);
+       if (retval != 0) {
+               dbg("'%s' not found in database, falling back on default name", path);
+               temp = strrchr(path, '/');
+               if (temp == NULL)
+                       return -ENODEV;
+               strfieldcpy(dev.name, &temp[1]);
+       }
+       dbg("name='%s'", dev.name);
 
-               dev_d_send(&dev, subsystem);
+       dev.type = get_device_type(path, subsystem);
+       dev_d_send(&dev, subsystem);
+       udevdb_delete_dev(path);
 
+       if (dev.type == 'b' || dev.type == 'c')
                retval = delete_node(&dev);
-               break;
-
-       case 'n':
+       else if (dev.type == 'n')
                retval = 0;
-               break;
-
-       default:
-               dbg("unknown device type '%c'", dev.type);
-               retval = -EINVAL;
-       }
 
        return retval;
 }
diff --git a/udev.h b/udev.h
index eb42edce10211dbc9e5e6974aeadfc75377e4779..8d13fb5bc34178cbeffaefe918d63a2fdecb00d0 100644 (file)
--- a/udev.h
+++ b/udev.h
@@ -52,7 +52,7 @@ struct udevice {
        int partitions;
        int config_line;
        char config_file[NAME_SIZE];
-       time_t config_time;
+       long config_uptime;
 
        /* private data that help us in building strings */
        char bus_id[SYSFS_NAME_LEN];
@@ -80,5 +80,6 @@ extern char default_owner_str[OWNER_SIZE];
 extern char default_group_str[GROUP_SIZE];
 extern int udev_log;
 extern int udev_sleep;
+extern int udev_dev_d;
 
 #endif
index 57a512d711464f1dd32ef52ecfa005cb283d3a23..fe26850a87f69e7cc5e2036ba44c2d58c4217f89 100644 (file)
@@ -51,6 +51,7 @@ char default_owner_str[OWNER_SIZE];
 char default_group_str[GROUP_SIZE];
 int udev_log;
 int udev_sleep;
+int udev_dev_d;
 
 
 static int string_is_true(char *str)
@@ -77,6 +78,10 @@ static void init_variables(void)
        udev_sleep = 1;
        if (getenv("UDEV_NO_SLEEP") != NULL)
                udev_sleep = 0;
+
+       udev_dev_d = 1;
+       if (getenv("UDEV_NO_DEVD") != NULL)
+               udev_dev_d = 0;
 }
 
 #define set_var(_name, _var)                           \
index 40580e5a3b885550abd794258e3aaff9e96dd63e..f2469367109870009786cd6f5241c246ada8fafb 100644 (file)
--- a/udevdb.c
+++ b/udevdb.c
@@ -59,6 +59,7 @@ int udevdb_add_dev(const char *path, const struct udevice *dev)
 
        data.dptr = (void *)dev;
        data.dsize = UDEVICE_LEN;
+       dbg("store key '%s' for device '%s'", path, dev->name);
 
        return tdb_store(udevdb, key, data, TDB_REPLACE); 
 }
index b23f9d0aef45fb5f29619be091bc6d1facaa2f5e..8329fe7d06dd51681583b7af937f2c07c30121dd 100644 (file)
@@ -108,13 +108,14 @@ static int print_record(char *path, struct udevice *dev)
 {
        printf("P: %s\n", path);
        printf("N: %s\n", dev->name);
+       printf("T: %c\n", dev->type);
        printf("M: %#o\n", dev->mode);
        printf("S: %s\n", dev->symlink);
        printf("O: %s\n", dev->owner);
        printf("G: %s\n", dev->group);
        printf("F: %s\n", dev->config_file);
        printf("L: %i\n", dev->config_line);
-       printf("T: %li\n", dev->config_time);
+       printf("U: %li\n", dev->config_uptime);
        printf("\n");
        return 0;
 }
index af2cf7bb815372c2da530ffe3be5eff2b6fb9eac..a13bd625a875648639d6fd4c3230ab996c33b84c 100644 (file)
@@ -77,7 +77,7 @@ struct device {
        char devpath[DEVPATH_SIZE];
        int config_line;
        char config_file[NAME_SIZE];
-       time_t config_time;
+       long config_uptime;
        int added;
 };
 
@@ -106,7 +106,7 @@ static int add_record(char *path, struct udevice *udev)
        strfieldcpy(dev->devpath, path);
        dev->config_line = udev->config_line;
        strfieldcpy(dev->config_file, udev->config_file);
-       dev->config_time = udev->config_time;
+       dev->config_uptime = udev->config_uptime;
        dev->added = 0;
 
        /* sort in lexical order */
@@ -308,7 +308,7 @@ int main(int argc, char *argv[]) {
        char roottext[81];
        char path[NAME_SIZE];
        struct device *dev;
-       time_t time_last;
+       long time_last;
        int count_last;
 
        newtInit();
@@ -332,13 +332,13 @@ int main(int argc, char *argv[]) {
        /* look for last discovered device */
        time_last = 0;
        list_for_each_entry(dev, &device_list, list)
-               if (dev->config_time > time_last)
-                       time_last = dev->config_time;
+               if (dev->config_uptime > time_last)
+                       time_last = dev->config_uptime;
 
        /* skip if more than 16 recent devices */
        count_last = 0;
        list_for_each_entry(dev, &device_list, list) {
-               if (dev->config_time < time_last - 10)
+               if (dev->config_uptime < time_last - 10)
                        continue;
                count_last++;
        }
@@ -347,7 +347,7 @@ int main(int argc, char *argv[]) {
        if (count_last < 16) {
                newtListboxAppendEntry(lbox, "--- last dicovered ---", NULL);
                list_for_each_entry(dev, &device_list, list) {
-                       if (dev->config_time < time_last - 10)
+                       if (dev->config_uptime < time_last - 10)
                                continue;
 
                        dbg("%s %i", dev->name, dev->config_line);