xoofx / zio

A cross-platform abstract/virtual filesystem framework with many built-ins filesystems for .NET
BSD 2-Clause "Simplified" License
822 stars 61 forks source link

Symlinks? #74

Closed agocke closed 4 months ago

agocke commented 1 year ago

I'm trying to adopt a VFS for testing and my app uses symlinks. I didn't see support in the IFileSystem API. Curious whether that's desired.

In theory it could be part of a new ISymlinkFileSystem interface instead. That would presumably prevent things like ZipFileSystem from having to implement support (or throw, more likely).

xoofx commented 1 year ago

I didn't see support in the IFileSystem API. Curious whether that's desired.

Why not. Originally, the IFileSystem API was replicating what is accessible from System.IO.FileInfo and directory. I dunno if we have anything related to symlinks in more recent .NET?

I would probably avoid a new interface and add it to IFileSystem directly. The base FileSystem could throw for most of the implementations.

agocke commented 1 year ago

File.CreateSymbolicLink

Ellested commented 7 months ago

I found some stuff in my extensions that deals with this, using a mount file system.

        public static void MountSymlinkedDirectories(this MountFileSystem fs)
        {
            var dirs = fs.EnumerateDirectoryEntries("/", "*", SearchOption.AllDirectories);
            var symlinkDirs = dirs.Where(d => d.Attributes.HasFlag(FileAttributes.ReparsePoint)).ToList();

            foreach (var sd in symlinkDirs)
            {
                var systemPath = ResolveSymlinkedSystemPath(fs, sd.FullName);
                var slfs = CreatePhysicalSubFileSystem(systemPath);
                fs.Mount(sd.FullName, slfs);
            }
        }

        public static string ResolveSymlinkedSystemPath(this IFileSystem fs, UPath path)
        {
            var systemPath = fs.ConvertPathToInternal(path);
            var di = new DirectoryInfo(systemPath);
            return di.ResolveLinkTarget(true).FullName;
        }

        public static IFileSystem CreatePhysicalSubFileSystem(string systemPath)
        {
            var p = new PhysicalFileSystem();
            var subFilePath = p.ConvertPathFromInternal(systemPath);
            return new SubFileSystem(p, subFilePath);
        }