Skip to content

Commit a3635e8

Browse files
committed
init jsbackend
1 parent 9a14efe commit a3635e8

File tree

6 files changed

+143
-35
lines changed

6 files changed

+143
-35
lines changed

src/library_wasmfs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var WasmfsLibrary = {
22
$wasmFS$JSMemoryFiles : [],
33
$wasmFS$preloadedFiles: [],
44
$wasmFS$preloadedDirs: [],
5-
$FS__deps: ['$wasmFS$preloadedFiles', '$wasmFS$preloadedDirs'],
5+
$FS__deps: ['$wasmFS$preloadedFiles', '$wasmFS$preloadedDirs', '$wasmFS$JSMemoryFiles'],
66
$FS : {
77
// TODO: Clean up the following functions - currently copied from library_fs.js directly.
88
createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {

system/include/emscripten/wasmfs.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2021 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#pragma once
9+
10+
#include <stdint.h>
11+
#include <sys/stat.h>
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif
16+
17+
typedef struct Backend* backend_t;
18+
19+
// Creates a JSFile Backend in the new file system.
20+
backend_t createJSFileBackend();
21+
22+
// Creates a new file in the new file system under a specific backend.
23+
uint32_t wasmfs_create(char* pathname, mode_t mode, backend_t backend);
24+
25+
// Creates a new directory in the new file system under a specific backend.
26+
long wasmfs_mkdir(char* path, long mode, backend_t backend);
27+
28+
#ifdef __cplusplus
29+
}
30+
#endif

system/lib/wasmfs/js_file_backend.cpp

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,46 @@
77
// See https://github.com/emscripten-core/emscripten/issues/15041.
88

99
#include "backend.h"
10+
#include "wasmfs.h"
1011

1112
namespace wasmfs {
1213

13-
using jsIndex_t = uint32_t;
14+
using js_index_t = uint32_t;
1415

1516
// This class describes a file that lives in JS Memory
1617
class JSFile : public DataFile {
1718
// This index indicates the location of the JS File in $wasmFS$JSMemoryFiles.
18-
jsIndex_t index;
19+
js_index_t index;
1920

2021
// JSFiles will write from a Wasm Memory buffer into a JS array defined in
2122
// $wasmFS$JSMemoryFiles.
2223
__wasi_errno_t write(const uint8_t* buf, size_t len, off_t offset) override {
2324
EM_ASM(
2425
{
25-
var size = $wasmFS$JSMemoryFiles[$0].byteLength;
26+
var size = wasmFS$JSMemoryFiles[$0].length;
2627
if ($2 >= size) {
2728
// Resize the current arraybuffer.
28-
$wasmFS$JSMemoryFiles[$0] =
29-
new Uint8Array(size).set($wasmFS$JSMemoryFiles[$0]);
29+
var oldContents = wasmFS$JSMemoryFiles[$0];
30+
wasmFS$JSMemoryFiles[$0] = new Uint8Array($2);
31+
wasmFS$JSMemoryFiles[$0].set(oldContents.subarray(0, $2));
3032
}
31-
$wasmFS$JSMemoryFiles[$0].set(HEAPU8.subarray($1, $2), $3);
33+
wasmFS$JSMemoryFiles[$0].set(HEAPU8.subarray($1, $1 + $2), $3);
3234
},
33-
index,
34-
(int)buf,
35-
(int)(buf + len),
36-
(int)offset);
35+
index,
36+
buf,
37+
len,
38+
(size_t)offset);
3739

3840
return __WASI_ERRNO_SUCCESS;
3941
}
4042

4143
// JSFiles will read from JS Memory into a Wasm Memory buffer.
4244
__wasi_errno_t read(uint8_t* buf, size_t len, off_t offset) override {
4345
assert(offset + len - 1 < getSize());
44-
EM_ASM({ HEAPU8.set($wasmFS$JSMemoryFiles[$0].subarray($1, $2), $3); },
46+
EM_ASM({ HEAPU8.set(wasmFS$JSMemoryFiles[$0].subarray($1, $2), $3); },
4547
index,
46-
(int)offset,
47-
(int)offset + len,
48+
(size_t)offset,
49+
(size_t)offset + len,
4850
buf);
4951

5052
return __WASI_ERRNO_SUCCESS;
@@ -53,18 +55,17 @@ class JSFile : public DataFile {
5355
// The size of the JS File is defined as the length of the JS array in
5456
// $wasmFS$JSMemoryFiles.
5557
size_t getSize() override {
56-
return (size_t)EM_ASM_INT({ return $wasmFS$JSMemoryFiles[$0].length; },
58+
return (size_t)EM_ASM_INT({ return wasmFS$JSMemoryFiles[$0].length; },
5759
index);
5860
}
5961

6062
public:
6163
JSFile(mode_t mode) : DataFile(mode) {
6264
// Add the new JS File to the $wasmFS$JSMemoryFiles array and assign the
6365
// array index.
64-
index = (jsIndex_t)EM_ASM_INT({
65-
var typedBuffer = new Uint8Array();
66-
$wasmFS$JSMemoryFiles.push(typedBuffer);
67-
return $wasmFS$JSMemoryFiles.length - 1;
66+
index = (js_index_t)EM_ASM_INT({
67+
wasmFS$JSMemoryFiles.push(new Uint8Array(0));
68+
return wasmFS$JSMemoryFiles.length - 1;
6869
});
6970
}
7071

@@ -86,12 +87,13 @@ class JSFileBackend : public Backend {
8687
return std::make_shared<JSFile>(mode);
8788
}
8889
std::shared_ptr<Directory> createDirectory(mode_t mode) override {
89-
return std::make_shared<Directory>(mode, shared_from_this());
90+
return std::make_shared<Directory>(mode, this);
9091
}
9192
};
9293

93-
std::shared_ptr<Backend> createJSFileBackend() {
94-
return std::make_unique<JSFileBackend>();
94+
extern "C" backend_t createJSFileBackend() {
95+
wasmFS.backendTable.push_back(std::make_unique<JSFileBackend>());
96+
return wasmFS.backendTable.back().get();
9597
}
9698

97-
} // namespace wasmfs
99+
} // namespace wasmfs

system/lib/wasmfs/syscalls.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ long __syscall_fstat64(long fd, long buf) {
371371
return doStat(openFile.locked().getFile(), buffer);
372372
}
373373

374-
__wasi_fd_t
374+
static __wasi_fd_t
375375
doOpen(char* pathname, long flags, mode_t mode, backend_t backend = nullptr) {
376376
int accessMode = (flags & O_ACCMODE);
377377
bool canWrite = false;
@@ -421,7 +421,13 @@ doOpen(char* pathname, long flags, mode_t mode, backend_t backend = nullptr) {
421421
// Mask all permissions sent via mode.
422422
mode &= S_IALLUGO;
423423
// Create an empty in-memory file.
424-
auto backend = lockedParentDir.getBackend();
424+
425+
// By default, the backend that the file is created in is the same as the
426+
// parent directory. However, if a backend is passed as a parameter, then
427+
// that backend is used.
428+
if (!backend) {
429+
backend = lockedParentDir.getBackend();
430+
}
425431
auto created = backend->createFile(mode);
426432

427433
// TODO: When rename is implemented make sure that one can atomically
@@ -451,10 +457,10 @@ doOpen(char* pathname, long flags, mode_t mode, backend_t backend = nullptr) {
451457
return wasmFS.getLockedFileTable().add(openFile);
452458
}
453459

454-
// This function allows users to create files associated with a specific
455-
// backend.
456-
__wasi_fd_t wasmfs_create(long pathname, mode_t mode, backend_t backend) {
457-
return doOpen((char*)pathname, O_CREAT, mode, backend);
460+
// This function is exposed to users and allows them to specify a particular
461+
// backend that a file should be created within.
462+
__wasi_fd_t wasmfs_create(char* pathname, mode_t mode, backend_t backend) {
463+
return doOpen(pathname, O_CREAT, mode, backend);
458464
}
459465

460466
__wasi_fd_t __syscall_open(long pathname, long flags, ...) {
@@ -468,8 +474,8 @@ __wasi_fd_t __syscall_open(long pathname, long flags, ...) {
468474
return doOpen((char*)pathname, flags, mode);
469475
}
470476

471-
long __syscall_mkdir(long path, long mode) {
472-
auto pathParts = splitPath((char*)path);
477+
static long doMkdir(char* path, long mode, backend_t backend = nullptr) {
478+
auto pathParts = splitPath(path);
473479

474480
if (pathParts.empty()) {
475481
return -EINVAL;
@@ -502,14 +508,30 @@ long __syscall_mkdir(long path, long mode) {
502508
// https://www.gnu.org/software/libc/manual/html_node/Permission-Bits.html
503509
mode &= S_IRWXUGO | S_ISVTX;
504510
// Create an empty in-memory directory.
505-
auto backend = lockedParentDir.getBackend();
511+
512+
// By default, the backend that the directory is created in is the same as
513+
// the parent directory. However, if a backend is passed as a parameter,
514+
// then that backend is used.
515+
if (!backend) {
516+
backend = lockedParentDir.getBackend();
517+
}
506518
auto created = backend->createDirectory(mode);
507519

508520
lockedParentDir.setEntry(base, created);
509521
return 0;
510522
}
511523
}
512524

525+
// This function is exposed to users and allows users to specify a particular
526+
// backend that a directory should be created within.
527+
long wasmfs_mkdir(char* path, long mode, backend_t backend) {
528+
return doMkdir(path, mode, backend);
529+
}
530+
531+
long __syscall_mkdir(long path, long mode) {
532+
return doMkdir((char*)path, mode);
533+
}
534+
513535
__wasi_errno_t __wasi_fd_seek(__wasi_fd_t fd,
514536
__wasi_filedelta_t offset,
515537
__wasi_whence_t whence,

tests/wasmfs/wasmfs_jsfile.c

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*/
77

88
#include <assert.h>
9+
#include <emscripten/emscripten.h>
10+
#include <emscripten/wasmfs.h>
911
#include <errno.h>
1012
#include <fcntl.h>
1113
#include <signal.h>
@@ -17,13 +19,49 @@
1719

1820
int main() {
1921

20-
// Create a JS Backend
2122
backend_t JSBackend = createJSFileBackend();
2223

2324
// Create a new JS file under root.
2425
int fd = wasmfs_create("/testfile", 0777, JSBackend);
2526

2627
// Try writing to and reading from the file.
28+
errno = 0;
29+
const char* msg = "Test with a new JS file\n";
30+
write(fd, msg, strlen(msg));
31+
assert(errno == 0);
32+
33+
EM_ASM({out(wasmFS$JSMemoryFiles[0])});
34+
35+
errno = 0;
36+
lseek(fd, 0, SEEK_SET);
37+
assert(errno == 0);
38+
char buf[200] = {};
39+
read(fd, buf, sizeof(buf));
40+
assert(errno == 0);
41+
printf("%s\n", buf);
42+
43+
close(fd);
44+
45+
// Try creating a new JS directory under root.
46+
int result = wasmfs_mkdir("/test-dir", 0777, JSBackend);
47+
48+
// Try to create a new JS file under this new directory.
49+
int fd2 = open("/test-dir/jsfile", O_RDWR | O_CREAT, 0777);
50+
51+
// Try writing to and reading from the file.
52+
errno = 0;
53+
const char* msg2 = "Test with a JS file created under a JS directory\n";
54+
write(fd2, msg2, strlen(msg2));
55+
assert(errno == 0);
56+
57+
EM_ASM({out(wasmFS$JSMemoryFiles[1])});
58+
59+
errno = 0;
60+
lseek(fd2, 0, SEEK_SET);
61+
assert(errno == 0);
62+
read(fd2, buf, sizeof(buf));
63+
assert(errno == 0);
64+
printf("%s\n", buf);
2765

2866
return 0;
29-
}
67+
}

tests/wasmfs/wasmfs_jsfile.out

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,17 @@
1-
s
1+
Uint8Array(24) [
2+
84, 101, 115, 116, 32, 119, 105,
3+
116, 104, 32, 97, 32, 110, 101,
4+
119, 32, 74, 83, 32, 102, 105,
5+
108, 101, 10
6+
]
7+
Test with a new JS file
8+
9+
Uint8Array(49) [
10+
84, 101, 115, 116, 32, 119, 105, 116, 104,
11+
32, 97, 32, 74, 83, 32, 102, 105, 108,
12+
101, 32, 99, 114, 101, 97, 116, 101, 100,
13+
32, 117, 110, 100, 101, 114, 32, 97, 32,
14+
74, 83, 32, 100, 105, 114, 101, 99, 116,
15+
111, 114, 121, 10
16+
]
17+
Test with a JS file created under a JS directory

0 commit comments

Comments
 (0)