diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2024-02-19 23:20:25 +0100 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2024-02-19 23:35:09 +0100 |
| commit | 6c3bfa270b1de6cdea0da8e351f92ec65e90c4f0 (patch) | |
| tree | 3aec762e2bc802962afbb2fd6dcace45da7c62ce | |
| parent | 78c8c4dabb62a6669cfd4eca231e39fd7fd4567a (diff) | |
page.c: Use open(2) fdopen(3) and fstat(2)v0.2.1-rc1
Now, the same file descriptor can be reused for all of the operations
above, instead of calling stat(2) and fopen(3) separately.
| -rw-r--r-- | page.c | 104 |
1 files changed, 79 insertions, 25 deletions
@@ -1294,22 +1294,18 @@ end: } static int serve_file(struct http_response *const r, - const struct stat *const sb, const char *const res, const bool preview) + const struct stat *const sb, const char *const res, const bool preview, + const int fd, bool *const fdopened) { int ret = -1; - FILE *const f = fopen(res, "rb"); + FILE *f = NULL; struct dynstr b, d; char *bn; dynstr_init(&b); dynstr_init(&d); - if (!f) - { - fprintf(stderr, "%s: fopen(3): %s\n", __func__, strerror(errno)); - goto end; - } - else if (dynstr_append(&b, "%s", res)) + if (dynstr_append(&b, "%s", res)) { fprintf(stderr, "%s: dynstr_append res failed\n", __func__); goto end; @@ -1333,6 +1329,14 @@ static int serve_file(struct http_response *const r, goto end; } + if (!(f = fdopen(fd, "rb"))) + { + fprintf(stderr, "%s: fdopen(3): %s\n", __func__, strerror(errno)); + goto end; + } + + *fdopened = true; + *r = (const struct http_response) { .status = HTTP_STATUS_OK, @@ -1402,28 +1406,63 @@ static bool preview(const struct page_resource *const pr) int page_resource(const struct page_resource *const pr) { + int ret = -1; struct stat sb; + const int fd = open(pr->res, O_RDONLY); + bool fdopened = false; - if (stat(pr->res, &sb)) + if (fd < 0) { - fprintf(stderr, "%s: stat(2) %s: %s\n", - __func__, pr->res, strerror(errno)); - if (errno == ENOENT || errno == ENOTDIR) - return page_not_found(pr->r); + ret = page_not_found(pr->r); else - return -1; + fprintf(stderr, "%s: open(2) %s: %s\n", + __func__, pr->res, strerror(errno)); + + goto end; + } + else if (fstat(fd, &sb)) + { + fprintf(stderr, "%s: fstat(2) %s: %s\n", + __func__, pr->res, strerror(errno)); + goto end; } const mode_t m = sb.st_mode; if (S_ISDIR(m)) - return list_dir(pr); + { + if (list_dir(pr)) + { + fprintf(stderr, "%s: list_dir failed\n", __func__); + goto end; + } + } else if (S_ISREG(m)) - return serve_file(pr->r, &sb, pr->res, preview(pr)); + { + if (serve_file(pr->r, &sb, pr->res, preview(pr), fd, &fdopened)) + { + fprintf(stderr, "%s: serve_file failed\n", __func__); + goto end; + } + } + else + { + fprintf(stderr, "%s: unexpected st_mode %jo\n", __func__, (intmax_t)m); + goto end; + } - fprintf(stderr, "%s: unexpected st_mode %jd\n", __func__, (intmax_t)m); - return -1; + ret = 0; + +end: + if (!fdopened && fd >= 0 && close(fd)) + { + fprintf(stderr, "%s: close(2) %s: %s\n", + __func__, pr->res, strerror(errno)); + ret = -1; + } + + return ret; } static char *resolve_link(const char *const res) @@ -1466,18 +1505,26 @@ static char *resolve_link(const char *const res) int page_public(struct http_response *const r, const char *const res) { int ret = -1; + const int fd = open(res, O_RDONLY); struct stat sb; char *path = NULL; + bool fdopened = false; - if (stat(res, &sb)) + if (fd < 0) { - fprintf(stderr, "%s: stat(2) %s: %s\n", - __func__, res, strerror(errno)); - if (errno == ENOENT) - return page_not_found(r); + ret = page_not_found(r); else - goto end; + fprintf(stderr, "%s: stat(2) %s: %s\n", + __func__, res, strerror(errno)); + + goto end; + } + else if (fstat(fd, &sb)) + { + fprintf(stderr, "%s: fstat(2) %s: %s\n", + __func__, res, strerror(errno)); + goto end; } const mode_t m = sb.st_mode; @@ -1492,7 +1539,7 @@ int page_public(struct http_response *const r, const char *const res) fprintf(stderr, "%s: resolve_link failed\n", __func__); goto end; } - else if (serve_file(r, &sb, path, false)) + else if (serve_file(r, &sb, path, false, fd, &fdopened)) { fprintf(stderr, "%s: serve_file failed\n", __func__); goto end; @@ -1501,6 +1548,13 @@ int page_public(struct http_response *const r, const char *const res) ret = 0; end: + if (!fdopened && fd >= 0 && close(fd)) + { + fprintf(stderr, "%s: close(2) %s: %s\n", + __func__, res, strerror(errno)); + ret = -1; + } + free(path); return ret; } |
