tools: use __attribute__(cleanup)

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1184>
This commit is contained in:
Peter Hutterer 2025-04-01 13:42:27 +10:00
parent d5e2bb1267
commit 0ecd08c134
5 changed files with 140 additions and 250 deletions

View file

@ -100,7 +100,7 @@ handle_and_print_events(struct libinput *li, const struct libinput_print_options
} }
if (type != LIBINPUT_EVENT_TOUCH_FRAME || !compress_motion_events) { if (type != LIBINPUT_EVENT_TOUCH_FRAME || !compress_motion_events) {
char *event_str = libinput_event_to_str(ev, event_repeat_count + 1, opts); _autofree_ char *event_str = libinput_event_to_str(ev, event_repeat_count + 1, opts);
switch (type) { switch (type) {
case LIBINPUT_EVENT_DEVICE_ADDED: case LIBINPUT_EVENT_DEVICE_ADDED:
@ -120,7 +120,6 @@ handle_and_print_events(struct libinput *li, const struct libinput_print_options
} }
printq("%s\n", event_str); printq("%s\n", event_str);
free(event_str);
} }
last_device = device; last_device = device;

View file

@ -32,6 +32,8 @@
#include "quirks.h" #include "quirks.h"
#include "shared.h" #include "shared.h"
#include "builddir.h" #include "builddir.h"
#include "util-mem.h"
#include "libinput-util.h"
static bool verbose = false; static bool verbose = false;
@ -94,13 +96,8 @@ simple_printf(void *userdata, const char *val)
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
struct udev *udev = NULL;
struct udev_device *device = NULL;
const char *path;
const char *data_path = NULL, const char *data_path = NULL,
*override_file = NULL; *override_file = NULL;
int rc = 1;
struct quirks_context *quirks;
bool validate = false; bool validate = false;
while (1) { while (1) {
@ -137,31 +134,31 @@ main(int argc, char **argv)
break; break;
default: default:
usage(); usage();
return 1; return EXIT_FAILURE;
} }
} }
if (optind >= argc) { if (optind >= argc) {
usage(); usage();
return 1; return EXIT_FAILURE;
} }
if (streq(argv[optind], "list")) { if (streq(argv[optind], "list")) {
optind++; optind++;
if (optind >= argc) { if (optind >= argc) {
usage(); usage();
return 1; return EXIT_FAILURE;
} }
} else if (streq(argv[optind], "validate")) { } else if (streq(argv[optind], "validate")) {
optind++; optind++;
if (optind < argc) { if (optind < argc) {
usage(); usage();
return 1; return EXIT_FAILURE;
} }
validate = true; validate = true;
} else { } else {
fprintf(stderr, "Unnkown action '%s'\n", argv[optind]); fprintf(stderr, "Unnkown action '%s'\n", argv[optind]);
return 1; return EXIT_FAILURE;
} }
/* Overriding the data dir means no custom override file */ /* Overriding the data dir means no custom override file */
@ -174,53 +171,44 @@ main(int argc, char **argv)
} }
} }
quirks = quirks_init_subsystem(data_path, _unref_(quirks_context) *quirks = quirks_init_subsystem(data_path,
override_file, override_file,
log_handler, log_handler,
NULL, NULL,
QLOG_CUSTOM_LOG_PRIORITIES); QLOG_CUSTOM_LOG_PRIORITIES);
if (!quirks) { if (!quirks) {
fprintf(stderr, fprintf(stderr,
"Failed to initialize the device quirks. " "Failed to initialize the device quirks. "
"Please see the above errors " "Please see the above errors "
"and/or re-run with --verbose for more details\n"); "and/or re-run with --verbose for more details\n");
return 1; return EXIT_FAILURE;
} }
if (validate) { if (validate)
rc = 0; return EXIT_SUCCESS;
goto out;
}
udev = udev_new(); _unref_(udev) *udev = udev_new();
if (!udev) if (!udev)
goto out; return EXIT_FAILURE;
path = argv[optind]; _unref_(udev_device) *device = NULL;
const char *path = argv[optind];
if (strstartswith(path, "/sys/")) { if (strstartswith(path, "/sys/")) {
device = udev_device_new_from_syspath(udev, path); device = udev_device_new_from_syspath(udev, path);
} else { } else {
struct stat st; struct stat st;
if (stat(path, &st) < 0) { if (stat(path, &st) < 0) {
fprintf(stderr, "Error: %s: %m\n", path); fprintf(stderr, "Error: %s: %m\n", path);
goto out; return EXIT_FAILURE;
} }
device = udev_device_new_from_devnum(udev, 'c', st.st_rdev); device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
} }
if (device) { if (device) {
tools_list_device_quirks(quirks, device, simple_printf, NULL); tools_list_device_quirks(quirks, device, simple_printf, NULL);
rc = 0; return EXIT_SUCCESS;
} else { } else {
usage(); usage();
rc = 1; return EXIT_FAILURE;
} }
udev_device_unref(device);
out:
udev_unref(udev);
quirks_context_unref(quirks);
return rc;
} }

View file

@ -49,11 +49,14 @@
#include "shared.h" #include "shared.h"
#include "builddir.h" #include "builddir.h"
#include "util-bits.h" #include "util-bits.h"
#include "util-files.h"
#include "util-list.h" #include "util-list.h"
#include "util-time.h" #include "util-time.h"
#include "util-input-event.h" #include "util-input-event.h"
#include "util-macros.h" #include "util-macros.h"
#include "util-mem.h"
#include "util-strings.h" #include "util-strings.h"
#include "libinput-util.h"
static const int FILE_VERSION_NUMBER = 1; static const int FILE_VERSION_NUMBER = 1;
@ -785,28 +788,26 @@ buffer_tablet_axes(struct libinput_event_tablet_tool *t)
{ {
const int MAX_AXES = 10; const int MAX_AXES = 10;
struct libinput_tablet_tool *tool; struct libinput_tablet_tool *tool;
char *s = NULL;
int idx = 0; int idx = 0;
int len; int len;
double x, y; double x, y;
char **strv;
tool = libinput_event_tablet_tool_get_tool(t); tool = libinput_event_tablet_tool_get_tool(t);
strv = zalloc(MAX_AXES * sizeof *strv); _autostrvfree_ char **strv = zalloc(MAX_AXES * sizeof *strv);
x = libinput_event_tablet_tool_get_x(t); x = libinput_event_tablet_tool_get_x(t);
y = libinput_event_tablet_tool_get_y(t); y = libinput_event_tablet_tool_get_y(t);
len = xasprintf(&strv[idx++], "point: [%.2f, %.2f]", x, y); len = xasprintf(&strv[idx++], "point: [%.2f, %.2f]", x, y);
if (len <= 0) if (len <= 0)
goto out; return NULL;
if (libinput_tablet_tool_has_tilt(tool)) { if (libinput_tablet_tool_has_tilt(tool)) {
x = libinput_event_tablet_tool_get_tilt_x(t); x = libinput_event_tablet_tool_get_tilt_x(t);
y = libinput_event_tablet_tool_get_tilt_y(t); y = libinput_event_tablet_tool_get_tilt_y(t);
len = xasprintf(&strv[idx++], "tilt: [%.2f, %.2f]", x, y); len = xasprintf(&strv[idx++], "tilt: [%.2f, %.2f]", x, y);
if (len <= 0) if (len <= 0)
goto out; return NULL;
} }
if (libinput_tablet_tool_has_distance(tool) || if (libinput_tablet_tool_has_distance(tool) ||
@ -820,7 +821,7 @@ buffer_tablet_axes(struct libinput_event_tablet_tool *t)
else else
len = xasprintf(&strv[idx++], "pressure: %.2f", pressure); len = xasprintf(&strv[idx++], "pressure: %.2f", pressure);
if (len <= 0) if (len <= 0)
goto out; return NULL;
} }
if (libinput_tablet_tool_has_rotation(tool)) { if (libinput_tablet_tool_has_rotation(tool)) {
@ -829,7 +830,7 @@ buffer_tablet_axes(struct libinput_event_tablet_tool *t)
rotation = libinput_event_tablet_tool_get_rotation(t); rotation = libinput_event_tablet_tool_get_rotation(t);
len = xasprintf(&strv[idx++], "rotation: %.2f", rotation); len = xasprintf(&strv[idx++], "rotation: %.2f", rotation);
if (len <= 0) if (len <= 0)
goto out; return NULL;
} }
if (libinput_tablet_tool_has_slider(tool)) { if (libinput_tablet_tool_has_slider(tool)) {
@ -838,8 +839,7 @@ buffer_tablet_axes(struct libinput_event_tablet_tool *t)
slider = libinput_event_tablet_tool_get_slider_position(t); slider = libinput_event_tablet_tool_get_slider_position(t);
len = xasprintf(&strv[idx++], "slider: %.2f", slider); len = xasprintf(&strv[idx++], "slider: %.2f", slider);
if (len <= 0) if (len <= 0)
goto out; return NULL;
} }
if (libinput_tablet_tool_has_wheel(tool)) { if (libinput_tablet_tool_has_wheel(tool)) {
@ -849,20 +849,17 @@ buffer_tablet_axes(struct libinput_event_tablet_tool *t)
wheel = libinput_event_tablet_tool_get_wheel_delta(t); wheel = libinput_event_tablet_tool_get_wheel_delta(t);
len = xasprintf(&strv[idx++], "wheel: %.2f", wheel); len = xasprintf(&strv[idx++], "wheel: %.2f", wheel);
if (len <= 0) if (len <= 0)
goto out; return NULL;
delta = libinput_event_tablet_tool_get_wheel_delta_discrete(t); delta = libinput_event_tablet_tool_get_wheel_delta_discrete(t);
len = xasprintf(&strv[idx++], "wheel-discrete: %d", delta); len = xasprintf(&strv[idx++], "wheel-discrete: %d", delta);
if (len <= 0) if (len <= 0)
goto out; return NULL;
} }
assert(idx < MAX_AXES); assert(idx < MAX_AXES);
s = strv_join(strv, ", "); return strv_join(strv, ", ");
out:
strv_free(strv);
return s;
} }
static void static void
@ -874,7 +871,6 @@ print_tablet_tool_proximity_event(struct record_device *dev, struct libinput_eve
libinput_event_tablet_tool_get_tool(t); libinput_event_tablet_tool_get_tool(t);
uint64_t time; uint64_t time;
const char *type, *tool_type; const char *type, *tool_type;
char *axes;
char caps[10] = {0}; char caps[10] = {0};
enum libinput_tablet_tool_proximity_state prox; enum libinput_tablet_tool_proximity_state prox;
size_t idx; size_t idx;
@ -916,7 +912,7 @@ print_tablet_tool_proximity_event(struct record_device *dev, struct libinput_eve
prox = libinput_event_tablet_tool_get_proximity_state(t); prox = libinput_event_tablet_tool_get_proximity_state(t);
time = time_offset(dev->ctx, libinput_event_tablet_tool_get_time_usec(t)); time = time_offset(dev->ctx, libinput_event_tablet_tool_get_time_usec(t));
axes = buffer_tablet_axes(t); _autofree_ char *axes = buffer_tablet_axes(t);
idx = 0; idx = 0;
if (libinput_tablet_tool_has_pressure(tool)) if (libinput_tablet_tool_has_pressure(tool))
@ -944,7 +940,6 @@ print_tablet_tool_proximity_event(struct record_device *dev, struct libinput_eve
libinput_tablet_tool_get_serial(tool), libinput_tablet_tool_get_serial(tool),
caps, caps,
axes); axes);
free(axes);
} }
static void static void
@ -987,7 +982,6 @@ print_tablet_tool_event(struct record_device *dev, struct libinput_event *e)
libinput_event_get_tablet_tool_event(e); libinput_event_get_tablet_tool_event(e);
uint64_t time; uint64_t time;
const char *type; const char *type;
char *axes;
enum libinput_tablet_tool_tip_state tip; enum libinput_tablet_tool_tip_state tip;
char btn_buffer[30] = {0}; char btn_buffer[30] = {0};
@ -1019,7 +1013,7 @@ print_tablet_tool_event(struct record_device *dev, struct libinput_event *e)
tip = libinput_event_tablet_tool_get_tip_state(t); tip = libinput_event_tablet_tool_get_tip_state(t);
time = time_offset(dev->ctx, libinput_event_tablet_tool_get_time_usec(t)); time = time_offset(dev->ctx, libinput_event_tablet_tool_get_time_usec(t));
axes = buffer_tablet_axes(t); _autofree_ char *axes = buffer_tablet_axes(t);
iprintf(dev->fp, iprintf(dev->fp,
I_EVENT, I_EVENT,
@ -1030,7 +1024,6 @@ print_tablet_tool_event(struct record_device *dev, struct libinput_event *e)
btn_buffer, /* may be empty string */ btn_buffer, /* may be empty string */
tip ? "down" : "up", tip ? "down" : "up",
axes); axes);
free(axes);
} }
static void static void
@ -1349,17 +1342,15 @@ print_system_header(FILE *fp)
{ {
struct utsname u; struct utsname u;
const char *kernel = "unknown"; const char *kernel = "unknown";
FILE *dmi, *osrelease;
char dmistr[2048] = "unknown";
iprintf(fp, I_TOPLEVEL, "system:\n"); iprintf(fp, I_TOPLEVEL, "system:\n");
/* /etc/os-release version and distribution name */ /* /etc/os-release version and distribution name */
osrelease = fopen("/etc/os-release", "r"); _autofclose_ FILE *osrelease = fopen("/etc/os-release", "r");
if (!osrelease) if (!osrelease)
osrelease = fopen("/usr/lib/os-release", "r"); osrelease = fopen("/usr/lib/os-release", "r");
if (osrelease) { if (osrelease) {
char *distro = NULL, *version = NULL; _autofree_ char *distro = NULL, *version = NULL;
char osrstr[256] = "unknown"; char osrstr[256] = "unknown";
while (fgets(osrstr, sizeof(osrstr), osrelease)) { while (fgets(osrstr, sizeof(osrstr), osrelease)) {
@ -1370,18 +1361,17 @@ print_system_header(FILE *fp)
else if (!version && strstartswith(osrstr, "VERSION_ID=")) else if (!version && strstartswith(osrstr, "VERSION_ID="))
version = strstrip(&osrstr[11], "\"'"); version = strstrip(&osrstr[11], "\"'");
if (distro && version) { if (distro && version)
iprintf(fp,
I_SYSTEM,
"os: \"%s:%s\"\n",
distro,
version);
break; break;
}
} }
free(distro);
free(version); if (distro && version) { // NOLINT: unix.Stream
fclose(osrelease); iprintf(fp,
I_SYSTEM,
"os: \"%s:%s\"\n",
distro,
version);
}
} }
/* kernel version */ /* kernel version */
@ -1390,14 +1380,15 @@ print_system_header(FILE *fp)
iprintf(fp, I_SYSTEM, "kernel: \"%s\"\n", kernel); iprintf(fp, I_SYSTEM, "kernel: \"%s\"\n", kernel);
/* dmi modalias */ /* dmi modalias */
dmi = fopen("/sys/class/dmi/id/modalias", "r"); _autofclose_ FILE *dmi = fopen("/sys/class/dmi/id/modalias", "r");
_autofree_ char *dmistr = strdup("unknown"); //
if (dmi) { if (dmi) {
if (fgets(dmistr, sizeof(dmistr), dmi)) { char buf[2048] = "unknown";
dmistr[strlen(dmistr) - 1] = '\0'; /* linebreak */ size_t n = fread(buf, sizeof(buf), 1, dmi); // NOLINT: unix.Stream
} else { if (n > 0) {
sprintf(dmistr, "unknown"); free(dmistr);
dmistr = strndup(buf, n - 1);
} }
fclose(dmi);
} }
iprintf(fp, I_SYSTEM, "dmi: \"%s\"\n", dmistr); iprintf(fp, I_SYSTEM, "dmi: \"%s\"\n", dmistr);
} }
@ -1720,27 +1711,24 @@ print_hid_report_descriptor(struct record_device *dev)
static void static void
print_udev_properties(struct record_device *dev) print_udev_properties(struct record_device *dev)
{ {
struct udev *udev = NULL;
struct udev_device *udev_device = NULL;
struct udev_list_entry *entry;
struct stat st; struct stat st;
if (stat(dev->devnode, &st) < 0) if (stat(dev->devnode, &st) < 0)
return; return;
udev = udev_new(); _unref_(udev) *udev = udev_new();
if (!udev) if (!udev)
goto out; return;
udev_device = udev_device_new_from_devnum(udev, 'c', st.st_rdev); _unref_(udev_device) *udev_device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
if (!udev_device) if (!udev_device)
goto out; return;
iprintf(dev->fp, I_DEVICE, "udev:\n"); iprintf(dev->fp, I_DEVICE, "udev:\n");
iprintf(dev->fp, I_UDEV, "properties:\n"); iprintf(dev->fp, I_UDEV, "properties:\n");
entry = udev_device_get_properties_list_entry(udev_device); struct udev_list_entry *entry = udev_device_get_properties_list_entry(udev_device);
while (entry) { while (entry) {
const char *key, *value; const char *key, *value;
@ -1768,10 +1756,6 @@ print_udev_properties(struct record_device *dev)
break; break;
} }
} }
out:
udev_device_unref(udev_device);
udev_unref(udev);
} }
static void static void
@ -1793,10 +1777,7 @@ list_print(void *userdata, const char *val)
static void static void
print_device_quirks(struct record_device *dev) print_device_quirks(struct record_device *dev)
{ {
struct udev *udev = NULL;
struct udev_device *udev_device = NULL;
struct stat st; struct stat st;
struct quirks_context *quirks;
const char *data_path = LIBINPUT_QUIRKS_DIR; const char *data_path = LIBINPUT_QUIRKS_DIR;
const char *override_file = LIBINPUT_QUIRKS_OVERRIDE_FILE; const char *override_file = LIBINPUT_QUIRKS_OVERRIDE_FILE;
@ -1809,11 +1790,11 @@ print_device_quirks(struct record_device *dev)
override_file = NULL; override_file = NULL;
} }
quirks = quirks_init_subsystem(data_path, _unref_(quirks_context) *quirks = quirks_init_subsystem(data_path,
override_file, override_file,
quirks_log_handler, quirks_log_handler,
NULL, NULL,
QLOG_CUSTOM_LOG_PRIORITIES); QLOG_CUSTOM_LOG_PRIORITIES);
if (!quirks) { if (!quirks) {
fprintf(stderr, fprintf(stderr,
"Failed to load the device quirks from %s%s%s. " "Failed to load the device quirks from %s%s%s. "
@ -1826,20 +1807,15 @@ print_device_quirks(struct record_device *dev)
return; return;
} }
udev = udev_new(); _unref_(udev) *udev = udev_new();
if (!udev) if (!udev)
goto out; return;
udev_device = udev_device_new_from_devnum(udev, 'c', st.st_rdev); _unref_(udev_device) *udev_device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
if (!udev_device) if (udev_device) {
goto out; iprintf(dev->fp, I_DEVICE, "quirks:\n");
tools_list_device_quirks(quirks, udev_device, list_print, dev->fp);
iprintf(dev->fp, I_DEVICE, "quirks:\n"); }
tools_list_device_quirks(quirks, udev_device, list_print, dev->fp);
out:
udev_device_unref(udev_device);
udev_unref(udev);
quirks_context_unref(quirks);
} }
static void static void
@ -1903,7 +1879,7 @@ static int is_event_node(const struct dirent *dir) {
static char * static char *
select_device(void) select_device(void)
{ {
struct dirent **namelist; _autofree_ struct dirent **namelist;
int ndev, selected_device; int ndev, selected_device;
int rc; int rc;
char *device_path; char *device_path;
@ -1920,23 +1896,19 @@ select_device(void)
fprintf(stderr, "%sAvailable devices:\n", prefix); fprintf(stderr, "%sAvailable devices:\n", prefix);
for (int i = 0; i < ndev; i++) { for (int i = 0; i < ndev; i++) {
struct libevdev *device; _autofree_ struct dirent *entry = namelist[i];
char path[PATH_MAX]; char path[PATH_MAX];
int fd = -1;
snprintf(path, snprintf(path, sizeof(path), "/dev/input/%s", entry->d_name);
sizeof(path), _cleanup_(xclose) int fd = open(path, O_RDONLY);
"/dev/input/%s",
namelist[i]->d_name);
fd = open(path, O_RDONLY);
if (fd < 0) { if (fd < 0) {
if (errno == EACCES) if (errno == EACCES)
has_eaccess = true; has_eaccess = true;
continue; continue;
} }
struct libevdev *device;
rc = libevdev_new_from_fd(fd, &device); rc = libevdev_new_from_fd(fd, &device);
close(fd);
if (rc != 0) if (rc != 0)
continue; continue;
@ -1945,10 +1917,6 @@ select_device(void)
available_devices++; available_devices++;
} }
for (int i = 0; i < ndev; i++)
free(namelist[i]);
free(namelist);
if (available_devices == 0) { if (available_devices == 0) {
fprintf(stderr, fprintf(stderr,
"No devices available.%s\n", "No devices available.%s\n",
@ -1972,9 +1940,9 @@ select_device(void)
static char ** static char **
all_devices(void) all_devices(void)
{ {
struct dirent **namelist; _autofree_ struct dirent **namelist;
int ndev; int ndev;
char **devices = NULL; _autostrvfree_ char **devices = NULL;
ndev = scandir("/dev/input", &namelist, is_event_node, versionsort); ndev = scandir("/dev/input", &namelist, is_event_node, versionsort);
if (ndev <= 0) if (ndev <= 0)
@ -1982,26 +1950,17 @@ all_devices(void)
devices = zalloc((ndev + 1)* sizeof *devices); /* NULL-terminated */ devices = zalloc((ndev + 1)* sizeof *devices); /* NULL-terminated */
for (int i = 0; i < ndev; i++) { for (int i = 0; i < ndev; i++) {
_autofree_ struct dirent *entry = namelist[i];
char *device_path; char *device_path;
int rc = xasprintf(&device_path, int rc = xasprintf(&device_path, "/dev/input/%s", entry->d_name);
"/dev/input/%s",
namelist[i]->d_name);
if (rc == -1) if (rc == -1)
goto error; return NULL;
devices[i] = device_path; devices[i] = device_path;
} }
return devices; return steal(&devices);
error:
for (int i = 0; i < ndev; i++)
free(namelist[i]);
free(namelist);
if (devices)
strv_free(devices);
return NULL;
} }
static char * static char *
@ -2111,27 +2070,24 @@ add_source(struct record_context *ctx,
source_dispatch_t dispatch, source_dispatch_t dispatch,
void *user_data) void *user_data)
{ {
struct source *source;
struct epoll_event ep;
assert(fd != -1); assert(fd != -1);
source = zalloc(sizeof *source); _autofree_ struct source *source = zalloc(sizeof *source);
source->dispatch = dispatch; source->dispatch = dispatch;
source->user_data = user_data; source->user_data = user_data;
source->fd = fd; source->fd = fd;
list_append(&ctx->sources, &source->link);
struct epoll_event ep;
memset(&ep, 0, sizeof ep); memset(&ep, 0, sizeof ep);
ep.events = EPOLLIN; ep.events = EPOLLIN;
ep.data.ptr = source; ep.data.ptr = source;
if (epoll_ctl(ctx->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) { if (epoll_ctl(ctx->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
free(source);
return NULL; return NULL;
} }
return source; list_append(&ctx->sources, &source->link);
return steal(&source);
} }
static void static void
@ -2408,24 +2364,21 @@ mainloop(struct record_context *ctx)
static bool static bool
init_device(struct record_context *ctx, const char *path, bool grab) init_device(struct record_context *ctx, const char *path, bool grab)
{ {
struct record_device *d; _autofree_ struct record_device *d = zalloc(sizeof(*d));
int fd, rc;
d = zalloc(sizeof(*d));
d->ctx = ctx; d->ctx = ctx;
d->devnode = safe_strdup(path); d->devnode = safe_strdup(path);
list_init(&d->hidraw_devices); list_init(&d->hidraw_devices);
fd = open(d->devnode, O_RDONLY|O_NONBLOCK); _cleanup_(xclose) int fd = open(d->devnode, O_RDONLY|O_NONBLOCK);
if (fd < 0) { if (fd < 0) {
fprintf(stderr, fprintf(stderr,
"Failed to open device %s (%m)\n", "Failed to open device %s (%m)\n",
d->devnode); d->devnode);
goto error; return false;
} }
rc = libevdev_new_from_fd(fd, &d->evdev); int rc = libevdev_new_from_fd(fd, &d->evdev);
if (rc == 0) if (rc == 0)
rc = libevdev_new_from_fd(fd, &d->evdev_prev); rc = libevdev_new_from_fd(fd, &d->evdev_prev);
if (rc != 0) { if (rc != 0) {
@ -2433,7 +2386,7 @@ init_device(struct record_context *ctx, const char *path, bool grab)
"Failed to create context for %s (%s)\n", "Failed to create context for %s (%s)\n",
d->devnode, d->devnode,
strerror(-rc)); strerror(-rc));
goto error; return false;
} }
if (grab) { if (grab) {
@ -2443,7 +2396,7 @@ init_device(struct record_context *ctx, const char *path, bool grab)
"Grab failed on %s: %s\n", "Grab failed on %s: %s\n",
path, path,
strerror(-rc)); strerror(-rc));
goto error; return false;
} }
} }
@ -2452,18 +2405,17 @@ init_device(struct record_context *ctx, const char *path, bool grab)
if (libevdev_get_num_slots(d->evdev) > 0) if (libevdev_get_num_slots(d->evdev) > 0)
d->touch.is_touch_device = true; d->touch.is_touch_device = true;
list_append(&ctx->devices, &d->link);
if (!ctx->first_device) if (!ctx->first_device)
ctx->first_device = d; ctx->first_device = d;
list_take_append(&ctx->devices, d, link);
ctx->ndevices++; ctx->ndevices++;
return true; // Shut up clang-tidy
error: steal_fd(&fd);
close(fd);
free(d);
return false;
return true;
} }
static int static int
open_restricted(const char *path, int flags, void *user_data) open_restricted(const char *path, int flags, void *user_data)
{ {
@ -2709,7 +2661,7 @@ main(int argc, char **argv)
grab = false; grab = false;
int ndevices; int ndevices;
int rc = EXIT_FAILURE; int rc = EXIT_FAILURE;
char **paths = NULL; _autostrvfree_ char **paths = NULL;
list_init(&ctx.devices); list_init(&ctx.devices);
list_init(&ctx.sources); list_init(&ctx.sources);
@ -2813,13 +2765,11 @@ main(int argc, char **argv)
} else if (ndevices >= 1) { } else if (ndevices >= 1) {
paths = strv_from_argv(ndevices, &argv[optind]); paths = strv_from_argv(ndevices, &argv[optind]);
} else { } else {
char *path = select_device(); _autofree_ char *path = select_device();
if (path == NULL) { if (path == NULL) {
goto out; goto out;
} }
paths = strv_from_argv(1, &path); paths = strv_from_argv(1, &path);
free(path);
} }
for (char **p = paths; *p; p++) { for (char **p = paths; *p; p++) {
@ -2836,7 +2786,6 @@ main(int argc, char **argv)
rc = mainloop(&ctx); rc = mainloop(&ctx);
out: out:
strv_free(paths);
list_for_each_safe(d, &ctx.devices, link) { list_for_each_safe(d, &ctx.devices, link) {
struct hidraw *hidraw; struct hidraw *hidraw;

View file

@ -324,9 +324,9 @@ main(int argc, char **argv)
break; break;
case OPT_CUSTOM_POINTS: { case OPT_CUSTOM_POINTS: {
size_t npoints; size_t npoints;
double *points = double_array_from_string(optarg, _autofree_ double *points = double_array_from_string(optarg,
";", ";",
&npoints); &npoints);
if (!points || if (!points ||
npoints < LIBINPUT_ACCEL_NPOINTS_MIN || npoints < LIBINPUT_ACCEL_NPOINTS_MIN ||
npoints > LIBINPUT_ACCEL_NPOINTS_MAX) { npoints > LIBINPUT_ACCEL_NPOINTS_MAX) {
@ -334,14 +334,12 @@ main(int argc, char **argv)
"Invalid --custom-points\n" "Invalid --custom-points\n"
"Please provide at least 2 points separated by a semicolon\n" "Please provide at least 2 points separated by a semicolon\n"
" e.g. --custom-points=\"1.0;1.5\"\n"); " e.g. --custom-points=\"1.0;1.5\"\n");
free(points);
return 1; return 1;
} }
custom_func.npoints = npoints; custom_func.npoints = npoints;
memcpy(custom_func.points, memcpy(custom_func.points,
points, points,
sizeof(*points) * npoints); sizeof(*points) * npoints);
free(points);
break; break;
} }
case OPT_CUSTOM_STEP: case OPT_CUSTOM_STEP:

View file

@ -40,6 +40,7 @@
#include "builddir.h" #include "builddir.h"
#include "libinput.h" #include "libinput.h"
#include "libinput-util.h"
#include "shared.h" #include "shared.h"
#include "util-macros.h" #include "util-macros.h"
#include "util-strings.h" #include "util-strings.h"
@ -381,15 +382,13 @@ tools_parse_option(int option,
return 1; return 1;
size_t npoints = 0; size_t npoints = 0;
double *range = double_array_from_string(optarg, ":", &npoints); _autofree_ double *range = double_array_from_string(optarg, ":", &npoints);
if (npoints != 2 || !range || range[0] < 0.0 || range[1] > 1.0 || range[0] >= range[1]) { if (npoints != 2 || !range || range[0] < 0.0 || range[1] > 1.0 || range[0] >= range[1]) {
free(range);
fprintf(stderr, "Invalid pressure range, must be in format \"min:max\"\n"); fprintf(stderr, "Invalid pressure range, must be in format \"min:max\"\n");
return 1; return 1;
} }
options->pressure_range[0] = range[0]; options->pressure_range[0] = range[0];
options->pressure_range[1] = range[1]; options->pressure_range[1] = range[1];
free(range);
break; break;
} }
case OPT_CALIBRATION: { case OPT_CALIBRATION: {
@ -397,15 +396,13 @@ tools_parse_option(int option,
return 1; return 1;
size_t npoints = 0; size_t npoints = 0;
double *matrix = double_array_from_string(optarg, " ", &npoints); _autofree_ double *matrix = double_array_from_string(optarg, " ", &npoints);
if (!matrix || npoints != 6) { if (!matrix || npoints != 6) {
free(matrix);
fprintf(stderr, "Invalid calibration matrix, must be 6 space-separated values\n"); fprintf(stderr, "Invalid calibration matrix, must be 6 space-separated values\n");
return 1; return 1;
} }
for (size_t i = 0; i < 6; i++) for (size_t i = 0; i < 6; i++)
options->calibration[i] = matrix[i]; options->calibration[i] = matrix[i];
free(matrix);
break; break;
} }
case OPT_AREA: { case OPT_AREA: {
@ -473,18 +470,16 @@ static const struct libinput_interface interface = {
static struct libinput * static struct libinput *
tools_open_udev(const char *seat, bool verbose, bool *grab) tools_open_udev(const char *seat, bool verbose, bool *grab)
{ {
struct libinput *li; _unref_(udev) *udev = udev_new();
struct udev *udev = udev_new();
if (!udev) { if (!udev) {
fprintf(stderr, "Failed to initialize udev\n"); fprintf(stderr, "Failed to initialize udev\n");
return NULL; return NULL;
} }
li = libinput_udev_create_context(&interface, grab, udev); _unref_(libinput) *li = libinput_udev_create_context(&interface, grab, udev);
if (!li) { if (!li) {
fprintf(stderr, "Failed to initialize context from udev\n"); fprintf(stderr, "Failed to initialize context from udev\n");
goto out; return NULL;
} }
libinput_log_set_handler(li, log_handler); libinput_log_set_handler(li, log_handler);
@ -493,24 +488,16 @@ tools_open_udev(const char *seat, bool verbose, bool *grab)
if (libinput_udev_assign_seat(li, seat)) { if (libinput_udev_assign_seat(li, seat)) {
fprintf(stderr, "Failed to set seat\n"); fprintf(stderr, "Failed to set seat\n");
libinput_unref(li); return NULL;
li = NULL;
goto out;
} }
out: return steal(&li);
udev_unref(udev);
return li;
} }
static struct libinput * static struct libinput *
tools_open_device(const char **paths, bool verbose, bool *grab) tools_open_device(const char **paths, bool verbose, bool *grab)
{ {
struct libinput_device *device; _unref_(libinput) *li = libinput_path_create_context(&interface, grab);
struct libinput *li;
const char **p = paths;
li = libinput_path_create_context(&interface, grab);
if (!li) { if (!li) {
fprintf(stderr, "Failed to initialize path context\n"); fprintf(stderr, "Failed to initialize path context\n");
return NULL; return NULL;
@ -521,26 +508,24 @@ tools_open_device(const char **paths, bool verbose, bool *grab)
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG); libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
} }
const char **p = paths;
while (*p) { while (*p) {
device = libinput_path_add_device(li, *p); struct libinput_device *device = libinput_path_add_device(li, *p);
if (!device) { if (!device) {
fprintf(stderr, "Failed to initialize device %s\n", *p); fprintf(stderr, "Failed to initialize device %s\n", *p);
libinput_unref(li); return NULL;
li = NULL;
break;
} }
p++; p++;
} }
return li; return steal(&li);
} }
static void static void
tools_setenv_quirks_dir(void) tools_setenv_quirks_dir(void)
{ {
if (builddir_lookup(NULL)) { if (builddir_lookup(NULL))
setenv("LIBINPUT_QUIRKS_DIR", LIBINPUT_QUIRKS_SRCDIR, 0); setenv("LIBINPUT_QUIRKS_DIR", LIBINPUT_QUIRKS_SRCDIR, 0);
}
} }
struct libinput * struct libinput *
@ -638,7 +623,7 @@ tools_device_apply_config(struct libinput_device *device,
} }
if (options->profile == LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM) { if (options->profile == LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM) {
struct libinput_config_accel *config = _destroy_(libinput_config_accel) *config =
libinput_config_accel_create(LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM); libinput_config_accel_create(LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM);
libinput_config_accel_set_points(config, libinput_config_accel_set_points(config,
options->custom_type, options->custom_type,
@ -646,7 +631,6 @@ tools_device_apply_config(struct libinput_device *device,
options->custom_npoints, options->custom_npoints,
options->custom_points); options->custom_points);
libinput_device_config_accel_apply(device, config); libinput_device_config_accel_apply(device, config);
libinput_config_accel_destroy(config);
} }
if (options->angle != 0) if (options->angle != 0)
@ -674,57 +658,43 @@ tools_tablet_tool_apply_config(struct libinput_tablet_tool *tool,
static char* static char*
find_device(const char *udev_tag) find_device(const char *udev_tag)
{ {
struct udev *udev; _unref_(udev) *udev = udev_new();
struct udev_enumerate *e = NULL;
struct udev_list_entry *entry = NULL;
struct udev_device *device;
const char *path, *sysname;
char *device_node = NULL;
udev = udev_new();
if (!udev) if (!udev)
goto out; return NULL;
e = udev_enumerate_new(udev); _unref_(udev_enumerate) *e = udev_enumerate_new(udev);
udev_enumerate_add_match_subsystem(e, "input"); udev_enumerate_add_match_subsystem(e, "input");
udev_enumerate_scan_devices(e); udev_enumerate_scan_devices(e);
struct udev_list_entry *entry = NULL;
udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
path = udev_list_entry_get_name(entry); const char *path = udev_list_entry_get_name(entry);
device = udev_device_new_from_syspath(udev, path); _unref_(udev_device) *device = udev_device_new_from_syspath(udev, path);
if (!device) if (!device)
continue; continue;
sysname = udev_device_get_sysname(device); const char *sysname = udev_device_get_sysname(device);
if (!strstartswith("event", sysname)) { if (!strstartswith("event", sysname)) {
udev_device_unref(device);
continue; continue;
} }
if (udev_device_get_property_value(device, udev_tag)) if (udev_device_get_property_value(device, udev_tag)) {
device_node = safe_strdup(udev_device_get_devnode(device)); char *device_node = safe_strdup(udev_device_get_devnode(device));
if (device_node)
udev_device_unref(device); return device_node;
}
if (device_node)
break;
} }
out:
udev_enumerate_unref(e);
udev_unref(udev);
return device_node; return NULL;
} }
bool bool
find_touchpad_device(char *path, size_t path_len) find_touchpad_device(char *path, size_t path_len)
{ {
char *devnode = find_device("ID_INPUT_TOUCHPAD"); _autofree_ char *devnode = find_device("ID_INPUT_TOUCHPAD");
if (devnode) { if (devnode)
snprintf(path, path_len, "%s", devnode); snprintf(path, path_len, "%s", devnode);
free(devnode);
}
return devnode != NULL; return devnode != NULL;
} }
@ -732,29 +702,19 @@ find_touchpad_device(char *path, size_t path_len)
bool bool
is_touchpad_device(const char *devnode) is_touchpad_device(const char *devnode)
{ {
struct udev *udev;
struct udev_device *dev = NULL;
struct stat st; struct stat st;
bool is_touchpad = false;
if (stat(devnode, &st) < 0) if (stat(devnode, &st) < 0)
return false; return false;
udev = udev_new(); _unref_(udev) *udev = udev_new();
if (!udev) if (!udev)
goto out; return false;
dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev); _unref_(udev_device) *dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
if (!dev) if (!dev)
goto out; return false;
is_touchpad = udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD"); return udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD");
out:
if (dev)
udev_device_unref(dev);
udev_unref(udev);
return is_touchpad;
} }
static inline void static inline void
@ -763,7 +723,7 @@ setup_path(void)
const char *path = getenv("PATH"); const char *path = getenv("PATH");
char new_path[PATH_MAX]; char new_path[PATH_MAX];
const char *extra_path = LIBINPUT_TOOL_PATH; const char *extra_path = LIBINPUT_TOOL_PATH;
char *builddir = NULL; _autofree_ char *builddir = NULL;
builddir_lookup(&builddir); builddir_lookup(&builddir);
snprintf(new_path, snprintf(new_path,
@ -772,7 +732,6 @@ setup_path(void)
builddir ? builddir : extra_path, builddir ? builddir : extra_path,
path ? path : ""); path ? path : "");
setenv("PATH", new_path, 1); setenv("PATH", new_path, 1);
free(builddir);
} }
int int
@ -881,10 +840,9 @@ tools_list_device_quirks(struct quirks_context *ctx,
{ {
char buf[256]; char buf[256];
struct quirks *quirks;
enum quirk q; enum quirk q;
quirks = quirks_fetch_for_device(ctx, device); _unref_(quirks) *quirks = quirks_fetch_for_device(ctx, device);
if (!quirks) if (!quirks)
return; return;
@ -969,6 +927,4 @@ tools_list_device_quirks(struct quirks_context *ctx,
} }
} }
} while(++q < _QUIRK_LAST_ATTR_QUIRK_); } while(++q < _QUIRK_LAST_ATTR_QUIRK_);
quirks_unref(quirks);
} }