Fix some issues with zipos and redbean

- redbean.com -D /zip/dir/ now works, for pure fun
- possibly fixed bug with redbean serving empty files
- zipos stat() mode now indicates directories on windows

See #372
This commit is contained in:
Justine Tunney 2022-03-21 07:34:19 -07:00
parent 4881ae7527
commit d57f87dc40
4 changed files with 49 additions and 9 deletions

View file

@ -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) {

View file

@ -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;

View file

@ -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 \

View file

@ -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();