diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index 7778519e4..01683b76b 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -273,6 +273,10 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd, } return VIP(efault()); } + if (__isfdkind(fd, kFdZip)) { + STRACE("mmap(%.12p, %'zu) EINVAL (fd is zipos handle)", p, size); + return VIP(einval()); + } STRACE("mmap(%.12p, %'zu, %s, %d, %'ld)% m", p, size, DescribeMapping(prot, flags, mode), fd, off); if (fd == -1) { diff --git a/libc/zipos/stat-impl.c b/libc/zipos/stat-impl.c index 16b040828..a9d9558a3 100644 --- a/libc/zipos/stat-impl.c +++ b/libc/zipos/stat-impl.c @@ -28,12 +28,8 @@ int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) { size_t lf; if (zipos && st) { bzero(st, sizeof(*st)); - if (ZIP_CFILE_FILEATTRCOMPAT(zipos->map + cf) == kZipOsUnix) { - st->st_mode = ZIP_CFILE_EXTERNALATTRIBUTES(zipos->map + cf) >> 16; - } else { - st->st_mode = 0100644; - } lf = GetZipCfileOffset(zipos->map + cf); + st->st_mode = GetZipCfileMode(zipos->map + cf); st->st_size = GetZipLfileUncompressedSize(zipos->map + lf); st->st_blocks = roundup(GetZipLfileCompressedSize(zipos->map + lf), 512) / 512; diff --git a/tool/net/net.mk b/tool/net/net.mk index 582d6ff7d..ca52719d2 100644 --- a/tool/net/net.mk +++ b/tool/net/net.mk @@ -130,6 +130,7 @@ o/$(MODE)/tool/net/demo/404.html.zip.o: \ ZIPOBJ_FLAGS += \ -B +o/$(MODE)/tool/net/demo/.lua/.zip.o \ o/$(MODE)/tool/net/demo/.lua/mymodule.lua.zip.o: \ ZIPOBJ_FLAGS += \ -C3 @@ -161,6 +162,9 @@ o/$(MODE)/tool/net/redbean-demo.com.dbg: \ o/$(MODE)/tool/net/demo/printpayload.lua.zip.o \ o/$(MODE)/tool/net/demo/redbean-form.lua.zip.o \ o/$(MODE)/tool/net/demo/redbean-xhr.lua.zip.o \ + o/$(MODE)/tool/.zip.o \ + o/$(MODE)/tool/net/.zip.o \ + o/$(MODE)/tool/net/demo/.zip.o \ o/$(MODE)/tool/net/demo/index.html.zip.o \ o/$(MODE)/tool/net/demo/redbean.css.zip.o \ o/$(MODE)/tool/net/redbean.png.zip.o \ @@ -168,6 +172,7 @@ o/$(MODE)/tool/net/redbean-demo.com.dbg: \ o/$(MODE)/tool/net/demo/404.html.zip.o \ o/$(MODE)/tool/net/demo/seekable.txt.zip.o \ o/$(MODE)/tool/net/demo/virtualbean.html.zip.o \ + o/$(MODE)/tool/net/demo/.lua/.zip.o \ o/$(MODE)/tool/net/demo/.lua/mymodule.lua.zip.o \ o/$(MODE)/tool/net/demo/.reload.lua.zip.o \ o/$(MODE)/tool/net/demo/.init.lua.zip.o \ diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 2cf6b473a..f45fe5053 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -50,6 +50,7 @@ #include "libc/rand/rand.h" #include "libc/runtime/clktck.h" #include "libc/runtime/directmap.internal.h" +#include "libc/runtime/gc.h" #include "libc/runtime/gc.internal.h" #include "libc/runtime/runtime.h" #include "libc/runtime/stack.h" @@ -129,6 +130,7 @@ #include "tool/build/lib/psk.h" STATIC_STACK_SIZE(0x40000); +STATIC_YOINK("zip_uri_support"); /** * @fileoverview redbean - single-file distributable web server @@ -155,6 +157,7 @@ STATIC_STACK_SIZE(0x40000); #endif #define VERSION 0x010500 +#define HEARTBEAT 5000 /*ms*/ #define HASH_LOAD_FACTOR /* 1. / */ 4 #define read(F, P, N) readv(F, &(struct iovec){P, N}, 1) #define write(F, P, N) writev(F, &(struct iovec){P, N}, 1) @@ -940,7 +943,7 @@ static void ProgramDirectory(const char *path) { size_t n; struct stat st; - if(stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { + if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { DIEF("(cfg) error: not a directory: %`'s", path); } @@ -1287,6 +1290,22 @@ static void ReapZombies(void) { } while (!terminated); } +static ssize_t ReadAll(int fd, const char *p, size_t n) { + ssize_t rc; + size_t i, got; + for (i = 0; i < n;) { + rc = read(fd, p + i, n - i); + if (rc != -1) { + got = rc; + i += got; + } else if (errno != EINTR) { + WARNF("(file) read error: %m"); + return -1; + } + } + return i; +} + static ssize_t WritevAll(int fd, struct iovec *iov, int iovlen) { int i; ssize_t rc; @@ -3525,9 +3544,11 @@ static void StoreFile(char *path) { if (startswith(target, "./")) target += 2; tlen = strlen(target); if (!IsReasonablePath(target, tlen)) - DIEF("(cfg) error: can't store %`'s: contains '.' or '..' segments", target); + DIEF("(cfg) error: can't store %`'s: contains '.' or '..' segments", + target); if (lstat(path, &st) == -1) DIEF("(cfg) error: can't stat %`'s: %m", path); - if (!(p = xslurp(path, &plen))) DIEF("(cfg) error: can't read %`'s: %m", path); + if (!(p = xslurp(path, &plen))) + DIEF("(cfg) error: can't read %`'s: %m", path); StoreAsset(target, tlen, p, plen, st.st_mode & 0777); free(p); } @@ -6144,6 +6165,7 @@ static char *OpenAsset(struct Asset *a) { int fd; void *data; size_t size; + struct stat *st; if (a->file->st.st_size) { size = a->file->st.st_size; if (msg.method == kHttpHead) { @@ -6158,6 +6180,18 @@ static char *OpenAsset(struct Asset *a) { UnmapLater(fd, data, size); content = data; contentlength = size; + } else if ((st = _gc(malloc(sizeof(struct stat)))) && + fstat(fd, st) != -1 && (data = malloc(st->st_size))) { + /* probably empty file or zipos handle */ + LockInc(&shared->c.slurps); + FreeLater(data); + if (ReadAll(fd, data, st->st_size) != -1) { + content = data; + contentlength = st->st_size; + close(fd); + } else { + return HandleMapFailed(a, fd); + } } else { return HandleMapFailed(a, fd); } @@ -6979,7 +7013,7 @@ static void HandleConnection(size_t i) { static void HandlePoll(void) { size_t i; - if (poll(polls, servers.n, 500) != -1) { + if (poll(polls, servers.n, HEARTBEAT) != -1) { for (i = 0; i < servers.n; ++i) { if (polls[i].revents) { serveraddr = &servers.p[i].addr; @@ -7343,6 +7377,7 @@ void RedBean(int argc, char *argv[]) { } int main(int argc, char *argv[]) { + int fd; if (!IsTiny()) { setenv("GDB", "", true); ShowCrashReports();