-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
rm: rm -f should not fail #1329
Conversation
The reason for the observed behavior is that The msdos file system could be modified to accept |
bin/rm/rm.c
Outdated
@@ -338,7 +338,7 @@ rm_file(char **argv) | |||
if (Wflag) { | |||
sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR; | |||
} else { | |||
if (!fflag || errno != ENOENT) { | |||
if (!fflag && errno != ENOENT) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stesser basically, either:
if (!fflag || (errno != ENOENT && errno != EINVAL)) {
Or better, modify the msdos file system to accept *
and ?
. The latter sounds like a better approach, although I have no idea how to do it. I'll have to look it up with it over the weekend. Thank you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can modify the msdos file system to return ENOENT for invalid file names, since I know that code after fixing a few long standing bugs:
diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c
index 2a90339d0878..9478196846d2 100644
--- a/sys/fs/msdosfs/msdosfs_lookup.c
+++ b/sys/fs/msdosfs/msdosfs_lookup.c
@@ -88,9 +88,13 @@ msdosfs_lookup_checker(struct msdosfsmount *pmp, struct vnode *dvp,
int
msdosfs_lookup(struct vop_cachedlookup_args *ap)
{
+ int error;
- return (msdosfs_lookup_ino(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL,
- NULL));
+ error = msdosfs_lookup_ino(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL,
+ NULL);
+ if (error == EINVAL)
+ error = ENOENT;
+ return (error);
}
struct deget_dotdot {
The result is as expected, rm -f
succeeds without reporting an error:
# rm -f /boot/efi/foo*
# echo $?
0
But this patch does also affect, e.g., ls -l
:
# ls -l /boot/efi/foo*
ls: /boot/efi/foo*: No such file or directory
Without the patch, the result has been ls: /boot/efi/foo*: Invalid argument
, and the behavior with the patch is similar to what would be returned on UFS.
But another side effect is that mv
also returns No such file or directory
instead of Invalid argument
when the target file name is invalid:
# touch /boot/efi/A.DAT
# mv /boot/efi/A.DAT /boot/efi/B*.DAT
mv: rename /boot/efi/A.DAT to /boot/efi/B*.DAT: No such file or directory
This is unexpected and might break existing code that uses rename()
or scripts that check the result of mv
!
On UFS, renaming to B*.DAT
would work and would result in a file with an asterisk in its name (as it is valid in filenames on UFS).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! At a first glance, I like it (even for mv
)!
Fix an inverted logic bug, so the -f flag is always honored. When trying to forcefully (-f) remove a nonexistent file on an msdosfs mount, an error is thrown: # rm -f /boot/efi/foo* rm: /boot/efi/foo*: Invalid argument
Revert commit 579add0138e351b3b4535f2c51c3e12fad8de0be. It was an extremely aggressive commit, almost tantrumical, to prove a corner case on MS-DOS fs mounts.
6f1ee45
to
21f41cf
Compare
I have updated the commits accordingly, to let this soak in/gather more feedback. Nobody wants breaking changes (even if they are for a greater good). The tests have no real relevance, and should be dropped. They are here just for convenience: /usr/tests/bin # kyua debug rm/rm_test:f_flag_msdosfs ; \
kyua debug ls/ls_tests:l_flag_nonexistent_msdosfs ; \
kyua debug mv/mv_test:wildcard_msdosfs Thank you! |
Note to self: The The On NetBSD: # touch /boot/efi/A.DAT
# mv /boot/efi/a.dat /boot/efi/B*.DAT
# ls /boot/efi
b~1.dat on OpenBSD/macOS: # touch /boot/efi/A.DAT
# mv /boot/efi/A.dat /boot/efi/B*.DAT
# ls /boot/efi
B*.DAT On Linux (Debian): # touch /boot/efi/A.DAT
# mv /boot/efi/A.DAT /boot/efi/B*.DAT
mv: cannot move '/boot/efi/A.DAT' to a subdirectory of itself, '/boot/efi/B*.DAT' |
So what's the status of this? Ready? |
Let's wait for @stesser , otherwise, please close it, and I'll try to document somehow that this is something that can happen on MS-DOS mounts on FreeBSD. |
See my comment above:
This is caused by Seems that different operating systems behave very different in that case (as you showed in your comment above), this might not be an issue. I doubt that it will cause existing scripts or programs to fail in unepected ways, but if they did, it might be hard to identify this change as the cause. But since the change affects namei() and functions that call it, more vnode operations will return The rename(2) man page mentions both
Maybe the case of a target name not allowed on some file system should be added, e.g. one of:
If changing the return code of |
Since GitHub is not (at the moment) a bug-reporting platform, I propose moving this conversation to bug report 281033. The bug report contains the three disposable tests with the desired output. Thank you for elucidating on the topic! |
For completeness, this was landed as 0b2c159. Thank you! |
The patch that landed was better than what I had proposed. |
It is a valid and reasonable request. I’ll come up with a patch. Thanks! |
This is a first draft. I just want to avoid using the word invalid to describe a condition in
Thoughts? I based my words taking a cue from open from The Open Group Issue 8. |
Fix an inverted logic bug, so the
-f
flag is always honored.When trying to forcefully (
-f
) remove a nonexistent file on anmsdosfs
mount, an error is thrown:It looks like it might be another issue underneath, and maybe other logic "bugs" in the file. At any rate, a more thorough explanation of when
rm -f
can fail (non-POSIX-compliant, etc.). Technically, only the penultimate case is needed to fix the issue.This pull request can be taken as a bug report, should it be the case.