From 218ef491476f15abb980ee89bf69344913a4c51d Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sat, 27 Feb 2021 10:47:19 -0800 Subject: [PATCH] Fix redbean zip central directory lookup This regression snuck in at some point. It resulted in the program sometimes failing to load when the zip content was changed. --- Makefile | 1 + build/definitions.mk | 1 + build/gdb | 5 ++ libc/zipos/get.c | 9 +++- test/libc/stdio/mkostempsm_test.c | 8 ++-- test/tool/net/redbean_test.c | 76 +++++++++++++++++++++++++++++++ test/tool/net/test.mk | 69 ++++++++++++++++++++++++++++ test/tool/test.mk | 1 + tool/net/redbean.c | 16 ++++++- tool/viz/derasterize.c | 8 ++-- 10 files changed, 183 insertions(+), 11 deletions(-) create mode 100755 build/gdb create mode 100644 test/tool/net/redbean_test.c create mode 100644 test/tool/net/test.mk diff --git a/Makefile b/Makefile index e2c63ea18..76ec679cc 100644 --- a/Makefile +++ b/Makefile @@ -178,6 +178,7 @@ include test/tool/build/lib/test.mk include test/tool/build/test.mk include test/tool/viz/lib/test.mk include test/tool/viz/test.mk +include test/tool/net/test.mk include test/tool/test.mk include test/dsp/core/test.mk include test/dsp/scale/test.mk diff --git a/build/definitions.mk b/build/definitions.mk index 2c5549448..c2746a40c 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -137,6 +137,7 @@ MATHEMATICAL = \ -fwrapv DEFAULT_CPPFLAGS = \ + -DMODE='"$(MODE)"' \ -DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL) \ -nostdinc \ -iquote. diff --git a/build/gdb b/build/gdb new file mode 100755 index 000000000..36e328b5d --- /dev/null +++ b/build/gdb @@ -0,0 +1,5 @@ +#!/bin/sh +exec gdb -q -nh -i=mi $1 \ + -ex "set confirm off" \ + -ex "add-symbol-file $1.dbg 0x401000" \ + -ex "run" diff --git a/libc/zipos/get.c b/libc/zipos/get.c index 4613364fe..d0b713094 100644 --- a/libc/zipos/get.c +++ b/libc/zipos/get.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/safemacros.h" #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" #include "libc/limits.h" @@ -33,12 +34,18 @@ struct Zipos *__zipos_get(void) { static struct Zipos zipos; static bool once; - const char *exe; + const char *exe, *dir; + char path[PATH_MAX]; size_t mapsize; uint8_t *cdir; void *map; if (!once) { + dir = nulltoempty(getenv("PWD")); /* suboptimal */ exe = (const char *)getauxval(AT_EXECFN); + if (!fileexists(exe) && strlen(dir) + 1 + strlen(exe) + 1 <= PATH_MAX) { + stpcpy(stpcpy(stpcpy(path, dir), "/"), exe); + exe = path; + } if ((zipos.fd = open(exe, O_RDONLY)) != -1) { if ((mapsize = getfiledescriptorsize(zipos.fd)) != SIZE_MAX && (map = mmap(NULL, mapsize, PROT_READ, MAP_SHARED, zipos.fd, 0)) != diff --git a/test/libc/stdio/mkostempsm_test.c b/test/libc/stdio/mkostempsm_test.c index f59abc407..af911e000 100644 --- a/test/libc/stdio/mkostempsm_test.c +++ b/test/libc/stdio/mkostempsm_test.c @@ -24,7 +24,7 @@ #include "libc/sysv/consts/o.h" #include "libc/testlib/testlib.h" -#define MODE() \ +#define Mode() \ ({ \ va_list va; \ unsigned Mode; \ @@ -40,7 +40,7 @@ static int MockOpen1(const char *file, int flags, ...) { once = true; EXPECT_STREQ("/tmp/mkostemps.ctre5m", file); EXPECT_EQ(O_RDWR | O_CREAT | O_EXCL, flags); - EXPECT_EQ(0600, MODE()); + EXPECT_EQ(0600, Mode()); return 123; } @@ -59,14 +59,14 @@ static int MockOpen2(const char *file, int flags, ...) { state = 1; EXPECT_STREQ("/tmp/mkostemps.ctre5m", file); EXPECT_EQ((unsigned)(O_RDWR | O_CREAT | O_EXCL), flags); - EXPECT_EQ(0600, MODE()); + EXPECT_EQ(0600, Mode()); errno = EEXIST; return -1; case 1: state = 1; EXPECT_STREQ("/tmp/mkostemps.jl1h61", file); EXPECT_EQ((unsigned)(O_RDWR | O_CREAT | O_EXCL), flags); - EXPECT_EQ(0600, MODE()); + EXPECT_EQ(0600, Mode()); return 123; default: abort(); diff --git a/test/tool/net/redbean_test.c b/test/tool/net/redbean_test.c new file mode 100644 index 000000000..cb90f0299 --- /dev/null +++ b/test/tool/net/redbean_test.c @@ -0,0 +1,76 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/calls/calls.h" +#include "libc/calls/sigbits.h" +#include "libc/fmt/conv.h" +#include "libc/runtime/gc.h" +#include "libc/runtime/runtime.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/auxv.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/consts/sig.h" +#include "libc/testlib/testlib.h" +#include "libc/x/x.h" + +/* TODO(jart): Finish this */ + +STATIC_YOINK("zip_uri_support"); +STATIC_YOINK("o/" MODE "/tool/net/redbean.com"); +char testlib_enable_tmp_setup_teardown; + +void SetUp(void) { + return; + ssize_t n; + char buf[512]; + int fdin, fdout; + ASSERT_NE(-1, mkdir("bin", 0755)); + ASSERT_NE(-1, (fdin = open("zip:o/" MODE "/tool/net/redbean.com", O_RDONLY))); + ASSERT_NE(-1, (fdout = creat("bin/redbean.com", 0755))); + for (;;) { + ASSERT_NE(-1, (n = read(fdin, buf, sizeof(buf)))); + if (!n) break; + ASSERT_EQ(n, write(fdout, buf, sizeof(buf))); + } + close(fdout); + close(fdin); +} + +TEST(redbean, test) { + return; + char portbuf[16]; + int pid, port, pipefds[2]; + sigset_t chldmask, savemask; + sigaddset(&chldmask, SIGCHLD); + sigprocmask(SIG_BLOCK, &chldmask, &savemask); + ASSERT_NE(-1, pipe2(pipefds, O_CLOEXEC)); + ASSERT_NE(-1, (pid = vfork())); + if (!pid) { + dup2(pipefds[1], 1); + sigprocmask(SIG_SETMASK, &savemask, NULL); + execv("bin/redbean.com", + (char *const[]){"bin/redbean.com", "-zp0", "-l127.0.0.1", 0}); + _exit(127); + } + EXPECT_NE(-1, close(pipefds[1])); + EXPECT_NE(-1, read(pipefds[0], portbuf, sizeof(portbuf))); + port = atoi(portbuf); + printf("port %d\n", port); + EXPECT_NE(-1, kill(pid, SIGTERM)); + EXPECT_NE(-1, wait(0)); +} diff --git a/test/tool/net/test.mk b/test/tool/net/test.mk new file mode 100644 index 000000000..5dae443a7 --- /dev/null +++ b/test/tool/net/test.mk @@ -0,0 +1,69 @@ +#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ +#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ + +PKGS += TEST_TOOL_NET + +TEST_TOOL_NET = $(TOOL_NET_A_DEPS) $(TOOL_NET_A) +TEST_TOOL_NET_A = o/$(MODE)/test/tool/net/net.a +TEST_TOOL_NET_FILES := $(wildcard test/tool/net/*) +TEST_TOOL_NET_SRCS = $(filter %.c,$(TEST_TOOL_NET_FILES)) +TEST_TOOL_NET_SRCS_TEST = $(filter %_test.c,$(TEST_TOOL_NET_SRCS)) +TEST_TOOL_NET_HDRS = $(filter %.h,$(TEST_TOOL_NET_FILES)) +TEST_TOOL_NET_COMS = $(TEST_TOOL_NET_OBJS:%.o=%.com) +TEST_TOOL_NET_COMS = $(TEST_TOOL_NET_SRCS:%.c=o/$(MODE)/%.com) + +TEST_TOOL_NET_OBJS = \ + $(TEST_TOOL_NET_SRCS:%.c=o/$(MODE)/%.o) \ + o/$(MODE)/tool/net/redbean.com.zip.o + +TEST_TOOL_NET_BINS = \ + $(TEST_TOOL_NET_COMS) \ + $(TEST_TOOL_NET_COMS:%=%.dbg) + +TEST_TOOL_NET_TESTS = \ + $(TEST_TOOL_NET_SRCS_TEST:%.c=o/$(MODE)/%.com.ok) + +TEST_TOOL_NET_CHECKS = \ + $(TEST_TOOL_NET_HDRS:%=o/$(MODE)/%.ok) \ + $(TEST_TOOL_NET_SRCS_TEST:%.c=o/$(MODE)/%.com.runs) + +TEST_TOOL_NET_DIRECTDEPS = \ + LIBC_CALLS \ + LIBC_STUBS \ + LIBC_FMT \ + LIBC_STDIO \ + LIBC_INTRIN \ + LIBC_NEXGEN32E \ + LIBC_SYSV \ + LIBC_MEM \ + LIBC_RUNTIME \ + LIBC_X \ + LIBC_TESTLIB \ + LIBC_ZIPOS + +TEST_TOOL_NET_DEPS := \ + $(call uniq,$(foreach x,$(TEST_TOOL_NET_DIRECTDEPS),$($(x)))) + +$(TEST_TOOL_NET_A): \ + test/tool/net/ \ + $(TEST_TOOL_NET_A).pkg \ + $(TEST_TOOL_NET_OBJS) + +$(TEST_TOOL_NET_A).pkg: \ + $(TEST_TOOL_NET_OBJS) \ + $(foreach x,$(TEST_TOOL_NET_DIRECTDEPS),$($(x)_A).pkg) + +o/$(MODE)/test/tool/net/%.com.dbg: \ + $(TEST_TOOL_NET_DEPS) \ + $(TEST_TOOL_NET_A) \ + o/$(MODE)/test/tool/net/%.o \ + $(TEST_TOOL_NET_A).pkg \ + $(LIBC_TESTMAIN) \ + $(CRT) \ + $(APE) + @$(APELINK) + +.PHONY: o/$(MODE)/test/tool/net +o/$(MODE)/test/tool/net: \ + $(TEST_TOOL_NET_BINS) \ + $(TEST_TOOL_NET_CHECKS) diff --git a/test/tool/test.mk b/test/tool/test.mk index 066943cf5..fa224a841 100644 --- a/test/tool/test.mk +++ b/test/tool/test.mk @@ -4,4 +4,5 @@ .PHONY: o/$(MODE)/test/tool o/$(MODE)/test/tool: \ o/$(MODE)/test/tool/build \ + o/$(MODE)/test/tool/net \ o/$(MODE)/test/tool/viz diff --git a/tool/net/redbean.c b/tool/net/redbean.c index a6ecce185..385166b2a 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -86,6 +86,7 @@ FLAGS\n\ -v verbosity\n\ -d daemonize\n\ -s uniprocess\n\ + -z print port\n\ -m log messages\n\ -c INT cache seconds\n\ -r /X=/Y redirect X to Y\n\ @@ -216,6 +217,7 @@ static struct Assets { static bool killed; static bool notimer; +static bool printport; static bool heartbeat; static bool daemonize; static bool terminated; @@ -372,7 +374,7 @@ void GetOpts(int argc, char *argv[]) { serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(DEFAULT_PORT); serveraddr.sin_addr.s_addr = INADDR_ANY; - while ((opt = getopt(argc, argv, "hduvml:p:w:r:c:L:P:U:G:B:")) != -1) { + while ((opt = getopt(argc, argv, "zhduvml:p:w:r:c:L:P:U:G:B:")) != -1) { switch (opt) { case 'v': g_loglevel++; @@ -386,6 +388,9 @@ void GetOpts(int argc, char *argv[]) { case 'm': logmessages = true; break; + case 'z': + printport = true; + break; case 'r': AddRedirect(optarg); break; @@ -646,7 +651,7 @@ static bool OpenZip(const char *path) { if ((fd = open(path, O_RDONLY)) != -1 && fstat(fd, &st) != -1 && st.st_size && (map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) && - (cdir = zipfindcentraldir(zmap, zmapsize)) && IndexAssets(map, cdir)) { + (cdir = zipfindcentraldir(map, st.st_size)) && IndexAssets(map, cdir)) { ok = true; zmap = map; zbase = map; @@ -1144,6 +1149,7 @@ static void TuneServerSocket(void) { } void RedBean(void) { + uint32_t addrsize; gmtoff = GetGmtOffset(); programfile = (const char *)getauxval(AT_EXECFN); CHECK(OpenZip(programfile)); @@ -1159,9 +1165,15 @@ void RedBean(void) { TuneServerSocket(); CHECK_NE(-1, bind(server, &serveraddr, sizeof(serveraddr))); CHECK_NE(-1, listen(server, 10)); + addrsize = sizeof(serveraddr); + CHECK_NE(-1, getsockname(server, &serveraddr, &addrsize)); DescribeAddress(serveraddrstr, &serveraddr); if (daemonize) Daemonize(); VERBOSEF("%s listen", serveraddrstr); + if (printport) { + printf("%d\n", ntohs(serveraddr.sin_port)); + fflush(stdout); + } heartbeat = true; while (!terminated) { if (invalidated) { diff --git a/tool/viz/derasterize.c b/tool/viz/derasterize.c index 9ebe8680c..af52d5943 100644 --- a/tool/viz/derasterize.c +++ b/tool/viz/derasterize.c @@ -101,15 +101,15 @@ int y_; /* -y HEIGHT [in flexidecimal] */ #define FAST 1 #define FASTER 2 -#define MODE BEST +#define Mode BEST -#if MODE == BEST +#if Mode == BEST #define MC 9u /* log2(#) of color combos to consider */ #define GN 35u /* # of glyphs to consider */ -#elif MODE == FAST +#elif Mode == FAST #define MC 6u #define GN 35u -#elif MODE == FASTER +#elif Mode == FASTER #define MC 4u #define GN 25u #endif