From a1af6685b7700e4521a1861e57afc9c8fe99aa0a Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sun, 5 Jan 2020 06:11:55 +0100 Subject: [PATCH] unix: squelch fchmod() EPERM on CIFS share MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uv_fs_copyfile() calls fchmod() to change the target file's permissions to the source file's permissions but that operation errors with EPERM on CIFS shares unless they are mounted with the "noperm" option. Since UNIX-style permissions don't make sense for CIFS anyway, let's handle the error in libuv by recognizing that it's a CIFS share and continuing when that is the case. The same logic probably applies to (a subset of) FUSE file systems but those haven't been whitelisted yet. Fixes: https://github.com/libuv/libuv/issues/2596 Refs: https://github.com/nodejs/node/issues/31170 PR-URL: https://github.com/libuv/libuv/pull/2597 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- src/unix/fs.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/unix/fs.c b/src/unix/fs.c index 07df52a6..d5017ebb 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -1137,7 +1137,28 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { if (fchmod(dstfd, src_statsbuf.st_mode) == -1) { err = UV__ERR(errno); +#ifdef __linux__ + if (err != UV_EPERM) + goto out; + + { + struct statfs s; + + /* fchmod() on CIFS shares always fails with EPERM unless the share is + * mounted with "noperm". As fchmod() is a meaningless operation on such + * shares anyway, detect that condition and squelch the error. + */ + if (fstatfs(dstfd, &s) == -1) + goto out; + + if (s.f_type != /* CIFS */ 0xFF534D42u) + goto out; + } + + err = 0; +#else /* !__linux__ */ goto out; +#endif /* !__linux__ */ } #ifdef FICLONE