Skip to content

Commit b918706

Browse files
committed
Let redbean use its own ZIP EXE as NoSQL database
1 parent e56a9d0 commit b918706

File tree

1 file changed

+139
-14
lines changed

1 file changed

+139
-14
lines changed

tool/net/redbean.c

Lines changed: 139 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ static bool loggednetworkorigin;
299299
static bool hasluaglobalhandler;
300300

301301
static int zfd;
302+
static int zprot;
302303
static int frags;
303304
static int gmtoff;
304305
static int server;
@@ -1365,12 +1366,10 @@ static bool ZipCdirChanged(void) {
13651366
static void OpenZip(void) {
13661367
uint8_t *p;
13671368
if (zmap) munmap(zmap, zsize);
1368-
CHECK_NE(-1, (zfd = open(zpath, O_RDONLY)));
13691369
CHECK_NE(-1, fstat(zfd, &zst));
13701370
CHECK((zsize = zst.st_size));
1371-
CHECK_NE(MAP_FAILED,
1372-
(zmap = mmap((void *)0x0000300000000000, zsize, PROT_READ,
1373-
MAP_FIXED | MAP_SHARED, zfd, 0)));
1371+
CHECK_NE(MAP_FAILED, (zmap = mmap((void *)0x0000300000000000, zsize, zprot,
1372+
MAP_FIXED | MAP_SHARED, zfd, 0)));
13741373
CHECK_NOTNULL((zcdir = GetZipCdir(zmap, zsize)));
13751374
if (endswith(zpath, ".com.dbg") && (p = memmem(zmap, zsize, "MZqFpD", 6))) {
13761375
zsize -= p - zmap;
@@ -2367,6 +2366,14 @@ static int LuaLoadAsset(lua_State *L) {
23672366
return 0;
23682367
}
23692368

2369+
static void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time,
2370+
uint16_t *out_date) {
2371+
struct tm tm;
2372+
CHECK_NOTNULL(localtime_r(&utcunixts, &tm));
2373+
*out_time = DOS_TIME(tm.tm_hour, tm.tm_min, tm.tm_sec);
2374+
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1);
2375+
}
2376+
23702377
static bool IsUtf8(const void *data, size_t size) {
23712378
const unsigned char *p, *pe;
23722379
for (p = data, pe = p + size; p + 2 <= pe; ++p) {
@@ -2391,12 +2398,125 @@ static bool IsText(const void *data, size_t size) {
23912398
return true;
23922399
}
23932400

2394-
static void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time,
2395-
uint16_t *out_date) {
2396-
struct tm tm;
2397-
CHECK_NOTNULL(localtime_r(&utcunixts, &tm));
2398-
*out_time = DOS_TIME(tm.tm_hour, tm.tm_min, tm.tm_sec);
2399-
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1);
2401+
static int LuaStoreAsset(lua_State *L) {
2402+
int mode;
2403+
int64_t ft;
2404+
uint8_t era;
2405+
uint32_t crc;
2406+
long double now;
2407+
char *comp, *p, *q;
2408+
const char *path, *data, *use;
2409+
uint16_t gflags, iattrs, mtime, mdate, dosmode, method, disk;
2410+
size_t newlfileoffset, newcdiroffset, neweocdoffset, oldcdirrecords;
2411+
size_t pathlen, datalen, complen, uselen, oldcdirsize, moar, extralen;
2412+
if (IsOpenbsd() || IsNetbsd() || IsWindows()) {
2413+
luaL_error(L, "StoreAsset() not available on Windows/NetBSD/OpenBSD yet");
2414+
unreachable;
2415+
}
2416+
now = nowl();
2417+
path = LuaCheckPath(L, 1, &pathlen);
2418+
data = luaL_checklstring(L, 2, &datalen);
2419+
mode = luaL_optinteger(L, 3, 0644);
2420+
if (!(mode & S_IFMT)) mode |= S_IFREG;
2421+
if (pathlen > 1 && path[0] == '/') ++path, --pathlen;
2422+
crc = crc32_z(0, data, datalen);
2423+
if (datalen < 100) {
2424+
method = kZipCompressionNone;
2425+
comp = NULL;
2426+
use = data;
2427+
uselen = datalen;
2428+
} else {
2429+
comp = Deflate(data, datalen, &complen);
2430+
if (complen < datalen) {
2431+
method = kZipCompressionDeflate;
2432+
use = comp;
2433+
uselen = complen;
2434+
} else {
2435+
method = kZipCompressionNone;
2436+
use = data;
2437+
uselen = datalen;
2438+
}
2439+
}
2440+
disk = gflags = iattrs = 0;
2441+
era = method ? kZipEra1993 : kZipEra1989;
2442+
ft = (now + MODERNITYSECONDS) * HECTONANOSECONDS;
2443+
dosmode = !(mode & 0200) ? kNtFileAttributeReadonly : 0;
2444+
GetDosLocalTime(now, &mtime, &mdate);
2445+
if (IsUtf8(path, pathlen)) gflags |= kZipGflagUtf8;
2446+
if (IsText(data, datalen)) iattrs |= kZipIattrText;
2447+
CHECK_NE(-1, flock(zfd, LOCK_EX));
2448+
if (ZipCdirChanged()) Reindex();
2449+
oldcdirrecords = GetZipCdirRecords(zcdir);
2450+
oldcdirsize = GetZipCdirSize(zcdir);
2451+
extralen = 36;
2452+
moar = kZipLfileHdrMinSize + pathlen + datalen + oldcdirsize +
2453+
kZipCfileHdrMinSize + pathlen + extralen + kZipCdirHdrMinSize;
2454+
CHECK_NE(-1, ftruncate(zfd, zsize + moar));
2455+
CHECK_NE(MAP_FAILED, (zmap = mmap((void *)0x0000300000000000, zsize + moar,
2456+
PROT_READ | PROT_WRITE,
2457+
MAP_FIXED | MAP_SHARED, zfd, 0)));
2458+
p = q = (char *)zmap;
2459+
p += zsize;
2460+
newlfileoffset = p - q;
2461+
p = WRITE32LE(p, kZipLfileHdrMagic);
2462+
*p++ = era;
2463+
*p++ = kZipOsDos;
2464+
p = WRITE16LE(p, gflags);
2465+
p = WRITE16LE(p, method);
2466+
p = WRITE16LE(p, mtime);
2467+
p = WRITE16LE(p, mdate);
2468+
p = WRITE32LE(p, crc);
2469+
p = WRITE32LE(p, uselen);
2470+
p = WRITE32LE(p, datalen);
2471+
p = WRITE16LE(p, pathlen);
2472+
p = WRITE16LE(p, 0);
2473+
p = mempcpy(p, path, pathlen);
2474+
p = mempcpy(p, data, datalen);
2475+
newcdiroffset = p - q;
2476+
p = mempcpy(p, zmap + GetZipCdirOffset(zcdir), oldcdirsize);
2477+
p = WRITE32LE(p, kZipCfileHdrMagic);
2478+
*p++ = kZipCosmopolitanVersion;
2479+
*p++ = kZipOsUnix;
2480+
*p++ = era;
2481+
*p++ = kZipOsDos;
2482+
p = WRITE16LE(p, gflags);
2483+
p = WRITE16LE(p, method);
2484+
p = WRITE16LE(p, mtime);
2485+
p = WRITE16LE(p, mdate);
2486+
p = WRITE32LE(p, crc);
2487+
p = WRITE32LE(p, uselen);
2488+
p = WRITE32LE(p, datalen);
2489+
p = WRITE16LE(p, pathlen);
2490+
p = WRITE16LE(p, extralen);
2491+
p = WRITE16LE(p, 0);
2492+
p = WRITE16LE(p, disk);
2493+
p = WRITE16LE(p, iattrs);
2494+
p = WRITE16LE(p, dosmode);
2495+
p = WRITE16LE(p, mode);
2496+
p = WRITE32LE(p, newlfileoffset);
2497+
p = mempcpy(p, path, pathlen);
2498+
p = WRITE16LE(p, kZipExtraNtfs);
2499+
p = WRITE16LE(p, 32);
2500+
p = WRITE32LE(p, 0);
2501+
p = WRITE16LE(p, 1);
2502+
p = WRITE16LE(p, 24);
2503+
p = WRITE64LE(p, ft);
2504+
p = WRITE64LE(p, ft);
2505+
p = WRITE64LE(p, ft);
2506+
neweocdoffset = p - q;
2507+
p = WRITE32LE(p, kZipCdirHdrMagic);
2508+
p = WRITE16LE(p, 0);
2509+
p = WRITE16LE(p, 0);
2510+
p = WRITE16LE(p, oldcdirrecords + 1);
2511+
p = WRITE16LE(p, oldcdirrecords + 1);
2512+
p = WRITE32LE(p, neweocdoffset - newcdiroffset);
2513+
p = WRITE32LE(p, newcdiroffset);
2514+
p = WRITE16LE(p, 0);
2515+
zcdir[0] = 'J';
2516+
zcdir[1] = 'T';
2517+
CHECK_NE(-1, flock(zfd, LOCK_UN));
2518+
free(comp);
2519+
return 0;
24002520
}
24012521

24022522
static int LuaGetDate(lua_State *L) {
@@ -3524,6 +3644,7 @@ static const luaL_Reg kLuaFuncs[] = {
35243644
{"SetHeader", LuaSetHeader}, //
35253645
{"SetLogLevel", LuaSetLogLevel}, //
35263646
{"SetStatus", LuaSetStatus}, //
3647+
{"StoreAsset", LuaStoreAsset}, //
35273648
{"Underlong", LuaUnderlong}, //
35283649
{"VisualizeControlCodes", LuaVisualizeControlCodes}, //
35293650
{"Write", LuaWrite}, //
@@ -4517,7 +4638,6 @@ static void TuneSockets(void) {
45174638
}
45184639

45194640
static void RestoreApe(void) {
4520-
int fd;
45214641
char *p;
45224642
size_t n;
45234643
struct Asset *a;
@@ -4526,14 +4646,17 @@ static void RestoreApe(void) {
45264646
if (IsOpenbsd()) return; /* TODO */
45274647
if (IsNetbsd()) return; /* TODO */
45284648
if (endswith(zpath, ".com.dbg")) return;
4529-
fd = OpenExecutable();
4649+
close(zfd);
4650+
zfd = OpenExecutable();
45304651
if ((a = GetAssetZip("/.ape", 5)) && (p = LoadAsset(a, &n))) {
4531-
write(fd, p, n);
4652+
write(zfd, p, n);
45324653
free(p);
4654+
zprot = PROT_READ | PROT_WRITE;
4655+
CHECK_NE(MAP_FAILED, (zmap = mmap((void *)0x0000300000000000, zsize, zprot,
4656+
MAP_FIXED | MAP_SHARED, zfd, 0)));
45334657
} else {
45344658
WARNF("/.ape not found");
45354659
}
4536-
close(fd);
45374660
}
45384661

45394662
void RedBean(int argc, char *argv[]) {
@@ -4544,7 +4667,9 @@ void RedBean(int argc, char *argv[]) {
45444667
(shared = mmap(NULL, ROUNDUP(sizeof(struct Shared), FRAMESIZE),
45454668
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
45464669
-1, 0)));
4670+
zprot = PROT_READ;
45474671
zpath = (const char *)getauxval(AT_EXECFN);
4672+
CHECK_NE(-1, (zfd = open(zpath, O_RDONLY)));
45484673
OpenZip();
45494674
IndexAssets();
45504675
RestoreApe();

0 commit comments

Comments
 (0)