Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Get Unix file stats with LStat (instead of Stat) #5020

Merged
merged 1 commit into from
Jan 14, 2016

Conversation

mjrousos
Copy link
Member

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

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);
Copy link
Member Author

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).

@weshaggard
Copy link
Member

cc @JeremyKuhne

@weshaggard
Copy link
Member

Sorry didn't mean to close

@mjrousos
Copy link
Member Author

Looks like the Jenkins task failed while trying to clone the repro. Is there something we can do to reset it?

@stephentoub
Copy link
Member

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?

@mjrousos
Copy link
Member Author

mjrousos commented Jan 4, 2016

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):

Info length: 0
File.Open length: 8718
Is symlink: True

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).

@stephentoub
Copy link
Member

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?

@mjrousos
Copy link
Member Author

mjrousos commented Jan 4, 2016

Yes, I agree adding some test cases here makes sense. I'll do that and update the PR.

@stephentoub
Copy link
Member

Thanks, @mjrousos.

@stephentoub
Copy link
Member

@mjrousos, are you still working on this?

@mjrousos
Copy link
Member Author

Yes, sorry for the slow progress. I should have a chance to add these tests at the end of the week.

@mjrousos mjrousos force-pushed the UnixGetAttributesFix branch 2 times, most recently from 2a555a1 to 628384e Compare January 14, 2016 04:31
@mjrousos
Copy link
Member Author

@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.

@stephentoub
Copy link
Member

Do you know of a way to make sure Jenkins runs tests elevated?

We don't currently have a mechanism for that.

@mjrousos
Copy link
Member Author

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.

@mjrousos
Copy link
Member Author

@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)
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

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.

@stephentoub
Copy link
Member

Thanks, @mjrousos. Overall looks good, though left some comments on the tests.

@mjrousos
Copy link
Member Author

Thanks, @stephentoub. I've updated the tests based on your feedback.

{
get
{
var path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
Copy link
Member

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.

Copy link
Member Author

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.

@stephentoub
Copy link
Member

A few remaining things to address, then LGTM. Can you also squash this? Thanks for the fix.

@mjrousos mjrousos force-pushed the UnixGetAttributesFix branch 2 times, most recently from 75dedd7 to d7b709c Compare January 14, 2016 20:04
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
@mjrousos mjrousos force-pushed the UnixGetAttributesFix branch from d7b709c to 967cde5 Compare January 14, 2016 20:06
@mjrousos
Copy link
Member Author

Sure thing. I addressed the last couple issues and squashed.

@stephentoub
Copy link
Member

Thanks!

stephentoub added a commit that referenced this pull request Jan 14, 2016
Get Unix file stats with LStat (instead of Stat)
@stephentoub stephentoub merged commit 984cb7d into dotnet:master Jan 14, 2016
@karelz karelz modified the milestone: 1.0.0-rtm Dec 3, 2016
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
Get Unix file stats with LStat (instead of Stat)

Commit migrated from dotnet/corefx@984cb7d
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants