commit 5769f9a0a07516237666a060ff3e06d43f4db8ed from: Stefan Sperling via: Thomas Adam date: Sat Apr 22 18:09:16 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 - c282f7879bc381d455df8a2fbe57446aba59c985 commit + 5769f9a0a07516237666a060ff3e06d43f4db8ed 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 - afd9bcda117c08da3020fefb04f6b713a6872af9 blob + 7cb0c0edba72b2dbaaafc7061d6915e91f743945 --- gotsh/gotsh.c +++ gotsh/gotsh.c @@ -31,6 +31,8 @@ #include "got_serve.h" #include "got_path.h" +#include "got_lib_dial.h" + #include "gotd.h" static int chattygot; @@ -39,7 +41,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); } @@ -81,17 +83,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 - a1c36d79fc027c5d4edaac9730210cbe320a2492 blob + 6fa757506d48c984249b92d3cdc2b11114394737 --- lib/dial.c +++ lib/dial.c @@ -248,7 +248,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]; @@ -293,15 +293,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"); @@ -317,7 +315,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; @@ -355,7 +353,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; } @@ -372,3 +370,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 - 1b9c44d8abfd973a64562825814d314f19f3b6b8 blob + c5cbff1e5a5e603896233f86eb2b3dfd1c8a49d1 --- lib/fetch.c +++ lib/fetch.c @@ -83,10 +83,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 - d823489f72203b7adc78e6127598a107a3e5df56 blob + 2a780cfc3b6f825130e78b9a3264b088b679ca61 --- lib/send.c +++ lib/send.c @@ -88,10 +88,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 - 5e391cda4af389271a4144ffa39bd42c91322160 blob + 340896dbcc22a207db8373da81afa58055c86128 --- lib/serve.c +++ lib/serve.c @@ -62,103 +62,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) @@ -1477,9 +1380,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