From dca407945cbab0e016a0c555ef94fc11a95818a0 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Mon, 11 May 2020 13:11:19 +0200 Subject: [PATCH] win,fs: use namespaced path in absolute symlinks 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 --- lib/internal/fs/utils.js | 4 ++++ test/parallel/test-fs-symlink-longpath.js | 29 +++++++++++++++++++++++ 2 files changed, 33 insertions(+) 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 96be328a8ea2fc..b005a5793387ea 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -302,6 +302,10 @@ function preprocessSymlinkDestination(path, type, linkPath) { path = pathModule.resolve(linkPath, '..', path); return pathModule.toNamespacedPath(path); } + 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, '\\'); } 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)); +}));