mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-04-27 17:24:43 +00:00
Let redbean use its own ZIP EXE as NoSQL database
This commit is contained in:
parent
e56a9d0e23
commit
b9187061a7
1 changed files with 139 additions and 14 deletions
|
@ -299,6 +299,7 @@ static bool loggednetworkorigin;
|
||||||
static bool hasluaglobalhandler;
|
static bool hasluaglobalhandler;
|
||||||
|
|
||||||
static int zfd;
|
static int zfd;
|
||||||
|
static int zprot;
|
||||||
static int frags;
|
static int frags;
|
||||||
static int gmtoff;
|
static int gmtoff;
|
||||||
static int server;
|
static int server;
|
||||||
|
@ -1365,12 +1366,10 @@ static bool ZipCdirChanged(void) {
|
||||||
static void OpenZip(void) {
|
static void OpenZip(void) {
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
if (zmap) munmap(zmap, zsize);
|
if (zmap) munmap(zmap, zsize);
|
||||||
CHECK_NE(-1, (zfd = open(zpath, O_RDONLY)));
|
|
||||||
CHECK_NE(-1, fstat(zfd, &zst));
|
CHECK_NE(-1, fstat(zfd, &zst));
|
||||||
CHECK((zsize = zst.st_size));
|
CHECK((zsize = zst.st_size));
|
||||||
CHECK_NE(MAP_FAILED,
|
CHECK_NE(MAP_FAILED, (zmap = mmap((void *)0x0000300000000000, zsize, zprot,
|
||||||
(zmap = mmap((void *)0x0000300000000000, zsize, PROT_READ,
|
MAP_FIXED | MAP_SHARED, zfd, 0)));
|
||||||
MAP_FIXED | MAP_SHARED, zfd, 0)));
|
|
||||||
CHECK_NOTNULL((zcdir = GetZipCdir(zmap, zsize)));
|
CHECK_NOTNULL((zcdir = GetZipCdir(zmap, zsize)));
|
||||||
if (endswith(zpath, ".com.dbg") && (p = memmem(zmap, zsize, "MZqFpD", 6))) {
|
if (endswith(zpath, ".com.dbg") && (p = memmem(zmap, zsize, "MZqFpD", 6))) {
|
||||||
zsize -= p - zmap;
|
zsize -= p - zmap;
|
||||||
|
@ -2367,6 +2366,14 @@ static int LuaLoadAsset(lua_State *L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time,
|
||||||
|
uint16_t *out_date) {
|
||||||
|
struct tm tm;
|
||||||
|
CHECK_NOTNULL(localtime_r(&utcunixts, &tm));
|
||||||
|
*out_time = DOS_TIME(tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||||
|
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1);
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsUtf8(const void *data, size_t size) {
|
static bool IsUtf8(const void *data, size_t size) {
|
||||||
const unsigned char *p, *pe;
|
const unsigned char *p, *pe;
|
||||||
for (p = data, pe = p + size; p + 2 <= pe; ++p) {
|
for (p = data, pe = p + size; p + 2 <= pe; ++p) {
|
||||||
|
@ -2391,12 +2398,125 @@ static bool IsText(const void *data, size_t size) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time,
|
static int LuaStoreAsset(lua_State *L) {
|
||||||
uint16_t *out_date) {
|
int mode;
|
||||||
struct tm tm;
|
int64_t ft;
|
||||||
CHECK_NOTNULL(localtime_r(&utcunixts, &tm));
|
uint8_t era;
|
||||||
*out_time = DOS_TIME(tm.tm_hour, tm.tm_min, tm.tm_sec);
|
uint32_t crc;
|
||||||
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1);
|
long double now;
|
||||||
|
char *comp, *p, *q;
|
||||||
|
const char *path, *data, *use;
|
||||||
|
uint16_t gflags, iattrs, mtime, mdate, dosmode, method, disk;
|
||||||
|
size_t newlfileoffset, newcdiroffset, neweocdoffset, oldcdirrecords;
|
||||||
|
size_t pathlen, datalen, complen, uselen, oldcdirsize, moar, extralen;
|
||||||
|
if (IsOpenbsd() || IsNetbsd() || IsWindows()) {
|
||||||
|
luaL_error(L, "StoreAsset() not available on Windows/NetBSD/OpenBSD yet");
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
now = nowl();
|
||||||
|
path = LuaCheckPath(L, 1, &pathlen);
|
||||||
|
data = luaL_checklstring(L, 2, &datalen);
|
||||||
|
mode = luaL_optinteger(L, 3, 0644);
|
||||||
|
if (!(mode & S_IFMT)) mode |= S_IFREG;
|
||||||
|
if (pathlen > 1 && path[0] == '/') ++path, --pathlen;
|
||||||
|
crc = crc32_z(0, data, datalen);
|
||||||
|
if (datalen < 100) {
|
||||||
|
method = kZipCompressionNone;
|
||||||
|
comp = NULL;
|
||||||
|
use = data;
|
||||||
|
uselen = datalen;
|
||||||
|
} else {
|
||||||
|
comp = Deflate(data, datalen, &complen);
|
||||||
|
if (complen < datalen) {
|
||||||
|
method = kZipCompressionDeflate;
|
||||||
|
use = comp;
|
||||||
|
uselen = complen;
|
||||||
|
} else {
|
||||||
|
method = kZipCompressionNone;
|
||||||
|
use = data;
|
||||||
|
uselen = datalen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disk = gflags = iattrs = 0;
|
||||||
|
era = method ? kZipEra1993 : kZipEra1989;
|
||||||
|
ft = (now + MODERNITYSECONDS) * HECTONANOSECONDS;
|
||||||
|
dosmode = !(mode & 0200) ? kNtFileAttributeReadonly : 0;
|
||||||
|
GetDosLocalTime(now, &mtime, &mdate);
|
||||||
|
if (IsUtf8(path, pathlen)) gflags |= kZipGflagUtf8;
|
||||||
|
if (IsText(data, datalen)) iattrs |= kZipIattrText;
|
||||||
|
CHECK_NE(-1, flock(zfd, LOCK_EX));
|
||||||
|
if (ZipCdirChanged()) Reindex();
|
||||||
|
oldcdirrecords = GetZipCdirRecords(zcdir);
|
||||||
|
oldcdirsize = GetZipCdirSize(zcdir);
|
||||||
|
extralen = 36;
|
||||||
|
moar = kZipLfileHdrMinSize + pathlen + datalen + oldcdirsize +
|
||||||
|
kZipCfileHdrMinSize + pathlen + extralen + kZipCdirHdrMinSize;
|
||||||
|
CHECK_NE(-1, ftruncate(zfd, zsize + moar));
|
||||||
|
CHECK_NE(MAP_FAILED, (zmap = mmap((void *)0x0000300000000000, zsize + moar,
|
||||||
|
PROT_READ | PROT_WRITE,
|
||||||
|
MAP_FIXED | MAP_SHARED, zfd, 0)));
|
||||||
|
p = q = (char *)zmap;
|
||||||
|
p += zsize;
|
||||||
|
newlfileoffset = p - q;
|
||||||
|
p = WRITE32LE(p, kZipLfileHdrMagic);
|
||||||
|
*p++ = era;
|
||||||
|
*p++ = kZipOsDos;
|
||||||
|
p = WRITE16LE(p, gflags);
|
||||||
|
p = WRITE16LE(p, method);
|
||||||
|
p = WRITE16LE(p, mtime);
|
||||||
|
p = WRITE16LE(p, mdate);
|
||||||
|
p = WRITE32LE(p, crc);
|
||||||
|
p = WRITE32LE(p, uselen);
|
||||||
|
p = WRITE32LE(p, datalen);
|
||||||
|
p = WRITE16LE(p, pathlen);
|
||||||
|
p = WRITE16LE(p, 0);
|
||||||
|
p = mempcpy(p, path, pathlen);
|
||||||
|
p = mempcpy(p, data, datalen);
|
||||||
|
newcdiroffset = p - q;
|
||||||
|
p = mempcpy(p, zmap + GetZipCdirOffset(zcdir), oldcdirsize);
|
||||||
|
p = WRITE32LE(p, kZipCfileHdrMagic);
|
||||||
|
*p++ = kZipCosmopolitanVersion;
|
||||||
|
*p++ = kZipOsUnix;
|
||||||
|
*p++ = era;
|
||||||
|
*p++ = kZipOsDos;
|
||||||
|
p = WRITE16LE(p, gflags);
|
||||||
|
p = WRITE16LE(p, method);
|
||||||
|
p = WRITE16LE(p, mtime);
|
||||||
|
p = WRITE16LE(p, mdate);
|
||||||
|
p = WRITE32LE(p, crc);
|
||||||
|
p = WRITE32LE(p, uselen);
|
||||||
|
p = WRITE32LE(p, datalen);
|
||||||
|
p = WRITE16LE(p, pathlen);
|
||||||
|
p = WRITE16LE(p, extralen);
|
||||||
|
p = WRITE16LE(p, 0);
|
||||||
|
p = WRITE16LE(p, disk);
|
||||||
|
p = WRITE16LE(p, iattrs);
|
||||||
|
p = WRITE16LE(p, dosmode);
|
||||||
|
p = WRITE16LE(p, mode);
|
||||||
|
p = WRITE32LE(p, newlfileoffset);
|
||||||
|
p = mempcpy(p, path, pathlen);
|
||||||
|
p = WRITE16LE(p, kZipExtraNtfs);
|
||||||
|
p = WRITE16LE(p, 32);
|
||||||
|
p = WRITE32LE(p, 0);
|
||||||
|
p = WRITE16LE(p, 1);
|
||||||
|
p = WRITE16LE(p, 24);
|
||||||
|
p = WRITE64LE(p, ft);
|
||||||
|
p = WRITE64LE(p, ft);
|
||||||
|
p = WRITE64LE(p, ft);
|
||||||
|
neweocdoffset = p - q;
|
||||||
|
p = WRITE32LE(p, kZipCdirHdrMagic);
|
||||||
|
p = WRITE16LE(p, 0);
|
||||||
|
p = WRITE16LE(p, 0);
|
||||||
|
p = WRITE16LE(p, oldcdirrecords + 1);
|
||||||
|
p = WRITE16LE(p, oldcdirrecords + 1);
|
||||||
|
p = WRITE32LE(p, neweocdoffset - newcdiroffset);
|
||||||
|
p = WRITE32LE(p, newcdiroffset);
|
||||||
|
p = WRITE16LE(p, 0);
|
||||||
|
zcdir[0] = 'J';
|
||||||
|
zcdir[1] = 'T';
|
||||||
|
CHECK_NE(-1, flock(zfd, LOCK_UN));
|
||||||
|
free(comp);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int LuaGetDate(lua_State *L) {
|
static int LuaGetDate(lua_State *L) {
|
||||||
|
@ -3524,6 +3644,7 @@ static const luaL_Reg kLuaFuncs[] = {
|
||||||
{"SetHeader", LuaSetHeader}, //
|
{"SetHeader", LuaSetHeader}, //
|
||||||
{"SetLogLevel", LuaSetLogLevel}, //
|
{"SetLogLevel", LuaSetLogLevel}, //
|
||||||
{"SetStatus", LuaSetStatus}, //
|
{"SetStatus", LuaSetStatus}, //
|
||||||
|
{"StoreAsset", LuaStoreAsset}, //
|
||||||
{"Underlong", LuaUnderlong}, //
|
{"Underlong", LuaUnderlong}, //
|
||||||
{"VisualizeControlCodes", LuaVisualizeControlCodes}, //
|
{"VisualizeControlCodes", LuaVisualizeControlCodes}, //
|
||||||
{"Write", LuaWrite}, //
|
{"Write", LuaWrite}, //
|
||||||
|
@ -4517,7 +4638,6 @@ static void TuneSockets(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RestoreApe(void) {
|
static void RestoreApe(void) {
|
||||||
int fd;
|
|
||||||
char *p;
|
char *p;
|
||||||
size_t n;
|
size_t n;
|
||||||
struct Asset *a;
|
struct Asset *a;
|
||||||
|
@ -4526,14 +4646,17 @@ static void RestoreApe(void) {
|
||||||
if (IsOpenbsd()) return; /* TODO */
|
if (IsOpenbsd()) return; /* TODO */
|
||||||
if (IsNetbsd()) return; /* TODO */
|
if (IsNetbsd()) return; /* TODO */
|
||||||
if (endswith(zpath, ".com.dbg")) return;
|
if (endswith(zpath, ".com.dbg")) return;
|
||||||
fd = OpenExecutable();
|
close(zfd);
|
||||||
|
zfd = OpenExecutable();
|
||||||
if ((a = GetAssetZip("/.ape", 5)) && (p = LoadAsset(a, &n))) {
|
if ((a = GetAssetZip("/.ape", 5)) && (p = LoadAsset(a, &n))) {
|
||||||
write(fd, p, n);
|
write(zfd, p, n);
|
||||||
free(p);
|
free(p);
|
||||||
|
zprot = PROT_READ | PROT_WRITE;
|
||||||
|
CHECK_NE(MAP_FAILED, (zmap = mmap((void *)0x0000300000000000, zsize, zprot,
|
||||||
|
MAP_FIXED | MAP_SHARED, zfd, 0)));
|
||||||
} else {
|
} else {
|
||||||
WARNF("/.ape not found");
|
WARNF("/.ape not found");
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RedBean(int argc, char *argv[]) {
|
void RedBean(int argc, char *argv[]) {
|
||||||
|
@ -4544,7 +4667,9 @@ void RedBean(int argc, char *argv[]) {
|
||||||
(shared = mmap(NULL, ROUNDUP(sizeof(struct Shared), FRAMESIZE),
|
(shared = mmap(NULL, ROUNDUP(sizeof(struct Shared), FRAMESIZE),
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
|
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
|
||||||
-1, 0)));
|
-1, 0)));
|
||||||
|
zprot = PROT_READ;
|
||||||
zpath = (const char *)getauxval(AT_EXECFN);
|
zpath = (const char *)getauxval(AT_EXECFN);
|
||||||
|
CHECK_NE(-1, (zfd = open(zpath, O_RDONLY)));
|
||||||
OpenZip();
|
OpenZip();
|
||||||
IndexAssets();
|
IndexAssets();
|
||||||
RestoreApe();
|
RestoreApe();
|
||||||
|
|
Loading…
Add table
Reference in a new issue