Skip to content

Commit 3026c4e

Browse files
committed
Allow invoking helper script as a replacement for udev rules
1 parent bbeb7ad commit 3026c4e

1 file changed

Lines changed: 96 additions & 11 deletions

File tree

udev_device.c

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
#include <string.h>
2121
#include <stdlib.h>
2222
#include <limits.h>
23+
#include <spawn.h>
2324
#include <sys/stat.h>
25+
#include <sys/wait.h>
2426
#include <linux/input.h>
2527

2628
#include "udev.h"
@@ -52,6 +54,18 @@
5254
#define INPUT_PROP_CNT 0x20
5355
#endif
5456

57+
#ifndef RULES_HELPER_PATH
58+
#define RULES_HELPER_PATH "/sbin/libudev-zero-rules-helper"
59+
#endif
60+
61+
#ifndef UEVENT_NUM_ENVP
62+
#define UEVENT_NUM_ENVP 64
63+
#endif
64+
65+
#ifndef UEVENT_BUFFER_SIZE
66+
#define UEVENT_BUFFER_SIZE 2048
67+
#endif
68+
5569
struct udev_device {
5670
struct udev_list_entry properties;
5771
struct udev_list_entry sysattrs;
@@ -349,19 +363,10 @@ static char *read_symlink(const char *syspath, const char *name)
349363
return strdup(strrchr(link, '/') + 1);
350364
}
351365

352-
static int set_properties_from_uevent(struct udev_device *udev_device, const char *syspath)
366+
static void set_properties_from_file(struct udev_device *udev_device, FILE *file)
353367
{
354-
char line[LINE_MAX], path[PATH_MAX + sizeof("/uevent")], devnode[PATH_MAX];
355-
FILE *file;
368+
char line[LINE_MAX], devnode[PATH_MAX];
356369
char *pos;
357-
358-
snprintf(path, sizeof(path), "%s/uevent", syspath);
359-
file = fopen(path, "r");
360-
361-
if (!file) {
362-
return -1;
363-
}
364-
365370
while (fgets(line, sizeof(line), file)) {
366371
line[strlen(line) - 1] = '\0';
367372

@@ -374,7 +379,21 @@ static int set_properties_from_uevent(struct udev_device *udev_device, const cha
374379
udev_list_entry_add(&udev_device->properties, line, pos + 1, 0);
375380
}
376381
}
382+
}
383+
384+
static int set_properties_from_uevent(struct udev_device *udev_device, const char *syspath)
385+
{
386+
char path[PATH_MAX + sizeof("/uevent")];
387+
FILE *file;
388+
389+
snprintf(path, sizeof(path), "%s/uevent", syspath);
390+
file = fopen(path, "r");
391+
392+
if (!file) {
393+
return -1;
394+
}
377395

396+
set_properties_from_file(udev_device, file);
378397
fclose(file);
379398
return 0;
380399
}
@@ -540,6 +559,70 @@ static void set_properties_from_props(struct udev_device *udev_device)
540559
udev_list_entry_add(&udev_device->properties, "ID_PATH", id, 0);
541560
}
542561

562+
static int set_properties_from_helper(struct udev_device *udev_device)
563+
{
564+
char *envp[UEVENT_NUM_ENVP];
565+
char env[UEVENT_BUFFER_SIZE];
566+
567+
char *ptr = env;
568+
size_t i = 0;
569+
struct udev_list_entry *entry;
570+
571+
for (entry = udev_device_get_properties_list_entry(udev_device);
572+
entry;
573+
entry = udev_list_entry_get_next(entry)) {
574+
const char *name = entry->name;
575+
const char *value = entry->value ? entry->value : "";
576+
577+
// '{name}={value}\0'
578+
size_t max_size = strlen(name) + 1 + strlen(value) + 1;
579+
snprintf(ptr, max_size, "%s=%s", name, value);
580+
581+
envp[i] = ptr;
582+
ptr += max_size;
583+
i++;
584+
}
585+
586+
envp[i] = NULL;
587+
588+
int out_pipe[2];
589+
590+
if (pipe(out_pipe)) {
591+
return -1;
592+
}
593+
594+
posix_spawn_file_actions_t actions;
595+
596+
posix_spawn_file_actions_init(&actions);
597+
posix_spawn_file_actions_addclose(&actions, out_pipe[0]);
598+
posix_spawn_file_actions_adddup2(&actions, out_pipe[1], 1);
599+
posix_spawn_file_actions_addclose(&actions, out_pipe[1]);
600+
601+
pid_t pid;
602+
603+
char argv0[] = RULES_HELPER_PATH;
604+
char *argv[] = { argv0, NULL };
605+
606+
if (posix_spawn(&pid, argv0, &actions, NULL, argv, envp)) {
607+
return -1;
608+
}
609+
610+
close(out_pipe[1]);
611+
612+
FILE *file = fdopen(out_pipe[0], "r");
613+
614+
if (!file) {
615+
return -1;
616+
}
617+
618+
set_properties_from_file(udev_device, file);
619+
620+
int status;
621+
waitpid(pid, &status, 0);
622+
fclose(file);
623+
return 0;
624+
}
625+
543626
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath)
544627
{
545628
char *subsystem, *driver, *sysname;
@@ -593,6 +676,7 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *
593676

594677
set_properties_from_evdev(udev_device);
595678
set_properties_from_props(udev_device);
679+
set_properties_from_helper(udev_device);
596680

597681
free(driver);
598682
free(subsystem);
@@ -712,6 +796,7 @@ struct udev_device *udev_device_new_from_uevent(struct udev *udev, char *buf, si
712796

713797
set_properties_from_props(udev_device);
714798
set_properties_from_evdev(udev_device);
799+
set_properties_from_helper(udev_device);
715800
return udev_device;
716801
}
717802

0 commit comments

Comments
 (0)