+
Skip to content

Conversation

frendsick
Copy link
Contributor

@frendsick frendsick commented May 29, 2025

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:

cat - fy <fxy1 1<>fxy1
cat fxy2 fy 1<>fxy2

fixes: #7284

Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/tee (passes in this run but fails in the 'main' branch)

@sylvestre
Copy link
Contributor

could you please add a test to make sure we don't regress? thanks

@frendsick
Copy link
Contributor Author

@sylvestre I thought that this PR would make the GNU test cat-self.sh pass, but apparently not. What do you think, does the GNU test itself have a bug? As far as I can tell, the new version of the uutils cat behaves the same as GNU cat for each of its test cases.

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 diff commands are the same for both the GNU cat and the uutils cat commands after the patch introduced in this PR. With the version of the main branch, the uutils cat does not report the "input file is output file" error and produces the following diff:

$ target/debug/cat - fy <fxy1 1<>fxy1
$ diff fxy fxy1
1c1
< x
---
> y

I would expect the GNU test to diff the cat command's output files with the fx file, rather than fxy, as that matches the behavior of the GNU cat.

@frendsick
Copy link
Contributor Author

@sylvestre I added the test_write_to_read_write_self with the assumption that the current behavior is correct and that the GNU test tests/cat/cat-self.sh is wrong. Please review and give your opinion on this.

@frendsick frendsick force-pushed the fix/cat-output-is-input branch from 088684a to 6ba134f Compare May 29, 2025 10:19
Copy link

GNU testsuite comparison:

Skip an intermittent issue tests/misc/tee (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/misc/usage_vs_getopt (fails in this run but passes in the 'main' branch)

@frendsick
Copy link
Contributor Author

The newer version of GNU cat could behave differently. I will test it when I have the time. See #7284.

@frendsick frendsick marked this pull request as draft May 30, 2025 11:01
@frendsick frendsick force-pushed the fix/cat-output-is-input branch 2 times, most recently from 45e57e6 to 48ff58b Compare June 3, 2025 13:32
Copy link

github-actions bot commented Jun 3, 2025

GNU testsuite comparison:

Skip an intermittent issue tests/misc/stdbuf (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/misc/tee (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/timeout/timeout (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/cat/cat-self is no longer failing!

@frendsick frendsick force-pushed the fix/cat-output-is-input branch from 48ff58b to fae6feb Compare June 4, 2025 19:11
@frendsick frendsick force-pushed the fix/cat-output-is-input branch from fae6feb to aaa8f68 Compare June 4, 2025 19:12
Copy link

github-actions bot commented Jun 4, 2025

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/stdbuf (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/misc/tee (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/timeout/timeout (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/cat/cat-self is no longer failing!

@frendsick
Copy link
Contributor Author

The tests/cat/cat-self test is no longer failing.

@frendsick frendsick force-pushed the fix/cat-output-is-input branch from 994c809 to ba4d7d8 Compare June 4, 2025 21:13
@frendsick frendsick marked this pull request as ready for review June 4, 2025 21:14
Comment on lines +18 to +25
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)
Copy link
Contributor Author

@frendsick frendsick Jun 4, 2025

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 {
Copy link
Contributor Author

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.

Copy link

github-actions bot commented Jun 4, 2025

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/stdbuf (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/timeout/timeout (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/cat/cat-self is no longer failing!

@sylvestre
Copy link
Contributor

great work! :)

@frendsick frendsick force-pushed the fix/cat-output-is-input branch from fc8dfe3 to a39780b Compare June 5, 2025 12:28
@frendsick frendsick requested a review from sylvestre June 5, 2025 13:03
Copy link

github-actions bot commented Jun 5, 2025

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/tee (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/cat/cat-self is no longer failing!

@frendsick frendsick force-pushed the fix/cat-output-is-input branch from fdc9d02 to b2b9c99 Compare June 5, 2025 14:06
Copy link

github-actions bot commented Jun 5, 2025

GNU testsuite comparison:

Skip an intermittent issue tests/misc/stdbuf (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)
Congrats! The gnu test tests/cat/cat-self is no longer failing!

@frendsick frendsick requested a review from sylvestre June 6, 2025 08:16
Copy link

github-actions bot commented Jun 6, 2025

GNU testsuite comparison:

Skip an intermittent issue tests/misc/tee (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/timeout/timeout (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/cat/cat-self is no longer failing!

@sylvestre sylvestre merged commit 4d40671 into uutils:main Jun 6, 2025
74 checks passed
@frendsick frendsick deleted the fix/cat-output-is-input branch June 6, 2025 10:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cat: errors when first argument is open for reading and writing, but shouldn't

2 participants

点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载