diff --git a/src/library_noderawfs.js b/src/library_noderawfs.js index 3540bfda1..0c3a748ed 100644 --- a/src/library_noderawfs.js +++ b/src/library_noderawfs.js @@ -46,7 +46,13 @@ mergeInto(LibraryManager.library, { chown: function() { fs.chownSync.apply(void 0, arguments); }, fchown: function() { fs.fchownSync.apply(void 0, arguments); }, truncate: function() { fs.truncateSync.apply(void 0, arguments); }, - ftruncate: function() { fs.ftruncateSync.apply(void 0, arguments); }, + ftruncate: function(fd, len) { + // See https://github.com/nodejs/node/issues/35632 + if (len < 0) { + throw new FS.ErrnoError({{{ cDefine('EINVAL') }}}); + } + fs.ftruncateSync.apply(void 0, arguments); + }, utime: function() { fs.utimesSync.apply(void 0, arguments); }, open: function(path, flags, mode, suggestFD) { if (typeof flags === "string") { diff --git a/tests/test_core.py b/tests/test_core.py index c12b5a0a3..9e60f699a 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5273,10 +5273,8 @@ main( int argv, char ** argc ) { @no_windows("Windows throws EPERM rather than EACCES or EINVAL") @unittest.skipIf(WINDOWS or os.geteuid() == 0, "Root access invalidates this test by being able to write on readonly files") def test_unistd_truncate_noderawfs(self): - # FIXME - self.skipTest('fails on some node versions and OSes, e.g. 10.13.0 on linux') - - self.emcc_args += ['-s', 'NODERAWFS=1'] + self.uses_es6 = True + self.set_setting('NODERAWFS') self.do_run_in_out_file_test('tests', 'unistd', 'truncate.c', js_engines=[NODE_JS]) def test_unistd_swab(self): diff --git a/tests/unistd/truncate.c b/tests/unistd/truncate.c index c43c95345..be610a850 100644 --- a/tests/unistd/truncate.c +++ b/tests/unistd/truncate.c @@ -11,9 +11,12 @@ #include #include #include +#ifdef __EMSCRIPTEN__ #include +#endif -int main() { +void setup() { +#ifdef __EMSCRIPTEN__ EM_ASM( FS.mkdir('working'); #if NODEFS @@ -24,6 +27,20 @@ int main() { FS.writeFile('toread', 'abcdef'); FS.chmod('toread', 0o444); ); +#else + FILE* f = fopen("towrite", "w"); + fwrite("abcdef", 6, 1, f); + fclose(f); + f = fopen("toread", "w"); + fwrite("abcdef", 6, 1, f); + fclose(f); + + chmod("toread", 0444); +#endif +} + +int main() { + setup(); struct stat s; int f = open("towrite", O_WRONLY); @@ -31,63 +48,67 @@ int main() { printf("f2: %d\n", f2); fstat(f, &s); - printf("st_size: %d\n", s.st_size); + printf("st_size: %ld\n", s.st_size); memset(&s, 0, sizeof s); errno = 0; printf("\n"); printf("ftruncate(10): %d\n", ftruncate(f, 10)); - printf("errno: %d\n", errno); + printf("errno: %s\n", strerror(errno)); fstat(f, &s); - printf("st_size: %d\n", s.st_size); + printf("st_size: %ld\n", s.st_size); memset(&s, 0, sizeof s); errno = 0; printf("\n"); printf("ftruncate(4): %d\n", ftruncate(f, 4)); - printf("errno: %d\n", errno); + printf("errno: %s\n", strerror(errno)); fstat(f, &s); - printf("st_size: %d\n", s.st_size); + printf("st_size: %ld\n", s.st_size); memset(&s, 0, sizeof s); errno = 0; printf("\n"); printf("ftruncate(-1): %d\n", ftruncate(f, -1)); - printf("errno: %d\n", errno); + printf("errno: %s\n", strerror(errno)); fstat(f, &s); - printf("st_size: %d\n", s.st_size); + printf("st_size: %ld\n", s.st_size); memset(&s, 0, sizeof s); errno = 0; printf("\n"); printf("truncate(2): %d\n", truncate("towrite", 2)); - printf("errno: %d\n", errno); + printf("errno: %s\n", strerror(errno)); stat("towrite", &s); - printf("st_size: %d\n", s.st_size); + printf("st_size: %ld\n", s.st_size); memset(&s, 0, sizeof s); errno = 0; printf("\n"); printf("truncate(readonly, 2): %d\n", truncate("toread", 2)); - printf("errno: %d\n", errno); + printf("errno: %s\n", strerror(errno)); stat("toread", &s); - printf("st_size: %d\n", s.st_size); + printf("st_size: %ld\n", s.st_size); memset(&s, 0, sizeof s); errno = 0; printf("\n"); printf("ftruncate(readonly, 4): %d\n", ftruncate(f2, 4)); - printf("errno: %d\n", errno); + printf("errno: %s\n", strerror(errno)); fstat(f2, &s); - printf("st_size: %d\n", s.st_size); + printf("st_size: %ld\n", s.st_size); memset(&s, 0, sizeof s); errno = 0; +#ifdef __EMSCRIPTEN__ // 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', 0o777); ); +#else + chmod("toread", 0777); +#endif return 0; } diff --git a/tests/unistd/truncate.out b/tests/unistd/truncate.out index 6abbf264b..c410cf655 100644 --- a/tests/unistd/truncate.out +++ b/tests/unistd/truncate.out @@ -1,25 +1,25 @@ st_size: 6 ftruncate(10): 0 -errno: 0 +errno: No error information st_size: 10 ftruncate(4): 0 -errno: 0 +errno: No error information st_size: 4 ftruncate(-1): -1 -errno: 28 +errno: Invalid argument st_size: 4 truncate(2): 0 -errno: 0 +errno: No error information st_size: 2 truncate(readonly, 2): -1 -errno: 2 +errno: Permission denied st_size: 6 ftruncate(readonly, 4): -1 -errno: 28 +errno: Invalid argument st_size: 6