if (event->tmp_node != NULL) {
util_strlcat(string, event->tmp_node, maxsize);
- dbg(event->udev, "return existing temporary node\n");
+ dbg(event->udev, "tempnode: return earlier created one\n");
break;
}
devnum = udev_device_get_devnum(dev);
- if (major(udev_device_get_devnum(dev) == 0))
+ if (major(devnum) == 0)
break;
+ /* lookup kernel provided node */
+ if (udev_device_get_knodename(dev) != NULL) {
+ util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename));
+ util_strlcat(filename, "/", sizeof(filename));
+ util_strlcat(filename, udev_device_get_knodename(dev), sizeof(filename));
+ if (stat(filename, &statbuf) == 0 && statbuf.st_rdev == devnum) {
+ util_strlcat(string, filename, maxsize);
+ dbg(event->udev, "tempnode: return kernel node\n");
+ break;
+ }
+ }
+ /* lookup /dev/{char,block}/<maj>:<min> */
if (strcmp(udev_device_get_subsystem(dev), "block") == 0)
devtype = "block";
else
minor(udev_device_get_devnum(dev)));
if (stat(filename, &statbuf) == 0 && statbuf.st_rdev == devnum) {
util_strlcat(string, filename, maxsize);
- dbg(event->udev, "return existing temporary node\n");
+ dbg(event->udev, "tempnode: return maj:min node\n");
break;
}
- dbg(event->udev, "create temporary node\n");
+ /* create temporary node */
+ dbg(event->udev, "tempnode: create temp node\n");
asprintf(&event->tmp_node, "%s/.tmp-%s-%u:%u",
udev_get_dev_path(event->udev), devtype,
major(udev_device_get_devnum(dev)),
goto exit;
}
- /* wait 30 seconds for our target to become available */
+ /* wait 90 seconds for our target to become available */
util_strlcpy(ifr.ifr_name, ifr.ifr_newname, IFNAMSIZ);
util_strlcpy(ifr.ifr_newname, event->name, IFNAMSIZ);
- loop = 30 * 20;
+ loop = 90 * 20;
while (loop--) {
err = ioctl(sk, SIOCSIFNAME, &ifr);
if (err == 0) {
break;
}
dbg(event->udev, "wait for netif '%s' to become free, loop=%i\n",
- event->name, (30 * 20) - loop);
+ event->name, (90 * 20) - loop);
usleep(1000 * 1000 / 20);
}
}
(strcmp(udev_device_get_action(dev), "add") == 0 || strcmp(udev_device_get_action(dev), "change") == 0)) {
char filename[UTIL_PATH_SIZE];
struct udev_device *dev_old;
+ int delete_kdevnode = 0;
dbg(event->udev, "device node add '%s'\n", udev_device_get_devpath(dev));
+ /* read old database entry */
+ dev_old = udev_device_new_from_syspath(event->udev, udev_device_get_syspath(dev));
+ if (dev_old != NULL) {
+ udev_device_read_db(dev_old);
+ udev_device_set_info_loaded(dev_old);
+
+ /* disable watch during event processing */
+ udev_watch_end(event->udev, dev_old);
+ }
+
udev_rules_apply_to_event(rules, event);
if (event->tmp_node != NULL) {
- dbg(event->udev, "removing temporary device node\n");
+ dbg(event->udev, "cleanup temporary device node\n");
util_unlink_secure(event->udev, event->tmp_node);
free(event->tmp_node);
event->tmp_node = NULL;
if (event->ignore_device) {
info(event->udev, "device event will be ignored\n");
- goto exit;
+ delete_kdevnode = 1;
+ goto exit_add;
}
if (event->name != NULL && event->name[0] == '\0') {
info(event->udev, "device node creation supressed\n");
- goto exit;
+ delete_kdevnode = 1;
+ goto exit_add;
+ }
+
+ /* if rule given name disagrees with kernel node name, delete kernel node */
+ if (event->name != NULL && udev_device_get_knodename(dev) != NULL) {
+ if (strcmp(event->name, udev_device_get_knodename(dev)) != 0)
+ delete_kdevnode = 1;
}
+ /* no rule, use kernel provided name */
if (event->name == NULL) {
- info(event->udev, "no node name set, will use kernel name '%s'\n",
- udev_device_get_sysname(event->dev));
- event->name = strdup(udev_device_get_sysname(event->dev));
- if (event->name == NULL)
- goto exit;
+ if (udev_device_get_knodename(dev) != NULL) {
+ event->name = strdup(udev_device_get_knodename(dev));
+ info(event->udev, "no node name set, will use kernel supplied name '%s'\n", event->name);
+ } else {
+ event->name = strdup(udev_device_get_sysname(event->dev));
+ info(event->udev, "no node name set, will use device name '%s'\n", event->name);
+ }
+ }
+
+ /* something went wrong */
+ if (event->name == NULL) {
+ err(event->udev, "no node name for '%s'\n", udev_device_get_sysname(event->dev));
+ goto exit_add;
}
/* set device node name */
util_strlcat(filename, event->name, sizeof(filename));
udev_device_set_devnode(dev, filename);
- /* read current database entry */
- dev_old = udev_device_new_from_syspath(event->udev, udev_device_get_syspath(dev));
- if (dev_old != NULL) {
- udev_device_read_db(dev_old);
- udev_device_set_info_loaded(dev_old);
- }
-
- /* update database, create node and symlinks */
+ /* write current database entry */
udev_device_update_db(dev);
- err = udev_node_add(dev, event->mode, event->uid, event->gid);
/* remove/update possible left-over symlinks from old database entry */
- if (dev_old != NULL) {
+ if (dev_old != NULL)
udev_node_update_old_links(dev, dev_old);
- udev_device_unref(dev_old);
+
+ /* create new node and symlinks */
+ err = udev_node_add(dev, event->mode, event->uid, event->gid);
+exit_add:
+ if (delete_kdevnode && udev_device_get_knodename(dev) != NULL) {
+ struct stat stats;
+
+ util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename));
+ util_strlcat(filename, "/", sizeof(filename));
+ util_strlcat(filename, udev_device_get_knodename(dev), sizeof(filename));
+ if (stat(filename, &stats) == 0 && stats.st_rdev == udev_device_get_devnum(dev)) {
+ unlink(filename);
+ util_delete_path(event->udev, filename);
+ info(event->udev, "removed kernel created node '%s'\n", filename);
+ }
}
+ udev_device_unref(dev_old);
goto exit;
}
udev_device_set_info_loaded(dev);
udev_device_delete_db(dev);
+ /* remove watch */
+ udev_watch_end(event->udev, dev);
+
if (udev_device_get_devnode(dev) == NULL) {
char devnode[UTIL_PATH_SIZE];