5112 lines
159 KiB
JavaScript
5112 lines
159 KiB
JavaScript
var libarchive = (function() {
|
|
var _scriptDir =
|
|
typeof document !== 'undefined' && document.currentScript
|
|
? document.currentScript.src
|
|
: undefined
|
|
return function(libarchive) {
|
|
libarchive = libarchive || {}
|
|
|
|
var Module = typeof libarchive !== 'undefined' ? libarchive : {}
|
|
var moduleOverrides = {}
|
|
var key
|
|
for (key in Module) {
|
|
if (Module.hasOwnProperty(key)) {
|
|
moduleOverrides[key] = Module[key]
|
|
}
|
|
}
|
|
Module['arguments'] = []
|
|
Module['thisProgram'] = './this.program'
|
|
Module['quit'] = function(status, toThrow) {
|
|
throw toThrow
|
|
}
|
|
Module['preRun'] = []
|
|
Module['postRun'] = []
|
|
var ENVIRONMENT_IS_WEB = false
|
|
var ENVIRONMENT_IS_WORKER = false
|
|
var ENVIRONMENT_IS_NODE = false
|
|
var ENVIRONMENT_IS_SHELL = false
|
|
ENVIRONMENT_IS_WEB = typeof window === 'object'
|
|
ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'
|
|
ENVIRONMENT_IS_NODE =
|
|
typeof process === 'object' &&
|
|
typeof require === 'function' &&
|
|
!ENVIRONMENT_IS_WEB &&
|
|
!ENVIRONMENT_IS_WORKER
|
|
ENVIRONMENT_IS_SHELL =
|
|
!ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER
|
|
var scriptDirectory = ''
|
|
function locateFile(path) {
|
|
if (Module['locateFile']) {
|
|
return Module['locateFile'](path, scriptDirectory)
|
|
} else {
|
|
return scriptDirectory + path
|
|
}
|
|
}
|
|
if (ENVIRONMENT_IS_NODE) {
|
|
scriptDirectory = __dirname + '/'
|
|
var nodeFS
|
|
var nodePath
|
|
Module['read'] = function shell_read(filename, binary) {
|
|
var ret
|
|
if (!nodeFS) nodeFS = require('fs')
|
|
if (!nodePath) nodePath = require('path')
|
|
filename = nodePath['normalize'](filename)
|
|
ret = nodeFS['readFileSync'](filename)
|
|
return binary ? ret : ret.toString()
|
|
}
|
|
Module['readBinary'] = function readBinary(filename) {
|
|
var ret = Module['read'](filename, true)
|
|
if (!ret.buffer) {
|
|
ret = new Uint8Array(ret)
|
|
}
|
|
assert(ret.buffer)
|
|
return ret
|
|
}
|
|
if (process['argv'].length > 1) {
|
|
Module['thisProgram'] = process['argv'][1].replace(/\\/g, '/')
|
|
}
|
|
Module['arguments'] = process['argv'].slice(2)
|
|
process['on']('uncaughtException', function(ex) {
|
|
if (!(ex instanceof ExitStatus)) {
|
|
throw ex
|
|
}
|
|
})
|
|
process['on']('unhandledRejection', abort)
|
|
Module['quit'] = function(status) {
|
|
process['exit'](status)
|
|
}
|
|
Module['inspect'] = function() {
|
|
return '[Emscripten Module object]'
|
|
}
|
|
} else if (ENVIRONMENT_IS_SHELL) {
|
|
if (typeof read != 'undefined') {
|
|
Module['read'] = function shell_read(f) {
|
|
return read(f)
|
|
}
|
|
}
|
|
Module['readBinary'] = function readBinary(f) {
|
|
var data
|
|
if (typeof readbuffer === 'function') {
|
|
return new Uint8Array(readbuffer(f))
|
|
}
|
|
data = read(f, 'binary')
|
|
assert(typeof data === 'object')
|
|
return data
|
|
}
|
|
if (typeof scriptArgs != 'undefined') {
|
|
Module['arguments'] = scriptArgs
|
|
} else if (typeof arguments != 'undefined') {
|
|
Module['arguments'] = arguments
|
|
}
|
|
if (typeof quit === 'function') {
|
|
Module['quit'] = function(status) {
|
|
quit(status)
|
|
}
|
|
}
|
|
} else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
|
|
if (ENVIRONMENT_IS_WORKER) {
|
|
scriptDirectory = self.location.href
|
|
} else if (document.currentScript) {
|
|
scriptDirectory = document.currentScript.src
|
|
}
|
|
if (_scriptDir) {
|
|
scriptDirectory = _scriptDir
|
|
}
|
|
if (scriptDirectory.indexOf('blob:') !== 0) {
|
|
scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf('/') + 1)
|
|
} else {
|
|
scriptDirectory = ''
|
|
}
|
|
Module['read'] = function shell_read(url) {
|
|
var xhr = new XMLHttpRequest()
|
|
xhr.open('GET', url, false)
|
|
xhr.send(null)
|
|
return xhr.responseText
|
|
}
|
|
if (ENVIRONMENT_IS_WORKER) {
|
|
Module['readBinary'] = function readBinary(url) {
|
|
var xhr = new XMLHttpRequest()
|
|
xhr.open('GET', url, false)
|
|
xhr.responseType = 'arraybuffer'
|
|
xhr.send(null)
|
|
return new Uint8Array(xhr.response)
|
|
}
|
|
}
|
|
Module['readAsync'] = function readAsync(url, onload, onerror) {
|
|
var xhr = new XMLHttpRequest()
|
|
xhr.open('GET', url, true)
|
|
xhr.responseType = 'arraybuffer'
|
|
xhr.onload = function xhr_onload() {
|
|
if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) {
|
|
onload(xhr.response)
|
|
return
|
|
}
|
|
onerror()
|
|
}
|
|
xhr.onerror = onerror
|
|
xhr.send(null)
|
|
}
|
|
Module['setWindowTitle'] = function(title) {
|
|
document.title = title
|
|
}
|
|
} else {
|
|
}
|
|
var out =
|
|
Module['print'] ||
|
|
(typeof console !== 'undefined'
|
|
? console.log.bind(console)
|
|
: typeof print !== 'undefined'
|
|
? print
|
|
: null)
|
|
var err =
|
|
Module['printErr'] ||
|
|
(typeof printErr !== 'undefined'
|
|
? printErr
|
|
: (typeof console !== 'undefined' && console.warn.bind(console)) || out)
|
|
for (key in moduleOverrides) {
|
|
if (moduleOverrides.hasOwnProperty(key)) {
|
|
Module[key] = moduleOverrides[key]
|
|
}
|
|
}
|
|
moduleOverrides = undefined
|
|
function dynamicAlloc(size) {
|
|
var ret = HEAP32[DYNAMICTOP_PTR >> 2]
|
|
var end = (ret + size + 15) & -16
|
|
if (end <= _emscripten_get_heap_size()) {
|
|
HEAP32[DYNAMICTOP_PTR >> 2] = end
|
|
} else {
|
|
var success = _emscripten_resize_heap(end)
|
|
if (!success) return 0
|
|
}
|
|
return ret
|
|
}
|
|
function getNativeTypeSize(type) {
|
|
switch (type) {
|
|
case 'i1':
|
|
case 'i8':
|
|
return 1
|
|
case 'i16':
|
|
return 2
|
|
case 'i32':
|
|
return 4
|
|
case 'i64':
|
|
return 8
|
|
case 'float':
|
|
return 4
|
|
case 'double':
|
|
return 8
|
|
default: {
|
|
if (type[type.length - 1] === '*') {
|
|
return 4
|
|
} else if (type[0] === 'i') {
|
|
var bits = parseInt(type.substr(1))
|
|
assert(
|
|
bits % 8 === 0,
|
|
'getNativeTypeSize invalid bits ' + bits + ', type ' + type
|
|
)
|
|
return bits / 8
|
|
} else {
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var asm2wasmImports = {
|
|
'f64-rem': function(x, y) {
|
|
return x % y
|
|
},
|
|
debugger: function() {
|
|
debugger
|
|
},
|
|
}
|
|
var functionPointers = new Array(0)
|
|
var tempRet0 = 0
|
|
var setTempRet0 = function(value) {
|
|
tempRet0 = value
|
|
}
|
|
if (typeof WebAssembly !== 'object') {
|
|
err('no native wasm support detected')
|
|
}
|
|
var wasmMemory
|
|
var wasmTable
|
|
var ABORT = false
|
|
var EXITSTATUS = 0
|
|
function assert(condition, text) {
|
|
if (!condition) {
|
|
abort('Assertion failed: ' + text)
|
|
}
|
|
}
|
|
function getCFunc(ident) {
|
|
var func = Module['_' + ident]
|
|
assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported')
|
|
return func
|
|
}
|
|
function ccall(ident, returnType, argTypes, args, opts) {
|
|
var toC = {
|
|
string: function(str) {
|
|
var ret = 0
|
|
if (str !== null && str !== undefined && str !== 0) {
|
|
var len = (str.length << 2) + 1
|
|
ret = stackAlloc(len)
|
|
stringToUTF8(str, ret, len)
|
|
}
|
|
return ret
|
|
},
|
|
array: function(arr) {
|
|
var ret = stackAlloc(arr.length)
|
|
writeArrayToMemory(arr, ret)
|
|
return ret
|
|
},
|
|
}
|
|
function convertReturnValue(ret) {
|
|
if (returnType === 'string') return UTF8ToString(ret)
|
|
if (returnType === 'boolean') return Boolean(ret)
|
|
return ret
|
|
}
|
|
var func = getCFunc(ident)
|
|
var cArgs = []
|
|
var stack = 0
|
|
if (args) {
|
|
for (var i = 0; i < args.length; i++) {
|
|
var converter = toC[argTypes[i]]
|
|
if (converter) {
|
|
if (stack === 0) stack = stackSave()
|
|
cArgs[i] = converter(args[i])
|
|
} else {
|
|
cArgs[i] = args[i]
|
|
}
|
|
}
|
|
}
|
|
var ret = func.apply(null, cArgs)
|
|
ret = convertReturnValue(ret)
|
|
if (stack !== 0) stackRestore(stack)
|
|
return ret
|
|
}
|
|
function cwrap(ident, returnType, argTypes, opts) {
|
|
argTypes = argTypes || []
|
|
var numericArgs = argTypes.every(function(type) {
|
|
return type === 'number'
|
|
})
|
|
var numericRet = returnType !== 'string'
|
|
if (numericRet && numericArgs && !opts) {
|
|
return getCFunc(ident)
|
|
}
|
|
return function() {
|
|
return ccall(ident, returnType, argTypes, arguments, opts)
|
|
}
|
|
}
|
|
function setValue(ptr, value, type, noSafe) {
|
|
type = type || 'i8'
|
|
if (type.charAt(type.length - 1) === '*') type = 'i32'
|
|
switch (type) {
|
|
case 'i1':
|
|
HEAP8[ptr >> 0] = value
|
|
break
|
|
case 'i8':
|
|
HEAP8[ptr >> 0] = value
|
|
break
|
|
case 'i16':
|
|
HEAP16[ptr >> 1] = value
|
|
break
|
|
case 'i32':
|
|
HEAP32[ptr >> 2] = value
|
|
break
|
|
case 'i64':
|
|
;(tempI64 = [
|
|
value >>> 0,
|
|
((tempDouble = value),
|
|
+Math_abs(tempDouble) >= 1
|
|
? tempDouble > 0
|
|
? (Math_min(+Math_floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0
|
|
: ~~+Math_ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0
|
|
: 0),
|
|
]),
|
|
(HEAP32[ptr >> 2] = tempI64[0]),
|
|
(HEAP32[(ptr + 4) >> 2] = tempI64[1])
|
|
break
|
|
case 'float':
|
|
HEAPF32[ptr >> 2] = value
|
|
break
|
|
case 'double':
|
|
HEAPF64[ptr >> 3] = value
|
|
break
|
|
default:
|
|
abort('invalid type for setValue: ' + type)
|
|
}
|
|
}
|
|
var ALLOC_NORMAL = 0
|
|
var ALLOC_NONE = 3
|
|
function allocate(slab, types, allocator, ptr) {
|
|
var zeroinit, size
|
|
if (typeof slab === 'number') {
|
|
zeroinit = true
|
|
size = slab
|
|
} else {
|
|
zeroinit = false
|
|
size = slab.length
|
|
}
|
|
var singleType = typeof types === 'string' ? types : null
|
|
var ret
|
|
if (allocator == ALLOC_NONE) {
|
|
ret = ptr
|
|
} else {
|
|
ret = [_malloc, stackAlloc, dynamicAlloc][allocator](
|
|
Math.max(size, singleType ? 1 : types.length)
|
|
)
|
|
}
|
|
if (zeroinit) {
|
|
var stop
|
|
ptr = ret
|
|
assert((ret & 3) == 0)
|
|
stop = ret + (size & ~3)
|
|
for (; ptr < stop; ptr += 4) {
|
|
HEAP32[ptr >> 2] = 0
|
|
}
|
|
stop = ret + size
|
|
while (ptr < stop) {
|
|
HEAP8[ptr++ >> 0] = 0
|
|
}
|
|
return ret
|
|
}
|
|
if (singleType === 'i8') {
|
|
if (slab.subarray || slab.slice) {
|
|
HEAPU8.set(slab, ret)
|
|
} else {
|
|
HEAPU8.set(new Uint8Array(slab), ret)
|
|
}
|
|
return ret
|
|
}
|
|
var i = 0,
|
|
type,
|
|
typeSize,
|
|
previousType
|
|
while (i < size) {
|
|
var curr = slab[i]
|
|
type = singleType || types[i]
|
|
if (type === 0) {
|
|
i++
|
|
continue
|
|
}
|
|
if (type == 'i64') type = 'i32'
|
|
setValue(ret + i, curr, type)
|
|
if (previousType !== type) {
|
|
typeSize = getNativeTypeSize(type)
|
|
previousType = type
|
|
}
|
|
i += typeSize
|
|
}
|
|
return ret
|
|
}
|
|
function getMemory(size) {
|
|
if (!runtimeInitialized) return dynamicAlloc(size)
|
|
return _malloc(size)
|
|
}
|
|
var UTF8Decoder =
|
|
typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined
|
|
function UTF8ArrayToString(u8Array, idx, maxBytesToRead) {
|
|
var endIdx = idx + maxBytesToRead
|
|
var endPtr = idx
|
|
while (u8Array[endPtr] && !(endPtr >= endIdx)) ++endPtr
|
|
if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) {
|
|
return UTF8Decoder.decode(u8Array.subarray(idx, endPtr))
|
|
} else {
|
|
var str = ''
|
|
while (idx < endPtr) {
|
|
var u0 = u8Array[idx++]
|
|
if (!(u0 & 128)) {
|
|
str += String.fromCharCode(u0)
|
|
continue
|
|
}
|
|
var u1 = u8Array[idx++] & 63
|
|
if ((u0 & 224) == 192) {
|
|
str += String.fromCharCode(((u0 & 31) << 6) | u1)
|
|
continue
|
|
}
|
|
var u2 = u8Array[idx++] & 63
|
|
if ((u0 & 240) == 224) {
|
|
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2
|
|
} else {
|
|
u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (u8Array[idx++] & 63)
|
|
}
|
|
if (u0 < 65536) {
|
|
str += String.fromCharCode(u0)
|
|
} else {
|
|
var ch = u0 - 65536
|
|
str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023))
|
|
}
|
|
}
|
|
}
|
|
return str
|
|
}
|
|
function UTF8ToString(ptr, maxBytesToRead) {
|
|
return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''
|
|
}
|
|
function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) {
|
|
if (!(maxBytesToWrite > 0)) return 0
|
|
var startIdx = outIdx
|
|
var endIdx = outIdx + maxBytesToWrite - 1
|
|
for (var i = 0; i < str.length; ++i) {
|
|
var u = str.charCodeAt(i)
|
|
if (u >= 55296 && u <= 57343) {
|
|
var u1 = str.charCodeAt(++i)
|
|
u = (65536 + ((u & 1023) << 10)) | (u1 & 1023)
|
|
}
|
|
if (u <= 127) {
|
|
if (outIdx >= endIdx) break
|
|
outU8Array[outIdx++] = u
|
|
} else if (u <= 2047) {
|
|
if (outIdx + 1 >= endIdx) break
|
|
outU8Array[outIdx++] = 192 | (u >> 6)
|
|
outU8Array[outIdx++] = 128 | (u & 63)
|
|
} else if (u <= 65535) {
|
|
if (outIdx + 2 >= endIdx) break
|
|
outU8Array[outIdx++] = 224 | (u >> 12)
|
|
outU8Array[outIdx++] = 128 | ((u >> 6) & 63)
|
|
outU8Array[outIdx++] = 128 | (u & 63)
|
|
} else {
|
|
if (outIdx + 3 >= endIdx) break
|
|
outU8Array[outIdx++] = 240 | (u >> 18)
|
|
outU8Array[outIdx++] = 128 | ((u >> 12) & 63)
|
|
outU8Array[outIdx++] = 128 | ((u >> 6) & 63)
|
|
outU8Array[outIdx++] = 128 | (u & 63)
|
|
}
|
|
}
|
|
outU8Array[outIdx] = 0
|
|
return outIdx - startIdx
|
|
}
|
|
function stringToUTF8(str, outPtr, maxBytesToWrite) {
|
|
return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite)
|
|
}
|
|
function lengthBytesUTF8(str) {
|
|
var len = 0
|
|
for (var i = 0; i < str.length; ++i) {
|
|
var u = str.charCodeAt(i)
|
|
if (u >= 55296 && u <= 57343)
|
|
u = (65536 + ((u & 1023) << 10)) | (str.charCodeAt(++i) & 1023)
|
|
if (u <= 127) ++len
|
|
else if (u <= 2047) len += 2
|
|
else if (u <= 65535) len += 3
|
|
else len += 4
|
|
}
|
|
return len
|
|
}
|
|
var UTF16Decoder =
|
|
typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined
|
|
function writeArrayToMemory(array, buffer) {
|
|
HEAP8.set(array, buffer)
|
|
}
|
|
function writeAsciiToMemory(str, buffer, dontAddNull) {
|
|
for (var i = 0; i < str.length; ++i) {
|
|
HEAP8[buffer++ >> 0] = str.charCodeAt(i)
|
|
}
|
|
if (!dontAddNull) HEAP8[buffer >> 0] = 0
|
|
}
|
|
function demangle(func) {
|
|
return func
|
|
}
|
|
function demangleAll(text) {
|
|
var regex = /__Z[\w\d_]+/g
|
|
return text.replace(regex, function(x) {
|
|
var y = demangle(x)
|
|
return x === y ? x : y + ' [' + x + ']'
|
|
})
|
|
}
|
|
function jsStackTrace() {
|
|
var err = new Error()
|
|
if (!err.stack) {
|
|
try {
|
|
throw new Error(0)
|
|
} catch (e) {
|
|
err = e
|
|
}
|
|
if (!err.stack) {
|
|
return '(no stack trace available)'
|
|
}
|
|
}
|
|
return err.stack.toString()
|
|
}
|
|
function stackTrace() {
|
|
var js = jsStackTrace()
|
|
if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace']()
|
|
return demangleAll(js)
|
|
}
|
|
var WASM_PAGE_SIZE = 65536
|
|
function alignUp(x, multiple) {
|
|
if (x % multiple > 0) {
|
|
x += multiple - (x % multiple)
|
|
}
|
|
return x
|
|
}
|
|
var buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64
|
|
function updateGlobalBufferViews() {
|
|
Module['HEAP8'] = HEAP8 = new Int8Array(buffer)
|
|
Module['HEAP16'] = HEAP16 = new Int16Array(buffer)
|
|
Module['HEAP32'] = HEAP32 = new Int32Array(buffer)
|
|
Module['HEAPU8'] = HEAPU8 = new Uint8Array(buffer)
|
|
Module['HEAPU16'] = HEAPU16 = new Uint16Array(buffer)
|
|
Module['HEAPU32'] = HEAPU32 = new Uint32Array(buffer)
|
|
Module['HEAPF32'] = HEAPF32 = new Float32Array(buffer)
|
|
Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer)
|
|
}
|
|
var DYNAMIC_BASE = 5520464,
|
|
DYNAMICTOP_PTR = 277552
|
|
var TOTAL_STACK = 5242880
|
|
var INITIAL_TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216
|
|
if (INITIAL_TOTAL_MEMORY < TOTAL_STACK)
|
|
err(
|
|
'TOTAL_MEMORY should be larger than TOTAL_STACK, was ' +
|
|
INITIAL_TOTAL_MEMORY +
|
|
'! (TOTAL_STACK=' +
|
|
TOTAL_STACK +
|
|
')'
|
|
)
|
|
if (Module['buffer']) {
|
|
buffer = Module['buffer']
|
|
} else {
|
|
if (typeof WebAssembly === 'object' && typeof WebAssembly.Memory === 'function') {
|
|
wasmMemory = new WebAssembly.Memory({
|
|
initial: INITIAL_TOTAL_MEMORY / WASM_PAGE_SIZE,
|
|
})
|
|
buffer = wasmMemory.buffer
|
|
} else {
|
|
buffer = new ArrayBuffer(INITIAL_TOTAL_MEMORY)
|
|
}
|
|
}
|
|
updateGlobalBufferViews()
|
|
HEAP32[DYNAMICTOP_PTR >> 2] = DYNAMIC_BASE
|
|
function callRuntimeCallbacks(callbacks) {
|
|
while (callbacks.length > 0) {
|
|
var callback = callbacks.shift()
|
|
if (typeof callback == 'function') {
|
|
callback()
|
|
continue
|
|
}
|
|
var func = callback.func
|
|
if (typeof func === 'number') {
|
|
if (callback.arg === undefined) {
|
|
Module['dynCall_v'](func)
|
|
} else {
|
|
Module['dynCall_vi'](func, callback.arg)
|
|
}
|
|
} else {
|
|
func(callback.arg === undefined ? null : callback.arg)
|
|
}
|
|
}
|
|
}
|
|
var __ATPRERUN__ = []
|
|
var __ATINIT__ = []
|
|
var __ATMAIN__ = []
|
|
var __ATPOSTRUN__ = []
|
|
var runtimeInitialized = false
|
|
var runtimeExited = false
|
|
function preRun() {
|
|
if (Module['preRun']) {
|
|
if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]
|
|
while (Module['preRun'].length) {
|
|
addOnPreRun(Module['preRun'].shift())
|
|
}
|
|
}
|
|
callRuntimeCallbacks(__ATPRERUN__)
|
|
}
|
|
function ensureInitRuntime() {
|
|
if (runtimeInitialized) return
|
|
runtimeInitialized = true
|
|
if (!Module['noFSInit'] && !FS.init.initialized) FS.init()
|
|
TTY.init()
|
|
PIPEFS.root = FS.mount(PIPEFS, {}, null)
|
|
callRuntimeCallbacks(__ATINIT__)
|
|
}
|
|
function preMain() {
|
|
FS.ignorePermissions = false
|
|
callRuntimeCallbacks(__ATMAIN__)
|
|
}
|
|
function exitRuntime() {
|
|
runtimeExited = true
|
|
}
|
|
function postRun() {
|
|
if (Module['postRun']) {
|
|
if (typeof Module['postRun'] == 'function')
|
|
Module['postRun'] = [Module['postRun']]
|
|
while (Module['postRun'].length) {
|
|
addOnPostRun(Module['postRun'].shift())
|
|
}
|
|
}
|
|
callRuntimeCallbacks(__ATPOSTRUN__)
|
|
}
|
|
function addOnPreRun(cb) {
|
|
__ATPRERUN__.unshift(cb)
|
|
}
|
|
function addOnPostRun(cb) {
|
|
__ATPOSTRUN__.unshift(cb)
|
|
}
|
|
var Math_abs = Math.abs
|
|
var Math_ceil = Math.ceil
|
|
var Math_floor = Math.floor
|
|
var Math_min = Math.min
|
|
var runDependencies = 0
|
|
var runDependencyWatcher = null
|
|
var dependenciesFulfilled = null
|
|
function getUniqueRunDependency(id) {
|
|
return id
|
|
}
|
|
function addRunDependency(id) {
|
|
runDependencies++
|
|
if (Module['monitorRunDependencies']) {
|
|
Module['monitorRunDependencies'](runDependencies)
|
|
}
|
|
}
|
|
function removeRunDependency(id) {
|
|
runDependencies--
|
|
if (Module['monitorRunDependencies']) {
|
|
Module['monitorRunDependencies'](runDependencies)
|
|
}
|
|
if (runDependencies == 0) {
|
|
if (runDependencyWatcher !== null) {
|
|
clearInterval(runDependencyWatcher)
|
|
runDependencyWatcher = null
|
|
}
|
|
if (dependenciesFulfilled) {
|
|
var callback = dependenciesFulfilled
|
|
dependenciesFulfilled = null
|
|
callback()
|
|
}
|
|
}
|
|
}
|
|
Module['preloadedImages'] = {}
|
|
Module['preloadedAudios'] = {}
|
|
var dataURIPrefix = 'data:application/octet-stream;base64,'
|
|
function isDataURI(filename) {
|
|
return String.prototype.startsWith
|
|
? filename.startsWith(dataURIPrefix)
|
|
: filename.indexOf(dataURIPrefix) === 0
|
|
}
|
|
var wasmBinaryFile = 'libarchive.wasm'
|
|
if (!isDataURI(wasmBinaryFile)) {
|
|
wasmBinaryFile = locateFile(wasmBinaryFile)
|
|
}
|
|
function getBinary() {
|
|
try {
|
|
if (Module['wasmBinary']) {
|
|
return new Uint8Array(Module['wasmBinary'])
|
|
}
|
|
if (Module['readBinary']) {
|
|
return Module['readBinary'](wasmBinaryFile)
|
|
} else {
|
|
throw 'both async and sync fetching of the wasm failed'
|
|
}
|
|
} catch (err) {
|
|
abort(err)
|
|
}
|
|
}
|
|
function getBinaryPromise() {
|
|
if (
|
|
!Module['wasmBinary'] &&
|
|
(ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) &&
|
|
typeof fetch === 'function'
|
|
) {
|
|
return fetch(wasmBinaryFile, { credentials: 'same-origin' })
|
|
.then(function(response) {
|
|
if (!response['ok']) {
|
|
throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"
|
|
}
|
|
return response['arrayBuffer']()
|
|
})
|
|
.catch(function() {
|
|
return getBinary()
|
|
})
|
|
}
|
|
return new Promise(function(resolve, reject) {
|
|
resolve(getBinary())
|
|
})
|
|
}
|
|
function createWasm(env) {
|
|
var info = {
|
|
env: env,
|
|
global: { NaN: NaN, Infinity: Infinity },
|
|
'global.Math': Math,
|
|
asm2wasm: asm2wasmImports,
|
|
}
|
|
function receiveInstance(instance, module) {
|
|
var exports = instance.exports
|
|
Module['asm'] = exports
|
|
removeRunDependency('wasm-instantiate')
|
|
}
|
|
addRunDependency('wasm-instantiate')
|
|
if (Module['instantiateWasm']) {
|
|
try {
|
|
return Module['instantiateWasm'](info, receiveInstance)
|
|
} catch (e) {
|
|
err('Module.instantiateWasm callback failed with error: ' + e)
|
|
return false
|
|
}
|
|
}
|
|
function receiveInstantiatedSource(output) {
|
|
receiveInstance(output['instance'])
|
|
}
|
|
function instantiateArrayBuffer(receiver) {
|
|
getBinaryPromise()
|
|
.then(function(binary) {
|
|
return WebAssembly.instantiate(binary, info)
|
|
})
|
|
.then(receiver, function(reason) {
|
|
err('failed to asynchronously prepare wasm: ' + reason)
|
|
abort(reason)
|
|
})
|
|
}
|
|
if (
|
|
!Module['wasmBinary'] &&
|
|
typeof WebAssembly.instantiateStreaming === 'function' &&
|
|
!isDataURI(wasmBinaryFile) &&
|
|
typeof fetch === 'function'
|
|
) {
|
|
WebAssembly.instantiateStreaming(
|
|
fetch(wasmBinaryFile, { credentials: 'same-origin' }),
|
|
info
|
|
).then(receiveInstantiatedSource, function(reason) {
|
|
err('wasm streaming compile failed: ' + reason)
|
|
err('falling back to ArrayBuffer instantiation')
|
|
instantiateArrayBuffer(receiveInstantiatedSource)
|
|
})
|
|
} else {
|
|
instantiateArrayBuffer(receiveInstantiatedSource)
|
|
}
|
|
return {}
|
|
}
|
|
Module['asm'] = function(global, env, providedBuffer) {
|
|
env['memory'] = wasmMemory
|
|
env['table'] = wasmTable = new WebAssembly.Table({
|
|
initial: 507,
|
|
maximum: 507,
|
|
element: 'anyfunc',
|
|
})
|
|
env['__memory_base'] = 1024
|
|
env['__table_base'] = 0
|
|
var exports = createWasm(env)
|
|
return exports
|
|
}
|
|
__ATINIT__.push({
|
|
func: function() {
|
|
___emscripten_environ_constructor()
|
|
},
|
|
})
|
|
var ENV = {}
|
|
function ___buildEnvironment(environ) {
|
|
var MAX_ENV_VALUES = 64
|
|
var TOTAL_ENV_SIZE = 1024
|
|
var poolPtr
|
|
var envPtr
|
|
if (!___buildEnvironment.called) {
|
|
___buildEnvironment.called = true
|
|
ENV['USER'] = ENV['LOGNAME'] = 'web_user'
|
|
ENV['PATH'] = '/'
|
|
ENV['PWD'] = '/'
|
|
ENV['HOME'] = '/home/web_user'
|
|
ENV['LANG'] = 'C.UTF-8'
|
|
ENV['_'] = Module['thisProgram']
|
|
poolPtr = getMemory(TOTAL_ENV_SIZE)
|
|
envPtr = getMemory(MAX_ENV_VALUES * 4)
|
|
HEAP32[envPtr >> 2] = poolPtr
|
|
HEAP32[environ >> 2] = envPtr
|
|
} else {
|
|
envPtr = HEAP32[environ >> 2]
|
|
poolPtr = HEAP32[envPtr >> 2]
|
|
}
|
|
var strings = []
|
|
var totalSize = 0
|
|
for (var key in ENV) {
|
|
if (typeof ENV[key] === 'string') {
|
|
var line = key + '=' + ENV[key]
|
|
strings.push(line)
|
|
totalSize += line.length
|
|
}
|
|
}
|
|
if (totalSize > TOTAL_ENV_SIZE) {
|
|
throw new Error('Environment size exceeded TOTAL_ENV_SIZE!')
|
|
}
|
|
var ptrSize = 4
|
|
for (var i = 0; i < strings.length; i++) {
|
|
var line = strings[i]
|
|
writeAsciiToMemory(line, poolPtr)
|
|
HEAP32[(envPtr + i * ptrSize) >> 2] = poolPtr
|
|
poolPtr += line.length + 1
|
|
}
|
|
HEAP32[(envPtr + strings.length * ptrSize) >> 2] = 0
|
|
}
|
|
var PATH = {
|
|
splitPath: function(filename) {
|
|
var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/
|
|
return splitPathRe.exec(filename).slice(1)
|
|
},
|
|
normalizeArray: function(parts, allowAboveRoot) {
|
|
var up = 0
|
|
for (var i = parts.length - 1; i >= 0; i--) {
|
|
var last = parts[i]
|
|
if (last === '.') {
|
|
parts.splice(i, 1)
|
|
} else if (last === '..') {
|
|
parts.splice(i, 1)
|
|
up++
|
|
} else if (up) {
|
|
parts.splice(i, 1)
|
|
up--
|
|
}
|
|
}
|
|
if (allowAboveRoot) {
|
|
for (; up; up--) {
|
|
parts.unshift('..')
|
|
}
|
|
}
|
|
return parts
|
|
},
|
|
normalize: function(path) {
|
|
var isAbsolute = path.charAt(0) === '/',
|
|
trailingSlash = path.substr(-1) === '/'
|
|
path = PATH.normalizeArray(
|
|
path.split('/').filter(function(p) {
|
|
return !!p
|
|
}),
|
|
!isAbsolute
|
|
).join('/')
|
|
if (!path && !isAbsolute) {
|
|
path = '.'
|
|
}
|
|
if (path && trailingSlash) {
|
|
path += '/'
|
|
}
|
|
return (isAbsolute ? '/' : '') + path
|
|
},
|
|
dirname: function(path) {
|
|
var result = PATH.splitPath(path),
|
|
root = result[0],
|
|
dir = result[1]
|
|
if (!root && !dir) {
|
|
return '.'
|
|
}
|
|
if (dir) {
|
|
dir = dir.substr(0, dir.length - 1)
|
|
}
|
|
return root + dir
|
|
},
|
|
basename: function(path) {
|
|
if (path === '/') return '/'
|
|
var lastSlash = path.lastIndexOf('/')
|
|
if (lastSlash === -1) return path
|
|
return path.substr(lastSlash + 1)
|
|
},
|
|
extname: function(path) {
|
|
return PATH.splitPath(path)[3]
|
|
},
|
|
join: function() {
|
|
var paths = Array.prototype.slice.call(arguments, 0)
|
|
return PATH.normalize(paths.join('/'))
|
|
},
|
|
join2: function(l, r) {
|
|
return PATH.normalize(l + '/' + r)
|
|
},
|
|
}
|
|
function ___setErrNo(value) {
|
|
if (Module['___errno_location']) HEAP32[Module['___errno_location']() >> 2] = value
|
|
return value
|
|
}
|
|
var PATH_FS = {
|
|
resolve: function() {
|
|
var resolvedPath = '',
|
|
resolvedAbsolute = false
|
|
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
|
var path = i >= 0 ? arguments[i] : FS.cwd()
|
|
if (typeof path !== 'string') {
|
|
throw new TypeError('Arguments to path.resolve must be strings')
|
|
} else if (!path) {
|
|
return ''
|
|
}
|
|
resolvedPath = path + '/' + resolvedPath
|
|
resolvedAbsolute = path.charAt(0) === '/'
|
|
}
|
|
resolvedPath = PATH.normalizeArray(
|
|
resolvedPath.split('/').filter(function(p) {
|
|
return !!p
|
|
}),
|
|
!resolvedAbsolute
|
|
).join('/')
|
|
return (resolvedAbsolute ? '/' : '') + resolvedPath || '.'
|
|
},
|
|
relative: function(from, to) {
|
|
from = PATH_FS.resolve(from).substr(1)
|
|
to = PATH_FS.resolve(to).substr(1)
|
|
function trim(arr) {
|
|
var start = 0
|
|
for (; start < arr.length; start++) {
|
|
if (arr[start] !== '') break
|
|
}
|
|
var end = arr.length - 1
|
|
for (; end >= 0; end--) {
|
|
if (arr[end] !== '') break
|
|
}
|
|
if (start > end) return []
|
|
return arr.slice(start, end - start + 1)
|
|
}
|
|
var fromParts = trim(from.split('/'))
|
|
var toParts = trim(to.split('/'))
|
|
var length = Math.min(fromParts.length, toParts.length)
|
|
var samePartsLength = length
|
|
for (var i = 0; i < length; i++) {
|
|
if (fromParts[i] !== toParts[i]) {
|
|
samePartsLength = i
|
|
break
|
|
}
|
|
}
|
|
var outputParts = []
|
|
for (var i = samePartsLength; i < fromParts.length; i++) {
|
|
outputParts.push('..')
|
|
}
|
|
outputParts = outputParts.concat(toParts.slice(samePartsLength))
|
|
return outputParts.join('/')
|
|
},
|
|
}
|
|
var TTY = {
|
|
ttys: [],
|
|
init: function() {},
|
|
shutdown: function() {},
|
|
register: function(dev, ops) {
|
|
TTY.ttys[dev] = { input: [], output: [], ops: ops }
|
|
FS.registerDevice(dev, TTY.stream_ops)
|
|
},
|
|
stream_ops: {
|
|
open: function(stream) {
|
|
var tty = TTY.ttys[stream.node.rdev]
|
|
if (!tty) {
|
|
throw new FS.ErrnoError(19)
|
|
}
|
|
stream.tty = tty
|
|
stream.seekable = false
|
|
},
|
|
close: function(stream) {
|
|
stream.tty.ops.flush(stream.tty)
|
|
},
|
|
flush: function(stream) {
|
|
stream.tty.ops.flush(stream.tty)
|
|
},
|
|
read: function(stream, buffer, offset, length, pos) {
|
|
if (!stream.tty || !stream.tty.ops.get_char) {
|
|
throw new FS.ErrnoError(6)
|
|
}
|
|
var bytesRead = 0
|
|
for (var i = 0; i < length; i++) {
|
|
var result
|
|
try {
|
|
result = stream.tty.ops.get_char(stream.tty)
|
|
} catch (e) {
|
|
throw new FS.ErrnoError(5)
|
|
}
|
|
if (result === undefined && bytesRead === 0) {
|
|
throw new FS.ErrnoError(11)
|
|
}
|
|
if (result === null || result === undefined) break
|
|
bytesRead++
|
|
buffer[offset + i] = result
|
|
}
|
|
if (bytesRead) {
|
|
stream.node.timestamp = Date.now()
|
|
}
|
|
return bytesRead
|
|
},
|
|
write: function(stream, buffer, offset, length, pos) {
|
|
if (!stream.tty || !stream.tty.ops.put_char) {
|
|
throw new FS.ErrnoError(6)
|
|
}
|
|
try {
|
|
for (var i = 0; i < length; i++) {
|
|
stream.tty.ops.put_char(stream.tty, buffer[offset + i])
|
|
}
|
|
} catch (e) {
|
|
throw new FS.ErrnoError(5)
|
|
}
|
|
if (length) {
|
|
stream.node.timestamp = Date.now()
|
|
}
|
|
return i
|
|
},
|
|
},
|
|
default_tty_ops: {
|
|
get_char: function(tty) {
|
|
if (!tty.input.length) {
|
|
var result = null
|
|
if (ENVIRONMENT_IS_NODE) {
|
|
var BUFSIZE = 256
|
|
var buf = new Buffer(BUFSIZE)
|
|
var bytesRead = 0
|
|
var isPosixPlatform = process.platform != 'win32'
|
|
var fd = process.stdin.fd
|
|
if (isPosixPlatform) {
|
|
var usingDevice = false
|
|
try {
|
|
fd = fs.openSync('/dev/stdin', 'r')
|
|
usingDevice = true
|
|
} catch (e) {}
|
|
}
|
|
try {
|
|
bytesRead = fs.readSync(fd, buf, 0, BUFSIZE, null)
|
|
} catch (e) {
|
|
if (e.toString().indexOf('EOF') != -1) bytesRead = 0
|
|
else throw e
|
|
}
|
|
if (usingDevice) {
|
|
fs.closeSync(fd)
|
|
}
|
|
if (bytesRead > 0) {
|
|
result = buf.slice(0, bytesRead).toString('utf-8')
|
|
} else {
|
|
result = null
|
|
}
|
|
} else if (
|
|
typeof window != 'undefined' &&
|
|
typeof window.prompt == 'function'
|
|
) {
|
|
result = window.prompt('Input: ')
|
|
if (result !== null) {
|
|
result += '\n'
|
|
}
|
|
} else if (typeof readline == 'function') {
|
|
result = readline()
|
|
if (result !== null) {
|
|
result += '\n'
|
|
}
|
|
}
|
|
if (!result) {
|
|
return null
|
|
}
|
|
tty.input = intArrayFromString(result, true)
|
|
}
|
|
return tty.input.shift()
|
|
},
|
|
put_char: function(tty, val) {
|
|
if (val === null || val === 10) {
|
|
out(UTF8ArrayToString(tty.output, 0))
|
|
tty.output = []
|
|
} else {
|
|
if (val != 0) tty.output.push(val)
|
|
}
|
|
},
|
|
flush: function(tty) {
|
|
if (tty.output && tty.output.length > 0) {
|
|
out(UTF8ArrayToString(tty.output, 0))
|
|
tty.output = []
|
|
}
|
|
},
|
|
},
|
|
default_tty1_ops: {
|
|
put_char: function(tty, val) {
|
|
if (val === null || val === 10) {
|
|
err(UTF8ArrayToString(tty.output, 0))
|
|
tty.output = []
|
|
} else {
|
|
if (val != 0) tty.output.push(val)
|
|
}
|
|
},
|
|
flush: function(tty) {
|
|
if (tty.output && tty.output.length > 0) {
|
|
err(UTF8ArrayToString(tty.output, 0))
|
|
tty.output = []
|
|
}
|
|
},
|
|
},
|
|
}
|
|
var MEMFS = {
|
|
ops_table: null,
|
|
mount: function(mount) {
|
|
return MEMFS.createNode(null, '/', 16384 | 511, 0)
|
|
},
|
|
createNode: function(parent, name, mode, dev) {
|
|
if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
|
|
throw new FS.ErrnoError(1)
|
|
}
|
|
if (!MEMFS.ops_table) {
|
|
MEMFS.ops_table = {
|
|
dir: {
|
|
node: {
|
|
getattr: MEMFS.node_ops.getattr,
|
|
setattr: MEMFS.node_ops.setattr,
|
|
lookup: MEMFS.node_ops.lookup,
|
|
mknod: MEMFS.node_ops.mknod,
|
|
rename: MEMFS.node_ops.rename,
|
|
unlink: MEMFS.node_ops.unlink,
|
|
rmdir: MEMFS.node_ops.rmdir,
|
|
readdir: MEMFS.node_ops.readdir,
|
|
symlink: MEMFS.node_ops.symlink,
|
|
},
|
|
stream: { llseek: MEMFS.stream_ops.llseek },
|
|
},
|
|
file: {
|
|
node: { getattr: MEMFS.node_ops.getattr, setattr: MEMFS.node_ops.setattr },
|
|
stream: {
|
|
llseek: MEMFS.stream_ops.llseek,
|
|
read: MEMFS.stream_ops.read,
|
|
write: MEMFS.stream_ops.write,
|
|
allocate: MEMFS.stream_ops.allocate,
|
|
mmap: MEMFS.stream_ops.mmap,
|
|
msync: MEMFS.stream_ops.msync,
|
|
},
|
|
},
|
|
link: {
|
|
node: {
|
|
getattr: MEMFS.node_ops.getattr,
|
|
setattr: MEMFS.node_ops.setattr,
|
|
readlink: MEMFS.node_ops.readlink,
|
|
},
|
|
stream: {},
|
|
},
|
|
chrdev: {
|
|
node: { getattr: MEMFS.node_ops.getattr, setattr: MEMFS.node_ops.setattr },
|
|
stream: FS.chrdev_stream_ops,
|
|
},
|
|
}
|
|
}
|
|
var node = FS.createNode(parent, name, mode, dev)
|
|
if (FS.isDir(node.mode)) {
|
|
node.node_ops = MEMFS.ops_table.dir.node
|
|
node.stream_ops = MEMFS.ops_table.dir.stream
|
|
node.contents = {}
|
|
} else if (FS.isFile(node.mode)) {
|
|
node.node_ops = MEMFS.ops_table.file.node
|
|
node.stream_ops = MEMFS.ops_table.file.stream
|
|
node.usedBytes = 0
|
|
node.contents = null
|
|
} else if (FS.isLink(node.mode)) {
|
|
node.node_ops = MEMFS.ops_table.link.node
|
|
node.stream_ops = MEMFS.ops_table.link.stream
|
|
} else if (FS.isChrdev(node.mode)) {
|
|
node.node_ops = MEMFS.ops_table.chrdev.node
|
|
node.stream_ops = MEMFS.ops_table.chrdev.stream
|
|
}
|
|
node.timestamp = Date.now()
|
|
if (parent) {
|
|
parent.contents[name] = node
|
|
}
|
|
return node
|
|
},
|
|
getFileDataAsRegularArray: function(node) {
|
|
if (node.contents && node.contents.subarray) {
|
|
var arr = []
|
|
for (var i = 0; i < node.usedBytes; ++i) arr.push(node.contents[i])
|
|
return arr
|
|
}
|
|
return node.contents
|
|
},
|
|
getFileDataAsTypedArray: function(node) {
|
|
if (!node.contents) return new Uint8Array()
|
|
if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes)
|
|
return new Uint8Array(node.contents)
|
|
},
|
|
expandFileStorage: function(node, newCapacity) {
|
|
var prevCapacity = node.contents ? node.contents.length : 0
|
|
if (prevCapacity >= newCapacity) return
|
|
var CAPACITY_DOUBLING_MAX = 1024 * 1024
|
|
newCapacity = Math.max(
|
|
newCapacity,
|
|
(prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125)) | 0
|
|
)
|
|
if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256)
|
|
var oldContents = node.contents
|
|
node.contents = new Uint8Array(newCapacity)
|
|
if (node.usedBytes > 0)
|
|
node.contents.set(oldContents.subarray(0, node.usedBytes), 0)
|
|
return
|
|
},
|
|
resizeFileStorage: function(node, newSize) {
|
|
if (node.usedBytes == newSize) return
|
|
if (newSize == 0) {
|
|
node.contents = null
|
|
node.usedBytes = 0
|
|
return
|
|
}
|
|
if (!node.contents || node.contents.subarray) {
|
|
var oldContents = node.contents
|
|
node.contents = new Uint8Array(new ArrayBuffer(newSize))
|
|
if (oldContents) {
|
|
node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)))
|
|
}
|
|
node.usedBytes = newSize
|
|
return
|
|
}
|
|
if (!node.contents) node.contents = []
|
|
if (node.contents.length > newSize) node.contents.length = newSize
|
|
else while (node.contents.length < newSize) node.contents.push(0)
|
|
node.usedBytes = newSize
|
|
},
|
|
node_ops: {
|
|
getattr: function(node) {
|
|
var attr = {}
|
|
attr.dev = FS.isChrdev(node.mode) ? node.id : 1
|
|
attr.ino = node.id
|
|
attr.mode = node.mode
|
|
attr.nlink = 1
|
|
attr.uid = 0
|
|
attr.gid = 0
|
|
attr.rdev = node.rdev
|
|
if (FS.isDir(node.mode)) {
|
|
attr.size = 4096
|
|
} else if (FS.isFile(node.mode)) {
|
|
attr.size = node.usedBytes
|
|
} else if (FS.isLink(node.mode)) {
|
|
attr.size = node.link.length
|
|
} else {
|
|
attr.size = 0
|
|
}
|
|
attr.atime = new Date(node.timestamp)
|
|
attr.mtime = new Date(node.timestamp)
|
|
attr.ctime = new Date(node.timestamp)
|
|
attr.blksize = 4096
|
|
attr.blocks = Math.ceil(attr.size / attr.blksize)
|
|
return attr
|
|
},
|
|
setattr: function(node, attr) {
|
|
if (attr.mode !== undefined) {
|
|
node.mode = attr.mode
|
|
}
|
|
if (attr.timestamp !== undefined) {
|
|
node.timestamp = attr.timestamp
|
|
}
|
|
if (attr.size !== undefined) {
|
|
MEMFS.resizeFileStorage(node, attr.size)
|
|
}
|
|
},
|
|
lookup: function(parent, name) {
|
|
throw FS.genericErrors[2]
|
|
},
|
|
mknod: function(parent, name, mode, dev) {
|
|
return MEMFS.createNode(parent, name, mode, dev)
|
|
},
|
|
rename: function(old_node, new_dir, new_name) {
|
|
if (FS.isDir(old_node.mode)) {
|
|
var new_node
|
|
try {
|
|
new_node = FS.lookupNode(new_dir, new_name)
|
|
} catch (e) {}
|
|
if (new_node) {
|
|
for (var i in new_node.contents) {
|
|
throw new FS.ErrnoError(39)
|
|
}
|
|
}
|
|
}
|
|
delete old_node.parent.contents[old_node.name]
|
|
old_node.name = new_name
|
|
new_dir.contents[new_name] = old_node
|
|
old_node.parent = new_dir
|
|
},
|
|
unlink: function(parent, name) {
|
|
delete parent.contents[name]
|
|
},
|
|
rmdir: function(parent, name) {
|
|
var node = FS.lookupNode(parent, name)
|
|
for (var i in node.contents) {
|
|
throw new FS.ErrnoError(39)
|
|
}
|
|
delete parent.contents[name]
|
|
},
|
|
readdir: function(node) {
|
|
var entries = ['.', '..']
|
|
for (var key in node.contents) {
|
|
if (!node.contents.hasOwnProperty(key)) {
|
|
continue
|
|
}
|
|
entries.push(key)
|
|
}
|
|
return entries
|
|
},
|
|
symlink: function(parent, newname, oldpath) {
|
|
var node = MEMFS.createNode(parent, newname, 511 | 40960, 0)
|
|
node.link = oldpath
|
|
return node
|
|
},
|
|
readlink: function(node) {
|
|
if (!FS.isLink(node.mode)) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
return node.link
|
|
},
|
|
},
|
|
stream_ops: {
|
|
read: function(stream, buffer, offset, length, position) {
|
|
var contents = stream.node.contents
|
|
if (position >= stream.node.usedBytes) return 0
|
|
var size = Math.min(stream.node.usedBytes - position, length)
|
|
if (size > 8 && contents.subarray) {
|
|
buffer.set(contents.subarray(position, position + size), offset)
|
|
} else {
|
|
for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i]
|
|
}
|
|
return size
|
|
},
|
|
write: function(stream, buffer, offset, length, position, canOwn) {
|
|
canOwn = false
|
|
if (!length) return 0
|
|
var node = stream.node
|
|
node.timestamp = Date.now()
|
|
if (buffer.subarray && (!node.contents || node.contents.subarray)) {
|
|
if (canOwn) {
|
|
node.contents = buffer.subarray(offset, offset + length)
|
|
node.usedBytes = length
|
|
return length
|
|
} else if (node.usedBytes === 0 && position === 0) {
|
|
node.contents = new Uint8Array(buffer.subarray(offset, offset + length))
|
|
node.usedBytes = length
|
|
return length
|
|
} else if (position + length <= node.usedBytes) {
|
|
node.contents.set(buffer.subarray(offset, offset + length), position)
|
|
return length
|
|
}
|
|
}
|
|
MEMFS.expandFileStorage(node, position + length)
|
|
if (node.contents.subarray && buffer.subarray)
|
|
node.contents.set(buffer.subarray(offset, offset + length), position)
|
|
else {
|
|
for (var i = 0; i < length; i++) {
|
|
node.contents[position + i] = buffer[offset + i]
|
|
}
|
|
}
|
|
node.usedBytes = Math.max(node.usedBytes, position + length)
|
|
return length
|
|
},
|
|
llseek: function(stream, offset, whence) {
|
|
var position = offset
|
|
if (whence === 1) {
|
|
position += stream.position
|
|
} else if (whence === 2) {
|
|
if (FS.isFile(stream.node.mode)) {
|
|
position += stream.node.usedBytes
|
|
}
|
|
}
|
|
if (position < 0) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
return position
|
|
},
|
|
allocate: function(stream, offset, length) {
|
|
MEMFS.expandFileStorage(stream.node, offset + length)
|
|
stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length)
|
|
},
|
|
mmap: function(stream, buffer, offset, length, position, prot, flags) {
|
|
if (!FS.isFile(stream.node.mode)) {
|
|
throw new FS.ErrnoError(19)
|
|
}
|
|
var ptr
|
|
var allocated
|
|
var contents = stream.node.contents
|
|
if (
|
|
!(flags & 2) &&
|
|
(contents.buffer === buffer || contents.buffer === buffer.buffer)
|
|
) {
|
|
allocated = false
|
|
ptr = contents.byteOffset
|
|
} else {
|
|
if (position > 0 || position + length < stream.node.usedBytes) {
|
|
if (contents.subarray) {
|
|
contents = contents.subarray(position, position + length)
|
|
} else {
|
|
contents = Array.prototype.slice.call(
|
|
contents,
|
|
position,
|
|
position + length
|
|
)
|
|
}
|
|
}
|
|
allocated = true
|
|
ptr = _malloc(length)
|
|
if (!ptr) {
|
|
throw new FS.ErrnoError(12)
|
|
}
|
|
buffer.set(contents, ptr)
|
|
}
|
|
return { ptr: ptr, allocated: allocated }
|
|
},
|
|
msync: function(stream, buffer, offset, length, mmapFlags) {
|
|
if (!FS.isFile(stream.node.mode)) {
|
|
throw new FS.ErrnoError(19)
|
|
}
|
|
if (mmapFlags & 2) {
|
|
return 0
|
|
}
|
|
var bytesWritten = MEMFS.stream_ops.write(
|
|
stream,
|
|
buffer,
|
|
0,
|
|
length,
|
|
offset,
|
|
false
|
|
)
|
|
return 0
|
|
},
|
|
},
|
|
}
|
|
var IDBFS = {
|
|
dbs: {},
|
|
indexedDB: function() {
|
|
if (typeof indexedDB !== 'undefined') return indexedDB
|
|
var ret = null
|
|
if (typeof window === 'object')
|
|
ret =
|
|
window.indexedDB ||
|
|
window.mozIndexedDB ||
|
|
window.webkitIndexedDB ||
|
|
window.msIndexedDB
|
|
assert(ret, 'IDBFS used, but indexedDB not supported')
|
|
return ret
|
|
},
|
|
DB_VERSION: 21,
|
|
DB_STORE_NAME: 'FILE_DATA',
|
|
mount: function(mount) {
|
|
return MEMFS.mount.apply(null, arguments)
|
|
},
|
|
syncfs: function(mount, populate, callback) {
|
|
IDBFS.getLocalSet(mount, function(err, local) {
|
|
if (err) return callback(err)
|
|
IDBFS.getRemoteSet(mount, function(err, remote) {
|
|
if (err) return callback(err)
|
|
var src = populate ? remote : local
|
|
var dst = populate ? local : remote
|
|
IDBFS.reconcile(src, dst, callback)
|
|
})
|
|
})
|
|
},
|
|
getDB: function(name, callback) {
|
|
var db = IDBFS.dbs[name]
|
|
if (db) {
|
|
return callback(null, db)
|
|
}
|
|
var req
|
|
try {
|
|
req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION)
|
|
} catch (e) {
|
|
return callback(e)
|
|
}
|
|
if (!req) {
|
|
return callback('Unable to connect to IndexedDB')
|
|
}
|
|
req.onupgradeneeded = function(e) {
|
|
var db = e.target.result
|
|
var transaction = e.target.transaction
|
|
var fileStore
|
|
if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) {
|
|
fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME)
|
|
} else {
|
|
fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME)
|
|
}
|
|
if (!fileStore.indexNames.contains('timestamp')) {
|
|
fileStore.createIndex('timestamp', 'timestamp', { unique: false })
|
|
}
|
|
}
|
|
req.onsuccess = function() {
|
|
db = req.result
|
|
IDBFS.dbs[name] = db
|
|
callback(null, db)
|
|
}
|
|
req.onerror = function(e) {
|
|
callback(this.error)
|
|
e.preventDefault()
|
|
}
|
|
},
|
|
getLocalSet: function(mount, callback) {
|
|
var entries = {}
|
|
function isRealDir(p) {
|
|
return p !== '.' && p !== '..'
|
|
}
|
|
function toAbsolute(root) {
|
|
return function(p) {
|
|
return PATH.join2(root, p)
|
|
}
|
|
}
|
|
var check = FS.readdir(mount.mountpoint)
|
|
.filter(isRealDir)
|
|
.map(toAbsolute(mount.mountpoint))
|
|
while (check.length) {
|
|
var path = check.pop()
|
|
var stat
|
|
try {
|
|
stat = FS.stat(path)
|
|
} catch (e) {
|
|
return callback(e)
|
|
}
|
|
if (FS.isDir(stat.mode)) {
|
|
check.push.apply(
|
|
check,
|
|
FS.readdir(path)
|
|
.filter(isRealDir)
|
|
.map(toAbsolute(path))
|
|
)
|
|
}
|
|
entries[path] = { timestamp: stat.mtime }
|
|
}
|
|
return callback(null, { type: 'local', entries: entries })
|
|
},
|
|
getRemoteSet: function(mount, callback) {
|
|
var entries = {}
|
|
IDBFS.getDB(mount.mountpoint, function(err, db) {
|
|
if (err) return callback(err)
|
|
try {
|
|
var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly')
|
|
transaction.onerror = function(e) {
|
|
callback(this.error)
|
|
e.preventDefault()
|
|
}
|
|
var store = transaction.objectStore(IDBFS.DB_STORE_NAME)
|
|
var index = store.index('timestamp')
|
|
index.openKeyCursor().onsuccess = function(event) {
|
|
var cursor = event.target.result
|
|
if (!cursor) {
|
|
return callback(null, { type: 'remote', db: db, entries: entries })
|
|
}
|
|
entries[cursor.primaryKey] = { timestamp: cursor.key }
|
|
cursor.continue()
|
|
}
|
|
} catch (e) {
|
|
return callback(e)
|
|
}
|
|
})
|
|
},
|
|
loadLocalEntry: function(path, callback) {
|
|
var stat, node
|
|
try {
|
|
var lookup = FS.lookupPath(path)
|
|
node = lookup.node
|
|
stat = FS.stat(path)
|
|
} catch (e) {
|
|
return callback(e)
|
|
}
|
|
if (FS.isDir(stat.mode)) {
|
|
return callback(null, { timestamp: stat.mtime, mode: stat.mode })
|
|
} else if (FS.isFile(stat.mode)) {
|
|
node.contents = MEMFS.getFileDataAsTypedArray(node)
|
|
return callback(null, {
|
|
timestamp: stat.mtime,
|
|
mode: stat.mode,
|
|
contents: node.contents,
|
|
})
|
|
} else {
|
|
return callback(new Error('node type not supported'))
|
|
}
|
|
},
|
|
storeLocalEntry: function(path, entry, callback) {
|
|
try {
|
|
if (FS.isDir(entry.mode)) {
|
|
FS.mkdir(path, entry.mode)
|
|
} else if (FS.isFile(entry.mode)) {
|
|
FS.writeFile(path, entry.contents, { canOwn: true })
|
|
} else {
|
|
return callback(new Error('node type not supported'))
|
|
}
|
|
FS.chmod(path, entry.mode)
|
|
FS.utime(path, entry.timestamp, entry.timestamp)
|
|
} catch (e) {
|
|
return callback(e)
|
|
}
|
|
callback(null)
|
|
},
|
|
removeLocalEntry: function(path, callback) {
|
|
try {
|
|
var lookup = FS.lookupPath(path)
|
|
var stat = FS.stat(path)
|
|
if (FS.isDir(stat.mode)) {
|
|
FS.rmdir(path)
|
|
} else if (FS.isFile(stat.mode)) {
|
|
FS.unlink(path)
|
|
}
|
|
} catch (e) {
|
|
return callback(e)
|
|
}
|
|
callback(null)
|
|
},
|
|
loadRemoteEntry: function(store, path, callback) {
|
|
var req = store.get(path)
|
|
req.onsuccess = function(event) {
|
|
callback(null, event.target.result)
|
|
}
|
|
req.onerror = function(e) {
|
|
callback(this.error)
|
|
e.preventDefault()
|
|
}
|
|
},
|
|
storeRemoteEntry: function(store, path, entry, callback) {
|
|
var req = store.put(entry, path)
|
|
req.onsuccess = function() {
|
|
callback(null)
|
|
}
|
|
req.onerror = function(e) {
|
|
callback(this.error)
|
|
e.preventDefault()
|
|
}
|
|
},
|
|
removeRemoteEntry: function(store, path, callback) {
|
|
var req = store.delete(path)
|
|
req.onsuccess = function() {
|
|
callback(null)
|
|
}
|
|
req.onerror = function(e) {
|
|
callback(this.error)
|
|
e.preventDefault()
|
|
}
|
|
},
|
|
reconcile: function(src, dst, callback) {
|
|
var total = 0
|
|
var create = []
|
|
Object.keys(src.entries).forEach(function(key) {
|
|
var e = src.entries[key]
|
|
var e2 = dst.entries[key]
|
|
if (!e2 || e.timestamp > e2.timestamp) {
|
|
create.push(key)
|
|
total++
|
|
}
|
|
})
|
|
var remove = []
|
|
Object.keys(dst.entries).forEach(function(key) {
|
|
var e = dst.entries[key]
|
|
var e2 = src.entries[key]
|
|
if (!e2) {
|
|
remove.push(key)
|
|
total++
|
|
}
|
|
})
|
|
if (!total) {
|
|
return callback(null)
|
|
}
|
|
var errored = false
|
|
var completed = 0
|
|
var db = src.type === 'remote' ? src.db : dst.db
|
|
var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite')
|
|
var store = transaction.objectStore(IDBFS.DB_STORE_NAME)
|
|
function done(err) {
|
|
if (err) {
|
|
if (!done.errored) {
|
|
done.errored = true
|
|
return callback(err)
|
|
}
|
|
return
|
|
}
|
|
if (++completed >= total) {
|
|
return callback(null)
|
|
}
|
|
}
|
|
transaction.onerror = function(e) {
|
|
done(this.error)
|
|
e.preventDefault()
|
|
}
|
|
create.sort().forEach(function(path) {
|
|
if (dst.type === 'local') {
|
|
IDBFS.loadRemoteEntry(store, path, function(err, entry) {
|
|
if (err) return done(err)
|
|
IDBFS.storeLocalEntry(path, entry, done)
|
|
})
|
|
} else {
|
|
IDBFS.loadLocalEntry(path, function(err, entry) {
|
|
if (err) return done(err)
|
|
IDBFS.storeRemoteEntry(store, path, entry, done)
|
|
})
|
|
}
|
|
})
|
|
remove
|
|
.sort()
|
|
.reverse()
|
|
.forEach(function(path) {
|
|
if (dst.type === 'local') {
|
|
IDBFS.removeLocalEntry(path, done)
|
|
} else {
|
|
IDBFS.removeRemoteEntry(store, path, done)
|
|
}
|
|
})
|
|
},
|
|
}
|
|
var NODEFS = {
|
|
isWindows: false,
|
|
staticInit: function() {
|
|
NODEFS.isWindows = !!process.platform.match(/^win/)
|
|
var flags = process['binding']('constants')
|
|
if (flags['fs']) {
|
|
flags = flags['fs']
|
|
}
|
|
NODEFS.flagsForNodeMap = {
|
|
1024: flags['O_APPEND'],
|
|
64: flags['O_CREAT'],
|
|
128: flags['O_EXCL'],
|
|
0: flags['O_RDONLY'],
|
|
2: flags['O_RDWR'],
|
|
4096: flags['O_SYNC'],
|
|
512: flags['O_TRUNC'],
|
|
1: flags['O_WRONLY'],
|
|
}
|
|
},
|
|
bufferFrom: function(arrayBuffer) {
|
|
return Buffer.alloc ? Buffer.from(arrayBuffer) : new Buffer(arrayBuffer)
|
|
},
|
|
mount: function(mount) {
|
|
assert(ENVIRONMENT_IS_NODE)
|
|
return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0)
|
|
},
|
|
createNode: function(parent, name, mode, dev) {
|
|
if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
var node = FS.createNode(parent, name, mode)
|
|
node.node_ops = NODEFS.node_ops
|
|
node.stream_ops = NODEFS.stream_ops
|
|
return node
|
|
},
|
|
getMode: function(path) {
|
|
var stat
|
|
try {
|
|
stat = fs.lstatSync(path)
|
|
if (NODEFS.isWindows) {
|
|
stat.mode = stat.mode | ((stat.mode & 292) >> 2)
|
|
}
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
return stat.mode
|
|
},
|
|
realPath: function(node) {
|
|
var parts = []
|
|
while (node.parent !== node) {
|
|
parts.push(node.name)
|
|
node = node.parent
|
|
}
|
|
parts.push(node.mount.opts.root)
|
|
parts.reverse()
|
|
return PATH.join.apply(null, parts)
|
|
},
|
|
flagsForNode: function(flags) {
|
|
flags &= ~2097152
|
|
flags &= ~2048
|
|
flags &= ~32768
|
|
flags &= ~524288
|
|
var newFlags = 0
|
|
for (var k in NODEFS.flagsForNodeMap) {
|
|
if (flags & k) {
|
|
newFlags |= NODEFS.flagsForNodeMap[k]
|
|
flags ^= k
|
|
}
|
|
}
|
|
if (!flags) {
|
|
return newFlags
|
|
} else {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
},
|
|
node_ops: {
|
|
getattr: function(node) {
|
|
var path = NODEFS.realPath(node)
|
|
var stat
|
|
try {
|
|
stat = fs.lstatSync(path)
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
if (NODEFS.isWindows && !stat.blksize) {
|
|
stat.blksize = 4096
|
|
}
|
|
if (NODEFS.isWindows && !stat.blocks) {
|
|
stat.blocks = ((stat.size + stat.blksize - 1) / stat.blksize) | 0
|
|
}
|
|
return {
|
|
dev: stat.dev,
|
|
ino: stat.ino,
|
|
mode: stat.mode,
|
|
nlink: stat.nlink,
|
|
uid: stat.uid,
|
|
gid: stat.gid,
|
|
rdev: stat.rdev,
|
|
size: stat.size,
|
|
atime: stat.atime,
|
|
mtime: stat.mtime,
|
|
ctime: stat.ctime,
|
|
blksize: stat.blksize,
|
|
blocks: stat.blocks,
|
|
}
|
|
},
|
|
setattr: function(node, attr) {
|
|
var path = NODEFS.realPath(node)
|
|
try {
|
|
if (attr.mode !== undefined) {
|
|
fs.chmodSync(path, attr.mode)
|
|
node.mode = attr.mode
|
|
}
|
|
if (attr.timestamp !== undefined) {
|
|
var date = new Date(attr.timestamp)
|
|
fs.utimesSync(path, date, date)
|
|
}
|
|
if (attr.size !== undefined) {
|
|
fs.truncateSync(path, attr.size)
|
|
}
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
lookup: function(parent, name) {
|
|
var path = PATH.join2(NODEFS.realPath(parent), name)
|
|
var mode = NODEFS.getMode(path)
|
|
return NODEFS.createNode(parent, name, mode)
|
|
},
|
|
mknod: function(parent, name, mode, dev) {
|
|
var node = NODEFS.createNode(parent, name, mode, dev)
|
|
var path = NODEFS.realPath(node)
|
|
try {
|
|
if (FS.isDir(node.mode)) {
|
|
fs.mkdirSync(path, node.mode)
|
|
} else {
|
|
fs.writeFileSync(path, '', { mode: node.mode })
|
|
}
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
return node
|
|
},
|
|
rename: function(oldNode, newDir, newName) {
|
|
var oldPath = NODEFS.realPath(oldNode)
|
|
var newPath = PATH.join2(NODEFS.realPath(newDir), newName)
|
|
try {
|
|
fs.renameSync(oldPath, newPath)
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
unlink: function(parent, name) {
|
|
var path = PATH.join2(NODEFS.realPath(parent), name)
|
|
try {
|
|
fs.unlinkSync(path)
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
rmdir: function(parent, name) {
|
|
var path = PATH.join2(NODEFS.realPath(parent), name)
|
|
try {
|
|
fs.rmdirSync(path)
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
readdir: function(node) {
|
|
var path = NODEFS.realPath(node)
|
|
try {
|
|
return fs.readdirSync(path)
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
symlink: function(parent, newName, oldPath) {
|
|
var newPath = PATH.join2(NODEFS.realPath(parent), newName)
|
|
try {
|
|
fs.symlinkSync(oldPath, newPath)
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
readlink: function(node) {
|
|
var path = NODEFS.realPath(node)
|
|
try {
|
|
path = fs.readlinkSync(path)
|
|
path = NODEJS_PATH.relative(NODEJS_PATH.resolve(node.mount.opts.root), path)
|
|
return path
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
},
|
|
stream_ops: {
|
|
open: function(stream) {
|
|
var path = NODEFS.realPath(stream.node)
|
|
try {
|
|
if (FS.isFile(stream.node.mode)) {
|
|
stream.nfd = fs.openSync(path, NODEFS.flagsForNode(stream.flags))
|
|
}
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
close: function(stream) {
|
|
try {
|
|
if (FS.isFile(stream.node.mode) && stream.nfd) {
|
|
fs.closeSync(stream.nfd)
|
|
}
|
|
} catch (e) {
|
|
if (!e.code) throw e
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
read: function(stream, buffer, offset, length, position) {
|
|
if (length === 0) return 0
|
|
try {
|
|
return fs.readSync(
|
|
stream.nfd,
|
|
NODEFS.bufferFrom(buffer.buffer),
|
|
offset,
|
|
length,
|
|
position
|
|
)
|
|
} catch (e) {
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
write: function(stream, buffer, offset, length, position) {
|
|
try {
|
|
return fs.writeSync(
|
|
stream.nfd,
|
|
NODEFS.bufferFrom(buffer.buffer),
|
|
offset,
|
|
length,
|
|
position
|
|
)
|
|
} catch (e) {
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
},
|
|
llseek: function(stream, offset, whence) {
|
|
var position = offset
|
|
if (whence === 1) {
|
|
position += stream.position
|
|
} else if (whence === 2) {
|
|
if (FS.isFile(stream.node.mode)) {
|
|
try {
|
|
var stat = fs.fstatSync(stream.nfd)
|
|
position += stat.size
|
|
} catch (e) {
|
|
throw new FS.ErrnoError(-e.errno)
|
|
}
|
|
}
|
|
}
|
|
if (position < 0) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
return position
|
|
},
|
|
},
|
|
}
|
|
var WORKERFS = {
|
|
DIR_MODE: 16895,
|
|
FILE_MODE: 33279,
|
|
reader: null,
|
|
mount: function(mount) {
|
|
assert(ENVIRONMENT_IS_WORKER)
|
|
if (!WORKERFS.reader) WORKERFS.reader = new FileReaderSync()
|
|
var root = WORKERFS.createNode(null, '/', WORKERFS.DIR_MODE, 0)
|
|
var createdParents = {}
|
|
function ensureParent(path) {
|
|
var parts = path.split('/')
|
|
var parent = root
|
|
for (var i = 0; i < parts.length - 1; i++) {
|
|
var curr = parts.slice(0, i + 1).join('/')
|
|
if (!createdParents[curr]) {
|
|
createdParents[curr] = WORKERFS.createNode(
|
|
parent,
|
|
parts[i],
|
|
WORKERFS.DIR_MODE,
|
|
0
|
|
)
|
|
}
|
|
parent = createdParents[curr]
|
|
}
|
|
return parent
|
|
}
|
|
function base(path) {
|
|
var parts = path.split('/')
|
|
return parts[parts.length - 1]
|
|
}
|
|
Array.prototype.forEach.call(mount.opts['files'] || [], function(file) {
|
|
WORKERFS.createNode(
|
|
ensureParent(file.name),
|
|
base(file.name),
|
|
WORKERFS.FILE_MODE,
|
|
0,
|
|
file,
|
|
file.lastModifiedDate
|
|
)
|
|
})
|
|
;(mount.opts['blobs'] || []).forEach(function(obj) {
|
|
WORKERFS.createNode(
|
|
ensureParent(obj['name']),
|
|
base(obj['name']),
|
|
WORKERFS.FILE_MODE,
|
|
0,
|
|
obj['data']
|
|
)
|
|
})
|
|
;(mount.opts['packages'] || []).forEach(function(pack) {
|
|
pack['metadata'].files.forEach(function(file) {
|
|
var name = file.filename.substr(1)
|
|
WORKERFS.createNode(
|
|
ensureParent(name),
|
|
base(name),
|
|
WORKERFS.FILE_MODE,
|
|
0,
|
|
pack['blob'].slice(file.start, file.end)
|
|
)
|
|
})
|
|
})
|
|
return root
|
|
},
|
|
createNode: function(parent, name, mode, dev, contents, mtime) {
|
|
var node = FS.createNode(parent, name, mode)
|
|
node.mode = mode
|
|
node.node_ops = WORKERFS.node_ops
|
|
node.stream_ops = WORKERFS.stream_ops
|
|
node.timestamp = (mtime || new Date()).getTime()
|
|
assert(WORKERFS.FILE_MODE !== WORKERFS.DIR_MODE)
|
|
if (mode === WORKERFS.FILE_MODE) {
|
|
node.size = contents.size
|
|
node.contents = contents
|
|
} else {
|
|
node.size = 4096
|
|
node.contents = {}
|
|
}
|
|
if (parent) {
|
|
parent.contents[name] = node
|
|
}
|
|
return node
|
|
},
|
|
node_ops: {
|
|
getattr: function(node) {
|
|
return {
|
|
dev: 1,
|
|
ino: undefined,
|
|
mode: node.mode,
|
|
nlink: 1,
|
|
uid: 0,
|
|
gid: 0,
|
|
rdev: undefined,
|
|
size: node.size,
|
|
atime: new Date(node.timestamp),
|
|
mtime: new Date(node.timestamp),
|
|
ctime: new Date(node.timestamp),
|
|
blksize: 4096,
|
|
blocks: Math.ceil(node.size / 4096),
|
|
}
|
|
},
|
|
setattr: function(node, attr) {
|
|
if (attr.mode !== undefined) {
|
|
node.mode = attr.mode
|
|
}
|
|
if (attr.timestamp !== undefined) {
|
|
node.timestamp = attr.timestamp
|
|
}
|
|
},
|
|
lookup: function(parent, name) {
|
|
throw new FS.ErrnoError(2)
|
|
},
|
|
mknod: function(parent, name, mode, dev) {
|
|
throw new FS.ErrnoError(1)
|
|
},
|
|
rename: function(oldNode, newDir, newName) {
|
|
throw new FS.ErrnoError(1)
|
|
},
|
|
unlink: function(parent, name) {
|
|
throw new FS.ErrnoError(1)
|
|
},
|
|
rmdir: function(parent, name) {
|
|
throw new FS.ErrnoError(1)
|
|
},
|
|
readdir: function(node) {
|
|
var entries = ['.', '..']
|
|
for (var key in node.contents) {
|
|
if (!node.contents.hasOwnProperty(key)) {
|
|
continue
|
|
}
|
|
entries.push(key)
|
|
}
|
|
return entries
|
|
},
|
|
symlink: function(parent, newName, oldPath) {
|
|
throw new FS.ErrnoError(1)
|
|
},
|
|
readlink: function(node) {
|
|
throw new FS.ErrnoError(1)
|
|
},
|
|
},
|
|
stream_ops: {
|
|
read: function(stream, buffer, offset, length, position) {
|
|
if (position >= stream.node.size) return 0
|
|
var chunk = stream.node.contents.slice(position, position + length)
|
|
var ab = WORKERFS.reader.readAsArrayBuffer(chunk)
|
|
buffer.set(new Uint8Array(ab), offset)
|
|
return chunk.size
|
|
},
|
|
write: function(stream, buffer, offset, length, position) {
|
|
throw new FS.ErrnoError(5)
|
|
},
|
|
llseek: function(stream, offset, whence) {
|
|
var position = offset
|
|
if (whence === 1) {
|
|
position += stream.position
|
|
} else if (whence === 2) {
|
|
if (FS.isFile(stream.node.mode)) {
|
|
position += stream.node.size
|
|
}
|
|
}
|
|
if (position < 0) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
return position
|
|
},
|
|
},
|
|
}
|
|
var FS = {
|
|
root: null,
|
|
mounts: [],
|
|
devices: {},
|
|
streams: [],
|
|
nextInode: 1,
|
|
nameTable: null,
|
|
currentPath: '/',
|
|
initialized: false,
|
|
ignorePermissions: true,
|
|
trackingDelegate: {},
|
|
tracking: { openFlags: { READ: 1, WRITE: 2 } },
|
|
ErrnoError: null,
|
|
genericErrors: {},
|
|
filesystems: null,
|
|
syncFSRequests: 0,
|
|
handleFSError: function(e) {
|
|
if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace()
|
|
return ___setErrNo(e.errno)
|
|
},
|
|
lookupPath: function(path, opts) {
|
|
path = PATH_FS.resolve(FS.cwd(), path)
|
|
opts = opts || {}
|
|
if (!path) return { path: '', node: null }
|
|
var defaults = { follow_mount: true, recurse_count: 0 }
|
|
for (var key in defaults) {
|
|
if (opts[key] === undefined) {
|
|
opts[key] = defaults[key]
|
|
}
|
|
}
|
|
if (opts.recurse_count > 8) {
|
|
throw new FS.ErrnoError(40)
|
|
}
|
|
var parts = PATH.normalizeArray(
|
|
path.split('/').filter(function(p) {
|
|
return !!p
|
|
}),
|
|
false
|
|
)
|
|
var current = FS.root
|
|
var current_path = '/'
|
|
for (var i = 0; i < parts.length; i++) {
|
|
var islast = i === parts.length - 1
|
|
if (islast && opts.parent) {
|
|
break
|
|
}
|
|
current = FS.lookupNode(current, parts[i])
|
|
current_path = PATH.join2(current_path, parts[i])
|
|
if (FS.isMountpoint(current)) {
|
|
if (!islast || (islast && opts.follow_mount)) {
|
|
current = current.mounted.root
|
|
}
|
|
}
|
|
if (!islast || opts.follow) {
|
|
var count = 0
|
|
while (FS.isLink(current.mode)) {
|
|
var link = FS.readlink(current_path)
|
|
current_path = PATH_FS.resolve(PATH.dirname(current_path), link)
|
|
var lookup = FS.lookupPath(current_path, {
|
|
recurse_count: opts.recurse_count,
|
|
})
|
|
current = lookup.node
|
|
if (count++ > 40) {
|
|
throw new FS.ErrnoError(40)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return { path: current_path, node: current }
|
|
},
|
|
getPath: function(node) {
|
|
var path
|
|
while (true) {
|
|
if (FS.isRoot(node)) {
|
|
var mount = node.mount.mountpoint
|
|
if (!path) return mount
|
|
return mount[mount.length - 1] !== '/' ? mount + '/' + path : mount + path
|
|
}
|
|
path = path ? node.name + '/' + path : node.name
|
|
node = node.parent
|
|
}
|
|
},
|
|
hashName: function(parentid, name) {
|
|
var hash = 0
|
|
for (var i = 0; i < name.length; i++) {
|
|
hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0
|
|
}
|
|
return ((parentid + hash) >>> 0) % FS.nameTable.length
|
|
},
|
|
hashAddNode: function(node) {
|
|
var hash = FS.hashName(node.parent.id, node.name)
|
|
node.name_next = FS.nameTable[hash]
|
|
FS.nameTable[hash] = node
|
|
},
|
|
hashRemoveNode: function(node) {
|
|
var hash = FS.hashName(node.parent.id, node.name)
|
|
if (FS.nameTable[hash] === node) {
|
|
FS.nameTable[hash] = node.name_next
|
|
} else {
|
|
var current = FS.nameTable[hash]
|
|
while (current) {
|
|
if (current.name_next === node) {
|
|
current.name_next = node.name_next
|
|
break
|
|
}
|
|
current = current.name_next
|
|
}
|
|
}
|
|
},
|
|
lookupNode: function(parent, name) {
|
|
var err = FS.mayLookup(parent)
|
|
if (err) {
|
|
throw new FS.ErrnoError(err, parent)
|
|
}
|
|
var hash = FS.hashName(parent.id, name)
|
|
for (var node = FS.nameTable[hash]; node; node = node.name_next) {
|
|
var nodeName = node.name
|
|
if (node.parent.id === parent.id && nodeName === name) {
|
|
return node
|
|
}
|
|
}
|
|
return FS.lookup(parent, name)
|
|
},
|
|
createNode: function(parent, name, mode, rdev) {
|
|
if (!FS.FSNode) {
|
|
FS.FSNode = function(parent, name, mode, rdev) {
|
|
if (!parent) {
|
|
parent = this
|
|
}
|
|
this.parent = parent
|
|
this.mount = parent.mount
|
|
this.mounted = null
|
|
this.id = FS.nextInode++
|
|
this.name = name
|
|
this.mode = mode
|
|
this.node_ops = {}
|
|
this.stream_ops = {}
|
|
this.rdev = rdev
|
|
}
|
|
FS.FSNode.prototype = {}
|
|
var readMode = 292 | 73
|
|
var writeMode = 146
|
|
Object.defineProperties(FS.FSNode.prototype, {
|
|
read: {
|
|
get: function() {
|
|
return (this.mode & readMode) === readMode
|
|
},
|
|
set: function(val) {
|
|
val ? (this.mode |= readMode) : (this.mode &= ~readMode)
|
|
},
|
|
},
|
|
write: {
|
|
get: function() {
|
|
return (this.mode & writeMode) === writeMode
|
|
},
|
|
set: function(val) {
|
|
val ? (this.mode |= writeMode) : (this.mode &= ~writeMode)
|
|
},
|
|
},
|
|
isFolder: {
|
|
get: function() {
|
|
return FS.isDir(this.mode)
|
|
},
|
|
},
|
|
isDevice: {
|
|
get: function() {
|
|
return FS.isChrdev(this.mode)
|
|
},
|
|
},
|
|
})
|
|
}
|
|
var node = new FS.FSNode(parent, name, mode, rdev)
|
|
FS.hashAddNode(node)
|
|
return node
|
|
},
|
|
destroyNode: function(node) {
|
|
FS.hashRemoveNode(node)
|
|
},
|
|
isRoot: function(node) {
|
|
return node === node.parent
|
|
},
|
|
isMountpoint: function(node) {
|
|
return !!node.mounted
|
|
},
|
|
isFile: function(mode) {
|
|
return (mode & 61440) === 32768
|
|
},
|
|
isDir: function(mode) {
|
|
return (mode & 61440) === 16384
|
|
},
|
|
isLink: function(mode) {
|
|
return (mode & 61440) === 40960
|
|
},
|
|
isChrdev: function(mode) {
|
|
return (mode & 61440) === 8192
|
|
},
|
|
isBlkdev: function(mode) {
|
|
return (mode & 61440) === 24576
|
|
},
|
|
isFIFO: function(mode) {
|
|
return (mode & 61440) === 4096
|
|
},
|
|
isSocket: function(mode) {
|
|
return (mode & 49152) === 49152
|
|
},
|
|
flagModes: {
|
|
r: 0,
|
|
rs: 1052672,
|
|
'r+': 2,
|
|
w: 577,
|
|
wx: 705,
|
|
xw: 705,
|
|
'w+': 578,
|
|
'wx+': 706,
|
|
'xw+': 706,
|
|
a: 1089,
|
|
ax: 1217,
|
|
xa: 1217,
|
|
'a+': 1090,
|
|
'ax+': 1218,
|
|
'xa+': 1218,
|
|
},
|
|
modeStringToFlags: function(str) {
|
|
var flags = FS.flagModes[str]
|
|
if (typeof flags === 'undefined') {
|
|
throw new Error('Unknown file open mode: ' + str)
|
|
}
|
|
return flags
|
|
},
|
|
flagsToPermissionString: function(flag) {
|
|
var perms = ['r', 'w', 'rw'][flag & 3]
|
|
if (flag & 512) {
|
|
perms += 'w'
|
|
}
|
|
return perms
|
|
},
|
|
nodePermissions: function(node, perms) {
|
|
if (FS.ignorePermissions) {
|
|
return 0
|
|
}
|
|
if (perms.indexOf('r') !== -1 && !(node.mode & 292)) {
|
|
return 13
|
|
} else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) {
|
|
return 13
|
|
} else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) {
|
|
return 13
|
|
}
|
|
return 0
|
|
},
|
|
mayLookup: function(dir) {
|
|
var err = FS.nodePermissions(dir, 'x')
|
|
if (err) return err
|
|
if (!dir.node_ops.lookup) return 13
|
|
return 0
|
|
},
|
|
mayCreate: function(dir, name) {
|
|
try {
|
|
var node = FS.lookupNode(dir, name)
|
|
return 17
|
|
} catch (e) {}
|
|
return FS.nodePermissions(dir, 'wx')
|
|
},
|
|
mayDelete: function(dir, name, isdir) {
|
|
var node
|
|
try {
|
|
node = FS.lookupNode(dir, name)
|
|
} catch (e) {
|
|
return e.errno
|
|
}
|
|
var err = FS.nodePermissions(dir, 'wx')
|
|
if (err) {
|
|
return err
|
|
}
|
|
if (isdir) {
|
|
if (!FS.isDir(node.mode)) {
|
|
return 20
|
|
}
|
|
if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
|
|
return 16
|
|
}
|
|
} else {
|
|
if (FS.isDir(node.mode)) {
|
|
return 21
|
|
}
|
|
}
|
|
return 0
|
|
},
|
|
mayOpen: function(node, flags) {
|
|
if (!node) {
|
|
return 2
|
|
}
|
|
if (FS.isLink(node.mode)) {
|
|
return 40
|
|
} else if (FS.isDir(node.mode)) {
|
|
if (FS.flagsToPermissionString(flags) !== 'r' || flags & 512) {
|
|
return 21
|
|
}
|
|
}
|
|
return FS.nodePermissions(node, FS.flagsToPermissionString(flags))
|
|
},
|
|
MAX_OPEN_FDS: 4096,
|
|
nextfd: function(fd_start, fd_end) {
|
|
fd_start = fd_start || 0
|
|
fd_end = fd_end || FS.MAX_OPEN_FDS
|
|
for (var fd = fd_start; fd <= fd_end; fd++) {
|
|
if (!FS.streams[fd]) {
|
|
return fd
|
|
}
|
|
}
|
|
throw new FS.ErrnoError(24)
|
|
},
|
|
getStream: function(fd) {
|
|
return FS.streams[fd]
|
|
},
|
|
createStream: function(stream, fd_start, fd_end) {
|
|
if (!FS.FSStream) {
|
|
FS.FSStream = function() {}
|
|
FS.FSStream.prototype = {}
|
|
Object.defineProperties(FS.FSStream.prototype, {
|
|
object: {
|
|
get: function() {
|
|
return this.node
|
|
},
|
|
set: function(val) {
|
|
this.node = val
|
|
},
|
|
},
|
|
isRead: {
|
|
get: function() {
|
|
return (this.flags & 2097155) !== 1
|
|
},
|
|
},
|
|
isWrite: {
|
|
get: function() {
|
|
return (this.flags & 2097155) !== 0
|
|
},
|
|
},
|
|
isAppend: {
|
|
get: function() {
|
|
return this.flags & 1024
|
|
},
|
|
},
|
|
})
|
|
}
|
|
var newStream = new FS.FSStream()
|
|
for (var p in stream) {
|
|
newStream[p] = stream[p]
|
|
}
|
|
stream = newStream
|
|
var fd = FS.nextfd(fd_start, fd_end)
|
|
stream.fd = fd
|
|
FS.streams[fd] = stream
|
|
return stream
|
|
},
|
|
closeStream: function(fd) {
|
|
FS.streams[fd] = null
|
|
},
|
|
chrdev_stream_ops: {
|
|
open: function(stream) {
|
|
var device = FS.getDevice(stream.node.rdev)
|
|
stream.stream_ops = device.stream_ops
|
|
if (stream.stream_ops.open) {
|
|
stream.stream_ops.open(stream)
|
|
}
|
|
},
|
|
llseek: function() {
|
|
throw new FS.ErrnoError(29)
|
|
},
|
|
},
|
|
major: function(dev) {
|
|
return dev >> 8
|
|
},
|
|
minor: function(dev) {
|
|
return dev & 255
|
|
},
|
|
makedev: function(ma, mi) {
|
|
return (ma << 8) | mi
|
|
},
|
|
registerDevice: function(dev, ops) {
|
|
FS.devices[dev] = { stream_ops: ops }
|
|
},
|
|
getDevice: function(dev) {
|
|
return FS.devices[dev]
|
|
},
|
|
getMounts: function(mount) {
|
|
var mounts = []
|
|
var check = [mount]
|
|
while (check.length) {
|
|
var m = check.pop()
|
|
mounts.push(m)
|
|
check.push.apply(check, m.mounts)
|
|
}
|
|
return mounts
|
|
},
|
|
syncfs: function(populate, callback) {
|
|
if (typeof populate === 'function') {
|
|
callback = populate
|
|
populate = false
|
|
}
|
|
FS.syncFSRequests++
|
|
if (FS.syncFSRequests > 1) {
|
|
console.log(
|
|
'warning: ' +
|
|
FS.syncFSRequests +
|
|
' FS.syncfs operations in flight at once, probably just doing extra work'
|
|
)
|
|
}
|
|
var mounts = FS.getMounts(FS.root.mount)
|
|
var completed = 0
|
|
function doCallback(err) {
|
|
FS.syncFSRequests--
|
|
return callback(err)
|
|
}
|
|
function done(err) {
|
|
if (err) {
|
|
if (!done.errored) {
|
|
done.errored = true
|
|
return doCallback(err)
|
|
}
|
|
return
|
|
}
|
|
if (++completed >= mounts.length) {
|
|
doCallback(null)
|
|
}
|
|
}
|
|
mounts.forEach(function(mount) {
|
|
if (!mount.type.syncfs) {
|
|
return done(null)
|
|
}
|
|
mount.type.syncfs(mount, populate, done)
|
|
})
|
|
},
|
|
mount: function(type, opts, mountpoint) {
|
|
var root = mountpoint === '/'
|
|
var pseudo = !mountpoint
|
|
var node
|
|
if (root && FS.root) {
|
|
throw new FS.ErrnoError(16)
|
|
} else if (!root && !pseudo) {
|
|
var lookup = FS.lookupPath(mountpoint, { follow_mount: false })
|
|
mountpoint = lookup.path
|
|
node = lookup.node
|
|
if (FS.isMountpoint(node)) {
|
|
throw new FS.ErrnoError(16)
|
|
}
|
|
if (!FS.isDir(node.mode)) {
|
|
throw new FS.ErrnoError(20)
|
|
}
|
|
}
|
|
var mount = { type: type, opts: opts, mountpoint: mountpoint, mounts: [] }
|
|
var mountRoot = type.mount(mount)
|
|
mountRoot.mount = mount
|
|
mount.root = mountRoot
|
|
if (root) {
|
|
FS.root = mountRoot
|
|
} else if (node) {
|
|
node.mounted = mount
|
|
if (node.mount) {
|
|
node.mount.mounts.push(mount)
|
|
}
|
|
}
|
|
return mountRoot
|
|
},
|
|
unmount: function(mountpoint) {
|
|
var lookup = FS.lookupPath(mountpoint, { follow_mount: false })
|
|
if (!FS.isMountpoint(lookup.node)) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
var node = lookup.node
|
|
var mount = node.mounted
|
|
var mounts = FS.getMounts(mount)
|
|
Object.keys(FS.nameTable).forEach(function(hash) {
|
|
var current = FS.nameTable[hash]
|
|
while (current) {
|
|
var next = current.name_next
|
|
if (mounts.indexOf(current.mount) !== -1) {
|
|
FS.destroyNode(current)
|
|
}
|
|
current = next
|
|
}
|
|
})
|
|
node.mounted = null
|
|
var idx = node.mount.mounts.indexOf(mount)
|
|
node.mount.mounts.splice(idx, 1)
|
|
},
|
|
lookup: function(parent, name) {
|
|
return parent.node_ops.lookup(parent, name)
|
|
},
|
|
mknod: function(path, mode, dev) {
|
|
var lookup = FS.lookupPath(path, { parent: true })
|
|
var parent = lookup.node
|
|
var name = PATH.basename(path)
|
|
if (!name || name === '.' || name === '..') {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
var err = FS.mayCreate(parent, name)
|
|
if (err) {
|
|
throw new FS.ErrnoError(err)
|
|
}
|
|
if (!parent.node_ops.mknod) {
|
|
throw new FS.ErrnoError(1)
|
|
}
|
|
return parent.node_ops.mknod(parent, name, mode, dev)
|
|
},
|
|
create: function(path, mode) {
|
|
mode = mode !== undefined ? mode : 438
|
|
mode &= 4095
|
|
mode |= 32768
|
|
return FS.mknod(path, mode, 0)
|
|
},
|
|
mkdir: function(path, mode) {
|
|
mode = mode !== undefined ? mode : 511
|
|
mode &= 511 | 512
|
|
mode |= 16384
|
|
return FS.mknod(path, mode, 0)
|
|
},
|
|
mkdirTree: function(path, mode) {
|
|
var dirs = path.split('/')
|
|
var d = ''
|
|
for (var i = 0; i < dirs.length; ++i) {
|
|
if (!dirs[i]) continue
|
|
d += '/' + dirs[i]
|
|
try {
|
|
FS.mkdir(d, mode)
|
|
} catch (e) {
|
|
if (e.errno != 17) throw e
|
|
}
|
|
}
|
|
},
|
|
mkdev: function(path, mode, dev) {
|
|
if (typeof dev === 'undefined') {
|
|
dev = mode
|
|
mode = 438
|
|
}
|
|
mode |= 8192
|
|
return FS.mknod(path, mode, dev)
|
|
},
|
|
symlink: function(oldpath, newpath) {
|
|
if (!PATH_FS.resolve(oldpath)) {
|
|
throw new FS.ErrnoError(2)
|
|
}
|
|
var lookup = FS.lookupPath(newpath, { parent: true })
|
|
var parent = lookup.node
|
|
if (!parent) {
|
|
throw new FS.ErrnoError(2)
|
|
}
|
|
var newname = PATH.basename(newpath)
|
|
var err = FS.mayCreate(parent, newname)
|
|
if (err) {
|
|
throw new FS.ErrnoError(err)
|
|
}
|
|
if (!parent.node_ops.symlink) {
|
|
throw new FS.ErrnoError(1)
|
|
}
|
|
return parent.node_ops.symlink(parent, newname, oldpath)
|
|
},
|
|
rename: function(old_path, new_path) {
|
|
var old_dirname = PATH.dirname(old_path)
|
|
var new_dirname = PATH.dirname(new_path)
|
|
var old_name = PATH.basename(old_path)
|
|
var new_name = PATH.basename(new_path)
|
|
var lookup, old_dir, new_dir
|
|
try {
|
|
lookup = FS.lookupPath(old_path, { parent: true })
|
|
old_dir = lookup.node
|
|
lookup = FS.lookupPath(new_path, { parent: true })
|
|
new_dir = lookup.node
|
|
} catch (e) {
|
|
throw new FS.ErrnoError(16)
|
|
}
|
|
if (!old_dir || !new_dir) throw new FS.ErrnoError(2)
|
|
if (old_dir.mount !== new_dir.mount) {
|
|
throw new FS.ErrnoError(18)
|
|
}
|
|
var old_node = FS.lookupNode(old_dir, old_name)
|
|
var relative = PATH_FS.relative(old_path, new_dirname)
|
|
if (relative.charAt(0) !== '.') {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
relative = PATH_FS.relative(new_path, old_dirname)
|
|
if (relative.charAt(0) !== '.') {
|
|
throw new FS.ErrnoError(39)
|
|
}
|
|
var new_node
|
|
try {
|
|
new_node = FS.lookupNode(new_dir, new_name)
|
|
} catch (e) {}
|
|
if (old_node === new_node) {
|
|
return
|
|
}
|
|
var isdir = FS.isDir(old_node.mode)
|
|
var err = FS.mayDelete(old_dir, old_name, isdir)
|
|
if (err) {
|
|
throw new FS.ErrnoError(err)
|
|
}
|
|
err = new_node
|
|
? FS.mayDelete(new_dir, new_name, isdir)
|
|
: FS.mayCreate(new_dir, new_name)
|
|
if (err) {
|
|
throw new FS.ErrnoError(err)
|
|
}
|
|
if (!old_dir.node_ops.rename) {
|
|
throw new FS.ErrnoError(1)
|
|
}
|
|
if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
|
|
throw new FS.ErrnoError(16)
|
|
}
|
|
if (new_dir !== old_dir) {
|
|
err = FS.nodePermissions(old_dir, 'w')
|
|
if (err) {
|
|
throw new FS.ErrnoError(err)
|
|
}
|
|
}
|
|
try {
|
|
if (FS.trackingDelegate['willMovePath']) {
|
|
FS.trackingDelegate['willMovePath'](old_path, new_path)
|
|
}
|
|
} catch (e) {
|
|
console.log(
|
|
"FS.trackingDelegate['willMovePath']('" +
|
|
old_path +
|
|
"', '" +
|
|
new_path +
|
|
"') threw an exception: " +
|
|
e.message
|
|
)
|
|
}
|
|
FS.hashRemoveNode(old_node)
|
|
try {
|
|
old_dir.node_ops.rename(old_node, new_dir, new_name)
|
|
} catch (e) {
|
|
throw e
|
|
} finally {
|
|
FS.hashAddNode(old_node)
|
|
}
|
|
try {
|
|
if (FS.trackingDelegate['onMovePath'])
|
|
FS.trackingDelegate['onMovePath'](old_path, new_path)
|
|
} catch (e) {
|
|
console.log(
|
|
"FS.trackingDelegate['onMovePath']('" +
|
|
old_path +
|
|
"', '" +
|
|
new_path +
|
|
"') threw an exception: " +
|
|
e.message
|
|
)
|
|
}
|
|
},
|
|
rmdir: function(path) {
|
|
var lookup = FS.lookupPath(path, { parent: true })
|
|
var parent = lookup.node
|
|
var name = PATH.basename(path)
|
|
var node = FS.lookupNode(parent, name)
|
|
var err = FS.mayDelete(parent, name, true)
|
|
if (err) {
|
|
throw new FS.ErrnoError(err)
|
|
}
|
|
if (!parent.node_ops.rmdir) {
|
|
throw new FS.ErrnoError(1)
|
|
}
|
|
if (FS.isMountpoint(node)) {
|
|
throw new FS.ErrnoError(16)
|
|
}
|
|
try {
|
|
if (FS.trackingDelegate['willDeletePath']) {
|
|
FS.trackingDelegate['willDeletePath'](path)
|
|
}
|
|
} catch (e) {
|
|
console.log(
|
|
"FS.trackingDelegate['willDeletePath']('" +
|
|
path +
|
|
"') threw an exception: " +
|
|
e.message
|
|
)
|
|
}
|
|
parent.node_ops.rmdir(parent, name)
|
|
FS.destroyNode(node)
|
|
try {
|
|
if (FS.trackingDelegate['onDeletePath'])
|
|
FS.trackingDelegate['onDeletePath'](path)
|
|
} catch (e) {
|
|
console.log(
|
|
"FS.trackingDelegate['onDeletePath']('" +
|
|
path +
|
|
"') threw an exception: " +
|
|
e.message
|
|
)
|
|
}
|
|
},
|
|
readdir: function(path) {
|
|
var lookup = FS.lookupPath(path, { follow: true })
|
|
var node = lookup.node
|
|
if (!node.node_ops.readdir) {
|
|
throw new FS.ErrnoError(20)
|
|
}
|
|
return node.node_ops.readdir(node)
|
|
},
|
|
unlink: function(path) {
|
|
var lookup = FS.lookupPath(path, { parent: true })
|
|
var parent = lookup.node
|
|
var name = PATH.basename(path)
|
|
var node = FS.lookupNode(parent, name)
|
|
var err = FS.mayDelete(parent, name, false)
|
|
if (err) {
|
|
throw new FS.ErrnoError(err)
|
|
}
|
|
if (!parent.node_ops.unlink) {
|
|
throw new FS.ErrnoError(1)
|
|
}
|
|
if (FS.isMountpoint(node)) {
|
|
throw new FS.ErrnoError(16)
|
|
}
|
|
try {
|
|
if (FS.trackingDelegate['willDeletePath']) {
|
|
FS.trackingDelegate['willDeletePath'](path)
|
|
}
|
|
} catch (e) {
|
|
console.log(
|
|
"FS.trackingDelegate['willDeletePath']('" +
|
|
path +
|
|
"') threw an exception: " +
|
|
e.message
|
|
)
|
|
}
|
|
parent.node_ops.unlink(parent, name)
|
|
FS.destroyNode(node)
|
|
try {
|
|
if (FS.trackingDelegate['onDeletePath'])
|
|
FS.trackingDelegate['onDeletePath'](path)
|
|
} catch (e) {
|
|
console.log(
|
|
"FS.trackingDelegate['onDeletePath']('" +
|
|
path +
|
|
"') threw an exception: " +
|
|
e.message
|
|
)
|
|
}
|
|
},
|
|
readlink: function(path) {
|
|
var lookup = FS.lookupPath(path)
|
|
var link = lookup.node
|
|
if (!link) {
|
|
throw new FS.ErrnoError(2)
|
|
}
|
|
if (!link.node_ops.readlink) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link))
|
|
},
|
|
stat: function(path, dontFollow) {
|
|
var lookup = FS.lookupPath(path, { follow: !dontFollow })
|
|
var node = lookup.node
|
|
if (!node) {
|
|
throw new FS.ErrnoError(2)
|
|
}
|
|
if (!node.node_ops.getattr) {
|
|
throw new FS.ErrnoError(1)
|
|
}
|
|
return node.node_ops.getattr(node)
|
|
},
|
|
lstat: function(path) {
|
|
return FS.stat(path, true)
|
|
},
|
|
chmod: function(path, mode, dontFollow) {
|
|
var node
|
|
if (typeof path === 'string') {
|
|
var lookup = FS.lookupPath(path, { follow: !dontFollow })
|
|
node = lookup.node
|
|
} else {
|
|
node = path
|
|
}
|
|
if (!node.node_ops.setattr) {
|
|
throw new FS.ErrnoError(1)
|
|
}
|
|
node.node_ops.setattr(node, {
|
|
mode: (mode & 4095) | (node.mode & ~4095),
|
|
timestamp: Date.now(),
|
|
})
|
|
},
|
|
lchmod: function(path, mode) {
|
|
FS.chmod(path, mode, true)
|
|
},
|
|
fchmod: function(fd, mode) {
|
|
var stream = FS.getStream(fd)
|
|
if (!stream) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
FS.chmod(stream.node, mode)
|
|
},
|
|
chown: function(path, uid, gid, dontFollow) {
|
|
var node
|
|
if (typeof path === 'string') {
|
|
var lookup = FS.lookupPath(path, { follow: !dontFollow })
|
|
node = lookup.node
|
|
} else {
|
|
node = path
|
|
}
|
|
if (!node.node_ops.setattr) {
|
|
throw new FS.ErrnoError(1)
|
|
}
|
|
node.node_ops.setattr(node, { timestamp: Date.now() })
|
|
},
|
|
lchown: function(path, uid, gid) {
|
|
FS.chown(path, uid, gid, true)
|
|
},
|
|
fchown: function(fd, uid, gid) {
|
|
var stream = FS.getStream(fd)
|
|
if (!stream) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
FS.chown(stream.node, uid, gid)
|
|
},
|
|
truncate: function(path, len) {
|
|
if (len < 0) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
var node
|
|
if (typeof path === 'string') {
|
|
var lookup = FS.lookupPath(path, { follow: true })
|
|
node = lookup.node
|
|
} else {
|
|
node = path
|
|
}
|
|
if (!node.node_ops.setattr) {
|
|
throw new FS.ErrnoError(1)
|
|
}
|
|
if (FS.isDir(node.mode)) {
|
|
throw new FS.ErrnoError(21)
|
|
}
|
|
if (!FS.isFile(node.mode)) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
var err = FS.nodePermissions(node, 'w')
|
|
if (err) {
|
|
throw new FS.ErrnoError(err)
|
|
}
|
|
node.node_ops.setattr(node, { size: len, timestamp: Date.now() })
|
|
},
|
|
ftruncate: function(fd, len) {
|
|
var stream = FS.getStream(fd)
|
|
if (!stream) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
if ((stream.flags & 2097155) === 0) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
FS.truncate(stream.node, len)
|
|
},
|
|
utime: function(path, atime, mtime) {
|
|
var lookup = FS.lookupPath(path, { follow: true })
|
|
var node = lookup.node
|
|
node.node_ops.setattr(node, { timestamp: Math.max(atime, mtime) })
|
|
},
|
|
open: function(path, flags, mode, fd_start, fd_end) {
|
|
if (path === '') {
|
|
throw new FS.ErrnoError(2)
|
|
}
|
|
flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags
|
|
mode = typeof mode === 'undefined' ? 438 : mode
|
|
if (flags & 64) {
|
|
mode = (mode & 4095) | 32768
|
|
} else {
|
|
mode = 0
|
|
}
|
|
var node
|
|
if (typeof path === 'object') {
|
|
node = path
|
|
} else {
|
|
path = PATH.normalize(path)
|
|
try {
|
|
var lookup = FS.lookupPath(path, { follow: !(flags & 131072) })
|
|
node = lookup.node
|
|
} catch (e) {}
|
|
}
|
|
var created = false
|
|
if (flags & 64) {
|
|
if (node) {
|
|
if (flags & 128) {
|
|
throw new FS.ErrnoError(17)
|
|
}
|
|
} else {
|
|
node = FS.mknod(path, mode, 0)
|
|
created = true
|
|
}
|
|
}
|
|
if (!node) {
|
|
throw new FS.ErrnoError(2)
|
|
}
|
|
if (FS.isChrdev(node.mode)) {
|
|
flags &= ~512
|
|
}
|
|
if (flags & 65536 && !FS.isDir(node.mode)) {
|
|
throw new FS.ErrnoError(20)
|
|
}
|
|
if (!created) {
|
|
var err = FS.mayOpen(node, flags)
|
|
if (err) {
|
|
throw new FS.ErrnoError(err)
|
|
}
|
|
}
|
|
if (flags & 512) {
|
|
FS.truncate(node, 0)
|
|
}
|
|
flags &= ~(128 | 512)
|
|
var stream = FS.createStream(
|
|
{
|
|
node: node,
|
|
path: FS.getPath(node),
|
|
flags: flags,
|
|
seekable: true,
|
|
position: 0,
|
|
stream_ops: node.stream_ops,
|
|
ungotten: [],
|
|
error: false,
|
|
},
|
|
fd_start,
|
|
fd_end
|
|
)
|
|
if (stream.stream_ops.open) {
|
|
stream.stream_ops.open(stream)
|
|
}
|
|
if (Module['logReadFiles'] && !(flags & 1)) {
|
|
if (!FS.readFiles) FS.readFiles = {}
|
|
if (!(path in FS.readFiles)) {
|
|
FS.readFiles[path] = 1
|
|
console.log('FS.trackingDelegate error on read file: ' + path)
|
|
}
|
|
}
|
|
try {
|
|
if (FS.trackingDelegate['onOpenFile']) {
|
|
var trackingFlags = 0
|
|
if ((flags & 2097155) !== 1) {
|
|
trackingFlags |= FS.tracking.openFlags.READ
|
|
}
|
|
if ((flags & 2097155) !== 0) {
|
|
trackingFlags |= FS.tracking.openFlags.WRITE
|
|
}
|
|
FS.trackingDelegate['onOpenFile'](path, trackingFlags)
|
|
}
|
|
} catch (e) {
|
|
console.log(
|
|
"FS.trackingDelegate['onOpenFile']('" +
|
|
path +
|
|
"', flags) threw an exception: " +
|
|
e.message
|
|
)
|
|
}
|
|
return stream
|
|
},
|
|
close: function(stream) {
|
|
if (FS.isClosed(stream)) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
if (stream.getdents) stream.getdents = null
|
|
try {
|
|
if (stream.stream_ops.close) {
|
|
stream.stream_ops.close(stream)
|
|
}
|
|
} catch (e) {
|
|
throw e
|
|
} finally {
|
|
FS.closeStream(stream.fd)
|
|
}
|
|
stream.fd = null
|
|
},
|
|
isClosed: function(stream) {
|
|
return stream.fd === null
|
|
},
|
|
llseek: function(stream, offset, whence) {
|
|
if (FS.isClosed(stream)) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
if (!stream.seekable || !stream.stream_ops.llseek) {
|
|
throw new FS.ErrnoError(29)
|
|
}
|
|
if (whence != 0 && whence != 1 && whence != 2) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
stream.position = stream.stream_ops.llseek(stream, offset, whence)
|
|
stream.ungotten = []
|
|
return stream.position
|
|
},
|
|
read: function(stream, buffer, offset, length, position) {
|
|
if (length < 0 || position < 0) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
if (FS.isClosed(stream)) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
if ((stream.flags & 2097155) === 1) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
if (FS.isDir(stream.node.mode)) {
|
|
throw new FS.ErrnoError(21)
|
|
}
|
|
if (!stream.stream_ops.read) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
var seeking = typeof position !== 'undefined'
|
|
if (!seeking) {
|
|
position = stream.position
|
|
} else if (!stream.seekable) {
|
|
throw new FS.ErrnoError(29)
|
|
}
|
|
var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position)
|
|
if (!seeking) stream.position += bytesRead
|
|
return bytesRead
|
|
},
|
|
write: function(stream, buffer, offset, length, position, canOwn) {
|
|
if (length < 0 || position < 0) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
if (FS.isClosed(stream)) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
if ((stream.flags & 2097155) === 0) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
if (FS.isDir(stream.node.mode)) {
|
|
throw new FS.ErrnoError(21)
|
|
}
|
|
if (!stream.stream_ops.write) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
if (stream.flags & 1024) {
|
|
FS.llseek(stream, 0, 2)
|
|
}
|
|
var seeking = typeof position !== 'undefined'
|
|
if (!seeking) {
|
|
position = stream.position
|
|
} else if (!stream.seekable) {
|
|
throw new FS.ErrnoError(29)
|
|
}
|
|
var bytesWritten = stream.stream_ops.write(
|
|
stream,
|
|
buffer,
|
|
offset,
|
|
length,
|
|
position,
|
|
canOwn
|
|
)
|
|
if (!seeking) stream.position += bytesWritten
|
|
try {
|
|
if (stream.path && FS.trackingDelegate['onWriteToFile'])
|
|
FS.trackingDelegate['onWriteToFile'](stream.path)
|
|
} catch (e) {
|
|
console.log(
|
|
"FS.trackingDelegate['onWriteToFile']('" +
|
|
stream.path +
|
|
"') threw an exception: " +
|
|
e.message
|
|
)
|
|
}
|
|
return bytesWritten
|
|
},
|
|
allocate: function(stream, offset, length) {
|
|
if (FS.isClosed(stream)) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
if (offset < 0 || length <= 0) {
|
|
throw new FS.ErrnoError(22)
|
|
}
|
|
if ((stream.flags & 2097155) === 0) {
|
|
throw new FS.ErrnoError(9)
|
|
}
|
|
if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {
|
|
throw new FS.ErrnoError(19)
|
|
}
|
|
if (!stream.stream_ops.allocate) {
|
|
throw new FS.ErrnoError(95)
|
|
}
|
|
stream.stream_ops.allocate(stream, offset, length)
|
|
},
|
|
mmap: function(stream, buffer, offset, length, position, prot, flags) {
|
|
if ((stream.flags & 2097155) === 1) {
|
|
throw new FS.ErrnoError(13)
|
|
}
|
|
if (!stream.stream_ops.mmap) {
|
|
throw new FS.ErrnoError(19)
|
|
}
|
|
return stream.stream_ops.mmap(
|
|
stream,
|
|
buffer,
|
|
offset,
|
|
length,
|
|
position,
|
|
prot,
|
|
flags
|
|
)
|
|
},
|
|
msync: function(stream, buffer, offset, length, mmapFlags) {
|
|
if (!stream || !stream.stream_ops.msync) {
|
|
return 0
|
|
}
|
|
return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags)
|
|
},
|
|
munmap: function(stream) {
|
|
return 0
|
|
},
|
|
ioctl: function(stream, cmd, arg) {
|
|
if (!stream.stream_ops.ioctl) {
|
|
throw new FS.ErrnoError(25)
|
|
}
|
|
return stream.stream_ops.ioctl(stream, cmd, arg)
|
|
},
|
|
readFile: function(path, opts) {
|
|
opts = opts || {}
|
|
opts.flags = opts.flags || 'r'
|
|
opts.encoding = opts.encoding || 'binary'
|
|
if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
|
|
throw new Error('Invalid encoding type "' + opts.encoding + '"')
|
|
}
|
|
var ret
|
|
var stream = FS.open(path, opts.flags)
|
|
var stat = FS.stat(path)
|
|
var length = stat.size
|
|
var buf = new Uint8Array(length)
|
|
FS.read(stream, buf, 0, length, 0)
|
|
if (opts.encoding === 'utf8') {
|
|
ret = UTF8ArrayToString(buf, 0)
|
|
} else if (opts.encoding === 'binary') {
|
|
ret = buf
|
|
}
|
|
FS.close(stream)
|
|
return ret
|
|
},
|
|
writeFile: function(path, data, opts) {
|
|
opts = opts || {}
|
|
opts.flags = opts.flags || 'w'
|
|
var stream = FS.open(path, opts.flags, opts.mode)
|
|
if (typeof data === 'string') {
|
|
var buf = new Uint8Array(lengthBytesUTF8(data) + 1)
|
|
var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length)
|
|
FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn)
|
|
} else if (ArrayBuffer.isView(data)) {
|
|
FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn)
|
|
} else {
|
|
throw new Error('Unsupported data type')
|
|
}
|
|
FS.close(stream)
|
|
},
|
|
cwd: function() {
|
|
return FS.currentPath
|
|
},
|
|
chdir: function(path) {
|
|
var lookup = FS.lookupPath(path, { follow: true })
|
|
if (lookup.node === null) {
|
|
throw new FS.ErrnoError(2)
|
|
}
|
|
if (!FS.isDir(lookup.node.mode)) {
|
|
throw new FS.ErrnoError(20)
|
|
}
|
|
var err = FS.nodePermissions(lookup.node, 'x')
|
|
if (err) {
|
|
throw new FS.ErrnoError(err)
|
|
}
|
|
FS.currentPath = lookup.path
|
|
},
|
|
createDefaultDirectories: function() {
|
|
FS.mkdir('/tmp')
|
|
FS.mkdir('/home')
|
|
FS.mkdir('/home/web_user')
|
|
},
|
|
createDefaultDevices: function() {
|
|
FS.mkdir('/dev')
|
|
FS.registerDevice(FS.makedev(1, 3), {
|
|
read: function() {
|
|
return 0
|
|
},
|
|
write: function(stream, buffer, offset, length, pos) {
|
|
return length
|
|
},
|
|
})
|
|
FS.mkdev('/dev/null', FS.makedev(1, 3))
|
|
TTY.register(FS.makedev(5, 0), TTY.default_tty_ops)
|
|
TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops)
|
|
FS.mkdev('/dev/tty', FS.makedev(5, 0))
|
|
FS.mkdev('/dev/tty1', FS.makedev(6, 0))
|
|
var random_device
|
|
if (
|
|
typeof crypto === 'object' &&
|
|
typeof crypto['getRandomValues'] === 'function'
|
|
) {
|
|
var randomBuffer = new Uint8Array(1)
|
|
random_device = function() {
|
|
crypto.getRandomValues(randomBuffer)
|
|
return randomBuffer[0]
|
|
}
|
|
} else if (ENVIRONMENT_IS_NODE) {
|
|
try {
|
|
var crypto_module = require('crypto')
|
|
random_device = function() {
|
|
return crypto_module['randomBytes'](1)[0]
|
|
}
|
|
} catch (e) {}
|
|
} else {
|
|
}
|
|
if (!random_device) {
|
|
random_device = function() {
|
|
abort('random_device')
|
|
}
|
|
}
|
|
FS.createDevice('/dev', 'random', random_device)
|
|
FS.createDevice('/dev', 'urandom', random_device)
|
|
FS.mkdir('/dev/shm')
|
|
FS.mkdir('/dev/shm/tmp')
|
|
},
|
|
createSpecialDirectories: function() {
|
|
FS.mkdir('/proc')
|
|
FS.mkdir('/proc/self')
|
|
FS.mkdir('/proc/self/fd')
|
|
FS.mount(
|
|
{
|
|
mount: function() {
|
|
var node = FS.createNode('/proc/self', 'fd', 16384 | 511, 73)
|
|
node.node_ops = {
|
|
lookup: function(parent, name) {
|
|
var fd = +name
|
|
var stream = FS.getStream(fd)
|
|
if (!stream) throw new FS.ErrnoError(9)
|
|
var ret = {
|
|
parent: null,
|
|
mount: { mountpoint: 'fake' },
|
|
node_ops: {
|
|
readlink: function() {
|
|
return stream.path
|
|
},
|
|
},
|
|
}
|
|
ret.parent = ret
|
|
return ret
|
|
},
|
|
}
|
|
return node
|
|
},
|
|
},
|
|
{},
|
|
'/proc/self/fd'
|
|
)
|
|
},
|
|
createStandardStreams: function() {
|
|
if (Module['stdin']) {
|
|
FS.createDevice('/dev', 'stdin', Module['stdin'])
|
|
} else {
|
|
FS.symlink('/dev/tty', '/dev/stdin')
|
|
}
|
|
if (Module['stdout']) {
|
|
FS.createDevice('/dev', 'stdout', null, Module['stdout'])
|
|
} else {
|
|
FS.symlink('/dev/tty', '/dev/stdout')
|
|
}
|
|
if (Module['stderr']) {
|
|
FS.createDevice('/dev', 'stderr', null, Module['stderr'])
|
|
} else {
|
|
FS.symlink('/dev/tty1', '/dev/stderr')
|
|
}
|
|
var stdin = FS.open('/dev/stdin', 'r')
|
|
var stdout = FS.open('/dev/stdout', 'w')
|
|
var stderr = FS.open('/dev/stderr', 'w')
|
|
},
|
|
ensureErrnoError: function() {
|
|
if (FS.ErrnoError) return
|
|
FS.ErrnoError = function ErrnoError(errno, node) {
|
|
this.node = node
|
|
this.setErrno = function(errno) {
|
|
this.errno = errno
|
|
}
|
|
this.setErrno(errno)
|
|
this.message = 'FS error'
|
|
if (this.stack)
|
|
Object.defineProperty(this, 'stack', {
|
|
value: new Error().stack,
|
|
writable: true,
|
|
})
|
|
}
|
|
FS.ErrnoError.prototype = new Error()
|
|
FS.ErrnoError.prototype.constructor = FS.ErrnoError
|
|
;[2].forEach(function(code) {
|
|
FS.genericErrors[code] = new FS.ErrnoError(code)
|
|
FS.genericErrors[code].stack = '<generic error, no stack>'
|
|
})
|
|
},
|
|
staticInit: function() {
|
|
FS.ensureErrnoError()
|
|
FS.nameTable = new Array(4096)
|
|
FS.mount(MEMFS, {}, '/')
|
|
FS.createDefaultDirectories()
|
|
FS.createDefaultDevices()
|
|
FS.createSpecialDirectories()
|
|
FS.filesystems = {
|
|
MEMFS: MEMFS,
|
|
IDBFS: IDBFS,
|
|
NODEFS: NODEFS,
|
|
WORKERFS: WORKERFS,
|
|
}
|
|
},
|
|
init: function(input, output, error) {
|
|
FS.init.initialized = true
|
|
FS.ensureErrnoError()
|
|
Module['stdin'] = input || Module['stdin']
|
|
Module['stdout'] = output || Module['stdout']
|
|
Module['stderr'] = error || Module['stderr']
|
|
FS.createStandardStreams()
|
|
},
|
|
quit: function() {
|
|
FS.init.initialized = false
|
|
var fflush = Module['_fflush']
|
|
if (fflush) fflush(0)
|
|
for (var i = 0; i < FS.streams.length; i++) {
|
|
var stream = FS.streams[i]
|
|
if (!stream) {
|
|
continue
|
|
}
|
|
FS.close(stream)
|
|
}
|
|
},
|
|
getMode: function(canRead, canWrite) {
|
|
var mode = 0
|
|
if (canRead) mode |= 292 | 73
|
|
if (canWrite) mode |= 146
|
|
return mode
|
|
},
|
|
joinPath: function(parts, forceRelative) {
|
|
var path = PATH.join.apply(null, parts)
|
|
if (forceRelative && path[0] == '/') path = path.substr(1)
|
|
return path
|
|
},
|
|
absolutePath: function(relative, base) {
|
|
return PATH_FS.resolve(base, relative)
|
|
},
|
|
standardizePath: function(path) {
|
|
return PATH.normalize(path)
|
|
},
|
|
findObject: function(path, dontResolveLastLink) {
|
|
var ret = FS.analyzePath(path, dontResolveLastLink)
|
|
if (ret.exists) {
|
|
return ret.object
|
|
} else {
|
|
___setErrNo(ret.error)
|
|
return null
|
|
}
|
|
},
|
|
analyzePath: function(path, dontResolveLastLink) {
|
|
try {
|
|
var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink })
|
|
path = lookup.path
|
|
} catch (e) {}
|
|
var ret = {
|
|
isRoot: false,
|
|
exists: false,
|
|
error: 0,
|
|
name: null,
|
|
path: null,
|
|
object: null,
|
|
parentExists: false,
|
|
parentPath: null,
|
|
parentObject: null,
|
|
}
|
|
try {
|
|
var lookup = FS.lookupPath(path, { parent: true })
|
|
ret.parentExists = true
|
|
ret.parentPath = lookup.path
|
|
ret.parentObject = lookup.node
|
|
ret.name = PATH.basename(path)
|
|
lookup = FS.lookupPath(path, { follow: !dontResolveLastLink })
|
|
ret.exists = true
|
|
ret.path = lookup.path
|
|
ret.object = lookup.node
|
|
ret.name = lookup.node.name
|
|
ret.isRoot = lookup.path === '/'
|
|
} catch (e) {
|
|
ret.error = e.errno
|
|
}
|
|
return ret
|
|
},
|
|
createFolder: function(parent, name, canRead, canWrite) {
|
|
var path = PATH.join2(
|
|
typeof parent === 'string' ? parent : FS.getPath(parent),
|
|
name
|
|
)
|
|
var mode = FS.getMode(canRead, canWrite)
|
|
return FS.mkdir(path, mode)
|
|
},
|
|
createPath: function(parent, path, canRead, canWrite) {
|
|
parent = typeof parent === 'string' ? parent : FS.getPath(parent)
|
|
var parts = path.split('/').reverse()
|
|
while (parts.length) {
|
|
var part = parts.pop()
|
|
if (!part) continue
|
|
var current = PATH.join2(parent, part)
|
|
try {
|
|
FS.mkdir(current)
|
|
} catch (e) {}
|
|
parent = current
|
|
}
|
|
return current
|
|
},
|
|
createFile: function(parent, name, properties, canRead, canWrite) {
|
|
var path = PATH.join2(
|
|
typeof parent === 'string' ? parent : FS.getPath(parent),
|
|
name
|
|
)
|
|
var mode = FS.getMode(canRead, canWrite)
|
|
return FS.create(path, mode)
|
|
},
|
|
createDataFile: function(parent, name, data, canRead, canWrite, canOwn) {
|
|
var path = name
|
|
? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name)
|
|
: parent
|
|
var mode = FS.getMode(canRead, canWrite)
|
|
var node = FS.create(path, mode)
|
|
if (data) {
|
|
if (typeof data === 'string') {
|
|
var arr = new Array(data.length)
|
|
for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i)
|
|
data = arr
|
|
}
|
|
FS.chmod(node, mode | 146)
|
|
var stream = FS.open(node, 'w')
|
|
FS.write(stream, data, 0, data.length, 0, canOwn)
|
|
FS.close(stream)
|
|
FS.chmod(node, mode)
|
|
}
|
|
return node
|
|
},
|
|
createDevice: function(parent, name, input, output) {
|
|
var path = PATH.join2(
|
|
typeof parent === 'string' ? parent : FS.getPath(parent),
|
|
name
|
|
)
|
|
var mode = FS.getMode(!!input, !!output)
|
|
if (!FS.createDevice.major) FS.createDevice.major = 64
|
|
var dev = FS.makedev(FS.createDevice.major++, 0)
|
|
FS.registerDevice(dev, {
|
|
open: function(stream) {
|
|
stream.seekable = false
|
|
},
|
|
close: function(stream) {
|
|
if (output && output.buffer && output.buffer.length) {
|
|
output(10)
|
|
}
|
|
},
|
|
read: function(stream, buffer, offset, length, pos) {
|
|
var bytesRead = 0
|
|
for (var i = 0; i < length; i++) {
|
|
var result
|
|
try {
|
|
result = input()
|
|
} catch (e) {
|
|
throw new FS.ErrnoError(5)
|
|
}
|
|
if (result === undefined && bytesRead === 0) {
|
|
throw new FS.ErrnoError(11)
|
|
}
|
|
if (result === null || result === undefined) break
|
|
bytesRead++
|
|
buffer[offset + i] = result
|
|
}
|
|
if (bytesRead) {
|
|
stream.node.timestamp = Date.now()
|
|
}
|
|
return bytesRead
|
|
},
|
|
write: function(stream, buffer, offset, length, pos) {
|
|
for (var i = 0; i < length; i++) {
|
|
try {
|
|
output(buffer[offset + i])
|
|
} catch (e) {
|
|
throw new FS.ErrnoError(5)
|
|
}
|
|
}
|
|
if (length) {
|
|
stream.node.timestamp = Date.now()
|
|
}
|
|
return i
|
|
},
|
|
})
|
|
return FS.mkdev(path, mode, dev)
|
|
},
|
|
createLink: function(parent, name, target, canRead, canWrite) {
|
|
var path = PATH.join2(
|
|
typeof parent === 'string' ? parent : FS.getPath(parent),
|
|
name
|
|
)
|
|
return FS.symlink(target, path)
|
|
},
|
|
forceLoadFile: function(obj) {
|
|
if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true
|
|
var success = true
|
|
if (typeof XMLHttpRequest !== 'undefined') {
|
|
throw new Error(
|
|
'Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.'
|
|
)
|
|
} else if (Module['read']) {
|
|
try {
|
|
obj.contents = intArrayFromString(Module['read'](obj.url), true)
|
|
obj.usedBytes = obj.contents.length
|
|
} catch (e) {
|
|
success = false
|
|
}
|
|
} else {
|
|
throw new Error('Cannot load without read() or XMLHttpRequest.')
|
|
}
|
|
if (!success) ___setErrNo(5)
|
|
return success
|
|
},
|
|
createLazyFile: function(parent, name, url, canRead, canWrite) {
|
|
function LazyUint8Array() {
|
|
this.lengthKnown = false
|
|
this.chunks = []
|
|
}
|
|
LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) {
|
|
if (idx > this.length - 1 || idx < 0) {
|
|
return undefined
|
|
}
|
|
var chunkOffset = idx % this.chunkSize
|
|
var chunkNum = (idx / this.chunkSize) | 0
|
|
return this.getter(chunkNum)[chunkOffset]
|
|
}
|
|
LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(
|
|
getter
|
|
) {
|
|
this.getter = getter
|
|
}
|
|
LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {
|
|
var xhr = new XMLHttpRequest()
|
|
xhr.open('HEAD', url, false)
|
|
xhr.send(null)
|
|
if (!((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304))
|
|
throw new Error("Couldn't load " + url + '. Status: ' + xhr.status)
|
|
var datalength = Number(xhr.getResponseHeader('Content-length'))
|
|
var header
|
|
var hasByteServing =
|
|
(header = xhr.getResponseHeader('Accept-Ranges')) && header === 'bytes'
|
|
var usesGzip =
|
|
(header = xhr.getResponseHeader('Content-Encoding')) && header === 'gzip'
|
|
var chunkSize = 1024 * 1024
|
|
if (!hasByteServing) chunkSize = datalength
|
|
var doXHR = function(from, to) {
|
|
if (from > to)
|
|
throw new Error(
|
|
'invalid range (' + from + ', ' + to + ') or no bytes requested!'
|
|
)
|
|
if (to > datalength - 1)
|
|
throw new Error(
|
|
'only ' + datalength + ' bytes available! programmer error!'
|
|
)
|
|
var xhr = new XMLHttpRequest()
|
|
xhr.open('GET', url, false)
|
|
if (datalength !== chunkSize)
|
|
xhr.setRequestHeader('Range', 'bytes=' + from + '-' + to)
|
|
if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer'
|
|
if (xhr.overrideMimeType) {
|
|
xhr.overrideMimeType('text/plain; charset=x-user-defined')
|
|
}
|
|
xhr.send(null)
|
|
if (!((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304))
|
|
throw new Error("Couldn't load " + url + '. Status: ' + xhr.status)
|
|
if (xhr.response !== undefined) {
|
|
return new Uint8Array(xhr.response || [])
|
|
} else {
|
|
return intArrayFromString(xhr.responseText || '', true)
|
|
}
|
|
}
|
|
var lazyArray = this
|
|
lazyArray.setDataGetter(function(chunkNum) {
|
|
var start = chunkNum * chunkSize
|
|
var end = (chunkNum + 1) * chunkSize - 1
|
|
end = Math.min(end, datalength - 1)
|
|
if (typeof lazyArray.chunks[chunkNum] === 'undefined') {
|
|
lazyArray.chunks[chunkNum] = doXHR(start, end)
|
|
}
|
|
if (typeof lazyArray.chunks[chunkNum] === 'undefined')
|
|
throw new Error('doXHR failed!')
|
|
return lazyArray.chunks[chunkNum]
|
|
})
|
|
if (usesGzip || !datalength) {
|
|
chunkSize = datalength = 1
|
|
datalength = this.getter(0).length
|
|
chunkSize = datalength
|
|
console.log(
|
|
'LazyFiles on gzip forces download of the whole file when length is accessed'
|
|
)
|
|
}
|
|
this._length = datalength
|
|
this._chunkSize = chunkSize
|
|
this.lengthKnown = true
|
|
}
|
|
if (typeof XMLHttpRequest !== 'undefined') {
|
|
if (!ENVIRONMENT_IS_WORKER)
|
|
throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'
|
|
var lazyArray = new LazyUint8Array()
|
|
Object.defineProperties(lazyArray, {
|
|
length: {
|
|
get: function() {
|
|
if (!this.lengthKnown) {
|
|
this.cacheLength()
|
|
}
|
|
return this._length
|
|
},
|
|
},
|
|
chunkSize: {
|
|
get: function() {
|
|
if (!this.lengthKnown) {
|
|
this.cacheLength()
|
|
}
|
|
return this._chunkSize
|
|
},
|
|
},
|
|
})
|
|
var properties = { isDevice: false, contents: lazyArray }
|
|
} else {
|
|
var properties = { isDevice: false, url: url }
|
|
}
|
|
var node = FS.createFile(parent, name, properties, canRead, canWrite)
|
|
if (properties.contents) {
|
|
node.contents = properties.contents
|
|
} else if (properties.url) {
|
|
node.contents = null
|
|
node.url = properties.url
|
|
}
|
|
Object.defineProperties(node, {
|
|
usedBytes: {
|
|
get: function() {
|
|
return this.contents.length
|
|
},
|
|
},
|
|
})
|
|
var stream_ops = {}
|
|
var keys = Object.keys(node.stream_ops)
|
|
keys.forEach(function(key) {
|
|
var fn = node.stream_ops[key]
|
|
stream_ops[key] = function forceLoadLazyFile() {
|
|
if (!FS.forceLoadFile(node)) {
|
|
throw new FS.ErrnoError(5)
|
|
}
|
|
return fn.apply(null, arguments)
|
|
}
|
|
})
|
|
stream_ops.read = function stream_ops_read(
|
|
stream,
|
|
buffer,
|
|
offset,
|
|
length,
|
|
position
|
|
) {
|
|
if (!FS.forceLoadFile(node)) {
|
|
throw new FS.ErrnoError(5)
|
|
}
|
|
var contents = stream.node.contents
|
|
if (position >= contents.length) return 0
|
|
var size = Math.min(contents.length - position, length)
|
|
if (contents.slice) {
|
|
for (var i = 0; i < size; i++) {
|
|
buffer[offset + i] = contents[position + i]
|
|
}
|
|
} else {
|
|
for (var i = 0; i < size; i++) {
|
|
buffer[offset + i] = contents.get(position + i)
|
|
}
|
|
}
|
|
return size
|
|
}
|
|
node.stream_ops = stream_ops
|
|
return node
|
|
},
|
|
createPreloadedFile: function(
|
|
parent,
|
|
name,
|
|
url,
|
|
canRead,
|
|
canWrite,
|
|
onload,
|
|
onerror,
|
|
dontCreateFile,
|
|
canOwn,
|
|
preFinish
|
|
) {
|
|
Browser.init()
|
|
var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent
|
|
var dep = getUniqueRunDependency('cp ' + fullname)
|
|
function processData(byteArray) {
|
|
function finish(byteArray) {
|
|
if (preFinish) preFinish()
|
|
if (!dontCreateFile) {
|
|
FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn)
|
|
}
|
|
if (onload) onload()
|
|
removeRunDependency(dep)
|
|
}
|
|
var handled = false
|
|
Module['preloadPlugins'].forEach(function(plugin) {
|
|
if (handled) return
|
|
if (plugin['canHandle'](fullname)) {
|
|
plugin['handle'](byteArray, fullname, finish, function() {
|
|
if (onerror) onerror()
|
|
removeRunDependency(dep)
|
|
})
|
|
handled = true
|
|
}
|
|
})
|
|
if (!handled) finish(byteArray)
|
|
}
|
|
addRunDependency(dep)
|
|
if (typeof url == 'string') {
|
|
Browser.asyncLoad(
|
|
url,
|
|
function(byteArray) {
|
|
processData(byteArray)
|
|
},
|
|
onerror
|
|
)
|
|
} else {
|
|
processData(url)
|
|
}
|
|
},
|
|
indexedDB: function() {
|
|
return (
|
|
window.indexedDB ||
|
|
window.mozIndexedDB ||
|
|
window.webkitIndexedDB ||
|
|
window.msIndexedDB
|
|
)
|
|
},
|
|
DB_NAME: function() {
|
|
return 'EM_FS_' + window.location.pathname
|
|
},
|
|
DB_VERSION: 20,
|
|
DB_STORE_NAME: 'FILE_DATA',
|
|
saveFilesToDB: function(paths, onload, onerror) {
|
|
onload = onload || function() {}
|
|
onerror = onerror || function() {}
|
|
var indexedDB = FS.indexedDB()
|
|
try {
|
|
var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION)
|
|
} catch (e) {
|
|
return onerror(e)
|
|
}
|
|
openRequest.onupgradeneeded = function openRequest_onupgradeneeded() {
|
|
console.log('creating db')
|
|
var db = openRequest.result
|
|
db.createObjectStore(FS.DB_STORE_NAME)
|
|
}
|
|
openRequest.onsuccess = function openRequest_onsuccess() {
|
|
var db = openRequest.result
|
|
var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite')
|
|
var files = transaction.objectStore(FS.DB_STORE_NAME)
|
|
var ok = 0,
|
|
fail = 0,
|
|
total = paths.length
|
|
function finish() {
|
|
if (fail == 0) onload()
|
|
else onerror()
|
|
}
|
|
paths.forEach(function(path) {
|
|
var putRequest = files.put(FS.analyzePath(path).object.contents, path)
|
|
putRequest.onsuccess = function putRequest_onsuccess() {
|
|
ok++
|
|
if (ok + fail == total) finish()
|
|
}
|
|
putRequest.onerror = function putRequest_onerror() {
|
|
fail++
|
|
if (ok + fail == total) finish()
|
|
}
|
|
})
|
|
transaction.onerror = onerror
|
|
}
|
|
openRequest.onerror = onerror
|
|
},
|
|
loadFilesFromDB: function(paths, onload, onerror) {
|
|
onload = onload || function() {}
|
|
onerror = onerror || function() {}
|
|
var indexedDB = FS.indexedDB()
|
|
try {
|
|
var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION)
|
|
} catch (e) {
|
|
return onerror(e)
|
|
}
|
|
openRequest.onupgradeneeded = onerror
|
|
openRequest.onsuccess = function openRequest_onsuccess() {
|
|
var db = openRequest.result
|
|
try {
|
|
var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly')
|
|
} catch (e) {
|
|
onerror(e)
|
|
return
|
|
}
|
|
var files = transaction.objectStore(FS.DB_STORE_NAME)
|
|
var ok = 0,
|
|
fail = 0,
|
|
total = paths.length
|
|
function finish() {
|
|
if (fail == 0) onload()
|
|
else onerror()
|
|
}
|
|
paths.forEach(function(path) {
|
|
var getRequest = files.get(path)
|
|
getRequest.onsuccess = function getRequest_onsuccess() {
|
|
if (FS.analyzePath(path).exists) {
|
|
FS.unlink(path)
|
|
}
|
|
FS.createDataFile(
|
|
PATH.dirname(path),
|
|
PATH.basename(path),
|
|
getRequest.result,
|
|
true,
|
|
true,
|
|
true
|
|
)
|
|
ok++
|
|
if (ok + fail == total) finish()
|
|
}
|
|
getRequest.onerror = function getRequest_onerror() {
|
|
fail++
|
|
if (ok + fail == total) finish()
|
|
}
|
|
})
|
|
transaction.onerror = onerror
|
|
}
|
|
openRequest.onerror = onerror
|
|
},
|
|
}
|
|
var SYSCALLS = {
|
|
DEFAULT_POLLMASK: 5,
|
|
mappings: {},
|
|
umask: 511,
|
|
calculateAt: function(dirfd, path) {
|
|
if (path[0] !== '/') {
|
|
var dir
|
|
if (dirfd === -100) {
|
|
dir = FS.cwd()
|
|
} else {
|
|
var dirstream = FS.getStream(dirfd)
|
|
if (!dirstream) throw new FS.ErrnoError(9)
|
|
dir = dirstream.path
|
|
}
|
|
path = PATH.join2(dir, path)
|
|
}
|
|
return path
|
|
},
|
|
doStat: function(func, path, buf) {
|
|
try {
|
|
var stat = func(path)
|
|
} catch (e) {
|
|
if (
|
|
e &&
|
|
e.node &&
|
|
PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))
|
|
) {
|
|
return -20
|
|
}
|
|
throw e
|
|
}
|
|
HEAP32[buf >> 2] = stat.dev
|
|
HEAP32[(buf + 4) >> 2] = 0
|
|
HEAP32[(buf + 8) >> 2] = stat.ino
|
|
HEAP32[(buf + 12) >> 2] = stat.mode
|
|
HEAP32[(buf + 16) >> 2] = stat.nlink
|
|
HEAP32[(buf + 20) >> 2] = stat.uid
|
|
HEAP32[(buf + 24) >> 2] = stat.gid
|
|
HEAP32[(buf + 28) >> 2] = stat.rdev
|
|
HEAP32[(buf + 32) >> 2] = 0
|
|
;(tempI64 = [
|
|
stat.size >>> 0,
|
|
((tempDouble = stat.size),
|
|
+Math_abs(tempDouble) >= 1
|
|
? tempDouble > 0
|
|
? (Math_min(+Math_floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0
|
|
: ~~+Math_ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0
|
|
: 0),
|
|
]),
|
|
(HEAP32[(buf + 40) >> 2] = tempI64[0]),
|
|
(HEAP32[(buf + 44) >> 2] = tempI64[1])
|
|
HEAP32[(buf + 48) >> 2] = 4096
|
|
HEAP32[(buf + 52) >> 2] = stat.blocks
|
|
HEAP32[(buf + 56) >> 2] = (stat.atime.getTime() / 1e3) | 0
|
|
HEAP32[(buf + 60) >> 2] = 0
|
|
HEAP32[(buf + 64) >> 2] = (stat.mtime.getTime() / 1e3) | 0
|
|
HEAP32[(buf + 68) >> 2] = 0
|
|
HEAP32[(buf + 72) >> 2] = (stat.ctime.getTime() / 1e3) | 0
|
|
HEAP32[(buf + 76) >> 2] = 0
|
|
;(tempI64 = [
|
|
stat.ino >>> 0,
|
|
((tempDouble = stat.ino),
|
|
+Math_abs(tempDouble) >= 1
|
|
? tempDouble > 0
|
|
? (Math_min(+Math_floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0
|
|
: ~~+Math_ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0
|
|
: 0),
|
|
]),
|
|
(HEAP32[(buf + 80) >> 2] = tempI64[0]),
|
|
(HEAP32[(buf + 84) >> 2] = tempI64[1])
|
|
return 0
|
|
},
|
|
doMsync: function(addr, stream, len, flags) {
|
|
var buffer = new Uint8Array(HEAPU8.subarray(addr, addr + len))
|
|
FS.msync(stream, buffer, 0, len, flags)
|
|
},
|
|
doMkdir: function(path, mode) {
|
|
path = PATH.normalize(path)
|
|
if (path[path.length - 1] === '/') path = path.substr(0, path.length - 1)
|
|
FS.mkdir(path, mode, 0)
|
|
return 0
|
|
},
|
|
doMknod: function(path, mode, dev) {
|
|
switch (mode & 61440) {
|
|
case 32768:
|
|
case 8192:
|
|
case 24576:
|
|
case 4096:
|
|
case 49152:
|
|
break
|
|
default:
|
|
return -22
|
|
}
|
|
FS.mknod(path, mode, dev)
|
|
return 0
|
|
},
|
|
doReadlink: function(path, buf, bufsize) {
|
|
if (bufsize <= 0) return -22
|
|
var ret = FS.readlink(path)
|
|
var len = Math.min(bufsize, lengthBytesUTF8(ret))
|
|
var endChar = HEAP8[buf + len]
|
|
stringToUTF8(ret, buf, bufsize + 1)
|
|
HEAP8[buf + len] = endChar
|
|
return len
|
|
},
|
|
doAccess: function(path, amode) {
|
|
if (amode & ~7) {
|
|
return -22
|
|
}
|
|
var node
|
|
var lookup = FS.lookupPath(path, { follow: true })
|
|
node = lookup.node
|
|
var perms = ''
|
|
if (amode & 4) perms += 'r'
|
|
if (amode & 2) perms += 'w'
|
|
if (amode & 1) perms += 'x'
|
|
if (perms && FS.nodePermissions(node, perms)) {
|
|
return -13
|
|
}
|
|
return 0
|
|
},
|
|
doDup: function(path, flags, suggestFD) {
|
|
var suggest = FS.getStream(suggestFD)
|
|
if (suggest) FS.close(suggest)
|
|
return FS.open(path, flags, 0, suggestFD, suggestFD).fd
|
|
},
|
|
doReadv: function(stream, iov, iovcnt, offset) {
|
|
var ret = 0
|
|
for (var i = 0; i < iovcnt; i++) {
|
|
var ptr = HEAP32[(iov + i * 8) >> 2]
|
|
var len = HEAP32[(iov + (i * 8 + 4)) >> 2]
|
|
var curr = FS.read(stream, HEAP8, ptr, len, offset)
|
|
if (curr < 0) return -1
|
|
ret += curr
|
|
if (curr < len) break
|
|
}
|
|
return ret
|
|
},
|
|
doWritev: function(stream, iov, iovcnt, offset) {
|
|
var ret = 0
|
|
for (var i = 0; i < iovcnt; i++) {
|
|
var ptr = HEAP32[(iov + i * 8) >> 2]
|
|
var len = HEAP32[(iov + (i * 8 + 4)) >> 2]
|
|
var curr = FS.write(stream, HEAP8, ptr, len, offset)
|
|
if (curr < 0) return -1
|
|
ret += curr
|
|
}
|
|
return ret
|
|
},
|
|
varargs: 0,
|
|
get: function(varargs) {
|
|
SYSCALLS.varargs += 4
|
|
var ret = HEAP32[(SYSCALLS.varargs - 4) >> 2]
|
|
return ret
|
|
},
|
|
getStr: function() {
|
|
var ret = UTF8ToString(SYSCALLS.get())
|
|
return ret
|
|
},
|
|
getStreamFromFD: function() {
|
|
var stream = FS.getStream(SYSCALLS.get())
|
|
if (!stream) throw new FS.ErrnoError(9)
|
|
return stream
|
|
},
|
|
get64: function() {
|
|
var low = SYSCALLS.get(),
|
|
high = SYSCALLS.get()
|
|
return low
|
|
},
|
|
getZero: function() {
|
|
SYSCALLS.get()
|
|
},
|
|
}
|
|
function ___syscall140(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var stream = SYSCALLS.getStreamFromFD(),
|
|
offset_high = SYSCALLS.get(),
|
|
offset_low = SYSCALLS.get(),
|
|
result = SYSCALLS.get(),
|
|
whence = SYSCALLS.get()
|
|
if (
|
|
!(offset_high == -1 && offset_low < 0) &&
|
|
!(offset_high == 0 && offset_low >= 0)
|
|
) {
|
|
return -75
|
|
}
|
|
var offset = offset_low
|
|
FS.llseek(stream, offset, whence)
|
|
;(tempI64 = [
|
|
stream.position >>> 0,
|
|
((tempDouble = stream.position),
|
|
+Math_abs(tempDouble) >= 1
|
|
? tempDouble > 0
|
|
? (Math_min(+Math_floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0
|
|
: ~~+Math_ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0
|
|
: 0),
|
|
]),
|
|
(HEAP32[result >> 2] = tempI64[0]),
|
|
(HEAP32[(result + 4) >> 2] = tempI64[1])
|
|
if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null
|
|
return 0
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall146(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var stream = SYSCALLS.getStreamFromFD(),
|
|
iov = SYSCALLS.get(),
|
|
iovcnt = SYSCALLS.get()
|
|
return SYSCALLS.doWritev(stream, iov, iovcnt)
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall168(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var fds = SYSCALLS.get(),
|
|
nfds = SYSCALLS.get(),
|
|
timeout = SYSCALLS.get()
|
|
var nonzero = 0
|
|
for (var i = 0; i < nfds; i++) {
|
|
var pollfd = fds + 8 * i
|
|
var fd = HEAP32[pollfd >> 2]
|
|
var events = HEAP16[(pollfd + 4) >> 1]
|
|
var mask = 32
|
|
var stream = FS.getStream(fd)
|
|
if (stream) {
|
|
mask = SYSCALLS.DEFAULT_POLLMASK
|
|
if (stream.stream_ops.poll) {
|
|
mask = stream.stream_ops.poll(stream)
|
|
}
|
|
}
|
|
mask &= events | 8 | 16
|
|
if (mask) nonzero++
|
|
HEAP16[(pollfd + 6) >> 1] = mask
|
|
}
|
|
return nonzero
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall195(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var path = SYSCALLS.getStr(),
|
|
buf = SYSCALLS.get()
|
|
return SYSCALLS.doStat(FS.stat, path, buf)
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall196(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var path = SYSCALLS.getStr(),
|
|
buf = SYSCALLS.get()
|
|
return SYSCALLS.doStat(FS.lstat, path, buf)
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall197(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var stream = SYSCALLS.getStreamFromFD(),
|
|
buf = SYSCALLS.get()
|
|
return SYSCALLS.doStat(FS.stat, stream.path, buf)
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall221(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var stream = SYSCALLS.getStreamFromFD(),
|
|
cmd = SYSCALLS.get()
|
|
switch (cmd) {
|
|
case 0: {
|
|
var arg = SYSCALLS.get()
|
|
if (arg < 0) {
|
|
return -22
|
|
}
|
|
var newStream
|
|
newStream = FS.open(stream.path, stream.flags, 0, arg)
|
|
return newStream.fd
|
|
}
|
|
case 1:
|
|
case 2:
|
|
return 0
|
|
case 3:
|
|
return stream.flags
|
|
case 4: {
|
|
var arg = SYSCALLS.get()
|
|
stream.flags |= arg
|
|
return 0
|
|
}
|
|
case 12: {
|
|
var arg = SYSCALLS.get()
|
|
var offset = 0
|
|
HEAP16[(arg + offset) >> 1] = 2
|
|
return 0
|
|
}
|
|
case 13:
|
|
case 14:
|
|
return 0
|
|
case 16:
|
|
case 8:
|
|
return -22
|
|
case 9:
|
|
___setErrNo(22)
|
|
return -1
|
|
default: {
|
|
return -22
|
|
}
|
|
}
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall3(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var stream = SYSCALLS.getStreamFromFD(),
|
|
buf = SYSCALLS.get(),
|
|
count = SYSCALLS.get()
|
|
return FS.read(stream, HEAP8, buf, count)
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall4(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var stream = SYSCALLS.getStreamFromFD(),
|
|
buf = SYSCALLS.get(),
|
|
count = SYSCALLS.get()
|
|
return FS.write(stream, HEAP8, buf, count)
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall41(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var old = SYSCALLS.getStreamFromFD()
|
|
return FS.open(old.path, old.flags, 0).fd
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
var ERRNO_CODES = {
|
|
EPERM: 1,
|
|
ENOENT: 2,
|
|
ESRCH: 3,
|
|
EINTR: 4,
|
|
EIO: 5,
|
|
ENXIO: 6,
|
|
E2BIG: 7,
|
|
ENOEXEC: 8,
|
|
EBADF: 9,
|
|
ECHILD: 10,
|
|
EAGAIN: 11,
|
|
EWOULDBLOCK: 11,
|
|
ENOMEM: 12,
|
|
EACCES: 13,
|
|
EFAULT: 14,
|
|
ENOTBLK: 15,
|
|
EBUSY: 16,
|
|
EEXIST: 17,
|
|
EXDEV: 18,
|
|
ENODEV: 19,
|
|
ENOTDIR: 20,
|
|
EISDIR: 21,
|
|
EINVAL: 22,
|
|
ENFILE: 23,
|
|
EMFILE: 24,
|
|
ENOTTY: 25,
|
|
ETXTBSY: 26,
|
|
EFBIG: 27,
|
|
ENOSPC: 28,
|
|
ESPIPE: 29,
|
|
EROFS: 30,
|
|
EMLINK: 31,
|
|
EPIPE: 32,
|
|
EDOM: 33,
|
|
ERANGE: 34,
|
|
ENOMSG: 42,
|
|
EIDRM: 43,
|
|
ECHRNG: 44,
|
|
EL2NSYNC: 45,
|
|
EL3HLT: 46,
|
|
EL3RST: 47,
|
|
ELNRNG: 48,
|
|
EUNATCH: 49,
|
|
ENOCSI: 50,
|
|
EL2HLT: 51,
|
|
EDEADLK: 35,
|
|
ENOLCK: 37,
|
|
EBADE: 52,
|
|
EBADR: 53,
|
|
EXFULL: 54,
|
|
ENOANO: 55,
|
|
EBADRQC: 56,
|
|
EBADSLT: 57,
|
|
EDEADLOCK: 35,
|
|
EBFONT: 59,
|
|
ENOSTR: 60,
|
|
ENODATA: 61,
|
|
ETIME: 62,
|
|
ENOSR: 63,
|
|
ENONET: 64,
|
|
ENOPKG: 65,
|
|
EREMOTE: 66,
|
|
ENOLINK: 67,
|
|
EADV: 68,
|
|
ESRMNT: 69,
|
|
ECOMM: 70,
|
|
EPROTO: 71,
|
|
EMULTIHOP: 72,
|
|
EDOTDOT: 73,
|
|
EBADMSG: 74,
|
|
ENOTUNIQ: 76,
|
|
EBADFD: 77,
|
|
EREMCHG: 78,
|
|
ELIBACC: 79,
|
|
ELIBBAD: 80,
|
|
ELIBSCN: 81,
|
|
ELIBMAX: 82,
|
|
ELIBEXEC: 83,
|
|
ENOSYS: 38,
|
|
ENOTEMPTY: 39,
|
|
ENAMETOOLONG: 36,
|
|
ELOOP: 40,
|
|
EOPNOTSUPP: 95,
|
|
EPFNOSUPPORT: 96,
|
|
ECONNRESET: 104,
|
|
ENOBUFS: 105,
|
|
EAFNOSUPPORT: 97,
|
|
EPROTOTYPE: 91,
|
|
ENOTSOCK: 88,
|
|
ENOPROTOOPT: 92,
|
|
ESHUTDOWN: 108,
|
|
ECONNREFUSED: 111,
|
|
EADDRINUSE: 98,
|
|
ECONNABORTED: 103,
|
|
ENETUNREACH: 101,
|
|
ENETDOWN: 100,
|
|
ETIMEDOUT: 110,
|
|
EHOSTDOWN: 112,
|
|
EHOSTUNREACH: 113,
|
|
EINPROGRESS: 115,
|
|
EALREADY: 114,
|
|
EDESTADDRREQ: 89,
|
|
EMSGSIZE: 90,
|
|
EPROTONOSUPPORT: 93,
|
|
ESOCKTNOSUPPORT: 94,
|
|
EADDRNOTAVAIL: 99,
|
|
ENETRESET: 102,
|
|
EISCONN: 106,
|
|
ENOTCONN: 107,
|
|
ETOOMANYREFS: 109,
|
|
EUSERS: 87,
|
|
EDQUOT: 122,
|
|
ESTALE: 116,
|
|
ENOTSUP: 95,
|
|
ENOMEDIUM: 123,
|
|
EILSEQ: 84,
|
|
EOVERFLOW: 75,
|
|
ECANCELED: 125,
|
|
ENOTRECOVERABLE: 131,
|
|
EOWNERDEAD: 130,
|
|
ESTRPIPE: 86,
|
|
}
|
|
var PIPEFS = {
|
|
BUCKET_BUFFER_SIZE: 8192,
|
|
mount: function(mount) {
|
|
return FS.createNode(null, '/', 16384 | 511, 0)
|
|
},
|
|
createPipe: function() {
|
|
var pipe = { buckets: [] }
|
|
pipe.buckets.push({
|
|
buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
|
|
offset: 0,
|
|
roffset: 0,
|
|
})
|
|
var rName = PIPEFS.nextname()
|
|
var wName = PIPEFS.nextname()
|
|
var rNode = FS.createNode(PIPEFS.root, rName, 4096, 0)
|
|
var wNode = FS.createNode(PIPEFS.root, wName, 4096, 0)
|
|
rNode.pipe = pipe
|
|
wNode.pipe = pipe
|
|
var readableStream = FS.createStream({
|
|
path: rName,
|
|
node: rNode,
|
|
flags: FS.modeStringToFlags('r'),
|
|
seekable: false,
|
|
stream_ops: PIPEFS.stream_ops,
|
|
})
|
|
rNode.stream = readableStream
|
|
var writableStream = FS.createStream({
|
|
path: wName,
|
|
node: wNode,
|
|
flags: FS.modeStringToFlags('w'),
|
|
seekable: false,
|
|
stream_ops: PIPEFS.stream_ops,
|
|
})
|
|
wNode.stream = writableStream
|
|
return { readable_fd: readableStream.fd, writable_fd: writableStream.fd }
|
|
},
|
|
stream_ops: {
|
|
poll: function(stream) {
|
|
var pipe = stream.node.pipe
|
|
if ((stream.flags & 2097155) === 1) {
|
|
return 256 | 4
|
|
} else {
|
|
if (pipe.buckets.length > 0) {
|
|
for (var i = 0; i < pipe.buckets.length; i++) {
|
|
var bucket = pipe.buckets[i]
|
|
if (bucket.offset - bucket.roffset > 0) {
|
|
return 64 | 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0
|
|
},
|
|
ioctl: function(stream, request, varargs) {
|
|
return ERRNO_CODES.EINVAL
|
|
},
|
|
read: function(stream, buffer, offset, length, position) {
|
|
var pipe = stream.node.pipe
|
|
var currentLength = 0
|
|
for (var i = 0; i < pipe.buckets.length; i++) {
|
|
var bucket = pipe.buckets[i]
|
|
currentLength += bucket.offset - bucket.roffset
|
|
}
|
|
assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer))
|
|
var data = buffer.subarray(offset, offset + length)
|
|
if (length <= 0) {
|
|
return 0
|
|
}
|
|
if (currentLength == 0) {
|
|
throw new FS.ErrnoError(ERRNO_CODES.EAGAIN)
|
|
}
|
|
var toRead = Math.min(currentLength, length)
|
|
var totalRead = toRead
|
|
var toRemove = 0
|
|
for (var i = 0; i < pipe.buckets.length; i++) {
|
|
var currBucket = pipe.buckets[i]
|
|
var bucketSize = currBucket.offset - currBucket.roffset
|
|
if (toRead <= bucketSize) {
|
|
var tmpSlice = currBucket.buffer.subarray(
|
|
currBucket.roffset,
|
|
currBucket.offset
|
|
)
|
|
if (toRead < bucketSize) {
|
|
tmpSlice = tmpSlice.subarray(0, toRead)
|
|
currBucket.roffset += toRead
|
|
} else {
|
|
toRemove++
|
|
}
|
|
data.set(tmpSlice)
|
|
break
|
|
} else {
|
|
var tmpSlice = currBucket.buffer.subarray(
|
|
currBucket.roffset,
|
|
currBucket.offset
|
|
)
|
|
data.set(tmpSlice)
|
|
data = data.subarray(tmpSlice.byteLength)
|
|
toRead -= tmpSlice.byteLength
|
|
toRemove++
|
|
}
|
|
}
|
|
if (toRemove && toRemove == pipe.buckets.length) {
|
|
toRemove--
|
|
pipe.buckets[toRemove].offset = 0
|
|
pipe.buckets[toRemove].roffset = 0
|
|
}
|
|
pipe.buckets.splice(0, toRemove)
|
|
return totalRead
|
|
},
|
|
write: function(stream, buffer, offset, length, position) {
|
|
var pipe = stream.node.pipe
|
|
assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer))
|
|
var data = buffer.subarray(offset, offset + length)
|
|
var dataLen = data.byteLength
|
|
if (dataLen <= 0) {
|
|
return 0
|
|
}
|
|
var currBucket = null
|
|
if (pipe.buckets.length == 0) {
|
|
currBucket = {
|
|
buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
|
|
offset: 0,
|
|
roffset: 0,
|
|
}
|
|
pipe.buckets.push(currBucket)
|
|
} else {
|
|
currBucket = pipe.buckets[pipe.buckets.length - 1]
|
|
}
|
|
assert(currBucket.offset <= PIPEFS.BUCKET_BUFFER_SIZE)
|
|
var freeBytesInCurrBuffer = PIPEFS.BUCKET_BUFFER_SIZE - currBucket.offset
|
|
if (freeBytesInCurrBuffer >= dataLen) {
|
|
currBucket.buffer.set(data, currBucket.offset)
|
|
currBucket.offset += dataLen
|
|
return dataLen
|
|
} else if (freeBytesInCurrBuffer > 0) {
|
|
currBucket.buffer.set(
|
|
data.subarray(0, freeBytesInCurrBuffer),
|
|
currBucket.offset
|
|
)
|
|
currBucket.offset += freeBytesInCurrBuffer
|
|
data = data.subarray(freeBytesInCurrBuffer, data.byteLength)
|
|
}
|
|
var numBuckets = (data.byteLength / PIPEFS.BUCKET_BUFFER_SIZE) | 0
|
|
var remElements = data.byteLength % PIPEFS.BUCKET_BUFFER_SIZE
|
|
for (var i = 0; i < numBuckets; i++) {
|
|
var newBucket = {
|
|
buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
|
|
offset: PIPEFS.BUCKET_BUFFER_SIZE,
|
|
roffset: 0,
|
|
}
|
|
pipe.buckets.push(newBucket)
|
|
newBucket.buffer.set(data.subarray(0, PIPEFS.BUCKET_BUFFER_SIZE))
|
|
data = data.subarray(PIPEFS.BUCKET_BUFFER_SIZE, data.byteLength)
|
|
}
|
|
if (remElements > 0) {
|
|
var newBucket = {
|
|
buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),
|
|
offset: data.byteLength,
|
|
roffset: 0,
|
|
}
|
|
pipe.buckets.push(newBucket)
|
|
newBucket.buffer.set(data)
|
|
}
|
|
return dataLen
|
|
},
|
|
close: function(stream) {
|
|
var pipe = stream.node.pipe
|
|
pipe.buckets = null
|
|
},
|
|
},
|
|
nextname: function() {
|
|
if (!PIPEFS.nextname.current) {
|
|
PIPEFS.nextname.current = 0
|
|
}
|
|
return 'pipe[' + PIPEFS.nextname.current++ + ']'
|
|
},
|
|
}
|
|
function ___syscall42(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var fdPtr = SYSCALLS.get()
|
|
if (fdPtr == 0) {
|
|
throw new FS.ErrnoError(14)
|
|
}
|
|
var res = PIPEFS.createPipe()
|
|
HEAP32[fdPtr >> 2] = res.readable_fd
|
|
HEAP32[(fdPtr + 4) >> 2] = res.writable_fd
|
|
return 0
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall5(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var pathname = SYSCALLS.getStr(),
|
|
flags = SYSCALLS.get(),
|
|
mode = SYSCALLS.get()
|
|
var stream = FS.open(pathname, flags, mode)
|
|
return stream.fd
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function ___syscall6(which, varargs) {
|
|
SYSCALLS.varargs = varargs
|
|
try {
|
|
var stream = SYSCALLS.getStreamFromFD()
|
|
FS.close(stream)
|
|
return 0
|
|
} catch (e) {
|
|
if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e)
|
|
return -e.errno
|
|
}
|
|
}
|
|
function _abort() {
|
|
Module['abort']()
|
|
}
|
|
function _emscripten_get_heap_size() {
|
|
return HEAP8.length
|
|
}
|
|
function abortOnCannotGrowMemory(requestedSize) {
|
|
abort('OOM')
|
|
}
|
|
function emscripten_realloc_buffer(size) {
|
|
var PAGE_MULTIPLE = 65536
|
|
size = alignUp(size, PAGE_MULTIPLE)
|
|
var oldSize = buffer.byteLength
|
|
try {
|
|
var result = wasmMemory.grow((size - oldSize) / 65536)
|
|
if (result !== (-1 | 0)) {
|
|
buffer = wasmMemory.buffer
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
} catch (e) {
|
|
return false
|
|
}
|
|
}
|
|
function _emscripten_resize_heap(requestedSize) {
|
|
var oldSize = _emscripten_get_heap_size()
|
|
var PAGE_MULTIPLE = 65536
|
|
var LIMIT = 2147483648 - PAGE_MULTIPLE
|
|
if (requestedSize > LIMIT) {
|
|
return false
|
|
}
|
|
var MIN_TOTAL_MEMORY = 16777216
|
|
var newSize = Math.max(oldSize, MIN_TOTAL_MEMORY)
|
|
while (newSize < requestedSize) {
|
|
if (newSize <= 536870912) {
|
|
newSize = alignUp(2 * newSize, PAGE_MULTIPLE)
|
|
} else {
|
|
newSize = Math.min(
|
|
alignUp((3 * newSize + 2147483648) / 4, PAGE_MULTIPLE),
|
|
LIMIT
|
|
)
|
|
}
|
|
}
|
|
if (!emscripten_realloc_buffer(newSize)) {
|
|
return false
|
|
}
|
|
updateGlobalBufferViews()
|
|
return true
|
|
}
|
|
function _exit(status) {
|
|
exit(status)
|
|
}
|
|
var ___tm_current = 277408
|
|
var ___tm_timezone = (stringToUTF8('GMT', 277456, 4), 277456)
|
|
function _tzset() {
|
|
if (_tzset.called) return
|
|
_tzset.called = true
|
|
HEAP32[__get_timezone() >> 2] = new Date().getTimezoneOffset() * 60
|
|
var winter = new Date(2e3, 0, 1)
|
|
var summer = new Date(2e3, 6, 1)
|
|
HEAP32[__get_daylight() >> 2] = Number(
|
|
winter.getTimezoneOffset() != summer.getTimezoneOffset()
|
|
)
|
|
function extractZone(date) {
|
|
var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/)
|
|
return match ? match[1] : 'GMT'
|
|
}
|
|
var winterName = extractZone(winter)
|
|
var summerName = extractZone(summer)
|
|
var winterNamePtr = allocate(intArrayFromString(winterName), 'i8', ALLOC_NORMAL)
|
|
var summerNamePtr = allocate(intArrayFromString(summerName), 'i8', ALLOC_NORMAL)
|
|
if (summer.getTimezoneOffset() < winter.getTimezoneOffset()) {
|
|
HEAP32[__get_tzname() >> 2] = winterNamePtr
|
|
HEAP32[(__get_tzname() + 4) >> 2] = summerNamePtr
|
|
} else {
|
|
HEAP32[__get_tzname() >> 2] = summerNamePtr
|
|
HEAP32[(__get_tzname() + 4) >> 2] = winterNamePtr
|
|
}
|
|
}
|
|
function _localtime_r(time, tmPtr) {
|
|
_tzset()
|
|
var date = new Date(HEAP32[time >> 2] * 1e3)
|
|
HEAP32[tmPtr >> 2] = date.getSeconds()
|
|
HEAP32[(tmPtr + 4) >> 2] = date.getMinutes()
|
|
HEAP32[(tmPtr + 8) >> 2] = date.getHours()
|
|
HEAP32[(tmPtr + 12) >> 2] = date.getDate()
|
|
HEAP32[(tmPtr + 16) >> 2] = date.getMonth()
|
|
HEAP32[(tmPtr + 20) >> 2] = date.getFullYear() - 1900
|
|
HEAP32[(tmPtr + 24) >> 2] = date.getDay()
|
|
var start = new Date(date.getFullYear(), 0, 1)
|
|
var yday = ((date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24)) | 0
|
|
HEAP32[(tmPtr + 28) >> 2] = yday
|
|
HEAP32[(tmPtr + 36) >> 2] = -(date.getTimezoneOffset() * 60)
|
|
var summerOffset = new Date(2e3, 6, 1).getTimezoneOffset()
|
|
var winterOffset = start.getTimezoneOffset()
|
|
var dst =
|
|
(summerOffset != winterOffset &&
|
|
date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0
|
|
HEAP32[(tmPtr + 32) >> 2] = dst
|
|
var zonePtr = HEAP32[(__get_tzname() + (dst ? 4 : 0)) >> 2]
|
|
HEAP32[(tmPtr + 40) >> 2] = zonePtr
|
|
return tmPtr
|
|
}
|
|
function _localtime(time) {
|
|
return _localtime_r(time, ___tm_current)
|
|
}
|
|
function _emscripten_memcpy_big(dest, src, num) {
|
|
HEAPU8.set(HEAPU8.subarray(src, src + num), dest)
|
|
}
|
|
function _mktime(tmPtr) {
|
|
_tzset()
|
|
var date = new Date(
|
|
HEAP32[(tmPtr + 20) >> 2] + 1900,
|
|
HEAP32[(tmPtr + 16) >> 2],
|
|
HEAP32[(tmPtr + 12) >> 2],
|
|
HEAP32[(tmPtr + 8) >> 2],
|
|
HEAP32[(tmPtr + 4) >> 2],
|
|
HEAP32[tmPtr >> 2],
|
|
0
|
|
)
|
|
var dst = HEAP32[(tmPtr + 32) >> 2]
|
|
var guessedOffset = date.getTimezoneOffset()
|
|
var start = new Date(date.getFullYear(), 0, 1)
|
|
var summerOffset = new Date(2e3, 6, 1).getTimezoneOffset()
|
|
var winterOffset = start.getTimezoneOffset()
|
|
var dstOffset = Math.min(winterOffset, summerOffset)
|
|
if (dst < 0) {
|
|
HEAP32[(tmPtr + 32) >> 2] = Number(
|
|
summerOffset != winterOffset && dstOffset == guessedOffset
|
|
)
|
|
} else if (dst > 0 != (dstOffset == guessedOffset)) {
|
|
var nonDstOffset = Math.max(winterOffset, summerOffset)
|
|
var trueOffset = dst > 0 ? dstOffset : nonDstOffset
|
|
date.setTime(date.getTime() + (trueOffset - guessedOffset) * 6e4)
|
|
}
|
|
HEAP32[(tmPtr + 24) >> 2] = date.getDay()
|
|
var yday = ((date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24)) | 0
|
|
HEAP32[(tmPtr + 28) >> 2] = yday
|
|
return (date.getTime() / 1e3) | 0
|
|
}
|
|
function _posix_spawn_file_actions_addclose() {
|
|
err('missing function: posix_spawn_file_actions_addclose')
|
|
abort(-1)
|
|
}
|
|
function _posix_spawn_file_actions_adddup2() {
|
|
err('missing function: posix_spawn_file_actions_adddup2')
|
|
abort(-1)
|
|
}
|
|
function _posix_spawn_file_actions_destroy() {
|
|
err('missing function: posix_spawn_file_actions_destroy')
|
|
abort(-1)
|
|
}
|
|
function _posix_spawn_file_actions_init() {
|
|
err('missing function: posix_spawn_file_actions_init')
|
|
abort(-1)
|
|
}
|
|
function _fork() {
|
|
___setErrNo(11)
|
|
return -1
|
|
}
|
|
function _posix_spawnp() {
|
|
return _fork.apply(null, arguments)
|
|
}
|
|
function _timegm(tmPtr) {
|
|
_tzset()
|
|
var time = Date.UTC(
|
|
HEAP32[(tmPtr + 20) >> 2] + 1900,
|
|
HEAP32[(tmPtr + 16) >> 2],
|
|
HEAP32[(tmPtr + 12) >> 2],
|
|
HEAP32[(tmPtr + 8) >> 2],
|
|
HEAP32[(tmPtr + 4) >> 2],
|
|
HEAP32[tmPtr >> 2],
|
|
0
|
|
)
|
|
var date = new Date(time)
|
|
HEAP32[(tmPtr + 24) >> 2] = date.getUTCDay()
|
|
var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0)
|
|
var yday = ((date.getTime() - start) / (1e3 * 60 * 60 * 24)) | 0
|
|
HEAP32[(tmPtr + 28) >> 2] = yday
|
|
return (date.getTime() / 1e3) | 0
|
|
}
|
|
function _wait(stat_loc) {
|
|
___setErrNo(10)
|
|
return -1
|
|
}
|
|
function _waitpid() {
|
|
return _wait.apply(null, arguments)
|
|
}
|
|
FS.staticInit()
|
|
if (ENVIRONMENT_IS_NODE) {
|
|
var fs = require('fs')
|
|
var NODEJS_PATH = require('path')
|
|
NODEFS.staticInit()
|
|
}
|
|
function intArrayFromString(stringy, dontAddNull, length) {
|
|
var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1
|
|
var u8array = new Array(len)
|
|
var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length)
|
|
if (dontAddNull) u8array.length = numBytesWritten
|
|
return u8array
|
|
}
|
|
var asmGlobalArg = {}
|
|
var asmLibraryArg = {
|
|
b: abort,
|
|
q: setTempRet0,
|
|
G: ___buildEnvironment,
|
|
l: ___setErrNo,
|
|
s: ___syscall140,
|
|
i: ___syscall146,
|
|
p: ___syscall168,
|
|
o: ___syscall195,
|
|
n: ___syscall196,
|
|
m: ___syscall197,
|
|
c: ___syscall221,
|
|
F: ___syscall3,
|
|
E: ___syscall4,
|
|
D: ___syscall41,
|
|
C: ___syscall42,
|
|
B: ___syscall5,
|
|
h: ___syscall6,
|
|
g: _abort,
|
|
A: _emscripten_get_heap_size,
|
|
z: _emscripten_memcpy_big,
|
|
y: _emscripten_resize_heap,
|
|
f: _exit,
|
|
x: _localtime,
|
|
d: _mktime,
|
|
e: _posix_spawn_file_actions_addclose,
|
|
k: _posix_spawn_file_actions_adddup2,
|
|
j: _posix_spawn_file_actions_destroy,
|
|
w: _posix_spawn_file_actions_init,
|
|
v: _posix_spawnp,
|
|
u: _timegm,
|
|
t: _waitpid,
|
|
r: abortOnCannotGrowMemory,
|
|
a: DYNAMICTOP_PTR,
|
|
}
|
|
var asm = Module['asm'](asmGlobalArg, asmLibraryArg, buffer)
|
|
Module['asm'] = asm
|
|
var ___emscripten_environ_constructor = (Module[
|
|
'___emscripten_environ_constructor'
|
|
] = function() {
|
|
return Module['asm']['H'].apply(null, arguments)
|
|
})
|
|
var ___errno_location = (Module['___errno_location'] = function() {
|
|
return Module['asm']['I'].apply(null, arguments)
|
|
})
|
|
var __get_daylight = (Module['__get_daylight'] = function() {
|
|
return Module['asm']['J'].apply(null, arguments)
|
|
})
|
|
var __get_timezone = (Module['__get_timezone'] = function() {
|
|
return Module['asm']['K'].apply(null, arguments)
|
|
})
|
|
var __get_tzname = (Module['__get_tzname'] = function() {
|
|
return Module['asm']['L'].apply(null, arguments)
|
|
})
|
|
var _archive_close = (Module['_archive_close'] = function() {
|
|
return Module['asm']['M'].apply(null, arguments)
|
|
})
|
|
var _archive_entry_filetype = (Module['_archive_entry_filetype'] = function() {
|
|
return Module['asm']['N'].apply(null, arguments)
|
|
})
|
|
var _archive_entry_is_encrypted = (Module[
|
|
'_archive_entry_is_encrypted'
|
|
] = function() {
|
|
return Module['asm']['O'].apply(null, arguments)
|
|
})
|
|
var _archive_entry_pathname = (Module['_archive_entry_pathname'] = function() {
|
|
return Module['asm']['P'].apply(null, arguments)
|
|
})
|
|
var _archive_entry_pathname_utf8 = (Module[
|
|
'_archive_entry_pathname_utf8'
|
|
] = function() {
|
|
return Module['asm']['Q'].apply(null, arguments)
|
|
})
|
|
var _archive_entry_size = (Module['_archive_entry_size'] = function() {
|
|
return Module['asm']['R'].apply(null, arguments)
|
|
})
|
|
var _archive_error_string = (Module['_archive_error_string'] = function() {
|
|
return Module['asm']['S'].apply(null, arguments)
|
|
})
|
|
var _archive_open = (Module['_archive_open'] = function() {
|
|
return Module['asm']['T'].apply(null, arguments)
|
|
})
|
|
var _archive_read_add_passphrase = (Module[
|
|
'_archive_read_add_passphrase'
|
|
] = function() {
|
|
return Module['asm']['U'].apply(null, arguments)
|
|
})
|
|
var _archive_read_data_skip = (Module['_archive_read_data_skip'] = function() {
|
|
return Module['asm']['V'].apply(null, arguments)
|
|
})
|
|
var _archive_read_has_encrypted_entries = (Module[
|
|
'_archive_read_has_encrypted_entries'
|
|
] = function() {
|
|
return Module['asm']['W'].apply(null, arguments)
|
|
})
|
|
var _free = (Module['_free'] = function() {
|
|
return Module['asm']['X'].apply(null, arguments)
|
|
})
|
|
var _get_filedata = (Module['_get_filedata'] = function() {
|
|
return Module['asm']['Y'].apply(null, arguments)
|
|
})
|
|
var _get_next_entry = (Module['_get_next_entry'] = function() {
|
|
return Module['asm']['Z'].apply(null, arguments)
|
|
})
|
|
var _get_version = (Module['_get_version'] = function() {
|
|
return Module['asm']['_'].apply(null, arguments)
|
|
})
|
|
var _malloc = (Module['_malloc'] = function() {
|
|
return Module['asm']['$'].apply(null, arguments)
|
|
})
|
|
var stackAlloc = (Module['stackAlloc'] = function() {
|
|
return Module['asm']['ca'].apply(null, arguments)
|
|
})
|
|
var stackRestore = (Module['stackRestore'] = function() {
|
|
return Module['asm']['da'].apply(null, arguments)
|
|
})
|
|
var stackSave = (Module['stackSave'] = function() {
|
|
return Module['asm']['ea'].apply(null, arguments)
|
|
})
|
|
var dynCall_v = (Module['dynCall_v'] = function() {
|
|
return Module['asm']['aa'].apply(null, arguments)
|
|
})
|
|
var dynCall_vi = (Module['dynCall_vi'] = function() {
|
|
return Module['asm']['ba'].apply(null, arguments)
|
|
})
|
|
Module['asm'] = asm
|
|
Module['intArrayFromString'] = intArrayFromString
|
|
Module['cwrap'] = cwrap
|
|
Module['allocate'] = allocate
|
|
Module['then'] = function(func) {
|
|
if (Module['calledRun']) {
|
|
func(Module)
|
|
} else {
|
|
var old = Module['onRuntimeInitialized']
|
|
Module['onRuntimeInitialized'] = function() {
|
|
if (old) old()
|
|
func(Module)
|
|
}
|
|
}
|
|
return Module
|
|
}
|
|
function ExitStatus(status) {
|
|
this.name = 'ExitStatus'
|
|
this.message = 'Program terminated with exit(' + status + ')'
|
|
this.status = status
|
|
}
|
|
ExitStatus.prototype = new Error()
|
|
ExitStatus.prototype.constructor = ExitStatus
|
|
dependenciesFulfilled = function runCaller() {
|
|
if (!Module['calledRun']) run()
|
|
if (!Module['calledRun']) dependenciesFulfilled = runCaller
|
|
}
|
|
function run(args) {
|
|
args = args || Module['arguments']
|
|
if (runDependencies > 0) {
|
|
return
|
|
}
|
|
preRun()
|
|
if (runDependencies > 0) return
|
|
if (Module['calledRun']) return
|
|
function doRun() {
|
|
if (Module['calledRun']) return
|
|
Module['calledRun'] = true
|
|
if (ABORT) return
|
|
ensureInitRuntime()
|
|
preMain()
|
|
if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']()
|
|
postRun()
|
|
}
|
|
if (Module['setStatus']) {
|
|
Module['setStatus']('Running...')
|
|
setTimeout(function() {
|
|
setTimeout(function() {
|
|
Module['setStatus']('')
|
|
}, 1)
|
|
doRun()
|
|
}, 1)
|
|
} else {
|
|
doRun()
|
|
}
|
|
}
|
|
Module['run'] = run
|
|
function exit(status, implicit) {
|
|
if (implicit && Module['noExitRuntime'] && status === 0) {
|
|
return
|
|
}
|
|
if (Module['noExitRuntime']) {
|
|
} else {
|
|
ABORT = true
|
|
EXITSTATUS = status
|
|
exitRuntime()
|
|
if (Module['onExit']) Module['onExit'](status)
|
|
}
|
|
Module['quit'](status, new ExitStatus(status))
|
|
}
|
|
function abort(what) {
|
|
if (Module['onAbort']) {
|
|
Module['onAbort'](what)
|
|
}
|
|
if (what !== undefined) {
|
|
out(what)
|
|
err(what)
|
|
what = JSON.stringify(what)
|
|
} else {
|
|
what = ''
|
|
}
|
|
ABORT = true
|
|
EXITSTATUS = 1
|
|
throw 'abort(' + what + '). Build with -s ASSERTIONS=1 for more info.'
|
|
}
|
|
Module['abort'] = abort
|
|
if (Module['preInit']) {
|
|
if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]
|
|
while (Module['preInit'].length > 0) {
|
|
Module['preInit'].pop()()
|
|
}
|
|
}
|
|
Module['noExitRuntime'] = true
|
|
run()
|
|
|
|
return libarchive
|
|
}
|
|
})()
|
|
export default libarchive
|