diff options
Diffstat (limited to '')
-rw-r--r-- | libgamepad_list_superdevices.c | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/libgamepad_list_superdevices.c b/libgamepad_list_superdevices.c index f8c7c4d..57068cb 100644 --- a/libgamepad_list_superdevices.c +++ b/libgamepad_list_superdevices.c @@ -5,7 +5,9 @@ int libgamepad_list_superdevices(char ***devicesp, size_t *ndevicesp) { - char path[PATH_MAX], target[PATH_MAX]; /* TODO do not use PATH_MAX */ + char *path, *target; + size_t path_size, target_size = 256; + const size_t path_size_base = sizeof("/sys/class/input//device/device"); int dirfd; DIR *dir; struct dirent *f; @@ -28,18 +30,48 @@ libgamepad_list_superdevices(char ***devicesp, size_t *ndevicesp) return -1; } + path_size = path_size_base + 255; + path_size = path_size > sizeof("/dev/fd/") + 3 * sizeof(int) ? path_size : sizeof("/dev/fd/") + 3 * sizeof(int); + path = malloc(path_size); + if (!path) + goto fail; + + target = malloc(target_size); + if (!target) + goto fail; + while (errno = 0, (f = readdir(dir))) { if (!strncmp(f->d_name, "event", 5) && isdigit(f->d_name[5])) { + if (path_size_base + strlen(f->d_name) > path_size) { + path_size = path_size_base + strlen(f->d_name); + new = realloc(path, path_size); + if (!new) + goto fail; + path = new; + } stpcpy(stpcpy(stpcpy(path, "/sys/class/input/"), f->d_name), "/device/device"); dirfd = open(path, O_PATH); if (dirfd < 0) continue; + sprintf(path, "/dev/fd/%i", dirfd); - r = readlink(path, target, sizeof(target) - 1); - close(dirfd); - if (r < 0) - continue; - target[r] = '\0'; + for (;;) { + r = readlink(path, target, target_size); + if (r < 0) { + close(dirfd); + goto next; + } + if ((size_t)r < target_size) { + close(dirfd); + target[r] = '\0'; + break; + } + new = realloc(target, target_size += 256); + if (!new) + goto fail; + target = new; + } + if (paths) for (i = 0; i < n; i++) if (!strcmp(paths[i], target)) @@ -61,6 +93,8 @@ libgamepad_list_superdevices(char ***devicesp, size_t *ndevicesp) if (errno) goto fail; + free(path); + free(target); closedir(dir); errno = saved_errno; @@ -72,6 +106,8 @@ fail: for (i = 0; i < n; i++) free(paths[i]); free(paths); + free(path); + free(target); closedir(dir); return -1; } |