From: Omar Polo Subject: gotwebd: openat(2) and less params for scraping repo info To: gameoftrees@openbsd.org Date: Wed, 09 Nov 2022 19:54:41 +0100 diff below does two things: - drops the unused path argument to got_get_repo_{owner,age} - makes gotweb_get_repo_{description,clone_url} use openat instead of re-constructing the path. less strings allocated on-the-fly. I couldn't help myself not to change `len' to be at least `long' to match ftell(3) return type. side question: for nitpicking' sake, should we also make sure len is less than SIZE_MAX-1 before trying to calloc? (minus one to account for NUL.) diff /home/op/w/got commit - 906ae6c0c06930fb1fc983786177f7de6c4d0403 path + /home/op/w/got blob - b5a140ba22d460fe720b01f0db1a2c26b2d0661f file + gotwebd/got_operations.c --- gotwebd/got_operations.c +++ gotwebd/got_operations.c @@ -108,7 +108,7 @@ got_get_repo_owner(char **owner, struct request *c, ch } const struct got_error * -got_get_repo_owner(char **owner, struct request *c, char *dir) +got_get_repo_owner(char **owner, struct request *c) { struct server *srv = c->srv; struct transport *t = c->t; @@ -134,7 +134,7 @@ got_get_repo_age(char **repo_age, struct request *c, c } const struct got_error * -got_get_repo_age(char **repo_age, struct request *c, char *dir, +got_get_repo_age(char **repo_age, struct request *c, const char *refname, int ref_tm) { const struct got_error *error = NULL; blob - 09d8f166fab40a704104d07aaa4c8e0564295c66 file + gotwebd/gotweb.c --- gotwebd/gotweb.c +++ gotwebd/gotweb.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -93,9 +94,9 @@ static const struct got_error *gotweb_get_repo_descrip static const struct got_error *gotweb_load_got_path(struct request *c, struct repo_dir *); static const struct got_error *gotweb_get_repo_description(char **, - struct server *, char *); + struct server *, DIR *); static const struct got_error *gotweb_get_clone_url(char **, struct server *, - char *); + DIR *); static const struct got_error *gotweb_render_navs(struct request *); static const struct got_error *gotweb_render_blame(struct request *); static const struct got_error *gotweb_render_briefs(struct request *); @@ -1545,8 +1546,7 @@ gotweb_render_branches(struct request *c) if (strncmp(refname, "refs/heads/", 11) != 0) continue; - error = got_get_repo_age(&age, c, qs->path, refname, - TM_DIFF); + error = got_get_repo_age(&age, c, refname, TM_DIFF); if (error) goto done; @@ -2431,7 +2431,6 @@ done: goto err; } - repo = find_cached_repo(srv, repo_dir->path); if (repo == NULL) { error = cache_repo(&repo, srv, repo_dir, sock); @@ -2439,18 +2438,16 @@ done: goto err; } t->repo = repo; - error = gotweb_get_repo_description(&repo_dir->description, srv, - repo_dir->path); + error = gotweb_get_repo_description(&repo_dir->description, srv, dt); if (error) goto err; - error = got_get_repo_owner(&repo_dir->owner, c, repo_dir->path); + error = got_get_repo_owner(&repo_dir->owner, c); if (error) goto err; - error = got_get_repo_age(&repo_dir->age, c, repo_dir->path, - NULL, TM_DIFF); + error = got_get_repo_age(&repo_dir->age, c, NULL, TM_DIFF); if (error) goto err; - error = gotweb_get_clone_url(&repo_dir->url, srv, repo_dir->path); + error = gotweb_get_clone_url(&repo_dir->url, srv, dt); err: free(dir_test); if (dt != NULL && closedir(dt) == EOF && error == NULL) @@ -2483,28 +2480,32 @@ gotweb_get_repo_description(char **description, struct } static const struct got_error * -gotweb_get_repo_description(char **description, struct server *srv, char *dir) +gotweb_get_repo_description(char **description, struct server *srv, DIR *dir) { const struct got_error *error = NULL; FILE *f = NULL; - char *d_file = NULL; - unsigned int len; + int fd; + long len; size_t n; *description = NULL; if (srv->show_repo_description == 0) return NULL; - if (asprintf(&d_file, "%s/description", dir) == -1) - return got_error_from_errno("asprintf"); - - f = fopen(d_file, "r"); - if (f == NULL) { + fd = openat(dirfd(dir), "description", O_RDONLY); + if (fd == -1) { if (errno != ENOENT && errno != EACCES) - error = got_error_from_errno2("fopen", d_file); + error = got_error_from_errno2("openat", "description"); goto done; } + f = fdopen(fd, "r"); + if (f == NULL) { + error = got_error_from_errno("fdopen"); + close(fd); + goto done; + } + if (fseek(f, 0, SEEK_END) == -1) { error = got_ferror(f, GOT_ERR_IO); goto done; @@ -2538,17 +2539,16 @@ done: done: if (f != NULL && fclose(f) == EOF && error == NULL) error = got_error_from_errno("fclose"); - free(d_file); return error; } static const struct got_error * -gotweb_get_clone_url(char **url, struct server *srv, char *dir) +gotweb_get_clone_url(char **url, struct server *srv, DIR *dir) { const struct got_error *error = NULL; - FILE *f; - char *d_file = NULL; - unsigned int len; + FILE *f = NULL; + int fd; + long len; size_t n; *url = NULL; @@ -2556,16 +2556,20 @@ gotweb_get_clone_url(char **url, struct server *srv, c if (srv->show_repo_cloneurl == 0) return NULL; - if (asprintf(&d_file, "%s/cloneurl", dir) == -1) - return got_error_from_errno("asprintf"); - - f = fopen(d_file, "r"); - if (f == NULL) { + fd = openat(dirfd(dir), "cloneurl", O_RDONLY); + if (fd == -1) { if (errno != ENOENT && errno != EACCES) - error = got_error_from_errno2("fopen", d_file); + error = got_error_from_errno2("fopen", "cloneurl"); goto done; } + f = fdopen(fd, "r"); + if (f == NULL) { + error = got_error_from_errno("fdopen"); + close(fd); + goto done; + } + if (fseek(f, 0, SEEK_END) == -1) { error = got_ferror(f, GOT_ERR_IO); goto done; @@ -2595,7 +2599,6 @@ done: done: if (f != NULL && fclose(f) == EOF && error == NULL) error = got_error_from_errno("fclose"); - free(d_file); return error; } blob - a8a55276acbd0b209205938c75b88d6918b1c6b8 file + gotwebd/gotwebd.h --- gotwebd/gotwebd.h +++ gotwebd/gotwebd.h @@ -455,8 +455,8 @@ const struct got_error *got_get_repo_owner(char **, st int fcgi_gen_binary_response(struct request *, const uint8_t *, int); /* got_operations.c */ -const struct got_error *got_get_repo_owner(char **, struct request *, char *); -const struct got_error *got_get_repo_age(char **, struct request *, char *, +const struct got_error *got_get_repo_owner(char **, struct request *); +const struct got_error *got_get_repo_age(char **, struct request *, const char *, int); const struct got_error *got_get_repo_commits(struct request *, int); const struct got_error *got_get_repo_tags(struct request *, int);