Added Storage access framework, DiscUtils More of Zio, Fixed Dispose and internal function UnixPath.SetPath
This commit is contained in:
parent
60a1f8e7d3
commit
1f3f1c9b89
|
@ -15,6 +15,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tesses.VirtualFilesystem.Lo
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tesses.VirtualFilesystem.Zio", "Tesses.VirtualFilesystem.Zio\Tesses.VirtualFilesystem.Zio.csproj", "{F30FD55D-194C-437E-AAD2-6E1E0FEEF1C2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tesses.VirtualFilesystem.DiscUtils", "Tesses.VirtualFilesystem.DiscUtils\Tesses.VirtualFilesystem.DiscUtils.csproj", "{D399E2F3-B852-443E-8117-4B715EB84953}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tesses.VirtualFilesystem.Saf", "Tesses.VirtualFilesystem.Saf\Tesses.VirtualFilesystem.Saf.csproj", "{61FADB48-263C-494E-A564-A477B0D8C3F3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -48,5 +52,13 @@ Global
|
|||
{F30FD55D-194C-437E-AAD2-6E1E0FEEF1C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F30FD55D-194C-437E-AAD2-6E1E0FEEF1C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F30FD55D-194C-437E-AAD2-6E1E0FEEF1C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D399E2F3-B852-443E-8117-4B715EB84953}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D399E2F3-B852-443E-8117-4B715EB84953}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D399E2F3-B852-443E-8117-4B715EB84953}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D399E2F3-B852-443E-8117-4B715EB84953}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{61FADB48-263C-494E-A564-A477B0D8C3F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{61FADB48-263C-494E-A564-A477B0D8C3F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{61FADB48-263C-494E-A564-A477B0D8C3F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{61FADB48-263C-494E-A564-A477B0D8C3F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -488,7 +488,7 @@ namespace Tesses.VirtualFilesystem
|
|||
|
||||
}
|
||||
|
||||
public interface IVirtualWatcher
|
||||
public interface IVirtualWatcher : IDisposable
|
||||
{
|
||||
|
||||
event EventHandler<VirtualWatcherChangedArgs> Changed;
|
||||
|
@ -527,6 +527,7 @@ namespace Tesses.VirtualFilesystem
|
|||
/// in <see cref="Path"/>.
|
||||
/// </summary>
|
||||
bool IncludeSubdirectories { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class VirtualWatcherRenamedEventArgs : VirtualWatcherChangedArgs
|
||||
|
@ -871,7 +872,10 @@ namespace Tesses.VirtualFilesystem
|
|||
{
|
||||
pa.Append($"/{_parts[i]}");
|
||||
}
|
||||
if(pa.Length > 0)
|
||||
_path = pa.ToString();
|
||||
else
|
||||
_path = "/";
|
||||
}
|
||||
public UnixPath(UnixPath path1)
|
||||
{
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
<PackageId>Tesses.VirtualFilesystem.Base</PackageId>
|
||||
<Author>Mike Nolan</Author>
|
||||
<Company>Tesses</Company>
|
||||
<Version>1.0.0</Version>
|
||||
<AssemblyVersion>1.0.0</AssemblyVersion>
|
||||
<FileVersion>1.0.0</FileVersion>
|
||||
<Version>1.0.1</Version>
|
||||
<AssemblyVersion>1.0.1</AssemblyVersion>
|
||||
<FileVersion>1.0.1</FileVersion>
|
||||
<Description>Another VirtualFilesystem for .NET</Description>
|
||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using DiscUtils;
|
||||
using Tesses.VirtualFilesystem;
|
||||
using Tesses.VirtualFilesystem.Filesystems;
|
||||
|
||||
namespace Tesses.VirtualFilesystem.Filesystems
|
||||
{
|
||||
public class DiscUtilsFilesystem : SyncFileSystem
|
||||
{
|
||||
IFileSystem fs;
|
||||
public DiscUtilsFilesystem(IFileSystem fs)
|
||||
{
|
||||
this.fs = fs;
|
||||
}
|
||||
public override string ConvertPathFromUnixPath(UnixPath path)
|
||||
{
|
||||
return path.Path.Replace("/","\\");
|
||||
}
|
||||
public override UnixPath ConvertPathToUnixPath(string path)
|
||||
{
|
||||
return new UnixPath(path.Replace("\\","/"));
|
||||
}
|
||||
public override void CreateDirectory(UnixPath directory)
|
||||
{
|
||||
fs.CreateDirectory(ConvertPathFromUnixPath(directory));
|
||||
}
|
||||
|
||||
public override void DeleteDirectory(UnixPath path)
|
||||
{
|
||||
fs.DeleteDirectory(ConvertPathFromUnixPath(path));
|
||||
}
|
||||
|
||||
public override void DeleteFile(UnixPath path)
|
||||
{
|
||||
fs.DeleteFile(ConvertPathFromUnixPath(path));
|
||||
}
|
||||
|
||||
public override bool DirectoryExists(UnixPath path)
|
||||
{
|
||||
return fs.DirectoryExists(ConvertPathFromUnixPath(path));
|
||||
}
|
||||
|
||||
public override IEnumerable<UnixPath> EnumerateFileSystemEntries(UnixPath path)
|
||||
{
|
||||
foreach(var item in fs.GetFileSystemEntries(ConvertPathFromUnixPath(path)))
|
||||
{
|
||||
yield return ConvertPathToUnixPath(item);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool FileExists(UnixPath path)
|
||||
{
|
||||
return fs.FileExists(ConvertPathFromUnixPath(path));
|
||||
}
|
||||
|
||||
public override DateTime GetCreationTime(UnixPath path)
|
||||
{
|
||||
return fs.GetCreationTime(ConvertPathFromUnixPath(path));
|
||||
}
|
||||
|
||||
public override DateTime GetLastAccessTime(UnixPath path)
|
||||
{
|
||||
return fs.GetLastAccessTime(ConvertPathFromUnixPath(path));
|
||||
}
|
||||
|
||||
public override DateTime GetLastWriteTime(UnixPath path)
|
||||
{
|
||||
return fs.GetLastWriteTime(ConvertPathFromUnixPath(path));
|
||||
}
|
||||
|
||||
public override void MoveDirectory(UnixPath src, UnixPath dest)
|
||||
{
|
||||
fs.MoveDirectory(ConvertPathFromUnixPath(src),ConvertPathFromUnixPath(dest));
|
||||
}
|
||||
|
||||
public override void MoveFile(UnixPath src, UnixPath dest)
|
||||
{
|
||||
fs.MoveFile(ConvertPathFromUnixPath(src),ConvertPathFromUnixPath(dest));
|
||||
}
|
||||
|
||||
public override Stream Open(UnixPath path, FileMode mode, FileAccess access, FileShare share)
|
||||
{
|
||||
return fs.OpenFile(ConvertPathFromUnixPath(path),mode,access);
|
||||
}
|
||||
|
||||
public override void SetCreationTime(UnixPath path, DateTime time)
|
||||
{
|
||||
fs.SetCreationTime(ConvertPathFromUnixPath(path),time);
|
||||
}
|
||||
|
||||
public override void SetLastAccessTime(UnixPath path, DateTime time)
|
||||
{
|
||||
fs.SetLastAccessTime(ConvertPathFromUnixPath(path),time);
|
||||
}
|
||||
|
||||
public override void SetLastWriteTime(UnixPath path, DateTime time)
|
||||
{
|
||||
fs.SetLastWriteTime(ConvertPathFromUnixPath(path),time);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Tesses.VirtualFilesystem.Extensions\Tesses.VirtualFilesystem.Extensions.csproj" />
|
||||
<ProjectReference Include="..\Tesses.VirtualFilesystem\Tesses.VirtualFilesystem.csproj" />
|
||||
<ProjectReference Include="..\Tesses.VirtualFilesystem.Base\Tesses.VirtualFilesystem.Base.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DiscUtils" Version="0.16.13" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\README.md" Pack="true" PackagePath="\"/>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>Tesses.VirtualFilesystem.DiscUtils</PackageId>
|
||||
<Author>Mike Nolan</Author>
|
||||
<Company>Tesses</Company>
|
||||
<Version>1.0.0</Version>
|
||||
<AssemblyVersion>1.0.0</AssemblyVersion>
|
||||
<FileVersion>1.0.0</FileVersion>
|
||||
<Description>Another VirtualFilesystem for .NET</Description>
|
||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<PackageTags>VFS, Filesystem, VirtualFilesystem</PackageTags>
|
||||
<RepositoryUrl>https://gitlab.tesses.net/tesses50/tesses-vfs</RepositoryUrl>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
</Project>
|
|
@ -165,6 +165,11 @@ namespace Tesses.VirtualFilesystem.Filesystems
|
|||
public event EventHandler<VirtualWatcherChangedArgs> Deleted;
|
||||
public event EventHandler<VirtualWatcherRenamedEventArgs> Renamed;
|
||||
public event EventHandler<ErrorEventArgs> Error;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.watcher.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public override IVirtualWatcher WatchDirectory(UnixPath dir)
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
<PackageId>Tesses.VirtualFilesystem.Local</PackageId>
|
||||
<Author>Mike Nolan</Author>
|
||||
<Company>Tesses</Company>
|
||||
<Version>1.0.0</Version>
|
||||
<AssemblyVersion>1.0.0</AssemblyVersion>
|
||||
<FileVersion>1.0.0</FileVersion>
|
||||
<Version>1.0.1</Version>
|
||||
<AssemblyVersion>1.0.1</AssemblyVersion>
|
||||
<FileVersion>1.0.1</FileVersion>
|
||||
<Description>Another VirtualFilesystem for .NET</Description>
|
||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
|
|
|
@ -0,0 +1,510 @@
|
|||
using Android.Content;
|
||||
using Tesses.VirtualFilesystem;
|
||||
using Android.App;
|
||||
using Android.Content.PM;
|
||||
using AndroidX.DocumentFile.Provider;
|
||||
using Tesses.VirtualFilesystem.Extensions;
|
||||
namespace Tesses.VirtualFilesystem.Filesystems;
|
||||
|
||||
|
||||
public class SAFFileSystem : SyncFileSystem
|
||||
{
|
||||
public const int RequestCode = 1447775022;
|
||||
public const string SharedPreferencesFile = "tesess_vfs";
|
||||
public static void RequestDirectory(Activity app,bool canwrite=true,bool presistant=false,int reqCode=RequestCode)
|
||||
{
|
||||
Intent intent = new Intent(Intent.ActionOpenDocumentTree);
|
||||
intent.AddFlags(ActivityFlags.GrantReadUriPermission|(canwrite? ActivityFlags.GrantWriteUriPermission : 0)|(presistant?ActivityFlags.GrantPersistableUriPermission:0));
|
||||
app.StartActivityForResult(intent,reqCode);
|
||||
}
|
||||
|
||||
public static SAFFileSystem? GetSAFFromResponse(Context? app,Intent? intent)
|
||||
{
|
||||
if(app == null || intent == null) return null;
|
||||
var uri=intent.Data;
|
||||
if(uri != null)
|
||||
{
|
||||
return new SAFFileSystem(uri,app);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static SAFFileSystem? GetSAFFromResponsePresistant(Context? app,Intent? intent,string key)
|
||||
{
|
||||
if(app == null || intent == null) return null;
|
||||
var uri=intent.Data;
|
||||
if(uri != null)
|
||||
{
|
||||
var r = app?.ContentResolver;
|
||||
if(r == null) return null;
|
||||
var rw = intent.Flags & (ActivityFlags.GrantReadUriPermission | ActivityFlags.GrantWriteUriPermission);
|
||||
r.TakePersistableUriPermission(uri,rw);
|
||||
var app2=app?.CreatePackageContext(app.PackageName,0);
|
||||
var sharedPrefs=app2?.GetSharedPreferences(SharedPreferencesFile,FileCreationMode.Private);
|
||||
|
||||
sharedPrefs?.Edit()?.PutString(key,uri.ToString())?.Apply();
|
||||
|
||||
|
||||
return new SAFFileSystem(uri,app);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static void Revoke(Context? app,string key)
|
||||
{
|
||||
var app2=app?.CreatePackageContext(app.PackageName,0);
|
||||
var sharedPrefs=app2?.GetSharedPreferences(SharedPreferencesFile,FileCreationMode.Private);
|
||||
var res=sharedPrefs?.GetString(key,null);
|
||||
var r = app?.ContentResolver;
|
||||
if(r == null) return;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(res)) return;
|
||||
var uri = Android.Net.Uri.Parse(res);
|
||||
if(uri == null) return;
|
||||
r.ReleasePersistableUriPermission(uri,ActivityFlags.GrantReadUriPermission);
|
||||
sharedPrefs?.Edit()?.Remove(key)?.Apply();
|
||||
}
|
||||
|
||||
public static SAFFileSystem? GetSAFFromSharedStorage(Context? app,string key)
|
||||
{
|
||||
if(app == null) return null;
|
||||
var app2=app?.CreatePackageContext(app.PackageName,0);
|
||||
var sharedPrefs=app2?.GetSharedPreferences(SharedPreferencesFile,FileCreationMode.Private);
|
||||
var res=sharedPrefs?.GetString(key,null);
|
||||
|
||||
if(string.IsNullOrWhiteSpace(res)) return null;
|
||||
var uri = Android.Net.Uri.Parse(res);
|
||||
if(uri == null) return null;
|
||||
|
||||
return new SAFFileSystem(uri,app);
|
||||
}
|
||||
|
||||
|
||||
public SAFFileSystem(global::Android.Net.Uri uri,Context? ctx)
|
||||
{
|
||||
Uri = uri;
|
||||
Context = ctx;
|
||||
|
||||
}
|
||||
public global::Android.Net.Uri Uri {get;set;}
|
||||
public Context? Context {get;set;}
|
||||
|
||||
|
||||
public override void CreateDirectory(UnixPath directory)
|
||||
{
|
||||
if(Context != null && Uri != null)
|
||||
{
|
||||
|
||||
var dir = DocumentFile.FromTreeUri(Context,Uri);
|
||||
if(dir == null) return;
|
||||
|
||||
foreach(var item in directory.Parts)
|
||||
{
|
||||
var dir2= dir?.FindFile(item);
|
||||
if(dir2 != null)
|
||||
{
|
||||
if(!dir2.IsDirectory && !dir2.IsFile && !dir2.IsVirtual)
|
||||
{
|
||||
dir = dir2.CreateDirectory(item);
|
||||
}
|
||||
else if(dir2.IsDirectory)
|
||||
{
|
||||
dir = dir2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override void DeleteDirectory(UnixPath path)
|
||||
{
|
||||
if(Context != null && Uri != null)
|
||||
{
|
||||
|
||||
var dir = DocumentFile.FromTreeUri(Context,Uri);
|
||||
if(dir == null) return;
|
||||
|
||||
for(int i = 0;i<path.Parts.Length;i++)
|
||||
{
|
||||
var item = path.Parts[i];
|
||||
var dir2= dir?.FindFile(item);
|
||||
if(dir2 != null)
|
||||
{
|
||||
if(!dir2.IsDirectory && !dir2.IsFile && !dir2.IsVirtual)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(dir2.IsDirectory)
|
||||
{
|
||||
dir = dir2;
|
||||
if(i==path.Parts.Length -1)
|
||||
dir.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override void DeleteFile(UnixPath path)
|
||||
{
|
||||
|
||||
if(Context != null && Uri != null)
|
||||
{
|
||||
|
||||
var dir = DocumentFile.FromTreeUri(Context,Uri);
|
||||
if(dir == null) return;
|
||||
|
||||
for(int i = 0;i<path.Parts.Length;i++)
|
||||
{
|
||||
var item = path.Parts[i];
|
||||
var dir2= dir?.FindFile(item);
|
||||
if(dir2 != null)
|
||||
{
|
||||
if(!dir2.IsDirectory && !dir2.IsFile && !dir2.IsVirtual)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(dir2.IsDirectory)
|
||||
{
|
||||
dir=dir2;
|
||||
}
|
||||
else if(dir2.IsFile)
|
||||
{
|
||||
dir = dir2;
|
||||
if(i==path.Parts.Length -1)
|
||||
dir.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool DirectoryExists(UnixPath path)
|
||||
{
|
||||
if(path.IsRoot) return true;
|
||||
if(Context != null && Uri != null)
|
||||
{
|
||||
|
||||
var dir = DocumentFile.FromTreeUri(Context,Uri);
|
||||
if(dir == null) return false;
|
||||
|
||||
for(int i = 0;i<path.Parts.Length;i++)
|
||||
{
|
||||
var item = path.Parts[i];
|
||||
var dir2= dir?.FindFile(item);
|
||||
if(dir2 != null)
|
||||
{
|
||||
if(!dir2.IsDirectory && !dir2.IsFile && !dir2.IsVirtual)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(dir2.IsDirectory)
|
||||
{
|
||||
dir = dir2;
|
||||
if(i==path.Parts.Length -1)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override IEnumerable<UnixPath> EnumerateFileSystemEntries(UnixPath path)
|
||||
{
|
||||
if(Context != null && Uri != null)
|
||||
{
|
||||
|
||||
var dir = DocumentFile.FromTreeUri(Context,Uri);
|
||||
if(dir == null) yield break;
|
||||
|
||||
if(path.IsRoot)
|
||||
{
|
||||
foreach(var _item in dir.ListFiles())
|
||||
{
|
||||
yield return path / _item.Name;
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
for(int i = 0;i<path.Parts.Length;i++)
|
||||
{
|
||||
var item = path.Parts[i];
|
||||
var dir2= dir?.FindFile(item);
|
||||
if(dir2 != null)
|
||||
{
|
||||
if(!dir2.IsDirectory && !dir2.IsFile && !dir2.IsVirtual)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
else if(dir2.IsDirectory)
|
||||
{
|
||||
dir = dir2;
|
||||
if(i==path.Parts.Length -1)
|
||||
{
|
||||
foreach(var _item in dir2.ListFiles())
|
||||
{
|
||||
yield return path / _item.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool FileExists(UnixPath path)
|
||||
{
|
||||
if(Context != null && Uri != null)
|
||||
{
|
||||
|
||||
var dir = DocumentFile.FromTreeUri(Context,Uri);
|
||||
if(dir == null) return false;
|
||||
|
||||
for(int i = 0;i<path.Parts.Length;i++)
|
||||
{
|
||||
var item = path.Parts[i];
|
||||
var dir2= dir?.FindFile(item);
|
||||
if(dir2 != null)
|
||||
{
|
||||
if(!dir2.IsDirectory && !dir2.IsFile && !dir2.IsVirtual)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(dir2.IsDirectory)
|
||||
{
|
||||
dir=dir2;
|
||||
}
|
||||
else if(dir2.IsFile)
|
||||
{
|
||||
dir = dir2;
|
||||
if(i==path.Parts.Length -1)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override DateTime GetCreationTime(UnixPath path)
|
||||
{
|
||||
return DateTime.Now;
|
||||
}
|
||||
|
||||
public override DateTime GetLastAccessTime(UnixPath path)
|
||||
{
|
||||
return DateTime.Now;
|
||||
}
|
||||
|
||||
public override DateTime GetLastWriteTime(UnixPath path)
|
||||
{
|
||||
if(Context != null && Uri != null)
|
||||
{
|
||||
|
||||
var dir = DocumentFile.FromTreeUri(Context,Uri);
|
||||
if(dir == null) return DateTime.Now;
|
||||
|
||||
for(int i = 0;i<path.Parts.Length;i++)
|
||||
{
|
||||
var item = path.Parts[i];
|
||||
var dir2= dir?.FindFile(item);
|
||||
if(dir2 != null)
|
||||
{
|
||||
if(dir2.Exists())
|
||||
{
|
||||
|
||||
|
||||
dir = dir2;
|
||||
if(i==path.Parts.Length -1)
|
||||
return DateTimeOffset.FromUnixTimeSeconds(dir2.LastModified()).DateTime;
|
||||
}
|
||||
else return DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return DateTime.Now;
|
||||
}
|
||||
|
||||
public override void MoveDirectory(UnixPath src, UnixPath dest)
|
||||
{
|
||||
foreach(var item in this.EnumerateDirectories(src))
|
||||
{
|
||||
MoveDirectory(item,dest / item.Name);
|
||||
}
|
||||
foreach(var item in this.EnumerateFiles(src))
|
||||
{
|
||||
MoveFile(item,dest / item.Name);
|
||||
}
|
||||
DeleteDirectory(src);
|
||||
}
|
||||
|
||||
public override void MoveFile(UnixPath src, UnixPath dest)
|
||||
{
|
||||
if(src.Parent == dest.Parent)
|
||||
{
|
||||
if(Context != null && Uri != null)
|
||||
{
|
||||
|
||||
var dir = DocumentFile.FromTreeUri(Context,Uri);
|
||||
if(dir == null) return;
|
||||
|
||||
for(int i = 0;i<src.Parts.Length;i++)
|
||||
{
|
||||
var item = src.Parts[i];
|
||||
var dir2= dir?.FindFile(item);
|
||||
if(dir2 != null)
|
||||
{
|
||||
if(!dir2.IsDirectory && !dir2.IsFile && !dir2.IsVirtual)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(dir2.IsDirectory)
|
||||
{
|
||||
dir=dir2;
|
||||
}
|
||||
else if(dir2.IsFile)
|
||||
{
|
||||
dir = dir2;
|
||||
if(i==src.Parts.Length -1)
|
||||
dir.RenameTo(dest.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
this.CopyFile(src,dest);
|
||||
DeleteFile(src);
|
||||
}
|
||||
}
|
||||
|
||||
public override Stream Open(UnixPath path, FileMode mode, FileAccess access, FileShare share)
|
||||
{
|
||||
if(Context != null && Uri != null)
|
||||
{
|
||||
|
||||
var dir = DocumentFile.FromTreeUri(Context,Uri);
|
||||
if(dir == null) throw new FileNotFoundException(path.ToString());
|
||||
|
||||
for(int i = 0;i<path.Parts.Length;i++)
|
||||
{
|
||||
var item = path.Parts[i];
|
||||
var dir2= dir?.FindFile(item);
|
||||
if(dir2 != null)
|
||||
{
|
||||
if(!dir2.IsDirectory && !dir2.IsFile && !dir2.IsVirtual)
|
||||
{
|
||||
throw new FileNotFoundException(path.ToString());
|
||||
}
|
||||
else if(dir2.IsDirectory)
|
||||
{
|
||||
dir = dir2;
|
||||
|
||||
}
|
||||
|
||||
if(i==path.Parts.Length -1)
|
||||
{
|
||||
if(dir2?.IsFile ?? false)
|
||||
{
|
||||
if(mode == FileMode.CreateNew) throw new IOException("File already exists");
|
||||
return _OpenFile(dir2.Uri,mode,access,share);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var (mimeType,displayName)=GetDisplayNameAndMime(item);
|
||||
var f=dir?.CreateFile(mimeType,displayName);
|
||||
if(mode == FileMode.Open || mode == FileMode.Truncate || mode == FileMode.Append)
|
||||
throw new IOException("File does not exist");
|
||||
if(f != null)
|
||||
return _OpenFile(f.Uri,mode,access,share);
|
||||
throw new IOException("Could not open file");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
throw new FileNotFoundException(path.ToString());
|
||||
}
|
||||
|
||||
private (string mimeType, string displayName) GetDisplayNameAndMime(string item)
|
||||
{
|
||||
var mime=HeyRed.Mime.MimeTypesMap.GetMimeType(item);
|
||||
if(mime == "application/octet-stream")
|
||||
{
|
||||
return ("unknown/unknown",item);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (mime,Path.GetFileNameWithoutExtension(item));
|
||||
}
|
||||
}
|
||||
|
||||
private Stream _OpenFile(global::Android.Net.Uri uri, FileMode mode, FileAccess access, FileShare share)
|
||||
{
|
||||
|
||||
//FileMode.Append -> "a"
|
||||
//FileMode.Create -> "w"
|
||||
//FileMode.CreateNew -> "w"
|
||||
//FileMode.Open -> "r or w"
|
||||
//FileMode.OpenOrCreate -> "r or w"
|
||||
//FileMode.Truncate -> "t"
|
||||
//"r", "w", "wt", "wa", "rw" or "rwt"
|
||||
|
||||
Stream? strm = null;
|
||||
|
||||
if(access == FileAccess.Read)
|
||||
strm = Context?.ContentResolver?.OpenInputStream(uri) ?? null;
|
||||
|
||||
if(access == FileAccess.Write)
|
||||
if(mode == FileMode.Truncate)
|
||||
strm = Context?.ContentResolver?.OpenOutputStream(uri,"wt");
|
||||
else if(mode == FileMode.Append)
|
||||
strm = Context?.ContentResolver?.OpenOutputStream(uri,"wa");
|
||||
else
|
||||
strm = Context?.ContentResolver?.OpenOutputStream(uri,"w");
|
||||
|
||||
if(access == FileAccess.ReadWrite)
|
||||
if(mode == FileMode.Truncate)
|
||||
strm = Context?.ContentResolver?.OpenOutputStream(uri,"rwt");
|
||||
else
|
||||
strm = Context?.ContentResolver?.OpenOutputStream(uri,"rw");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(strm == null) throw new IOException("Failed to open stream");
|
||||
return strm;
|
||||
|
||||
}
|
||||
|
||||
public override void SetCreationTime(UnixPath path, DateTime time)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void SetLastAccessTime(UnixPath path, DateTime time)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void SetLastWriteTime(UnixPath path, DateTime time)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
# Tesses.VirtualFilesystem.Saf
|
||||
|
||||
A library to use Tesses.VirtualFilesystem with Storage Access Framework (Android)
|
||||
|
||||
# Nuget
|
||||
|
||||
# License
|
||||
|
||||
![GPL3-only](https://www.gnu.org/graphics/gplv3-with-text-136x68.png)
|
||||
Licensed under [GPL3](https://www.gnu.org/licenses/)
|
||||
|
||||
# How to use (not presistant)
|
||||
```csharp
|
||||
...
|
||||
using Tesses.VirtualFilesystem;
|
||||
using Tesses.VirtualFilesystem.Filesystems;
|
||||
using Android.Content;
|
||||
using AndroidX.DocumentFile.Provider;
|
||||
using Tesses.VirtualFilesystem.Extensions;
|
||||
...
|
||||
|
||||
void SomeActivityFunction()
|
||||
{
|
||||
SAFFileSystem.RequestDirectory(this,true);
|
||||
}
|
||||
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent? data)
|
||||
{
|
||||
if(requestCode == SAFFileSystem.RequestCode && resultCode == Result.Ok)
|
||||
{
|
||||
var res=SAFFileSystem.GetSAFFromResponse(this,data);
|
||||
if(res != null)
|
||||
HandleFilesystem(res);
|
||||
}
|
||||
}
|
||||
void HandleFilesystem(SAFFileSystem fs)
|
||||
{
|
||||
fs.CreateDirectory(Special.Root/"My Special Folder");
|
||||
//read https://gitea.site.tesses.net/tesses50/tesses-vfs to get up to speed
|
||||
//root is relative to the folder the user chose
|
||||
//so get subdir filesystem is not needed
|
||||
}
|
||||
```
|
||||
|
||||
# How to use (presistant)
|
||||
```csharp
|
||||
...
|
||||
using Tesses.VirtualFilesystem;
|
||||
using Tesses.VirtualFilesystem.Filesystems;
|
||||
using Android.Content;
|
||||
using AndroidX.DocumentFile.Provider;
|
||||
using Tesses.VirtualFilesystem.Extensions;
|
||||
...
|
||||
const string MySAFKey = "MySafKey";
|
||||
void SomethingWithContext()
|
||||
{
|
||||
var res= SAFFileSystem.GetSAFFromSharedStorage(this,MySAFKey);
|
||||
if(res != null)
|
||||
HandleFilesystem(res);
|
||||
}
|
||||
void SomeActivityFunction()
|
||||
{
|
||||
var res= SAFFileSystem.GetSAFFromSharedStorage(this,MySAFKey);
|
||||
if(res != null)
|
||||
HandleFilesystem(res);
|
||||
else
|
||||
SAFFileSystem.RequestDirectory(this,true,true);
|
||||
}
|
||||
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent? data)
|
||||
{
|
||||
if(requestCode == SAFFileSystem.RequestCode && resultCode == Result.Ok)
|
||||
{
|
||||
var res=SAFFileSystem.GetSAFFromResponsePresistant(this,data,MySAFKey);
|
||||
if(res != null)
|
||||
HandleFilesystem(res);
|
||||
}
|
||||
}
|
||||
void HandleFilesystem(SAFFileSystem fs)
|
||||
{
|
||||
fs.CreateDirectory(Special.Root/"My Special Folder");
|
||||
//read https://gitea.site.tesses.net/tesses50/tesses-vfs to get up to speed
|
||||
//root is relative to the folder the user chose
|
||||
//so get subdir filesystem is not needed
|
||||
}
|
||||
```
|
||||
# How to revoke permissions
|
||||
```csharp
|
||||
...
|
||||
using Tesses.VirtualFilesystem;
|
||||
using Tesses.VirtualFilesystem.Filesystems;
|
||||
using Android.Content;
|
||||
using AndroidX.DocumentFile.Provider;
|
||||
using Tesses.VirtualFilesystem.Extensions;
|
||||
...
|
||||
const string MySAFKey = "MySafKey";
|
||||
void SomethingWithContext()
|
||||
{
|
||||
SAFFileSystem.Revoke(this,MySAFKey);
|
||||
}
|
||||
```
|
|
@ -0,0 +1,32 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-android</TargetFramework>
|
||||
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>Tesses.VirtualFilesystem.Saf</PackageId>
|
||||
<Author>Mike Nolan</Author>
|
||||
<Company>Tesses</Company>
|
||||
<Version>1.0.0</Version>
|
||||
<AssemblyVersion>1.0.0</AssemblyVersion>
|
||||
<FileVersion>1.0.0</FileVersion>
|
||||
<Description>Tesses.VirtualFilesystem for Android Storage Access Framework (Is slow though)</Description>
|
||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<PackageTags>VFS, Filesystem, VirtualFilesystem</PackageTags>
|
||||
<RepositoryUrl>https://gitlab.tesses.net/tesses50/tesses-vfs</RepositoryUrl>
|
||||
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MimeTypesMap" Version="1.0.8" />
|
||||
<PackageReference Include="Tesses.VirtualFilesystem" Version="1.0.2" />
|
||||
<PackageReference Include="Xamarin.AndroidX.DocumentFile" Version="1.0.1.27" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="README.md" Pack="true" PackagePath="\"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
|
@ -21,13 +21,20 @@ using Tesses.VirtualFilesystem;
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.IO;
|
||||
using Tesses.VirtualFilesystem.Extensions;
|
||||
|
||||
namespace Tesses.VirtualFilesystem.Filesystems
|
||||
{
|
||||
|
||||
public class ZioFileSystem : SyncFileSystem
|
||||
{
|
||||
IFileSystem fs;
|
||||
|
||||
public IFileSystem Filesystem => fs;
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
fs.Dispose();
|
||||
}
|
||||
public ZioFileSystem(IFileSystem fs)
|
||||
{
|
||||
this.fs = fs;
|
||||
|
@ -171,7 +178,301 @@ namespace Tesses.VirtualFilesystem.Filesystems
|
|||
public event EventHandler<VirtualWatcherChangedArgs> Deleted;
|
||||
public event EventHandler<VirtualWatcherRenamedEventArgs> Renamed;
|
||||
public event EventHandler<ErrorEventArgs> Error;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.watcher.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class ZioMountableWrapper : ZioFileSystem
|
||||
{
|
||||
public MountFileSystem MountFilesystem {get;}
|
||||
private ZioMountableWrapper(MountFileSystem fs) : base(fs)
|
||||
{
|
||||
MountFilesystem = fs;
|
||||
}
|
||||
|
||||
public static ZioMountableWrapper Create(IVirtualFilesystem fs,bool owned=true)
|
||||
{
|
||||
return new ZioMountableWrapper(new MountFileSystem(new TessesVFSFilesystem(fs),owned));
|
||||
}
|
||||
public static ZioMountableWrapper Create(bool owned=true)
|
||||
{
|
||||
return new ZioMountableWrapper(new MountFileSystem(owned));
|
||||
}
|
||||
public void Mount(UnixPath path,IVirtualFilesystem fs)
|
||||
{
|
||||
MountFilesystem.Mount(path.Path,new TessesVFSFilesystem(fs));
|
||||
}
|
||||
public bool IsMounted(UnixPath path)
|
||||
{
|
||||
return MountFilesystem.IsMounted(path.Path);
|
||||
}
|
||||
public Dictionary<UnixPath,IVirtualFilesystem> GetMounts()
|
||||
{
|
||||
Dictionary<UnixPath,IVirtualFilesystem> fs=new Dictionary<UnixPath, IVirtualFilesystem>();
|
||||
|
||||
foreach(var item in MountFilesystem.GetMounts())
|
||||
{
|
||||
var _fs=item.Value as TessesVFSFilesystem;
|
||||
if(_fs !=null)
|
||||
fs.Add(item.Key.FullName,_fs.Filesystem);
|
||||
}
|
||||
return fs;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
namespace Zio.FileSystems
|
||||
{
|
||||
public class TessesVFSFilesystem : Zio.FileSystems.FileSystem
|
||||
{
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing)
|
||||
fs.Dispose();
|
||||
}
|
||||
IVirtualFilesystem fs;
|
||||
public IVirtualFilesystem Filesystem => fs;
|
||||
public TessesVFSFilesystem(IVirtualFilesystem fs)
|
||||
{
|
||||
this.fs = fs;
|
||||
}
|
||||
protected override UPath ConvertPathFromInternalImpl(string innerPath)
|
||||
{
|
||||
return innerPath;
|
||||
}
|
||||
|
||||
protected override string ConvertPathToInternalImpl(UPath path)
|
||||
{
|
||||
return path.FullName;
|
||||
}
|
||||
|
||||
protected override void CopyFileImpl(UPath srcPath, UPath destPath, bool overwrite)
|
||||
{
|
||||
if(!overwrite && fs.FileExists(fs.ConvertPathToUnixPath(ConvertPathToInternal(destPath)))) throw new IOException("File already exists");
|
||||
|
||||
fs.CopyFile(fs.ConvertPathToUnixPath(ConvertPathToInternal(srcPath)),fs.ConvertPathToUnixPath(ConvertPathToInternal(destPath)));
|
||||
}
|
||||
|
||||
protected override void CreateDirectoryImpl(UPath path)
|
||||
{
|
||||
fs.CreateDirectory(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)));
|
||||
}
|
||||
|
||||
protected override void DeleteDirectoryImpl(UPath path, bool isRecursive)
|
||||
{
|
||||
fs.DeleteDirectory(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)),isRecursive);
|
||||
}
|
||||
|
||||
protected override void DeleteFileImpl(UPath path)
|
||||
{
|
||||
fs.DeleteFile(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)));
|
||||
}
|
||||
|
||||
protected override bool DirectoryExistsImpl(UPath path)
|
||||
{
|
||||
return fs.DirectoryExists(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)));
|
||||
}
|
||||
|
||||
protected override IEnumerable<FileSystemItem> EnumerateItemsImpl(UPath path, SearchOption searchOption, SearchPredicate searchPredicate)
|
||||
{
|
||||
foreach(var item in fs.EnumerateFileSystemEntries(fs.ConvertPathToUnixPath(ConvertPathToInternal(path))))
|
||||
{
|
||||
yield return new FileSystemItem(this,ConvertPathFromInternal(fs.ConvertPathFromUnixPath(item)),fs.DirectoryExists(item));
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<UPath> EnumeratePathsImpl(UPath path, string searchPattern, SearchOption searchOption, SearchTarget searchTarget)
|
||||
{
|
||||
foreach(var item in fs.EnumerateFileSystemEntries(fs.ConvertPathToUnixPath(ConvertPathToInternal(path))))
|
||||
{
|
||||
yield return ConvertPathFromInternal(fs.ConvertPathFromUnixPath(item));
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool FileExistsImpl(UPath path)
|
||||
{
|
||||
return fs.FileExists(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)));
|
||||
}
|
||||
|
||||
protected override FileAttributes GetAttributesImpl(UPath path)
|
||||
{
|
||||
return fs.GetAttributes(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)));
|
||||
}
|
||||
|
||||
protected override DateTime GetCreationTimeImpl(UPath path)
|
||||
{
|
||||
return fs.GetCreationTime(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)));
|
||||
}
|
||||
|
||||
protected override long GetFileLengthImpl(UPath path)
|
||||
{
|
||||
using(var f = fs.OpenRead(fs.ConvertPathToUnixPath(ConvertPathToInternal(path))))
|
||||
{
|
||||
return f.Length;
|
||||
}
|
||||
}
|
||||
|
||||
protected override DateTime GetLastAccessTimeImpl(UPath path)
|
||||
{
|
||||
return fs.GetLastAccessTime(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)));
|
||||
}
|
||||
|
||||
protected override DateTime GetLastWriteTimeImpl(UPath path)
|
||||
{
|
||||
return fs.GetLastWriteTime(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)));
|
||||
}
|
||||
|
||||
protected override void MoveDirectoryImpl(UPath srcPath, UPath destPath)
|
||||
{
|
||||
fs.MoveDirectory(fs.ConvertPathToUnixPath(ConvertPathToInternal(srcPath)),fs.ConvertPathToUnixPath(ConvertPathToInternal(destPath)));
|
||||
}
|
||||
|
||||
protected override void MoveFileImpl(UPath srcPath, UPath destPath)
|
||||
{
|
||||
fs.MoveDirectory(fs.ConvertPathToUnixPath(ConvertPathToInternal(srcPath)),fs.ConvertPathToUnixPath(ConvertPathToInternal(destPath)));
|
||||
|
||||
}
|
||||
|
||||
protected override Stream OpenFileImpl(UPath path, FileMode mode, FileAccess access, FileShare share)
|
||||
{
|
||||
return fs.Open(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)),mode,access,share);
|
||||
}
|
||||
|
||||
protected override void ReplaceFileImpl(UPath srcPath, UPath destPath, UPath destBackupPath, bool ignoreMetadataErrors)
|
||||
{
|
||||
MoveFile(destPath,destBackupPath);
|
||||
MoveFile(srcPath,destPath);
|
||||
}
|
||||
|
||||
protected override void SetAttributesImpl(UPath path, FileAttributes attributes)
|
||||
{
|
||||
fs.SetAttributes(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)),attributes);
|
||||
}
|
||||
|
||||
protected override void SetCreationTimeImpl(UPath path, DateTime time)
|
||||
{
|
||||
fs.SetCreationTime(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)),time);
|
||||
}
|
||||
|
||||
protected override void SetLastAccessTimeImpl(UPath path, DateTime time)
|
||||
{
|
||||
fs.SetLastAccessTime(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)),time);
|
||||
}
|
||||
|
||||
protected override void SetLastWriteTimeImpl(UPath path, DateTime time)
|
||||
{
|
||||
fs.SetLastWriteTime(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)),time);
|
||||
}
|
||||
|
||||
protected override IFileSystemWatcher WatchImpl(UPath path)
|
||||
{
|
||||
return new _FSW(this,fs,fs.ConvertPathToUnixPath(ConvertPathToInternal(path)));
|
||||
}
|
||||
|
||||
protected override void CreateSymbolicLinkImpl(UPath path, UPath pathToTarget)
|
||||
{
|
||||
fs.CreateSymlink(fs.ConvertPathToUnixPath(ConvertPathToInternal(path)),fs.ConvertPathToUnixPath(ConvertPathToInternal(pathToTarget)));
|
||||
}
|
||||
|
||||
protected override bool TryResolveLinkTargetImpl(UPath linkPath, out UPath resolvedPath)
|
||||
{
|
||||
if(fs.SymlinkExists(fs.ConvertPathToUnixPath(ConvertPathToInternal(linkPath))))
|
||||
{
|
||||
resolvedPath = ConvertPathFromInternal(fs.ConvertPathFromUnixPath(fs.ReadLink(fs.ConvertPathToUnixPath(ConvertPathToInternal(linkPath)))));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedPath = ConvertPathFromInternal(fs.ConvertPathFromUnixPath(Special.Root));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class _FSW : IFileSystemWatcher
|
||||
{
|
||||
IVirtualWatcher watcher;
|
||||
|
||||
|
||||
|
||||
public _FSW(IFileSystem fs2,IVirtualFilesystem fs,UnixPath unixPath)
|
||||
{
|
||||
this.FileSystem=fs2;
|
||||
watcher=fs.WatchDirectory(unixPath);
|
||||
Path = fs2.ConvertPathFromInternal(fs.ConvertPathFromUnixPath(unixPath));
|
||||
this._fs = fs;
|
||||
watcher.Changed += W_Changed;
|
||||
watcher.Created += W_Created;
|
||||
watcher.Deleted += W_Deleted;
|
||||
watcher.Error += W_Error;
|
||||
watcher.Renamed += W_Renamed;
|
||||
}
|
||||
|
||||
private void W_Renamed(object sender, VirtualWatcherRenamedEventArgs e)
|
||||
{
|
||||
Renamed?.Invoke(this,new FileRenamedEventArgs(FileSystem,(Zio.WatcherChangeTypes)e.ChangeType,FileSystem.ConvertPathFromInternal(_fs.ConvertPathFromUnixPath(e.FullPath)),FileSystem.ConvertPathFromInternal(_fs.ConvertPathFromUnixPath(e.OldFullPath))));
|
||||
}
|
||||
|
||||
private void W_Error(object sender, System.IO.ErrorEventArgs e)
|
||||
{
|
||||
Error?.Invoke(this,new FileSystemErrorEventArgs(e.GetException()));
|
||||
}
|
||||
|
||||
private void W_Deleted(object sender, VirtualWatcherChangedArgs e)
|
||||
{
|
||||
Deleted?.Invoke(this,new FileChangedEventArgs(FileSystem,(Zio.WatcherChangeTypes)e.ChangeType,FileSystem.ConvertPathFromInternal(_fs.ConvertPathFromUnixPath(e.FullPath))));
|
||||
|
||||
}
|
||||
|
||||
IVirtualFilesystem _fs;
|
||||
private void W_Created(object sender, VirtualWatcherChangedArgs e)
|
||||
{
|
||||
Created?.Invoke(this,new FileChangedEventArgs(FileSystem,(Zio.WatcherChangeTypes)e.ChangeType,FileSystem.ConvertPathFromInternal(_fs.ConvertPathFromUnixPath(e.FullPath))));
|
||||
}
|
||||
|
||||
private void W_Changed(object sender, VirtualWatcherChangedArgs e)
|
||||
{
|
||||
Changed?.Invoke(this,new FileChangedEventArgs(FileSystem,(Zio.WatcherChangeTypes)e.ChangeType,FileSystem.ConvertPathFromInternal(_fs.ConvertPathFromUnixPath(e.FullPath))));
|
||||
}
|
||||
|
||||
public IFileSystem FileSystem {get;}
|
||||
|
||||
public UPath Path {get;}
|
||||
|
||||
public int InternalBufferSize { get => watcher.InternalBufferSize; set => watcher.InternalBufferSize = value; }
|
||||
public Zio.NotifyFilters NotifyFilter { get => (Zio.NotifyFilters)watcher.NotifyFilter; set => watcher.NotifyFilter = (System.IO.NotifyFilters)value; }
|
||||
public bool EnableRaisingEvents { get => watcher.EnableRaisingEvents; set => watcher.EnableRaisingEvents=value; }
|
||||
public string Filter { get => watcher.Filter; set => watcher.Filter=value; }
|
||||
public bool IncludeSubdirectories { get => watcher.IncludeSubdirectories; set => watcher.IncludeSubdirectories=value; }
|
||||
|
||||
public event EventHandler<FileChangedEventArgs> Changed;
|
||||
public event EventHandler<FileChangedEventArgs> Created;
|
||||
public event EventHandler<FileChangedEventArgs> Deleted;
|
||||
public event EventHandler<FileSystemErrorEventArgs> Error;
|
||||
public event EventHandler<FileRenamedEventArgs> Renamed;
|
||||
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
watcher.Changed -= W_Changed;
|
||||
watcher.Created -= W_Created;
|
||||
watcher.Deleted -= W_Deleted;
|
||||
watcher.Error -= W_Error;
|
||||
watcher.Renamed -= W_Renamed;
|
||||
watcher.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -2,14 +2,16 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Tesses.VirtualFilesystem\Tesses.VirtualFilesystem.csproj" />
|
||||
<ProjectReference Include="..\Tesses.VirtualFilesystem.Extensions\Tesses.VirtualFilesystem.Extensions.csproj" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Zio" Version="0.16.1" />
|
||||
<PackageReference Include="Zio" Version="0.19.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\README.md" Pack="true" PackagePath="\"/>
|
||||
<None Include="..\README.md" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
@ -18,9 +20,9 @@
|
|||
<PackageId>Tesses.VirtualFilesystem.Zio</PackageId>
|
||||
<Author>Mike Nolan</Author>
|
||||
<Company>Tesses</Company>
|
||||
<Version>1.0.0</Version>
|
||||
<AssemblyVersion>1.0.0</AssemblyVersion>
|
||||
<FileVersion>1.0.0</FileVersion>
|
||||
<Version>1.0.1</Version>
|
||||
<AssemblyVersion>1.0.1</AssemblyVersion>
|
||||
<FileVersion>1.0.1</FileVersion>
|
||||
<Description>Another VirtualFilesystem for .NET</Description>
|
||||
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
|
|
Loading…
Reference in New Issue