X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev%2Fudev-event.c;h=63a8b3aa830d9db833614a7ffa678ec21aa5de18;hp=26939e75dbbc18e649efbb9c3a04d8454a977901;hb=17fd0f60f2735cbe1bb79ba55fed55291dd61fd2;hpb=3ba7e651ad36e4f37d9bfffadb638bc2ef784217 diff --git a/udev/udev-event.c b/udev/udev-event.c index 26939e75d..63a8b3aa8 100644 --- a/udev/udev-event.c +++ b/udev/udev-event.c @@ -38,10 +38,10 @@ struct udev_event *udev_event_new(struct udev_device *dev) event = calloc(1, sizeof(struct udev_event)); if (event == NULL) return NULL; + event->mode = 0600; event->dev = dev; event->udev = udev_device_get_udev(dev); udev_list_init(&event->run_list); - event->mode = 0660; dbg(event->udev, "allocated event %p\n", event); return event; } @@ -111,7 +111,7 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char * s = dest; l = size; - while (1) { + for (;;) { enum subst_type type = SUBST_UNKNOWN; char attrbuf[UTIL_PATH_SIZE]; char *attr = NULL; @@ -380,7 +380,7 @@ subst: minor(udev_device_get_devnum(dev))); if (event->tmp_node == NULL) break; - udev_node_mknod(dev, event->tmp_node, makedev(0, 0), 0600, 0, 0); + udev_node_mknod(dev, event->tmp_node, 0600, 0, 0); l = util_strpcpy(&s, l, event->tmp_node); break; } @@ -454,8 +454,8 @@ static void rename_netif_kernel_log(struct ifreq ifr) return; } - fprintf(f, "<6>udev: renamed network interface %s to %s\n", - ifr.ifr_name, ifr.ifr_newname); + fprintf(f, "<30>udev[%u]: renamed network interface %s to %s\n", + getpid(), ifr.ifr_name, ifr.ifr_newname); fclose(f); } @@ -464,6 +464,7 @@ static int rename_netif(struct udev_event *event) struct udev_device *dev = event->dev; int sk; struct ifreq ifr; + int loop; int err; info(event->udev, "changing net interface name from '%s' to '%s'\n", @@ -471,59 +472,60 @@ static int rename_netif(struct udev_event *event) sk = socket(PF_INET, SOCK_DGRAM, 0); if (sk < 0) { + err = -errno; err(event->udev, "error opening socket: %m\n"); - return -1; + return err; } memset(&ifr, 0x00, sizeof(struct ifreq)); util_strscpy(ifr.ifr_name, IFNAMSIZ, udev_device_get_sysname(dev)); util_strscpy(ifr.ifr_newname, IFNAMSIZ, event->name); err = ioctl(sk, SIOCSIFNAME, &ifr); - if (err == 0) + if (err == 0) { rename_netif_kernel_log(ifr); - else { - int loop; - - /* see if the destination interface name already exists */ - if (errno != EEXIST) { - err(event->udev, "error changing netif name %s to %s: %m\n", - ifr.ifr_name, ifr.ifr_newname); - goto exit; - } + goto out; + } - /* free our own name, another process may wait for us */ - util_strscpyl(ifr.ifr_newname, IFNAMSIZ, udev_device_get_sysname(dev), "_rename", NULL); - err = ioctl(sk, SIOCSIFNAME, &ifr); - if (err != 0) { - err(event->udev, "error changing netif name %s to %s: %m\n", - ifr.ifr_name, ifr.ifr_newname); - goto exit; - } + /* keep trying if the destination interface name already exists */ + err = -errno; + if (err != -EEXIST) + goto out; + + /* free our own name, another process may wait for us */ + util_strscpyl(ifr.ifr_newname, IFNAMSIZ, udev_device_get_sysname(dev), "-", event->name, NULL); + err = ioctl(sk, SIOCSIFNAME, &ifr); + if (err < 0) { + err = -errno; + goto out; + } - /* wait 90 seconds for our target to become available */ - util_strscpy(ifr.ifr_name, IFNAMSIZ, ifr.ifr_newname); - util_strscpy(ifr.ifr_newname, IFNAMSIZ, event->name); - loop = 90 * 20; - while (loop--) { - const struct timespec duration = { 0, 1000 * 1000 * 1000 / 20 }; + /* log temporary name */ + rename_netif_kernel_log(ifr); - err = ioctl(sk, SIOCSIFNAME, &ifr); - if (err == 0) { - rename_netif_kernel_log(ifr); - break; - } + /* wait a maximum of 90 seconds for our target to become available */ + util_strscpy(ifr.ifr_name, IFNAMSIZ, ifr.ifr_newname); + util_strscpy(ifr.ifr_newname, IFNAMSIZ, event->name); + loop = 90 * 20; + while (loop--) { + const struct timespec duration = { 0, 1000 * 1000 * 1000 / 20 }; - if (errno != EEXIST) { - err(event->udev, "error changing net interface name %s to %s: %m\n", - ifr.ifr_name, ifr.ifr_newname); - break; - } - dbg(event->udev, "wait for netif '%s' to become free, loop=%i\n", - event->name, (90 * 20) - loop); - nanosleep(&duration, NULL); + dbg(event->udev, "wait for netif '%s' to become free, loop=%i\n", + event->name, (90 * 20) - loop); + nanosleep(&duration, NULL); + + err = ioctl(sk, SIOCSIFNAME, &ifr); + if (err == 0) { + rename_netif_kernel_log(ifr); + break; } + err = -errno; + if (err != -EEXIST) + break; } -exit: + +out: + if (err < 0) + err(event->udev, "error changing net interface name %s to %s: %m\n", ifr.ifr_name, ifr.ifr_newname); close(sk); return err; } @@ -533,18 +535,13 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules) struct udev_device *dev = event->dev; int err = 0; - if (udev_device_get_sysname_old(dev) != NULL && - strcmp(udev_device_get_sysname_old(dev), udev_device_get_sysname(dev)) != 0) { - udev_device_rename_db(dev); - info(event->udev, "moved database from '%s:%s' to '%s:%s'\n", - udev_device_get_subsystem(dev), udev_device_get_sysname_old(dev), - udev_device_get_subsystem(dev), udev_device_get_sysname(dev)); - } + if (udev_device_get_subsystem(dev) == NULL) + return -1; if (strcmp(udev_device_get_action(dev), "remove") == 0) { - udev_device_read_db(dev); - udev_device_set_info_loaded(dev); + udev_device_read_db(dev, NULL); udev_device_delete_db(dev); + udev_device_tag_index(dev, NULL, false); if (major(udev_device_get_devnum(dev)) != 0) udev_watch_end(event->udev, dev); @@ -556,7 +553,7 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules) } else { event->dev_db = udev_device_new_from_syspath(event->udev, udev_device_get_syspath(dev)); if (event->dev_db != NULL) { - udev_device_read_db(event->dev_db); + udev_device_read_db(event->dev_db, NULL); udev_device_set_info_loaded(event->dev_db); /* disable watch during event processing */ @@ -567,7 +564,7 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules) udev_rules_apply_to_event(rules, event); /* rename a new network interface, if needed */ - if (strcmp(udev_device_get_subsystem(dev), "net") == 0 && strcmp(udev_device_get_action(dev), "add") == 0 && + if (udev_device_get_ifindex(dev) > 0 && strcmp(udev_device_get_action(dev), "add") == 0 && event->name != NULL && strcmp(event->name, udev_device_get_sysname(dev)) != 0) { char syspath[UTIL_PATH_SIZE]; char *pos; @@ -578,6 +575,7 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules) /* delete stale db file */ udev_device_delete_db(dev); + udev_device_tag_index(dev, NULL, false); /* remember old name */ udev_device_add_property(dev, "INTERFACE_OLD", udev_device_get_sysname(dev)); @@ -616,45 +614,46 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules) } } - if (event->name == NULL) { - /* things went wrong */ + if (event->name == NULL || event->name[0] == '\0') { udev_device_delete_db(dev); + udev_device_tag_index(dev, NULL, false); udev_device_unref(event->dev_db); err = -ENOMEM; + err(event->udev, "no node name, something went wrong, ignoring\n"); goto out; } + if (udev_device_get_knodename(dev) != NULL && strcmp(udev_device_get_knodename(dev), event->name) != 0) + err(event->udev, "kernel-provided name '%s' and NAME= '%s' disagree, " + "please use SYMLINK+= or change the kernel to provide the proper name\n", + udev_device_get_knodename(dev), event->name); + /* set device node name */ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", event->name, NULL); udev_device_set_devnode(dev, filename); - } - - udev_device_update_db(dev); - if (major(udev_device_get_devnum(dev)) != 0) { /* remove/update possible left-over symlinks from old database entry */ if (event->dev_db != NULL) udev_node_update_old_links(dev, event->dev_db); - if (event->name[0] != '\0') - err = udev_node_add(dev, event->mode, event->uid, event->gid); - else - info(event->udev, "device node creation suppressed\n"); - - /* remove kernel-created node, if needed */ - if (udev_device_get_knodename(dev) != NULL && strcmp(event->name, udev_device_get_knodename(dev)) != 0) { - struct stat stats; - char filename[UTIL_PATH_SIZE]; - - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", udev_device_get_knodename(dev), NULL); - if (stat(filename, &stats) == 0 && stats.st_rdev == udev_device_get_devnum(dev)) { - info(event->udev, "remove kernel created node '%s'\n", udev_device_get_knodename(dev)); - util_unlink_secure(event->udev, filename); - util_delete_path(event->udev, filename); - } - } + /* change default 0600 to 0660 if a group is assigned */ + if (event->mode == 0600 && event->gid > 0) + event->mode = 0660; + + err = udev_node_add(dev, event->mode, event->uid, event->gid); } + /* preserve old, or get new initialization timestamp */ + if (event->dev_db != NULL && udev_device_get_usec_initialized(event->dev_db) > 0) + udev_device_set_usec_initialized(event->dev, udev_device_get_usec_initialized(event->dev_db)); + else + udev_device_set_usec_initialized(event->dev, usec_monotonic()); + + /* (re)write database file */ + udev_device_update_db(dev); + udev_device_tag_index(dev, event->dev_db, true); + udev_device_set_is_initialized(dev); + udev_device_unref(event->dev_db); event->dev_db = NULL; } @@ -685,7 +684,11 @@ int udev_event_execute_run(struct udev_event *event, const sigset_t *sigmask) udev_event_apply_format(event, cmd, program, sizeof(program)); envp = udev_device_get_properties_envp(event->dev); - if (util_run_program(event->udev, program, envp, NULL, 0, NULL, sigmask) != 0) { + if (event->exec_delay > 0) { + info(event->udev, "delay execution of '%s'\n", program); + sleep(event->exec_delay); + } + if (util_run_program(event->udev, program, envp, NULL, 0, NULL, sigmask, true) != 0) { if (udev_list_entry_get_flags(list_entry)) err = -1; }