aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library_nodefs.js58
-rw-r--r--tests/test_core.py6
-rw-r--r--tests/unistd/access.c10
-rw-r--r--tests/unistd/truncate.c6
4 files changed, 77 insertions, 3 deletions
diff --git a/src/library_nodefs.js b/src/library_nodefs.js
index d8df1689..2be54076 100644
--- a/src/library_nodefs.js
+++ b/src/library_nodefs.js
@@ -1,7 +1,11 @@
mergeInto(LibraryManager.library, {
$NODEFS__deps: ['$FS', '$PATH'],
- $NODEFS__postset: 'if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); }',
+ $NODEFS__postset: 'if (ENVIRONMENT_IS_NODE) { var fs = require("fs"); NODEFS.staticInit(); }',
$NODEFS: {
+ isWindows: false,
+ staticInit: function() {
+ NODEFS.isWindows = !!process.platform.match(/^win/);
+ },
mount: function (mount) {
assert(ENVIRONMENT_IS_NODE);
return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0);
@@ -19,6 +23,11 @@ mergeInto(LibraryManager.library, {
var stat;
try {
stat = fs.lstatSync(path);
+ if (NODEFS.isWindows) {
+ // On Windows, directories return permission bits 'rw-rw-rw-', even though they have 'rwxrwxrwx', so
+ // propagate write bits to execute bits.
+ stat.mode = stat.mode | ((stat.mode & 146) >> 1);
+ }
} catch (e) {
if (!e.code) throw e;
throw new FS.ErrnoError(ERRNO_CODES[e.code]);
@@ -35,6 +44,41 @@ mergeInto(LibraryManager.library, {
parts.reverse();
return PATH.join.apply(null, parts);
},
+ // This maps the integer permission modes from http://linux.die.net/man/3/open
+ // to node.js-specific file open permission strings at http://nodejs.org/api/fs.html#fs_fs_open_path_flags_mode_callback
+ flagsToPermissionStringMap: {
+ 0/*O_RDONLY*/: 'r',
+ 1/*O_WRONLY*/: 'r+',
+ 2/*O_RDWR*/: 'r+',
+ 64/*O_CREAT*/: 'r',
+ 65/*O_WRONLY|O_CREAT*/: 'r+',
+ 66/*O_RDWR|O_CREAT*/: 'r+',
+ 129/*O_WRONLY|O_EXCL*/: 'rx+',
+ 193/*O_WRONLY|O_CREAT|O_EXCL*/: 'rx+',
+ 514/*O_RDWR|O_TRUNC*/: 'w+',
+ 577/*O_WRONLY|O_CREAT|O_TRUNC*/: 'w',
+ 578/*O_CREAT|O_RDWR|O_TRUNC*/: 'w+',
+ 705/*O_WRONLY|O_CREAT|O_EXCL|O_TRUNC*/: 'wx',
+ 706/*O_RDWR|O_CREAT|O_EXCL|O_TRUNC*/: 'wx+',
+ 1024/*O_APPEND*/: 'a',
+ 1025/*O_WRONLY|O_APPEND*/: 'a',
+ 1026/*O_RDWR|O_APPEND*/: 'a+',
+ 1089/*O_WRONLY|O_CREAT|O_APPEND*/: 'a',
+ 1090/*O_RDWR|O_CREAT|O_APPEND*/: 'a+',
+ 1153/*O_WRONLY|O_EXCL|O_APPEND*/: 'ax',
+ 1154/*O_RDWR|O_EXCL|O_APPEND*/: 'ax+',
+ 1217/*O_WRONLY|O_CREAT|O_EXCL|O_APPEND*/: 'ax',
+ 1218/*O_RDWR|O_CREAT|O_EXCL|O_APPEND*/: 'ax+',
+ 4096/*O_RDONLY|O_DSYNC*/: 'rs',
+ 4098/*O_RDWR|O_DSYNC*/: 'rs+'
+ },
+ flagsToPermissionString: function(flags) {
+ if (flags in NODEFS.flagsToPermissionStringMap) {
+ return NODEFS.flagsToPermissionStringMap[flags];
+ } else {
+ return flags;
+ }
+ },
node_ops: {
getattr: function(node) {
var path = NODEFS.realPath(node);
@@ -45,6 +89,14 @@ mergeInto(LibraryManager.library, {
if (!e.code) throw e;
throw new FS.ErrnoError(ERRNO_CODES[e.code]);
}
+ // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096.
+ // See http://support.microsoft.com/kb/140365
+ 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,
@@ -163,7 +215,7 @@ mergeInto(LibraryManager.library, {
var path = NODEFS.realPath(stream.node);
try {
if (FS.isFile(stream.node.mode)) {
- stream.nfd = fs.openSync(path, stream.flags);
+ stream.nfd = fs.openSync(path, NODEFS.flagsToPermissionString(stream.flags));
}
} catch (e) {
if (!e.code) throw e;
@@ -172,7 +224,7 @@ mergeInto(LibraryManager.library, {
},
close: function (stream) {
try {
- if (FS.isFile(stream.node.mode)) {
+ if (FS.isFile(stream.node.mode) && stream.nfd) {
fs.closeSync(stream.nfd);
}
} catch (e) {
diff --git a/tests/test_core.py b/tests/test_core.py
index 4ab8f8e1..69fb31f3 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -7841,6 +7841,12 @@ def process(filename):
self.clear()
if not self.is_le32(): return self.skip('le32 needed for inline js')
for fs in ['MEMFS', 'NODEFS']:
+ if WINDOWS and fs == 'NODEFS':
+ print >> sys.stderr, 'Skipping NODEFS part of this test for test_unistd_links on Windows, since it would require administrative privileges.'
+ # Also, other detected discrepancies if you do end up running this test on NODEFS:
+ # test expects /, but Windows gives \ as path slashes.
+ # Calling readlink() on a non-link gives error 22 EINVAL on Unix, but simply error 0 OK on Windows.
+ continue
src = open(path_from_root('tests', 'unistd', 'links.c'), 'r').read()
expected = open(path_from_root('tests', 'unistd', 'links.out'), 'r').read()
Building.COMPILER_TEST_OPTS += ['-D' + fs]
diff --git a/tests/unistd/access.c b/tests/unistd/access.c
index 57d38f5c..92b52e5e 100644
--- a/tests/unistd/access.c
+++ b/tests/unistd/access.c
@@ -33,5 +33,15 @@ int main() {
errno = 0;
printf("\n");
}
+
+ // Restore full permissions on all created files so that python test runner rmtree
+ // won't have problems on deleting the files. On Windows, calling shutil.rmtree()
+ // will fail if any of the files are read-only.
+ EM_ASM(
+ FS.chmod('forbidden', 0777);
+ FS.chmod('readable', 0777);
+ FS.chmod('writeable', 0777);
+ FS.chmod('allaccess', 0777);
+ );
return 0;
}
diff --git a/tests/unistd/truncate.c b/tests/unistd/truncate.c
index e63a4c13..5620f502 100644
--- a/tests/unistd/truncate.c
+++ b/tests/unistd/truncate.c
@@ -76,5 +76,11 @@ int main() {
memset(&s, 0, sizeof s);
errno = 0;
+ // Restore full permissions on all created files so that python test runner rmtree
+ // won't have problems on deleting the files. On Windows, calling shutil.rmtree()
+ // will fail if any of the files are read-only.
+ EM_ASM(
+ FS.chmod('toread', 0777);
+ );
return 0;
}