aboutgitcodebugslistschat
path: root/passt-repair.c
diff options
context:
space:
mode:
Diffstat (limited to 'passt-repair.c')
-rw-r--r--passt-repair.c137
1 files 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
@@ -47,6 +47,82 @@
#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
* @argv: Argument: path of UNIX domain socket to connect to
@@ -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]);