runtime: .NET Core is missing suitable APIs for dealing with filesystems that contain symbolic links
Ref: https://github.com/aspnet/Home/issues/2774 for discovery point
.NET Core is missing suitable APIs for dealing with filesystems that contain symbolic links
FileInfo does not resolve symbolic links, leading to subtle bugs. There’s no API that gives information about the link target. There’s other problems with the existing APIs causing them to have trouble when you call Directory.EnumerateFileSystemEntries involving having to do not one but two stat calls for each node. Might as well resolve them all at once.
Proposed API surface:
// These are deliberately set to the *nix constant values where possible.
public enum FileTypes {
Missing = 0,
Fifo = 0010000,
CharacterDevice = 0020000,
Directory = 0040000,
BlockDevice = 0060000,
File = 010000,
SymbolicLink = 0120000,
Socket = 0140000,
SymbolicLinkMissingTarget = 0200000,
SymbolicLinkLoop = 0400000,
ReparsePoint = 01000000, // ReparsePoint attribute set but not a symbolic link
}
public struct FileNode {
public string Path { get; private set; }
public string FileName { get => System.IO.Path.GetFileName(Path); }
public DateTime LastAccessTime { get; private set; }
public DateTime LastAccessTimeUTC { get; private set; }
public DateTime LastWriteTime { get; private set; }
public DateTime LastWriteTimeUTC { get; private set; }
public DateTime LastChangeTime { get; private set; }
public DateTime LastChangeTimeUTC { get; private set; }
public FileAttributes Attributes { get; private set; }
public FileTypes FileNodeType { get; private set; }
public string SymbolicLinkTargetPath { get; private set; }
public bool Exists { get => FileNodeType != 0 }
FileNode(string path, bool resolvesymboliclink)
{
/* The general idea of this API is it doesn't throw; just gives the appropriate information You could probably put Cer.Success on it. */
Path = path;
bool statpermissiondenied;
if (resolvesymboliclink)
{
/* This code path would call CreateFile with only FILE_READ_ATTRIBUTES and then call GetFileInformationByHandle; on AccessDenied or PermissionDenied fall through below */
/* on unix this would be a stat() call */
}
/* This code path would call FindFirstFileEx to get the file information by name from the node attribute */
if (resolvesymboliclink && FileNodeType == FileTypes.SymbolicLink)
FileNodeType = 0;
}
/* Deserialization constructor */
FileNode(string path, FileTypes fileNodeType, FileAttributes Attributes, DateTime lastAccessTimeUTC, DateTime lastChangeTimeUTC, DateTime lastWriteTimeUTC, string symbolicLinkTargetPath);
}
public partial class File {
public static void CreateSymbolicLink(string path, string targetPath, bool targetisdirectory = false);
}
public partial class Directory {
// This one exists only code readability
// The idea is the programmer would normally only pass the third parameter if it was indirection from another layer of indirection, and otherwise would call File.CreateSymbolicLink to create a symbolic link to a file and Directory.CreateSymbolicLink to create a symbolic link to a directory
public static void CreateSymbolicLink(string path, string targetPath, bool targetisdirectory = true);
=> File.CreateSymbolicLink(path, targetPath, targetisdirectory);
}
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 6
- Comments: 26 (13 by maintainers)
Commits related to this issue
- Enable pooling for `async ValueTask/ValueTask<T>` methods (#26310) Today `async ValueTask/ValueTask<T>` methods use builders that special-case the synchronously completing case (to just return a `def... — committed to Dotnet-GitSync-Bot/corefx by stephentoub 5 years ago
- Enable pooling for `async ValueTask/ValueTask<T>` methods (#26310) Today `async ValueTask/ValueTask<T>` methods use builders that special-case the synchronously completing case (to just return a `def... — committed to dotnet/corefx by stephentoub 5 years ago
Hello, Is there any news on this ? at least a workaround to allow netcore application to follow symlinks ? It seems to be a basic feature on linux environment. Thanks
FileInfo, etc. are documented to work on the link itself.
CreateFiledoesn’t open the symlink itself, it opens the target. While I agree that can be confusing, it works in most cases. Your example isn’t safe even if they were aligned better. Even if you checkExistson the target there is a risk the file will be gone when you try to create the FileStream around it, let alone any number of other IO related errors (access issues, volume dismounts, etc.).We could potentially add a
TargetExistsor something like that to FileInfo/DirectoryInfo. (Or maybeFileInfo Target { get; }that gives you backthisor the link target if applicable.)I absolutely agree that we need better symbolic link support, but I don’t feel depreciating existing APIs is the way to do it.
@xp-1000 : Here’s something to play with
https://github.com/joshudson/Emet/tree/master/FileSystems
I published Emet.FileSystems 0.0.1-alpha1 on nuget; it’s still verifying right now.
In PowerShell we already dynamically add a Target property to FileInfo/DirectoryInfo objects.