From 2f602258e0e99e8af2b09f7073382563cdd34646 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 10 Dec 2021 11:26:47 +0100 Subject: [PATCH] fs: fix error codes for `fs.cp` The context passed into this error must have `.code`, `.syscall` and `.message`. Fixes: https://github.com/nodejs/node/issues/41104 PR-URL: https://github.com/nodejs/node/pull/41106 Reviewed-By: Rich Trott Reviewed-By: Evan Lucas Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca --- lib/.eslintrc.yaml | 2 ++ lib/internal/fs/cp/cp-sync.js | 12 ++++++++++++ lib/internal/fs/cp/cp.js | 14 +++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index 90715e4ea37d69..a8881c6b398939 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -25,6 +25,8 @@ rules: message: "Please use `require('internal/errors').hideStackFrames()` instead." - selector: "AssignmentExpression:matches([left.name='prepareStackTrace'], [left.property.name='prepareStackTrace'])" message: "Use 'overrideStackTrace' from 'lib/internal/errors.js' instead of 'Error.prepareStackTrace'." + - selector: "ThrowStatement > NewExpression[callee.name=/^ERR_[A-Z_]+$/] > ObjectExpression:first-child:not(:has([key.name='message']):has([key.name='code']):has([key.name='syscall']))" + message: "The context passed into SystemError constructor must have .code, .syscall and .message." no-restricted-globals: - error - name: AbortController diff --git a/lib/internal/fs/cp/cp-sync.js b/lib/internal/fs/cp/cp-sync.js index 723a5c86d3fb73..3ee6a70f959582 100644 --- a/lib/internal/fs/cp/cp-sync.js +++ b/lib/internal/fs/cp/cp-sync.js @@ -70,6 +70,7 @@ function checkPathsSync(src, dest, opts) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } if (srcStat.isDirectory() && !destStat.isDirectory()) { @@ -79,6 +80,7 @@ function checkPathsSync(src, dest, opts) { path: dest, syscall: 'cp', errno: EISDIR, + code: 'EISDIR', }); } if (!srcStat.isDirectory() && destStat.isDirectory()) { @@ -88,6 +90,7 @@ function checkPathsSync(src, dest, opts) { path: dest, syscall: 'cp', errno: ENOTDIR, + code: 'ENOTDIR', }); } } @@ -98,6 +101,7 @@ function checkPathsSync(src, dest, opts) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } return { srcStat, destStat }; @@ -135,6 +139,7 @@ function checkParentPathsSync(src, srcStat, dest) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } return checkParentPathsSync(src, srcStat, destParent); @@ -170,6 +175,7 @@ function getStats(destStat, src, dest, opts) { path: src, syscall: 'cp', errno: EINVAL, + code: 'EISDIR', }); } else if (srcStat.isFile() || srcStat.isCharacterDevice() || @@ -183,6 +189,7 @@ function getStats(destStat, src, dest, opts) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } else if (srcStat.isFIFO()) { throw new ERR_FS_CP_FIFO_PIPE({ @@ -190,6 +197,7 @@ function getStats(destStat, src, dest, opts) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } throw new ERR_FS_CP_UNKNOWN({ @@ -197,6 +205,7 @@ function getStats(destStat, src, dest, opts) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } @@ -215,6 +224,7 @@ function mayCopyFile(srcStat, src, dest, opts) { path: dest, syscall: 'cp', errno: EEXIST, + code: 'EEXIST', }); } } @@ -305,6 +315,7 @@ function onLink(destStat, src, dest) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } // Prevent copy if src is a subdir of dest since unlinking @@ -316,6 +327,7 @@ function onLink(destStat, src, dest) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } return copyLink(resolvedSrc, dest); diff --git a/lib/internal/fs/cp/cp.js b/lib/internal/fs/cp/cp.js index 9ee661be68d1e2..090a4023df14e8 100644 --- a/lib/internal/fs/cp/cp.js +++ b/lib/internal/fs/cp/cp.js @@ -82,6 +82,7 @@ async function checkPaths(src, dest, opts) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } if (srcStat.isDirectory() && !destStat.isDirectory()) { @@ -91,6 +92,7 @@ async function checkPaths(src, dest, opts) { path: dest, syscall: 'cp', errno: EISDIR, + code: 'EISDIR', }); } if (!srcStat.isDirectory() && destStat.isDirectory()) { @@ -100,6 +102,7 @@ async function checkPaths(src, dest, opts) { path: dest, syscall: 'cp', errno: ENOTDIR, + code: 'ENOTDIR', }); } } @@ -110,6 +113,7 @@ async function checkPaths(src, dest, opts) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } return { srcStat, destStat }; @@ -171,6 +175,7 @@ async function checkParentPaths(src, srcStat, dest) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } return checkParentPaths(src, srcStat, destParent); @@ -209,7 +214,8 @@ async function getStatsForCopy(destStat, src, dest, opts) { message: `${src} is a directory (not copied)`, path: src, syscall: 'cp', - errno: EINVAL, + errno: EISDIR, + code: 'EISDIR', }); } else if (srcStat.isFile() || srcStat.isCharacterDevice() || @@ -223,6 +229,7 @@ async function getStatsForCopy(destStat, src, dest, opts) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } else if (srcStat.isFIFO()) { throw new ERR_FS_CP_FIFO_PIPE({ @@ -230,6 +237,7 @@ async function getStatsForCopy(destStat, src, dest, opts) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } throw new ERR_FS_CP_UNKNOWN({ @@ -237,6 +245,7 @@ async function getStatsForCopy(destStat, src, dest, opts) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } @@ -255,6 +264,7 @@ async function mayCopyFile(srcStat, src, dest, opts) { path: dest, syscall: 'cp', errno: EEXIST, + code: 'EEXIST', }); } } @@ -355,6 +365,7 @@ async function onLink(destStat, src, dest) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } // Do not copy if src is a subdir of dest since unlinking @@ -367,6 +378,7 @@ async function onLink(destStat, src, dest) { path: dest, syscall: 'cp', errno: EINVAL, + code: 'EINVAL', }); } return copyLink(resolvedSrc, dest);