-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fs.copyFile fails with permission denied when source is read-only #37284
Comments
It seems to be working for ❯ cat test.js
const fs = require('fs');
fs.copyFileSync('a/file', 'b/file');
❯ mkdir a b
❯ touch a/file
❯ ls -l a/file
-rw-r--r-- 1 raisinten raisinten 0 Feb 9 19:35 a/file
❯ chmod -w a/file
❯ node test.js
❯ ls -l a/file b/file
-r--r--r-- 1 raisinten raisinten 0 Feb 9 19:35 a/file
-r--r--r-- 1 raisinten raisinten 0 Feb 9 19:35 b/file |
I just tried it on 15.2.0 and I still get the same error. I understand that it unfortunately makes this much harder to reproduce on a test environment. EDIT: My bad, it does work on 12.18.4 but fails with 15.2.0 with an NFS mount. A file does get created despite the thrown exception, but it has no data in it (on a cephfs mount, no file is created). |
I believe this should be reported to libuv too because internally, this calls Lines 1802 to 1803 in ad3ebed
According to the warning in the docs for the function, the destination path cc @nodejs/fs |
That's what I originally thought as I dug a bit into the internals, but I'm not sure then why the behavior changed between 12.18.4 and 12.19.0, unless libuv is statically linked to nodejs. |
I think, I understand what's going on. libuv/libuv#2352 introduced
This particular check was ignored. |
copy_file_range will not work when in_fd and out_fd are not on the same mounted filesystem (pre Linux 5.3). Fixes: nodejs/node#37284 Refs: https://www.man7.org/linux/man-pages/man2/copy_file_range.2.html#ERRORS
Potential fix: libuv/libuv#3108 |
copy_file_range will not work when in_fd and out_fd are not on the same mounted filesystem (pre Linux 5.3). Refs: nodejs/node#37284 PR-URL: #3108 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Richard Lau <rlau@redhat.com>
@kakaroto does this issue still exist in |
Sorry for my lack of availability. Managing a startup is exhausting! I'm not sure that this would be the cause, since EXDEV seems to be about "a different mount" but not be about whether or not the source file is read-only or not. The error doesn't happen if the source file is read-write, only if it's read-only, so I think EXDEV is unrelated. The error shown is also with Regardless, thank you for looking into that and providing that EXDEV fix so quickly. Unfortunately, I just tested with v15.9.0 and the issue is still happening. |
@kakaroto I have reported your issue at libuv: libuv/libuv#3117 |
Thank you. I appreciate that. |
copy_file_range will not work when in_fd and out_fd are not on the same mounted filesystem (pre Linux 5.3). Refs: nodejs/node#37284 PR-URL: libuv#3108 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Richard Lau <rlau@redhat.com>
Trying to copy a read-only file onto a ceph-fuse filesystem fails, returning an `EACCES` error. This happens when the destination doesn't exist yet, and a new file is created. By checking that the error matches, and that the destination file is empty, we can fix this issue while waiting for a proper Ceph fix to be upstreamed. Fixes: libuv#3919 Refs: nodejs/node#37284 Refs: libuv#3117 Refs: libuv#3322
Trying to copy a read-only file onto a ceph-fuse filesystem fails, returning an `EACCES` error. This happens when the destination doesn't exist yet, and a new file is created. By checking that the error matches, and that the destination file is empty, we can fix this issue while waiting for a proper Ceph fix to be upstreamed. Fixes: #3919 Refs: nodejs/node#37284 Refs: #3117 Refs: #3322
What steps will reproduce the bug?
if I have an external mount (in my case a cephfs cluster mounted using
ceph-fuse
), then copying a file into it will fail with permission denied if the source file is read-only.Simple code to reproduce the issue :
Doing a
touch /tmp/foo && chmod -w /tmp/foo
before running the script will allow you to reproduce the error. The above code will fail as long as the source file is read-only, even if the file can be copied in the shell.(note, it might work with an NFS mount or some other type of mount, but have only tested with my cephfs mount. A local ext4fs mount does not seem to be affected by the problem).
Also note that this works with Node 12.18.4. I actually noticed this issue a little while ago when I reinstalled one of my systems, and ended up with node 12.19.0 and my app started failing to copy files from a read-only file system and I was forced to downgrade to 12.18.3 where it was known to be working as expected. Today, I confirmed the bug is still there in node 14.15.4.
Using this command
docker run --rm -it -v /ceph-mount/:/ceph-mount node:12.19.0-alpine /bin/sh
to run node then pasting these commands in it will show the problem :How often does it reproduce? Is there a required condition?
100% reproducible on node 12.19.0 up to 14.15.4, 0% reproducible on node 12.18.4
What is the expected behavior?
the
fs.copyFile
should be able to succeed in copying the file as long as the destination folder is writable.What do you see instead?
The output is :
Here are screenshots showing the above running on node 12.19.0 as well as 12.18.4 to prove that the bug was introduced in the 12.19.x branch :
And a screenshot showing it with node 14.15.4 proving that a
cp
in the shell works as well (this is on another system, the/forge-vtt-dev/
folder is the cephfs mount):This also shows a second bug where it's unable to overwrite the file if it already exists, and I'm about to file another issue for it.
The text was updated successfully, but these errors were encountered: