From 3b46e7f1485c62935b2cb1a66bee82fdca738660 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Thu, 21 May 2020 14:12:42 +0200 Subject: [PATCH] win,fs: use namespaced path in absolute symlinks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the namespaced (with the \\?\ prefix) paths for symlink targets when the path is absolute. This allows creation of symlinks to files with long filenames. Fixes: https://github.com/nodejs/node/issues/27795 PR-URL: https://github.com/nodejs/node/pull/33351 Reviewed-By: Colin Ihrig Reviewed-By: Gerhard Stöbich Reviewed-By: Anna Henningsen Reviewed-By: Ruben Bridgewater --- lib/internal/fs/utils.js | 10 +++++--- test/parallel/test-fs-symlink-longpath.js | 29 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 test/parallel/test-fs-symlink-longpath.js diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 6f096336f20e10..989bccc7c153d3 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -272,10 +272,14 @@ function preprocessSymlinkDestination(path, type, linkPath) { // A relative target is relative to the link's parent directory. path = pathModule.resolve(linkPath, '..', path); return pathModule.toNamespacedPath(path); - } else { - // Windows symlinks don't tolerate forward slashes. - return ('' + path).replace(/\//g, '\\'); } + + if (pathModule.isAbsolute(path)) { + // If the path is absolute, use the \\?\-prefix to enable long filenames + return pathModule.toNamespacedPath(path); + } + // Windows symlinks don't tolerate forward slashes. + return ('' + path).replace(/\//g, '\\'); } // Constructor for file stats. diff --git a/test/parallel/test-fs-symlink-longpath.js b/test/parallel/test-fs-symlink-longpath.js new file mode 100644 index 00000000000000..f6824218137bf2 --- /dev/null +++ b/test/parallel/test-fs-symlink-longpath.js @@ -0,0 +1,29 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); +const fs = require('fs'); + +const tmpdir = require('../common/tmpdir'); +tmpdir.refresh(); +const tmpDir = tmpdir.path; +const longPath = path.join(...[tmpDir].concat(Array(30).fill('1234567890'))); +fs.mkdirSync(longPath, { recursive: true }); + +// Test if we can have symlinks to files and folders with long filenames +const targetDirtectory = path.join(longPath, 'target-directory'); +fs.mkdirSync(targetDirtectory); +const pathDirectory = path.join(tmpDir, 'new-directory'); +fs.symlink(targetDirtectory, pathDirectory, 'dir', common.mustCall((err) => { + assert.ifError(err); + assert(fs.existsSync(pathDirectory)); +})); + +const targetFile = path.join(longPath, 'target-file'); +fs.writeFileSync(targetFile, 'data'); +const pathFile = path.join(tmpDir, 'new-file'); +fs.symlink(targetFile, pathFile, common.mustCall((err) => { + assert.ifError(err); + assert(fs.existsSync(pathFile)); +}));