event->fd_signal = -1;
event->birth_usec = now_usec();
event->timeout_usec = 30 * 1000 * 1000;
- dbg(event->udev, "allocated event %p\n", event);
return event;
}
udev_list_cleanup(&event->run_list);
free(event->program_result);
free(event->name);
- dbg(event->udev, "free event %p\n", event);
free(event);
}
SUBST_SYS,
};
static const struct subst_map {
- char *name;
- char fmt;
+ const char *name;
+ const char fmt;
enum subst_type type;
} map[] = {
{ .name = "devnode", .fmt = 'N', .type = SUBST_DEVNODE },
goto copy;
}
- for (i = 0; i < ARRAY_SIZE(map); i++) {
- if (strncmp(&from[1], map[i].name, strlen(map[i].name)) == 0) {
+ for (i = 0; i < ELEMENTSOF(map); i++) {
+ if (startswith(&from[1], map[i].name)) {
type = map[i].type;
from += strlen(map[i].name)+1;
- dbg(event->udev, "will substitute format name '%s'\n", map[i].name);
goto subst;
}
}
goto copy;
}
- for (i = 0; i < ARRAY_SIZE(map); i++) {
+ for (i = 0; i < ELEMENTSOF(map); i++) {
if (from[1] == map[i].fmt) {
type = map[i].type;
from += 2;
- dbg(event->udev, "will substitute format char '%c'\n", map[i].fmt);
goto subst;
}
}
from++;
for (i = 0; from[i] != '}'; i++) {
if (from[i] == '\0') {
- err(event->udev, "missing closing brace for format '%s'\n", src);
+ log_error("missing closing brace for format '%s'\n", src);
goto out;
}
}
switch (type) {
case SUBST_DEVPATH:
l = util_strpcpy(&s, l, udev_device_get_devpath(dev));
- dbg(event->udev, "substitute devpath '%s'\n", udev_device_get_devpath(dev));
break;
case SUBST_KERNEL:
l = util_strpcpy(&s, l, udev_device_get_sysname(dev));
- dbg(event->udev, "substitute kernel name '%s'\n", udev_device_get_sysname(dev));
break;
case SUBST_KERNEL_NUMBER:
if (udev_device_get_sysnum(dev) == NULL)
break;
l = util_strpcpy(&s, l, udev_device_get_sysnum(dev));
- dbg(event->udev, "substitute kernel number '%s'\n", udev_device_get_sysnum(dev));
break;
case SUBST_ID:
if (event->dev_parent == NULL)
break;
l = util_strpcpy(&s, l, udev_device_get_sysname(event->dev_parent));
- dbg(event->udev, "substitute id '%s'\n", udev_device_get_sysname(event->dev_parent));
break;
case SUBST_DRIVER: {
const char *driver;
if (driver == NULL)
break;
l = util_strpcpy(&s, l, driver);
- dbg(event->udev, "substitute driver '%s'\n", driver);
break;
}
case SUBST_MAJOR: {
sprintf(num, "%d", major(udev_device_get_devnum(dev)));
l = util_strpcpy(&s, l, num);
- dbg(event->udev, "substitute major number '%s'\n", num);
break;
}
case SUBST_MINOR: {
sprintf(num, "%d", minor(udev_device_get_devnum(dev)));
l = util_strpcpy(&s, l, num);
- dbg(event->udev, "substitute minor number '%s'\n", num);
break;
}
case SUBST_RESULT: {
char tmp[UTIL_PATH_SIZE];
char *cpos;
- dbg(event->udev, "request part #%d of result string\n", i);
util_strscpy(result, sizeof(result), event->program_result);
cpos = result;
while (--i) {
cpos++;
}
if (i > 0) {
- err(event->udev, "requested part of result string not found\n");
+ log_error("requested part of result string not found\n");
break;
}
util_strscpy(tmp, sizeof(tmp), cpos);
cpos[0] = '\0';
}
l = util_strpcpy(&s, l, tmp);
- dbg(event->udev, "substitute part of result string '%s'\n", tmp);
} else {
l = util_strpcpy(&s, l, event->program_result);
- dbg(event->udev, "substitute result string '%s'\n", event->program_result);
}
break;
}
int count;
if (attr == NULL) {
- err(event->udev, "missing file parameter for attr\n");
+ log_error("missing file parameter for attr\n");
break;
}
vbuf[len] = '\0';
count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT);
if (count > 0)
- info(event->udev, "%i character(s) replaced\n" , count);
+ log_debug("%i character(s) replaced\n" , count);
l = util_strpcpy(&s, l, vbuf);
- dbg(event->udev, "substitute sysfs value '%s'\n", vbuf);
break;
}
case SUBST_PARENT: {
if (dev_parent == NULL)
break;
devnode = udev_device_get_devnode(dev_parent);
- if (devnode != NULL) {
- size_t devlen = strlen(udev_get_dev_path(event->udev))+1;
-
- l = util_strpcpy(&s, l, &devnode[devlen]);
- dbg(event->udev, "found parent '%s', got node name '%s'\n",
- udev_device_get_syspath(dev_parent), &devnode[devlen]);
- }
+ if (devnode != NULL)
+ l = util_strpcpy(&s, l, devnode + strlen("/dev/"));
break;
}
case SUBST_DEVNODE:
if (udev_device_get_devnode(dev) != NULL)
l = util_strpcpy(&s, l, udev_device_get_devnode(dev));
break;
- case SUBST_NAME: {
- if (event->name != NULL) {
+ case SUBST_NAME:
+ if (event->name != NULL)
l = util_strpcpy(&s, l, event->name);
- dbg(event->udev, "substitute custom node name '%s'\n", event->name);
- } else if (udev_device_get_devnode(dev) != NULL) {
- size_t devlen = strlen(udev_get_dev_path(event->udev))+1;
-
- l = util_strpcpy(&s, l, &udev_device_get_devnode(dev)[devlen]);
- dbg(event->udev, "substitute node name'%s'\n", &udev_device_get_devnode(dev)[devlen]);
- } else {
+ else if (udev_device_get_devnode(dev) != NULL)
+ l = util_strpcpy(&s, l, udev_device_get_devnode(dev) + strlen("/dev/"));
+ else
l = util_strpcpy(&s, l, udev_device_get_sysname(dev));
- dbg(event->udev, "substitute device name'%s'\n", udev_device_get_sysname(dev));
- }
break;
- }
case SUBST_LINKS: {
- size_t devlen = strlen(udev_get_dev_path(event->udev))+1;
struct udev_list_entry *list_entry;
list_entry = udev_device_get_devlinks_list_entry(dev);
if (list_entry == NULL)
break;
- l = util_strpcpy(&s, l, &udev_list_entry_get_name(list_entry)[devlen]);
+ l = util_strpcpy(&s, l, udev_list_entry_get_name(list_entry) + strlen("/dev/"));
udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry))
- l = util_strpcpyl(&s, l, " ", &udev_list_entry_get_name(list_entry)[devlen], NULL);
+ l = util_strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry) + strlen("/dev/"), NULL);
break;
}
case SUBST_ROOT:
- l = util_strpcpy(&s, l, udev_get_dev_path(event->udev));
- dbg(event->udev, "substitute udev_root '%s'\n", udev_get_dev_path(event->udev));
+ l = util_strpcpy(&s, l, "/dev");
break;
case SUBST_SYS:
- l = util_strpcpy(&s, l, udev_get_sys_path(event->udev));
- dbg(event->udev, "substitute sys_path '%s'\n", udev_get_sys_path(event->udev));
+ l = util_strpcpy(&s, l, "/sys");
break;
case SUBST_ENV:
if (attr == NULL) {
- dbg(event->udev, "missing attribute\n");
break;
} else {
const char *value;
value = udev_device_get_property_value(event->dev, attr);
if (value == NULL)
break;
- dbg(event->udev, "substitute env '%s=%s'\n", attr, value);
l = util_strpcpy(&s, l, value);
break;
}
default:
- err(event->udev, "unknown substitution type=%i\n", type);
+ log_error("unknown substitution type=%i\n", type);
break;
}
}
out:
s[0] = '\0';
- dbg(event->udev, "'%s' -> '%s' (%zu)\n", src, dest, l);
return l;
}
const char *cmd, char *const argv[], char **envp, const sigset_t *sigmask,
int fd_stdout, int fd_stderr)
{
- struct udev *udev = event->udev;
int err;
int fd;
dup2(fd, STDERR_FILENO);
close(fd);
} else {
- err(udev, "open /dev/null failed: %m\n");
+ log_error("open /dev/null failed: %m\n");
}
/* connect pipes to std{out,err} */
/* exec failed */
err = -errno;
- err(udev, "failed to execute '%s' '%s': %m\n", argv[0], cmd);
+ log_error("failed to execute '%s' '%s': %m\n", argv[0], cmd);
return err;
}
int fd_stdout, int fd_stderr,
char *result, size_t ressize)
{
- struct udev *udev = event->udev;
size_t respos = 0;
int fd_ep = -1;
struct epoll_event ep_outpipe, ep_errpipe;
fd_ep = epoll_create1(EPOLL_CLOEXEC);
if (fd_ep < 0) {
- err(udev, "error creating epoll fd: %m\n");
+ log_error("error creating epoll fd: %m\n");
goto out;
}
ep_outpipe.events = EPOLLIN;
ep_outpipe.data.ptr = &fd_stdout;
if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stdout, &ep_outpipe) < 0) {
- err(udev, "fail to add fd to epoll: %m\n");
+ log_error("fail to add fd to epoll: %m\n");
goto out;
}
}
ep_errpipe.events = EPOLLIN;
ep_errpipe.data.ptr = &fd_stderr;
if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_stderr, &ep_errpipe) < 0) {
- err(udev, "fail to add fd to epoll: %m\n");
+ log_error("fail to add fd to epoll: %m\n");
goto out;
}
}
age_usec = now_usec() - event->birth_usec;
if (age_usec >= event->timeout_usec) {
- err(udev, "timeout '%s'\n", cmd);
+ log_error("timeout '%s'\n", cmd);
goto out;
}
timeout = ((event->timeout_usec - age_usec) / 1000) + 1000;
timeout = -1;
}
- fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), timeout);
+ fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), timeout);
if (fdcount < 0) {
if (errno == EINTR)
continue;
- err(udev, "failed to poll: %m\n");
+ log_error("failed to poll: %m\n");
goto out;
}
if (fdcount == 0) {
- err(udev, "timeout '%s'\n", cmd);
+ log_error("timeout '%s'\n", cmd);
goto out;
}
memcpy(&result[respos], buf, count);
respos += count;
} else {
- err(udev, "'%s' ressize %zd too short\n", cmd, ressize);
+ log_error("'%s' ressize %zd too short\n", cmd, ressize);
}
}
pos = buf;
while ((line = strsep(&pos, "\n"))) {
if (pos != NULL || line[0] != '\0')
- info(udev, "'%s'(%s) '%s'\n", cmd, *fd == fd_stdout ? "out" : "err" , line);
+ log_debug("'%s'(%s) '%s'\n", cmd, *fd == fd_stdout ? "out" : "err" , line);
}
}
} else if (ev[i].events & EPOLLHUP) {
if (epoll_ctl(fd_ep, EPOLL_CTL_DEL, *fd, NULL) < 0) {
- err(udev, "failed to remove fd from epoll: %m\n");
+ log_error("failed to remove fd from epoll: %m\n");
goto out;
}
*fd = -1;
}
/* return the child's stdout string */
- if (result != NULL) {
+ if (result != NULL)
result[respos] = '\0';
- dbg(udev, "result='%s'\n", result);
- }
out:
if (fd_ep >= 0)
close(fd_ep);
static int spawn_wait(struct udev_event *event, const char *cmd, pid_t pid)
{
- struct udev *udev = event->udev;
struct pollfd pfd[1];
int err = 0;
if (errno == EINTR)
continue;
err = -errno;
- err(udev, "failed to poll: %m\n");
+ log_error("failed to poll: %m\n");
goto out;
}
if (fdcount == 0) {
- err(udev, "timeout: killing '%s' [%u]\n", cmd, pid);
+ log_error("timeout: killing '%s' [%u]\n", cmd, pid);
kill(pid, SIGKILL);
}
if (waitpid(pid, &status, WNOHANG) < 0)
break;
if (WIFEXITED(status)) {
- info(udev, "'%s' [%u] exit with return code %i\n", cmd, pid, WEXITSTATUS(status));
+ log_debug("'%s' [%u] exit with return code %i\n", cmd, pid, WEXITSTATUS(status));
if (WEXITSTATUS(status) != 0)
err = -1;
} else if (WIFSIGNALED(status)) {
- err(udev, "'%s' [%u] terminated by signal %i (%s)\n", cmd, pid, WTERMSIG(status), strsignal(WTERMSIG(status)));
+ log_error("'%s' [%u] terminated by signal %i (%s)\n", cmd, pid, WTERMSIG(status), strsignal(WTERMSIG(status)));
err = -1;
} else if (WIFSTOPPED(status)) {
- err(udev, "'%s' [%u] stopped\n", cmd, pid);
+ log_error("'%s' [%u] stopped\n", cmd, pid);
err = -1;
} else if (WIFCONTINUED(status)) {
- err(udev, "'%s' [%u] continued\n", cmd, pid);
+ log_error("'%s' [%u] continued\n", cmd, pid);
err = -1;
} else {
- err(udev, "'%s' [%u] exit with status 0x%04x\n", cmd, pid, status);
+ log_error("'%s' [%u] exit with status 0x%04x\n", cmd, pid, status);
err = -1;
}
pid = 0;
while (pos[0] == ' ')
pos++;
}
- dbg(udev, "argv[%i] '%s'\n", i, argv[i]);
i++;
}
out:
if (result != NULL || udev_get_log_priority(udev) >= LOG_INFO) {
if (pipe2(outpipe, O_NONBLOCK) != 0) {
err = -errno;
- err(udev, "pipe failed: %m\n");
+ log_error("pipe failed: %m\n");
goto out;
}
}
if (udev_get_log_priority(udev) >= LOG_INFO) {
if (pipe2(errpipe, O_NONBLOCK) != 0) {
err = -errno;
- err(udev, "pipe failed: %m\n");
+ log_error("pipe failed: %m\n");
goto out;
}
}
errpipe[READ_END] = -1;
}
- info(udev, "starting '%s'\n", cmd);
+ log_debug("starting '%s'\n", cmd);
- err = spawn_exec(event, cmd, argv, envp, sigmask,
- outpipe[WRITE_END], errpipe[WRITE_END]);
+ spawn_exec(event, cmd, argv, envp, sigmask,
+ outpipe[WRITE_END], errpipe[WRITE_END]);
_exit(2 );
case -1:
- err(udev, "fork of '%s' failed: %m\n", cmd);
+ log_error("fork of '%s' failed: %m\n", cmd);
err = -1;
goto out;
default:
return err;
}
-static void rename_netif_kernel_log(struct ifreq ifr)
-{
- int klog;
- FILE *f;
-
- klog = open("/dev/kmsg", O_WRONLY);
- if (klog < 0)
- return;
-
- f = fdopen(klog, "w");
- if (f == NULL) {
- close(klog);
- return;
- }
-
- fprintf(f, "<30>udevd[%u]: renamed network interface %s to %s\n",
- getpid(), ifr.ifr_name, ifr.ifr_newname);
- fclose(f);
-}
-
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",
- udev_device_get_sysname(dev), event->name);
+ log_debug("changing net interface name from '%s' to '%s'\n",
+ udev_device_get_sysname(dev), event->name);
sk = socket(PF_INET, SOCK_DGRAM, 0);
if (sk < 0) {
err = -errno;
- err(event->udev, "error opening socket: %m\n");
+ log_error("error opening socket: %m\n");
return err;
}
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) {
- rename_netif_kernel_log(ifr);
- goto out;
- }
-
- /* 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 */
- snprintf(ifr.ifr_newname, IFNAMSIZ, "rename%u", udev_device_get_ifindex(dev));
- err = ioctl(sk, SIOCSIFNAME, &ifr);
- if (err < 0) {
- err = -errno;
- goto out;
- }
-
- /* log temporary name */
- rename_netif_kernel_log(ifr);
-
- /* 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 };
-
- 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;
- }
+ if (err >= 0) {
+ print_kmsg("renamed network interface %s to %s\n", ifr.ifr_name, ifr.ifr_newname);
+ } else {
err = -errno;
- if (err != -EEXIST)
- break;
+ log_error("error changing net interface name %s to %s: %m\n", ifr.ifr_name, ifr.ifr_newname);
}
-
-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;
}
err = rename_netif(event);
if (err == 0) {
- info(event->udev, "renamed netif to '%s'\n", event->name);
+ log_debug("renamed netif to '%s'\n", event->name);
/* remember old name */
udev_device_add_property(dev, "INTERFACE_OLD", udev_device_get_sysname(dev));
util_strscpy(pos, sizeof(syspath) - (pos - syspath), event->name);
udev_device_set_syspath(event->dev, syspath);
udev_device_add_property(dev, "INTERFACE", udev_device_get_sysname(dev));
- info(event->udev, "changed devpath to '%s'\n", udev_device_get_devpath(dev));
+ log_debug("changed devpath to '%s'\n", udev_device_get_devpath(dev));
}
}
}
udev_device_unref(event->dev_db);
event->dev_db = NULL;
}
-out:
return err;
}
-int udev_event_execute_run(struct udev_event *event, const sigset_t *sigmask)
+void udev_event_execute_run(struct udev_event *event, const sigset_t *sigmask)
{
struct udev_list_entry *list_entry;
- int err = 0;
- dbg(event->udev, "executing run list\n");
udev_list_entry_foreach(list_entry, udev_list_get_entry(&event->run_list)) {
const char *cmd = udev_list_entry_get_name(list_entry);
+ enum udev_builtin_cmd builtin_cmd = udev_list_entry_get_num(list_entry);
- if (strncmp(cmd, "socket:", strlen("socket:")) == 0) {
- struct udev_monitor *monitor;
+ if (builtin_cmd < UDEV_BUILTIN_MAX) {
+ char command[UTIL_PATH_SIZE];
- monitor = udev_monitor_new_from_socket(event->udev, &cmd[strlen("socket:")]);
- if (monitor == NULL)
- continue;
- udev_monitor_send_device(monitor, NULL, event->dev);
- udev_monitor_unref(monitor);
+ udev_event_apply_format(event, cmd, command, sizeof(command));
+ udev_builtin_run(event->dev, builtin_cmd, command, false);
} else {
char program[UTIL_PATH_SIZE];
char **envp;
if (event->exec_delay > 0) {
- info(event->udev, "delay execution of '%s'\n", program);
+ log_debug("delay execution of '%s'\n", program);
sleep(event->exec_delay);
}
udev_event_apply_format(event, cmd, program, sizeof(program));
envp = udev_device_get_properties_envp(event->dev);
- if (udev_event_spawn(event, program, envp, sigmask, NULL, 0) < 0) {
- if (udev_list_entry_get_num(list_entry))
- err = -1;
- }
+ udev_event_spawn(event, program, envp, sigmask, NULL, 0);
}
}
- return err;
}