From 2002dd16d89c3a60be24c213b2439955e10fadf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Reis?= Date: Thu, 22 Aug 2019 00:40:47 +0100 Subject: [PATCH 1/6] src,lib: expose memory file mapping flag Support for UV_FS_O_FILEMAP was added in libuv in version 1.31.0. This exposes the flag in fs.constants and adds the prefix 'm' for text flags. --- doc/api/fs.md | 9 +++++++++ lib/internal/fs/utils.js | 5 +++++ src/node_constants.cc | 4 ++++ test/parallel/test-fs-fmap.js | 30 +++++++++++++++++++++++++++++ test/parallel/test-fs-open-flags.js | 9 ++++++++- 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-fs-fmap.js diff --git a/doc/api/fs.md b/doc/api/fs.md index c61f0d4e3ef660..e3716f2ce7caeb 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4949,6 +4949,11 @@ The following constants are meant for use with `fs.open()`. O_NONBLOCK Flag indicating to open the file in nonblocking mode when possible. + + UV_FS_O_FILEMAP + When set, a memory file mapping is used to access the file. This flag + is available on Windows operating systems only. + ### File Type Constants @@ -5141,6 +5146,10 @@ On Windows, opening an existing hidden file using the `'w'` flag (either through `fs.open()` or `fs.writeFile()` or `fsPromises.open()`) will fail with `EPERM`. Existing hidden files can be opened for writing with the `'r+'` flag. +All of the flags can be prepended with `'m'` to use a memory file mapping for +accessing the file (for example `'max+'`). This is only available on Windows, +on other operative systems `'m'` is ignored. + A call to `fs.ftruncate()` or `filehandle.truncate()` can be used to reset the file contents. diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 600d118db3c298..0c1c88f5e8a7ae 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -35,6 +35,7 @@ const { O_SYNC, O_TRUNC, O_WRONLY, + UV_FS_O_FILEMAP, S_IFBLK, S_IFCHR, S_IFDIR, @@ -417,6 +418,10 @@ function stringToFlags(flags) { case 'sa+': return O_APPEND | O_CREAT | O_RDWR | O_SYNC; } + if (typeof flags === 'string' && flags.charAt(0) === 'm') { + return UV_FS_O_FILEMAP | stringToFlags(flags.substring(1)); + } + throw new ERR_INVALID_OPT_VALUE('flags', flags); } diff --git a/src/node_constants.cc b/src/node_constants.cc index 7c9e4ce276112b..dc33d6c4ba1960 100644 --- a/src/node_constants.cc +++ b/src/node_constants.cc @@ -1127,6 +1127,10 @@ void DefineSystemConstants(Local target) { NODE_DEFINE_CONSTANT(target, O_EXCL); #endif +#ifdef UV_FS_O_FILEMAP + NODE_DEFINE_CONSTANT(target, UV_FS_O_FILEMAP); +#endif + #ifdef O_NOCTTY NODE_DEFINE_CONSTANT(target, O_NOCTTY); #endif diff --git a/test/parallel/test-fs-fmap.js b/test/parallel/test-fs-fmap.js new file mode 100644 index 00000000000000..59bb5356b334a2 --- /dev/null +++ b/test/parallel/test-fs-fmap.js @@ -0,0 +1,30 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const fs = require('fs'); +const join = require('path').join; + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); + +// Run this test on all platforms. While the 'm' flag is only available on +// Windows, it should be silently ignored on other platforms. + +const filename = join(tmpdir.path, 'fmap.txt'); +const text = 'Memory File Mapping Test'; + +fs.writeFileSync(filename, text, { flag: 'mw' }); +const r1 = fs.readFileSync(filename, { encoding: 'utf8', flag: 'mr' }); +assert.strictEqual(r1, text); + +fs.writeFileSync(filename, text, { flag: 'mr+' }); +const r2 = fs.readFileSync(filename, { encoding: 'utf8', flag: 'ma+' }); +assert.strictEqual(r2, text); + +fs.writeFileSync(filename, text, { flag: 'ma' }); +const numericFlag = fs.constants.UV_FS_O_FILEMAP | fs.constants.O_RDONLY; +const r3 = fs.readFileSync(filename, { encoding: 'utf8', flag: numericFlag }); +assert.strictEqual(r3, text + text); + +const r4 = fs.readFileSync(filename, { encoding: 'utf8', flag: 'mw+' }); +assert.strictEqual(r4, ''); diff --git a/test/parallel/test-fs-open-flags.js b/test/parallel/test-fs-open-flags.js index 62866cfb1b251d..bdff3797a34be6 100644 --- a/test/parallel/test-fs-open-flags.js +++ b/test/parallel/test-fs-open-flags.js @@ -38,7 +38,8 @@ const { O_APPEND = 0, O_SYNC = 0, O_DSYNC = 0, O_TRUNC = 0, - O_WRONLY = 0 + O_WRONLY = 0, + UV_FS_O_FILEMAP = 0 } = fs.constants; const { stringToFlags } = require('internal/fs/utils'); @@ -65,6 +66,12 @@ assert.strictEqual(stringToFlags('xa+'), O_APPEND | O_CREAT | O_RDWR | O_EXCL); assert.strictEqual(stringToFlags('as+'), O_APPEND | O_CREAT | O_RDWR | O_SYNC); assert.strictEqual(stringToFlags('sa+'), O_APPEND | O_CREAT | O_RDWR | O_SYNC); +assert.strictEqual(stringToFlags('mr'), UV_FS_O_FILEMAP | O_RDONLY); +assert.strictEqual(stringToFlags('mw'), + UV_FS_O_FILEMAP | O_TRUNC | O_CREAT | O_WRONLY); +assert.strictEqual(stringToFlags('max+'), + UV_FS_O_FILEMAP | O_APPEND | O_CREAT | O_RDWR | O_EXCL); + ('+ +a +r +w rw wa war raw r++ a++ w++ x +x x+ rx rx+ wxx wax xwx xxx') .split(' ') .forEach(function(flags) { From a7146a35ba40469a39f035032aeff21c9ed190a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Reis?= Date: Thu, 22 Aug 2019 16:32:57 +0100 Subject: [PATCH 2/6] fixup! src,lib: expose memory file mapping flag Co-Authored-By: Rich Trott --- doc/api/fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index e3716f2ce7caeb..bdf9b545631e79 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -5148,7 +5148,7 @@ through `fs.open()` or `fs.writeFile()` or `fsPromises.open()`) will fail with All of the flags can be prepended with `'m'` to use a memory file mapping for accessing the file (for example `'max+'`). This is only available on Windows, -on other operative systems `'m'` is ignored. +On other operating systems, `'m'` is ignored. A call to `fs.ftruncate()` or `filehandle.truncate()` can be used to reset the file contents. From b447c3ca5dbbb3060b2088f12d6efe0ffbfa9211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Reis?= Date: Thu, 22 Aug 2019 16:33:40 +0100 Subject: [PATCH 3/6] fixup! src,lib: expose memory file mapping flag Co-Authored-By: Rich Trott --- doc/api/fs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index bdf9b545631e79..ee81e2da5d7ffd 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -5147,7 +5147,7 @@ through `fs.open()` or `fs.writeFile()` or `fsPromises.open()`) will fail with `EPERM`. Existing hidden files can be opened for writing with the `'r+'` flag. All of the flags can be prepended with `'m'` to use a memory file mapping for -accessing the file (for example `'max+'`). This is only available on Windows, +accessing the file (for example `'max+'`). This is only available on Windows. On other operating systems, `'m'` is ignored. A call to `fs.ftruncate()` or `filehandle.truncate()` can be used to reset From 45cea0bde75ef3c8e25775eaa4158968f38dff16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Reis?= Date: Thu, 22 Aug 2019 16:42:48 +0100 Subject: [PATCH 4/6] fixup! src,lib: expose memory file mapping flag --- src/node_constants.cc | 4 +--- test/parallel/test-fs-open-flags.js | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/node_constants.cc b/src/node_constants.cc index dc33d6c4ba1960..68af221b60aa65 100644 --- a/src/node_constants.cc +++ b/src/node_constants.cc @@ -1127,9 +1127,7 @@ void DefineSystemConstants(Local target) { NODE_DEFINE_CONSTANT(target, O_EXCL); #endif -#ifdef UV_FS_O_FILEMAP - NODE_DEFINE_CONSTANT(target, UV_FS_O_FILEMAP); -#endif +NODE_DEFINE_CONSTANT(target, UV_FS_O_FILEMAP); #ifdef O_NOCTTY NODE_DEFINE_CONSTANT(target, O_NOCTTY); diff --git a/test/parallel/test-fs-open-flags.js b/test/parallel/test-fs-open-flags.js index bdff3797a34be6..ec56ba5a3e637f 100644 --- a/test/parallel/test-fs-open-flags.js +++ b/test/parallel/test-fs-open-flags.js @@ -79,6 +79,10 @@ assert.strictEqual(stringToFlags('max+'), () => stringToFlags(flags), { code: 'ERR_INVALID_OPT_VALUE', type: TypeError } ); + common.expectsError( + () => stringToFlags(`m${flags}`), + { code: 'ERR_INVALID_OPT_VALUE', type: TypeError } + ); }); common.expectsError( From c77569ec533814c5ec2021c57503eba772dcd815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Reis?= Date: Mon, 2 Sep 2019 21:37:44 +0100 Subject: [PATCH 5/6] fixup! src,lib: expose memory file mapping flag --- doc/api/fs.md | 4 ---- lib/internal/fs/utils.js | 5 ----- test/parallel/test-fs-fmap.js | 29 ++++++++++++++--------------- test/parallel/test-fs-open-flags.js | 13 +------------ 4 files changed, 15 insertions(+), 36 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index ee81e2da5d7ffd..d26dd1c23114dc 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -5146,10 +5146,6 @@ On Windows, opening an existing hidden file using the `'w'` flag (either through `fs.open()` or `fs.writeFile()` or `fsPromises.open()`) will fail with `EPERM`. Existing hidden files can be opened for writing with the `'r+'` flag. -All of the flags can be prepended with `'m'` to use a memory file mapping for -accessing the file (for example `'max+'`). This is only available on Windows. -On other operating systems, `'m'` is ignored. - A call to `fs.ftruncate()` or `filehandle.truncate()` can be used to reset the file contents. diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 0c1c88f5e8a7ae..600d118db3c298 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -35,7 +35,6 @@ const { O_SYNC, O_TRUNC, O_WRONLY, - UV_FS_O_FILEMAP, S_IFBLK, S_IFCHR, S_IFDIR, @@ -418,10 +417,6 @@ function stringToFlags(flags) { case 'sa+': return O_APPEND | O_CREAT | O_RDWR | O_SYNC; } - if (typeof flags === 'string' && flags.charAt(0) === 'm') { - return UV_FS_O_FILEMAP | stringToFlags(flags.substring(1)); - } - throw new ERR_INVALID_OPT_VALUE('flags', flags); } diff --git a/test/parallel/test-fs-fmap.js b/test/parallel/test-fs-fmap.js index 59bb5356b334a2..4b21ce8d95a12f 100644 --- a/test/parallel/test-fs-fmap.js +++ b/test/parallel/test-fs-fmap.js @@ -4,27 +4,26 @@ const assert = require('assert'); const fs = require('fs'); const join = require('path').join; +const { + O_CREAT = 0, + O_RDONLY = 0, + O_TRUNC = 0, + O_WRONLY = 0, + UV_FS_O_FILEMAP = 0 +} = fs.constants; + const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); -// Run this test on all platforms. While the 'm' flag is only available on +// Run this test on all platforms. While UV_FS_O_FILEMAP is only available on // Windows, it should be silently ignored on other platforms. const filename = join(tmpdir.path, 'fmap.txt'); const text = 'Memory File Mapping Test'; -fs.writeFileSync(filename, text, { flag: 'mw' }); -const r1 = fs.readFileSync(filename, { encoding: 'utf8', flag: 'mr' }); -assert.strictEqual(r1, text); - -fs.writeFileSync(filename, text, { flag: 'mr+' }); -const r2 = fs.readFileSync(filename, { encoding: 'utf8', flag: 'ma+' }); -assert.strictEqual(r2, text); +const mw = UV_FS_O_FILEMAP | O_TRUNC | O_CREAT | O_WRONLY; +const mr = UV_FS_O_FILEMAP | O_RDONLY; -fs.writeFileSync(filename, text, { flag: 'ma' }); -const numericFlag = fs.constants.UV_FS_O_FILEMAP | fs.constants.O_RDONLY; -const r3 = fs.readFileSync(filename, { encoding: 'utf8', flag: numericFlag }); -assert.strictEqual(r3, text + text); - -const r4 = fs.readFileSync(filename, { encoding: 'utf8', flag: 'mw+' }); -assert.strictEqual(r4, ''); +fs.writeFileSync(filename, text, { flag: mw }); +const r1 = fs.readFileSync(filename, { encoding: 'utf8', flag: mr }); +assert.strictEqual(r1, text); diff --git a/test/parallel/test-fs-open-flags.js b/test/parallel/test-fs-open-flags.js index ec56ba5a3e637f..62866cfb1b251d 100644 --- a/test/parallel/test-fs-open-flags.js +++ b/test/parallel/test-fs-open-flags.js @@ -38,8 +38,7 @@ const { O_APPEND = 0, O_SYNC = 0, O_DSYNC = 0, O_TRUNC = 0, - O_WRONLY = 0, - UV_FS_O_FILEMAP = 0 + O_WRONLY = 0 } = fs.constants; const { stringToFlags } = require('internal/fs/utils'); @@ -66,12 +65,6 @@ assert.strictEqual(stringToFlags('xa+'), O_APPEND | O_CREAT | O_RDWR | O_EXCL); assert.strictEqual(stringToFlags('as+'), O_APPEND | O_CREAT | O_RDWR | O_SYNC); assert.strictEqual(stringToFlags('sa+'), O_APPEND | O_CREAT | O_RDWR | O_SYNC); -assert.strictEqual(stringToFlags('mr'), UV_FS_O_FILEMAP | O_RDONLY); -assert.strictEqual(stringToFlags('mw'), - UV_FS_O_FILEMAP | O_TRUNC | O_CREAT | O_WRONLY); -assert.strictEqual(stringToFlags('max+'), - UV_FS_O_FILEMAP | O_APPEND | O_CREAT | O_RDWR | O_EXCL); - ('+ +a +r +w rw wa war raw r++ a++ w++ x +x x+ rx rx+ wxx wax xwx xxx') .split(' ') .forEach(function(flags) { @@ -79,10 +72,6 @@ assert.strictEqual(stringToFlags('max+'), () => stringToFlags(flags), { code: 'ERR_INVALID_OPT_VALUE', type: TypeError } ); - common.expectsError( - () => stringToFlags(`m${flags}`), - { code: 'ERR_INVALID_OPT_VALUE', type: TypeError } - ); }); common.expectsError( From cc923d381b94aa0da9ffcc6edeac18c9c4f3a247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Reis?= Date: Wed, 4 Sep 2019 11:50:35 +0100 Subject: [PATCH 6/6] fixup! src,lib: expose memory file mapping flag --- doc/api/fs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index d26dd1c23114dc..ff887f8f0dbf30 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -4952,7 +4952,8 @@ The following constants are meant for use with `fs.open()`. UV_FS_O_FILEMAP When set, a memory file mapping is used to access the file. This flag - is available on Windows operating systems only. + is available on Windows operating systems only. On other operating systems, + this flag is ignored.