@@ -299,6 +299,7 @@ static bool loggednetworkorigin;
299
299
static bool hasluaglobalhandler ;
300
300
301
301
static int zfd ;
302
+ static int zprot ;
302
303
static int frags ;
303
304
static int gmtoff ;
304
305
static int server ;
@@ -1365,12 +1366,10 @@ static bool ZipCdirChanged(void) {
1365
1366
static void OpenZip (void ) {
1366
1367
uint8_t * p ;
1367
1368
if (zmap ) munmap (zmap , zsize );
1368
- CHECK_NE (-1 , (zfd = open (zpath , O_RDONLY )));
1369
1369
CHECK_NE (-1 , fstat (zfd , & zst ));
1370
1370
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 )));
1374
1373
CHECK_NOTNULL ((zcdir = GetZipCdir (zmap , zsize )));
1375
1374
if (endswith (zpath , ".com.dbg" ) && (p = memmem (zmap , zsize , "MZqFpD" , 6 ))) {
1376
1375
zsize -= p - zmap ;
@@ -2367,6 +2366,14 @@ static int LuaLoadAsset(lua_State *L) {
2367
2366
return 0 ;
2368
2367
}
2369
2368
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
+
2370
2377
static bool IsUtf8 (const void * data , size_t size ) {
2371
2378
const unsigned char * p , * pe ;
2372
2379
for (p = data , pe = p + size ; p + 2 <= pe ; ++ p ) {
@@ -2391,12 +2398,125 @@ static bool IsText(const void *data, size_t size) {
2391
2398
return true;
2392
2399
}
2393
2400
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 ;
2400
2520
}
2401
2521
2402
2522
static int LuaGetDate (lua_State * L ) {
@@ -3524,6 +3644,7 @@ static const luaL_Reg kLuaFuncs[] = {
3524
3644
{"SetHeader" , LuaSetHeader }, //
3525
3645
{"SetLogLevel" , LuaSetLogLevel }, //
3526
3646
{"SetStatus" , LuaSetStatus }, //
3647
+ {"StoreAsset" , LuaStoreAsset }, //
3527
3648
{"Underlong" , LuaUnderlong }, //
3528
3649
{"VisualizeControlCodes" , LuaVisualizeControlCodes }, //
3529
3650
{"Write" , LuaWrite }, //
@@ -4517,7 +4638,6 @@ static void TuneSockets(void) {
4517
4638
}
4518
4639
4519
4640
static void RestoreApe (void ) {
4520
- int fd ;
4521
4641
char * p ;
4522
4642
size_t n ;
4523
4643
struct Asset * a ;
@@ -4526,14 +4646,17 @@ static void RestoreApe(void) {
4526
4646
if (IsOpenbsd ()) return ; /* TODO */
4527
4647
if (IsNetbsd ()) return ; /* TODO */
4528
4648
if (endswith (zpath , ".com.dbg" )) return ;
4529
- fd = OpenExecutable ();
4649
+ close (zfd );
4650
+ zfd = OpenExecutable ();
4530
4651
if ((a = GetAssetZip ("/.ape" , 5 )) && (p = LoadAsset (a , & n ))) {
4531
- write (fd , p , n );
4652
+ write (zfd , p , n );
4532
4653
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 )));
4533
4657
} else {
4534
4658
WARNF ("/.ape not found" );
4535
4659
}
4536
- close (fd );
4537
4660
}
4538
4661
4539
4662
void RedBean (int argc , char * argv []) {
@@ -4544,7 +4667,9 @@ void RedBean(int argc, char *argv[]) {
4544
4667
(shared = mmap (NULL , ROUNDUP (sizeof (struct Shared ), FRAMESIZE ),
4545
4668
PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANONYMOUS ,
4546
4669
-1 , 0 )));
4670
+ zprot = PROT_READ ;
4547
4671
zpath = (const char * )getauxval (AT_EXECFN );
4672
+ CHECK_NE (-1 , (zfd = open (zpath , O_RDONLY )));
4548
4673
OpenZip ();
4549
4674
IndexAssets ();
4550
4675
RestoreApe ();
0 commit comments