-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Filesystem API
File I/O in emscripten is provided by the FS library. This same library is used internally for all of emscripten's libc and libcxx file I/O.
Emscripten deals predominantly with synchronous file I/O, so the majority of the FS member functions offer a synchronous interface, with errors being reported by raising exceptions of type FS.ErrnorError
.
The file data in emscription is partioned by mounted filesystems, of which several are provided to work with. By default, an instance of MEMFS is mounted to /
and instances of NODEFS and IDBFS can be mounted to other directories if your application needs to persist data.
Applications being compiled with emscripten expect synchronous I/O, therefor, emscripten itself must provide filesystems with completely synchronous interfaces. However, due to JavaScript's event-driven nature, most persistent storage options offer only asynchronous interfaces.
Because of this, emscripten offers multiple filesystems that can be mounted with FS.mount to help deal with persistence depending on the execution context.
This is the default filesystem mounted at /
when the runtime is initialized. All files exist strictly in-memory, and any data written to it is lost when the page is reloaded.
NODEFS lets a program in node directly access files on the local filesystem, as if the problem were running normally. See this test for an example.
- root
string
Path to persist the data to on the local filesystem.
This filesystem is only for use when running inside of node. It uses node's synchronous fs API to immediately persist any data written to emscripten's filesystem to your local disk.
This filesystem is only for use when running inside of the browser. Due to the browser not offering any synchronous APIs for persistent storage, by default all writes exist only temporarily in-memory. However, the IDBFS filesystem implements the FS.syncfs interface, which once called will persist any operations to a backing IndexedDB instance.
Emscripten supports registering arbitrary device drivers composed of a device id and a set of unique stream callbacks. Once a driver has been registered with FS.registerDevice, a device node (acting as an interface between the device and the filesystem) can be created to reference it with FS.mkdev. Any stream referencing the new node will inherit the stream callbacks registered for the device, making all of the high-level FS operations transparently interact with the device.
Converts a major and minor number into a single unique integer.
Registers a device driver for the specified id / callbacks.
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). Note that all the configuration should be done before the main run()
method is executed, typically by implementing Module.preRun
, see Interacting-with-code.
- 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
.
Mounts the FS object specified by type
to the directory specified by mountpoint
. The opts
objects is specific to each filesystem type.
- populate
bool
Responsible for iterating and synchronizing all mounted filesystems in an asynchronous fashion.
The populate
flag is used to control the intended direction of the underlying synchronization between emscripten's internal data, and the filesystem's persistent data. populate=true
is used for initializing emscripten's filesystem data with the data from the filesystem's persistent source, and populate=false
is used to save emscripten's filesystem data to the filesystem's persistent source.
function myAppStartup(callback) {
FS.mkdir('/data');
FS.mount(IDBFS, {}, '/data');
FS.syncfs(true, function (err) {
// handle callback
});
}
function myAppShutdown(callback) {
FS.syncfs(function (err) {
// handle callback
});
}
An actual test implementing this functionality can be seen at /~https://github.com/kripken/emscripten/blob/master/tests/fs/test_idbfs_sync.c.
NOTE: Currently, only the IDBFS filesystem implements the interfaces needed by this. All other filesystems are completely synchronous and don't require synchronization.
- path
string
- mode
int
default = 0777
Creates a new directory node in the filesystem.
FS.mkdir('/data');
- path
string
- mode
int
default = 0777 - dev
int
Creates a new device node in the filesystem referencing the device driver registered for dev
.
var id = FS.makedev(64, 0);
FS.registerDevice(id, {});
FS.mkdev('/dummy', id);
- oldpath
string
- newpath
string
Creates a symlink node at newpath
linking to oldpath
.
FS.writeFile('file', 'foobar');
FS.symlink('file', 'link');
- oldpath
string
- newpath
string
Renames the node at oldpath
to newpath
.
FS.writeFile('file', 'foobar');
FS.rename('file', 'newfile');
- path
string
Removes an empty directory located at path
.
FS.mkdir('data');
FS.rmdir('data');
- path
string
Unlink the node at path
.
FS.writeFile('/foobar.txt', 'Hello, world');
FS.unlink('/foobar.txt');
- path
string
Returns the string value stored in the symbolic link at path
.
#include <stdio.h>
#include <emscripten.h>
int main() {
EM_ASM(
FS.writeFile('file', 'foobar');
FS.symlink('file', 'link');
console.log(FS.readlink('link'));
);
return 0;
}
outputs
file
- path
string
Returns a JavaScript object of stats for the node at path
.
#include <stdio.h>
#include <emscripten.h>
int main() {
EM_ASM(
FS.writeFile('file', 'foobar');
console.log(FS.stat('file'));
);
return 0;
}
outputs
{
dev: 1,
ino: 13,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
size: 6,
atime: Mon Nov 25 2013 00:37:27 GMT-0800 (PST),
mtime: Mon Nov 25 2013 00:37:27 GMT-0800 (PST),
ctime: Mon Nov 25 2013 00:37:27 GMT-0800 (PST),
blksize: 4096,
blocks: 1
}
- path
string
Identical to FS.stat
, However, if path
is a symbolic link then the returned stats will be for the link itself, not the file that it links to.
- path
string
- mode
int
Change the mode flags for path
to mode
.
FS.writeFile('forbidden', 'can\'t touch this');
FS.chmod('forbidden', 0000);
- path
string
- mode
int
Identical to FS.chmod
. However, if path
is a symbolic link then the mode will be set on the link itself, not the file that it links to.
- fd
int
- mode
int
Identical to FS.chmod
. However, a raw file decriptor is supplied as fd
.
- path
string
- uid
int
- gid
int
Set uid
and gid
properties of the node at path
.
- path
string
- uid
int
- gid
int
Identical to FS.chown
. However, if path is a symbolic link then the properties will be set on the link itself, not the file that it links to.
- fd
int
- uid
int
- gid
int
Identical to FS.chown
. However, a raw file decriptor is supplied as fd
.
- path
string
- len
int
Truncates a file to the specified length.
#include <stdio.h>
#include <emscripten.h>
int main() {
EM_ASM(
FS.writeFile('file', 'foobar');
FS.truncate('file', 3);
console.log(FS.readFile('file', { encoding: 'utf8' }));
);
return 0;
}
outputs
foo
- fd
int
- len
int
Truncates the file identified by the file descriptor to the specified length.
- path
string
- atime
int
- mtime
int
Change the timestamps of the file located at path
.
- path
string
- flags
sring
- mode
int
default = 0666
Opens a file with the specified flags. flags
can be:
- 'r' - Open file for reading.
- 'r+' - Open file for reading and writing.
- 'w' - Open file for writing.
- 'wx' - Like 'w' but fails if path exists.
- 'w+' - Open file for reading and writing. The file is created if it does not exist or truncated if it exists.
- 'wx+' - Like 'w+' but fails if path exists.
- 'a' - Open file for appending. The file is created if it does not exist.
- 'ax' - Like 'a' but fails if path exists.
- 'a+' - Open file for reading and appending. The file is created if it does not exist.
- 'ax+' - Like 'a+' but fails if path exists.
mode
specifies the permissions for the file, and are only used if the file is created.
Returns a stream object.
- stream
object
Closes the file stream.
- stream
object
- offset
int
- whence
int
Repositions the offset of the stream offset
bytes, relative to the whence
parameter.
When can be SEEK_SET (0), SEEK_CUR(1) or SEEK_END(2);
- stream
object
- buffer
ArrayBufferView
- offset
int
- length
int
- position
int
Read length
bytes from the stream, storing them into buffer
starting at offset
. By default, reading starts from the stream's current offset, however, a specific offset can be specified with the position
argument.
var stream = FS.open('abinaryfile', 'r');
var buf = new Uint8Array(4);
FS.read(stream, buf, 0, 4, 0);
FS.close(stream);
- stream
object
- buffer
ArrayBufferView
- offset
int
- length
int
- position
int
Write length
bytes from buffer
, starting at offset
. By default, writing starts from the stream's current offset, however, a specific offset can be specified with the position
argument.
var data = new Uint8Array(32);
var stream = FS.open('dummy', 'w+');
FS.write(stream, data, 0, data.length, 0);
FS.close(stream);
- path
string
- opts
object
- flags
string
default = 'r' - encoding
string
default = 'binary'
- flags
Slurps the entire file at path
and returns it either as a string, or a new Uint8Array buffer (encoding
= 'binary').
- path
string
- data
ArrayBufferView
- opts
object
- flags
string
default = 'w' - encoding
string
default = 'utf8'
- flags
Writes the entire contents of data
to the file at path
. data
is treated either as a string (encoding
= 'utf8'), or as an ArrayBufferView (encoding
= 'binary').
FS.writeFile('file', 'foobar');
var contents = FS.readFile('file', { encoding: 'utf8' });
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 for Javascript in regular HTML pages (but it works within WebWorkers).
* `(string|object) parent`: The parent folder, either as a path (e.g. `'/usr/lib'`) or an object previously returned from a `FS.createFolder()` or `FS.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.
FS.createLazyFile('/', 'foo', 'other/page.htm', true, false);
FS.createLazyFile('/', 'bar', '/get_file.php?name=baz', true, true);
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.
Emscripten's filesystem supports regular files, directories, symlinks, character devices, block devices and sockets. In a similar manner to most Unix systems, all of these file types are able to be operated on with the higher-level FS operations such as FS.read and FS.write.
Returns true if the mode bitmask represents a file.
Returns true if the mode bitmask represents a directory.
Returns true if the mode bitmask represents a symlink.
Returns true if the mode bitmask represents a character device.
Returns true if the mode bitmask represents a block device.
Returns true if the mode bitmask represents a socket.
Return the current working directory.
- path
string
- opts
object
- parent
bool
default = false - follow
bool
default = false
Lookups up the incoming path and returns an object of the format:
{
path: resolved_path,
node: resolved_node
}
The parent
option says to stop resolving the path once the next to the last component is reached. For example, for the path /foo/bar
with { parent: true }
, would return receive back an object representing /foo
.
The follow
option says whether to follow the last component in the case that is is a symlink. To illustrate, let's say there exists a symlink /foo/symlink
that links to /foo/notes.txt
. If /foo/symlink
is looked up with { follow: false }
an object representing the symlink file itself would be returned. However if { follow: true }
is passed, an object representing /foo/notes.txt
would be returned.
Takes in a node object and return the absolute path to it, accounting for mounts.
README.md ``