-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
cat: Fix reporting "input file is output file" error when outputting to an input file #8025
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
Conversation
5aca32b
to
d7d9c70
Compare
GNU testsuite comparison:
|
could you please add a test to make sure we don't regress? thanks |
@sylvestre I thought that this PR would make the GNU test These test cases fail: # Initialize files
$ echo x >fx
$ echo x >fx
$ cat fx fy >fxy
$ cat fx >fxy1
$ cat fx >fxy2
# Run `cat` commands
$ cat - fy <fxy1 1<>fxy1
cat: -: input file is output file
$ cat fxy2 fy 1<>fxy2
cat: fxy2: input file is output file
# Test expectations
$ diff fxy fxy1
1d0
< x
$ diff fxy fxy2
1d0
< x The $ target/debug/cat - fy <fxy1 1<>fxy1
$ diff fxy fxy1
1c1
< x
---
> y I would expect the GNU test to diff the |
@sylvestre I added the |
088684a
to
6ba134f
Compare
GNU testsuite comparison:
|
The newer version of GNU |
45e57e6
to
48ff58b
Compare
GNU testsuite comparison:
|
48ff58b
to
fae6feb
Compare
fae6feb
to
aaa8f68
Compare
GNU testsuite comparison:
|
The |
994c809
to
ba4d7d8
Compare
if !is_same_file_by_path(input, output) { | ||
return false; | ||
} | ||
|
||
// Check if the output file is empty | ||
FileInformation::from_file(output) | ||
.map(|info| info.file_size() > 0) | ||
.unwrap_or(false) |
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 would have liked to do the same thing as with Unix, but unfortunately, the FileInformation
objects were not equal when the same file was used as the input and output in Windows. Even their file indexes were different. I could not figure out a simpler way to verify if the files are the same than to use Win32 API to carve the file paths from the handles using GetFinalPathNameByHandleW
. I am open to suggestions on a better way to do this.
The corresponding Unix code for a reference:
let Ok(input_info) = FileInformation::from_file(input) else {
return false;
};
let Ok(output_info) = FileInformation::from_file(output) else {
return false;
};
if input_info != output_info || output_info.file_size() == 0 {
return false;
}
|
||
/// An unsafe overwrite occurs when the same file is used as both stdin and stdout | ||
/// and the stdout file is not empty. | ||
pub fn is_unsafe_overwrite<I: AsHandleRef, O: AsHandleRef>(input: &I, output: &O) -> bool { |
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.
This function differs from the Unix version in that it does not attempt to determine when a file is safe to be overwritten, namely, when the input handle is pointing to an earlier or the same position of the file as the output handle. I also could not figure out an easy way of determining if the file handle is opened for append, like the O_APPEND
flag in Unix.
GNU testsuite comparison:
|
great work! :) |
fc8dfe3
to
a39780b
Compare
GNU testsuite comparison:
|
fdc9d02
to
b2b9c99
Compare
GNU testsuite comparison:
|
GNU testsuite comparison:
|
Remove check if we are appending from stdin to a file. The GNU
cat
command reports the "input file is output file" whenever outputting to a file that was used as input for the command. There are other ways to output to a file than appending.This PR fixes the rest of the test cases from
cat-self.sh
:fixes: #7284