mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Add storing folders in redbean from CLI (#366)
This commit is contained in:
parent
38112aeb20
commit
cfc557f7c7
2 changed files with 105 additions and 68 deletions
|
@ -48,7 +48,7 @@ FLAGS
|
||||||
-R /X=/Y rewrites X to Y [repeatable]
|
-R /X=/Y rewrites X to Y [repeatable]
|
||||||
-K PATH tls private key path [repeatable]
|
-K PATH tls private key path [repeatable]
|
||||||
-C PATH tls certificate(s) path [repeatable]
|
-C PATH tls certificate(s) path [repeatable]
|
||||||
-A PATH add asset with path [repeatable]
|
-A PATH add assets with path (recursive) [repeatable]
|
||||||
-M INT tunes max message payload size [def. 65536]
|
-M INT tunes max message payload size [def. 65536]
|
||||||
-t INT timeout ms or keepalive sec if <0 [def. 60000]
|
-t INT timeout ms or keepalive sec if <0 [def. 60000]
|
||||||
-p PORT listen port [def. 8080; repeatable]
|
-p PORT listen port [def. 8080; repeatable]
|
||||||
|
|
|
@ -2137,58 +2137,6 @@ static wontreturn void PrintUsage(FILE *f, int rc) {
|
||||||
exit(rc);
|
exit(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetOpts(int argc, char *argv[]) {
|
|
||||||
int opt;
|
|
||||||
bool storeasset = false;
|
|
||||||
while ((opt = getopt(argc, argv,
|
|
||||||
"jkazhdugvVsmbfB"
|
|
||||||
"e:A:l:p:r:R:H:c:L:P:U:G:D:t:M:C:K:F:T:")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
CASE('v', ++__log_level);
|
|
||||||
CASE('s', --__log_level);
|
|
||||||
CASE('V', ++mbedtls_debug_threshold);
|
|
||||||
CASE('B', suiteb = true);
|
|
||||||
CASE('f', funtrace = true);
|
|
||||||
CASE('b', logbodies = true);
|
|
||||||
CASE('z', printport = true);
|
|
||||||
CASE('d', daemonize = true);
|
|
||||||
CASE('a', logrusage = true);
|
|
||||||
CASE('u', uniprocess = true);
|
|
||||||
CASE('g', loglatency = true);
|
|
||||||
CASE('m', logmessages = true);
|
|
||||||
CASE('k', sslfetchverify = false);
|
|
||||||
CASE('j', sslclientverify = true);
|
|
||||||
CASE('e', LuaRunCode(optarg));
|
|
||||||
CASE('A', storeasset = true;
|
|
||||||
LuaRunCode(gc(xasprintf("StoreAsset(%`'s, Slurp(%`'s))",
|
|
||||||
optarg, optarg))));
|
|
||||||
CASE('l', ProgramAddr(optarg));
|
|
||||||
CASE('H', ProgramHeader(optarg));
|
|
||||||
CASE('L', ProgramLogPath(optarg));
|
|
||||||
CASE('P', ProgramPidPath(optarg));
|
|
||||||
CASE('D', ProgramDirectory(optarg));
|
|
||||||
CASE('U', ProgramUid(atoi(optarg)));
|
|
||||||
CASE('G', ProgramGid(atoi(optarg)));
|
|
||||||
CASE('p', ProgramPort(ParseInt(optarg)));
|
|
||||||
CASE('R', ProgramRedirectArg(0, optarg));
|
|
||||||
CASE('c', ProgramCache(ParseInt(optarg)));
|
|
||||||
CASE('r', ProgramRedirectArg(307, optarg));
|
|
||||||
CASE('t', ProgramTimeout(ParseInt(optarg)));
|
|
||||||
CASE('h', PrintUsage(stdout, EXIT_SUCCESS));
|
|
||||||
CASE('T', ProgramSslTicketLifetime(ParseInt(optarg)));
|
|
||||||
CASE('M', ProgramMaxPayloadSize(ParseInt(optarg)));
|
|
||||||
#ifndef UNSECURE
|
|
||||||
CASE('C', ProgramFile(optarg, ProgramCertificate));
|
|
||||||
CASE('K', ProgramFile(optarg, ProgramPrivateKey));
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
PrintUsage(stderr, EX_USAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if storing asset(s) is requested, don't need to continue
|
|
||||||
if (storeasset) exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void AppendLogo(void) {
|
static void AppendLogo(void) {
|
||||||
size_t n;
|
size_t n;
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
|
@ -3258,29 +3206,27 @@ static void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time,
|
||||||
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1);
|
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int LuaStoreAsset(lua_State *L) {
|
static void StoreAsset(char *path, size_t pathlen, char *data, size_t datalen,
|
||||||
|
int mode) {
|
||||||
int64_t ft;
|
int64_t ft;
|
||||||
int i, mode;
|
int i;
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
char *comp, *p;
|
char *comp, *p;
|
||||||
long double now;
|
long double now;
|
||||||
struct Asset *a;
|
struct Asset *a;
|
||||||
struct iovec v[13];
|
struct iovec v[13];
|
||||||
uint8_t *cdir, era;
|
uint8_t *cdir, era;
|
||||||
const char *path, *data, *use;
|
const char *use;
|
||||||
uint16_t gflags, iattrs, mtime, mdate, dosmode, method, disk;
|
uint16_t gflags, iattrs, mtime, mdate, dosmode, method, disk;
|
||||||
size_t oldcdirsize, oldcdiroffset, records, cdiroffset, cdirsize, pathlen,
|
size_t oldcdirsize, oldcdiroffset, records, cdiroffset, cdirsize, complen,
|
||||||
datalen, complen, uselen;
|
uselen;
|
||||||
|
|
||||||
if (IsOpenbsd() || IsNetbsd() || IsWindows()) {
|
if (IsOpenbsd() || IsNetbsd() || IsWindows()) {
|
||||||
luaL_error(L, "StoreAsset() not available on Windows/NetBSD/OpenBSD yet");
|
DIEF("(cfg) StoreAsset() not available on Windows/NetBSD/OpenBSD yet");
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
path = LuaCheckPath(L, 1, &pathlen);
|
|
||||||
if (pathlen > 0xffff) {
|
INFOF("Storing asset %`'s", path);
|
||||||
luaL_argerror(L, 1, "path too long");
|
|
||||||
unreachable;
|
|
||||||
}
|
|
||||||
data = luaL_checklstring(L, 2, &datalen);
|
|
||||||
disk = gflags = iattrs = 0;
|
disk = gflags = iattrs = 0;
|
||||||
if (IsUtf8(path, pathlen)) gflags |= kZipGflagUtf8;
|
if (IsUtf8(path, pathlen)) gflags |= kZipGflagUtf8;
|
||||||
if (IsText(data, datalen)) iattrs |= kZipIattrText;
|
if (IsText(data, datalen)) iattrs |= kZipIattrText;
|
||||||
|
@ -3309,8 +3255,8 @@ static int LuaStoreAsset(lua_State *L) {
|
||||||
CHECK_NE(-1, fcntl(zfd, F_SETLKW, &(struct flock){F_WRLCK}));
|
CHECK_NE(-1, fcntl(zfd, F_SETLKW, &(struct flock){F_WRLCK}));
|
||||||
OpenZip(false);
|
OpenZip(false);
|
||||||
now = nowl();
|
now = nowl();
|
||||||
a = GetAsset(path, pathlen);
|
a = GetAssetZip(path, pathlen);
|
||||||
mode = luaL_optinteger(L, 3, a ? GetMode(a) : 0644);
|
if (!mode) mode = a ? GetMode(a) : 0644;
|
||||||
if (!(mode & S_IFMT)) mode |= S_IFREG;
|
if (!(mode & S_IFMT)) mode |= S_IFREG;
|
||||||
if (pathlen > 1 && path[0] == '/') ++path, --pathlen;
|
if (pathlen > 1 && path[0] == '/') ++path, --pathlen;
|
||||||
dosmode = !(mode & 0200) ? kNtFileAttributeReadonly : 0;
|
dosmode = !(mode & 0200) ? kNtFileAttributeReadonly : 0;
|
||||||
|
@ -3454,6 +3400,47 @@ static int LuaStoreAsset(lua_State *L) {
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
OpenZip(false);
|
OpenZip(false);
|
||||||
free(comp);
|
free(comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void StoreFile(char *path) {
|
||||||
|
char *p;
|
||||||
|
size_t n;
|
||||||
|
struct stat st;
|
||||||
|
if (lstat(path, &st) == -1) DIEF("Can't stat %`'s: %m", path);
|
||||||
|
if (!(p = xslurp(path, &n))) DIEF("Can't read %`'s: %m", path);
|
||||||
|
StoreAsset(path, strlen(path), p, n, st.st_mode & 0777);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void StorePath(const char *dirpath) {
|
||||||
|
DIR *d;
|
||||||
|
char *path;
|
||||||
|
struct dirent *e;
|
||||||
|
if (!isdirectory(dirpath)) return StoreFile(dirpath);
|
||||||
|
if (!(d = opendir(dirpath))) DIEF("Can't open %`'s", dirpath);
|
||||||
|
while ((e = readdir(d))) {
|
||||||
|
if (strcmp(e->d_name, ".") == 0) continue;
|
||||||
|
if (strcmp(e->d_name, "..") == 0) continue;
|
||||||
|
path = _gc(xjoinpaths(dirpath, e->d_name));
|
||||||
|
if (e->d_type == DT_DIR) {
|
||||||
|
StorePath(path);
|
||||||
|
} else {
|
||||||
|
StoreFile(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int LuaStoreAsset(lua_State *L) {
|
||||||
|
const char *path, *data;
|
||||||
|
size_t pathlen, datalen;
|
||||||
|
int mode;
|
||||||
|
path = LuaCheckPath(L, 1, &pathlen);
|
||||||
|
if (pathlen > 0xffff) {
|
||||||
|
return luaL_argerror(L, 1, "path too long");
|
||||||
|
}
|
||||||
|
data = luaL_checklstring(L, 2, &datalen);
|
||||||
|
mode = luaL_optinteger(L, 3, 0);
|
||||||
|
StoreAsset(path, pathlen, data, datalen, mode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7110,6 +7097,56 @@ static void MemDestroy(void) {
|
||||||
Free(&polls);
|
Free(&polls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void GetOpts(int argc, char *argv[]) {
|
||||||
|
int opt;
|
||||||
|
bool storeasset = false;
|
||||||
|
while ((opt = getopt(argc, argv,
|
||||||
|
"jkazhdugvVsmbfB"
|
||||||
|
"e:A:l:p:r:R:H:c:L:P:U:G:D:t:M:C:K:F:T:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
CASE('v', ++__log_level);
|
||||||
|
CASE('s', --__log_level);
|
||||||
|
CASE('V', ++mbedtls_debug_threshold);
|
||||||
|
CASE('B', suiteb = true);
|
||||||
|
CASE('f', funtrace = true);
|
||||||
|
CASE('b', logbodies = true);
|
||||||
|
CASE('z', printport = true);
|
||||||
|
CASE('d', daemonize = true);
|
||||||
|
CASE('a', logrusage = true);
|
||||||
|
CASE('u', uniprocess = true);
|
||||||
|
CASE('g', loglatency = true);
|
||||||
|
CASE('m', logmessages = true);
|
||||||
|
CASE('k', sslfetchverify = false);
|
||||||
|
CASE('j', sslclientverify = true);
|
||||||
|
CASE('e', LuaRunCode(optarg));
|
||||||
|
CASE('A', storeasset = true; StorePath(optarg));
|
||||||
|
CASE('l', ProgramAddr(optarg));
|
||||||
|
CASE('H', ProgramHeader(optarg));
|
||||||
|
CASE('L', ProgramLogPath(optarg));
|
||||||
|
CASE('P', ProgramPidPath(optarg));
|
||||||
|
CASE('D', ProgramDirectory(optarg));
|
||||||
|
CASE('U', ProgramUid(atoi(optarg)));
|
||||||
|
CASE('G', ProgramGid(atoi(optarg)));
|
||||||
|
CASE('p', ProgramPort(ParseInt(optarg)));
|
||||||
|
CASE('R', ProgramRedirectArg(0, optarg));
|
||||||
|
CASE('c', ProgramCache(ParseInt(optarg)));
|
||||||
|
CASE('r', ProgramRedirectArg(307, optarg));
|
||||||
|
CASE('t', ProgramTimeout(ParseInt(optarg)));
|
||||||
|
CASE('h', PrintUsage(stdout, EXIT_SUCCESS));
|
||||||
|
CASE('T', ProgramSslTicketLifetime(ParseInt(optarg)));
|
||||||
|
CASE('M', ProgramMaxPayloadSize(ParseInt(optarg)));
|
||||||
|
#ifndef UNSECURE
|
||||||
|
CASE('C', ProgramFile(optarg, ProgramCertificate));
|
||||||
|
CASE('K', ProgramFile(optarg, ProgramPrivateKey));
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
PrintUsage(stderr, EX_USAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if storing asset(s) is requested, don't need to continue
|
||||||
|
if (storeasset) exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
void RedBean(int argc, char *argv[]) {
|
void RedBean(int argc, char *argv[]) {
|
||||||
reader = read;
|
reader = read;
|
||||||
writer = WritevAll;
|
writer = WritevAll;
|
||||||
|
|
Loading…
Add table
Reference in a new issue