diff options
author | dzwdz | 2023-09-02 17:45:35 +0200 |
---|---|---|
committer | dzwdz | 2023-09-02 17:45:35 +0200 |
commit | 48d6aa11451f6e4ee0c3716b1c4be3c11287dd3b (patch) | |
tree | 775219a4501957ed8bf52d76291817eb9dfa11ef /src | |
parent | fd7be968dd3bce84e31d62e1faecef9cf5ea14c1 (diff) |
libc: opendir_f; make httpd use it
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/httpd/httpd.c | 53 | ||||
-rw-r--r-- | src/libc/dirent.c | 20 | ||||
-rw-r--r-- | src/libc/include/dirent.h | 1 |
3 files changed, 39 insertions, 35 deletions
diff --git a/src/cmd/httpd/httpd.c b/src/cmd/httpd/httpd.c index 668e534..8826dcb 100644 --- a/src/cmd/httpd/httpd.c +++ b/src/cmd/httpd/httpd.c @@ -2,6 +2,7 @@ * easily DoSable (like the rest of the network stack), vulnerable to path traversal, etc */ #include <camellia/flags.h> #include <camellia/syscalls.h> +#include <dirent.h> #include <err.h> #include <stdio.h> #include <string.h> @@ -25,42 +26,46 @@ static void handle(FILE *c) { fprintf(c, "HTTP/1.1 404 Not Found\r\n\r\n"); return; } - FILE *f = fdopen(h, "r"); - if (!f) { - fprintf(c, "HTTP/1.1 500 Internal Server Error\r\n\r\n"); - return; - } if (path[strlen(path) - 1] != '/') { + FILE *f = fdopen(h, "r"); + if (!f) { + fprintf(c, "HTTP/1.1 500 Internal Server Error\r\n\r\n"); + return; + } + /* regular file */ - fprintf(c, "HTTP/1.1 200 OK\r\n"); - fprintf(c, "\r\n"); + fprintf(c, "HTTP/1.1 200 OK\r\n\r\n"); for (;;) { int len = fread(buf, 1, sizeof buf, f); if (len <= 0) break; fwrite(buf, 1, len, c); } + + fclose(f); } else { /* directory listing */ - fprintf(c, "HTTP/1.1 200 OK\r\n"); - fprintf(c, "Content-Type: text/html; charset=UTF-8\r\n"); - fprintf(c, "\r\n"); - fprintf(c, "<h1>directory listing for %s</h1><hr><ul><li><a href=..>..</a></li>", path); - for (;;) { - int len = fread(buf, 1, sizeof buf, f); - if (len <= 0) break; - // TODO directory library - // based on find.c - for (int pos = 0; pos < len; ) { - if (buf[pos] == '\0') break; - const char *end = memchr(buf + pos, 0, len - pos); - if (!end) break; - fprintf(c, "<li><a href=\"%s\">%s</a></li>", buf + pos, buf + pos); - pos += end - (buf + pos) + 1; - } + DIR *dir = opendir_f(fdopen(h, "r")); + if (!dir) { + fprintf(c, "HTTP/1.1 500 Internal Server Error\r\n\r\n"); + return; + } + + fprintf(c, + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=UTF-8\r\n" + "\r\n" + "<h1>directory listing for %s</h1><hr>" + "<ul><li><a href=..>..</a></li>", + path + ); + + struct dirent *d; + while ((d = readdir(dir))) { + fprintf(c, "<li><a href=\"%s\">%s</a></li>", d->d_name, d->d_name); } + closedir(dir); } - fclose(f); } int main(int argc, char **argv) { diff --git a/src/libc/dirent.c b/src/libc/dirent.c index c2d1b9c..61d8a48 100644 --- a/src/libc/dirent.c +++ b/src/libc/dirent.c @@ -4,22 +4,20 @@ #include <stdlib.h> DIR *opendir(const char *name) { - FILE *fp = NULL; - DIR *dir = NULL; - fp = fopen(name, "r"); - if (!fp) { - goto err; - } + return opendir_f(fopen(name, "r")); +} + +DIR *opendir_f(FILE *fp) { + if (!fp) return NULL; + + DIR *dir; dir = calloc(1, sizeof *dir); if (!dir) { - goto err; + fclose(fp); + return NULL; } dir->fp = fp; return dir; -err: - if (fp) fclose(fp); - free(dir); - return NULL; } int closedir(DIR *dir) { diff --git a/src/libc/include/dirent.h b/src/libc/include/dirent.h index 7c419d7..bfef9ec 100644 --- a/src/libc/include/dirent.h +++ b/src/libc/include/dirent.h @@ -12,5 +12,6 @@ typedef struct { } DIR; DIR *opendir(const char *name); +DIR *opendir_f(FILE *fp); int closedir(DIR *dir); struct dirent *readdir(DIR *dir); |