@php-wasm/node 1.1.3 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/asyncify/7_2_34/php_7_2.wasm +0 -0
- package/asyncify/7_3_33/php_7_3.wasm +0 -0
- package/asyncify/7_4_33/php_7_4.wasm +0 -0
- package/asyncify/8_0_30/php_8_0.wasm +0 -0
- package/asyncify/8_1_23/php_8_1.wasm +0 -0
- package/asyncify/8_2_10/php_8_2.wasm +0 -0
- package/asyncify/8_3_0/php_8_3.wasm +0 -0
- package/asyncify/8_4_0/php_8_4.wasm +0 -0
- package/asyncify/php_7_2.js +201 -138
- package/asyncify/php_7_3.js +200 -137
- package/asyncify/php_7_4.js +199 -136
- package/asyncify/php_8_0.js +203 -140
- package/asyncify/php_8_1.js +202 -139
- package/asyncify/php_8_2.js +203 -140
- package/asyncify/php_8_3.js +203 -140
- package/asyncify/php_8_4.js +202 -139
- package/fs_ext.node +0 -0
- package/index.cjs +9466 -3617
- package/index.js +9350 -3617
- package/jspi/7_2_34/php_7_2.wasm +0 -0
- package/jspi/7_3_33/php_7_3.wasm +0 -0
- package/jspi/7_4_33/php_7_4.wasm +0 -0
- package/jspi/8_0_30/php_8_0.wasm +0 -0
- package/jspi/8_1_23/php_8_1.wasm +0 -0
- package/jspi/8_2_10/php_8_2.wasm +0 -0
- package/jspi/8_3_0/php_8_3.wasm +0 -0
- package/jspi/8_4_0/php_8_4.wasm +0 -0
- package/jspi/php_7_2.js +2196 -1523
- package/jspi/php_7_3.js +2196 -1523
- package/jspi/php_7_4.js +9299 -7705
- package/jspi/php_8_0.js +2196 -1523
- package/jspi/php_8_1.js +2470 -1797
- package/jspi/php_8_2.js +2450 -1777
- package/jspi/php_8_3.js +2450 -1777
- package/jspi/php_8_4.js +2450 -1777
- package/lib/file-lock-manager-for-node.d.ts +149 -0
- package/lib/file-lock-manager.d.ts +96 -0
- package/lib/index.d.ts +2 -0
- package/lib/load-runtime.d.ts +31 -2
- package/package.json +10 -9
package/jspi/php_8_3.js
CHANGED
|
@@ -8,7 +8,7 @@ import path from 'path';
|
|
|
8
8
|
|
|
9
9
|
const dependencyFilename = path.join(__dirname, '8_3_0', 'php_8_3.wasm');
|
|
10
10
|
export { dependencyFilename };
|
|
11
|
-
export const dependenciesTotalSize =
|
|
11
|
+
export const dependenciesTotalSize = 17917660;
|
|
12
12
|
export function init(RuntimeName, PHPLoader) {
|
|
13
13
|
// The rest of the code comes from the built php.js file and esm-suffix.js
|
|
14
14
|
// include: shell.js
|
|
@@ -5227,637 +5227,887 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
5227
5227
|
|
|
5228
5228
|
var syscallGetVarargP = syscallGetVarargI;
|
|
5229
5229
|
|
|
5230
|
-
function ___syscall_fcntl64(fd, cmd, varargs) {
|
|
5231
|
-
SYSCALLS.varargs = varargs;
|
|
5232
|
-
try {
|
|
5233
|
-
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
5234
|
-
switch (cmd) {
|
|
5235
|
-
case 0: {
|
|
5236
|
-
var arg = syscallGetVarargI();
|
|
5237
|
-
if (arg < 0) {
|
|
5238
|
-
return -28;
|
|
5239
|
-
}
|
|
5240
|
-
while (FS.streams[arg]) {
|
|
5241
|
-
arg++;
|
|
5242
|
-
}
|
|
5243
|
-
var newStream;
|
|
5244
|
-
newStream = FS.dupStream(stream, arg);
|
|
5245
|
-
return newStream.fd;
|
|
5246
|
-
}
|
|
5247
|
-
|
|
5248
|
-
case 1:
|
|
5249
|
-
case 2:
|
|
5250
|
-
return 0;
|
|
5251
|
-
|
|
5252
|
-
// FD_CLOEXEC makes no sense for a single process.
|
|
5253
|
-
case 3:
|
|
5254
|
-
return stream.flags;
|
|
5255
|
-
|
|
5256
|
-
case 4: {
|
|
5257
|
-
var arg = syscallGetVarargI();
|
|
5258
|
-
stream.flags |= arg;
|
|
5259
|
-
return 0;
|
|
5260
|
-
}
|
|
5261
|
-
|
|
5262
|
-
case 12: {
|
|
5263
|
-
var arg = syscallGetVarargP();
|
|
5264
|
-
var offset = 0;
|
|
5265
|
-
// We're always unlocked.
|
|
5266
|
-
HEAP16[(arg + offset) >> 1] = 2;
|
|
5267
|
-
return 0;
|
|
5268
|
-
}
|
|
5269
|
-
|
|
5270
|
-
case 13:
|
|
5271
|
-
case 14:
|
|
5272
|
-
// Pretend that the locking is successful. These are process-level locks,
|
|
5273
|
-
// and Emscripten programs are a single process. If we supported linking a
|
|
5274
|
-
// filesystem between programs, we'd need to do more here.
|
|
5275
|
-
// See https://github.com/emscripten-core/emscripten/issues/23697
|
|
5276
|
-
return 0;
|
|
5277
|
-
}
|
|
5278
|
-
return -28;
|
|
5279
|
-
} catch (e) {
|
|
5280
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5281
|
-
return -e.errno;
|
|
5282
|
-
}
|
|
5283
|
-
}
|
|
5284
|
-
|
|
5285
|
-
function ___syscall_fdatasync(fd) {
|
|
5286
|
-
try {
|
|
5287
|
-
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
5288
|
-
return 0;
|
|
5289
|
-
} catch (e) {
|
|
5290
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5291
|
-
return -e.errno;
|
|
5292
|
-
}
|
|
5293
|
-
}
|
|
5294
|
-
|
|
5295
|
-
function ___syscall_fstat64(fd, buf) {
|
|
5296
|
-
try {
|
|
5297
|
-
return SYSCALLS.writeStat(buf, FS.fstat(fd));
|
|
5298
|
-
} catch (e) {
|
|
5299
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5300
|
-
return -e.errno;
|
|
5301
|
-
}
|
|
5302
|
-
}
|
|
5303
|
-
|
|
5304
|
-
function ___syscall_ftruncate64(fd, length) {
|
|
5305
|
-
length = bigintToI53Checked(length);
|
|
5306
|
-
try {
|
|
5307
|
-
if (isNaN(length)) return 61;
|
|
5308
|
-
FS.ftruncate(fd, length);
|
|
5309
|
-
return 0;
|
|
5310
|
-
} catch (e) {
|
|
5311
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5312
|
-
return -e.errno;
|
|
5313
|
-
}
|
|
5314
|
-
}
|
|
5315
|
-
|
|
5316
5230
|
var stringToUTF8 = (str, outPtr, maxBytesToWrite) =>
|
|
5317
5231
|
stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
|
|
5318
5232
|
|
|
5319
5233
|
Module['stringToUTF8'] = stringToUTF8;
|
|
5320
5234
|
|
|
5321
|
-
|
|
5322
|
-
try {
|
|
5323
|
-
if (size === 0) return -28;
|
|
5324
|
-
var cwd = FS.cwd();
|
|
5325
|
-
var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
|
|
5326
|
-
if (size < cwdLengthInBytes) return -68;
|
|
5327
|
-
stringToUTF8(cwd, buf, size);
|
|
5328
|
-
return cwdLengthInBytes;
|
|
5329
|
-
} catch (e) {
|
|
5330
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5331
|
-
return -e.errno;
|
|
5332
|
-
}
|
|
5333
|
-
}
|
|
5334
|
-
|
|
5335
|
-
function ___syscall_getdents64(fd, dirp, count) {
|
|
5336
|
-
try {
|
|
5337
|
-
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
5338
|
-
stream.getdents ||= FS.readdir(stream.path);
|
|
5339
|
-
var struct_size = 280;
|
|
5340
|
-
var pos = 0;
|
|
5341
|
-
var off = FS.llseek(stream, 0, 1);
|
|
5342
|
-
var startIdx = Math.floor(off / struct_size);
|
|
5343
|
-
var endIdx = Math.min(
|
|
5344
|
-
stream.getdents.length,
|
|
5345
|
-
startIdx + Math.floor(count / struct_size)
|
|
5346
|
-
);
|
|
5347
|
-
for (var idx = startIdx; idx < endIdx; idx++) {
|
|
5348
|
-
var id;
|
|
5349
|
-
var type;
|
|
5350
|
-
var name = stream.getdents[idx];
|
|
5351
|
-
if (name === '.') {
|
|
5352
|
-
id = stream.node.id;
|
|
5353
|
-
type = 4;
|
|
5354
|
-
} else if (name === '..') {
|
|
5355
|
-
var lookup = FS.lookupPath(stream.path, {
|
|
5356
|
-
parent: true,
|
|
5357
|
-
});
|
|
5358
|
-
id = lookup.node.id;
|
|
5359
|
-
type = 4;
|
|
5360
|
-
} else {
|
|
5361
|
-
var child;
|
|
5362
|
-
try {
|
|
5363
|
-
child = FS.lookupNode(stream.node, name);
|
|
5364
|
-
} catch (e) {
|
|
5365
|
-
// If the entry is not a directory, file, or symlink, nodefs
|
|
5366
|
-
// lookupNode will raise EINVAL. Skip these and continue.
|
|
5367
|
-
if (e?.errno === 28) {
|
|
5368
|
-
continue;
|
|
5369
|
-
}
|
|
5370
|
-
throw e;
|
|
5371
|
-
}
|
|
5372
|
-
id = child.id;
|
|
5373
|
-
type = FS.isChrdev(child.mode)
|
|
5374
|
-
? 2 // DT_CHR, character device.
|
|
5375
|
-
: FS.isDir(child.mode)
|
|
5376
|
-
? 4 // DT_DIR, directory.
|
|
5377
|
-
: FS.isLink(child.mode)
|
|
5378
|
-
? 10 // DT_LNK, symbolic link.
|
|
5379
|
-
: 8;
|
|
5380
|
-
}
|
|
5381
|
-
HEAP64[(dirp + pos) >> 3] = BigInt(id);
|
|
5382
|
-
HEAP64[(dirp + pos + 8) >> 3] = BigInt((idx + 1) * struct_size);
|
|
5383
|
-
HEAP16[(dirp + pos + 16) >> 1] = 280;
|
|
5384
|
-
HEAP8[dirp + pos + 18] = type;
|
|
5385
|
-
stringToUTF8(name, dirp + pos + 19, 256);
|
|
5386
|
-
pos += struct_size;
|
|
5387
|
-
}
|
|
5388
|
-
FS.llseek(stream, idx * struct_size, 0);
|
|
5389
|
-
return pos;
|
|
5390
|
-
} catch (e) {
|
|
5391
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5392
|
-
return -e.errno;
|
|
5393
|
-
}
|
|
5394
|
-
}
|
|
5395
|
-
|
|
5396
|
-
function ___syscall_getpeername(fd, addr, addrlen, d1, d2, d3) {
|
|
5397
|
-
try {
|
|
5398
|
-
var sock = getSocketFromFD(fd);
|
|
5399
|
-
if (!sock.daddr) {
|
|
5400
|
-
return -53;
|
|
5401
|
-
}
|
|
5402
|
-
var errno = writeSockaddr(
|
|
5403
|
-
addr,
|
|
5404
|
-
sock.family,
|
|
5405
|
-
DNS.lookup_name(sock.daddr),
|
|
5406
|
-
sock.dport,
|
|
5407
|
-
addrlen
|
|
5408
|
-
);
|
|
5409
|
-
return 0;
|
|
5410
|
-
} catch (e) {
|
|
5411
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5412
|
-
return -e.errno;
|
|
5413
|
-
}
|
|
5414
|
-
}
|
|
5415
|
-
|
|
5416
|
-
function ___syscall_getsockname(fd, addr, addrlen, d1, d2, d3) {
|
|
5417
|
-
try {
|
|
5418
|
-
var sock = getSocketFromFD(fd);
|
|
5419
|
-
// TODO: sock.saddr should never be undefined, see TODO in websocket_sock_ops.getname
|
|
5420
|
-
var errno = writeSockaddr(
|
|
5421
|
-
addr,
|
|
5422
|
-
sock.family,
|
|
5423
|
-
DNS.lookup_name(sock.saddr || '0.0.0.0'),
|
|
5424
|
-
sock.sport,
|
|
5425
|
-
addrlen
|
|
5426
|
-
);
|
|
5427
|
-
return 0;
|
|
5428
|
-
} catch (e) {
|
|
5429
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5430
|
-
return -e.errno;
|
|
5431
|
-
}
|
|
5432
|
-
}
|
|
5235
|
+
var stackAlloc = (sz) => __emscripten_stack_alloc(sz);
|
|
5433
5236
|
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
if (optname === 4) {
|
|
5441
|
-
HEAP32[optval >> 2] = sock.error;
|
|
5442
|
-
HEAP32[optlen >> 2] = 4;
|
|
5443
|
-
sock.error = null;
|
|
5444
|
-
// Clear the error (The SO_ERROR option obtains and then clears this field).
|
|
5445
|
-
return 0;
|
|
5446
|
-
}
|
|
5447
|
-
}
|
|
5448
|
-
return -50;
|
|
5449
|
-
} catch (e) {
|
|
5450
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5451
|
-
return -e.errno;
|
|
5452
|
-
}
|
|
5453
|
-
}
|
|
5237
|
+
/** @suppress {duplicate } */ var stringToUTF8OnStack = (str) => {
|
|
5238
|
+
var size = lengthBytesUTF8(str) + 1;
|
|
5239
|
+
var ret = stackAlloc(size);
|
|
5240
|
+
stringToUTF8(str, ret, size);
|
|
5241
|
+
return ret;
|
|
5242
|
+
};
|
|
5454
5243
|
|
|
5455
|
-
|
|
5456
|
-
SYSCALLS.varargs = varargs;
|
|
5457
|
-
try {
|
|
5458
|
-
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
5459
|
-
switch (op) {
|
|
5460
|
-
case 21509: {
|
|
5461
|
-
if (!stream.tty) return -59;
|
|
5462
|
-
return 0;
|
|
5463
|
-
}
|
|
5244
|
+
var allocateUTF8OnStack = stringToUTF8OnStack;
|
|
5464
5245
|
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
HEAP8[argp + i + 17] = termios.c_cc[i] || 0;
|
|
5476
|
-
}
|
|
5477
|
-
return 0;
|
|
5478
|
-
}
|
|
5479
|
-
return 0;
|
|
5480
|
-
}
|
|
5246
|
+
var PHPWASM = {
|
|
5247
|
+
init: function () {
|
|
5248
|
+
Module['ENV'] = Module['ENV'] || {};
|
|
5249
|
+
// Ensure a platform-level bin directory for a fallback `php` binary.
|
|
5250
|
+
Module['ENV']['PATH'] = [
|
|
5251
|
+
Module['ENV']['PATH'],
|
|
5252
|
+
'/internal/shared/bin',
|
|
5253
|
+
]
|
|
5254
|
+
.filter(Boolean)
|
|
5255
|
+
.join(':');
|
|
5481
5256
|
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5257
|
+
// The /internal directory is required by the C module. It's where the
|
|
5258
|
+
// stdout, stderr, and headers information are written for the JavaScript
|
|
5259
|
+
// code to read later on.
|
|
5260
|
+
FS.mkdir('/internal');
|
|
5261
|
+
// The files from the shared directory are shared between all the
|
|
5262
|
+
// PHP processes managed by PHPProcessManager.
|
|
5263
|
+
FS.mkdir('/internal/shared');
|
|
5264
|
+
// The files from the preload directory are preloaded using the
|
|
5265
|
+
// auto_prepend_file php.ini directive.
|
|
5266
|
+
FS.mkdir('/internal/shared/preload');
|
|
5267
|
+
// Platform-level bin directory for a fallback `php` binary. Without it,
|
|
5268
|
+
// PHP may not populate the PHP_BINARY constant.
|
|
5269
|
+
FS.mkdir('/internal/shared/bin');
|
|
5270
|
+
const originalOnRuntimeInitialized = Module['onRuntimeInitialized'];
|
|
5271
|
+
Module['onRuntimeInitialized'] = () => {
|
|
5272
|
+
// Dummy PHP binary for PHP to populate the PHP_BINARY constant.
|
|
5273
|
+
FS.writeFile(
|
|
5274
|
+
'/internal/shared/bin/php',
|
|
5275
|
+
new TextEncoder().encode('#!/bin/sh\nphp "$@"')
|
|
5276
|
+
);
|
|
5277
|
+
// It must be executable to be used by PHP.
|
|
5278
|
+
FS.chmod('/internal/shared/bin/php', 0o755);
|
|
5279
|
+
originalOnRuntimeInitialized();
|
|
5280
|
+
};
|
|
5281
|
+
// Create stdout and stderr devices. We can't just use Emscripten's
|
|
5282
|
+
// default stdout and stderr devices because they stop processing data
|
|
5283
|
+
// on the first null byte. However, when dealing with binary data,
|
|
5284
|
+
// null bytes are valid and common.
|
|
5285
|
+
FS.registerDevice(FS.makedev(64, 0), {
|
|
5286
|
+
open: () => {},
|
|
5287
|
+
close: () => {},
|
|
5288
|
+
read: () => 0,
|
|
5289
|
+
write: (stream, buffer, offset, length, pos) => {
|
|
5290
|
+
const chunk = buffer.subarray(offset, offset + length);
|
|
5291
|
+
PHPWASM.onStdout(chunk);
|
|
5292
|
+
return length;
|
|
5293
|
+
},
|
|
5294
|
+
});
|
|
5295
|
+
FS.mkdev('/internal/stdout', FS.makedev(64, 0));
|
|
5296
|
+
FS.registerDevice(FS.makedev(63, 0), {
|
|
5297
|
+
open: () => {},
|
|
5298
|
+
close: () => {},
|
|
5299
|
+
read: () => 0,
|
|
5300
|
+
write: (stream, buffer, offset, length, pos) => {
|
|
5301
|
+
const chunk = buffer.subarray(offset, offset + length);
|
|
5302
|
+
PHPWASM.onStderr(chunk);
|
|
5303
|
+
return length;
|
|
5304
|
+
},
|
|
5305
|
+
});
|
|
5306
|
+
FS.mkdev('/internal/stderr', FS.makedev(63, 0));
|
|
5307
|
+
FS.registerDevice(FS.makedev(62, 0), {
|
|
5308
|
+
open: () => {},
|
|
5309
|
+
close: () => {},
|
|
5310
|
+
read: () => 0,
|
|
5311
|
+
write: (stream, buffer, offset, length, pos) => {
|
|
5312
|
+
const chunk = buffer.subarray(offset, offset + length);
|
|
5313
|
+
PHPWASM.onHeaders(chunk);
|
|
5314
|
+
return length;
|
|
5315
|
+
},
|
|
5316
|
+
});
|
|
5317
|
+
FS.mkdev('/internal/headers', FS.makedev(62, 0));
|
|
5318
|
+
// Handle events.
|
|
5319
|
+
PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE
|
|
5320
|
+
? require('events').EventEmitter
|
|
5321
|
+
: class EventEmitter {
|
|
5322
|
+
constructor() {
|
|
5323
|
+
this.listeners = {};
|
|
5502
5324
|
}
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5325
|
+
emit(eventName, data) {
|
|
5326
|
+
if (this.listeners[eventName]) {
|
|
5327
|
+
this.listeners[eventName].forEach(
|
|
5328
|
+
(callback) => {
|
|
5329
|
+
callback(data);
|
|
5330
|
+
}
|
|
5331
|
+
);
|
|
5332
|
+
}
|
|
5333
|
+
}
|
|
5334
|
+
once(eventName, callback) {
|
|
5335
|
+
const self = this;
|
|
5336
|
+
function removedCallback() {
|
|
5337
|
+
callback(...arguments);
|
|
5338
|
+
self.removeListener(eventName, removedCallback);
|
|
5339
|
+
}
|
|
5340
|
+
this.on(eventName, removedCallback);
|
|
5341
|
+
}
|
|
5342
|
+
removeAllListeners(eventName) {
|
|
5343
|
+
if (eventName) {
|
|
5344
|
+
delete this.listeners[eventName];
|
|
5345
|
+
} else {
|
|
5346
|
+
this.listeners = {};
|
|
5347
|
+
}
|
|
5348
|
+
}
|
|
5349
|
+
removeListener(eventName, callback) {
|
|
5350
|
+
if (this.listeners[eventName]) {
|
|
5351
|
+
const idx =
|
|
5352
|
+
this.listeners[eventName].indexOf(callback);
|
|
5353
|
+
if (idx !== -1) {
|
|
5354
|
+
this.listeners[eventName].splice(idx, 1);
|
|
5355
|
+
}
|
|
5356
|
+
}
|
|
5357
|
+
}
|
|
5358
|
+
};
|
|
5359
|
+
// Clean up the fd -> childProcess mapping when the fd is closed:
|
|
5360
|
+
const originalClose = FS.close;
|
|
5361
|
+
FS.close = function (stream) {
|
|
5362
|
+
originalClose(stream);
|
|
5363
|
+
delete PHPWASM.child_proc_by_fd[stream.fd];
|
|
5364
|
+
};
|
|
5365
|
+
PHPWASM.child_proc_by_fd = {};
|
|
5366
|
+
PHPWASM.child_proc_by_pid = {};
|
|
5367
|
+
PHPWASM.input_devices = {};
|
|
5368
|
+
const originalWrite = TTY.stream_ops.write;
|
|
5369
|
+
TTY.stream_ops.write = function (stream, ...rest) {
|
|
5370
|
+
const retval = originalWrite(stream, ...rest);
|
|
5371
|
+
// Implicit flush since PHP's fflush() doesn't seem to trigger the fsync event
|
|
5372
|
+
// @TODO: Fix this at the wasm level
|
|
5373
|
+
stream.tty.ops.fsync(stream.tty);
|
|
5374
|
+
return retval;
|
|
5375
|
+
};
|
|
5376
|
+
const originalPutChar = TTY.stream_ops.put_char;
|
|
5377
|
+
TTY.stream_ops.put_char = function (tty, val) {
|
|
5378
|
+
/**
|
|
5379
|
+
* Buffer newlines that Emscripten normally ignores.
|
|
5380
|
+
*
|
|
5381
|
+
* Emscripten doesn't do it by default because its default
|
|
5382
|
+
* print function is console.log that implicitly adds a newline. We are overwriting
|
|
5383
|
+
* it with an environment-specific function that outputs exaclty what it was given,
|
|
5384
|
+
* e.g. in Node.js it's process.stdout.write(). Therefore, we need to mak sure
|
|
5385
|
+
* all the newlines make it to the output buffer.
|
|
5386
|
+
*/ if (val === 10) tty.output.push(val);
|
|
5387
|
+
return originalPutChar(tty, val);
|
|
5388
|
+
};
|
|
5389
|
+
},
|
|
5390
|
+
onHeaders: function (chunk) {
|
|
5391
|
+
if (Module['onHeaders']) {
|
|
5392
|
+
Module['onHeaders'](chunk);
|
|
5393
|
+
return;
|
|
5394
|
+
}
|
|
5395
|
+
console.log('headers', {
|
|
5396
|
+
chunk,
|
|
5397
|
+
});
|
|
5398
|
+
},
|
|
5399
|
+
onStdout: function (chunk) {
|
|
5400
|
+
if (Module['onStdout']) {
|
|
5401
|
+
Module['onStdout'](chunk);
|
|
5402
|
+
return;
|
|
5403
|
+
}
|
|
5404
|
+
if (ENVIRONMENT_IS_NODE) {
|
|
5405
|
+
process.stdout.write(chunk);
|
|
5406
|
+
} else {
|
|
5407
|
+
console.log('stdout', {
|
|
5408
|
+
chunk,
|
|
5409
|
+
});
|
|
5410
|
+
}
|
|
5411
|
+
},
|
|
5412
|
+
onStderr: function (chunk) {
|
|
5413
|
+
if (Module['onStderr']) {
|
|
5414
|
+
Module['onStderr'](chunk);
|
|
5415
|
+
return;
|
|
5416
|
+
}
|
|
5417
|
+
if (ENVIRONMENT_IS_NODE) {
|
|
5418
|
+
process.stderr.write(chunk);
|
|
5419
|
+
} else {
|
|
5420
|
+
console.warn('stderr', {
|
|
5421
|
+
chunk,
|
|
5422
|
+
});
|
|
5423
|
+
}
|
|
5424
|
+
},
|
|
5425
|
+
getAllWebSockets: function (sock) {
|
|
5426
|
+
const webSockets = new Set();
|
|
5427
|
+
if (sock.server) {
|
|
5428
|
+
sock.server.clients.forEach((ws) => {
|
|
5429
|
+
webSockets.add(ws);
|
|
5430
|
+
});
|
|
5431
|
+
}
|
|
5432
|
+
for (const peer of PHPWASM.getAllPeers(sock)) {
|
|
5433
|
+
webSockets.add(peer.socket);
|
|
5434
|
+
}
|
|
5435
|
+
return Array.from(webSockets);
|
|
5436
|
+
},
|
|
5437
|
+
getAllPeers: function (sock) {
|
|
5438
|
+
const peers = new Set();
|
|
5439
|
+
if (sock.server) {
|
|
5440
|
+
sock.pending
|
|
5441
|
+
.filter((pending) => pending.peers)
|
|
5442
|
+
.forEach((pending) => {
|
|
5443
|
+
for (const peer of Object.values(pending.peers)) {
|
|
5444
|
+
peers.add(peer);
|
|
5445
|
+
}
|
|
5446
|
+
});
|
|
5447
|
+
}
|
|
5448
|
+
if (sock.peers) {
|
|
5449
|
+
for (const peer of Object.values(sock.peers)) {
|
|
5450
|
+
peers.add(peer);
|
|
5529
5451
|
}
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5452
|
+
}
|
|
5453
|
+
return Array.from(peers);
|
|
5454
|
+
},
|
|
5455
|
+
awaitData: function (ws) {
|
|
5456
|
+
return PHPWASM.awaitEvent(ws, 'message');
|
|
5457
|
+
},
|
|
5458
|
+
awaitConnection: function (ws) {
|
|
5459
|
+
if (ws.OPEN === ws.readyState) {
|
|
5460
|
+
return [Promise.resolve(), PHPWASM.noop];
|
|
5461
|
+
}
|
|
5462
|
+
return PHPWASM.awaitEvent(ws, 'open');
|
|
5463
|
+
},
|
|
5464
|
+
awaitClose: function (ws) {
|
|
5465
|
+
if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) {
|
|
5466
|
+
return [Promise.resolve(), PHPWASM.noop];
|
|
5467
|
+
}
|
|
5468
|
+
return PHPWASM.awaitEvent(ws, 'close');
|
|
5469
|
+
},
|
|
5470
|
+
awaitError: function (ws) {
|
|
5471
|
+
if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) {
|
|
5472
|
+
return [Promise.resolve(), PHPWASM.noop];
|
|
5473
|
+
}
|
|
5474
|
+
return PHPWASM.awaitEvent(ws, 'error');
|
|
5475
|
+
},
|
|
5476
|
+
awaitEvent: function (ws, event) {
|
|
5477
|
+
let resolve;
|
|
5478
|
+
const listener = () => {
|
|
5479
|
+
resolve();
|
|
5480
|
+
};
|
|
5481
|
+
const promise = new Promise(function (_resolve) {
|
|
5482
|
+
resolve = _resolve;
|
|
5483
|
+
ws.once(event, listener);
|
|
5484
|
+
});
|
|
5485
|
+
const cancel = () => {
|
|
5486
|
+
ws.removeListener(event, listener);
|
|
5487
|
+
// Rejecting the promises bubbles up and kills the entire
|
|
5488
|
+
// node process. Let's resolve them on the next tick instead
|
|
5489
|
+
// to give the caller some space to unbind any handlers.
|
|
5490
|
+
setTimeout(resolve);
|
|
5491
|
+
};
|
|
5492
|
+
return [promise, cancel];
|
|
5493
|
+
},
|
|
5494
|
+
noop: function () {},
|
|
5495
|
+
spawnProcess: function (command, args, options) {
|
|
5496
|
+
if (Module['spawnProcess']) {
|
|
5497
|
+
const spawnedPromise = Module['spawnProcess'](
|
|
5498
|
+
command,
|
|
5499
|
+
args,
|
|
5500
|
+
options
|
|
5501
|
+
);
|
|
5502
|
+
return Promise.resolve(spawnedPromise).then(function (spawned) {
|
|
5503
|
+
if (!spawned || !spawned.on) {
|
|
5504
|
+
throw new Error(
|
|
5505
|
+
'spawnProcess() must return an EventEmitter but returned a different type.'
|
|
5538
5506
|
);
|
|
5539
|
-
var argp = syscallGetVarargP();
|
|
5540
|
-
HEAP16[argp >> 1] = winsize[0];
|
|
5541
|
-
HEAP16[(argp + 2) >> 1] = winsize[1];
|
|
5542
5507
|
}
|
|
5543
|
-
return
|
|
5544
|
-
}
|
|
5545
|
-
|
|
5546
|
-
case 21524: {
|
|
5547
|
-
// TODO: technically, this ioctl call should change the window size.
|
|
5548
|
-
// but, since emscripten doesn't have any concept of a terminal window
|
|
5549
|
-
// yet, we'll just silently throw it away as we do TIOCGWINSZ
|
|
5550
|
-
if (!stream.tty) return -59;
|
|
5551
|
-
return 0;
|
|
5552
|
-
}
|
|
5553
|
-
|
|
5554
|
-
case 21515: {
|
|
5555
|
-
if (!stream.tty) return -59;
|
|
5556
|
-
return 0;
|
|
5557
|
-
}
|
|
5558
|
-
|
|
5559
|
-
default:
|
|
5560
|
-
return -28;
|
|
5508
|
+
return spawned;
|
|
5509
|
+
});
|
|
5561
5510
|
}
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5511
|
+
if (ENVIRONMENT_IS_NODE) {
|
|
5512
|
+
return require('child_process').spawn(command, args, {
|
|
5513
|
+
...options,
|
|
5514
|
+
shell: true,
|
|
5515
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
5516
|
+
timeout: 100,
|
|
5517
|
+
});
|
|
5518
|
+
}
|
|
5519
|
+
const e = new Error(
|
|
5520
|
+
'popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() ' +
|
|
5521
|
+
'and provide a callback to handle spawning processes, or disable a popen(), proc_open() ' +
|
|
5522
|
+
'and similar functions via php.ini.'
|
|
5523
|
+
);
|
|
5524
|
+
e.code = 'SPAWN_UNSUPPORTED';
|
|
5525
|
+
throw e;
|
|
5526
|
+
},
|
|
5527
|
+
shutdownSocket: function (socketd, how) {
|
|
5528
|
+
// This implementation only supports websockets at the moment
|
|
5529
|
+
const sock = getSocketFromFD(socketd);
|
|
5530
|
+
const peer = Object.values(sock.peers)[0];
|
|
5531
|
+
if (!peer) {
|
|
5532
|
+
return -1;
|
|
5533
|
+
}
|
|
5534
|
+
try {
|
|
5535
|
+
peer.socket.close();
|
|
5536
|
+
SOCKFS.websocket_sock_ops.removePeer(sock, peer);
|
|
5537
|
+
return 0;
|
|
5538
|
+
} catch (e) {
|
|
5539
|
+
console.log('Socket shutdown error', e);
|
|
5540
|
+
return -1;
|
|
5541
|
+
}
|
|
5542
|
+
},
|
|
5543
|
+
};
|
|
5567
5544
|
|
|
5568
|
-
function
|
|
5569
|
-
|
|
5570
|
-
var sock = getSocketFromFD(fd);
|
|
5571
|
-
sock.sock_ops.listen(sock, backlog);
|
|
5572
|
-
return 0;
|
|
5573
|
-
} catch (e) {
|
|
5574
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5575
|
-
return -e.errno;
|
|
5576
|
-
}
|
|
5545
|
+
function _js_getpid() {
|
|
5546
|
+
return PHPLoader.processId ?? 42;
|
|
5577
5547
|
}
|
|
5578
|
-
|
|
5579
|
-
function
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
return SYSCALLS.writeStat(buf, FS.lstat(path));
|
|
5583
|
-
} catch (e) {
|
|
5584
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5585
|
-
return -e.errno;
|
|
5548
|
+
|
|
5549
|
+
function _js_wasm_trace(format, ...args) {
|
|
5550
|
+
if (PHPLoader.trace instanceof Function) {
|
|
5551
|
+
PHPLoader.trace(_js_getpid(), format, ...args);
|
|
5586
5552
|
}
|
|
5587
5553
|
}
|
|
5588
5554
|
|
|
5589
|
-
function
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5555
|
+
function _fd_close(fd) {
|
|
5556
|
+
_js_wasm_trace('fd_close(%d)', fd);
|
|
5557
|
+
const [vfsPath, pathResolutionErrno] = locking.get_vfs_path_from_fd(fd);
|
|
5558
|
+
if (pathResolutionErrno !== 0) {
|
|
5559
|
+
_js_wasm_trace(
|
|
5560
|
+
'fd_close(%d) get_vfs_path_from_fd error %d',
|
|
5561
|
+
fd,
|
|
5562
|
+
pathResolutionErrno
|
|
5563
|
+
);
|
|
5564
|
+
return -ERRNO_CODES.EBADF;
|
|
5565
|
+
}
|
|
5566
|
+
const result = _builtin_fd_close(fd);
|
|
5567
|
+
if (result === 0 && locking.maybeLockedFds.has(fd)) {
|
|
5568
|
+
const nativeFilePath =
|
|
5569
|
+
locking.get_native_path_from_vfs_path(vfsPath);
|
|
5570
|
+
return PHPLoader.fileLockManager
|
|
5571
|
+
.releaseLocksForProcessFd(
|
|
5572
|
+
PHPLoader.processId,
|
|
5573
|
+
fd,
|
|
5574
|
+
nativeFilePath
|
|
5575
|
+
)
|
|
5576
|
+
.then(() => {
|
|
5577
|
+
_js_wasm_trace('fd_close(%d) release locks success', fd);
|
|
5578
|
+
})
|
|
5579
|
+
.catch((e) => {
|
|
5580
|
+
_js_wasm_trace("fd_close(%d) error '%s'", fd, e);
|
|
5581
|
+
})
|
|
5582
|
+
.then(() => {
|
|
5583
|
+
_js_wasm_trace('fd_close(%d) result %d', fd, result);
|
|
5584
|
+
return result;
|
|
5585
|
+
})
|
|
5586
|
+
.finally(() => {
|
|
5587
|
+
locking.maybeLockedFds.delete(fd);
|
|
5588
|
+
});
|
|
5589
|
+
} else {
|
|
5590
|
+
_js_wasm_trace('fd_close(%d) result %d', fd, result);
|
|
5591
|
+
return result;
|
|
5598
5592
|
}
|
|
5599
5593
|
}
|
|
5600
5594
|
|
|
5601
|
-
function
|
|
5595
|
+
function _builtin_fd_close(fd) {
|
|
5602
5596
|
try {
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
flags = flags & ~6400;
|
|
5607
|
-
path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
|
|
5608
|
-
return SYSCALLS.writeStat(
|
|
5609
|
-
buf,
|
|
5610
|
-
nofollow ? FS.lstat(path) : FS.stat(path)
|
|
5611
|
-
);
|
|
5597
|
+
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
5598
|
+
FS.close(stream);
|
|
5599
|
+
return 0;
|
|
5612
5600
|
} catch (e) {
|
|
5613
5601
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5614
|
-
return
|
|
5602
|
+
return e.errno;
|
|
5615
5603
|
}
|
|
5616
5604
|
}
|
|
5617
5605
|
|
|
5618
|
-
function
|
|
5606
|
+
function _builtin_fcntl64(fd, cmd, varargs) {
|
|
5619
5607
|
SYSCALLS.varargs = varargs;
|
|
5620
5608
|
try {
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5609
|
+
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
5610
|
+
switch (cmd) {
|
|
5611
|
+
case 0: {
|
|
5612
|
+
var arg = syscallGetVarargI();
|
|
5613
|
+
if (arg < 0) {
|
|
5614
|
+
return -28;
|
|
5615
|
+
}
|
|
5616
|
+
while (FS.streams[arg]) {
|
|
5617
|
+
arg++;
|
|
5618
|
+
}
|
|
5619
|
+
var newStream;
|
|
5620
|
+
newStream = FS.dupStream(stream, arg);
|
|
5621
|
+
return newStream.fd;
|
|
5622
|
+
}
|
|
5623
|
+
|
|
5624
|
+
case 1:
|
|
5625
|
+
case 2:
|
|
5626
|
+
return 0;
|
|
5627
|
+
|
|
5628
|
+
// FD_CLOEXEC makes no sense for a single process.
|
|
5629
|
+
case 3:
|
|
5630
|
+
return stream.flags;
|
|
5631
|
+
|
|
5632
|
+
case 4: {
|
|
5633
|
+
var arg = syscallGetVarargI();
|
|
5634
|
+
stream.flags |= arg;
|
|
5635
|
+
return 0;
|
|
5636
|
+
}
|
|
5637
|
+
|
|
5638
|
+
case 12: {
|
|
5639
|
+
var arg = syscallGetVarargP();
|
|
5640
|
+
var offset = 0;
|
|
5641
|
+
// We're always unlocked.
|
|
5642
|
+
HEAP16[(arg + offset) >> 1] = 2;
|
|
5643
|
+
return 0;
|
|
5644
|
+
}
|
|
5645
|
+
|
|
5646
|
+
case 13:
|
|
5647
|
+
case 14:
|
|
5648
|
+
// Pretend that the locking is successful. These are process-level locks,
|
|
5649
|
+
// and Emscripten programs are a single process. If we supported linking a
|
|
5650
|
+
// filesystem between programs, we'd need to do more here.
|
|
5651
|
+
// See https://github.com/emscripten-core/emscripten/issues/23697
|
|
5652
|
+
return 0;
|
|
5653
|
+
}
|
|
5654
|
+
return -28;
|
|
5625
5655
|
} catch (e) {
|
|
5626
5656
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5627
5657
|
return -e.errno;
|
|
5628
5658
|
}
|
|
5629
5659
|
}
|
|
5630
5660
|
|
|
5631
|
-
var
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5661
|
+
var locking = {
|
|
5662
|
+
maybeLockedFds: new Set(),
|
|
5663
|
+
F_RDLCK: 0,
|
|
5664
|
+
F_WRLCK: 1,
|
|
5665
|
+
F_UNLCK: 2,
|
|
5666
|
+
lockStateToFcntl: {
|
|
5667
|
+
shared: 0,
|
|
5668
|
+
exclusive: 1,
|
|
5669
|
+
unlocked: 2,
|
|
5670
|
+
},
|
|
5671
|
+
fcntlToLockState: {
|
|
5672
|
+
0: 'shared',
|
|
5673
|
+
1: 'exclusive',
|
|
5674
|
+
2: 'unlocked',
|
|
5675
|
+
},
|
|
5676
|
+
is_shared_fs_node(node) {
|
|
5677
|
+
if (node?.isSharedFS) {
|
|
5678
|
+
return true;
|
|
5679
|
+
}
|
|
5680
|
+
|
|
5681
|
+
// Handle PROXYFS nodes which wrap other nodes.
|
|
5682
|
+
if (
|
|
5683
|
+
!node?.mount?.opts?.fs?.lookupPath ||
|
|
5684
|
+
!node?.mount?.type?.realPath
|
|
5685
|
+
) {
|
|
5686
|
+
return false;
|
|
5687
|
+
}
|
|
5688
|
+
|
|
5689
|
+
// Only NODEFS can be shared between workers at the moment.
|
|
5690
|
+
if (node.mount.type !== NODEFS) {
|
|
5691
|
+
return false;
|
|
5692
|
+
}
|
|
5693
|
+
const vfsPath = node.mount.type.realPath(node);
|
|
5694
|
+
try {
|
|
5695
|
+
const underlyingNode =
|
|
5696
|
+
node.mount.opts.fs.lookupPath(vfsPath)?.node;
|
|
5697
|
+
return !!underlyingNode?.isSharedFS;
|
|
5698
|
+
} catch (e) {
|
|
5699
|
+
return false;
|
|
5700
|
+
}
|
|
5637
5701
|
},
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
// refcnt 2 because pipe has a read end and a write end. We need to be
|
|
5642
|
-
// able to read from the read end after write end is closed.
|
|
5643
|
-
refcnt: 2,
|
|
5644
|
-
timestamp: new Date(),
|
|
5645
|
-
};
|
|
5646
|
-
pipe.buckets.push({
|
|
5647
|
-
buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
|
|
5648
|
-
offset: 0,
|
|
5649
|
-
roffset: 0,
|
|
5650
|
-
});
|
|
5651
|
-
var rName = PIPEFS.nextname();
|
|
5652
|
-
var wName = PIPEFS.nextname();
|
|
5653
|
-
var rNode = FS.createNode(PIPEFS.root, rName, 4096, 0);
|
|
5654
|
-
var wNode = FS.createNode(PIPEFS.root, wName, 4096, 0);
|
|
5655
|
-
rNode.pipe = pipe;
|
|
5656
|
-
wNode.pipe = pipe;
|
|
5657
|
-
var readableStream = FS.createStream({
|
|
5658
|
-
path: rName,
|
|
5659
|
-
node: rNode,
|
|
5660
|
-
flags: 0,
|
|
5661
|
-
seekable: false,
|
|
5662
|
-
stream_ops: PIPEFS.stream_ops,
|
|
5663
|
-
});
|
|
5664
|
-
rNode.stream = readableStream;
|
|
5665
|
-
var writableStream = FS.createStream({
|
|
5666
|
-
path: wName,
|
|
5667
|
-
node: wNode,
|
|
5668
|
-
flags: 1,
|
|
5669
|
-
seekable: false,
|
|
5670
|
-
stream_ops: PIPEFS.stream_ops,
|
|
5671
|
-
});
|
|
5672
|
-
wNode.stream = writableStream;
|
|
5673
|
-
return {
|
|
5674
|
-
readable_fd: readableStream.fd,
|
|
5675
|
-
writable_fd: writableStream.fd,
|
|
5676
|
-
};
|
|
5702
|
+
is_path_to_shared_fs(path) {
|
|
5703
|
+
const { node } = FS.lookupPath(path);
|
|
5704
|
+
return locking.is_shared_fs_node(node);
|
|
5677
5705
|
},
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5706
|
+
get_fd_access_mode(fd) {
|
|
5707
|
+
const emscripten_F_GETFL = Number('3');
|
|
5708
|
+
const emscripten_O_ACCMODE = Number('2097155');
|
|
5709
|
+
return (
|
|
5710
|
+
_builtin_fcntl64(fd, emscripten_F_GETFL) & emscripten_O_ACCMODE
|
|
5711
|
+
);
|
|
5712
|
+
},
|
|
5713
|
+
get_vfs_path_from_fd(fd) {
|
|
5714
|
+
try {
|
|
5715
|
+
return [FS.readlink(`/proc/self/fd/${fd}`), 0];
|
|
5716
|
+
} catch (error) {
|
|
5717
|
+
return [null, ERRNO_CODES.EBADF];
|
|
5718
|
+
}
|
|
5719
|
+
},
|
|
5720
|
+
get_native_path_from_vfs_path(vfsPath) {
|
|
5721
|
+
const { node } = FS.lookupPath(vfsPath);
|
|
5722
|
+
return NODEFS.realPath(node);
|
|
5723
|
+
},
|
|
5724
|
+
check_lock_params(fd, l_type) {
|
|
5725
|
+
const emscripten_O_RDONLY = Number('0');
|
|
5726
|
+
const emscripten_O_WRONLY = Number('1');
|
|
5727
|
+
const accessMode = locking.get_fd_access_mode(fd);
|
|
5728
|
+
if (
|
|
5729
|
+
(l_type === locking.F_WRLCK &&
|
|
5730
|
+
accessMode === emscripten_O_RDONLY) ||
|
|
5731
|
+
(l_type === locking.F_RDLCK &&
|
|
5732
|
+
accessMode === emscripten_O_WRONLY)
|
|
5733
|
+
) {
|
|
5734
|
+
return ERRNO_CODES.EBADF;
|
|
5735
|
+
}
|
|
5736
|
+
return 0;
|
|
5737
|
+
},
|
|
5738
|
+
};
|
|
5739
|
+
|
|
5740
|
+
async function ___syscall_fcntl64(fd, cmd, varargs) {
|
|
5741
|
+
// Necessary to use varargs accessor
|
|
5742
|
+
SYSCALLS.varargs = varargs;
|
|
5743
|
+
// These constants are replaced by Emscripten during the build process
|
|
5744
|
+
const emscripten_F_GETLK = Number('12');
|
|
5745
|
+
const emscripten_F_SETLK = Number('13');
|
|
5746
|
+
const emscripten_F_SETLKW = Number('14');
|
|
5747
|
+
const emscripten_SEEK_SET = Number('0');
|
|
5748
|
+
// NOTE: With the exception of l_type, these offsets are not exposed to
|
|
5749
|
+
// JS by Emscripten, so we hardcode them here.
|
|
5750
|
+
const emscripten_flock_l_type_offset = 0;
|
|
5751
|
+
const emscripten_flock_l_whence_offset = 2;
|
|
5752
|
+
const emscripten_flock_l_start_offset = 8;
|
|
5753
|
+
const emscripten_flock_l_len_offset = 16;
|
|
5754
|
+
const emscripten_flock_l_pid_offset = 24;
|
|
5755
|
+
/**
|
|
5756
|
+
* Read the flock struct at the given address.
|
|
5757
|
+
*
|
|
5758
|
+
* @param {bigint} flockStructAddress - the address of the flock struct
|
|
5759
|
+
* @returns the flock struct
|
|
5760
|
+
*/ function read_flock_struct(flockStructAddress) {
|
|
5761
|
+
/*
|
|
5762
|
+
* NOTE: Since we are using HEAP<WORD_SIZE> vars like HEAP16 and HEAP64,
|
|
5763
|
+
* we need to adjust offsets to address the word size of each HEAP.
|
|
5764
|
+
*
|
|
5765
|
+
* For example, an offset of 64 bytes is the following for each HEAP:
|
|
5766
|
+
* - HEAP8: 64 (the 64th byte)
|
|
5767
|
+
* - HEAP16: 32 (the 32nd 16-bit word)
|
|
5768
|
+
* - HEAP32: 16 (the 16th 32-bit word)
|
|
5769
|
+
* - HEAP64: 8 (the 8th 64-bit word)
|
|
5770
|
+
*
|
|
5771
|
+
* We get a word offset by dividing the byte offset by the word size.
|
|
5772
|
+
*/ return {
|
|
5773
|
+
l_type: HEAP16[ // Shift right by 1 to divide by 2^1.
|
|
5774
|
+
(flockStructAddress + emscripten_flock_l_type_offset) >> 1
|
|
5775
|
+
],
|
|
5776
|
+
l_whence:
|
|
5777
|
+
HEAP16[ // Shift right by 1 to divide by 2^1.
|
|
5778
|
+
(flockStructAddress +
|
|
5779
|
+
emscripten_flock_l_whence_offset) >>
|
|
5780
|
+
1
|
|
5781
|
+
],
|
|
5782
|
+
l_start:
|
|
5783
|
+
HEAP64[ // Shift right by 3 to divide by 2^3.
|
|
5784
|
+
(flockStructAddress +
|
|
5785
|
+
emscripten_flock_l_start_offset) >>
|
|
5786
|
+
3
|
|
5787
|
+
],
|
|
5788
|
+
l_len: HEAP64[ // Shift right by 3 to divide by 2^3.
|
|
5789
|
+
(flockStructAddress + emscripten_flock_l_len_offset) >> 3
|
|
5790
|
+
],
|
|
5791
|
+
l_pid: HEAP32[ // Shift right by 2 to divide by 2^2.
|
|
5792
|
+
(flockStructAddress + emscripten_flock_l_pid_offset) >> 2
|
|
5793
|
+
],
|
|
5794
|
+
};
|
|
5795
|
+
}
|
|
5796
|
+
/**
|
|
5797
|
+
* Update the flock struct at the given address with the given fields.
|
|
5798
|
+
*
|
|
5799
|
+
* @param {bigint} flockStructAddress - the address of the flock struct
|
|
5800
|
+
* @param {object} fields - the fields to update
|
|
5801
|
+
*/ function update_flock_struct(flockStructAddress, fields) {
|
|
5802
|
+
/*
|
|
5803
|
+
* NOTE: Since we are using HEAP<WORD_SIZE> vars like HEAP16 and HEAP64,
|
|
5804
|
+
* we need to adjust offsets to address the word size of each HEAP.
|
|
5805
|
+
*
|
|
5806
|
+
* For example, an offset of 64 bytes is the following for each HEAP:
|
|
5807
|
+
* - HEAP8: 64 (the 64th byte)
|
|
5808
|
+
* - HEAP16: 32 (the 32nd 16-bit word)
|
|
5809
|
+
* - HEAP32: 16 (the 16th 32-bit word)
|
|
5810
|
+
* - HEAP64: 8 (the 8th 64-bit word)
|
|
5811
|
+
*
|
|
5812
|
+
* We get a word offset by dividing the byte offset by the word size.
|
|
5813
|
+
*/ if (fields.l_type !== undefined) {
|
|
5814
|
+
HEAP16[ // Shift right by 1 to divide by 2^1.
|
|
5815
|
+
(flockStructAddress + emscripten_flock_l_type_offset) >> 1
|
|
5816
|
+
] = fields.l_type;
|
|
5817
|
+
}
|
|
5818
|
+
if (fields.l_whence !== undefined) {
|
|
5819
|
+
HEAP16[ // Shift right by 1 to divide by 2^1.
|
|
5820
|
+
(flockStructAddress + emscripten_flock_l_whence_offset) >> 1
|
|
5821
|
+
] = fields.l_whence;
|
|
5822
|
+
}
|
|
5823
|
+
if (fields.l_start !== undefined) {
|
|
5824
|
+
HEAP64[ // Shift right by 3 to divide by 2^3.
|
|
5825
|
+
(flockStructAddress + emscripten_flock_l_start_offset) >> 3
|
|
5826
|
+
] = fields.l_start;
|
|
5827
|
+
}
|
|
5828
|
+
if (fields.l_len !== undefined) {
|
|
5829
|
+
HEAP64[ // Shift right by 3 to divide by 2^3.
|
|
5830
|
+
(flockStructAddress + emscripten_flock_l_len_offset) >> 3
|
|
5831
|
+
] = fields.l_len;
|
|
5832
|
+
}
|
|
5833
|
+
if (fields.l_pid !== undefined) {
|
|
5834
|
+
HEAP32[ // Shift right by 2 to divide by 2^2.
|
|
5835
|
+
(flockStructAddress + emscripten_flock_l_pid_offset) >> 2
|
|
5836
|
+
] = fields.l_pid;
|
|
5837
|
+
}
|
|
5838
|
+
}
|
|
5839
|
+
/**
|
|
5840
|
+
* Resolve the base address of the range depending on the whence and start offset.
|
|
5841
|
+
*
|
|
5842
|
+
* @param {number} fd - the file descriptor
|
|
5843
|
+
* @param {number} whence - what the start offset is relative to
|
|
5844
|
+
* @param {bigint} startOffset - the offset from the whence
|
|
5845
|
+
* @returns The resolved offset and the errno. If there is an error,
|
|
5846
|
+
* the resolved offset is null, and the errno is non-zero.
|
|
5847
|
+
*/ function get_base_address(fd, whence, startOffset) {
|
|
5848
|
+
let baseAddress;
|
|
5849
|
+
switch (whence) {
|
|
5850
|
+
case emscripten_SEEK_SET:
|
|
5851
|
+
baseAddress = 0n;
|
|
5852
|
+
break;
|
|
5853
|
+
|
|
5854
|
+
case emscripten_SEEK_CUR:
|
|
5855
|
+
baseAddress = FS.lseek(fd, 0, whence);
|
|
5856
|
+
break;
|
|
5857
|
+
|
|
5858
|
+
case emscripten_SEEK_END:
|
|
5859
|
+
baseAddress = _wasm_get_end_offset(fd);
|
|
5860
|
+
break;
|
|
5861
|
+
|
|
5862
|
+
default:
|
|
5863
|
+
return [null, ERRNO_CODES.EINVAL];
|
|
5864
|
+
}
|
|
5865
|
+
if (baseAddress == -1) {
|
|
5866
|
+
// We cannot resolve the offset within the file.
|
|
5867
|
+
// Let's treat this as a problem with the file descriptor.
|
|
5868
|
+
return [null, ERRNO_CODES.EBADF];
|
|
5869
|
+
}
|
|
5870
|
+
const resolvedOffset = baseAddress + startOffset;
|
|
5871
|
+
if (resolvedOffset < 0) {
|
|
5872
|
+
// This is not a valid offset. Report args as invalid.
|
|
5873
|
+
return [null, ERRNO_CODES.EINVAL];
|
|
5874
|
+
}
|
|
5875
|
+
return [resolvedOffset, 0];
|
|
5876
|
+
}
|
|
5877
|
+
const pid = PHPLoader.processId;
|
|
5878
|
+
switch (cmd) {
|
|
5879
|
+
case emscripten_F_GETLK: {
|
|
5880
|
+
_js_wasm_trace('fcntl(%d, F_GETLK)', fd);
|
|
5881
|
+
let vfsPath;
|
|
5882
|
+
let errno;
|
|
5883
|
+
[vfsPath, errno] = locking.get_vfs_path_from_fd(fd);
|
|
5884
|
+
if (errno !== 0) {
|
|
5885
|
+
_js_wasm_trace(
|
|
5886
|
+
'fcntl(%d, F_GETLK) %s get_vfs_path_from_fd errno %d',
|
|
5887
|
+
fd,
|
|
5888
|
+
vfsPath,
|
|
5889
|
+
errno
|
|
5890
|
+
);
|
|
5891
|
+
return -ERRNO_CODES.EBADF;
|
|
5768
5892
|
}
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5893
|
+
if (!locking.is_path_to_shared_fs(vfsPath)) {
|
|
5894
|
+
_js_wasm_trace(
|
|
5895
|
+
"fcntl(%d, F_GETLK) locking is not implemented for non-NodeFS path '%s'",
|
|
5896
|
+
fd,
|
|
5897
|
+
vfsPath
|
|
5898
|
+
);
|
|
5899
|
+
// If not a NodeFS path, we can't lock it.
|
|
5900
|
+
// Default to succeeding as Emscripten does.
|
|
5901
|
+
update_flock_struct(flockStructAddr, {
|
|
5902
|
+
l_type: F_UNLCK,
|
|
5903
|
+
});
|
|
5777
5904
|
return 0;
|
|
5778
5905
|
}
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
var freeBytesInCurrBuffer =
|
|
5792
|
-
PIPEFS.BUCKET_BUFFER_SIZE - currBucket.offset;
|
|
5793
|
-
if (freeBytesInCurrBuffer >= dataLen) {
|
|
5794
|
-
currBucket.buffer.set(data, currBucket.offset);
|
|
5795
|
-
currBucket.offset += dataLen;
|
|
5796
|
-
return dataLen;
|
|
5797
|
-
} else if (freeBytesInCurrBuffer > 0) {
|
|
5798
|
-
currBucket.buffer.set(
|
|
5799
|
-
data.subarray(0, freeBytesInCurrBuffer),
|
|
5800
|
-
currBucket.offset
|
|
5801
|
-
);
|
|
5802
|
-
currBucket.offset += freeBytesInCurrBuffer;
|
|
5803
|
-
data = data.subarray(
|
|
5804
|
-
freeBytesInCurrBuffer,
|
|
5805
|
-
data.byteLength
|
|
5906
|
+
const flockStructAddr = syscallGetVarargP();
|
|
5907
|
+
const flockStruct = read_flock_struct(flockStructAddr);
|
|
5908
|
+
if (!(flockStruct.l_type in locking.fcntlToLockState)) {
|
|
5909
|
+
return -ERRNO_CODES.EINVAL;
|
|
5910
|
+
}
|
|
5911
|
+
errno = locking.check_lock_params(fd, flockStruct.l_type);
|
|
5912
|
+
if (errno !== 0) {
|
|
5913
|
+
_js_wasm_trace(
|
|
5914
|
+
'fcntl(%d, F_GETLK) %s check_lock_params errno %d',
|
|
5915
|
+
fd,
|
|
5916
|
+
vfsPath,
|
|
5917
|
+
errno
|
|
5806
5918
|
);
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5919
|
+
return -ERRNO_CODES.EINVAL;
|
|
5920
|
+
}
|
|
5921
|
+
const requestedLockType =
|
|
5922
|
+
locking.fcntlToLockState[flockStruct.l_type];
|
|
5923
|
+
let absoluteStartOffset;
|
|
5924
|
+
[absoluteStartOffset, errno] = get_base_address(
|
|
5925
|
+
fd,
|
|
5926
|
+
flockStruct.l_whence,
|
|
5927
|
+
flockStruct.l_start
|
|
5928
|
+
);
|
|
5929
|
+
if (errno !== 0) {
|
|
5930
|
+
_js_wasm_trace(
|
|
5931
|
+
'fcntl(%d, F_GETLK) %s get_base_address errno %d',
|
|
5932
|
+
fd,
|
|
5933
|
+
vfsPath,
|
|
5934
|
+
errno
|
|
5820
5935
|
);
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5936
|
+
return -ERRNO_CODES.EINVAL;
|
|
5937
|
+
}
|
|
5938
|
+
const nativeFilePath =
|
|
5939
|
+
locking.get_native_path_from_vfs_path(vfsPath);
|
|
5940
|
+
return PHPLoader.fileLockManager
|
|
5941
|
+
.findFirstConflictingByteRangeLock(nativeFilePath, {
|
|
5942
|
+
type: requestedLockType,
|
|
5943
|
+
start: absoluteStartOffset,
|
|
5944
|
+
end: absoluteStartOffset + flockStruct.l_len,
|
|
5945
|
+
pid,
|
|
5946
|
+
})
|
|
5947
|
+
.then((conflictingLock) => {
|
|
5948
|
+
if (conflictingLock === undefined) {
|
|
5949
|
+
_js_wasm_trace(
|
|
5950
|
+
'fcntl(%d, F_GETLK) %s findFirstConflictingByteRangeLock type=unlocked start=0x%x end=0x%x',
|
|
5951
|
+
fd,
|
|
5952
|
+
vfsPath,
|
|
5953
|
+
absoluteStartOffset,
|
|
5954
|
+
absoluteStartOffset + flockStruct.l_len
|
|
5955
|
+
);
|
|
5956
|
+
update_flock_struct(flockStructAddr, {
|
|
5957
|
+
l_type: F_UNLCK,
|
|
5958
|
+
});
|
|
5959
|
+
return 0;
|
|
5960
|
+
}
|
|
5961
|
+
_js_wasm_trace(
|
|
5962
|
+
'fcntl(%d, F_GETLK) %s findFirstConflictingByteRangeLock type=%s start=0x%x end=0x%x conflictingLock %d',
|
|
5963
|
+
fd,
|
|
5964
|
+
vfsPath,
|
|
5965
|
+
conflictingLock.type,
|
|
5966
|
+
conflictingLock.start,
|
|
5967
|
+
conflictingLock.end,
|
|
5968
|
+
conflictingLock.pid
|
|
5969
|
+
);
|
|
5970
|
+
const fcntlLockState =
|
|
5971
|
+
locking.lockStateToFcntl[conflictingLock.type];
|
|
5972
|
+
update_flock_struct(flockStructAddr, {
|
|
5973
|
+
l_type: fcntlLockState,
|
|
5974
|
+
l_whence: emscripten_SEEK_SET,
|
|
5975
|
+
l_start: conflictingLock.start,
|
|
5976
|
+
l_len: conflictingLock.end - conflictingLock.start,
|
|
5977
|
+
l_pid: conflictingLock.pid,
|
|
5978
|
+
});
|
|
5979
|
+
return 0;
|
|
5980
|
+
})
|
|
5981
|
+
.catch((e) => {
|
|
5982
|
+
_js_wasm_trace(
|
|
5983
|
+
'fcntl(%d, F_GETLK) %s findFirstConflictingByteRangeLock error %s',
|
|
5984
|
+
fd,
|
|
5985
|
+
vfsPath,
|
|
5986
|
+
e
|
|
5987
|
+
);
|
|
5988
|
+
return -ERRNO_CODES.EINVAL;
|
|
5989
|
+
});
|
|
5990
|
+
}
|
|
5991
|
+
|
|
5992
|
+
case emscripten_F_SETLK: {
|
|
5993
|
+
_js_wasm_trace('fcntl(%d, F_SETLK)', fd);
|
|
5994
|
+
let vfsPath;
|
|
5995
|
+
let errno;
|
|
5996
|
+
[vfsPath, errno] = locking.get_vfs_path_from_fd(fd);
|
|
5997
|
+
if (errno !== 0) {
|
|
5998
|
+
_js_wasm_trace(
|
|
5999
|
+
'fcntl(%d, F_SETLK) %s get_vfs_path_from_fd errno %d',
|
|
6000
|
+
fd,
|
|
6001
|
+
vfsPath,
|
|
6002
|
+
errno
|
|
5824
6003
|
);
|
|
6004
|
+
return -errno;
|
|
5825
6005
|
}
|
|
5826
|
-
if (
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
return dataLen;
|
|
5836
|
-
},
|
|
5837
|
-
close(stream) {
|
|
5838
|
-
var pipe = stream.node.pipe;
|
|
5839
|
-
pipe.refcnt--;
|
|
5840
|
-
if (pipe.refcnt === 0) {
|
|
5841
|
-
pipe.buckets = null;
|
|
6006
|
+
if (!locking.is_path_to_shared_fs(vfsPath)) {
|
|
6007
|
+
_js_wasm_trace(
|
|
6008
|
+
'fcntl(%d, F_SETLK) locking is not implemented for non-NodeFS path %s',
|
|
6009
|
+
fd,
|
|
6010
|
+
vfsPath
|
|
6011
|
+
);
|
|
6012
|
+
// If not a NodeFS path, we can't lock it.
|
|
6013
|
+
// Default to succeeding as Emscripten does.
|
|
6014
|
+
return 0;
|
|
5842
6015
|
}
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
6016
|
+
var flockStructAddr = syscallGetVarargP();
|
|
6017
|
+
const flockStruct = read_flock_struct(flockStructAddr);
|
|
6018
|
+
let absoluteStartOffset;
|
|
6019
|
+
[absoluteStartOffset, errno] = get_base_address(
|
|
6020
|
+
fd,
|
|
6021
|
+
flockStruct.l_whence,
|
|
6022
|
+
flockStruct.l_start
|
|
6023
|
+
);
|
|
6024
|
+
if (errno !== 0) {
|
|
6025
|
+
_js_wasm_trace(
|
|
6026
|
+
'fcntl(%d, F_SETLK) %s get_base_address errno %d',
|
|
6027
|
+
fd,
|
|
6028
|
+
vfsPath,
|
|
6029
|
+
errno
|
|
6030
|
+
);
|
|
6031
|
+
return -errno;
|
|
6032
|
+
}
|
|
6033
|
+
if (!(flockStruct.l_type in locking.fcntlToLockState)) {
|
|
6034
|
+
_js_wasm_trace(
|
|
6035
|
+
'fcntl(%d, F_SETLK) %s invalid lock type %d',
|
|
6036
|
+
fd,
|
|
6037
|
+
vfsPath,
|
|
6038
|
+
flockStruct.l_type
|
|
6039
|
+
);
|
|
6040
|
+
return -ERRNO_CODES.EINVAL;
|
|
6041
|
+
}
|
|
6042
|
+
errno = locking.check_lock_params(fd, flockStruct.l_type);
|
|
6043
|
+
if (errno !== 0) {
|
|
6044
|
+
_js_wasm_trace(
|
|
6045
|
+
'fcntl(%d, F_SETLK) %s check_lock_params errno %d',
|
|
6046
|
+
fd,
|
|
6047
|
+
vfsPath,
|
|
6048
|
+
errno
|
|
6049
|
+
);
|
|
6050
|
+
return -errno;
|
|
6051
|
+
}
|
|
6052
|
+
locking.maybeLockedFds.add(fd);
|
|
6053
|
+
const requestedLockType =
|
|
6054
|
+
locking.fcntlToLockState[flockStruct.l_type];
|
|
6055
|
+
const rangeLock = {
|
|
6056
|
+
type: requestedLockType,
|
|
6057
|
+
start: absoluteStartOffset,
|
|
6058
|
+
end: absoluteStartOffset + flockStruct.l_len,
|
|
6059
|
+
pid,
|
|
6060
|
+
};
|
|
6061
|
+
const nativeFilePath =
|
|
6062
|
+
locking.get_native_path_from_vfs_path(vfsPath);
|
|
6063
|
+
_js_wasm_trace(
|
|
6064
|
+
'fcntl(%d, F_SETLK) %s calling lockFileByteRange for range lock %s',
|
|
6065
|
+
fd,
|
|
6066
|
+
vfsPath,
|
|
6067
|
+
rangeLock
|
|
6068
|
+
);
|
|
6069
|
+
return PHPLoader.fileLockManager
|
|
6070
|
+
.lockFileByteRange(nativeFilePath, rangeLock)
|
|
6071
|
+
.then((succeeded) => {
|
|
6072
|
+
_js_wasm_trace(
|
|
6073
|
+
'fcntl(%d, F_SETLK) %s lockFileByteRange returned %d for range lock %s',
|
|
6074
|
+
fd,
|
|
6075
|
+
vfsPath,
|
|
6076
|
+
succeeded,
|
|
6077
|
+
rangeLock
|
|
6078
|
+
);
|
|
6079
|
+
return succeeded ? 0 : -ERRNO_CODES.EAGAIN;
|
|
6080
|
+
})
|
|
6081
|
+
.catch((e) => {
|
|
6082
|
+
_js_wasm_trace(
|
|
6083
|
+
'fcntl(%d, F_SETLK) %s lockFileByteRange error %s for range lock %s',
|
|
6084
|
+
fd,
|
|
6085
|
+
vfsPath,
|
|
6086
|
+
e,
|
|
6087
|
+
rangeLock
|
|
6088
|
+
);
|
|
6089
|
+
return -ERRNO_CODES.EINVAL;
|
|
6090
|
+
});
|
|
5848
6091
|
}
|
|
5849
|
-
return 'pipe[' + PIPEFS.nextname.current++ + ']';
|
|
5850
|
-
},
|
|
5851
|
-
};
|
|
5852
6092
|
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
6093
|
+
// @TODO: Implement waiting for lock
|
|
6094
|
+
case emscripten_F_SETLKW: {
|
|
6095
|
+
// We do not yet support the blocking form of flock().
|
|
6096
|
+
// We respond with EDEADLK to indicate failure
|
|
6097
|
+
// because it is a known errno for a failed F_SETLKW command.
|
|
6098
|
+
return -ERRNO_CODES.EDEADLK;
|
|
5857
6099
|
}
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
6100
|
+
|
|
6101
|
+
default:
|
|
6102
|
+
return _builtin_fcntl64(fd, cmd, varargs);
|
|
6103
|
+
}
|
|
6104
|
+
}
|
|
6105
|
+
|
|
6106
|
+
___syscall_fcntl64.isAsync = true;
|
|
6107
|
+
|
|
6108
|
+
function ___syscall_fdatasync(fd) {
|
|
6109
|
+
try {
|
|
6110
|
+
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
5861
6111
|
return 0;
|
|
5862
6112
|
} catch (e) {
|
|
5863
6113
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
@@ -5865,96 +6115,115 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
5865
6115
|
}
|
|
5866
6116
|
}
|
|
5867
6117
|
|
|
5868
|
-
function
|
|
6118
|
+
function ___syscall_fstat64(fd, buf) {
|
|
5869
6119
|
try {
|
|
5870
|
-
|
|
5871
|
-
for (var i = 0; i < nfds; i++) {
|
|
5872
|
-
var pollfd = fds + 8 * i;
|
|
5873
|
-
var fd = HEAP32[pollfd >> 2];
|
|
5874
|
-
var events = HEAP16[(pollfd + 4) >> 1];
|
|
5875
|
-
var mask = 32;
|
|
5876
|
-
var stream = FS.getStream(fd);
|
|
5877
|
-
if (stream) {
|
|
5878
|
-
mask = SYSCALLS.DEFAULT_POLLMASK;
|
|
5879
|
-
if (stream.stream_ops?.poll) {
|
|
5880
|
-
mask = stream.stream_ops.poll(stream, -1);
|
|
5881
|
-
}
|
|
5882
|
-
}
|
|
5883
|
-
mask &= events | 8 | 16;
|
|
5884
|
-
if (mask) nonzero++;
|
|
5885
|
-
HEAP16[(pollfd + 6) >> 1] = mask;
|
|
5886
|
-
}
|
|
5887
|
-
return nonzero;
|
|
6120
|
+
return SYSCALLS.writeStat(buf, FS.fstat(fd));
|
|
5888
6121
|
} catch (e) {
|
|
5889
6122
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5890
6123
|
return -e.errno;
|
|
5891
6124
|
}
|
|
5892
6125
|
}
|
|
5893
6126
|
|
|
5894
|
-
function
|
|
6127
|
+
function ___syscall_ftruncate64(fd, length) {
|
|
6128
|
+
length = bigintToI53Checked(length);
|
|
5895
6129
|
try {
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
var ret = FS.readlink(path);
|
|
5900
|
-
var len = Math.min(bufsize, lengthBytesUTF8(ret));
|
|
5901
|
-
var endChar = HEAP8[buf + len];
|
|
5902
|
-
stringToUTF8(ret, buf, bufsize + 1);
|
|
5903
|
-
// readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!)
|
|
5904
|
-
// stringToUTF8() always appends a null byte, so restore the character under the null byte after the write.
|
|
5905
|
-
HEAP8[buf + len] = endChar;
|
|
5906
|
-
return len;
|
|
6130
|
+
if (isNaN(length)) return 61;
|
|
6131
|
+
FS.ftruncate(fd, length);
|
|
6132
|
+
return 0;
|
|
5907
6133
|
} catch (e) {
|
|
5908
6134
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5909
6135
|
return -e.errno;
|
|
5910
6136
|
}
|
|
5911
6137
|
}
|
|
5912
6138
|
|
|
5913
|
-
function
|
|
6139
|
+
function ___syscall_getcwd(buf, size) {
|
|
5914
6140
|
try {
|
|
5915
|
-
|
|
5916
|
-
var
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
if (!msg) return 0;
|
|
5922
|
-
// socket is closed
|
|
5923
|
-
if (addr) {
|
|
5924
|
-
var errno = writeSockaddr(
|
|
5925
|
-
addr,
|
|
5926
|
-
sock.family,
|
|
5927
|
-
DNS.lookup_name(msg.addr),
|
|
5928
|
-
msg.port,
|
|
5929
|
-
addrlen
|
|
5930
|
-
);
|
|
5931
|
-
}
|
|
5932
|
-
HEAPU8.set(msg.buffer, buf);
|
|
5933
|
-
return msg.buffer.byteLength;
|
|
6141
|
+
if (size === 0) return -28;
|
|
6142
|
+
var cwd = FS.cwd();
|
|
6143
|
+
var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1;
|
|
6144
|
+
if (size < cwdLengthInBytes) return -68;
|
|
6145
|
+
stringToUTF8(cwd, buf, size);
|
|
6146
|
+
return cwdLengthInBytes;
|
|
5934
6147
|
} catch (e) {
|
|
5935
6148
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5936
6149
|
return -e.errno;
|
|
5937
6150
|
}
|
|
5938
6151
|
}
|
|
5939
6152
|
|
|
5940
|
-
function
|
|
6153
|
+
function ___syscall_getdents64(fd, dirp, count) {
|
|
5941
6154
|
try {
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
FS.
|
|
5947
|
-
|
|
6155
|
+
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
6156
|
+
stream.getdents ||= FS.readdir(stream.path);
|
|
6157
|
+
var struct_size = 280;
|
|
6158
|
+
var pos = 0;
|
|
6159
|
+
var off = FS.llseek(stream, 0, 1);
|
|
6160
|
+
var startIdx = Math.floor(off / struct_size);
|
|
6161
|
+
var endIdx = Math.min(
|
|
6162
|
+
stream.getdents.length,
|
|
6163
|
+
startIdx + Math.floor(count / struct_size)
|
|
6164
|
+
);
|
|
6165
|
+
for (var idx = startIdx; idx < endIdx; idx++) {
|
|
6166
|
+
var id;
|
|
6167
|
+
var type;
|
|
6168
|
+
var name = stream.getdents[idx];
|
|
6169
|
+
if (name === '.') {
|
|
6170
|
+
id = stream.node.id;
|
|
6171
|
+
type = 4;
|
|
6172
|
+
} else if (name === '..') {
|
|
6173
|
+
var lookup = FS.lookupPath(stream.path, {
|
|
6174
|
+
parent: true,
|
|
6175
|
+
});
|
|
6176
|
+
id = lookup.node.id;
|
|
6177
|
+
type = 4;
|
|
6178
|
+
} else {
|
|
6179
|
+
var child;
|
|
6180
|
+
try {
|
|
6181
|
+
child = FS.lookupNode(stream.node, name);
|
|
6182
|
+
} catch (e) {
|
|
6183
|
+
// If the entry is not a directory, file, or symlink, nodefs
|
|
6184
|
+
// lookupNode will raise EINVAL. Skip these and continue.
|
|
6185
|
+
if (e?.errno === 28) {
|
|
6186
|
+
continue;
|
|
6187
|
+
}
|
|
6188
|
+
throw e;
|
|
6189
|
+
}
|
|
6190
|
+
id = child.id;
|
|
6191
|
+
type = FS.isChrdev(child.mode)
|
|
6192
|
+
? 2 // DT_CHR, character device.
|
|
6193
|
+
: FS.isDir(child.mode)
|
|
6194
|
+
? 4 // DT_DIR, directory.
|
|
6195
|
+
: FS.isLink(child.mode)
|
|
6196
|
+
? 10 // DT_LNK, symbolic link.
|
|
6197
|
+
: 8;
|
|
6198
|
+
}
|
|
6199
|
+
HEAP64[(dirp + pos) >> 3] = BigInt(id);
|
|
6200
|
+
HEAP64[(dirp + pos + 8) >> 3] = BigInt((idx + 1) * struct_size);
|
|
6201
|
+
HEAP16[(dirp + pos + 16) >> 1] = 280;
|
|
6202
|
+
HEAP8[dirp + pos + 18] = type;
|
|
6203
|
+
stringToUTF8(name, dirp + pos + 19, 256);
|
|
6204
|
+
pos += struct_size;
|
|
6205
|
+
}
|
|
6206
|
+
FS.llseek(stream, idx * struct_size, 0);
|
|
6207
|
+
return pos;
|
|
5948
6208
|
} catch (e) {
|
|
5949
6209
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5950
6210
|
return -e.errno;
|
|
5951
6211
|
}
|
|
5952
6212
|
}
|
|
5953
6213
|
|
|
5954
|
-
function
|
|
6214
|
+
function ___syscall_getpeername(fd, addr, addrlen, d1, d2, d3) {
|
|
5955
6215
|
try {
|
|
5956
|
-
|
|
5957
|
-
|
|
6216
|
+
var sock = getSocketFromFD(fd);
|
|
6217
|
+
if (!sock.daddr) {
|
|
6218
|
+
return -53;
|
|
6219
|
+
}
|
|
6220
|
+
var errno = writeSockaddr(
|
|
6221
|
+
addr,
|
|
6222
|
+
sock.family,
|
|
6223
|
+
DNS.lookup_name(sock.daddr),
|
|
6224
|
+
sock.dport,
|
|
6225
|
+
addrlen
|
|
6226
|
+
);
|
|
5958
6227
|
return 0;
|
|
5959
6228
|
} catch (e) {
|
|
5960
6229
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
@@ -5962,52 +6231,162 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
5962
6231
|
}
|
|
5963
6232
|
}
|
|
5964
6233
|
|
|
5965
|
-
function
|
|
6234
|
+
function ___syscall_getsockname(fd, addr, addrlen, d1, d2, d3) {
|
|
5966
6235
|
try {
|
|
5967
6236
|
var sock = getSocketFromFD(fd);
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
sock,
|
|
5976
|
-
HEAP8,
|
|
5977
|
-
message,
|
|
5978
|
-
length,
|
|
5979
|
-
dest.addr,
|
|
5980
|
-
dest.port
|
|
6237
|
+
// TODO: sock.saddr should never be undefined, see TODO in websocket_sock_ops.getname
|
|
6238
|
+
var errno = writeSockaddr(
|
|
6239
|
+
addr,
|
|
6240
|
+
sock.family,
|
|
6241
|
+
DNS.lookup_name(sock.saddr || '0.0.0.0'),
|
|
6242
|
+
sock.sport,
|
|
6243
|
+
addrlen
|
|
5981
6244
|
);
|
|
6245
|
+
return 0;
|
|
5982
6246
|
} catch (e) {
|
|
5983
6247
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5984
6248
|
return -e.errno;
|
|
5985
6249
|
}
|
|
5986
6250
|
}
|
|
5987
6251
|
|
|
5988
|
-
function
|
|
6252
|
+
function ___syscall_getsockopt(fd, level, optname, optval, optlen, d1) {
|
|
5989
6253
|
try {
|
|
5990
|
-
var sock =
|
|
5991
|
-
|
|
6254
|
+
var sock = getSocketFromFD(fd);
|
|
6255
|
+
// Minimal getsockopt aimed at resolving https://github.com/emscripten-core/emscripten/issues/2211
|
|
6256
|
+
// so only supports SOL_SOCKET with SO_ERROR.
|
|
6257
|
+
if (level === 1) {
|
|
6258
|
+
if (optname === 4) {
|
|
6259
|
+
HEAP32[optval >> 2] = sock.error;
|
|
6260
|
+
HEAP32[optlen >> 2] = 4;
|
|
6261
|
+
sock.error = null;
|
|
6262
|
+
// Clear the error (The SO_ERROR option obtains and then clears this field).
|
|
6263
|
+
return 0;
|
|
6264
|
+
}
|
|
6265
|
+
}
|
|
6266
|
+
return -50;
|
|
5992
6267
|
} catch (e) {
|
|
5993
6268
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
5994
6269
|
return -e.errno;
|
|
5995
6270
|
}
|
|
5996
6271
|
}
|
|
5997
6272
|
|
|
5998
|
-
function
|
|
6273
|
+
function ___syscall_ioctl(fd, op, varargs) {
|
|
6274
|
+
SYSCALLS.varargs = varargs;
|
|
5999
6275
|
try {
|
|
6000
|
-
|
|
6001
|
-
|
|
6276
|
+
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
6277
|
+
switch (op) {
|
|
6278
|
+
case 21509: {
|
|
6279
|
+
if (!stream.tty) return -59;
|
|
6280
|
+
return 0;
|
|
6281
|
+
}
|
|
6282
|
+
|
|
6283
|
+
case 21505: {
|
|
6284
|
+
if (!stream.tty) return -59;
|
|
6285
|
+
if (stream.tty.ops.ioctl_tcgets) {
|
|
6286
|
+
var termios = stream.tty.ops.ioctl_tcgets(stream);
|
|
6287
|
+
var argp = syscallGetVarargP();
|
|
6288
|
+
HEAP32[argp >> 2] = termios.c_iflag || 0;
|
|
6289
|
+
HEAP32[(argp + 4) >> 2] = termios.c_oflag || 0;
|
|
6290
|
+
HEAP32[(argp + 8) >> 2] = termios.c_cflag || 0;
|
|
6291
|
+
HEAP32[(argp + 12) >> 2] = termios.c_lflag || 0;
|
|
6292
|
+
for (var i = 0; i < 32; i++) {
|
|
6293
|
+
HEAP8[argp + i + 17] = termios.c_cc[i] || 0;
|
|
6294
|
+
}
|
|
6295
|
+
return 0;
|
|
6296
|
+
}
|
|
6297
|
+
return 0;
|
|
6298
|
+
}
|
|
6299
|
+
|
|
6300
|
+
case 21510:
|
|
6301
|
+
case 21511:
|
|
6302
|
+
case 21512: {
|
|
6303
|
+
if (!stream.tty) return -59;
|
|
6304
|
+
return 0;
|
|
6305
|
+
}
|
|
6306
|
+
|
|
6307
|
+
case 21506:
|
|
6308
|
+
case 21507:
|
|
6309
|
+
case 21508: {
|
|
6310
|
+
if (!stream.tty) return -59;
|
|
6311
|
+
if (stream.tty.ops.ioctl_tcsets) {
|
|
6312
|
+
var argp = syscallGetVarargP();
|
|
6313
|
+
var c_iflag = HEAP32[argp >> 2];
|
|
6314
|
+
var c_oflag = HEAP32[(argp + 4) >> 2];
|
|
6315
|
+
var c_cflag = HEAP32[(argp + 8) >> 2];
|
|
6316
|
+
var c_lflag = HEAP32[(argp + 12) >> 2];
|
|
6317
|
+
var c_cc = [];
|
|
6318
|
+
for (var i = 0; i < 32; i++) {
|
|
6319
|
+
c_cc.push(HEAP8[argp + i + 17]);
|
|
6320
|
+
}
|
|
6321
|
+
return stream.tty.ops.ioctl_tcsets(stream.tty, op, {
|
|
6322
|
+
c_iflag,
|
|
6323
|
+
c_oflag,
|
|
6324
|
+
c_cflag,
|
|
6325
|
+
c_lflag,
|
|
6326
|
+
c_cc,
|
|
6327
|
+
});
|
|
6328
|
+
}
|
|
6329
|
+
return 0;
|
|
6330
|
+
}
|
|
6331
|
+
|
|
6332
|
+
case 21519: {
|
|
6333
|
+
if (!stream.tty) return -59;
|
|
6334
|
+
var argp = syscallGetVarargP();
|
|
6335
|
+
HEAP32[argp >> 2] = 0;
|
|
6336
|
+
return 0;
|
|
6337
|
+
}
|
|
6338
|
+
|
|
6339
|
+
case 21520: {
|
|
6340
|
+
if (!stream.tty) return -59;
|
|
6341
|
+
return -28;
|
|
6342
|
+
}
|
|
6343
|
+
|
|
6344
|
+
case 21531: {
|
|
6345
|
+
var argp = syscallGetVarargP();
|
|
6346
|
+
return FS.ioctl(stream, op, argp);
|
|
6347
|
+
}
|
|
6348
|
+
|
|
6349
|
+
case 21523: {
|
|
6350
|
+
// TODO: in theory we should write to the winsize struct that gets
|
|
6351
|
+
// passed in, but for now musl doesn't read anything on it
|
|
6352
|
+
if (!stream.tty) return -59;
|
|
6353
|
+
if (stream.tty.ops.ioctl_tiocgwinsz) {
|
|
6354
|
+
var winsize = stream.tty.ops.ioctl_tiocgwinsz(
|
|
6355
|
+
stream.tty
|
|
6356
|
+
);
|
|
6357
|
+
var argp = syscallGetVarargP();
|
|
6358
|
+
HEAP16[argp >> 1] = winsize[0];
|
|
6359
|
+
HEAP16[(argp + 2) >> 1] = winsize[1];
|
|
6360
|
+
}
|
|
6361
|
+
return 0;
|
|
6362
|
+
}
|
|
6363
|
+
|
|
6364
|
+
case 21524: {
|
|
6365
|
+
// TODO: technically, this ioctl call should change the window size.
|
|
6366
|
+
// but, since emscripten doesn't have any concept of a terminal window
|
|
6367
|
+
// yet, we'll just silently throw it away as we do TIOCGWINSZ
|
|
6368
|
+
if (!stream.tty) return -59;
|
|
6369
|
+
return 0;
|
|
6370
|
+
}
|
|
6371
|
+
|
|
6372
|
+
case 21515: {
|
|
6373
|
+
if (!stream.tty) return -59;
|
|
6374
|
+
return 0;
|
|
6375
|
+
}
|
|
6376
|
+
|
|
6377
|
+
default:
|
|
6378
|
+
return -28;
|
|
6379
|
+
}
|
|
6002
6380
|
} catch (e) {
|
|
6003
6381
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6004
6382
|
return -e.errno;
|
|
6005
6383
|
}
|
|
6006
6384
|
}
|
|
6007
6385
|
|
|
6008
|
-
function
|
|
6386
|
+
function ___syscall_listen(fd, backlog) {
|
|
6009
6387
|
try {
|
|
6010
|
-
|
|
6388
|
+
var sock = getSocketFromFD(fd);
|
|
6389
|
+
sock.sock_ops.listen(sock, backlog);
|
|
6011
6390
|
return 0;
|
|
6012
6391
|
} catch (e) {
|
|
6013
6392
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
@@ -6015,30 +6394,21 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
6015
6394
|
}
|
|
6016
6395
|
}
|
|
6017
6396
|
|
|
6018
|
-
function
|
|
6397
|
+
function ___syscall_lstat64(path, buf) {
|
|
6019
6398
|
try {
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
linkpath = SYSCALLS.calculateAt(dirfd, linkpath);
|
|
6023
|
-
FS.symlink(target, linkpath);
|
|
6024
|
-
return 0;
|
|
6399
|
+
path = SYSCALLS.getStr(path);
|
|
6400
|
+
return SYSCALLS.writeStat(buf, FS.lstat(path));
|
|
6025
6401
|
} catch (e) {
|
|
6026
6402
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6027
6403
|
return -e.errno;
|
|
6028
6404
|
}
|
|
6029
6405
|
}
|
|
6030
6406
|
|
|
6031
|
-
function
|
|
6407
|
+
function ___syscall_mkdirat(dirfd, path, mode) {
|
|
6032
6408
|
try {
|
|
6033
6409
|
path = SYSCALLS.getStr(path);
|
|
6034
6410
|
path = SYSCALLS.calculateAt(dirfd, path);
|
|
6035
|
-
|
|
6036
|
-
FS.unlink(path);
|
|
6037
|
-
} else if (flags === 512) {
|
|
6038
|
-
FS.rmdir(path);
|
|
6039
|
-
} else {
|
|
6040
|
-
abort('Invalid flags passed to unlinkat');
|
|
6041
|
-
}
|
|
6411
|
+
FS.mkdir(path, mode, 0);
|
|
6042
6412
|
return 0;
|
|
6043
6413
|
} catch (e) {
|
|
6044
6414
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
@@ -6046,1220 +6416,1370 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
6046
6416
|
}
|
|
6047
6417
|
}
|
|
6048
6418
|
|
|
6049
|
-
|
|
6050
|
-
HEAPU32[ptr >> 2] + HEAP32[(ptr + 4) >> 2] * 4294967296;
|
|
6051
|
-
|
|
6052
|
-
function ___syscall_utimensat(dirfd, path, times, flags) {
|
|
6419
|
+
function ___syscall_newfstatat(dirfd, path, buf, flags) {
|
|
6053
6420
|
try {
|
|
6054
6421
|
path = SYSCALLS.getStr(path);
|
|
6055
|
-
|
|
6056
|
-
var
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
var seconds = readI53FromI64(times);
|
|
6064
|
-
var nanoseconds = HEAP32[(times + 8) >> 2];
|
|
6065
|
-
if (nanoseconds == 1073741823) {
|
|
6066
|
-
atime = now;
|
|
6067
|
-
} else if (nanoseconds == 1073741822) {
|
|
6068
|
-
atime = null;
|
|
6069
|
-
} else {
|
|
6070
|
-
atime = seconds * 1e3 + nanoseconds / (1e3 * 1e3);
|
|
6071
|
-
}
|
|
6072
|
-
times += 16;
|
|
6073
|
-
seconds = readI53FromI64(times);
|
|
6074
|
-
nanoseconds = HEAP32[(times + 8) >> 2];
|
|
6075
|
-
if (nanoseconds == 1073741823) {
|
|
6076
|
-
mtime = now;
|
|
6077
|
-
} else if (nanoseconds == 1073741822) {
|
|
6078
|
-
mtime = null;
|
|
6079
|
-
} else {
|
|
6080
|
-
mtime = seconds * 1e3 + nanoseconds / (1e3 * 1e3);
|
|
6081
|
-
}
|
|
6082
|
-
}
|
|
6083
|
-
// null here means UTIME_OMIT was passed. If both were set to UTIME_OMIT then
|
|
6084
|
-
// we can skip the call completely.
|
|
6085
|
-
if ((mtime ?? atime) !== null) {
|
|
6086
|
-
FS.utime(path, atime, mtime);
|
|
6087
|
-
}
|
|
6088
|
-
return 0;
|
|
6422
|
+
var nofollow = flags & 256;
|
|
6423
|
+
var allowEmpty = flags & 4096;
|
|
6424
|
+
flags = flags & ~6400;
|
|
6425
|
+
path = SYSCALLS.calculateAt(dirfd, path, allowEmpty);
|
|
6426
|
+
return SYSCALLS.writeStat(
|
|
6427
|
+
buf,
|
|
6428
|
+
nofollow ? FS.lstat(path) : FS.stat(path)
|
|
6429
|
+
);
|
|
6089
6430
|
} catch (e) {
|
|
6090
6431
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6091
6432
|
return -e.errno;
|
|
6092
|
-
}
|
|
6093
|
-
}
|
|
6094
|
-
|
|
6095
|
-
var __abort_js = () => abort('');
|
|
6096
|
-
|
|
6097
|
-
var __emscripten_lookup_name = (name) => {
|
|
6098
|
-
// uint32_t _emscripten_lookup_name(const char *name);
|
|
6099
|
-
var nameString = UTF8ToString(name);
|
|
6100
|
-
return inetPton4(DNS.lookup_name(nameString));
|
|
6101
|
-
};
|
|
6102
|
-
|
|
6103
|
-
var runtimeKeepaliveCounter = 0;
|
|
6104
|
-
|
|
6105
|
-
var __emscripten_runtime_keepalive_clear = () => {
|
|
6106
|
-
noExitRuntime = false;
|
|
6107
|
-
runtimeKeepaliveCounter = 0;
|
|
6108
|
-
};
|
|
6109
|
-
|
|
6110
|
-
function __gmtime_js(time, tmPtr) {
|
|
6111
|
-
time = bigintToI53Checked(time);
|
|
6112
|
-
var date = new Date(time * 1e3);
|
|
6113
|
-
HEAP32[tmPtr >> 2] = date.getUTCSeconds();
|
|
6114
|
-
HEAP32[(tmPtr + 4) >> 2] = date.getUTCMinutes();
|
|
6115
|
-
HEAP32[(tmPtr + 8) >> 2] = date.getUTCHours();
|
|
6116
|
-
HEAP32[(tmPtr + 12) >> 2] = date.getUTCDate();
|
|
6117
|
-
HEAP32[(tmPtr + 16) >> 2] = date.getUTCMonth();
|
|
6118
|
-
HEAP32[(tmPtr + 20) >> 2] = date.getUTCFullYear() - 1900;
|
|
6119
|
-
HEAP32[(tmPtr + 24) >> 2] = date.getUTCDay();
|
|
6120
|
-
var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
|
|
6121
|
-
var yday = ((date.getTime() - start) / (1e3 * 60 * 60 * 24)) | 0;
|
|
6122
|
-
HEAP32[(tmPtr + 28) >> 2] = yday;
|
|
6433
|
+
}
|
|
6123
6434
|
}
|
|
6124
6435
|
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
var ydayFromDate = (date) => {
|
|
6137
|
-
var leap = isLeapYear(date.getFullYear());
|
|
6138
|
-
var monthDaysCumulative = leap
|
|
6139
|
-
? MONTH_DAYS_LEAP_CUMULATIVE
|
|
6140
|
-
: MONTH_DAYS_REGULAR_CUMULATIVE;
|
|
6141
|
-
var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1;
|
|
6142
|
-
// -1 since it's days since Jan 1
|
|
6143
|
-
return yday;
|
|
6144
|
-
};
|
|
6145
|
-
|
|
6146
|
-
function __localtime_js(time, tmPtr) {
|
|
6147
|
-
time = bigintToI53Checked(time);
|
|
6148
|
-
var date = new Date(time * 1e3);
|
|
6149
|
-
HEAP32[tmPtr >> 2] = date.getSeconds();
|
|
6150
|
-
HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
|
|
6151
|
-
HEAP32[(tmPtr + 8) >> 2] = date.getHours();
|
|
6152
|
-
HEAP32[(tmPtr + 12) >> 2] = date.getDate();
|
|
6153
|
-
HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
|
|
6154
|
-
HEAP32[(tmPtr + 20) >> 2] = date.getFullYear() - 1900;
|
|
6155
|
-
HEAP32[(tmPtr + 24) >> 2] = date.getDay();
|
|
6156
|
-
var yday = ydayFromDate(date) | 0;
|
|
6157
|
-
HEAP32[(tmPtr + 28) >> 2] = yday;
|
|
6158
|
-
HEAP32[(tmPtr + 36) >> 2] = -(date.getTimezoneOffset() * 60);
|
|
6159
|
-
// Attention: DST is in December in South, and some regions don't have DST at all.
|
|
6160
|
-
var start = new Date(date.getFullYear(), 0, 1);
|
|
6161
|
-
var summerOffset = new Date(
|
|
6162
|
-
date.getFullYear(),
|
|
6163
|
-
6,
|
|
6164
|
-
1
|
|
6165
|
-
).getTimezoneOffset();
|
|
6166
|
-
var winterOffset = start.getTimezoneOffset();
|
|
6167
|
-
var dst =
|
|
6168
|
-
(summerOffset != winterOffset &&
|
|
6169
|
-
date.getTimezoneOffset() ==
|
|
6170
|
-
Math.min(winterOffset, summerOffset)) | 0;
|
|
6171
|
-
HEAP32[(tmPtr + 32) >> 2] = dst;
|
|
6436
|
+
function ___syscall_openat(dirfd, path, flags, varargs) {
|
|
6437
|
+
SYSCALLS.varargs = varargs;
|
|
6438
|
+
try {
|
|
6439
|
+
path = SYSCALLS.getStr(path);
|
|
6440
|
+
path = SYSCALLS.calculateAt(dirfd, path);
|
|
6441
|
+
var mode = varargs ? syscallGetVarargI() : 0;
|
|
6442
|
+
return FS.open(path, flags, mode).fd;
|
|
6443
|
+
} catch (e) {
|
|
6444
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6445
|
+
return -e.errno;
|
|
6446
|
+
}
|
|
6172
6447
|
}
|
|
6173
6448
|
|
|
6174
|
-
var
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
var
|
|
6197
|
-
var
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6449
|
+
var PIPEFS = {
|
|
6450
|
+
BUCKET_BUFFER_SIZE: 8192,
|
|
6451
|
+
mount(mount) {
|
|
6452
|
+
// Do not pollute the real root directory or its child nodes with pipes
|
|
6453
|
+
// Looks like it is OK to create another pseudo-root node not linked to the FS.root hierarchy this way
|
|
6454
|
+
return FS.createNode(null, '/', 16384 | 511, 0);
|
|
6455
|
+
},
|
|
6456
|
+
createPipe() {
|
|
6457
|
+
var pipe = {
|
|
6458
|
+
buckets: [],
|
|
6459
|
+
// refcnt 2 because pipe has a read end and a write end. We need to be
|
|
6460
|
+
// able to read from the read end after write end is closed.
|
|
6461
|
+
refcnt: 2,
|
|
6462
|
+
timestamp: new Date(),
|
|
6463
|
+
};
|
|
6464
|
+
pipe.buckets.push({
|
|
6465
|
+
buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
|
|
6466
|
+
offset: 0,
|
|
6467
|
+
roffset: 0,
|
|
6468
|
+
});
|
|
6469
|
+
var rName = PIPEFS.nextname();
|
|
6470
|
+
var wName = PIPEFS.nextname();
|
|
6471
|
+
var rNode = FS.createNode(PIPEFS.root, rName, 4096, 0);
|
|
6472
|
+
var wNode = FS.createNode(PIPEFS.root, wName, 4096, 0);
|
|
6473
|
+
rNode.pipe = pipe;
|
|
6474
|
+
wNode.pipe = pipe;
|
|
6475
|
+
var readableStream = FS.createStream({
|
|
6476
|
+
path: rName,
|
|
6477
|
+
node: rNode,
|
|
6478
|
+
flags: 0,
|
|
6479
|
+
seekable: false,
|
|
6480
|
+
stream_ops: PIPEFS.stream_ops,
|
|
6481
|
+
});
|
|
6482
|
+
rNode.stream = readableStream;
|
|
6483
|
+
var writableStream = FS.createStream({
|
|
6484
|
+
path: wName,
|
|
6485
|
+
node: wNode,
|
|
6486
|
+
flags: 1,
|
|
6487
|
+
seekable: false,
|
|
6488
|
+
stream_ops: PIPEFS.stream_ops,
|
|
6489
|
+
});
|
|
6490
|
+
wNode.stream = writableStream;
|
|
6491
|
+
return {
|
|
6492
|
+
readable_fd: readableStream.fd,
|
|
6493
|
+
writable_fd: writableStream.fd,
|
|
6494
|
+
};
|
|
6495
|
+
},
|
|
6496
|
+
stream_ops: {
|
|
6497
|
+
getattr(stream) {
|
|
6498
|
+
var node = stream.node;
|
|
6499
|
+
var timestamp = node.pipe.timestamp;
|
|
6500
|
+
return {
|
|
6501
|
+
dev: 14,
|
|
6502
|
+
ino: node.id,
|
|
6503
|
+
mode: 4480,
|
|
6504
|
+
nlink: 1,
|
|
6505
|
+
uid: 0,
|
|
6506
|
+
gid: 0,
|
|
6507
|
+
rdev: 0,
|
|
6508
|
+
size: 0,
|
|
6509
|
+
atime: timestamp,
|
|
6510
|
+
mtime: timestamp,
|
|
6511
|
+
ctime: timestamp,
|
|
6512
|
+
blksize: 4096,
|
|
6513
|
+
blocks: 0,
|
|
6514
|
+
};
|
|
6515
|
+
},
|
|
6516
|
+
poll(stream) {
|
|
6517
|
+
var pipe = stream.node.pipe;
|
|
6518
|
+
if ((stream.flags & 2097155) === 1) {
|
|
6519
|
+
return 256 | 4;
|
|
6520
|
+
}
|
|
6521
|
+
for (var bucket of pipe.buckets) {
|
|
6522
|
+
if (bucket.offset - bucket.roffset > 0) {
|
|
6523
|
+
return 64 | 1;
|
|
6524
|
+
}
|
|
6525
|
+
}
|
|
6526
|
+
return 0;
|
|
6527
|
+
},
|
|
6528
|
+
dup(stream) {
|
|
6529
|
+
stream.node.pipe.refcnt++;
|
|
6530
|
+
},
|
|
6531
|
+
ioctl(stream, request, varargs) {
|
|
6532
|
+
return 28;
|
|
6533
|
+
},
|
|
6534
|
+
fsync(stream) {
|
|
6535
|
+
return 28;
|
|
6536
|
+
},
|
|
6537
|
+
read(stream, buffer, offset, length, position) {
|
|
6538
|
+
var pipe = stream.node.pipe;
|
|
6539
|
+
var currentLength = 0;
|
|
6540
|
+
for (var bucket of pipe.buckets) {
|
|
6541
|
+
currentLength += bucket.offset - bucket.roffset;
|
|
6542
|
+
}
|
|
6543
|
+
var data = buffer.subarray(offset, offset + length);
|
|
6544
|
+
if (length <= 0) {
|
|
6545
|
+
return 0;
|
|
6546
|
+
}
|
|
6547
|
+
if (currentLength == 0) {
|
|
6548
|
+
// Behave as if the read end is always non-blocking
|
|
6549
|
+
throw new FS.ErrnoError(6);
|
|
6550
|
+
}
|
|
6551
|
+
var toRead = Math.min(currentLength, length);
|
|
6552
|
+
var totalRead = toRead;
|
|
6553
|
+
var toRemove = 0;
|
|
6554
|
+
for (var bucket of pipe.buckets) {
|
|
6555
|
+
var bucketSize = bucket.offset - bucket.roffset;
|
|
6556
|
+
if (toRead <= bucketSize) {
|
|
6557
|
+
var tmpSlice = bucket.buffer.subarray(
|
|
6558
|
+
bucket.roffset,
|
|
6559
|
+
bucket.offset
|
|
6560
|
+
);
|
|
6561
|
+
if (toRead < bucketSize) {
|
|
6562
|
+
tmpSlice = tmpSlice.subarray(0, toRead);
|
|
6563
|
+
bucket.roffset += toRead;
|
|
6564
|
+
} else {
|
|
6565
|
+
toRemove++;
|
|
6566
|
+
}
|
|
6567
|
+
data.set(tmpSlice);
|
|
6568
|
+
break;
|
|
6569
|
+
} else {
|
|
6570
|
+
var tmpSlice = bucket.buffer.subarray(
|
|
6571
|
+
bucket.roffset,
|
|
6572
|
+
bucket.offset
|
|
6573
|
+
);
|
|
6574
|
+
data.set(tmpSlice);
|
|
6575
|
+
data = data.subarray(tmpSlice.byteLength);
|
|
6576
|
+
toRead -= tmpSlice.byteLength;
|
|
6577
|
+
toRemove++;
|
|
6578
|
+
}
|
|
6579
|
+
}
|
|
6580
|
+
if (toRemove && toRemove == pipe.buckets.length) {
|
|
6581
|
+
// Do not generate excessive garbage in use cases such as
|
|
6582
|
+
// write several bytes, read everything, write several bytes, read everything...
|
|
6583
|
+
toRemove--;
|
|
6584
|
+
pipe.buckets[toRemove].offset = 0;
|
|
6585
|
+
pipe.buckets[toRemove].roffset = 0;
|
|
6586
|
+
}
|
|
6587
|
+
pipe.buckets.splice(0, toRemove);
|
|
6588
|
+
return totalRead;
|
|
6589
|
+
},
|
|
6590
|
+
write(stream, buffer, offset, length, position) {
|
|
6591
|
+
var pipe = stream.node.pipe;
|
|
6592
|
+
var data = buffer.subarray(offset, offset + length);
|
|
6593
|
+
var dataLen = data.byteLength;
|
|
6594
|
+
if (dataLen <= 0) {
|
|
6595
|
+
return 0;
|
|
6596
|
+
}
|
|
6597
|
+
var currBucket = null;
|
|
6598
|
+
if (pipe.buckets.length == 0) {
|
|
6599
|
+
currBucket = {
|
|
6600
|
+
buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
|
|
6601
|
+
offset: 0,
|
|
6602
|
+
roffset: 0,
|
|
6603
|
+
};
|
|
6604
|
+
pipe.buckets.push(currBucket);
|
|
6605
|
+
} else {
|
|
6606
|
+
currBucket = pipe.buckets[pipe.buckets.length - 1];
|
|
6607
|
+
}
|
|
6608
|
+
assert(currBucket.offset <= PIPEFS.BUCKET_BUFFER_SIZE);
|
|
6609
|
+
var freeBytesInCurrBuffer =
|
|
6610
|
+
PIPEFS.BUCKET_BUFFER_SIZE - currBucket.offset;
|
|
6611
|
+
if (freeBytesInCurrBuffer >= dataLen) {
|
|
6612
|
+
currBucket.buffer.set(data, currBucket.offset);
|
|
6613
|
+
currBucket.offset += dataLen;
|
|
6614
|
+
return dataLen;
|
|
6615
|
+
} else if (freeBytesInCurrBuffer > 0) {
|
|
6616
|
+
currBucket.buffer.set(
|
|
6617
|
+
data.subarray(0, freeBytesInCurrBuffer),
|
|
6618
|
+
currBucket.offset
|
|
6619
|
+
);
|
|
6620
|
+
currBucket.offset += freeBytesInCurrBuffer;
|
|
6621
|
+
data = data.subarray(
|
|
6622
|
+
freeBytesInCurrBuffer,
|
|
6623
|
+
data.byteLength
|
|
6624
|
+
);
|
|
6625
|
+
}
|
|
6626
|
+
var numBuckets =
|
|
6627
|
+
(data.byteLength / PIPEFS.BUCKET_BUFFER_SIZE) | 0;
|
|
6628
|
+
var remElements = data.byteLength % PIPEFS.BUCKET_BUFFER_SIZE;
|
|
6629
|
+
for (var i = 0; i < numBuckets; i++) {
|
|
6630
|
+
var newBucket = {
|
|
6631
|
+
buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
|
|
6632
|
+
offset: PIPEFS.BUCKET_BUFFER_SIZE,
|
|
6633
|
+
roffset: 0,
|
|
6634
|
+
};
|
|
6635
|
+
pipe.buckets.push(newBucket);
|
|
6636
|
+
newBucket.buffer.set(
|
|
6637
|
+
data.subarray(0, PIPEFS.BUCKET_BUFFER_SIZE)
|
|
6638
|
+
);
|
|
6639
|
+
data = data.subarray(
|
|
6640
|
+
PIPEFS.BUCKET_BUFFER_SIZE,
|
|
6641
|
+
data.byteLength
|
|
6642
|
+
);
|
|
6643
|
+
}
|
|
6644
|
+
if (remElements > 0) {
|
|
6645
|
+
var newBucket = {
|
|
6646
|
+
buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
|
|
6647
|
+
offset: data.byteLength,
|
|
6648
|
+
roffset: 0,
|
|
6649
|
+
};
|
|
6650
|
+
pipe.buckets.push(newBucket);
|
|
6651
|
+
newBucket.buffer.set(data);
|
|
6652
|
+
}
|
|
6653
|
+
return dataLen;
|
|
6654
|
+
},
|
|
6655
|
+
close(stream) {
|
|
6656
|
+
var pipe = stream.node.pipe;
|
|
6657
|
+
pipe.refcnt--;
|
|
6658
|
+
if (pipe.refcnt === 0) {
|
|
6659
|
+
pipe.buckets = null;
|
|
6660
|
+
}
|
|
6661
|
+
},
|
|
6662
|
+
},
|
|
6663
|
+
nextname() {
|
|
6664
|
+
if (!PIPEFS.nextname.current) {
|
|
6665
|
+
PIPEFS.nextname.current = 0;
|
|
6225
6666
|
}
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
})();
|
|
6229
|
-
return BigInt(ret);
|
|
6667
|
+
return 'pipe[' + PIPEFS.nextname.current++ + ']';
|
|
6668
|
+
},
|
|
6230
6669
|
};
|
|
6231
6670
|
|
|
6232
|
-
function
|
|
6233
|
-
offset = bigintToI53Checked(offset);
|
|
6234
|
-
try {
|
|
6235
|
-
if (isNaN(offset)) return 61;
|
|
6236
|
-
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
6237
|
-
var res = FS.mmap(stream, len, offset, prot, flags);
|
|
6238
|
-
var ptr = res.ptr;
|
|
6239
|
-
HEAP32[allocated >> 2] = res.allocated;
|
|
6240
|
-
HEAPU32[addr >> 2] = ptr;
|
|
6241
|
-
return 0;
|
|
6242
|
-
} catch (e) {
|
|
6243
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6244
|
-
return -e.errno;
|
|
6245
|
-
}
|
|
6246
|
-
}
|
|
6247
|
-
|
|
6248
|
-
function __munmap_js(addr, len, prot, flags, fd, offset) {
|
|
6249
|
-
offset = bigintToI53Checked(offset);
|
|
6671
|
+
function ___syscall_pipe(fdPtr) {
|
|
6250
6672
|
try {
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
SYSCALLS.doMsync(addr, stream, len, flags, offset);
|
|
6673
|
+
if (fdPtr == 0) {
|
|
6674
|
+
throw new FS.ErrnoError(21);
|
|
6254
6675
|
}
|
|
6676
|
+
var res = PIPEFS.createPipe();
|
|
6677
|
+
HEAP32[fdPtr >> 2] = res.readable_fd;
|
|
6678
|
+
HEAP32[(fdPtr + 4) >> 2] = res.writable_fd;
|
|
6679
|
+
return 0;
|
|
6255
6680
|
} catch (e) {
|
|
6256
6681
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6257
6682
|
return -e.errno;
|
|
6258
6683
|
}
|
|
6259
6684
|
}
|
|
6260
6685
|
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
var handleException = (e) => {
|
|
6264
|
-
// Certain exception types we do not treat as errors since they are used for
|
|
6265
|
-
// internal control flow.
|
|
6266
|
-
// 1. ExitStatus, which is thrown by exit()
|
|
6267
|
-
// 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
|
|
6268
|
-
// that wish to return to JS event loop.
|
|
6269
|
-
if (e instanceof ExitStatus || e == 'unwind') {
|
|
6270
|
-
return EXITSTATUS;
|
|
6271
|
-
}
|
|
6272
|
-
quit_(1, e);
|
|
6273
|
-
};
|
|
6274
|
-
|
|
6275
|
-
var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
|
|
6276
|
-
|
|
6277
|
-
var _proc_exit = (code) => {
|
|
6278
|
-
EXITSTATUS = code;
|
|
6279
|
-
if (!keepRuntimeAlive()) {
|
|
6280
|
-
Module['onExit']?.(code);
|
|
6281
|
-
ABORT = true;
|
|
6282
|
-
}
|
|
6283
|
-
quit_(code, new ExitStatus(code));
|
|
6284
|
-
};
|
|
6285
|
-
|
|
6286
|
-
/** @suppress {duplicate } */ /** @param {boolean|number=} implicit */ var exitJS =
|
|
6287
|
-
(status, implicit) => {
|
|
6288
|
-
EXITSTATUS = status;
|
|
6289
|
-
if (!keepRuntimeAlive()) {
|
|
6290
|
-
exitRuntime();
|
|
6291
|
-
}
|
|
6292
|
-
_proc_exit(status);
|
|
6293
|
-
};
|
|
6294
|
-
|
|
6295
|
-
var _exit = exitJS;
|
|
6296
|
-
|
|
6297
|
-
Module['_exit'] = _exit;
|
|
6298
|
-
|
|
6299
|
-
var maybeExit = () => {
|
|
6300
|
-
if (runtimeExited) {
|
|
6301
|
-
return;
|
|
6302
|
-
}
|
|
6303
|
-
if (!keepRuntimeAlive()) {
|
|
6304
|
-
try {
|
|
6305
|
-
_exit(EXITSTATUS);
|
|
6306
|
-
} catch (e) {
|
|
6307
|
-
handleException(e);
|
|
6308
|
-
}
|
|
6309
|
-
}
|
|
6310
|
-
};
|
|
6311
|
-
|
|
6312
|
-
var callUserCallback = (func) => {
|
|
6313
|
-
if (runtimeExited || ABORT) {
|
|
6314
|
-
return;
|
|
6315
|
-
}
|
|
6316
|
-
try {
|
|
6317
|
-
func();
|
|
6318
|
-
maybeExit();
|
|
6319
|
-
} catch (e) {
|
|
6320
|
-
handleException(e);
|
|
6321
|
-
}
|
|
6322
|
-
};
|
|
6323
|
-
|
|
6324
|
-
var _emscripten_get_now = () => performance.now();
|
|
6325
|
-
|
|
6326
|
-
var __setitimer_js = (which, timeout_ms) => {
|
|
6327
|
-
// First, clear any existing timer.
|
|
6328
|
-
if (timers[which]) {
|
|
6329
|
-
clearTimeout(timers[which].id);
|
|
6330
|
-
delete timers[which];
|
|
6331
|
-
}
|
|
6332
|
-
// A timeout of zero simply cancels the current timeout so we have nothing
|
|
6333
|
-
// more to do.
|
|
6334
|
-
if (!timeout_ms) return 0;
|
|
6335
|
-
var id = setTimeout(() => {
|
|
6336
|
-
delete timers[which];
|
|
6337
|
-
callUserCallback(() =>
|
|
6338
|
-
__emscripten_timeout(which, _emscripten_get_now())
|
|
6339
|
-
);
|
|
6340
|
-
}, timeout_ms);
|
|
6341
|
-
timers[which] = {
|
|
6342
|
-
id,
|
|
6343
|
-
timeout_ms,
|
|
6344
|
-
};
|
|
6345
|
-
return 0;
|
|
6346
|
-
};
|
|
6347
|
-
|
|
6348
|
-
var __tzset_js = (timezone, daylight, std_name, dst_name) => {
|
|
6349
|
-
// TODO: Use (malleable) environment variables instead of system settings.
|
|
6350
|
-
var currentYear = new Date().getFullYear();
|
|
6351
|
-
var winter = new Date(currentYear, 0, 1);
|
|
6352
|
-
var summer = new Date(currentYear, 6, 1);
|
|
6353
|
-
var winterOffset = winter.getTimezoneOffset();
|
|
6354
|
-
var summerOffset = summer.getTimezoneOffset();
|
|
6355
|
-
// Local standard timezone offset. Local standard time is not adjusted for
|
|
6356
|
-
// daylight savings. This code uses the fact that getTimezoneOffset returns
|
|
6357
|
-
// a greater value during Standard Time versus Daylight Saving Time (DST).
|
|
6358
|
-
// Thus it determines the expected output during Standard Time, and it
|
|
6359
|
-
// compares whether the output of the given date the same (Standard) or less
|
|
6360
|
-
// (DST).
|
|
6361
|
-
var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
|
|
6362
|
-
// timezone is specified as seconds west of UTC ("The external variable
|
|
6363
|
-
// `timezone` shall be set to the difference, in seconds, between
|
|
6364
|
-
// Coordinated Universal Time (UTC) and local standard time."), the same
|
|
6365
|
-
// as returned by stdTimezoneOffset.
|
|
6366
|
-
// See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html
|
|
6367
|
-
HEAPU32[timezone >> 2] = stdTimezoneOffset * 60;
|
|
6368
|
-
HEAP32[daylight >> 2] = Number(winterOffset != summerOffset);
|
|
6369
|
-
var extractZone = (timezoneOffset) => {
|
|
6370
|
-
// Why inverse sign?
|
|
6371
|
-
// Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
|
|
6372
|
-
var sign = timezoneOffset >= 0 ? '-' : '+';
|
|
6373
|
-
var absOffset = Math.abs(timezoneOffset);
|
|
6374
|
-
var hours = String(Math.floor(absOffset / 60)).padStart(2, '0');
|
|
6375
|
-
var minutes = String(absOffset % 60).padStart(2, '0');
|
|
6376
|
-
return `UTC${sign}${hours}${minutes}`;
|
|
6377
|
-
};
|
|
6378
|
-
var winterName = extractZone(winterOffset);
|
|
6379
|
-
var summerName = extractZone(summerOffset);
|
|
6380
|
-
if (summerOffset < winterOffset) {
|
|
6381
|
-
// Northern hemisphere
|
|
6382
|
-
stringToUTF8(winterName, std_name, 17);
|
|
6383
|
-
stringToUTF8(summerName, dst_name, 17);
|
|
6384
|
-
} else {
|
|
6385
|
-
stringToUTF8(winterName, dst_name, 17);
|
|
6386
|
-
stringToUTF8(summerName, std_name, 17);
|
|
6387
|
-
}
|
|
6388
|
-
};
|
|
6389
|
-
|
|
6390
|
-
var _emscripten_date_now = () => Date.now();
|
|
6391
|
-
|
|
6392
|
-
var nowIsMonotonic = 1;
|
|
6393
|
-
|
|
6394
|
-
var checkWasiClock = (clock_id) => clock_id >= 0 && clock_id <= 3;
|
|
6395
|
-
|
|
6396
|
-
function _clock_time_get(clk_id, ignored_precision, ptime) {
|
|
6397
|
-
ignored_precision = bigintToI53Checked(ignored_precision);
|
|
6398
|
-
if (!checkWasiClock(clk_id)) {
|
|
6399
|
-
return 28;
|
|
6400
|
-
}
|
|
6401
|
-
var now;
|
|
6402
|
-
// all wasi clocks but realtime are monotonic
|
|
6403
|
-
if (clk_id === 0) {
|
|
6404
|
-
now = _emscripten_date_now();
|
|
6405
|
-
} else if (nowIsMonotonic) {
|
|
6406
|
-
now = _emscripten_get_now();
|
|
6407
|
-
} else {
|
|
6408
|
-
return 52;
|
|
6409
|
-
}
|
|
6410
|
-
// "now" is in ms, and wasi times are in ns.
|
|
6411
|
-
var nsec = Math.round(now * 1e3 * 1e3);
|
|
6412
|
-
HEAP64[ptime >> 3] = BigInt(nsec);
|
|
6413
|
-
return 0;
|
|
6414
|
-
}
|
|
6415
|
-
|
|
6416
|
-
var getHeapMax = () =>
|
|
6417
|
-
// Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
|
|
6418
|
-
// full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
|
|
6419
|
-
// for any code that deals with heap sizes, which would require special
|
|
6420
|
-
// casing all heap size related code to treat 0 specially.
|
|
6421
|
-
2147483648;
|
|
6422
|
-
|
|
6423
|
-
var _emscripten_get_heap_max = () => getHeapMax();
|
|
6424
|
-
|
|
6425
|
-
var growMemory = (size) => {
|
|
6426
|
-
var b = wasmMemory.buffer;
|
|
6427
|
-
var pages = ((size - b.byteLength + 65535) / 65536) | 0;
|
|
6686
|
+
function ___syscall_poll(fds, nfds, timeout) {
|
|
6428
6687
|
try {
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6688
|
+
var nonzero = 0;
|
|
6689
|
+
for (var i = 0; i < nfds; i++) {
|
|
6690
|
+
var pollfd = fds + 8 * i;
|
|
6691
|
+
var fd = HEAP32[pollfd >> 2];
|
|
6692
|
+
var events = HEAP16[(pollfd + 4) >> 1];
|
|
6693
|
+
var mask = 32;
|
|
6694
|
+
var stream = FS.getStream(fd);
|
|
6695
|
+
if (stream) {
|
|
6696
|
+
mask = SYSCALLS.DEFAULT_POLLMASK;
|
|
6697
|
+
if (stream.stream_ops?.poll) {
|
|
6698
|
+
mask = stream.stream_ops.poll(stream, -1);
|
|
6699
|
+
}
|
|
6700
|
+
}
|
|
6701
|
+
mask &= events | 8 | 16;
|
|
6702
|
+
if (mask) nonzero++;
|
|
6703
|
+
HEAP16[(pollfd + 6) >> 1] = mask;
|
|
6704
|
+
}
|
|
6705
|
+
return nonzero;
|
|
6706
|
+
} catch (e) {
|
|
6707
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6708
|
+
return -e.errno;
|
|
6709
|
+
}
|
|
6710
|
+
}
|
|
6436
6711
|
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
// 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
|
|
6454
|
-
// MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
|
|
6455
|
-
// 4. If we were unable to allocate as much memory, it may be due to
|
|
6456
|
-
// over-eager decision to excessively reserve due to (3) above.
|
|
6457
|
-
// Hence if an allocation fails, cut down on the amount of excess
|
|
6458
|
-
// growth, in an attempt to succeed to perform a smaller allocation.
|
|
6459
|
-
// A limit is set for how much we can grow. We should not exceed that
|
|
6460
|
-
// (the wasm binary specifies it, so if we tried, we'd fail anyhow).
|
|
6461
|
-
var maxHeapSize = getHeapMax();
|
|
6462
|
-
if (requestedSize > maxHeapSize) {
|
|
6463
|
-
return false;
|
|
6712
|
+
function ___syscall_readlinkat(dirfd, path, buf, bufsize) {
|
|
6713
|
+
try {
|
|
6714
|
+
path = SYSCALLS.getStr(path);
|
|
6715
|
+
path = SYSCALLS.calculateAt(dirfd, path);
|
|
6716
|
+
if (bufsize <= 0) return -28;
|
|
6717
|
+
var ret = FS.readlink(path);
|
|
6718
|
+
var len = Math.min(bufsize, lengthBytesUTF8(ret));
|
|
6719
|
+
var endChar = HEAP8[buf + len];
|
|
6720
|
+
stringToUTF8(ret, buf, bufsize + 1);
|
|
6721
|
+
// readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!)
|
|
6722
|
+
// stringToUTF8() always appends a null byte, so restore the character under the null byte after the write.
|
|
6723
|
+
HEAP8[buf + len] = endChar;
|
|
6724
|
+
return len;
|
|
6725
|
+
} catch (e) {
|
|
6726
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6727
|
+
return -e.errno;
|
|
6464
6728
|
}
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
var
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
requestedSize + 100663296
|
|
6475
|
-
);
|
|
6476
|
-
var newSize = Math.min(
|
|
6477
|
-
maxHeapSize,
|
|
6478
|
-
alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536)
|
|
6729
|
+
}
|
|
6730
|
+
|
|
6731
|
+
function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) {
|
|
6732
|
+
try {
|
|
6733
|
+
var sock = getSocketFromFD(fd);
|
|
6734
|
+
var msg = sock.sock_ops.recvmsg(
|
|
6735
|
+
sock,
|
|
6736
|
+
len,
|
|
6737
|
+
typeof flags !== 'undefined' ? flags : 0
|
|
6479
6738
|
);
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6739
|
+
if (!msg) return 0;
|
|
6740
|
+
// socket is closed
|
|
6741
|
+
if (addr) {
|
|
6742
|
+
var errno = writeSockaddr(
|
|
6743
|
+
addr,
|
|
6744
|
+
sock.family,
|
|
6745
|
+
DNS.lookup_name(msg.addr),
|
|
6746
|
+
msg.port,
|
|
6747
|
+
addrlen
|
|
6748
|
+
);
|
|
6483
6749
|
}
|
|
6750
|
+
HEAPU8.set(msg.buffer, buf);
|
|
6751
|
+
return msg.buffer.byteLength;
|
|
6752
|
+
} catch (e) {
|
|
6753
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6754
|
+
return -e.errno;
|
|
6484
6755
|
}
|
|
6485
|
-
|
|
6486
|
-
};
|
|
6487
|
-
|
|
6488
|
-
var runtimeKeepalivePush = () => {
|
|
6489
|
-
runtimeKeepaliveCounter += 1;
|
|
6490
|
-
};
|
|
6491
|
-
|
|
6492
|
-
var runtimeKeepalivePop = () => {
|
|
6493
|
-
runtimeKeepaliveCounter -= 1;
|
|
6494
|
-
};
|
|
6495
|
-
|
|
6496
|
-
/** @param {number=} timeout */ var safeSetTimeout = (func, timeout) => {
|
|
6497
|
-
runtimeKeepalivePush();
|
|
6498
|
-
return setTimeout(() => {
|
|
6499
|
-
runtimeKeepalivePop();
|
|
6500
|
-
callUserCallback(func);
|
|
6501
|
-
}, timeout);
|
|
6502
|
-
};
|
|
6503
|
-
|
|
6504
|
-
var _emscripten_sleep = (ms) =>
|
|
6505
|
-
Asyncify.handleSleep((wakeUp) => safeSetTimeout(wakeUp, ms));
|
|
6506
|
-
|
|
6507
|
-
Module['_emscripten_sleep'] = _emscripten_sleep;
|
|
6508
|
-
|
|
6509
|
-
_emscripten_sleep.isAsync = true;
|
|
6756
|
+
}
|
|
6510
6757
|
|
|
6511
|
-
|
|
6758
|
+
function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
|
|
6759
|
+
try {
|
|
6760
|
+
oldpath = SYSCALLS.getStr(oldpath);
|
|
6761
|
+
newpath = SYSCALLS.getStr(newpath);
|
|
6762
|
+
oldpath = SYSCALLS.calculateAt(olddirfd, oldpath);
|
|
6763
|
+
newpath = SYSCALLS.calculateAt(newdirfd, newpath);
|
|
6764
|
+
FS.rename(oldpath, newpath);
|
|
6765
|
+
return 0;
|
|
6766
|
+
} catch (e) {
|
|
6767
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6768
|
+
return -e.errno;
|
|
6769
|
+
}
|
|
6770
|
+
}
|
|
6512
6771
|
|
|
6513
|
-
|
|
6772
|
+
function ___syscall_rmdir(path) {
|
|
6773
|
+
try {
|
|
6774
|
+
path = SYSCALLS.getStr(path);
|
|
6775
|
+
FS.rmdir(path);
|
|
6776
|
+
return 0;
|
|
6777
|
+
} catch (e) {
|
|
6778
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6779
|
+
return -e.errno;
|
|
6780
|
+
}
|
|
6781
|
+
}
|
|
6514
6782
|
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
(
|
|
6521
|
-
(typeof navigator == 'object' &&
|
|
6522
|
-
navigator.languages &&
|
|
6523
|
-
navigator.languages[0]) ||
|
|
6524
|
-
'C'
|
|
6525
|
-
).replace('-', '_') + '.UTF-8';
|
|
6526
|
-
var env = {
|
|
6527
|
-
USER: 'web_user',
|
|
6528
|
-
LOGNAME: 'web_user',
|
|
6529
|
-
PATH: '/',
|
|
6530
|
-
PWD: '/',
|
|
6531
|
-
HOME: '/home/web_user',
|
|
6532
|
-
LANG: lang,
|
|
6533
|
-
_: getExecutableName(),
|
|
6534
|
-
};
|
|
6535
|
-
// Apply the user-provided values, if any.
|
|
6536
|
-
for (var x in ENV) {
|
|
6537
|
-
// x is a key in ENV; if ENV[x] is undefined, that means it was
|
|
6538
|
-
// explicitly set to be so. We allow user code to do that to
|
|
6539
|
-
// force variables with default values to remain unset.
|
|
6540
|
-
if (ENV[x] === undefined) delete env[x];
|
|
6541
|
-
else env[x] = ENV[x];
|
|
6542
|
-
}
|
|
6543
|
-
var strings = [];
|
|
6544
|
-
for (var x in env) {
|
|
6545
|
-
strings.push(`${x}=${env[x]}`);
|
|
6783
|
+
function ___syscall_sendto(fd, message, length, flags, addr, addr_len) {
|
|
6784
|
+
try {
|
|
6785
|
+
var sock = getSocketFromFD(fd);
|
|
6786
|
+
if (!addr) {
|
|
6787
|
+
// send, no address provided
|
|
6788
|
+
return FS.write(sock.stream, HEAP8, message, length);
|
|
6546
6789
|
}
|
|
6547
|
-
|
|
6790
|
+
var dest = getSocketAddress(addr, addr_len);
|
|
6791
|
+
// sendto an address
|
|
6792
|
+
return sock.sock_ops.sendmsg(
|
|
6793
|
+
sock,
|
|
6794
|
+
HEAP8,
|
|
6795
|
+
message,
|
|
6796
|
+
length,
|
|
6797
|
+
dest.addr,
|
|
6798
|
+
dest.port
|
|
6799
|
+
);
|
|
6800
|
+
} catch (e) {
|
|
6801
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6802
|
+
return -e.errno;
|
|
6548
6803
|
}
|
|
6549
|
-
|
|
6550
|
-
};
|
|
6804
|
+
}
|
|
6551
6805
|
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6806
|
+
function ___syscall_socket(domain, type, protocol) {
|
|
6807
|
+
try {
|
|
6808
|
+
var sock = SOCKFS.createSocket(domain, type, protocol);
|
|
6809
|
+
return sock.stream.fd;
|
|
6810
|
+
} catch (e) {
|
|
6811
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6812
|
+
return -e.errno;
|
|
6813
|
+
}
|
|
6814
|
+
}
|
|
6815
|
+
|
|
6816
|
+
function ___syscall_stat64(path, buf) {
|
|
6817
|
+
try {
|
|
6818
|
+
path = SYSCALLS.getStr(path);
|
|
6819
|
+
return SYSCALLS.writeStat(buf, FS.stat(path));
|
|
6820
|
+
} catch (e) {
|
|
6821
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6822
|
+
return -e.errno;
|
|
6555
6823
|
}
|
|
6556
|
-
|
|
6557
|
-
HEAP8[buffer] = 0;
|
|
6558
|
-
};
|
|
6824
|
+
}
|
|
6559
6825
|
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
}
|
|
6568
|
-
|
|
6569
|
-
};
|
|
6826
|
+
function ___syscall_statfs64(path, size, buf) {
|
|
6827
|
+
try {
|
|
6828
|
+
SYSCALLS.writeStatFs(buf, FS.statfs(SYSCALLS.getStr(path)));
|
|
6829
|
+
return 0;
|
|
6830
|
+
} catch (e) {
|
|
6831
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6832
|
+
return -e.errno;
|
|
6833
|
+
}
|
|
6834
|
+
}
|
|
6570
6835
|
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6836
|
+
function ___syscall_symlinkat(target, dirfd, linkpath) {
|
|
6837
|
+
try {
|
|
6838
|
+
target = SYSCALLS.getStr(target);
|
|
6839
|
+
linkpath = SYSCALLS.getStr(linkpath);
|
|
6840
|
+
linkpath = SYSCALLS.calculateAt(dirfd, linkpath);
|
|
6841
|
+
FS.symlink(target, linkpath);
|
|
6842
|
+
return 0;
|
|
6843
|
+
} catch (e) {
|
|
6844
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6845
|
+
return -e.errno;
|
|
6846
|
+
}
|
|
6847
|
+
}
|
|
6579
6848
|
|
|
6580
|
-
function
|
|
6849
|
+
function ___syscall_unlinkat(dirfd, path, flags) {
|
|
6581
6850
|
try {
|
|
6582
|
-
|
|
6583
|
-
|
|
6851
|
+
path = SYSCALLS.getStr(path);
|
|
6852
|
+
path = SYSCALLS.calculateAt(dirfd, path);
|
|
6853
|
+
if (flags === 0) {
|
|
6854
|
+
FS.unlink(path);
|
|
6855
|
+
} else if (flags === 512) {
|
|
6856
|
+
FS.rmdir(path);
|
|
6857
|
+
} else {
|
|
6858
|
+
abort('Invalid flags passed to unlinkat');
|
|
6859
|
+
}
|
|
6584
6860
|
return 0;
|
|
6585
6861
|
} catch (e) {
|
|
6586
6862
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6587
|
-
return e.errno;
|
|
6863
|
+
return -e.errno;
|
|
6588
6864
|
}
|
|
6589
6865
|
}
|
|
6590
6866
|
|
|
6591
|
-
|
|
6867
|
+
var readI53FromI64 = (ptr) =>
|
|
6868
|
+
HEAPU32[ptr >> 2] + HEAP32[(ptr + 4) >> 2] * 4294967296;
|
|
6869
|
+
|
|
6870
|
+
function ___syscall_utimensat(dirfd, path, times, flags) {
|
|
6592
6871
|
try {
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
var
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6872
|
+
path = SYSCALLS.getStr(path);
|
|
6873
|
+
path = SYSCALLS.calculateAt(dirfd, path, true);
|
|
6874
|
+
var now = Date.now(),
|
|
6875
|
+
atime,
|
|
6876
|
+
mtime;
|
|
6877
|
+
if (!times) {
|
|
6878
|
+
atime = now;
|
|
6879
|
+
mtime = now;
|
|
6880
|
+
} else {
|
|
6881
|
+
var seconds = readI53FromI64(times);
|
|
6882
|
+
var nanoseconds = HEAP32[(times + 8) >> 2];
|
|
6883
|
+
if (nanoseconds == 1073741823) {
|
|
6884
|
+
atime = now;
|
|
6885
|
+
} else if (nanoseconds == 1073741822) {
|
|
6886
|
+
atime = null;
|
|
6887
|
+
} else {
|
|
6888
|
+
atime = seconds * 1e3 + nanoseconds / (1e3 * 1e3);
|
|
6889
|
+
}
|
|
6890
|
+
times += 16;
|
|
6891
|
+
seconds = readI53FromI64(times);
|
|
6892
|
+
nanoseconds = HEAP32[(times + 8) >> 2];
|
|
6893
|
+
if (nanoseconds == 1073741823) {
|
|
6894
|
+
mtime = now;
|
|
6895
|
+
} else if (nanoseconds == 1073741822) {
|
|
6896
|
+
mtime = null;
|
|
6897
|
+
} else {
|
|
6898
|
+
mtime = seconds * 1e3 + nanoseconds / (1e3 * 1e3);
|
|
6899
|
+
}
|
|
6900
|
+
}
|
|
6901
|
+
// null here means UTIME_OMIT was passed. If both were set to UTIME_OMIT then
|
|
6902
|
+
// we can skip the call completely.
|
|
6903
|
+
if ((mtime ?? atime) !== null) {
|
|
6904
|
+
FS.utime(path, atime, mtime);
|
|
6607
6905
|
}
|
|
6608
|
-
HEAP8[pbuf] = type;
|
|
6609
|
-
HEAP16[(pbuf + 2) >> 1] = flags;
|
|
6610
|
-
HEAP64[(pbuf + 8) >> 3] = BigInt(rightsBase);
|
|
6611
|
-
HEAP64[(pbuf + 16) >> 3] = BigInt(rightsInheriting);
|
|
6612
6906
|
return 0;
|
|
6613
6907
|
} catch (e) {
|
|
6614
6908
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6615
|
-
return e.errno;
|
|
6909
|
+
return -e.errno;
|
|
6616
6910
|
}
|
|
6617
6911
|
}
|
|
6618
6912
|
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6913
|
+
var __abort_js = () => abort('');
|
|
6914
|
+
|
|
6915
|
+
var __emscripten_lookup_name = (name) => {
|
|
6916
|
+
// uint32_t _emscripten_lookup_name(const char *name);
|
|
6917
|
+
var nameString = UTF8ToString(name);
|
|
6918
|
+
return inetPton4(DNS.lookup_name(nameString));
|
|
6919
|
+
};
|
|
6920
|
+
|
|
6921
|
+
var runtimeKeepaliveCounter = 0;
|
|
6922
|
+
|
|
6923
|
+
var __emscripten_runtime_keepalive_clear = () => {
|
|
6924
|
+
noExitRuntime = false;
|
|
6925
|
+
runtimeKeepaliveCounter = 0;
|
|
6926
|
+
};
|
|
6927
|
+
|
|
6928
|
+
function __gmtime_js(time, tmPtr) {
|
|
6929
|
+
time = bigintToI53Checked(time);
|
|
6930
|
+
var date = new Date(time * 1e3);
|
|
6931
|
+
HEAP32[tmPtr >> 2] = date.getUTCSeconds();
|
|
6932
|
+
HEAP32[(tmPtr + 4) >> 2] = date.getUTCMinutes();
|
|
6933
|
+
HEAP32[(tmPtr + 8) >> 2] = date.getUTCHours();
|
|
6934
|
+
HEAP32[(tmPtr + 12) >> 2] = date.getUTCDate();
|
|
6935
|
+
HEAP32[(tmPtr + 16) >> 2] = date.getUTCMonth();
|
|
6936
|
+
HEAP32[(tmPtr + 20) >> 2] = date.getUTCFullYear() - 1900;
|
|
6937
|
+
HEAP32[(tmPtr + 24) >> 2] = date.getUTCDay();
|
|
6938
|
+
var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
|
|
6939
|
+
var yday = ((date.getTime() - start) / (1e3 * 60 * 60 * 24)) | 0;
|
|
6940
|
+
HEAP32[(tmPtr + 28) >> 2] = yday;
|
|
6941
|
+
}
|
|
6942
|
+
|
|
6943
|
+
var isLeapYear = (year) =>
|
|
6944
|
+
year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
6945
|
+
|
|
6946
|
+
var MONTH_DAYS_LEAP_CUMULATIVE = [
|
|
6947
|
+
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
|
|
6948
|
+
];
|
|
6949
|
+
|
|
6950
|
+
var MONTH_DAYS_REGULAR_CUMULATIVE = [
|
|
6951
|
+
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
|
|
6952
|
+
];
|
|
6953
|
+
|
|
6954
|
+
var ydayFromDate = (date) => {
|
|
6955
|
+
var leap = isLeapYear(date.getFullYear());
|
|
6956
|
+
var monthDaysCumulative = leap
|
|
6957
|
+
? MONTH_DAYS_LEAP_CUMULATIVE
|
|
6958
|
+
: MONTH_DAYS_REGULAR_CUMULATIVE;
|
|
6959
|
+
var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1;
|
|
6960
|
+
// -1 since it's days since Jan 1
|
|
6961
|
+
return yday;
|
|
6962
|
+
};
|
|
6963
|
+
|
|
6964
|
+
function __localtime_js(time, tmPtr) {
|
|
6965
|
+
time = bigintToI53Checked(time);
|
|
6966
|
+
var date = new Date(time * 1e3);
|
|
6967
|
+
HEAP32[tmPtr >> 2] = date.getSeconds();
|
|
6968
|
+
HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
|
|
6969
|
+
HEAP32[(tmPtr + 8) >> 2] = date.getHours();
|
|
6970
|
+
HEAP32[(tmPtr + 12) >> 2] = date.getDate();
|
|
6971
|
+
HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
|
|
6972
|
+
HEAP32[(tmPtr + 20) >> 2] = date.getFullYear() - 1900;
|
|
6973
|
+
HEAP32[(tmPtr + 24) >> 2] = date.getDay();
|
|
6974
|
+
var yday = ydayFromDate(date) | 0;
|
|
6975
|
+
HEAP32[(tmPtr + 28) >> 2] = yday;
|
|
6976
|
+
HEAP32[(tmPtr + 36) >> 2] = -(date.getTimezoneOffset() * 60);
|
|
6977
|
+
// Attention: DST is in December in South, and some regions don't have DST at all.
|
|
6978
|
+
var start = new Date(date.getFullYear(), 0, 1);
|
|
6979
|
+
var summerOffset = new Date(
|
|
6980
|
+
date.getFullYear(),
|
|
6981
|
+
6,
|
|
6982
|
+
1
|
|
6983
|
+
).getTimezoneOffset();
|
|
6984
|
+
var winterOffset = start.getTimezoneOffset();
|
|
6985
|
+
var dst =
|
|
6986
|
+
(summerOffset != winterOffset &&
|
|
6987
|
+
date.getTimezoneOffset() ==
|
|
6988
|
+
Math.min(winterOffset, summerOffset)) | 0;
|
|
6989
|
+
HEAP32[(tmPtr + 32) >> 2] = dst;
|
|
6990
|
+
}
|
|
6991
|
+
|
|
6992
|
+
var __mktime_js = function (tmPtr) {
|
|
6993
|
+
var ret = (() => {
|
|
6994
|
+
var date = new Date(
|
|
6995
|
+
HEAP32[(tmPtr + 20) >> 2] + 1900,
|
|
6996
|
+
HEAP32[(tmPtr + 16) >> 2],
|
|
6997
|
+
HEAP32[(tmPtr + 12) >> 2],
|
|
6998
|
+
HEAP32[(tmPtr + 8) >> 2],
|
|
6999
|
+
HEAP32[(tmPtr + 4) >> 2],
|
|
7000
|
+
HEAP32[tmPtr >> 2],
|
|
7001
|
+
0
|
|
7002
|
+
);
|
|
7003
|
+
// There's an ambiguous hour when the time goes back; the tm_isdst field is
|
|
7004
|
+
// used to disambiguate it. Date() basically guesses, so we fix it up if it
|
|
7005
|
+
// guessed wrong, or fill in tm_isdst with the guess if it's -1.
|
|
7006
|
+
var dst = HEAP32[(tmPtr + 32) >> 2];
|
|
7007
|
+
var guessedOffset = date.getTimezoneOffset();
|
|
7008
|
+
var start = new Date(date.getFullYear(), 0, 1);
|
|
7009
|
+
var summerOffset = new Date(
|
|
7010
|
+
date.getFullYear(),
|
|
7011
|
+
6,
|
|
7012
|
+
1
|
|
7013
|
+
).getTimezoneOffset();
|
|
7014
|
+
var winterOffset = start.getTimezoneOffset();
|
|
7015
|
+
var dstOffset = Math.min(winterOffset, summerOffset);
|
|
7016
|
+
// DST is in December in South
|
|
7017
|
+
if (dst < 0) {
|
|
7018
|
+
// Attention: some regions don't have DST at all.
|
|
7019
|
+
HEAP32[(tmPtr + 32) >> 2] = Number(
|
|
7020
|
+
summerOffset != winterOffset && dstOffset == guessedOffset
|
|
7021
|
+
);
|
|
7022
|
+
} else if (dst > 0 != (dstOffset == guessedOffset)) {
|
|
7023
|
+
var nonDstOffset = Math.max(winterOffset, summerOffset);
|
|
7024
|
+
var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
|
|
7025
|
+
// Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
|
|
7026
|
+
date.setTime(
|
|
7027
|
+
date.getTime() + (trueOffset - guessedOffset) * 6e4
|
|
7028
|
+
);
|
|
7029
|
+
}
|
|
7030
|
+
HEAP32[(tmPtr + 24) >> 2] = date.getDay();
|
|
7031
|
+
var yday = ydayFromDate(date) | 0;
|
|
7032
|
+
HEAP32[(tmPtr + 28) >> 2] = yday;
|
|
7033
|
+
// To match expected behavior, update fields from date
|
|
7034
|
+
HEAP32[tmPtr >> 2] = date.getSeconds();
|
|
7035
|
+
HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
|
|
7036
|
+
HEAP32[(tmPtr + 8) >> 2] = date.getHours();
|
|
7037
|
+
HEAP32[(tmPtr + 12) >> 2] = date.getDate();
|
|
7038
|
+
HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
|
|
7039
|
+
HEAP32[(tmPtr + 20) >> 2] = date.getYear();
|
|
7040
|
+
var timeMs = date.getTime();
|
|
7041
|
+
if (isNaN(timeMs)) {
|
|
7042
|
+
return -1;
|
|
6637
7043
|
}
|
|
6638
|
-
|
|
6639
|
-
|
|
7044
|
+
// Return time in microseconds
|
|
7045
|
+
return timeMs / 1e3;
|
|
7046
|
+
})();
|
|
7047
|
+
return BigInt(ret);
|
|
6640
7048
|
};
|
|
6641
7049
|
|
|
6642
|
-
function
|
|
7050
|
+
function __mmap_js(len, prot, flags, fd, offset, allocated, addr) {
|
|
7051
|
+
offset = bigintToI53Checked(offset);
|
|
6643
7052
|
try {
|
|
7053
|
+
if (isNaN(offset)) return 61;
|
|
6644
7054
|
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
6645
|
-
var
|
|
6646
|
-
|
|
7055
|
+
var res = FS.mmap(stream, len, offset, prot, flags);
|
|
7056
|
+
var ptr = res.ptr;
|
|
7057
|
+
HEAP32[allocated >> 2] = res.allocated;
|
|
7058
|
+
HEAPU32[addr >> 2] = ptr;
|
|
6647
7059
|
return 0;
|
|
6648
7060
|
} catch (e) {
|
|
6649
7061
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6650
|
-
return e.errno;
|
|
7062
|
+
return -e.errno;
|
|
6651
7063
|
}
|
|
6652
7064
|
}
|
|
6653
7065
|
|
|
6654
|
-
function
|
|
7066
|
+
function __munmap_js(addr, len, prot, flags, fd, offset) {
|
|
6655
7067
|
offset = bigintToI53Checked(offset);
|
|
6656
7068
|
try {
|
|
6657
|
-
if (isNaN(offset)) return 61;
|
|
6658
7069
|
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
stream.getdents = null;
|
|
6663
|
-
// reset readdir state
|
|
6664
|
-
return 0;
|
|
7070
|
+
if (prot & 2) {
|
|
7071
|
+
SYSCALLS.doMsync(addr, stream, len, flags, offset);
|
|
7072
|
+
}
|
|
6665
7073
|
} catch (e) {
|
|
6666
7074
|
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6667
|
-
return e.errno;
|
|
7075
|
+
return -e.errno;
|
|
6668
7076
|
}
|
|
6669
7077
|
}
|
|
6670
7078
|
|
|
6671
|
-
var
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
mount.type.syncfs(mount, false, (err) => {
|
|
6682
|
-
if (err) {
|
|
6683
|
-
wakeUp(29);
|
|
6684
|
-
return;
|
|
6685
|
-
}
|
|
6686
|
-
wakeUp(0);
|
|
6687
|
-
});
|
|
6688
|
-
});
|
|
6689
|
-
} catch (e) {
|
|
6690
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6691
|
-
return e.errno;
|
|
7079
|
+
var timers = {};
|
|
7080
|
+
|
|
7081
|
+
var handleException = (e) => {
|
|
7082
|
+
// Certain exception types we do not treat as errors since they are used for
|
|
7083
|
+
// internal control flow.
|
|
7084
|
+
// 1. ExitStatus, which is thrown by exit()
|
|
7085
|
+
// 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
|
|
7086
|
+
// that wish to return to JS event loop.
|
|
7087
|
+
if (e instanceof ExitStatus || e == 'unwind') {
|
|
7088
|
+
return EXITSTATUS;
|
|
6692
7089
|
}
|
|
7090
|
+
quit_(1, e);
|
|
6693
7091
|
};
|
|
6694
7092
|
|
|
6695
|
-
|
|
7093
|
+
var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
|
|
6696
7094
|
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
) => {
|
|
6703
|
-
var ret = 0;
|
|
6704
|
-
for (var i = 0; i < iovcnt; i++) {
|
|
6705
|
-
var ptr = HEAPU32[iov >> 2];
|
|
6706
|
-
var len = HEAPU32[(iov + 4) >> 2];
|
|
6707
|
-
iov += 8;
|
|
6708
|
-
var curr = FS.write(stream, HEAP8, ptr, len, offset);
|
|
6709
|
-
if (curr < 0) return -1;
|
|
6710
|
-
ret += curr;
|
|
6711
|
-
if (curr < len) {
|
|
6712
|
-
// No more space to write.
|
|
6713
|
-
break;
|
|
6714
|
-
}
|
|
6715
|
-
if (typeof offset != 'undefined') {
|
|
6716
|
-
offset += curr;
|
|
6717
|
-
}
|
|
7095
|
+
var _proc_exit = (code) => {
|
|
7096
|
+
EXITSTATUS = code;
|
|
7097
|
+
if (!keepRuntimeAlive()) {
|
|
7098
|
+
Module['onExit']?.(code);
|
|
7099
|
+
ABORT = true;
|
|
6718
7100
|
}
|
|
6719
|
-
|
|
7101
|
+
quit_(code, new ExitStatus(code));
|
|
6720
7102
|
};
|
|
6721
7103
|
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
return 0;
|
|
6728
|
-
} catch (e) {
|
|
6729
|
-
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
6730
|
-
return e.errno;
|
|
6731
|
-
}
|
|
6732
|
-
}
|
|
6733
|
-
|
|
6734
|
-
var _getaddrinfo = (node, service, hint, out) => {
|
|
6735
|
-
var addr = 0;
|
|
6736
|
-
var port = 0;
|
|
6737
|
-
var flags = 0;
|
|
6738
|
-
var family = 0;
|
|
6739
|
-
var type = 0;
|
|
6740
|
-
var proto = 0;
|
|
6741
|
-
var ai;
|
|
6742
|
-
function allocaddrinfo(family, type, proto, canon, addr, port) {
|
|
6743
|
-
var sa, salen, ai;
|
|
6744
|
-
var errno;
|
|
6745
|
-
salen = family === 10 ? 28 : 16;
|
|
6746
|
-
addr = family === 10 ? inetNtop6(addr) : inetNtop4(addr);
|
|
6747
|
-
sa = _malloc(salen);
|
|
6748
|
-
errno = writeSockaddr(sa, family, addr, port);
|
|
6749
|
-
assert(!errno);
|
|
6750
|
-
ai = _malloc(32);
|
|
6751
|
-
HEAP32[(ai + 4) >> 2] = family;
|
|
6752
|
-
HEAP32[(ai + 8) >> 2] = type;
|
|
6753
|
-
HEAP32[(ai + 12) >> 2] = proto;
|
|
6754
|
-
HEAPU32[(ai + 24) >> 2] = canon;
|
|
6755
|
-
HEAPU32[(ai + 20) >> 2] = sa;
|
|
6756
|
-
if (family === 10) {
|
|
6757
|
-
HEAP32[(ai + 16) >> 2] = 28;
|
|
6758
|
-
} else {
|
|
6759
|
-
HEAP32[(ai + 16) >> 2] = 16;
|
|
6760
|
-
}
|
|
6761
|
-
HEAP32[(ai + 28) >> 2] = 0;
|
|
6762
|
-
return ai;
|
|
6763
|
-
}
|
|
6764
|
-
if (hint) {
|
|
6765
|
-
flags = HEAP32[hint >> 2];
|
|
6766
|
-
family = HEAP32[(hint + 4) >> 2];
|
|
6767
|
-
type = HEAP32[(hint + 8) >> 2];
|
|
6768
|
-
proto = HEAP32[(hint + 12) >> 2];
|
|
6769
|
-
}
|
|
6770
|
-
if (type && !proto) {
|
|
6771
|
-
proto = type === 2 ? 17 : 6;
|
|
6772
|
-
}
|
|
6773
|
-
if (!type && proto) {
|
|
6774
|
-
type = proto === 17 ? 2 : 1;
|
|
6775
|
-
}
|
|
6776
|
-
// If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for
|
|
6777
|
-
// now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints.
|
|
6778
|
-
if (proto === 0) {
|
|
6779
|
-
proto = 6;
|
|
6780
|
-
}
|
|
6781
|
-
if (type === 0) {
|
|
6782
|
-
type = 1;
|
|
6783
|
-
}
|
|
6784
|
-
if (!node && !service) {
|
|
6785
|
-
return -2;
|
|
6786
|
-
}
|
|
6787
|
-
if (flags & ~(1 | 2 | 4 | 1024 | 8 | 16 | 32)) {
|
|
6788
|
-
return -1;
|
|
6789
|
-
}
|
|
6790
|
-
if (hint !== 0 && HEAP32[hint >> 2] & 2 && !node) {
|
|
6791
|
-
return -1;
|
|
6792
|
-
}
|
|
6793
|
-
if (flags & 32) {
|
|
6794
|
-
// TODO
|
|
6795
|
-
return -2;
|
|
6796
|
-
}
|
|
6797
|
-
if (type !== 0 && type !== 1 && type !== 2) {
|
|
6798
|
-
return -7;
|
|
6799
|
-
}
|
|
6800
|
-
if (family !== 0 && family !== 2 && family !== 10) {
|
|
6801
|
-
return -6;
|
|
6802
|
-
}
|
|
6803
|
-
if (service) {
|
|
6804
|
-
service = UTF8ToString(service);
|
|
6805
|
-
port = parseInt(service, 10);
|
|
6806
|
-
if (isNaN(port)) {
|
|
6807
|
-
if (flags & 1024) {
|
|
6808
|
-
return -2;
|
|
6809
|
-
}
|
|
6810
|
-
// TODO support resolving well-known service names from:
|
|
6811
|
-
// http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
|
|
6812
|
-
return -8;
|
|
6813
|
-
}
|
|
6814
|
-
}
|
|
6815
|
-
if (!node) {
|
|
6816
|
-
if (family === 0) {
|
|
6817
|
-
family = 2;
|
|
6818
|
-
}
|
|
6819
|
-
if ((flags & 1) === 0) {
|
|
6820
|
-
if (family === 2) {
|
|
6821
|
-
addr = _htonl(2130706433);
|
|
6822
|
-
} else {
|
|
6823
|
-
addr = [0, 0, 0, _htonl(1)];
|
|
6824
|
-
}
|
|
6825
|
-
}
|
|
6826
|
-
ai = allocaddrinfo(family, type, proto, null, addr, port);
|
|
6827
|
-
HEAPU32[out >> 2] = ai;
|
|
6828
|
-
return 0;
|
|
6829
|
-
}
|
|
6830
|
-
// try as a numeric address
|
|
6831
|
-
node = UTF8ToString(node);
|
|
6832
|
-
addr = inetPton4(node);
|
|
6833
|
-
if (addr !== null) {
|
|
6834
|
-
// incoming node is a valid ipv4 address
|
|
6835
|
-
if (family === 0 || family === 2) {
|
|
6836
|
-
family = 2;
|
|
6837
|
-
} else if (family === 10 && flags & 8) {
|
|
6838
|
-
addr = [0, 0, _htonl(65535), addr];
|
|
6839
|
-
family = 10;
|
|
6840
|
-
} else {
|
|
6841
|
-
return -2;
|
|
6842
|
-
}
|
|
6843
|
-
} else {
|
|
6844
|
-
addr = inetPton6(node);
|
|
6845
|
-
if (addr !== null) {
|
|
6846
|
-
// incoming node is a valid ipv6 address
|
|
6847
|
-
if (family === 0 || family === 10) {
|
|
6848
|
-
family = 10;
|
|
6849
|
-
} else {
|
|
6850
|
-
return -2;
|
|
6851
|
-
}
|
|
7104
|
+
/** @suppress {duplicate } */ /** @param {boolean|number=} implicit */ var exitJS =
|
|
7105
|
+
(status, implicit) => {
|
|
7106
|
+
EXITSTATUS = status;
|
|
7107
|
+
if (!keepRuntimeAlive()) {
|
|
7108
|
+
exitRuntime();
|
|
6852
7109
|
}
|
|
7110
|
+
_proc_exit(status);
|
|
7111
|
+
};
|
|
7112
|
+
|
|
7113
|
+
var _exit = exitJS;
|
|
7114
|
+
|
|
7115
|
+
Module['_exit'] = _exit;
|
|
7116
|
+
|
|
7117
|
+
var maybeExit = () => {
|
|
7118
|
+
if (runtimeExited) {
|
|
7119
|
+
return;
|
|
6853
7120
|
}
|
|
6854
|
-
if (
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
7121
|
+
if (!keepRuntimeAlive()) {
|
|
7122
|
+
try {
|
|
7123
|
+
_exit(EXITSTATUS);
|
|
7124
|
+
} catch (e) {
|
|
7125
|
+
handleException(e);
|
|
7126
|
+
}
|
|
6858
7127
|
}
|
|
6859
|
-
|
|
6860
|
-
|
|
7128
|
+
};
|
|
7129
|
+
|
|
7130
|
+
var callUserCallback = (func) => {
|
|
7131
|
+
if (runtimeExited || ABORT) {
|
|
7132
|
+
return;
|
|
6861
7133
|
}
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
family = 2;
|
|
6868
|
-
} else if (family === 10) {
|
|
6869
|
-
addr = [0, 0, _htonl(65535), addr];
|
|
7134
|
+
try {
|
|
7135
|
+
func();
|
|
7136
|
+
maybeExit();
|
|
7137
|
+
} catch (e) {
|
|
7138
|
+
handleException(e);
|
|
6870
7139
|
}
|
|
6871
|
-
|
|
6872
|
-
|
|
7140
|
+
};
|
|
7141
|
+
|
|
7142
|
+
var _emscripten_get_now = () => performance.now();
|
|
7143
|
+
|
|
7144
|
+
var __setitimer_js = (which, timeout_ms) => {
|
|
7145
|
+
// First, clear any existing timer.
|
|
7146
|
+
if (timers[which]) {
|
|
7147
|
+
clearTimeout(timers[which].id);
|
|
7148
|
+
delete timers[which];
|
|
7149
|
+
}
|
|
7150
|
+
// A timeout of zero simply cancels the current timeout so we have nothing
|
|
7151
|
+
// more to do.
|
|
7152
|
+
if (!timeout_ms) return 0;
|
|
7153
|
+
var id = setTimeout(() => {
|
|
7154
|
+
delete timers[which];
|
|
7155
|
+
callUserCallback(() =>
|
|
7156
|
+
__emscripten_timeout(which, _emscripten_get_now())
|
|
7157
|
+
);
|
|
7158
|
+
}, timeout_ms);
|
|
7159
|
+
timers[which] = {
|
|
7160
|
+
id,
|
|
7161
|
+
timeout_ms,
|
|
7162
|
+
};
|
|
6873
7163
|
return 0;
|
|
6874
7164
|
};
|
|
6875
7165
|
|
|
6876
|
-
var
|
|
7166
|
+
var __tzset_js = (timezone, daylight, std_name, dst_name) => {
|
|
7167
|
+
// TODO: Use (malleable) environment variables instead of system settings.
|
|
7168
|
+
var currentYear = new Date().getFullYear();
|
|
7169
|
+
var winter = new Date(currentYear, 0, 1);
|
|
7170
|
+
var summer = new Date(currentYear, 6, 1);
|
|
7171
|
+
var winterOffset = winter.getTimezoneOffset();
|
|
7172
|
+
var summerOffset = summer.getTimezoneOffset();
|
|
7173
|
+
// Local standard timezone offset. Local standard time is not adjusted for
|
|
7174
|
+
// daylight savings. This code uses the fact that getTimezoneOffset returns
|
|
7175
|
+
// a greater value during Standard Time versus Daylight Saving Time (DST).
|
|
7176
|
+
// Thus it determines the expected output during Standard Time, and it
|
|
7177
|
+
// compares whether the output of the given date the same (Standard) or less
|
|
7178
|
+
// (DST).
|
|
7179
|
+
var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
|
|
7180
|
+
// timezone is specified as seconds west of UTC ("The external variable
|
|
7181
|
+
// `timezone` shall be set to the difference, in seconds, between
|
|
7182
|
+
// Coordinated Universal Time (UTC) and local standard time."), the same
|
|
7183
|
+
// as returned by stdTimezoneOffset.
|
|
7184
|
+
// See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html
|
|
7185
|
+
HEAPU32[timezone >> 2] = stdTimezoneOffset * 60;
|
|
7186
|
+
HEAP32[daylight >> 2] = Number(winterOffset != summerOffset);
|
|
7187
|
+
var extractZone = (timezoneOffset) => {
|
|
7188
|
+
// Why inverse sign?
|
|
7189
|
+
// Read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
|
|
7190
|
+
var sign = timezoneOffset >= 0 ? '-' : '+';
|
|
7191
|
+
var absOffset = Math.abs(timezoneOffset);
|
|
7192
|
+
var hours = String(Math.floor(absOffset / 60)).padStart(2, '0');
|
|
7193
|
+
var minutes = String(absOffset % 60).padStart(2, '0');
|
|
7194
|
+
return `UTC${sign}${hours}${minutes}`;
|
|
7195
|
+
};
|
|
7196
|
+
var winterName = extractZone(winterOffset);
|
|
7197
|
+
var summerName = extractZone(summerOffset);
|
|
7198
|
+
if (summerOffset < winterOffset) {
|
|
7199
|
+
// Northern hemisphere
|
|
7200
|
+
stringToUTF8(winterName, std_name, 17);
|
|
7201
|
+
stringToUTF8(summerName, dst_name, 17);
|
|
7202
|
+
} else {
|
|
7203
|
+
stringToUTF8(winterName, dst_name, 17);
|
|
7204
|
+
stringToUTF8(summerName, std_name, 17);
|
|
7205
|
+
}
|
|
7206
|
+
};
|
|
6877
7207
|
|
|
6878
|
-
var
|
|
7208
|
+
var _emscripten_date_now = () => Date.now();
|
|
6879
7209
|
|
|
6880
|
-
var
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
7210
|
+
var nowIsMonotonic = 1;
|
|
7211
|
+
|
|
7212
|
+
var checkWasiClock = (clock_id) => clock_id >= 0 && clock_id <= 3;
|
|
7213
|
+
|
|
7214
|
+
function _clock_time_get(clk_id, ignored_precision, ptime) {
|
|
7215
|
+
ignored_precision = bigintToI53Checked(ignored_precision);
|
|
7216
|
+
if (!checkWasiClock(clk_id)) {
|
|
7217
|
+
return 28;
|
|
6884
7218
|
}
|
|
6885
|
-
var
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
7219
|
+
var now;
|
|
7220
|
+
// all wasi clocks but realtime are monotonic
|
|
7221
|
+
if (clk_id === 0) {
|
|
7222
|
+
now = _emscripten_date_now();
|
|
7223
|
+
} else if (nowIsMonotonic) {
|
|
7224
|
+
now = _emscripten_get_now();
|
|
7225
|
+
} else {
|
|
7226
|
+
return 52;
|
|
7227
|
+
}
|
|
7228
|
+
// "now" is in ms, and wasi times are in ns.
|
|
7229
|
+
var nsec = Math.round(now * 1e3 * 1e3);
|
|
7230
|
+
HEAP64[ptime >> 3] = BigInt(nsec);
|
|
7231
|
+
return 0;
|
|
7232
|
+
}
|
|
7233
|
+
|
|
7234
|
+
var getHeapMax = () =>
|
|
7235
|
+
// Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
|
|
7236
|
+
// full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
|
|
7237
|
+
// for any code that deals with heap sizes, which would require special
|
|
7238
|
+
// casing all heap size related code to treat 0 specially.
|
|
7239
|
+
2147483648;
|
|
7240
|
+
|
|
7241
|
+
var _emscripten_get_heap_max = () => getHeapMax();
|
|
7242
|
+
|
|
7243
|
+
var growMemory = (size) => {
|
|
7244
|
+
var b = wasmMemory.buffer;
|
|
7245
|
+
var pages = ((size - b.byteLength + 65535) / 65536) | 0;
|
|
7246
|
+
try {
|
|
7247
|
+
// round size grow request up to wasm page size (fixed 64KB per spec)
|
|
7248
|
+
wasmMemory.grow(pages);
|
|
7249
|
+
// .grow() takes a delta compared to the previous size
|
|
7250
|
+
updateMemoryViews();
|
|
7251
|
+
return 1;
|
|
7252
|
+
} catch (e) {}
|
|
7253
|
+
};
|
|
7254
|
+
|
|
7255
|
+
var _emscripten_resize_heap = (requestedSize) => {
|
|
7256
|
+
var oldSize = HEAPU8.length;
|
|
7257
|
+
// With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
|
|
7258
|
+
requestedSize >>>= 0;
|
|
7259
|
+
// With multithreaded builds, races can happen (another thread might increase the size
|
|
7260
|
+
// in between), so return a failure, and let the caller retry.
|
|
7261
|
+
// Memory resize rules:
|
|
7262
|
+
// 1. Always increase heap size to at least the requested size, rounded up
|
|
7263
|
+
// to next page multiple.
|
|
7264
|
+
// 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
|
|
7265
|
+
// geometrically: increase the heap size according to
|
|
7266
|
+
// MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
|
|
7267
|
+
// overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
|
|
7268
|
+
// 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
|
|
7269
|
+
// linearly: increase the heap size by at least
|
|
7270
|
+
// MEMORY_GROWTH_LINEAR_STEP bytes.
|
|
7271
|
+
// 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
|
|
7272
|
+
// MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
|
|
7273
|
+
// 4. If we were unable to allocate as much memory, it may be due to
|
|
7274
|
+
// over-eager decision to excessively reserve due to (3) above.
|
|
7275
|
+
// Hence if an allocation fails, cut down on the amount of excess
|
|
7276
|
+
// growth, in an attempt to succeed to perform a smaller allocation.
|
|
7277
|
+
// A limit is set for how much we can grow. We should not exceed that
|
|
7278
|
+
// (the wasm binary specifies it, so if we tried, we'd fail anyhow).
|
|
7279
|
+
var maxHeapSize = getHeapMax();
|
|
7280
|
+
if (requestedSize > maxHeapSize) {
|
|
7281
|
+
return false;
|
|
7282
|
+
}
|
|
7283
|
+
// Loop through potential heap size increases. If we attempt a too eager
|
|
7284
|
+
// reservation that fails, cut down on the attempted size and reserve a
|
|
7285
|
+
// smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
|
|
7286
|
+
for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
|
|
7287
|
+
var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown);
|
|
7288
|
+
// ensure geometric growth
|
|
7289
|
+
// but limit overreserving (default to capping at +96MB overgrowth at most)
|
|
7290
|
+
overGrownHeapSize = Math.min(
|
|
7291
|
+
overGrownHeapSize,
|
|
7292
|
+
requestedSize + 100663296
|
|
7293
|
+
);
|
|
7294
|
+
var newSize = Math.min(
|
|
7295
|
+
maxHeapSize,
|
|
7296
|
+
alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536)
|
|
7297
|
+
);
|
|
7298
|
+
var replacement = growMemory(newSize);
|
|
7299
|
+
if (replacement) {
|
|
7300
|
+
return true;
|
|
6896
7301
|
}
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
7302
|
+
}
|
|
7303
|
+
return false;
|
|
7304
|
+
};
|
|
7305
|
+
|
|
7306
|
+
var runtimeKeepalivePush = () => {
|
|
7307
|
+
runtimeKeepaliveCounter += 1;
|
|
7308
|
+
};
|
|
7309
|
+
|
|
7310
|
+
var runtimeKeepalivePop = () => {
|
|
7311
|
+
runtimeKeepaliveCounter -= 1;
|
|
7312
|
+
};
|
|
7313
|
+
|
|
7314
|
+
/** @param {number=} timeout */ var safeSetTimeout = (func, timeout) => {
|
|
7315
|
+
runtimeKeepalivePush();
|
|
7316
|
+
return setTimeout(() => {
|
|
7317
|
+
runtimeKeepalivePop();
|
|
7318
|
+
callUserCallback(func);
|
|
7319
|
+
}, timeout);
|
|
7320
|
+
};
|
|
7321
|
+
|
|
7322
|
+
var _emscripten_sleep = (ms) =>
|
|
7323
|
+
Asyncify.handleSleep((wakeUp) => safeSetTimeout(wakeUp, ms));
|
|
7324
|
+
|
|
7325
|
+
Module['_emscripten_sleep'] = _emscripten_sleep;
|
|
7326
|
+
|
|
7327
|
+
_emscripten_sleep.isAsync = true;
|
|
7328
|
+
|
|
7329
|
+
var ENV = PHPLoader.ENV || {};
|
|
7330
|
+
|
|
7331
|
+
var getExecutableName = () => thisProgram || './this.program';
|
|
7332
|
+
|
|
7333
|
+
var getEnvStrings = () => {
|
|
7334
|
+
if (!getEnvStrings.strings) {
|
|
7335
|
+
// Default values.
|
|
7336
|
+
// Browser language detection #8751
|
|
7337
|
+
var lang =
|
|
7338
|
+
(
|
|
7339
|
+
(typeof navigator == 'object' &&
|
|
7340
|
+
navigator.languages &&
|
|
7341
|
+
navigator.languages[0]) ||
|
|
7342
|
+
'C'
|
|
7343
|
+
).replace('-', '_') + '.UTF-8';
|
|
7344
|
+
var env = {
|
|
7345
|
+
USER: 'web_user',
|
|
7346
|
+
LOGNAME: 'web_user',
|
|
7347
|
+
PATH: '/',
|
|
7348
|
+
PWD: '/',
|
|
7349
|
+
HOME: '/home/web_user',
|
|
7350
|
+
LANG: lang,
|
|
7351
|
+
_: getExecutableName(),
|
|
7352
|
+
};
|
|
7353
|
+
// Apply the user-provided values, if any.
|
|
7354
|
+
for (var x in ENV) {
|
|
7355
|
+
// x is a key in ENV; if ENV[x] is undefined, that means it was
|
|
7356
|
+
// explicitly set to be so. We allow user code to do that to
|
|
7357
|
+
// force variables with default values to remain unset.
|
|
7358
|
+
if (ENV[x] === undefined) delete env[x];
|
|
7359
|
+
else env[x] = ENV[x];
|
|
6900
7360
|
}
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen);
|
|
6905
|
-
if (numBytesWrittenExclNull + 1 >= servlen) {
|
|
6906
|
-
overflowed = true;
|
|
7361
|
+
var strings = [];
|
|
7362
|
+
for (var x in env) {
|
|
7363
|
+
strings.push(`${x}=${env[x]}`);
|
|
6907
7364
|
}
|
|
7365
|
+
getEnvStrings.strings = strings;
|
|
6908
7366
|
}
|
|
6909
|
-
|
|
6910
|
-
// Note: even when we overflow, getnameinfo() is specced to write out the truncated results.
|
|
6911
|
-
return -12;
|
|
6912
|
-
}
|
|
6913
|
-
return 0;
|
|
6914
|
-
};
|
|
6915
|
-
|
|
6916
|
-
var Protocols = {
|
|
6917
|
-
list: [],
|
|
6918
|
-
map: {},
|
|
7367
|
+
return getEnvStrings.strings;
|
|
6919
7368
|
};
|
|
6920
7369
|
|
|
6921
|
-
var
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
function allocprotoent(name, proto, aliases) {
|
|
6925
|
-
// write name into buffer
|
|
6926
|
-
var nameBuf = _malloc(name.length + 1);
|
|
6927
|
-
stringToAscii(name, nameBuf);
|
|
6928
|
-
// write aliases into buffer
|
|
6929
|
-
var j = 0;
|
|
6930
|
-
var length = aliases.length;
|
|
6931
|
-
var aliasListBuf = _malloc((length + 1) * 4);
|
|
6932
|
-
// Use length + 1 so we have space for the terminating NULL ptr.
|
|
6933
|
-
for (var i = 0; i < length; i++, j += 4) {
|
|
6934
|
-
var alias = aliases[i];
|
|
6935
|
-
var aliasBuf = _malloc(alias.length + 1);
|
|
6936
|
-
stringToAscii(alias, aliasBuf);
|
|
6937
|
-
HEAPU32[(aliasListBuf + j) >> 2] = aliasBuf;
|
|
6938
|
-
}
|
|
6939
|
-
HEAPU32[(aliasListBuf + j) >> 2] = 0;
|
|
6940
|
-
// Terminating NULL pointer.
|
|
6941
|
-
// generate protoent
|
|
6942
|
-
var pe = _malloc(12);
|
|
6943
|
-
HEAPU32[pe >> 2] = nameBuf;
|
|
6944
|
-
HEAPU32[(pe + 4) >> 2] = aliasListBuf;
|
|
6945
|
-
HEAP32[(pe + 8) >> 2] = proto;
|
|
6946
|
-
return pe;
|
|
6947
|
-
}
|
|
6948
|
-
// Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial
|
|
6949
|
-
// to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful.
|
|
6950
|
-
var list = Protocols.list;
|
|
6951
|
-
var map = Protocols.map;
|
|
6952
|
-
if (list.length === 0) {
|
|
6953
|
-
var entry = allocprotoent('tcp', 6, ['TCP']);
|
|
6954
|
-
list.push(entry);
|
|
6955
|
-
map['tcp'] = map['6'] = entry;
|
|
6956
|
-
entry = allocprotoent('udp', 17, ['UDP']);
|
|
6957
|
-
list.push(entry);
|
|
6958
|
-
map['udp'] = map['17'] = entry;
|
|
7370
|
+
var stringToAscii = (str, buffer) => {
|
|
7371
|
+
for (var i = 0; i < str.length; ++i) {
|
|
7372
|
+
HEAP8[buffer++] = str.charCodeAt(i);
|
|
6959
7373
|
}
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
var _getprotobyname = (name) => {
|
|
6964
|
-
// struct protoent *getprotobyname(const char *);
|
|
6965
|
-
name = UTF8ToString(name);
|
|
6966
|
-
_setprotoent(true);
|
|
6967
|
-
var result = Protocols.map[name];
|
|
6968
|
-
return result;
|
|
7374
|
+
// Null-terminate the string
|
|
7375
|
+
HEAP8[buffer] = 0;
|
|
6969
7376
|
};
|
|
6970
7377
|
|
|
6971
|
-
var
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
7378
|
+
var _environ_get = (__environ, environ_buf) => {
|
|
7379
|
+
var bufSize = 0;
|
|
7380
|
+
getEnvStrings().forEach((string, i) => {
|
|
7381
|
+
var ptr = environ_buf + bufSize;
|
|
7382
|
+
HEAPU32[(__environ + i * 4) >> 2] = ptr;
|
|
7383
|
+
stringToAscii(string, ptr);
|
|
7384
|
+
bufSize += string.length + 1;
|
|
7385
|
+
});
|
|
7386
|
+
return 0;
|
|
6976
7387
|
};
|
|
6977
7388
|
|
|
6978
|
-
var
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
var
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
return
|
|
7389
|
+
var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
|
|
7390
|
+
var strings = getEnvStrings();
|
|
7391
|
+
HEAPU32[penviron_count >> 2] = strings.length;
|
|
7392
|
+
var bufSize = 0;
|
|
7393
|
+
strings.forEach((string) => (bufSize += string.length + 1));
|
|
7394
|
+
HEAPU32[penviron_buf_size >> 2] = bufSize;
|
|
7395
|
+
return 0;
|
|
6985
7396
|
};
|
|
6986
7397
|
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
// on the first null byte. However, when dealing with binary data,
|
|
7004
|
-
// null bytes are valid and common.
|
|
7005
|
-
FS.registerDevice(FS.makedev(64, 0), {
|
|
7006
|
-
open: () => {},
|
|
7007
|
-
close: () => {},
|
|
7008
|
-
read: () => 0,
|
|
7009
|
-
write: (stream, buffer, offset, length, pos) => {
|
|
7010
|
-
const chunk = buffer.subarray(offset, offset + length);
|
|
7011
|
-
PHPWASM.onStdout(chunk);
|
|
7012
|
-
return length;
|
|
7013
|
-
},
|
|
7014
|
-
});
|
|
7015
|
-
FS.mkdev('/internal/stdout', FS.makedev(64, 0));
|
|
7016
|
-
FS.registerDevice(FS.makedev(63, 0), {
|
|
7017
|
-
open: () => {},
|
|
7018
|
-
close: () => {},
|
|
7019
|
-
read: () => 0,
|
|
7020
|
-
write: (stream, buffer, offset, length, pos) => {
|
|
7021
|
-
const chunk = buffer.subarray(offset, offset + length);
|
|
7022
|
-
PHPWASM.onStderr(chunk);
|
|
7023
|
-
return length;
|
|
7024
|
-
},
|
|
7025
|
-
});
|
|
7026
|
-
FS.mkdev('/internal/stderr', FS.makedev(63, 0));
|
|
7027
|
-
FS.registerDevice(FS.makedev(62, 0), {
|
|
7028
|
-
open: () => {},
|
|
7029
|
-
close: () => {},
|
|
7030
|
-
read: () => 0,
|
|
7031
|
-
write: (stream, buffer, offset, length, pos) => {
|
|
7032
|
-
const chunk = buffer.subarray(offset, offset + length);
|
|
7033
|
-
PHPWASM.onHeaders(chunk);
|
|
7034
|
-
return length;
|
|
7035
|
-
},
|
|
7036
|
-
});
|
|
7037
|
-
FS.mkdev('/internal/headers', FS.makedev(62, 0));
|
|
7038
|
-
// Handle events.
|
|
7039
|
-
PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE
|
|
7040
|
-
? require('events').EventEmitter
|
|
7041
|
-
: class EventEmitter {
|
|
7042
|
-
constructor() {
|
|
7043
|
-
this.listeners = {};
|
|
7044
|
-
}
|
|
7045
|
-
emit(eventName, data) {
|
|
7046
|
-
if (this.listeners[eventName]) {
|
|
7047
|
-
this.listeners[eventName].forEach(
|
|
7048
|
-
(callback) => {
|
|
7049
|
-
callback(data);
|
|
7050
|
-
}
|
|
7051
|
-
);
|
|
7052
|
-
}
|
|
7053
|
-
}
|
|
7054
|
-
once(eventName, callback) {
|
|
7055
|
-
const self = this;
|
|
7056
|
-
function removedCallback() {
|
|
7057
|
-
callback(...arguments);
|
|
7058
|
-
self.removeListener(eventName, removedCallback);
|
|
7059
|
-
}
|
|
7060
|
-
this.on(eventName, removedCallback);
|
|
7061
|
-
}
|
|
7062
|
-
removeAllListeners(eventName) {
|
|
7063
|
-
if (eventName) {
|
|
7064
|
-
delete this.listeners[eventName];
|
|
7065
|
-
} else {
|
|
7066
|
-
this.listeners = {};
|
|
7067
|
-
}
|
|
7068
|
-
}
|
|
7069
|
-
removeListener(eventName, callback) {
|
|
7070
|
-
if (this.listeners[eventName]) {
|
|
7071
|
-
const idx =
|
|
7072
|
-
this.listeners[eventName].indexOf(callback);
|
|
7073
|
-
if (idx !== -1) {
|
|
7074
|
-
this.listeners[eventName].splice(idx, 1);
|
|
7075
|
-
}
|
|
7076
|
-
}
|
|
7077
|
-
}
|
|
7078
|
-
};
|
|
7079
|
-
// Clean up the fd -> childProcess mapping when the fd is closed:
|
|
7080
|
-
const originalClose = FS.close;
|
|
7081
|
-
FS.close = function (stream) {
|
|
7082
|
-
originalClose(stream);
|
|
7083
|
-
delete PHPWASM.child_proc_by_fd[stream.fd];
|
|
7084
|
-
};
|
|
7085
|
-
PHPWASM.child_proc_by_fd = {};
|
|
7086
|
-
PHPWASM.child_proc_by_pid = {};
|
|
7087
|
-
PHPWASM.input_devices = {};
|
|
7088
|
-
const originalWrite = TTY.stream_ops.write;
|
|
7089
|
-
TTY.stream_ops.write = function (stream, ...rest) {
|
|
7090
|
-
const retval = originalWrite(stream, ...rest);
|
|
7091
|
-
// Implicit flush since PHP's fflush() doesn't seem to trigger the fsync event
|
|
7092
|
-
// @TODO: Fix this at the wasm level
|
|
7093
|
-
stream.tty.ops.fsync(stream.tty);
|
|
7094
|
-
return retval;
|
|
7095
|
-
};
|
|
7096
|
-
const originalPutChar = TTY.stream_ops.put_char;
|
|
7097
|
-
TTY.stream_ops.put_char = function (tty, val) {
|
|
7098
|
-
/**
|
|
7099
|
-
* Buffer newlines that Emscripten normally ignores.
|
|
7100
|
-
*
|
|
7101
|
-
* Emscripten doesn't do it by default because its default
|
|
7102
|
-
* print function is console.log that implicitly adds a newline. We are overwriting
|
|
7103
|
-
* it with an environment-specific function that outputs exaclty what it was given,
|
|
7104
|
-
* e.g. in Node.js it's process.stdout.write(). Therefore, we need to mak sure
|
|
7105
|
-
* all the newlines make it to the output buffer.
|
|
7106
|
-
*/ if (val === 10) tty.output.push(val);
|
|
7107
|
-
return originalPutChar(tty, val);
|
|
7108
|
-
};
|
|
7109
|
-
},
|
|
7110
|
-
onHeaders: function (chunk) {
|
|
7111
|
-
if (Module['onHeaders']) {
|
|
7112
|
-
Module['onHeaders'](chunk);
|
|
7113
|
-
return;
|
|
7398
|
+
function _fd_fdstat_get(fd, pbuf) {
|
|
7399
|
+
try {
|
|
7400
|
+
var rightsBase = 0;
|
|
7401
|
+
var rightsInheriting = 0;
|
|
7402
|
+
var flags = 0;
|
|
7403
|
+
{
|
|
7404
|
+
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
7405
|
+
// All character devices are terminals (other things a Linux system would
|
|
7406
|
+
// assume is a character device, like the mouse, we have special APIs for).
|
|
7407
|
+
var type = stream.tty
|
|
7408
|
+
? 2
|
|
7409
|
+
: FS.isDir(stream.mode)
|
|
7410
|
+
? 3
|
|
7411
|
+
: FS.isLink(stream.mode)
|
|
7412
|
+
? 7
|
|
7413
|
+
: 4;
|
|
7114
7414
|
}
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7415
|
+
HEAP8[pbuf] = type;
|
|
7416
|
+
HEAP16[(pbuf + 2) >> 1] = flags;
|
|
7417
|
+
HEAP64[(pbuf + 8) >> 3] = BigInt(rightsBase);
|
|
7418
|
+
HEAP64[(pbuf + 16) >> 3] = BigInt(rightsInheriting);
|
|
7419
|
+
return 0;
|
|
7420
|
+
} catch (e) {
|
|
7421
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
7422
|
+
return e.errno;
|
|
7423
|
+
}
|
|
7424
|
+
}
|
|
7425
|
+
|
|
7426
|
+
/** @param {number=} offset */ var doReadv = (
|
|
7427
|
+
stream,
|
|
7428
|
+
iov,
|
|
7429
|
+
iovcnt,
|
|
7430
|
+
offset
|
|
7431
|
+
) => {
|
|
7432
|
+
var ret = 0;
|
|
7433
|
+
for (var i = 0; i < iovcnt; i++) {
|
|
7434
|
+
var ptr = HEAPU32[iov >> 2];
|
|
7435
|
+
var len = HEAPU32[(iov + 4) >> 2];
|
|
7436
|
+
iov += 8;
|
|
7437
|
+
var curr = FS.read(stream, HEAP8, ptr, len, offset);
|
|
7438
|
+
if (curr < 0) return -1;
|
|
7439
|
+
ret += curr;
|
|
7440
|
+
if (curr < len) break;
|
|
7441
|
+
// nothing more to read
|
|
7442
|
+
if (typeof offset != 'undefined') {
|
|
7443
|
+
offset += curr;
|
|
7123
7444
|
}
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7445
|
+
}
|
|
7446
|
+
return ret;
|
|
7447
|
+
};
|
|
7448
|
+
|
|
7449
|
+
function _fd_read(fd, iov, iovcnt, pnum) {
|
|
7450
|
+
try {
|
|
7451
|
+
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
7452
|
+
var num = doReadv(stream, iov, iovcnt);
|
|
7453
|
+
HEAPU32[pnum >> 2] = num;
|
|
7454
|
+
return 0;
|
|
7455
|
+
} catch (e) {
|
|
7456
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
7457
|
+
return e.errno;
|
|
7458
|
+
}
|
|
7459
|
+
}
|
|
7460
|
+
|
|
7461
|
+
function _fd_seek(fd, offset, whence, newOffset) {
|
|
7462
|
+
offset = bigintToI53Checked(offset);
|
|
7463
|
+
try {
|
|
7464
|
+
if (isNaN(offset)) return 61;
|
|
7465
|
+
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
7466
|
+
FS.llseek(stream, offset, whence);
|
|
7467
|
+
HEAP64[newOffset >> 3] = BigInt(stream.position);
|
|
7468
|
+
if (stream.getdents && offset === 0 && whence === 0)
|
|
7469
|
+
stream.getdents = null;
|
|
7470
|
+
// reset readdir state
|
|
7471
|
+
return 0;
|
|
7472
|
+
} catch (e) {
|
|
7473
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
7474
|
+
return e.errno;
|
|
7475
|
+
}
|
|
7476
|
+
}
|
|
7477
|
+
|
|
7478
|
+
var _fd_sync = function (fd) {
|
|
7479
|
+
try {
|
|
7480
|
+
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
7481
|
+
return Asyncify.handleSleep((wakeUp) => {
|
|
7482
|
+
var mount = stream.node.mount;
|
|
7483
|
+
if (!mount.type.syncfs) {
|
|
7484
|
+
// We write directly to the file system, so there's nothing to do here.
|
|
7485
|
+
wakeUp(0);
|
|
7486
|
+
return;
|
|
7487
|
+
}
|
|
7488
|
+
mount.type.syncfs(mount, false, (err) => {
|
|
7489
|
+
if (err) {
|
|
7490
|
+
wakeUp(29);
|
|
7491
|
+
return;
|
|
7492
|
+
}
|
|
7493
|
+
wakeUp(0);
|
|
7129
7494
|
});
|
|
7495
|
+
});
|
|
7496
|
+
} catch (e) {
|
|
7497
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
7498
|
+
return e.errno;
|
|
7499
|
+
}
|
|
7500
|
+
};
|
|
7501
|
+
|
|
7502
|
+
_fd_sync.isAsync = true;
|
|
7503
|
+
|
|
7504
|
+
/** @param {number=} offset */ var doWritev = (
|
|
7505
|
+
stream,
|
|
7506
|
+
iov,
|
|
7507
|
+
iovcnt,
|
|
7508
|
+
offset
|
|
7509
|
+
) => {
|
|
7510
|
+
var ret = 0;
|
|
7511
|
+
for (var i = 0; i < iovcnt; i++) {
|
|
7512
|
+
var ptr = HEAPU32[iov >> 2];
|
|
7513
|
+
var len = HEAPU32[(iov + 4) >> 2];
|
|
7514
|
+
iov += 8;
|
|
7515
|
+
var curr = FS.write(stream, HEAP8, ptr, len, offset);
|
|
7516
|
+
if (curr < 0) return -1;
|
|
7517
|
+
ret += curr;
|
|
7518
|
+
if (curr < len) {
|
|
7519
|
+
// No more space to write.
|
|
7520
|
+
break;
|
|
7130
7521
|
}
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
if (Module['onStderr']) {
|
|
7134
|
-
Module['onStderr'](chunk);
|
|
7135
|
-
return;
|
|
7522
|
+
if (typeof offset != 'undefined') {
|
|
7523
|
+
offset += curr;
|
|
7136
7524
|
}
|
|
7137
|
-
|
|
7138
|
-
|
|
7525
|
+
}
|
|
7526
|
+
return ret;
|
|
7527
|
+
};
|
|
7528
|
+
|
|
7529
|
+
function _fd_write(fd, iov, iovcnt, pnum) {
|
|
7530
|
+
try {
|
|
7531
|
+
var stream = SYSCALLS.getStreamFromFD(fd);
|
|
7532
|
+
var num = doWritev(stream, iov, iovcnt);
|
|
7533
|
+
HEAPU32[pnum >> 2] = num;
|
|
7534
|
+
return 0;
|
|
7535
|
+
} catch (e) {
|
|
7536
|
+
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
|
|
7537
|
+
return e.errno;
|
|
7538
|
+
}
|
|
7539
|
+
}
|
|
7540
|
+
|
|
7541
|
+
var _getaddrinfo = (node, service, hint, out) => {
|
|
7542
|
+
var addr = 0;
|
|
7543
|
+
var port = 0;
|
|
7544
|
+
var flags = 0;
|
|
7545
|
+
var family = 0;
|
|
7546
|
+
var type = 0;
|
|
7547
|
+
var proto = 0;
|
|
7548
|
+
var ai;
|
|
7549
|
+
function allocaddrinfo(family, type, proto, canon, addr, port) {
|
|
7550
|
+
var sa, salen, ai;
|
|
7551
|
+
var errno;
|
|
7552
|
+
salen = family === 10 ? 28 : 16;
|
|
7553
|
+
addr = family === 10 ? inetNtop6(addr) : inetNtop4(addr);
|
|
7554
|
+
sa = _malloc(salen);
|
|
7555
|
+
errno = writeSockaddr(sa, family, addr, port);
|
|
7556
|
+
assert(!errno);
|
|
7557
|
+
ai = _malloc(32);
|
|
7558
|
+
HEAP32[(ai + 4) >> 2] = family;
|
|
7559
|
+
HEAP32[(ai + 8) >> 2] = type;
|
|
7560
|
+
HEAP32[(ai + 12) >> 2] = proto;
|
|
7561
|
+
HEAPU32[(ai + 24) >> 2] = canon;
|
|
7562
|
+
HEAPU32[(ai + 20) >> 2] = sa;
|
|
7563
|
+
if (family === 10) {
|
|
7564
|
+
HEAP32[(ai + 16) >> 2] = 28;
|
|
7139
7565
|
} else {
|
|
7140
|
-
|
|
7141
|
-
chunk,
|
|
7142
|
-
});
|
|
7566
|
+
HEAP32[(ai + 16) >> 2] = 16;
|
|
7143
7567
|
}
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7568
|
+
HEAP32[(ai + 28) >> 2] = 0;
|
|
7569
|
+
return ai;
|
|
7570
|
+
}
|
|
7571
|
+
if (hint) {
|
|
7572
|
+
flags = HEAP32[hint >> 2];
|
|
7573
|
+
family = HEAP32[(hint + 4) >> 2];
|
|
7574
|
+
type = HEAP32[(hint + 8) >> 2];
|
|
7575
|
+
proto = HEAP32[(hint + 12) >> 2];
|
|
7576
|
+
}
|
|
7577
|
+
if (type && !proto) {
|
|
7578
|
+
proto = type === 2 ? 17 : 6;
|
|
7579
|
+
}
|
|
7580
|
+
if (!type && proto) {
|
|
7581
|
+
type = proto === 17 ? 2 : 1;
|
|
7582
|
+
}
|
|
7583
|
+
// If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for
|
|
7584
|
+
// now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints.
|
|
7585
|
+
if (proto === 0) {
|
|
7586
|
+
proto = 6;
|
|
7587
|
+
}
|
|
7588
|
+
if (type === 0) {
|
|
7589
|
+
type = 1;
|
|
7590
|
+
}
|
|
7591
|
+
if (!node && !service) {
|
|
7592
|
+
return -2;
|
|
7593
|
+
}
|
|
7594
|
+
if (flags & ~(1 | 2 | 4 | 1024 | 8 | 16 | 32)) {
|
|
7595
|
+
return -1;
|
|
7596
|
+
}
|
|
7597
|
+
if (hint !== 0 && HEAP32[hint >> 2] & 2 && !node) {
|
|
7598
|
+
return -1;
|
|
7599
|
+
}
|
|
7600
|
+
if (flags & 32) {
|
|
7601
|
+
// TODO
|
|
7602
|
+
return -2;
|
|
7603
|
+
}
|
|
7604
|
+
if (type !== 0 && type !== 1 && type !== 2) {
|
|
7605
|
+
return -7;
|
|
7606
|
+
}
|
|
7607
|
+
if (family !== 0 && family !== 2 && family !== 10) {
|
|
7608
|
+
return -6;
|
|
7609
|
+
}
|
|
7610
|
+
if (service) {
|
|
7611
|
+
service = UTF8ToString(service);
|
|
7612
|
+
port = parseInt(service, 10);
|
|
7613
|
+
if (isNaN(port)) {
|
|
7614
|
+
if (flags & 1024) {
|
|
7615
|
+
return -2;
|
|
7616
|
+
}
|
|
7617
|
+
// TODO support resolving well-known service names from:
|
|
7618
|
+
// http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt
|
|
7619
|
+
return -8;
|
|
7151
7620
|
}
|
|
7152
|
-
|
|
7153
|
-
|
|
7621
|
+
}
|
|
7622
|
+
if (!node) {
|
|
7623
|
+
if (family === 0) {
|
|
7624
|
+
family = 2;
|
|
7154
7625
|
}
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7626
|
+
if ((flags & 1) === 0) {
|
|
7627
|
+
if (family === 2) {
|
|
7628
|
+
addr = _htonl(2130706433);
|
|
7629
|
+
} else {
|
|
7630
|
+
addr = [0, 0, 0, _htonl(1)];
|
|
7631
|
+
}
|
|
7632
|
+
}
|
|
7633
|
+
ai = allocaddrinfo(family, type, proto, null, addr, port);
|
|
7634
|
+
HEAPU32[out >> 2] = ai;
|
|
7635
|
+
return 0;
|
|
7636
|
+
}
|
|
7637
|
+
// try as a numeric address
|
|
7638
|
+
node = UTF8ToString(node);
|
|
7639
|
+
addr = inetPton4(node);
|
|
7640
|
+
if (addr !== null) {
|
|
7641
|
+
// incoming node is a valid ipv4 address
|
|
7642
|
+
if (family === 0 || family === 2) {
|
|
7643
|
+
family = 2;
|
|
7644
|
+
} else if (family === 10 && flags & 8) {
|
|
7645
|
+
addr = [0, 0, _htonl(65535), addr];
|
|
7646
|
+
family = 10;
|
|
7647
|
+
} else {
|
|
7648
|
+
return -2;
|
|
7167
7649
|
}
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7650
|
+
} else {
|
|
7651
|
+
addr = inetPton6(node);
|
|
7652
|
+
if (addr !== null) {
|
|
7653
|
+
// incoming node is a valid ipv6 address
|
|
7654
|
+
if (family === 0 || family === 10) {
|
|
7655
|
+
family = 10;
|
|
7656
|
+
} else {
|
|
7657
|
+
return -2;
|
|
7171
7658
|
}
|
|
7172
7659
|
}
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
if (Module['spawnProcess']) {
|
|
7217
|
-
const spawnedPromise = Module['spawnProcess'](
|
|
7218
|
-
command,
|
|
7219
|
-
args,
|
|
7220
|
-
options
|
|
7221
|
-
);
|
|
7222
|
-
return Promise.resolve(spawnedPromise).then(function (spawned) {
|
|
7223
|
-
if (!spawned || !spawned.on) {
|
|
7224
|
-
throw new Error(
|
|
7225
|
-
'spawnProcess() must return an EventEmitter but returned a different type.'
|
|
7226
|
-
);
|
|
7227
|
-
}
|
|
7228
|
-
return spawned;
|
|
7229
|
-
});
|
|
7660
|
+
}
|
|
7661
|
+
if (addr != null) {
|
|
7662
|
+
ai = allocaddrinfo(family, type, proto, node, addr, port);
|
|
7663
|
+
HEAPU32[out >> 2] = ai;
|
|
7664
|
+
return 0;
|
|
7665
|
+
}
|
|
7666
|
+
if (flags & 4) {
|
|
7667
|
+
return -2;
|
|
7668
|
+
}
|
|
7669
|
+
// try as a hostname
|
|
7670
|
+
// resolve the hostname to a temporary fake address
|
|
7671
|
+
node = DNS.lookup_name(node);
|
|
7672
|
+
addr = inetPton4(node);
|
|
7673
|
+
if (family === 0) {
|
|
7674
|
+
family = 2;
|
|
7675
|
+
} else if (family === 10) {
|
|
7676
|
+
addr = [0, 0, _htonl(65535), addr];
|
|
7677
|
+
}
|
|
7678
|
+
ai = allocaddrinfo(family, type, proto, null, addr, port);
|
|
7679
|
+
HEAPU32[out >> 2] = ai;
|
|
7680
|
+
return 0;
|
|
7681
|
+
};
|
|
7682
|
+
|
|
7683
|
+
var _getcontext = () => abort('missing function: ${name}');
|
|
7684
|
+
|
|
7685
|
+
var _getdtablesize = () => abort('missing function: ${name}');
|
|
7686
|
+
|
|
7687
|
+
var _getnameinfo = (sa, salen, node, nodelen, serv, servlen, flags) => {
|
|
7688
|
+
var info = readSockaddr(sa, salen);
|
|
7689
|
+
if (info.errno) {
|
|
7690
|
+
return -6;
|
|
7691
|
+
}
|
|
7692
|
+
var port = info.port;
|
|
7693
|
+
var addr = info.addr;
|
|
7694
|
+
var overflowed = false;
|
|
7695
|
+
if (node && nodelen) {
|
|
7696
|
+
var lookup;
|
|
7697
|
+
if (flags & 1 || !(lookup = DNS.lookup_addr(addr))) {
|
|
7698
|
+
if (flags & 8) {
|
|
7699
|
+
return -2;
|
|
7700
|
+
}
|
|
7701
|
+
} else {
|
|
7702
|
+
addr = lookup;
|
|
7230
7703
|
}
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
shell: true,
|
|
7235
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
7236
|
-
timeout: 100,
|
|
7237
|
-
});
|
|
7704
|
+
var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen);
|
|
7705
|
+
if (numBytesWrittenExclNull + 1 >= nodelen) {
|
|
7706
|
+
overflowed = true;
|
|
7238
7707
|
}
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
)
|
|
7244
|
-
|
|
7245
|
-
throw e;
|
|
7246
|
-
},
|
|
7247
|
-
shutdownSocket: function (socketd, how) {
|
|
7248
|
-
// This implementation only supports websockets at the moment
|
|
7249
|
-
const sock = getSocketFromFD(socketd);
|
|
7250
|
-
const peer = Object.values(sock.peers)[0];
|
|
7251
|
-
if (!peer) {
|
|
7252
|
-
return -1;
|
|
7708
|
+
}
|
|
7709
|
+
if (serv && servlen) {
|
|
7710
|
+
port = '' + port;
|
|
7711
|
+
var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen);
|
|
7712
|
+
if (numBytesWrittenExclNull + 1 >= servlen) {
|
|
7713
|
+
overflowed = true;
|
|
7253
7714
|
}
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7715
|
+
}
|
|
7716
|
+
if (overflowed) {
|
|
7717
|
+
// Note: even when we overflow, getnameinfo() is specced to write out the truncated results.
|
|
7718
|
+
return -12;
|
|
7719
|
+
}
|
|
7720
|
+
return 0;
|
|
7721
|
+
};
|
|
7722
|
+
|
|
7723
|
+
var Protocols = {
|
|
7724
|
+
list: [],
|
|
7725
|
+
map: {},
|
|
7726
|
+
};
|
|
7727
|
+
|
|
7728
|
+
var _setprotoent = (stayopen) => {
|
|
7729
|
+
// void setprotoent(int stayopen);
|
|
7730
|
+
// Allocate and populate a protoent structure given a name, protocol number and array of aliases
|
|
7731
|
+
function allocprotoent(name, proto, aliases) {
|
|
7732
|
+
// write name into buffer
|
|
7733
|
+
var nameBuf = _malloc(name.length + 1);
|
|
7734
|
+
stringToAscii(name, nameBuf);
|
|
7735
|
+
// write aliases into buffer
|
|
7736
|
+
var j = 0;
|
|
7737
|
+
var length = aliases.length;
|
|
7738
|
+
var aliasListBuf = _malloc((length + 1) * 4);
|
|
7739
|
+
// Use length + 1 so we have space for the terminating NULL ptr.
|
|
7740
|
+
for (var i = 0; i < length; i++, j += 4) {
|
|
7741
|
+
var alias = aliases[i];
|
|
7742
|
+
var aliasBuf = _malloc(alias.length + 1);
|
|
7743
|
+
stringToAscii(alias, aliasBuf);
|
|
7744
|
+
HEAPU32[(aliasListBuf + j) >> 2] = aliasBuf;
|
|
7261
7745
|
}
|
|
7262
|
-
|
|
7746
|
+
HEAPU32[(aliasListBuf + j) >> 2] = 0;
|
|
7747
|
+
// Terminating NULL pointer.
|
|
7748
|
+
// generate protoent
|
|
7749
|
+
var pe = _malloc(12);
|
|
7750
|
+
HEAPU32[pe >> 2] = nameBuf;
|
|
7751
|
+
HEAPU32[(pe + 4) >> 2] = aliasListBuf;
|
|
7752
|
+
HEAP32[(pe + 8) >> 2] = proto;
|
|
7753
|
+
return pe;
|
|
7754
|
+
}
|
|
7755
|
+
// Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial
|
|
7756
|
+
// to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful.
|
|
7757
|
+
var list = Protocols.list;
|
|
7758
|
+
var map = Protocols.map;
|
|
7759
|
+
if (list.length === 0) {
|
|
7760
|
+
var entry = allocprotoent('tcp', 6, ['TCP']);
|
|
7761
|
+
list.push(entry);
|
|
7762
|
+
map['tcp'] = map['6'] = entry;
|
|
7763
|
+
entry = allocprotoent('udp', 17, ['UDP']);
|
|
7764
|
+
list.push(entry);
|
|
7765
|
+
map['udp'] = map['17'] = entry;
|
|
7766
|
+
}
|
|
7767
|
+
_setprotoent.index = 0;
|
|
7768
|
+
};
|
|
7769
|
+
|
|
7770
|
+
var _getprotobyname = (name) => {
|
|
7771
|
+
// struct protoent *getprotobyname(const char *);
|
|
7772
|
+
name = UTF8ToString(name);
|
|
7773
|
+
_setprotoent(true);
|
|
7774
|
+
var result = Protocols.map[name];
|
|
7775
|
+
return result;
|
|
7776
|
+
};
|
|
7777
|
+
|
|
7778
|
+
var _getprotobynumber = (number) => {
|
|
7779
|
+
// struct protoent *getprotobynumber(int proto);
|
|
7780
|
+
_setprotoent(true);
|
|
7781
|
+
var result = Protocols.map[number];
|
|
7782
|
+
return result;
|
|
7263
7783
|
};
|
|
7264
7784
|
|
|
7265
7785
|
function _js_create_input_device(deviceId) {
|
|
@@ -7297,6 +7817,98 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7297
7817
|
return allocateUTF8OnStack(devicePath);
|
|
7298
7818
|
}
|
|
7299
7819
|
|
|
7820
|
+
async function _js_flock(fd, op) {
|
|
7821
|
+
_js_wasm_trace('js_flock(%d, %d)', fd, op);
|
|
7822
|
+
// Emscripten does not expose these constants to JS, so we hardcode them here.
|
|
7823
|
+
// Based on
|
|
7824
|
+
// https://github.com/emscripten-core/emscripten/blob/76860cc47cef67f5712a7a03a247bc1baabf7ba4/system/lib/libc/musl/include/sys/file.h#L7-L10
|
|
7825
|
+
const emscripten_LOCK_SH = 1;
|
|
7826
|
+
const emscripten_LOCK_EX = 2;
|
|
7827
|
+
const emscripten_LOCK_NB = 4;
|
|
7828
|
+
const emscripten_LOCK_UN = 8;
|
|
7829
|
+
const flockToLockOpType = {
|
|
7830
|
+
[emscripten_LOCK_SH]: 'shared',
|
|
7831
|
+
[emscripten_LOCK_EX]: 'exclusive',
|
|
7832
|
+
[emscripten_LOCK_UN]: 'unlocked',
|
|
7833
|
+
};
|
|
7834
|
+
let vfsPath;
|
|
7835
|
+
let errno;
|
|
7836
|
+
[vfsPath, errno] = locking.get_vfs_path_from_fd(fd);
|
|
7837
|
+
if (errno !== 0) {
|
|
7838
|
+
_js_wasm_trace(
|
|
7839
|
+
'js_flock(%d, %d) get_vfs_path_from_fd errno %d',
|
|
7840
|
+
fd,
|
|
7841
|
+
op,
|
|
7842
|
+
vfsPath,
|
|
7843
|
+
errno
|
|
7844
|
+
);
|
|
7845
|
+
return -errno;
|
|
7846
|
+
}
|
|
7847
|
+
if (!locking.is_path_to_shared_fs(vfsPath)) {
|
|
7848
|
+
_js_wasm_trace(
|
|
7849
|
+
'flock(%d, %d) locking is not implemented for non-NodeFS path %s',
|
|
7850
|
+
fd,
|
|
7851
|
+
op,
|
|
7852
|
+
vfsPath
|
|
7853
|
+
);
|
|
7854
|
+
// If not a NodeFS path, we can't lock it.
|
|
7855
|
+
// Default to succeeding as Emscripten does.
|
|
7856
|
+
return 0;
|
|
7857
|
+
}
|
|
7858
|
+
errno = locking.check_lock_params(fd, op);
|
|
7859
|
+
if (errno !== 0) {
|
|
7860
|
+
_js_wasm_trace(
|
|
7861
|
+
'js_flock(%d, %d) check_lock_params errno %d',
|
|
7862
|
+
fd,
|
|
7863
|
+
op,
|
|
7864
|
+
errno
|
|
7865
|
+
);
|
|
7866
|
+
return -errno;
|
|
7867
|
+
}
|
|
7868
|
+
// @TODO: Consider supporting blocking mode of flock()
|
|
7869
|
+
if (op & (emscripten_LOCK_NB === 0)) {
|
|
7870
|
+
_js_wasm_trace(
|
|
7871
|
+
'js_flock(%d, %d) blocking mode of flock() is not implemented',
|
|
7872
|
+
fd,
|
|
7873
|
+
op
|
|
7874
|
+
);
|
|
7875
|
+
// We do not yet support the blocking form of flock().
|
|
7876
|
+
// We respond with EINVAL to indicate failure
|
|
7877
|
+
// because it is a known errno for a failed blocking flock().
|
|
7878
|
+
return -ERRNO_CODES.EINVAL;
|
|
7879
|
+
}
|
|
7880
|
+
const maskedOp =
|
|
7881
|
+
op & (emscripten_LOCK_SH | emscripten_LOCK_EX | emscripten_LOCK_UN);
|
|
7882
|
+
const lockOpType = flockToLockOpType[maskedOp];
|
|
7883
|
+
if (lockOpType === undefined) {
|
|
7884
|
+
_js_wasm_trace(
|
|
7885
|
+
'js_flock(%d, %d) invalid flock() operation',
|
|
7886
|
+
fd,
|
|
7887
|
+
op
|
|
7888
|
+
);
|
|
7889
|
+
return -ERRNO_CODES.EINVAL;
|
|
7890
|
+
}
|
|
7891
|
+
const nativeFilePath = locking.get_native_path_from_vfs_path(vfsPath);
|
|
7892
|
+
const obtainedLock = await PHPLoader.fileLockManager.lockWholeFile(
|
|
7893
|
+
nativeFilePath,
|
|
7894
|
+
{
|
|
7895
|
+
type: lockOpType,
|
|
7896
|
+
pid: PHPLoader.processId,
|
|
7897
|
+
fd,
|
|
7898
|
+
}
|
|
7899
|
+
);
|
|
7900
|
+
_js_wasm_trace(
|
|
7901
|
+
'js_flock(%d, %d) lockWholeFile %s returned %d',
|
|
7902
|
+
fd,
|
|
7903
|
+
op,
|
|
7904
|
+
vfsPath,
|
|
7905
|
+
obtainedLock
|
|
7906
|
+
);
|
|
7907
|
+
return obtainedLock ? 0 : -ERRNO_CODES.EWOULDBLOCK;
|
|
7908
|
+
}
|
|
7909
|
+
|
|
7910
|
+
_js_flock.isAsync = true;
|
|
7911
|
+
|
|
7300
7912
|
function _js_open_process(
|
|
7301
7913
|
command,
|
|
7302
7914
|
argsPtr,
|
|
@@ -7569,6 +8181,21 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7569
8181
|
return 0;
|
|
7570
8182
|
}
|
|
7571
8183
|
|
|
8184
|
+
var _js_release_file_locks = async function js_release_file_locks() {
|
|
8185
|
+
_js_wasm_trace('js_release_file_locks()');
|
|
8186
|
+
const pid = PHPLoader.processId;
|
|
8187
|
+
return await PHPLoader.fileLockManager
|
|
8188
|
+
.releaseLocksForProcess(pid)
|
|
8189
|
+
.then(() => {
|
|
8190
|
+
_js_wasm_trace('js_release_file_locks succeeded');
|
|
8191
|
+
})
|
|
8192
|
+
.catch((e) => {
|
|
8193
|
+
_js_wasm_trace('js_release_file_locks error %s', e);
|
|
8194
|
+
});
|
|
8195
|
+
};
|
|
8196
|
+
|
|
8197
|
+
_js_release_file_locks.isAsync = true;
|
|
8198
|
+
|
|
7572
8199
|
function _js_waitpid(pid, exitCodePtr) {
|
|
7573
8200
|
if (!PHPWASM.child_proc_by_pid[pid]) {
|
|
7574
8201
|
return -1;
|
|
@@ -8502,9 +9129,13 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8502
9129
|
/** @export */ getprotobyname: _getprotobyname,
|
|
8503
9130
|
/** @export */ getprotobynumber: _getprotobynumber,
|
|
8504
9131
|
/** @export */ js_create_input_device: _js_create_input_device,
|
|
9132
|
+
/** @export */ js_flock: _js_flock,
|
|
9133
|
+
/** @export */ js_getpid: _js_getpid,
|
|
8505
9134
|
/** @export */ js_open_process: _js_open_process,
|
|
8506
9135
|
/** @export */ js_process_status: _js_process_status,
|
|
9136
|
+
/** @export */ js_release_file_locks: _js_release_file_locks,
|
|
8507
9137
|
/** @export */ js_waitpid: _js_waitpid,
|
|
9138
|
+
/** @export */ js_wasm_trace: _js_wasm_trace,
|
|
8508
9139
|
/** @export */ makecontext: _makecontext,
|
|
8509
9140
|
/** @export */ proc_exit: _proc_exit,
|
|
8510
9141
|
/** @export */ strptime: _strptime,
|
|
@@ -8523,6 +9154,9 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8523
9154
|
|
|
8524
9155
|
var _malloc = (a0) => (_malloc = wasmExports['malloc'])(a0);
|
|
8525
9156
|
|
|
9157
|
+
var _getpid = (Module['_getpid'] = () =>
|
|
9158
|
+
(_getpid = Module['_getpid'] = wasmExports['getpid'])());
|
|
9159
|
+
|
|
8526
9160
|
var _wasm_popen = (Module['_wasm_popen'] = (a0, a1) =>
|
|
8527
9161
|
(_wasm_popen = Module['_wasm_popen'] = wasmExports['wasm_popen'])(
|
|
8528
9162
|
a0,
|
|
@@ -8548,6 +9182,9 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8548
9182
|
|
|
8549
9183
|
var _fflush = (a0) => (_fflush = wasmExports['fflush'])(a0);
|
|
8550
9184
|
|
|
9185
|
+
var _flock = (Module['_flock'] = (a0, a1) =>
|
|
9186
|
+
(_flock = Module['_flock'] = wasmExports['flock'])(a0, a1));
|
|
9187
|
+
|
|
8551
9188
|
var _wasm_read = (Module['_wasm_read'] = (a0, a1, a2) =>
|
|
8552
9189
|
(_wasm_read = Module['_wasm_read'] = wasmExports['wasm_read'])(
|
|
8553
9190
|
a0,
|
|
@@ -8646,6 +9283,16 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8646
9283
|
var _wasm_free = (Module['_wasm_free'] = (a0) =>
|
|
8647
9284
|
(_wasm_free = Module['_wasm_free'] = wasmExports['wasm_free'])(a0));
|
|
8648
9285
|
|
|
9286
|
+
var _wasm_get_end_offset = (Module['_wasm_get_end_offset'] = (a0) =>
|
|
9287
|
+
(_wasm_get_end_offset = Module['_wasm_get_end_offset'] =
|
|
9288
|
+
wasmExports['wasm_get_end_offset'])(a0));
|
|
9289
|
+
|
|
9290
|
+
var _wasm_trace = (Module['_wasm_trace'] = (a0, a1) =>
|
|
9291
|
+
(_wasm_trace = Module['_wasm_trace'] = wasmExports['wasm_trace'])(
|
|
9292
|
+
a0,
|
|
9293
|
+
a1
|
|
9294
|
+
));
|
|
9295
|
+
|
|
8649
9296
|
var ___funcs_on_exit = () =>
|
|
8650
9297
|
(___funcs_on_exit = wasmExports['__funcs_on_exit'])();
|
|
8651
9298
|
|
|
@@ -8793,6 +9440,32 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8793
9440
|
PHPLoader['free'] =
|
|
8794
9441
|
typeof _free === 'function' ? _free : PHPLoader['_wasm_free'];
|
|
8795
9442
|
|
|
9443
|
+
if (typeof NODEFS === 'object') {
|
|
9444
|
+
// We override NODEFS.createNode() to add an `isSharedFS` flag to all NODEFS
|
|
9445
|
+
// nodes. This way we can tell whether file-locking is needed and possible
|
|
9446
|
+
// for an FS node, even if wrapped with PROXYFS.
|
|
9447
|
+
const originalCreateNode = NODEFS.createNode;
|
|
9448
|
+
NODEFS.createNode = function createNodeWithSharedFlag() {
|
|
9449
|
+
const node = originalCreateNode.apply(NODEFS, arguments);
|
|
9450
|
+
node.isSharedFS = true;
|
|
9451
|
+
return node;
|
|
9452
|
+
};
|
|
9453
|
+
|
|
9454
|
+
var originalHashAddNode = FS.hashAddNode;
|
|
9455
|
+
FS.hashAddNode = function hashAddNodeIfNotSharedFS(node) {
|
|
9456
|
+
if (
|
|
9457
|
+
typeof locking === 'object' &&
|
|
9458
|
+
locking?.is_shared_fs_node(node)
|
|
9459
|
+
) {
|
|
9460
|
+
// Avoid caching shared VFS nodes so multiple instances
|
|
9461
|
+
// can access the same underlying filesystem without
|
|
9462
|
+
// conflicting caches.
|
|
9463
|
+
return;
|
|
9464
|
+
}
|
|
9465
|
+
return originalHashAddNode.apply(FS, arguments);
|
|
9466
|
+
};
|
|
9467
|
+
}
|
|
9468
|
+
|
|
8796
9469
|
return PHPLoader;
|
|
8797
9470
|
|
|
8798
9471
|
// Close the opening bracket from esm-prefix.js:
|