Skip to content

Commit 537ce84

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

1 file changed

Lines changed: 94 additions & 11 deletions

File tree

udev_device.c

Lines changed: 94 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,10 @@
5254
#define INPUT_PROP_CNT 0x20
5355
#endif
5456

57+
#ifndef RULES_HELPER_NAME
58+
#define RULES_HELPER_NAME "libudev-zero-rules-helper"
59+
#endif
60+
5561
struct udev_device {
5662
struct udev_list_entry properties;
5763
struct udev_list_entry sysattrs;
@@ -349,19 +355,10 @@ static char *read_symlink(const char *syspath, const char *name)
349355
return strdup(strrchr(link, '/') + 1);
350356
}
351357

352-
static int set_properties_from_uevent(struct udev_device *udev_device, const char *syspath)
358+
static void set_properties_from_file(struct udev_device *udev_device, FILE *file)
353359
{
354-
char line[LINE_MAX], path[PATH_MAX + sizeof("/uevent")], devnode[PATH_MAX];
355-
FILE *file;
360+
char line[LINE_MAX], devnode[PATH_MAX];
356361
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-
365362
while (fgets(line, sizeof(line), file)) {
366363
line[strlen(line) - 1] = '\0';
367364

@@ -374,7 +371,21 @@ static int set_properties_from_uevent(struct udev_device *udev_device, const cha
374371
udev_list_entry_add(&udev_device->properties, line, pos + 1, 0);
375372
}
376373
}
374+
}
375+
376+
static int set_properties_from_uevent(struct udev_device *udev_device, const char *syspath)
377+
{
378+
char path[PATH_MAX + sizeof("/uevent")];
379+
FILE *file;
380+
381+
snprintf(path, sizeof(path), "%s/uevent", syspath);
382+
file = fopen(path, "r");
383+
384+
if (!file) {
385+
return -1;
386+
}
377387

388+
set_properties_from_file(udev_device, file);
378389
fclose(file);
379390
return 0;
380391
}
@@ -540,6 +551,76 @@ static void set_properties_from_props(struct udev_device *udev_device)
540551
udev_list_entry_add(&udev_device->properties, "ID_PATH", id, 0);
541552
}
542553

554+
static int set_properties_from_helper(struct udev_device *udev_device)
555+
{
556+
size_t size = 0;
557+
size_t count = 0;
558+
struct udev_list_entry *entry;
559+
for (entry = udev_device_get_properties_list_entry(udev_device);
560+
entry;
561+
entry = udev_list_entry_get_next(entry)) {
562+
563+
const char *name = entry->name;
564+
const char *value = entry->value?entry->value:"";
565+
// '{name}={value}\0'
566+
size += strlen(name) + 1 + strlen(value) + 1;
567+
count += 1;
568+
}
569+
570+
char **envp = malloc((count + 1) * sizeof(char *));
571+
char *env = malloc(size);
572+
char *ptr = env;
573+
unsigned i = 0;
574+
for (entry = udev_device_get_properties_list_entry(udev_device);
575+
entry;
576+
entry = udev_list_entry_get_next(entry)) {
577+
const char *name = entry->name;
578+
const char *value = entry->value?entry->value:"";
579+
// '{name}={value}\0'
580+
size_t max_size = strlen(name) + 1 + strlen(value) + 1;
581+
snprintf(ptr, max_size, "%s=%s", name, value);
582+
envp[i] = ptr;
583+
ptr += max_size;
584+
i++;
585+
}
586+
envp[count] = NULL;
587+
588+
int out_pipe[2];
589+
posix_spawn_file_actions_t actions;
590+
pipe(out_pipe);
591+
592+
posix_spawn_file_actions_init(&actions);
593+
posix_spawn_file_actions_addclose(&actions, out_pipe[0]);
594+
posix_spawn_file_actions_adddup2(&actions, out_pipe[1], 1);
595+
posix_spawn_file_actions_addclose(&actions, out_pipe[1]);
596+
597+
pid_t pid;
598+
599+
char *argv[] = { RULES_HELPER_NAME, NULL };
600+
601+
if (posix_spawnp(&pid, argv[0], &actions, NULL, argv, envp)) {
602+
perror("Could not launch properties helper");
603+
return -1;
604+
}
605+
606+
free(envp);
607+
free(env);
608+
close(out_pipe[1]);
609+
610+
FILE *file = fdopen(out_pipe[0], "r");
611+
612+
if (!file) {
613+
return -1;
614+
}
615+
616+
set_properties_from_file(udev_device, file);
617+
618+
int status;
619+
waitpid(pid, &status, 0);
620+
close(out_pipe[0]);
621+
return 0;
622+
}
623+
543624
struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath)
544625
{
545626
char *subsystem, *driver, *sysname;
@@ -593,6 +674,7 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *
593674

594675
set_properties_from_evdev(udev_device);
595676
set_properties_from_props(udev_device);
677+
set_properties_from_helper(udev_device);
596678

597679
free(driver);
598680
free(subsystem);
@@ -712,6 +794,7 @@ struct udev_device *udev_device_new_from_uevent(struct udev *udev, char *buf, si
712794

713795
set_properties_from_props(udev_device);
714796
set_properties_from_evdev(udev_device);
797+
set_properties_from_helper(udev_device);
715798
return udev_device;
716799
}
717800

0 commit comments

Comments
 (0)