chiark / gitweb /
[PATCH] add support for /devices-devices without any file to wait for
[elogind.git] / namedev.c
index b142dda4fe4d18872f5ff1af70483cb0b07a5805..69669709df9ef37211525a6bfd8d0527a2797e64 100644 (file)
--- a/namedev.c
+++ b/namedev.c
@@ -40,7 +40,7 @@
 #include "udev_version.h"
 #include "logging.h"
 #include "namedev.h"
-#include "udevdb.h"
+#include "udev_db.h"
 
 static struct sysfs_attribute *find_sysfs_attribute(struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device, char *attr);
 
@@ -184,29 +184,29 @@ static int get_format_len(char **str)
  *  @param  name                Name to check for
  *  @return                     0 if <name> didn't exist and N otherwise.
  */
-static unsigned int find_free_number (struct udevice *udev, char *name)
+static int find_free_number(struct udevice *udev, const char *name)
 {
-       char temp[NAME_SIZE];
-       char path[NAME_SIZE];
-       struct udevice dev;
-       int result;
+       char filename[NAME_SIZE];
+       int num = 0;
+       struct udevice db_udev;
 
-       /* have to sweep the database for each lookup */
-       result = 0;
-       strncpy(temp, name, sizeof (temp));
+       strfieldcpy(filename, name);
        while (1) {
-               if (udevdb_get_dev_byname(temp, path, &dev) != 0)
-                       goto found;
-               /* symlink might be stale if $(udevroot) isn't cleaned; check
-                * on major/minor to see if it's the same device
-                */
-               if (dev.major == udev->major && dev.minor == udev->minor)
-                       goto found;
-               snprintf (temp, sizeof(temp), "%s%d", name, ++result);
-       }
+               dbg("look for existing node '%s'", filename);
+               memset(&db_udev, 0x00, sizeof(struct udevice));
+               if (udev_db_get_device_byname(&db_udev, filename) != 0) {
+                       dbg("free num=%d", num);
+                       return num;
+               }
 
-found:
-       return result;
+               num++;
+               if (num > 1000) {
+                       info("find_free_number gone crazy (num=%d), aborted", num);
+                       return -1;
+               }
+               snprintf(filename, NAME_SIZE, "%s%d", name, num);
+               filename[NAME_SIZE-1] = '\0';
+       }
 }
 
 static void apply_format(struct udevice *udev, char *string, size_t maxsize,
@@ -329,7 +329,7 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize,
                case 'e':
                        next_free_number = find_free_number(udev, string);
                        if (next_free_number > 0) {
-                               snprintf(temp2, sizeof(temp2), "%d", next_free_number);
+                               sprintf(temp2, "%d", next_free_number);
                                strfieldcatmax(string, temp2, maxsize);
                        }
                        break;
@@ -358,7 +358,7 @@ static void fix_kernel_name(struct udevice *udev)
        }
 }
 
-static int execute_program(const char *path, char *value, int len)
+static int execute_program(struct udevice *udev, const char *path, char *value, int len)
 {
        int retval;
        int count;
@@ -391,7 +391,7 @@ static int execute_program(const char *path, char *value, int len)
                dbg("execute '%s' with parsed arguments", arg);
        } else {
                argv[0] = arg;
-               argv[1] = main_argv[1];
+               argv[1] = udev->subsystem;
                argv[2] = NULL;
                dbg("execute '%s' with subsystem '%s' argument", arg, argv[1]);
        }
@@ -444,7 +444,7 @@ static int execute_program(const char *path, char *value, int len)
                dbg("result is '%s'", value);
 
                close(fds[0]);
-               wait(&status);
+               waitpid(pid, &status, 0);
 
                if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
                        dbg("exec program status 0x%x", status);
@@ -604,7 +604,7 @@ static int match_rule(struct config_device *dev, struct sysfs_class_device *clas
                        }
                }
 
-               /* check for matching kernel name*/
+               /* check for matching kernel name */
                if (dev->kernel[0] != '\0') {
                        dbg("check for " FIELD_KERNEL " dev->kernel='%s' class_dev->name='%s'", dev->kernel, class_dev->name);
                        if (strcmp_pattern(dev->kernel, class_dev->name) != 0) {
@@ -615,6 +615,28 @@ static int match_rule(struct config_device *dev, struct sysfs_class_device *clas
                        }
                }
 
+               /* check for matching subsystem */
+               if (dev->subsystem[0] != '\0') {
+                       dbg("check for " FIELD_SUBSYSTEM " dev->subsystem='%s' class_dev->name='%s'", dev->subsystem, class_dev->name);
+                       if (strcmp_pattern(dev->subsystem, udev->subsystem) != 0) {
+                               dbg(FIELD_SUBSYSTEM " is not matching");
+                               goto try_parent;
+                       } else {
+                               dbg(FIELD_SUBSYSTEM " matches");
+                       }
+               }
+
+               /* check for matching driver */
+               if (dev->driver[0] != '\0') {
+                       dbg("check for " FIELD_DRIVER " dev->driver='%s' sysfs_device->driver_name='%s'", dev->driver, sysfs_device->driver_name);
+                       if (strcmp_pattern(dev->driver, sysfs_device->driver_name) != 0) {
+                               dbg(FIELD_DRIVER " is not matching");
+                               goto try_parent;
+                       } else {
+                               dbg(FIELD_DRIVER " matches");
+                       }
+               }
+
                /* check for matching bus id */
                if (dev->id[0] != '\0') {
                        dbg("check " FIELD_ID);
@@ -655,7 +677,7 @@ static int match_rule(struct config_device *dev, struct sysfs_class_device *clas
                        dbg("check " FIELD_PROGRAM);
                        strfieldcpy(program, dev->program);
                        apply_format(udev, program, sizeof(program), class_dev, sysfs_device);
-                       if (execute_program(program, udev->program_result, NAME_SIZE) != 0) {
+                       if (execute_program(udev, program, udev->program_result, NAME_SIZE) != 0) {
                                dbg(FIELD_PROGRAM " returned nonzero");
                                goto try_parent;
                        } else {
@@ -785,6 +807,7 @@ found:
                goto done;
 
        udev->partitions = dev->partitions;
+       udev->ignore_remove = dev->ignore_remove;
 
        /* get permissions given in rule */
        set_empty_perms(udev, dev->mode,