603 lines
28 KiB
C#
603 lines
28 KiB
C#
/*
|
|
Tesses.VirtualFilesystem a library for virtual filesystems in .NET
|
|
Copyright (C) 2023 Mike Nolan
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
using System;
|
|
using Tesses.VirtualFilesystem;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace Tesses.VirtualFilesystem.Extensions
|
|
{
|
|
public static class Extensions
|
|
{
|
|
public static StreamReader OpenText(this IVirtualFilesystem fs,UnixPath path,Encoding encoding)
|
|
{
|
|
Stream strm=fs.OpenRead(path);
|
|
return new StreamReader(strm,encoding,false,4096,false);
|
|
}
|
|
public static async Task<StreamReader> OpenTextAsync(this IVirtualFilesystem fs,UnixPath path,Encoding encoding)
|
|
{
|
|
Stream strm=await fs.OpenReadAsync(path);
|
|
return new StreamReader(strm,encoding,false,4096,false);
|
|
}
|
|
public static StreamReader OpenText(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
Stream strm = fs.OpenRead(path);
|
|
return new StreamReader(strm,Encoding.UTF8,false,4096,false);
|
|
}
|
|
public static async Task<StreamReader> OpenTextAsync(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
Stream strm = await fs.OpenReadAsync(path);
|
|
return new StreamReader(strm,Encoding.UTF8,false,4096,false);
|
|
}
|
|
public static StreamWriter CreateText(this IVirtualFilesystem fs,UnixPath path,Encoding encoding)
|
|
{
|
|
Stream strm = fs.Create(path);
|
|
return new StreamWriter(strm,encoding,4096,false);
|
|
}
|
|
public static async Task<StreamWriter> CreateTextAsync(this IVirtualFilesystem fs,UnixPath path,Encoding encoding)
|
|
{
|
|
Stream strm = await fs.CreateAsync(path);
|
|
return new StreamWriter(strm,encoding,4096,false);
|
|
}
|
|
public static StreamWriter CreateText(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
Stream strm = fs.Create(path);
|
|
return new StreamWriter(strm,Encoding.UTF8,4096,false);
|
|
}
|
|
public static async Task<StreamWriter> CreateTextAsync(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
Stream strm = await fs.CreateAsync(path);
|
|
return new StreamWriter(strm,Encoding.UTF8,4096,false);
|
|
}
|
|
public static void WriteAllText(this IVirtualFilesystem fs,UnixPath path,string text,Encoding encoding)
|
|
{
|
|
using(var sw=fs.CreateText(path,encoding))
|
|
sw.Write(text);
|
|
}
|
|
public static async Task WriteAllTextAsync(this IVirtualFilesystem fs,UnixPath path,string text,Encoding encoding)
|
|
{
|
|
using(var sw=await fs.CreateTextAsync(path,encoding))
|
|
await sw.WriteAsync(text);
|
|
}
|
|
public static void WriteAllText(this IVirtualFilesystem fs,UnixPath path,string text)
|
|
{
|
|
using(var sw=fs.CreateText(path,Encoding.UTF8))
|
|
sw.Write(text);
|
|
}
|
|
public static async Task WriteAllTextAsync(this IVirtualFilesystem fs,UnixPath path,string text)
|
|
{
|
|
using(var sw=await fs.CreateTextAsync(path,Encoding.UTF8))
|
|
await sw.WriteAsync(text);
|
|
}
|
|
public static string ReadAllText(this IVirtualFilesystem fs,UnixPath path,Encoding encoding)
|
|
{
|
|
using(var sr = fs.OpenText(path,encoding))
|
|
return sr.ReadToEnd();
|
|
}
|
|
public static async Task<string> ReadAllTextAsync(this IVirtualFilesystem fs,UnixPath path,Encoding encoding)
|
|
{
|
|
using(var sr = await fs.OpenTextAsync(path,encoding))
|
|
return await sr.ReadToEndAsync();
|
|
}
|
|
public static string ReadAllText(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
using(var sr = fs.OpenText(path,Encoding.UTF8))
|
|
return sr.ReadToEnd();
|
|
}
|
|
public static async Task<string> ReadAllTextAsync(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
using(var sr = await fs.OpenTextAsync(path,Encoding.UTF8))
|
|
return await sr.ReadToEndAsync();
|
|
}
|
|
|
|
public static void WriteAllBytes(this IVirtualFilesystem fs,UnixPath path,byte[] data)
|
|
{
|
|
using(var s = fs.Create(path))
|
|
StreamHelper.WriteAllBytes(s,data);
|
|
}
|
|
public static async Task WriteAllBytesAsync(this IVirtualFilesystem fs,UnixPath path,byte[] data,CancellationToken token=default)
|
|
{
|
|
using(var strm = await fs.CreateAsync(path,token))
|
|
{
|
|
using(MemoryStream ms = new MemoryStream(data))
|
|
await ms.CopyToAsync(strm,4096,token);
|
|
}
|
|
}
|
|
public static byte[] ReadAllBytes(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
using(var s = fs.OpenRead(path))
|
|
return StreamHelper.ReadAllBytes(s);
|
|
}
|
|
public static async Task<byte[]> ReadAllBytesAsync(this IVirtualFilesystem fs,UnixPath path,CancellationToken token=default)
|
|
{
|
|
using(var strm = await fs.OpenReadAsync(path,token))
|
|
{
|
|
MemoryStream ms=new MemoryStream();
|
|
await strm.CopyToAsync(ms,4096,token);
|
|
return ms.ToArray();
|
|
}
|
|
}
|
|
public static Stream OpenRead(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
return fs.Open(path,FileMode.Open,FileAccess.Read,FileShare.Read);
|
|
}
|
|
public static async Task<Stream> OpenReadAsync(this IVirtualFilesystem fs,UnixPath path,CancellationToken token=default)
|
|
{
|
|
return await fs.OpenAsync(path,FileMode.Open,FileAccess.Read,FileShare.Read,token);
|
|
}
|
|
public static Stream OpenWrite(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
return fs.Open(path,FileMode.OpenOrCreate,FileAccess.Write,FileShare.None);
|
|
}
|
|
public static async Task<Stream> OpenWriteAsync(this IVirtualFilesystem fs,UnixPath path,CancellationToken token=default)
|
|
{
|
|
return await fs.OpenAsync(path,FileMode.OpenOrCreate,FileAccess.Write,FileShare.None,token);
|
|
}
|
|
public static Stream Create(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
return fs.Open(path,FileMode.Create,FileAccess.ReadWrite,FileShare.None);
|
|
}
|
|
public static async Task<Stream> CreateAsync(this IVirtualFilesystem fs,UnixPath path,CancellationToken token=default)
|
|
{
|
|
return await fs.OpenAsync(path,FileMode.Create,FileAccess.ReadWrite,FileShare.None,token);
|
|
}
|
|
public static DirectoryPointer OpenDirectory(this IVirtualFilesystem fs,Environment.SpecialFolder specialFolder)
|
|
{
|
|
return new DirectoryPointer(fs,UnixPath.FromSpecialDirectory(specialFolder));
|
|
}
|
|
public static bool MoveFile(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath path,IProgress<TransferProgress> progress=null,int bufferLength=4096,bool deleteDir=true)
|
|
{
|
|
return srcfs.MoveFile(destfs,path,path,progress,bufferLength);
|
|
}
|
|
public static bool MoveDirectory(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath path,IProgress<TransferProgress> progress=null,int bufferLength=4096,bool deleteDir=true)
|
|
{
|
|
return srcfs.MoveDirectory(destfs,path,path,progress,bufferLength,deleteDir);
|
|
}
|
|
public static async Task<bool> MoveFileAsync(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath path,CancellationToken token=default(CancellationToken),IProgress<TransferProgress> progress=null,int bufferLength=4096,bool deleteDir=true)
|
|
{
|
|
return await srcfs.MoveFileAsync(destfs,path,path,token,progress,bufferLength);
|
|
}
|
|
public static async Task<bool> MoveDirectoryAsync(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath path,CancellationToken token=default(CancellationToken),IProgress<TransferProgress> progress=null,int bufferLength=4096,bool deleteDir=true)
|
|
{
|
|
|
|
return await srcfs.MoveDirectoryAsync(destfs,path,path,token,progress,bufferLength,deleteDir);
|
|
}
|
|
public static async Task<bool> MoveDirectoryAsync(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath source,UnixPath destination,CancellationToken token=default(CancellationToken),IProgress<TransferProgress> progress=null,int bufferLength=4096,bool deleteDir=true)
|
|
{
|
|
DateTime laccess=DateTime.Now;
|
|
DateTime lwrite = DateTime.Now;
|
|
try{
|
|
laccess = await srcfs.GetLastAccessTimeAsync(source,token);
|
|
lwrite = await srcfs.GetLastWriteTimeAsync(source,token);
|
|
if(!await destfs.DirectoryExistsAsync(destination,token))
|
|
await destfs.CreateDirectoryAsync(destination,token);
|
|
await foreach(var directory in srcfs.EnumerateDirectoriesAsync(source,token))
|
|
{
|
|
if(token.IsCancellationRequested) return false;
|
|
var newPath = destination / directory.Name;
|
|
var res=await srcfs.MoveDirectoryAsync(destfs,directory,newPath,token,progress,bufferLength);
|
|
if(!res) return false;
|
|
if(token.IsCancellationRequested) return false;
|
|
}
|
|
await foreach(var file in srcfs.EnumerateFilesAsync(source,token))
|
|
{
|
|
if(token.IsCancellationRequested) return false;
|
|
var newPath = destination / file.Name;
|
|
var res=await srcfs.MoveFileAsync(destfs,file,newPath,token,progress,bufferLength);
|
|
if(!res) return false;
|
|
if(token.IsCancellationRequested) return false;
|
|
}
|
|
}catch(Exception ex)
|
|
{
|
|
_=ex;
|
|
return false;
|
|
}
|
|
if(token.IsCancellationRequested) return false;
|
|
await destfs.SetCreationTimeAsync(destination,DateTime.Now,token);
|
|
await destfs.SetLastWriteTimeAsync(destination,lwrite,token);
|
|
await destfs.SetLastAccessTimeAsync(destination,laccess,token);
|
|
if(deleteDir && !token.IsCancellationRequested)
|
|
await srcfs.DeleteDirectoryAsync(source,token);
|
|
|
|
return true;
|
|
}
|
|
public static async Task<bool> MoveFileAsync(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath source,UnixPath destination,CancellationToken token=default(CancellationToken),IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
var success=await srcfs.CopyFileAsync(destfs,source,destination,token,progress,bufferLength);
|
|
if(!token.IsCancellationRequested && success)
|
|
await srcfs.DeleteFileAsync(source,token);
|
|
return success;
|
|
}
|
|
public static bool MoveFile(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath source,UnixPath destination,IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
bool success= srcfs.CopyFile(destfs,source,destination,progress,bufferLength);
|
|
if(success)
|
|
srcfs.DeleteFile(source);
|
|
return success;
|
|
}
|
|
public static bool MoveDirectory(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath source,UnixPath destination,IProgress<TransferProgress> progress=null,int bufferLength=4096,bool deleteDir=true)
|
|
{
|
|
DateTime laccess = DateTime.Now;
|
|
DateTime lwrite = DateTime.Now;
|
|
try{
|
|
laccess = srcfs.GetLastAccessTime(source);
|
|
lwrite = srcfs.GetLastWriteTime(source);
|
|
if(!destfs.DirectoryExists(destination))
|
|
destfs.CreateDirectory(destination);
|
|
foreach(var directory in srcfs.EnumerateDirectories(source))
|
|
{
|
|
var newPath = destination / directory.Name;
|
|
srcfs.MoveDirectory(destfs,directory,newPath,progress,bufferLength);
|
|
}
|
|
foreach(var file in srcfs.EnumerateFiles(source))
|
|
{
|
|
var newPath = destination / file.Name;
|
|
srcfs.MoveFile(destfs,file,newPath,progress,bufferLength);
|
|
}
|
|
}catch(Exception ex)
|
|
{
|
|
_=ex;
|
|
return false;
|
|
}
|
|
destfs.SetCreationTime(destination,DateTime.Now);
|
|
destfs.SetLastWriteTime(destination,lwrite);
|
|
destfs.SetLastAccessTime(destination,laccess);
|
|
if(deleteDir)
|
|
srcfs.DeleteDirectory(source);
|
|
return true;
|
|
}
|
|
public static UnixPath[] GetFiles(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
return fs.EnumerateFiles(path).ToArray();
|
|
}
|
|
public static UnixPath[] GetDirectories(this IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
return fs.EnumerateDirectories(path).ToArray();
|
|
}
|
|
public static async Task<UnixPath[]> GetFilesAsync(this IVirtualFilesystem fs,UnixPath path,CancellationToken token = default(CancellationToken))
|
|
{
|
|
return await fs.EnumerateFilesAsync(path,token).ToArrayAsync(token);
|
|
}
|
|
|
|
public static async Task<T[]> ToArrayAsync<T>(this IAsyncEnumerable<T> enumerator,CancellationToken token=default(CancellationToken))
|
|
{
|
|
List<T> paths=new List<T>();
|
|
|
|
await foreach(var item in enumerator)
|
|
{
|
|
if(token.IsCancellationRequested) return paths.ToArray();
|
|
paths.Add(item);
|
|
}
|
|
return paths.ToArray();
|
|
}
|
|
public static async Task<UnixPath[]> GetDirectoriesAsync(this IVirtualFilesystem fs,UnixPath path,CancellationToken token=default(CancellationToken))
|
|
{
|
|
return await fs.EnumerateDirectoriesAsync(path).ToArrayAsync(token);
|
|
}
|
|
public static async Task DeleteDirectoryAsync(this IVirtualFilesystem fs,UnixPath path,bool recursive,CancellationToken token=default(CancellationToken))
|
|
{
|
|
if(recursive)
|
|
{
|
|
await foreach(var dir in fs.EnumerateDirectoriesAsync(path,token))
|
|
{
|
|
if(token.IsCancellationRequested) return;
|
|
await fs.DeleteDirectoryAsync(dir,recursive,token);
|
|
}
|
|
await foreach(var file in fs.EnumerateFilesAsync(path,token))
|
|
{
|
|
if(token.IsCancellationRequested) return;
|
|
await fs.DeleteFileAsync(file,token);
|
|
}
|
|
}
|
|
}
|
|
public static void DeleteDirectory(this IVirtualFilesystem fs,UnixPath path,bool recursive)
|
|
{
|
|
if(recursive)
|
|
{
|
|
foreach(var dir in fs.EnumerateDirectories(path))
|
|
{
|
|
fs.DeleteDirectory(dir,true);
|
|
}
|
|
foreach(var file in fs.EnumerateFiles(path))
|
|
{
|
|
fs.DeleteFile(file);
|
|
}
|
|
}
|
|
fs.DeleteDirectory(path);
|
|
}
|
|
public static async Task<bool> CopyDirectoryAsync(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath path,CancellationToken token=default(CancellationToken),IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
return await srcfs.CopyDirectoryAsync(destfs,path,path,token,progress,bufferLength);
|
|
}
|
|
public static async Task<bool> CopyDirectoryAsync(this IVirtualFilesystem srcfs,UnixPath srcPath,UnixPath destPath,CancellationToken token=default(CancellationToken),IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
return await srcfs.CopyDirectoryAsync(srcfs,srcPath,destPath,token,progress,bufferLength);
|
|
}
|
|
public static async Task<bool> CopyFileAsync(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath path,CancellationToken token=default(CancellationToken),IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
return await srcfs.CopyFileAsync(destfs,path,path,token,progress,bufferLength);
|
|
}
|
|
public static async Task<bool> CopyFileAsync(this IVirtualFilesystem srcfs,UnixPath source,UnixPath destination,CancellationToken token=default(CancellationToken),IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
return await srcfs.CopyFileAsync(srcfs,source,destination,token,progress,bufferLength);
|
|
}
|
|
public static async Task<bool> CopyDirectoryAsync(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath source,UnixPath destination,CancellationToken token = default(CancellationToken),IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
DateTime laccess=DateTime.Now;
|
|
try{
|
|
laccess = await srcfs.GetLastAccessTimeAsync(source);
|
|
if(!await destfs.DirectoryExistsAsync(destination,token))
|
|
await destfs.CreateDirectoryAsync(destination,token);
|
|
await foreach(var directory in srcfs.EnumerateDirectoriesAsync(source,token))
|
|
{
|
|
if(token.IsCancellationRequested) return false;
|
|
var newPath = destination / directory.Name;
|
|
var res= await srcfs.CopyDirectoryAsync(destfs,directory,newPath,token,progress,bufferLength);
|
|
if(!res) return false;
|
|
}
|
|
await foreach(var file in srcfs.EnumerateFilesAsync(source,token))
|
|
{
|
|
if(token.IsCancellationRequested) return false;
|
|
var newPath = destination / file.Name;
|
|
var res= await srcfs.CopyFileAsync(destfs,file,newPath,token,progress,bufferLength);
|
|
if(!res) return false;
|
|
}
|
|
}catch(Exception ex)
|
|
{
|
|
_=ex;
|
|
return false;
|
|
}
|
|
await destfs.SetCreationTimeAsync(destination,DateTime.Now,token);
|
|
await destfs.SetLastWriteTimeAsync(destination,await srcfs.GetLastWriteTimeAsync(source,token),token);
|
|
await destfs.SetLastAccessTimeAsync(destination,laccess,token);
|
|
try
|
|
{
|
|
await srcfs.SetLastAccessTimeAsync(source,DateTime.Now,token);
|
|
}catch(Exception ex)
|
|
{
|
|
_=ex;
|
|
}
|
|
return true;
|
|
}
|
|
public static async Task<bool> CopyFileAsync(this IVirtualFilesystem srcfs, IVirtualFilesystem destfs,UnixPath source,UnixPath destination,CancellationToken token=default(CancellationToken),IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
DateTime laccess=DateTime.Now;
|
|
try{
|
|
laccess= await srcfs.GetLastAccessTimeAsync(source,token);
|
|
if(await destfs.DirectoryExistsAsync(destination,token)) destination /= source.Name;
|
|
|
|
using(var src = await srcfs.OpenAsync(source,FileMode.Open,FileAccess.Read,FileShare.Read,token))
|
|
{
|
|
using(var dest = await destfs.OpenAsync(destination,FileMode.OpenOrCreate,FileAccess.Write,FileShare.None,token))
|
|
{
|
|
byte[] buffer = new byte[bufferLength];
|
|
int read=0;
|
|
long readTotal=0;
|
|
long length = src.Length;
|
|
|
|
do
|
|
{
|
|
if(token.IsCancellationRequested) return false;
|
|
read = await src.ReadAsync(buffer,0,buffer.Length,token);
|
|
readTotal += read;
|
|
if(token.IsCancellationRequested) return false;
|
|
await dest.WriteAsync(buffer,0,read,token);
|
|
if(token.IsCancellationRequested) return false;
|
|
progress?.Report(new TransferProgress(readTotal,length,source,destination));
|
|
}
|
|
while(read != 0);
|
|
}
|
|
}
|
|
}catch(Exception ex)
|
|
{
|
|
_=ex;
|
|
|
|
return false;
|
|
}
|
|
await destfs.SetCreationTimeAsync(destination,DateTime.Now,token);
|
|
await destfs.SetLastWriteTimeAsync(destination,await srcfs.GetLastWriteTimeAsync(source,token),token);
|
|
await destfs.SetLastAccessTimeAsync(destination,laccess,token);
|
|
try
|
|
{
|
|
await srcfs.SetLastAccessTimeAsync(source,DateTime.Now,token);
|
|
}catch(Exception ex)
|
|
{
|
|
_=ex;
|
|
}
|
|
return true;
|
|
}
|
|
public static bool CopyFile(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath path,IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
return srcfs.CopyFile(destfs,path,path,progress,bufferLength);
|
|
}
|
|
|
|
public static bool CopyFile(this IVirtualFilesystem srcfs,IVirtualFilesystem destfs,UnixPath source,UnixPath destination,IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
DateTime laccess=DateTime.Now;
|
|
try{
|
|
laccess = srcfs.GetLastAccessTime(source);
|
|
if(destfs.DirectoryExists(destination)) destination /= source.Name;
|
|
using(var src = srcfs.Open(source,FileMode.Open,FileAccess.Read,FileShare.Read))
|
|
{
|
|
using(var dest = destfs.Open(destination,FileMode.OpenOrCreate,FileAccess.Write,FileShare.None))
|
|
{
|
|
byte[] buffer = new byte[bufferLength];
|
|
int read=0;
|
|
long readTotal=0;
|
|
long length = src.Length;
|
|
|
|
do
|
|
{
|
|
read = src.Read(buffer,0,buffer.Length);
|
|
readTotal += read;
|
|
dest.Write(buffer,0,read);
|
|
progress?.Report(new TransferProgress(readTotal,length,source,destination));
|
|
}
|
|
while(read != 0);
|
|
}
|
|
}
|
|
}catch(Exception ex)
|
|
{
|
|
_=ex;
|
|
return false;
|
|
}
|
|
destfs.SetCreationTime(destination,DateTime.Now);
|
|
destfs.SetLastWriteTime(destination,srcfs.GetLastWriteTime(source));
|
|
destfs.SetLastAccessTime(destination,laccess);
|
|
try
|
|
{
|
|
srcfs.SetLastAccessTime(source,DateTime.Now);
|
|
}catch(Exception ex)
|
|
{
|
|
_=ex;
|
|
}
|
|
return true;
|
|
}
|
|
public static bool CopyFile(this IVirtualFilesystem fs,UnixPath source,UnixPath dest,IProgress<TransferProgress> progress = null,int bufferLength=4096)
|
|
{
|
|
return fs.CopyFile(fs,source,dest,progress,bufferLength);
|
|
}
|
|
public static bool CopyDirectory(this IVirtualFilesystem fs,IVirtualFilesystem destfs,UnixPath path,IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
return fs.CopyDirectory(destfs,path,path,progress,bufferLength);
|
|
}
|
|
public static bool CopyDirectory(this IVirtualFilesystem fs,IVirtualFilesystem destfs,UnixPath source,UnixPath destination,IProgress<TransferProgress> progress=null,int bufferLength=4096)
|
|
{
|
|
DateTime laccess=DateTime.Now;
|
|
try{
|
|
laccess = fs.GetLastAccessTime(source);
|
|
if(!destfs.DirectoryExists(destination))
|
|
destfs.CreateDirectory(destination);
|
|
foreach(var directory in fs.EnumerateDirectories(source))
|
|
{
|
|
var newPath = destination / directory.Name;
|
|
fs.CopyDirectory(destfs,directory,newPath,progress,bufferLength);
|
|
}
|
|
foreach(var file in fs.EnumerateFiles(source))
|
|
{
|
|
var newPath = destination / file.Name;
|
|
fs.CopyFile(destfs,file,newPath,progress,bufferLength);
|
|
}
|
|
}catch(Exception ex)
|
|
{
|
|
_=ex;
|
|
return false;
|
|
}
|
|
destfs.SetCreationTime(destination,DateTime.Now);
|
|
destfs.SetLastWriteTime(destination,fs.GetLastWriteTime(source));
|
|
destfs.SetLastAccessTime(destination,laccess);
|
|
try
|
|
{
|
|
fs.SetLastAccessTime(source,DateTime.Now);
|
|
}catch(Exception ex)
|
|
{
|
|
_=ex;
|
|
}
|
|
return true;
|
|
}
|
|
public static bool CopyDirectory(this IVirtualFilesystem fs,UnixPath source,UnixPath destination,IProgress<TransferProgress> progress=null,int bufferLength = 4096)
|
|
{
|
|
return fs.CopyDirectory(fs,source,destination,progress,bufferLength);
|
|
}
|
|
|
|
public static double DivideByWith2Digits(long value,long divBy)
|
|
{
|
|
return Math.Round((double)value / (double)divBy,2);
|
|
}
|
|
|
|
public static double DivideByPowWith2Digits(long value,int unitSz,int pow)
|
|
{
|
|
return DivideByWith2Digits(value,(long)Math.Pow(unitSz,pow));
|
|
}
|
|
|
|
public static string ToDataUnits(this long val,bool binary=true)
|
|
{
|
|
int unitSz = binary ? 1024 : 1000;
|
|
string bytesSuffix = binary ? "iB" : "B";
|
|
|
|
if(val < unitSz)
|
|
{
|
|
return $"{val} B";
|
|
}
|
|
else if(val < Math.Pow(unitSz,2))
|
|
{
|
|
|
|
return $"{DivideByPowWith2Digits(val,unitSz,1)} k{bytesSuffix}";
|
|
}
|
|
else if(val < Math.Pow(unitSz,3))
|
|
{
|
|
|
|
return $"{DivideByPowWith2Digits(val,unitSz,2)} M{bytesSuffix}";
|
|
}
|
|
else if(val < Math.Pow(unitSz,4))
|
|
{
|
|
|
|
return $"{DivideByPowWith2Digits(val,unitSz,3)} G{bytesSuffix}";
|
|
}
|
|
return $"{DivideByPowWith2Digits(val,unitSz,4)} T{bytesSuffix}";
|
|
}
|
|
|
|
}
|
|
public class TransferProgress
|
|
{
|
|
public bool HasFiles {get;private set;}
|
|
|
|
public UnixPath DestinationPath {get;private set;}
|
|
public UnixPath SourcePath {get;private set;}
|
|
public long CopiedBytes {get;private set;}
|
|
public long RemainingBytes {get{return Length - CopiedBytes;}}
|
|
public long Length {get;private set;}
|
|
|
|
public double ProgressRaw {get;private set;}
|
|
public int Progress {get{return (int)(Math.Floor((double)(Progress * 100)) % 101);}}
|
|
public TransferProgress(long offset,long length,UnixPath src,UnixPath dest)
|
|
{
|
|
SourcePath = src;
|
|
DestinationPath = dest;
|
|
HasFiles = true;
|
|
CopiedBytes = offset;
|
|
Length = length;
|
|
|
|
|
|
if(length != 0)
|
|
{
|
|
ProgressRaw = offset / length;
|
|
}else{
|
|
|
|
ProgressRaw=0;
|
|
}
|
|
}
|
|
public TransferProgress(long offset,long length) : this(offset,length,new UnixPath(),new UnixPath())
|
|
{
|
|
HasFiles=false;
|
|
}
|
|
public override string ToString()
|
|
{
|
|
return ToString(true);
|
|
}
|
|
public string ToString(bool binary)
|
|
{
|
|
return $"{Progress}% {CopiedBytes.ToDataUnits(binary)}/{Length.ToDataUnits(binary)}";
|
|
}
|
|
}
|
|
}
|