-
Notifications
You must be signed in to change notification settings - Fork 675
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
Implment linkat #1101
Implment linkat #1101
Conversation
test/test_unistd.rs
Outdated
linkat(Some(dirfd), symoldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap(); | ||
|
||
let err_result = readlink(&newfilepath, &mut buf).unwrap_err(); | ||
assert!(err_result == Error::Sys(Errno::EINVAL)); |
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.
Could not find a convenient way to tell I've created a hard link and not another soft link so I simply try to follow the hardlink and when that fails check the error.
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.
It's easy to tell. Just stat
both old file and new file.
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.
Thanks ... yesterday I googled "rust stat file" and using std::fs::metadata came up. When I compared the metadata for the original file, the symlink, and the hardlink the metadata all looked the same. I then found something for libc::stat but it was describing a struct. I didn't notice there was also a function call of the same name available. Following rust-lang/libc#403 I've been able to see the filetype and number of hardlinks for a file through stat and will post this update.
4a9c4fe
to
5002f7a
Compare
@asomer Another example where mac is doing something different than all other targets. You have any thoughts on what flag it is expecting? I am testing not following the symlink. http://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html Says to use AT_SYMLINK_FOLLOW If I want to test creating a hardlink to the symbolic link I simply don't add this flag. On my linux host I can pass 0 for example. In NIX I pass AtFlags::empty(). I found this first thread from a few years back that says it is not supported: And I couldn't find it here: But another link I see this reference here:
where it is said not assigning anything results in an error. Any comments on what I should be adding as a FLAG? The last sentence makes it sound like this is inconsistently supported on mac and that some systems will only accept this call if AT_SYMLINK_FOLLOW is passed to it? |
@asomer In this scenario can we just a check that allows ENOTSOP error or should I just get rid of this test all together and comment that NOSYMLINKFOLLOW is not supported for all targets? |
Since the OSX man page documents that |
Ok, make sense. What is the process for doing that .. I guess manually triggering this patch to be retested while omitting specific targets? |
Ahh .. I see a travis.yml. I'll try to modify that! |
4a45294
to
6b00bf6
Compare
Actually .. will
I see modifying the travis.xml would disable all tests for the target. I see I should just add an attribute based guard as is done on another test.
|
@asomers Ok, cool. Tests passed and/or were excluded as expected. It think this is ready but needs review. |
6b00bf6
to
820ab8c
Compare
Thanks ... Let me know if there is anything else. |
src/unistd.rs
Outdated
/// with file descriptor `olddirfd` instead of the current working directory and similiarly for | ||
/// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and | ||
/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created. | ||
/// The function shall fail if either olddirfd or newdirfd is None, returning ENOENT and EEXIST |
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.
WTF? No it shall not fail. That's not what will happen.
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.
WTF? No it shall not fail. That's not what will happen.
What should happen? The spec I am referring to is here: http://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html
Failing is language the spec uses in the ERRORS section to describe errors returned. i.e.
ERRORS
These functions shall fail if:
[EEXIST]
[ENOENT]
When I tested by inserting "None" at the calls in test_linkat_file, ENOENT and EEXIST were returned.
Please comment on what you think should happen. If failing with ENOENT and EEXIST is not correct behavior then an update to the patch is needed.
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.
What should happen when olddirfd
is None
is that you call libc::linkat
with the AT_FDCWD
argument, which the operating system interprets to mean that oldpath
is relative to the current directory. Similarly with newdirfd
.
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.
@asomers Ok .. I see, thanks. I saw this mentioned and read the spec to mean this special value could be passed in directly by the user. However in case of None, instead of returning an error, we could define behavior such that this value is used in this case as well. I'll make this update and use newdirfd as a reference. Thanks.
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.
No, Johnnie. The code that you wrote already uses AT_FDCWD
. How did you not notice that?
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.
Hi @asomers Revisit this patch .. to your last comment, code that I wrote doesn't use it but code that I call "at_rawfd" does. This is not seen unless you peak into the implementation of at_rawfd. But my comment was just to have a quick reply and thank you for your suggestion.. I did not peak into at_rawfd beforehand to see this and interpret this. Also keep in mind, for me when contributing some small functions and test cases for nix I am not only doing this to help nix and projects that use it, but also it is being done for me as a good introduction to Rust. That is to say interpreting Rust syntax and semantics is nowhere close to second nature yet for me so please do not read too much into things that may be obvious to you.
But to recap the change request, you initially asked if I could update the comments for linkat on what happens when None is passed as a file descriptor .. a good suggestion. To see, I modifying the test for test_linkat_file to observe what actually happens. In doing so, I saw an error was returned and wrote that in the comments, but only after reviewing the docs at opengroup.org and not seeing explicit direction on what should happen or any contradiction to what I actually observed. Your response ultimately was that AT_FDCWD should be passed, and in peeking into at_rawfd I see it already does this. So interpreting what this is supposed to mean I think I was misled by my testing experiment and should not have interpreted the returned errors the way I did. That said, I still am not sure why something like this fails:
Line: 620
linkat(None, oldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap();
or
Line: 620
linkat(Some(dirfd), oldfilename, None, newfilename, LinkatFlags::SymlinkFollow).unwrap();
fails even if I create a foo.txt in the cur directory (to cover the first example).
echo "foo" > foo.txt
cargo test test_linkat_file
Do you have insight into what I am missing here and how to test the behavior for None assuming the implementation in unistd.rs is correct?
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.
Do you know how to use rust-gdb and strace? If not, then you should learn those tools. They'll help you to debug your problem.
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.
@asomers Thanks for the suggestion. The comment has been updated. Perhaps the patch is good now, but let me know if you'd like more changes. Thanks.
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.
Hi @asmoers .. I am not sure the etiquette concerning who marks "Resolve conversation" for change requests such as this. Do you have more comment for this request?
820ab8c
to
9326d7e
Compare
@asomers The change must have been unknowingly reverted before I pushed. I believe the newline is gone now but I no longer see the conversation to close. Does that happen in the github UI when an issue such as a newline is resolved as expected? |
74046ca
to
a27248b
Compare
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.
How about a test that sets olddirfd
and newdirfd
to None
?
src/unistd.rs
Outdated
/// with file descriptor `olddirfd` instead of the current working directory and similiarly for | ||
/// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and | ||
/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created. | ||
/// If either olddirfd or newdirfd is None, AT_FDCWD is used respectively where pathname is then |
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.
Need backticks on this line. Also, "pathname" should be "oldpath" and/or "newpath".
test/test_unistd.rs
Outdated
assert!(newfilepath.exists()); | ||
} | ||
|
||
#[cfg(target_os = "freebsd")] |
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.
Why is this test restricted to FreeBSD?
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.
Hi @asmoers .. I am not sure the etiquette concerning who marks "Resolve conversation" for change requests such as this. Do you have more comment for this request?
99d58a3
to
b8ffb63
Compare
@asomers Thanks for the suggestions. I think they've been handled. In particular I added tests for the cases of setting olddirfd and newdirfd to None. I think the test cover the input as we'd like, but if you have something else in mind I can definitely make a change no problem. I also updated the CHANGELOG file. Let me know anything else you'd like to see. Thanks. |
src/unistd.rs
Outdated
/// with file descriptor `olddirfd` instead of the current working directory and similiarly for | ||
/// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and | ||
/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created. | ||
/// If either `olddirfd` or `newdirfd` is None, AT_FDCWD is used respectively where `oldpath` |
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.
Missing backticks for "None" and "AT_FDCWD"
src/unistd.rs
Outdated
/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created. | ||
/// If either `olddirfd` or `newdirfd` is None, AT_FDCWD is used respectively where `oldpath` | ||
/// and/or `newpath` is then interpreted relative to the current working directory of the calling | ||
/// process. If either `oldpath` or `newpath` is absolute, then dirfd is ignored. |
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.
Missing backticks for dirfd
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.
Ok. Guess I was only adding backticks for the parameter names. Thanks for the correction. Updated now.
b8ffb63
to
ea75be9
Compare
Where did all of the whitespace changes come from? They seem unrelated. If you're going to modify whitespace that's unrelated to your PR, it needs to be in a separate commit (not necessarily a separate PR). Also, though it's too late now, in the future please don't force-push until after review is complete and I ask you to squash. |
5f03caa
to
854ee25
Compare
Ok, will do. At some point I've changed IDE settings to remove trailing white spaces to adhere to standards for a different project. In that previous push I removed a few trailing whitespaces that existed for an unrelated function as you pointed out. In the latest commit I added the whitespace back. I am thinking that is the change you wanted but if it is not then please let me know. Thanks. And btw .. the force-push you see for the latest commit is just my text editor also refusing to allow me to keep trailing whitespace, so I had a few tries at it. |
Ok, it looks good. Now you can squash and force-push. |
2d22219
to
b83cb8c
Compare
This adds the linkat function which is part of POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html and widely implmented on Unix-Family platforms. Add back trailing whitespace removed on previous force push
b83cb8c
to
848825b
Compare
Ok, thanks a lot. Hopefully this is good to go. |
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.
bors r+
1101: Implment linkat r=asomers a=jlb6740 This adds the linkat function which is part of POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html and widely implmented on Unix-Family platforms. Co-authored-by: Johnnie Birch <45402135+jlb6740@users.noreply.github.com>
Build succeeded
|
This adds the linkat function which is part of POSIX:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html
and widely implmented on Unix-Family platforms.