-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Get Unix file stats with LStat (instead of Stat) #5020
Conversation
int result = Interop.Sys.Stat(FullPath, out _fileStatus); | ||
// Use LStat (rather than Stat) so that information about a symbolic link will be retrieved | ||
// (rather than information about the target) if FullPath points to a symbolic link. | ||
int result = Interop.Sys.LStat(FullPath, out _fileStatus); |
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 will change other properties (such as file size and attributes like 'hidden') to report information on the symlink instead of the target file, also.
That seems desirable, though, because it looks like that matches the Windows behavior for those properties (FileInfo.Size on a sym link returns 0, for example).
cc @JeremyKuhne |
Sorry didn't mean to close |
Looks like the Jenkins task failed while trying to clone the repro. Is there something we can do to reset it? |
I'm not convinced this is something we want to change, at least not in this manner. The point of a symlink is to represent some other file. If you're given the path to a symlink and you open it, you're actually opening the file it points to. So with this change, for example, getting the length via FileInfo.Length and via File.Open(,,,,).Length will end up being different, right? And File.Exists (which also uses stat) could end up returning a different result? |
FileInfo.Length and File.Open length will differ, but that's consistent with our Windows behavior. This code: var info = new FileInfo(args[0]);
Console.WriteLine($"Info length: {info.Length}");
var file = File.Open(args[0], FileMode.Open);
Console.WriteLine($"File.Open length: {file.Length}");
Console.WriteLine($"Is symlink: {((info.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint).ToString()}"); Produces this output with Windows CoreFX bits currently (when args[0] is a sym link):
File.Exists also works as you predict on Windows (a link with its target moved/deleted still returns true). I see what you're saying about it being confusing that FileInfo and FileStream give different information for a file, but it's useful to be able to see both the linked file's information as well as information for the link itself. A very concrete case of this mattering is in dotnet/corefx#5015 (currently, it's not possible to determine whether a file/directory is a reparse point on Unix because the attributes returned are for the target file/directory). |
Ok. If this new behavior better matches what's on Windows, then I'm ok with it. Can you please add corresponding tests, though, both to a) lock in the behavior, and b) help demonstrate that the behavior matches between Windows and Unix? |
Yes, I agree adding some test cases here makes sense. I'll do that and update the PR. |
Thanks, @mjrousos. |
@mjrousos, are you still working on this? |
Yes, sorry for the slow progress. I should have a chance to add these tests at the end of the week. |
2a555a1
to
628384e
Compare
@stephentoub, I've added some test cases to confirm that FileInfo attributes reflect reparse point attributes, as expected (and that behavior is consistent across platforms). But it looks like the tests fail on Windows because creating symbolic links requires admin rights. The tests passed on my machine because I ran them from an elevated command prompt. Do you know of a way to make sure Jenkins runs tests elevated? If not, I'll just change the tests to only run in cases when they can successfully create sym links. |
We don't currently have a mechanism for that. |
Ah, bummer. I looked around but I think we can't create symbolic links on Windows without elevated permissions. So, I'll update the test cases to only execute if they can successfully create the links. I should have an update shortly. |
@stephentoub, after updating the tests to only run if symbolic links can be created, it looks like everything's passing. Please let me know if you have any other feedback. |
/// Creates a non-empty file | ||
/// </summary> | ||
/// <param name="path">Path to create the file at</param> | ||
protected void CreateNonEmptyFile(string path, int fileSize) |
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.
Can you use https://github.com/mjrousos/corefx/blob/UnixGetAttributesFix/src/Common/tests/System/IO/TempFile.cs instead of adding this?
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.
Yep; that looks like exactly what I want.
Thanks, @mjrousos. Overall looks good, though left some comments on the tests. |
Thanks, @stephentoub. I've updated the tests based on your feedback. |
{ | ||
get | ||
{ | ||
var path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); |
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.
GetTempFileName() returns a full path.
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.
Excellent; I'll lose the Path.Combine.
A few remaining things to address, then LGTM. Can you also squash this? Thanks for the fix. |
75dedd7
to
d7b709c
Compare
Stat was ignoring symbolic links (and getting stats for the target instead) which caused checks for whether or not a path was a sym link to fail on Unix. Fixes dotnet/corefx#5015
d7b709c
to
967cde5
Compare
Sure thing. I addressed the last couple issues and squashed. |
Thanks! |
Get Unix file stats with LStat (instead of Stat)
Get Unix file stats with LStat (instead of Stat) Commit migrated from dotnet/corefx@984cb7d
Stat was ignoring symbolic links (and getting stats for the target
instead) which caused checks for whether or not a path was a sym link
to fail on Unix.
Fixes dotnet/corefx#5015