From 37095b599613c64825b33025b72251aaa97cf466 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 16 Mar 2020 20:41:55 +0200 Subject: Initial commit --- physfs-serve.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 physfs-serve.c (limited to 'physfs-serve.c') diff --git a/physfs-serve.c b/physfs-serve.c new file mode 100644 index 0000000..55e4dce --- /dev/null +++ b/physfs-serve.c @@ -0,0 +1,127 @@ +#include "libphysfs-serve.h" +#include +#include +#include +#include +#include +#include + +#ifndef SERVE_INIT +# define SERVE_INIT 0 +#endif + +static char* +strrchr_safe(const char *s, int c) { + char *ret = strrchr(s, c); + return (ret ? ret : (char*)s + strlen(s)); +} + +static void +dirname(char *path) { + char *ret; + if (!(ret = strrchr(path, '/'))) { + *path = 0; + return; + } + *ret = 0; +} + +const bool +find_file(const char *root, const char *file, char res_buf[], size_t res_buf_sz) { + char **rc; + if (!(rc = PHYSFS_enumerateFiles(root))) + return false; + + for (char **i = rc; *i != NULL; ++i) { + char fullpath[1024]; + snprintf(fullpath, sizeof(fullpath), "%s/%s", root, *i); + struct PHYSFS_Stat st = {0}; + PHYSFS_stat(fullpath, &st); + if (st.filetype == PHYSFS_FILETYPE_DIRECTORY) { + if (find_file(fullpath, file, res_buf, res_buf_sz)) { + PHYSFS_freeList(rc); + return true; + } + } else { + if (strcmp(file, *i)) continue; + snprintf(res_buf, res_buf_sz, "%s", fullpath); + PHYSFS_freeList(rc); + return true; + } + } + + PHYSFS_freeList(rc); + return false; +} + +struct args { + const char *path[32]; + unsigned int npaths; + unsigned int port; + const char *addr; +}; + +bool +parse_arg(char *argv[], int argc, struct args *args) { + if (*argv[0] != '-') { + args->path[args->npaths++] = argv[0]; + } else { + const char *next = (argc > 1 ? argv[1] : ""); + for (const char *s = argv[0] + 1; *s; ++s) { + switch (*s) { + case 'i': args->addr = next; return true; + case 'p': args->port = strtoul(next, NULL, 10); return true; + } + } + } + return false; +} + +int +main(int argc, char *argv[]) { + if (argc < 2) + errx(EXIT_FAILURE, "usage: [-i addr] [-p port] archive ..."); + + struct args args = { .addr = "0.0.0.0", .port = 1337 }; + for (int i = 1; i < argc; ++i) + i += parse_arg(&argv[i], argc - i, &args); + + if (!PHYSFS_init(argv[0])) + errx(EXIT_FAILURE, "PHYSFS_init failed"); + + for (unsigned int i = 0; i < args.npaths; ++i) { + if (!PHYSFS_mount(args.path[i], NULL, 0)) + errx(EXIT_FAILURE, "failed to mount archive: %s", args.path[i]); + + if (i == 0) { + char root[1024]; + if (!find_file("", "index.html", root, sizeof(root))) + errx(EXIT_FAILURE, "no index.html found in the root archive"); + + dirname(root); + PHYSFS_setRoot(args.path[i], root); + } + } + + while (1) { + struct physfs_serve serve = { SERVE_INIT }; + if (!physfs_serve_init(&serve, args.port, args.addr)) + errx(EXIT_FAILURE, "couldn't listen"); + + while (1) { + struct pollfd pfd[ARRAY_SIZE(serve.fd)]; + for (int i = 0; i < ARRAY_SIZE(serve.fd); ++i) + pfd[i] = (struct pollfd){ .fd = serve.fd[i], .events = POLLIN }; + + poll(pfd, serve.nfds, -1); + for (int i = 0; i < serve.nfds; ++i) + if (pfd[i].revents & POLLIN && !physfs_serve_event(&serve, i)) + break; + } + + physfs_serve_free(&serve); + } + + PHYSFS_deinit(); + return EXIT_SUCCESS; +} -- cgit v1.2.3