-
Notifications
You must be signed in to change notification settings - Fork 3
Filesystem Guide
Emscripten allows you to set up a virtual filesystem that points to preloaded data, as well as virtual devices that can read and write data. Note that all the configuration should be done before the main run()
method is executed, typically by implementing Module.preRun
, see Interacting-with-code.
For examples of using the filesystem API, see the automatic tests in tests/runner.py
. Search for FS.
for find relevant tests, for example test_files. For specific examples of how to embed files that can be read from compiled C/C++, see for example the OpenJPEG test.
Emscripten standard I/O works by going though the virtual /dev/stdin
, /dev/stdout
and /dev/stderr
devices. You can set them up using your own I/O functions by calling FS.init(input_callback, output_callback, error_callback)
(all arguments optional).
- The input callback will be called with no parameters whenever the program attempts to read from
stdin
. It should return an ASCII character code when data is available, ornull
when it isn't. - The output callback will be called with an ASCII character code whenever the program writes to
stdout
. It may also be called withnull
to flush the output. - The error callback is similar to the output one, except it is called when data is written to
stderr
.
If any of the callbacks throws an exception, it will be caught and handled as if the device malfunctioned.
By default:
-
stdin
will read from the terminal in command line engines and usewindow.prompt()
in browsers (in both cases, with line buffering). -
stdout
will use aprint
function if one such is defined, printing to the terminal in command line engines and to the browser console in browsers that have a console (again, line-buffered). -
stderr
will use the same output function asstdout
.
The FS
object provides several methods to create files, folders, devices and symbolic links:
-
FS.createFolder(parent, name, canRead, canWrite)
: Creates a single empty folder and returns a reference to it.-
(string|object) parent
: The parent folder, either as a path (e.g.'/usr/lib'
) or an object previously returned from aFS.createFolder()
orFS.createPath()
call. -
string name
: The name of the new folder. -
bool canRead
: Whether this folder should have read permissions set from the program's point of view. -
bool canWrite
: Whether this folder should have write permissions set from the program's point of view.
Example:
var home = FS.createFolder('/', 'home', true, false); FS.createFolder(home, 'user', true, true); FS.createFolder('/home', 'other-user', false, false);
-
-
FS.createPath(parent, path, canRead, canWrite)
: Recursively creates a path and returns a reference to the innermost folder.-
(string|object) parent
: The parent folder, either as a path (e.g.'/usr/lib'
) or an object previously returned from aFS.createFolder()
orFS.createPath()
call. -
string path
: The path to the new folder. Any folders missing in this path will be created. -
bool canRead
: Whether the created folders should have read permissions set from the program's point of view. -
bool canWrite
: Whether the created folders should have write permissions set from the program's point of view.
Example:
FS.createPath('/', 'home/user1', true, false); FS.createPath('/', 'home/user2/Desktop', true, false);
-
-
FS.createDataFile(parent, name, data, canRead, canWrite)
: Creates a file containing given data and returns a reference to it. A convenient way to set up a file for you is to call emcc with--preload-file
. That will do everything necessary, including calling this function.-
(string|object) parent
: The parent folder, either as a path (e.g.'/usr/lib'
) or an object previously returned from aFS.createFolder()
orFS.createPath()
call. -
string name
: The name of the new file. -
(string|array) data
: The data that the new file will contain, either as a string or an array of bytes (integers in the [-128, 255] range). -
bool canRead
: Whether the file should have read permissions set from the program's point of view. -
bool canWrite
: Whether the file should have write permissions set from the program's point of view.
Example:
FS.createDataFile('/', 'foo', 'abc', true, false); FS.createDataFile('/', 'bar', [1, 2, 3], true, true);
-
-
FS.createLazyFile(parent, name, url, canRead, canWrite)
: Creates a file that will be loaded lazily on first access from a given URL or local filesystem path, and returns a reference to it. WARNING: Firefox and Chrome have recently disabled synchronous binary XHRs, which means this cannot work. Instead, use createDataFile.-
(string|object) parent
: The parent folder, either as a path (e.g.'/usr/lib'
) or an object previously returned from aFS.createFolder()
orFS.createPath()
call. -
string name
: The name of the new file. -
string url
: In the browser, this is the URL whose contents will be returned when this file is accessed. In a command line engine, this will be the local (real) filesystem path from where the contents will be loaded. Note that writes to this file are virtual. -
bool canRead
: Whether the file should have read permissions set from the program's point of view. -
bool canWrite
: Whether the file should have write permissions set from the program's point of view.
Example:
FS.createLazyFile('/', 'foo', 'other/page.htm', true, false); FS.createLazyFile('/', 'bar', '/get_file.php?name=baz', true, true);
-
-
FS.createPreloadedFile(parent, name, url, canRead, canWrite)
: Preloads a file asychronously. You should call this in preRun, and then run() will be delayed until all preloaded files are ready. This is how--preload-file
works in emcc. -
FS.createLink(parent, name, target, canRead, canWrite)
: Creates a symbolic link and returns a reference to it.-
(string|object) parent
: The parent folder, either as a path (e.g.'/usr/lib'
) or an object previously returned from aFS.createFolder()
orFS.createPath()
call. -
string name
: The name of the link. -
string target
: The target of the link, a relative or absolute path. The path does not need to exist at the time the link is created. -
bool canRead
: Whether the link should have read permissions set from the program's point of view. -
bool canWrite
: Whether the link should have write permissions set from the program's point of view.
Example:
FS.createLink('/bin', 'g++', 'gcc' true, true); FS.createLink('/home/jack', 'log', '/var/log/prog.log', true, true); FS.createLink('/home/jack/Desktop', 'test', '../dev/prog/run.sh', true, true);
-
-
FS.createDevice(parent, name, input, output)
: Creates a virtual device and returns a reference to it.-
(string|object) parent
: The parent folder, either as a path (e.g.'/usr/lib'
) or an object previously returned from aFS.createFolder()
orFS.createPath()
call. -
string name
: The name of the file representing the device. -
function input
: The function called when reading from the device. Should return a byte-sized integer if there's data, ornull
if there isn't. Ifoutput
is specified, this can benull
orundefined
. -
function output
: The function called when writing to the device. Will be called with a byte-sizes integer to write data, ornull
to flush it (if flushing makes sense for the device). Ifinput
is specified, this can benull
orundefined
.
Example:
FS.createDevice('/dev', 'random', function() { return Math.floor(Math.random() * 256); }); FS.createDevice('/dev/snd', 'pcm', null, playSound);
-
The whole filesystem can be safely serialized and restored at any time by saving the values of FS.root
and FS.nextInode
, and replacing them with previously saved values, respectively. Keep in mind, however, that devices use functions, which are discarded on a normal JSON.stringify()
call, so you might want to use a custom stringifier.
As mentioned above, Firefox and Chrome recently disabled synchronous typed array XMLHttpRequests, sadly. Asynchronous ones work, but synchronous code that is compiled needs to run synchronously. There are a few possible solutions to work around this:
- Do not do XHRs at all, instead preload the files. The easiest way to do that is to use
--embed-file
in emcc, it will bundle a file with the code, and prepare it in the filesystem API. For a browser environment, use--preload-file
instead. Both are documented inemcc --help
. - If your compiled code can run in a web worker, then it can do synchronous typed array XHRs, browsers allow that.
- Closure compiler will minify the FS API code in
-O2
and above. To write code that uses it, it must be optimized with the FS API code by closure. To do that, use emcc's--pre-js
option, seeemcc --help
. There is also a subset of the FS API that is exported through closure, usable by things likeModule['FS_createFolder']
(note_
instead of.
), search forFS_createFolder
insrc/library.js
to see which. If you use that API you do not need to optimize your code together.