| /** |
| * @license |
| * Copyright 2022 The Emscripten Authors |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| mergeInto(LibraryManager.library, { |
| $wasmFSPreloadedFiles: [], |
| $wasmFSPreloadedDirs: [], |
| #if USE_CLOSURE_COMPILER |
| // Declare variable for Closure, FS.createPreloadedFile() below calls Browser.handledByPreloadPlugin() |
| $FS__postset: '/**@suppress {duplicate, undefinedVars}*/var Browser;', |
| #endif |
| $FS__deps: [ |
| '$wasmFSPreloadedFiles', |
| '$wasmFSPreloadedDirs', |
| '$asyncLoad', |
| '$PATH', |
| '$allocateUTF8', |
| '$allocateUTF8OnStack', |
| '$withStackSave', |
| '$readI53FromI64', |
| ], |
| $FS : { |
| // TODO: Clean up the following functions - currently copied from library_fs.js directly. |
| createPreloadedFile: (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => { |
| // TODO: use WasmFS code to resolve and join the path here? |
| var fullname = name ? parent + '/' + name : parent; |
| var dep = getUniqueRunDependency('cp ' + fullname); // might have several active requests for the same 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); |
| } |
| #if !MINIMAL_RUNTIME |
| if (Browser.handledByPreloadPlugin(byteArray, fullname, finish, () => { |
| if (onerror) onerror(); |
| removeRunDependency(dep); |
| })) { |
| return; |
| } |
| #endif |
| finish(byteArray); |
| } |
| addRunDependency(dep); |
| if (typeof url == 'string') { |
| asyncLoad(url, (byteArray) => { |
| processData(byteArray); |
| }, onerror); |
| } else { |
| processData(url); |
| } |
| }, |
| getMode: (canRead, canWrite) => { |
| var mode = 0; |
| if (canRead) mode |= {{{ cDefine('S_IRUGO') }}} | {{{ cDefine('S_IXUGO') }}}; |
| if (canWrite) mode |= {{{ cDefine('S_IWUGO') }}}; |
| return mode; |
| }, |
| createDataFile: (parent, name, data, canRead, canWrite, canOwn) => { |
| // Data files must be cached until the file system itself has been initialized. |
| var mode = FS.getMode(canRead, canWrite); |
| var pathName = name ? parent + '/' + name : parent; |
| wasmFSPreloadedFiles.push({pathName: pathName, fileData: data, mode: mode}); |
| }, |
| createPath: (parent, path, canRead, canWrite) => { |
| // Cache file path directory names. |
| var parts = path.split('/').reverse(); |
| while (parts.length) { |
| var part = parts.pop(); |
| if (!part) continue; |
| var current = PATH.join2(parent, part); |
| wasmFSPreloadedDirs.push({parentPath: parent, childName: part}); |
| parent = current; |
| } |
| return current; |
| }, |
| readFile: (path, opts = {}) => { |
| opts.encoding = opts.encoding || 'binary'; |
| if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { |
| throw new Error('Invalid encoding type "' + opts.encoding + '"'); |
| } |
| |
| var pathName = allocateUTF8(path); |
| |
| // Copy the file into a JS buffer on the heap. |
| var buf = __wasmfs_read_file(pathName); |
| // The signed integer length resides in the first 8 bytes of the buffer. |
| var length = {{{ makeGetValue('buf', '0', 'i53') }}}; |
| |
| // Default return type is binary. |
| // The buffer contents exist 8 bytes after the returned pointer. |
| var ret = new Uint8Array(HEAPU8.subarray(buf + 8, buf + 8 + length)); |
| if (opts.encoding === 'utf8') { |
| ret = UTF8ArrayToString(ret, 0); |
| } |
| |
| _free(pathName); |
| _free(buf); |
| return ret; |
| }, |
| cwd: () => { |
| // TODO: Remove dependency on FS.cwd(). |
| // User code should not be using FS.cwd(). |
| // For file preloading, cwd should be '/' to begin with. |
| return '/'; |
| }, |
| |
| #if FORCE_FILESYSTEM |
| // Full JS API support |
| mkdir: (path, mode) => { |
| return withStackSave(() => { |
| mode = mode !== undefined ? mode : 511 /* 0777 */; |
| var buffer = allocateUTF8OnStack(path); |
| return __wasmfs_mkdir({{{ to64('buffer') }}}, mode); |
| }); |
| }, |
| // TODO: mkdirTree |
| // TDOO: rmdir |
| // TODO: open |
| // TODO: create |
| // TODO: close |
| unlink: (path) => { |
| return withStackSave(() => { |
| var buffer = allocateUTF8OnStack(path); |
| return __wasmfs_unlink(buffer); |
| }); |
| }, |
| chdir: (path) => { |
| return withStackSave(() => { |
| var buffer = allocateUTF8OnStack(path); |
| return __wasmfs_chdir(buffer); |
| }); |
| }, |
| // TODO: read |
| // TODO: write |
| // TODO: allocate |
| // TODO: mmap |
| // TODO: msync |
| // TODO: munmap |
| writeFile: (path, data) => { |
| return withStackSave(() => { |
| var pathBuffer = allocateUTF8OnStack(path); |
| if (typeof data == 'string') { |
| var buf = new Uint8Array(lengthBytesUTF8(data) + 1); |
| var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length); |
| data = buf.slice(0, actualNumBytes); |
| } |
| var dataBuffer = _malloc(data.length); |
| #if ASSERTIONS |
| assert(dataBuffer); |
| #endif |
| for (var i = 0; i < data.length; i++) { |
| {{{ makeSetValue('dataBuffer', 'i', 'data[i]', 'i8') }}}; |
| } |
| var ret = __wasmfs_write_file(pathBuffer, dataBuffer, data.length); |
| _free(dataBuffer); |
| return ret; |
| }); |
| }, |
| symlink: (target, linkpath) => { |
| return withStackSave(() => { |
| var targetBuffer = allocateUTF8OnStack(target); |
| var linkpathBuffer = allocateUTF8OnStack(linkpath); |
| return __wasmfs_symlink(targetBuffer, linkpathBuffer); |
| }); |
| }, |
| // TODO: readlink |
| // TODO: stat |
| // TODO: lstat |
| chmod: (path, mode) => { |
| return withStackSave(() => { |
| var buffer = allocateUTF8OnStack(path); |
| return __wasmfs_chmod(buffer, mode); |
| }); |
| }, |
| // TODO: lchmod |
| // TODO: fchmod |
| // TDOO: chown |
| // TODO: lchown |
| // TODO: fchown |
| // TODO: truncate |
| // TODO: ftruncate |
| // TODO: utime |
| findObject: (path) => { |
| var result = __wasmfs_identify(path); |
| if (result == {{{ cDefine('ENOENT') }}}) { |
| return null; |
| } |
| return { |
| isFolder: result == {{{ cDefine('EISDIR') }}}, |
| isDevice: false, // TODO: wasmfs support for devices |
| }; |
| }, |
| readdir: (path) => { |
| return withStackSave(() => { |
| var pathBuffer = allocateUTF8OnStack(path); |
| var entries = []; |
| var state = __wasmfs_readdir_start(pathBuffer); |
| if (!state) { |
| // TODO: The old FS threw an ErrnoError here. |
| throw new Error("No such directory"); |
| } |
| var entry; |
| while (entry = __wasmfs_readdir_get(state)) { |
| entries.push(UTF8ToString(entry)); |
| } |
| __wasmfs_readdir_finish(state); |
| return entries; |
| }); |
| } |
| // TODO: mount |
| // TODO: unmount |
| // TODO: lookup |
| // TODO: mknod |
| // TODO: mkdev |
| // TODO: rename |
| // TODO: syncfs |
| // TODO: llseek |
| // TODO: ioctl |
| |
| #endif |
| }, |
| _wasmfs_get_num_preloaded_files__deps: ['$wasmFSPreloadedFiles'], |
| _wasmfs_get_num_preloaded_files: function() { |
| return wasmFSPreloadedFiles.length; |
| }, |
| _wasmfs_get_num_preloaded_dirs__deps: ['$wasmFSPreloadedDirs'], |
| _wasmfs_get_num_preloaded_dirs: function() { |
| return wasmFSPreloadedDirs.length; |
| }, |
| _wasmfs_get_preloaded_file_mode: function(index) { |
| return wasmFSPreloadedFiles[index].mode; |
| }, |
| _wasmfs_get_preloaded_parent_path__sig: 'vip', |
| _wasmfs_get_preloaded_parent_path: function(index, parentPathBuffer) { |
| var s = wasmFSPreloadedDirs[index].parentPath; |
| var len = lengthBytesUTF8(s) + 1; |
| stringToUTF8(s, parentPathBuffer, len); |
| }, |
| _wasmfs_get_preloaded_child_path__sig: 'vip', |
| _wasmfs_get_preloaded_child_path: function(index, childNameBuffer) { |
| var s = wasmFSPreloadedDirs[index].childName; |
| var len = lengthBytesUTF8(s) + 1; |
| stringToUTF8(s, childNameBuffer, len); |
| }, |
| _wasmfs_get_preloaded_path_name__sig: 'vip', |
| _wasmfs_get_preloaded_path_name: function(index, fileNameBuffer) { |
| var s = wasmFSPreloadedFiles[index].pathName; |
| var len = lengthBytesUTF8(s) + 1; |
| stringToUTF8(s, fileNameBuffer, len); |
| }, |
| _wasmfs_get_preloaded_file_size__sig: 'pi', |
| _wasmfs_get_preloaded_file_size: function(index) { |
| return wasmFSPreloadedFiles[index].fileData.length; |
| }, |
| _wasmfs_copy_preloaded_file_data__sig: 'vip', |
| _wasmfs_copy_preloaded_file_data: function(index, buffer) { |
| HEAPU8.set(wasmFSPreloadedFiles[index].fileData, buffer); |
| } |
| }); |
| |
| DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.push('$FS'); |