commit 1eb3899277955a87d80eef900b6ea458ff73bd6c from: Stefan Sperling date: Fri Apr 14 20:54:38 2023 UTC significantly reduce the amount of code linked into gitwrapper By moving got_serve_parse_command() from lib/serve.c into lib/dial.c as got_dial_parse_command(), we can significantly reduce the amount of symbols gitwrapper depends on indirectly. As a downside, gotsh now needs to link to dial.c. But it only uses the same parsing routine, and any other routines in dial.c would likely cause pledge violations in gotsh if used. No functional change. commit - 132d524727bc488554836990bad88e0208b85843 commit + 1eb3899277955a87d80eef900b6ea458ff73bd6c blob - 51b0f34ff387e3e735abc9f3d1f6e04404a3fbd5 blob + b5090f97c92dbb39058bb0025be416df747495c8 --- gitwrapper/Makefile +++ gitwrapper/Makefile @@ -8,15 +8,11 @@ BINDIR ?= ${PREFIX}/bin .endif PROG= gitwrapper -SRCS= gitwrapper.c parse.y log.c serve.c auth.c listen.c pkt.c \ - error.c gitproto.c hash.c reference.c object.c object_parse.c \ - path.c object_idset.c object_create.c inflate.c opentemp.c \ - lockfile.c repository.c gotconfig.c pack.c bloom.c buf.c \ - object_cache.c privsep_stub.c pollfd.c imsg.c \ - reference_parse.c object_open_io.c sigs.c deflate.c \ - read_gotconfig.c read_gitconfig.c delta_cache.c delta.c \ - murmurhash2.c date.c gitconfig.c +SRCS= gitwrapper.c parse.y log.c dial.c path.c error.c auth.c \ + listen.c reference_parse.c hash.c object_parse.c imsg.c \ + inflate.c pollfd.c + CLEANFILES = parse.h MAN = ${PROG}.1 blob - 61404820c89b2b713cc2e51739b6221e9ab104c1 blob + 7f8f5889223aa73b0ce751d3ade99c6d45147699 --- gitwrapper/gitwrapper.c +++ gitwrapper/gitwrapper.c @@ -38,8 +38,9 @@ #include "got_error.h" #include "got_path.h" -#include "got_serve.h" +#include "got_lib_dial.h" + #include "gotd.h" #include "log.h" @@ -56,7 +57,7 @@ __dead static void usage(void) { fprintf(stderr, "usage: %s -c '%s|%s repository-path'\n", - getprogname(), GOT_SERVE_CMD_SEND, GOT_SERVE_CMD_FETCH); + getprogname(), GOT_DIAL_CMD_SEND, GOT_DIAL_CMD_FETCH); exit(1); } @@ -68,9 +69,9 @@ static const struct got_error * apply_unveil(const char *myserver) { const char *fetchcmd = GITWRAPPER_GIT_LIBEXEC_DIR "/" \ - GOT_SERVE_CMD_FETCH; + GOT_DIAL_CMD_FETCH; const char *sendcmd = GITWRAPPER_GIT_LIBEXEC_DIR "/" \ - GOT_SERVE_CMD_SEND; + GOT_DIAL_CMD_SEND; #ifdef PROFILE if (unveil("gmon.out", "rwc") != 0) @@ -141,8 +142,8 @@ main(int argc, char *argv[]) err(1, "pledge"); #endif - if (strcmp(getprogname(), GOT_SERVE_CMD_SEND) == 0 || - strcmp(getprogname(), GOT_SERVE_CMD_FETCH) == 0) { + if (strcmp(getprogname(), GOT_DIAL_CMD_SEND) == 0 || + strcmp(getprogname(), GOT_DIAL_CMD_FETCH) == 0) { if (argc != 2) usage(); command = strdup(getprogname()); @@ -163,7 +164,7 @@ main(int argc, char *argv[]) if (argc != 3 || strcmp(argv[1], "-c") != 0) usage(); repo_path = argv[2]; - error = got_serve_parse_command(&command, &repo_name, + error = got_dial_parse_command(&command, &repo_name, repo_path); if (error && error->code == GOT_ERR_BAD_PACKET) usage(); blob - 3772cc684ff07adb2559919352418b7232dc14ec blob + 764d96444519d4dfc13f888b5824e4c35e38e76f --- gotsh/Makefile +++ gotsh/Makefile @@ -4,7 +4,8 @@ PROG= gotsh SRCS= gotsh.c error.c pkt.c hash.c serve.c path.c gitproto.c \ - imsg.c inflate.c object_parse.c pollfd.c reference_parse.c + imsg.c inflate.c object_parse.c pollfd.c reference_parse.c \ + dial.c MAN = ${PROG}.1 blob - 2baef036bd213663876faf58ee76e34028149d55 blob + 2523b2c27285f8b883a18bfa1d16fb268ff9cd5c --- gotsh/gotsh.c +++ gotsh/gotsh.c @@ -33,6 +33,8 @@ #include "got_serve.h" #include "got_path.h" +#include "got_lib_dial.h" + #include "gotd.h" static int chattygot; @@ -41,7 +43,7 @@ __dead static void usage(void) { fprintf(stderr, "usage: %s -c '%s|%s repository-path'\n", - getprogname(), GOT_SERVE_CMD_SEND, GOT_SERVE_CMD_FETCH); + getprogname(), GOT_DIAL_CMD_SEND, GOT_DIAL_CMD_FETCH); exit(1); } @@ -83,17 +85,17 @@ main(int argc, char *argv[]) if (error) goto done; - if (strcmp(argv[0], GOT_SERVE_CMD_SEND) == 0 || - strcmp(argv[0], GOT_SERVE_CMD_FETCH) == 0) { + if (strcmp(argv[0], GOT_DIAL_CMD_SEND) == 0 || + strcmp(argv[0], GOT_DIAL_CMD_FETCH) == 0) { if (argc != 2) usage(); if (asprintf(&gitcmd, "%s %s", argv[0], argv[1]) == -1) err(1, "asprintf"); - error = got_serve_parse_command(&command, &repo_path, gitcmd); + error = got_dial_parse_command(&command, &repo_path, gitcmd); } else { if (argc != 3 || strcmp(argv[1], "-c") != 0) usage(); - error = got_serve_parse_command(&command, &repo_path, argv[2]); + error = got_dial_parse_command(&command, &repo_path, argv[2]); } if (error && error->code == GOT_ERR_BAD_PACKET) usage(); blob - 437fff67924784d199bc37269ac367e71f2dc063 blob + 3296e799a3560e442faed27862ffa9ac96a77ece --- include/got_serve.h +++ include/got_serve.h @@ -14,9 +14,5 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define GOT_SERVE_CMD_SEND "git-receive-pack" -#define GOT_SERVE_CMD_FETCH "git-upload-pack" - -const struct got_error *got_serve_parse_command(char **, char **, const char *); const struct got_error *got_serve(int infd, int outfd, const char *command, const char *repo_path, int gotd_sock, int chattygot); blob - 5f5329cec70be10b102cac79e9dffe3f204c951a blob + 37f513651fb8783483a1bb2e446a59adf26cfda6 --- lib/dial.c +++ lib/dial.c @@ -244,7 +244,7 @@ escape_path(char *buf, size_t bufsize, const char *pat const struct got_error * got_dial_ssh(pid_t *newpid, int *newfd, const char *host, - const char *port, const char *path, const char *direction, int verbosity) + const char *port, const char *path, const char *command, int verbosity) { const struct got_error *error = NULL; int pid, pfd[2]; @@ -289,15 +289,13 @@ got_dial_ssh(pid_t *newpid, int *newfd, const char *ho close(pfd[1]); return error; } else if (pid == 0) { - int n; if (close(pfd[1]) == -1) err(1, "close"); if (dup2(pfd[0], 0) == -1) err(1, "dup2"); if (dup2(pfd[0], 1) == -1) err(1, "dup2"); - n = snprintf(cmd, sizeof(cmd), "git-%s-pack", direction); - if (n < 0 || n >= ssizeof(cmd)) + if (strlcpy(cmd, command, sizeof(cmd)) >= sizeof(cmd)) err(1, "snprintf"); if (execv(GOT_DIAL_PATH_SSH, (char *const *)argv) == -1) err(1, "execv"); @@ -313,7 +311,7 @@ got_dial_ssh(pid_t *newpid, int *newfd, const char *ho const struct got_error * got_dial_git(int *newfd, const char *host, const char *port, - const char *path, const char *direction) + const char *path, const char *command) { const struct got_error *err = NULL; struct addrinfo hints, *servinfo, *p; @@ -351,7 +349,7 @@ got_dial_git(int *newfd, const char *host, const char if (p == NULL) goto done; - if (asprintf(&cmd, "git-%s-pack %s", direction, path) == -1) { + if (asprintf(&cmd, "%s %s", command, path) == -1) { err = got_error_from_errno("asprintf"); goto done; } @@ -368,3 +366,100 @@ done: *newfd = fd; return err; } + +const struct got_error * +got_dial_parse_command(char **command, char **repo_path, const char *gitcmd) +{ + const struct got_error *err = NULL; + size_t len, cmdlen, pathlen; + char *path0 = NULL, *path, *abspath = NULL, *canonpath = NULL; + const char *relpath; + + *command = NULL; + *repo_path = NULL; + + len = strlen(gitcmd); + + if (len >= strlen(GOT_DIAL_CMD_SEND) && + strncmp(gitcmd, GOT_DIAL_CMD_SEND, + strlen(GOT_DIAL_CMD_SEND)) == 0) + cmdlen = strlen(GOT_DIAL_CMD_SEND); + else if (len >= strlen(GOT_DIAL_CMD_FETCH) && + strncmp(gitcmd, GOT_DIAL_CMD_FETCH, + strlen(GOT_DIAL_CMD_FETCH)) == 0) + cmdlen = strlen(GOT_DIAL_CMD_FETCH); + else + return got_error(GOT_ERR_BAD_PACKET); + + if (len <= cmdlen + 1 || gitcmd[cmdlen] != ' ') + return got_error(GOT_ERR_BAD_PACKET); + + if (memchr(&gitcmd[cmdlen + 1], '\0', len - cmdlen) == NULL) + return got_error(GOT_ERR_BAD_PATH); + + /* Forbid linefeeds in paths, like Git does. */ + if (memchr(&gitcmd[cmdlen + 1], '\n', len - cmdlen) != NULL) + return got_error(GOT_ERR_BAD_PATH); + + path0 = strdup(&gitcmd[cmdlen + 1]); + if (path0 == NULL) + return got_error_from_errno("strdup"); + path = path0; + pathlen = strlen(path); + + /* + * Git clients send a shell command. + * Trim spaces and quotes around the path. + */ + while (path[0] == '\'' || path[0] == '\"' || path[0] == ' ') { + path++; + pathlen--; + } + while (pathlen > 0 && + (path[pathlen - 1] == '\'' || path[pathlen - 1] == '\"' || + path[pathlen - 1] == ' ')) { + path[pathlen - 1] = '\0'; + pathlen--; + } + + /* Deny an empty repository path. */ + if (path[0] == '\0' || got_path_is_root_dir(path)) { + err = got_error(GOT_ERR_NOT_GIT_REPO); + goto done; + } + + if (asprintf(&abspath, "/%s", path) == -1) { + err = got_error_from_errno("asprintf"); + goto done; + } + pathlen = strlen(abspath); + canonpath = malloc(pathlen + 1); + if (canonpath == NULL) { + err = got_error_from_errno("malloc"); + goto done; + } + err = got_canonpath(abspath, canonpath, pathlen + 1); + if (err) + goto done; + + relpath = canonpath; + while (relpath[0] == '/') + relpath++; + *repo_path = strdup(relpath); + if (*repo_path == NULL) { + err = got_error_from_errno("strdup"); + goto done; + } + *command = strndup(gitcmd, cmdlen); + if (*command == NULL) + err = got_error_from_errno("strndup"); +done: + free(path0); + free(abspath); + free(canonpath); + if (err) { + free(*repo_path); + *repo_path = NULL; + } + return err; +} blob - 83b488b1eeb279f409a37815878f9eb4f43aa0a3 blob + 15eea55419c93fd724e16e8904ae2506a727a5e2 --- lib/fetch.c +++ lib/fetch.c @@ -88,10 +88,10 @@ got_fetch_connect(pid_t *fetchpid, int *fetchfd, const if (strcmp(proto, "ssh") == 0 || strcmp(proto, "git+ssh") == 0) err = got_dial_ssh(fetchpid, fetchfd, host, port, - server_path, GOT_DIAL_DIRECTION_FETCH, verbosity); + server_path, GOT_DIAL_CMD_FETCH, verbosity); else if (strcmp(proto, "git") == 0) err = got_dial_git(fetchfd, host, port, server_path, - GOT_DIAL_DIRECTION_FETCH); + GOT_DIAL_CMD_FETCH); else if (strcmp(proto, "http") == 0 || strcmp(proto, "git+http") == 0) err = got_error_path(proto, GOT_ERR_NOT_IMPL); else blob - cbaf4ea224445b13ae795d7ec9ddb72fda40ab52 blob + 4717b9365391333147b3bf4e949e34865e8da431 --- lib/got_lib_dial.h +++ lib/got_lib_dial.h @@ -15,12 +15,15 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define GOT_DIAL_DIRECTION_SEND "receive" -#define GOT_DIAL_DIRECTION_FETCH "upload" +#define GOT_DIAL_CMD_SEND "git-receive-pack" +#define GOT_DIAL_CMD_FETCH "git-upload-pack" const struct got_error *got_dial_git(int *newfd, const char *host, - const char *port, const char *path, const char *direction); + const char *port, const char *path, const char *command); const struct got_error *got_dial_ssh(pid_t *newpid, int *newfd, const char *host, const char *port, const char *path, - const char *direction, int verbosity); + const char *command, int verbosity); + +const struct got_error *got_dial_parse_command(char **command, + char **repo_path, const char *gitcmd); blob - 3b9f271aa9ce3830585ef554b0f559c8e5ea026e blob + baff5126bef7368795495150bcfabcb49a70dcd8 --- lib/send.c +++ lib/send.c @@ -92,10 +92,10 @@ got_send_connect(pid_t *sendpid, int *sendfd, const ch if (strcmp(proto, "ssh") == 0 || strcmp(proto, "git+ssh") == 0) err = got_dial_ssh(sendpid, sendfd, host, port, server_path, - GOT_DIAL_DIRECTION_SEND, verbosity); + GOT_DIAL_CMD_SEND, verbosity); else if (strcmp(proto, "git") == 0) err = got_dial_git(sendfd, host, port, server_path, - GOT_DIAL_DIRECTION_SEND); + GOT_DIAL_CMD_SEND); else if (strcmp(proto, "http") == 0 || strcmp(proto, "git+http") == 0) err = got_error_path(proto, GOT_ERR_NOT_IMPL); else blob - 8ef2f8a5f604c4672e7ef11adbba4c6af455fd18 blob + 3d1c9a901f008fc32a17f1ab6a9abc5b444cf986 --- lib/serve.c +++ lib/serve.c @@ -64,103 +64,6 @@ static const struct got_capability write_capabilities[ { GOT_CAPA_DELETE_REFS, NULL }, }; -const struct got_error * -got_serve_parse_command(char **command, char **repo_path, const char *gitcmd) -{ - const struct got_error *err = NULL; - size_t len, cmdlen, pathlen; - char *path0 = NULL, *path, *abspath = NULL, *canonpath = NULL; - const char *relpath; - - *command = NULL; - *repo_path = NULL; - - len = strlen(gitcmd); - - if (len >= strlen(GOT_SERVE_CMD_SEND) && - strncmp(gitcmd, GOT_SERVE_CMD_SEND, - strlen(GOT_SERVE_CMD_SEND)) == 0) - cmdlen = strlen(GOT_SERVE_CMD_SEND); - else if (len >= strlen(GOT_SERVE_CMD_FETCH) && - strncmp(gitcmd, GOT_SERVE_CMD_FETCH, - strlen(GOT_SERVE_CMD_FETCH)) == 0) - cmdlen = strlen(GOT_SERVE_CMD_FETCH); - else - return got_error(GOT_ERR_BAD_PACKET); - - if (len <= cmdlen + 1 || gitcmd[cmdlen] != ' ') - return got_error(GOT_ERR_BAD_PACKET); - - if (memchr(&gitcmd[cmdlen + 1], '\0', len - cmdlen) == NULL) - return got_error(GOT_ERR_BAD_PATH); - - /* Forbid linefeeds in paths, like Git does. */ - if (memchr(&gitcmd[cmdlen + 1], '\n', len - cmdlen) != NULL) - return got_error(GOT_ERR_BAD_PATH); - - path0 = strdup(&gitcmd[cmdlen + 1]); - if (path0 == NULL) - return got_error_from_errno("strdup"); - path = path0; - pathlen = strlen(path); - - /* - * Git clients send a shell command. - * Trim spaces and quotes around the path. - */ - while (path[0] == '\'' || path[0] == '\"' || path[0] == ' ') { - path++; - pathlen--; - } - while (pathlen > 0 && - (path[pathlen - 1] == '\'' || path[pathlen - 1] == '\"' || - path[pathlen - 1] == ' ')) { - path[pathlen - 1] = '\0'; - pathlen--; - } - - /* Deny an empty repository path. */ - if (path[0] == '\0' || got_path_is_root_dir(path)) { - err = got_error(GOT_ERR_NOT_GIT_REPO); - goto done; - } - - if (asprintf(&abspath, "/%s", path) == -1) { - err = got_error_from_errno("asprintf"); - goto done; - } - pathlen = strlen(abspath); - canonpath = malloc(pathlen + 1); - if (canonpath == NULL) { - err = got_error_from_errno("malloc"); - goto done; - } - err = got_canonpath(abspath, canonpath, pathlen + 1); - if (err) - goto done; - - relpath = canonpath; - while (relpath[0] == '/') - relpath++; - *repo_path = strdup(relpath); - if (*repo_path == NULL) { - err = got_error_from_errno("strdup"); - goto done; - } - *command = strndup(gitcmd, cmdlen); - if (*command == NULL) - err = got_error_from_errno("strndup"); -done: - free(path0); - free(abspath); - free(canonpath); - if (err) { - free(*repo_path); - *repo_path = NULL; - } - return err; -} - static const struct got_error * append_read_capabilities(size_t *capalen, size_t len, const char *symrefstr, uint8_t *buf, size_t bufsize) @@ -1479,9 +1382,9 @@ got_serve(int infd, int outfd, const char *command, co { const struct got_error *err = NULL; - if (strcmp(command, GOT_SERVE_CMD_FETCH) == 0) + if (strcmp(command, GOT_DIAL_CMD_FETCH) == 0) err = serve_read(infd, outfd, gotd_sock, repo_path, chattygot); - else if (strcmp(command, GOT_SERVE_CMD_SEND) == 0) + else if (strcmp(command, GOT_DIAL_CMD_SEND) == 0) err = serve_write(infd, outfd, gotd_sock, repo_path, chattygot); else