From 1254a1f9f9867a9d9022e709549388d9cdf4f7b4 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 12 May 2026 15:52:53 +1000 Subject: passt-repair: Split out inotify handling to its own function passt-repair can operate two ways: either it can be given an explicit socket path to connect to, or it can be given a directory. In the second mode, it will wait for a socket to appear in that directory before connecting to it. That waiting involves some inotify logic that is essentially unrelated to the rest of the code. However, it's currently inline in main() making that very long. Moreover, the block handling inotify shadows several variables used in the rest of main() which will make static checkers complain once we get them running on passt-repair. Address this by moving the inotify handling into its own function. Signed-off-by: David Gibson Signed-off-by: Stefano Brivio --- passt-repair.c | 137 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 77 insertions(+), 60 deletions(-) diff --git a/passt-repair.c b/passt-repair.c index c3c140f..980b0b0 100644 --- a/passt-repair.c +++ b/passt-repair.c @@ -46,6 +46,82 @@ #define REPAIR_EXT ".repair" #define REPAIR_EXT_LEN strlen(REPAIR_EXT) +/** + * wait_for_socket() - Wait for a Unix socket to appear in a directory + * @a: Unix domain address to update with socket's path + * @dir: Path to directory to wait for socket in + * @sb: Stat block, populated for the discovered socket on exit + * + * Return: Length of socket address + * + * #syscalls:repair close + * #syscalls:repair stat|statx stat64|statx statx + * #syscalls:repair inotify_init1 inotify_add_watch + */ +static int wait_for_socket(struct sockaddr_un *a, const char *dir, + struct stat *sb) +{ + char buf[sizeof(struct inotify_event) + NAME_MAX + 1] + __attribute__ ((aligned(__alignof__(struct inotify_event)))); + const struct inotify_event *ev = NULL; + char path[PATH_MAX + 1]; + bool found = false; + ssize_t n; + int fd; + + if ((fd = inotify_init1(IN_CLOEXEC)) < 0) { + fprintf(stderr, "inotify_init1: %i\n", errno); + _exit(1); + } + + if (inotify_add_watch(fd, dir, IN_CREATE) < 0) { + fprintf(stderr, "inotify_add_watch: %i\n", errno); + _exit(1); + } + + do { + char *p; + + n = read(fd, buf, sizeof(buf)); + if (n < 0) { + fprintf(stderr, "inotify read: %i\n", errno); + _exit(1); + } + buf[n - 1] = '\0'; + + if (n < (ssize_t)sizeof(*ev)) { + fprintf(stderr, "Short inotify read: %zi\n", n); + continue; + } + + for (p = buf; p < buf + n; p += sizeof(*ev) + ev->len) { + ev = (const struct inotify_event *)p; + + if (ev->len >= REPAIR_EXT_LEN && + !memcmp(ev->name + + strnlen(ev->name, ev->len) - + REPAIR_EXT_LEN, + REPAIR_EXT, REPAIR_EXT_LEN)) { + found = true; + break; + } + } + } while (!found); + + if (ev->len > NAME_MAX + 1 || ev->name[ev->len - 1] != '\0') { + fprintf(stderr, "Invalid filename from inotify\n"); + _exit(1); + } + + snprintf(path, sizeof(path), "%s/%s", dir, ev->name); + if ((stat(path, sb))) { + fprintf(stderr, "Can't stat() %s: %i\n", path, errno); + _exit(1); + } + + return snprintf(a->sun_path, sizeof(a->sun_path), "%s", path); +} + /** * main() - Entry point and whole program with loop * @argc: Argument count, must be 2 @@ -59,7 +135,6 @@ * #syscalls:repair sendto sendmsg arm:send ppc64le:send * #syscalls:repair stat|statx stat64|statx statx * #syscalls:repair fstat|fstat64 newfstatat|fstatat64 - * #syscalls:repair inotify_init1 inotify_add_watch */ int main(int argc, char **argv) { @@ -112,65 +187,7 @@ int main(int argc, char **argv) } if ((sb.st_mode & S_IFMT) == S_IFDIR) { - char buf[sizeof(struct inotify_event) + NAME_MAX + 1] - __attribute__ ((aligned(__alignof__(struct inotify_event)))); - const struct inotify_event *ev = NULL; - char path[PATH_MAX + 1]; - bool found = false; - ssize_t n; - int fd; - - if ((fd = inotify_init1(IN_CLOEXEC)) < 0) { - fprintf(stderr, "inotify_init1: %i\n", errno); - _exit(1); - } - - if (inotify_add_watch(fd, argv[1], IN_CREATE) < 0) { - fprintf(stderr, "inotify_add_watch: %i\n", errno); - _exit(1); - } - - do { - char *p; - - n = read(fd, buf, sizeof(buf)); - if (n < 0) { - fprintf(stderr, "inotify read: %i\n", errno); - _exit(1); - } - buf[n - 1] = '\0'; - - if (n < (ssize_t)sizeof(*ev)) { - fprintf(stderr, "Short inotify read: %zi\n", n); - continue; - } - - for (p = buf; p < buf + n; p += sizeof(*ev) + ev->len) { - ev = (const struct inotify_event *)p; - - if (ev->len >= REPAIR_EXT_LEN && - !memcmp(ev->name + - strnlen(ev->name, ev->len) - - REPAIR_EXT_LEN, - REPAIR_EXT, REPAIR_EXT_LEN)) { - found = true; - break; - } - } - } while (!found); - - if (ev->len > NAME_MAX + 1 || ev->name[ev->len - 1] != '\0') { - fprintf(stderr, "Invalid filename from inotify\n"); - _exit(1); - } - - snprintf(path, sizeof(path), "%s/%s", argv[1], ev->name); - if ((stat(path, &sb))) { - fprintf(stderr, "Can't stat() %s: %i\n", path, errno); - _exit(1); - } - - ret = snprintf(a.sun_path, sizeof(a.sun_path), "%s", path); + ret = wait_for_socket(&a, argv[1], &sb); inotify_dir = true; } else { ret = snprintf(a.sun_path, sizeof(a.sun_path), "%s", argv[1]); -- cgit v1.2.3