commit 4606e6d4d9f8bbd3f9e4ac08a08f06f8793467d7 from: Omar Polo via: Thomas Adam date: Wed Nov 23 17:07:20 2022 UTC gotwebd: rework gotweb_get_repo_{description,cloneurl} - use openat(2) since we've already opened the containing dir - use fstat(2) instead of multiple seeks - don't special case len == 0 ok and improvements by stsp commit - 6c7f10f7250c7b1cb44cc9490bec065ad0107d24 commit + 4606e6d4d9f8bbd3f9e4ac08a08f06f8793467d7 blob - 9a945a4f551877621c21213d3e00fb7b28392106 blob + 62c8affdffd90f8a7ac1ee1b3b6754e5edf6bc24 --- gotwebd/gotweb.c +++ gotwebd/gotweb.c @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -93,9 +96,9 @@ static const struct got_error *gotweb_init_repo_dir(st 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 *, const char *, int); static const struct got_error *gotweb_get_clone_url(char **, struct server *, - char *); + const char *, int); 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 *); @@ -2438,7 +2441,7 @@ done: } t->repo = repo; error = gotweb_get_repo_description(&repo_dir->description, srv, - repo_dir->path); + repo_dir->path, dirfd(dt)); if (error) goto err; error = got_get_repo_owner(&repo_dir->owner, c); @@ -2447,7 +2450,8 @@ done: 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, repo_dir->path, + dirfd(dt)); err: free(dir_test); if (dt != NULL && closedir(dt) == EOF && error == NULL) @@ -2480,105 +2484,82 @@ gotweb_init_repo_dir(struct repo_dir **repo_dir, const } 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, + const char *dirpath, int dir) { const struct got_error *error = NULL; - FILE *f = NULL; - char *d_file = NULL; - unsigned int len; - size_t n; + struct stat sb; + int fd = -1; + off_t len; *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) { - if (errno != ENOENT && errno != EACCES) - error = got_error_from_errno2("fopen", d_file); + fd = openat(dir, "description", O_RDONLY); + if (fd == -1) { + if (errno != ENOENT && errno != EACCES) { + error = got_error_from_errno_fmt("openat %s/%s", + dirpath, "description"); + } goto done; } - if (fseek(f, 0, SEEK_END) == -1) { - error = got_ferror(f, GOT_ERR_IO); + if (fstat(fd, &sb) == -1) { + error = got_error_from_errno_fmt("fstat %s/%s", + dirpath, "description"); goto done; } - len = ftell(f); - if (len == -1) { - error = got_ferror(f, GOT_ERR_IO); - goto done; - } - if (len == 0) { - *description = strdup(""); - if (*description == NULL) - error = got_error_from_errno("strdup"); - goto done; - } + len = sb.st_size; + if (len > SIZE_MAX - 1) + len = SIZE_MAX - 1; - if (fseek(f, 0, SEEK_SET) == -1) { - error = got_ferror(f, GOT_ERR_IO); - goto done; - } *description = calloc(len + 1, sizeof(**description)); if (*description == NULL) { error = got_error_from_errno("calloc"); goto done; } - n = fread(*description, 1, len, f); - if (n == 0 && ferror(f)) - error = got_ferror(f, GOT_ERR_IO); + if (read(fd, *description, len) == -1) + error = got_error_from_errno("read"); done: - if (f != NULL && fclose(f) == EOF && error == NULL) - error = got_error_from_errno("fclose"); - free(d_file); + if (fd != -1 && close(fd) == -1 && error == NULL) + error = got_error_from_errno("close"); 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, const char *dirpath, + int dir) { const struct got_error *error = NULL; - FILE *f; - char *d_file = NULL; - unsigned int len; - size_t n; + struct stat sb; + int fd = -1; + off_t len; *url = NULL; - 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) { - if (errno != ENOENT && errno != EACCES) - error = got_error_from_errno2("fopen", d_file); + fd = openat(dir, "cloneurl", O_RDONLY); + if (fd == -1) { + if (errno != ENOENT && errno != EACCES) { + error = got_error_from_errno_fmt("openat %s/%s", + dirpath, "cloneurl"); + } goto done; } - if (fseek(f, 0, SEEK_END) == -1) { - error = got_ferror(f, GOT_ERR_IO); + if (fstat(fd, &sb) == -1) { + error = got_error_from_errno_fmt("fstat %s/%s", + dirpath, "cloneurl"); goto done; } - len = ftell(f); - if (len == -1) { - error = got_ferror(f, GOT_ERR_IO); - goto done; - } - if (len == 0) - goto done; - if (fseek(f, 0, SEEK_SET) == -1) { - error = got_ferror(f, GOT_ERR_IO); - goto done; - } + len = sb.st_size; + if (len > SIZE_MAX - 1) + len = SIZE_MAX - 1; *url = calloc(len + 1, sizeof(**url)); if (*url == NULL) { @@ -2586,13 +2567,11 @@ gotweb_get_clone_url(char **url, struct server *srv, c goto done; } - n = fread(*url, 1, len, f); - if (n == 0 && ferror(f)) - error = got_ferror(f, GOT_ERR_IO); + if (read(fd, *url, len) == -1) + error = got_error_from_errno("read"); done: - if (f != NULL && fclose(f) == EOF && error == NULL) - error = got_error_from_errno("fclose"); - free(d_file); + if (fd != -1 && close(fd) == -1 && error == NULL) + error = got_error_from_errno("close"); return error; }