Skip to content
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

dd: fix GNU test 'dd/skip-seek-past-dev' #4527

Merged
merged 3 commits into from
Sep 24, 2023
Merged

Conversation

bbara
Copy link
Contributor

@bbara bbara commented Mar 18, 2023

The GNU test suggests that GNU's variant is trying to seek stdin/stdout s.t. it can abort early if the respective fd is seekable and does not have enough length to do the requested skip/seek.

Draft for now to signalize that I am working on it.
There are some small open points, e.g. recognize this better:

# dd bs=1 skip=10000000000000000 count=0 status=noxfer < /dev/sda1
dd: 'standard input': cannot skip: Invalid argument
0+0 records in
0+0 records out
# echo $?
1

vs

# echo "abcd" | dd bs=1 skip=5 count=0 status=noxfer
0+0 records in
0+0 records out
# echo $?
0

and obviously add tests :)

@bbara
Copy link
Contributor Author

bbara commented Mar 18, 2023

Because there are currently some attempts to work around the missing Rust feature to seek stdin/stdout/stderr, I found this open issue (actually a comment for another workaround implementation: rust-lang/rust#72802 (comment)).

I am currently not sure why skipping a non-seekable stdin does not return exit code 1:
echo "abcd" | dd bs=1 skip=5 count=0 status=noxfer
But I haven't checked the docu yet

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/dd/no-allocate is no longer failing!

@bbara bbara changed the title Draft: dd: fix GNU test 'dd/skip-seek-past-dev' dd: fix GNU test 'dd/skip-seek-past-dev' Mar 18, 2023
@bbara bbara marked this pull request as ready for review March 18, 2023 11:07
@jfinkels
Copy link
Collaborator

Hi @bbara, does this relate to issue #3008, for which pull request #4189 was just merged? I also just posted pull request #4542 to complement #4189.

@bbara
Copy link
Contributor Author

bbara commented Mar 20, 2023

@jfinkels: your implementation helps to fix my targeted problem. I had a similar implementation as you but observed a couple of illegal seeks and broken pipes. I think as long as there is no "safe Rust way" to do a seek on stdin/stdout, we should do some UNIX-specific workarounds to avoid the errors. I guess the correct way would be to find out if stdin is something "seekable" (e.g. a regular file), which could by done by using fstat on the fd of the stream, or using stat on /dev/std{in,out}.

I guess a stat would also help to solve my problem. My problem in short: if stdin or stdout has a known size, and we want so skip/seek past the size, a special error message is shown.

I tried to avoid to add too much UNIX-specific stuff, but I guess these problems/features are very UNIX-specific, therefore it should be ok.

Copy link
Member

@tertsdiepraam tertsdiepraam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to replicate the error messages you test for with GNU and I just get the error messages that we already have. So, I'm not sure this change makes sense? You mentioned some GNU test, which one is that? I'm using GNU coreutils 9.1 if that matters.

.set_stdout(File::open(at.plus("f")).unwrap())
.args(&["bs=1", "seek=10000000000000000000", "count=0", "status=noxfer"])
.run()
.stderr_is("dd: 'standard output': cannot seek: Invalid argument\n0+0 records in\n0+0 records out\n")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this case I get from GNU:

dd: invalid number: ‘10000000000000000000’: Value too large for defined data type

Which is more informative and has nothing to do with the length of the target file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, sorry was a little bit busy last week. The mentioned test is a "root test" and can be found here: tests/dd/skip-seek-past-dev.sh. It takes a block device as stdin/-out and therefore requires root. I try to "simulate" this by using a normal file, which unfortunately behaves not quite similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the error message should come when the position to skip to is "past" the device. My idea was to take a "high enough number" to skip past "every" device, but it seem to work not always as expected.

Copy link
Contributor Author

@bbara bbara Mar 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I will adapt my implementation to be more specific and only work with block devices.

.set_stdin(File::open(at.plus("f")).unwrap())
.args(&["bs=1", "skip=5", "count=0", "status=noxfer"])
.run()
.stderr_is("dd: 'standard input': cannot skip: Invalid argument\n0+0 records in\n0+0 records out\n")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this case I get:

dd: 'standard input': cannot skip to specified offset

@github-actions
Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/dd/nocache is no longer failing!
GNU test failed: tests/dd/nocache_eof. tests/dd/nocache_eof is passing on 'main'. Maybe you have to rebase?

@sylvestre
Copy link
Contributor

Sorry but Clippy is complaining about:

error: unreachable statement
    --> src\uu\dd\src/dd.rs:1119:5
     |
1117 |     return Ok(None);
     |     --------------- any code following this expression is unreachable
1118 |
1119 |     let ftype = file.metadata()?.file_type();
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement
     |
     = note: `-D unreachable-code` implied by `-D warnings`

error: unused variable: `ftype`
    --> src\uu\dd\src/dd.rs:1119:9
     |
1119 |     let ftype = file.metadata()?.file_type();
     |         ^^^^^ help: if this is intentional, prefix it with an underscore: `_ftype`
     |
     = note: `-D unused-variables` implied by `-D warnings`

error: unused variable: `file`
    --> src\uu\dd\src/dd.rs:1115:32
     |
1115 | fn try_get_len_of_block_device(file: &mut File) -> io::Result<Option<u64>> {
     |                                ^^^^ help: if this is intentional, prefix it with an underscore: `_file`

Copy link
Contributor

@sylvestre sylvestre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping ?

@bbara
Copy link
Contributor Author

bbara commented Jun 19, 2023

ping ?

Heyho, sorry for the late response.

I will look into run_ucmd_as_root() to try to set up a test working with a block device. Otherwise the implementation might currently not make really sense.

@bbara bbara force-pushed the dd-skip-seek branch 3 times, most recently from c7fdae1 to 45a328e Compare July 22, 2023 10:28
This enables to give path to files (as str) which are then used as either stdin or stdout.
These tests try to read or write past a block device, where the block device is either given as
stdin or stdout. It requires access to the block device, and therefore is executed as root. For now,
it is assumed that a block device "/dev/sda1" with a size smaller than 10000000000000000 exists.
@sylvestre
Copy link
Contributor

seems that it is fixed :)

it was failing with but it now passes:


2023-09-23T17:30:53.6409474Z 
2023-09-23T17:30:53.6409714Z FAIL: tests/dd/skip-seek-past-dev
2023-09-23T17:30:53.6415226Z =================================
2023-09-23T17:30:53.6415418Z 
2023-09-23T17:30:53.6418620Z --- err_ok	2023-09-23 17:30:34.758495511 +0000
2023-09-23T17:30:53.6419008Z +++ err	2023-09-23 17:30:23.706344514 +0000
2023-09-23T17:30:53.6422417Z @@ -1,3 +0,0 @@
2023-09-23T17:30:53.6425434Z -dd: 'standard input': cannot skip: Invalid argument
2023-09-23T17:30:53.6433997Z -0+0 records in
2023-09-23T17:30:53.6440725Z -0+0 records out
2023-09-23T17:30:53.6444320Z --- err_ok	2023-09-23 17:30:36.238516527 +0000
2023-09-23T17:30:53.6449599Z +++ err	2023-09-23 17:30:36.238516527 +0000
2023-09-23T17:30:53.6451600Z @@ -1,3 +1 @@
2023-09-23T17:30:53.6455605Z -dd: 'standard output': cannot seek: Invalid argument
2023-09-23T17:30:53.6456385Z -0+0 records in
2023-09-23T17:30:53.6459838Z -0+0 records out
2023-09-23T17:30:53.6460182Z +dd: failed to seek in output file: Invalid input
2023-09-23T17:30:53.6460697Z FAIL tests/dd/skip-seek-past-dev.sh (exit status: 1)
2023-09-23T17:30:53.6462780Z 

@sylvestre sylvestre merged commit e8b27d1 into uutils:main Sep 24, 2023
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.

4 participants