diff options
author | Runxi Yu <me@runxiyu.org> | 2025-02-17 06:56:18 +0800 |
---|---|---|
committer | Runxi Yu <me@runxiyu.org> | 2025-02-17 06:56:18 +0800 |
commit | ca830519e17e0b3fae6697839bc5e7347a1299a5 (patch) | |
tree | 73da88b0b49124e8835b23455d61072b2e2884a7 /git_hooks_client/git_hooks_client.c | |
parent | git_hooks_client: Produce useful error message on missing env var (diff) | |
download | forge-ca830519e17e0b3fae6697839bc5e7347a1299a5.tar.gz forge-ca830519e17e0b3fae6697839bc5e7347a1299a5.tar.zst forge-ca830519e17e0b3fae6697839bc5e7347a1299a5.zip |
git_hooks_client: Restructure for clarity
Diffstat (limited to 'git_hooks_client/git_hooks_client.c')
-rw-r--r-- | git_hooks_client/git_hooks_client.c | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/git_hooks_client/git_hooks_client.c b/git_hooks_client/git_hooks_client.c index 0d736a9..01af196 100644 --- a/git_hooks_client/git_hooks_client.c +++ b/git_hooks_client/git_hooks_client.c @@ -8,51 +8,56 @@ #include <fcntl.h> int main(void) { - int sock; - struct sockaddr_un addr; const char *socket_path = getenv("LINDENII_FORGE_HOOKS_SOCKET_PATH"); - if (socket_path == NULL) { dprintf(STDERR_FILENO, "fatal: environment variable LINDENII_FORGE_HOOKS_SOCKET_PATH undefined\n"); return EXIT_FAILURE; } - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock == -1) { - perror("socket"); - return EXIT_FAILURE; - } + /* + * All hooks in git (see builtin/receive-pack.c) use a pipe by setting + * .in = -1 on the child_process struct, which enables us to use + * splice(2) to move the data to the UNIX domain socket. Just to be + * safe, we check that stdin is a pipe; and additionally we fetch the + * buffer size of the pipe to use as the maximum size for the splice. + * + * We connect to the UNIX domain socket after ensuring that standard + * input matches our expectations. + */ - memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); - - if (connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) { - perror("connect"); - close(sock); - return EXIT_FAILURE; - } - - struct stat stdin_stat; + struct stat stdin_stat; if (fstat(STDIN_FILENO, &stdin_stat) == -1) { perror("fstat"); - close(sock); return EXIT_FAILURE; } - if (!S_ISFIFO(stdin_stat.st_mode)) { dprintf(STDERR_FILENO, "fatal: stdin must be a pipe\n"); - close(sock); return EXIT_FAILURE; } - int pipe_size = fcntl(STDIN_FILENO, F_GETPIPE_SZ); if (pipe_size == -1) { perror("fcntl"); + return EXIT_FAILURE; + } + + int sock; + struct sockaddr_un addr; + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock == -1) { + perror("socket"); + return EXIT_FAILURE; + } + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); + + if (connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) { + perror("connect"); close(sock); return EXIT_FAILURE; } + ssize_t bytes_spliced; while ((bytes_spliced = splice(STDIN_FILENO, NULL, sock, NULL, pipe_size, SPLICE_F_MORE)) > 0) { } |