diff --git a/Duplicati/Library/Backend/AlternativeFTP/AlternativeFTPBackend.cs b/Duplicati/Library/Backend/AlternativeFTP/AlternativeFTPBackend.cs
index c91d54c46..02557152b 100644
--- a/Duplicati/Library/Backend/AlternativeFTP/AlternativeFTPBackend.cs
+++ b/Duplicati/Library/Backend/AlternativeFTP/AlternativeFTPBackend.cs
@@ -27,7 +27,8 @@ using System.Security.Authentication;
using Duplicati.Library.Interface;
using Uri = System.Uri;
using CoreUtility = Duplicati.Library.Utility.Utility;
-
+using Duplicati.Library.IO;
+
namespace Duplicati.Library.Backend.AlternativeFTP
{
// ReSharper disable once RedundantExtendsListEntry
diff --git a/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs b/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs
index f54f2f578..7e7f74501 100644
--- a/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs
+++ b/Duplicati/Library/Backend/AzureBlob/AzureBlobWrapper.cs
@@ -21,6 +21,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using Duplicati.Library.IO;
using Duplicati.Library.Interface;
using Duplicati.Library.Utility;
using Microsoft.WindowsAzure.Storage;
diff --git a/Duplicati/Library/Backend/AzureBlob/Duplicati.Library.Backend.AzureBlob.csproj b/Duplicati/Library/Backend/AzureBlob/Duplicati.Library.Backend.AzureBlob.csproj
index e6a2c474c..74abcb7f4 100644
--- a/Duplicati/Library/Backend/AzureBlob/Duplicati.Library.Backend.AzureBlob.csproj
+++ b/Duplicati/Library/Backend/AzureBlob/Duplicati.Library.Backend.AzureBlob.csproj
@@ -79,6 +79,10 @@
{B68F2214-951F-4F78-8488-66E1ED3F50BF}
Duplicati.Library.Localization
+
+ {D63E53E4-A458-4C2F-914D-92F715F58ACF}
+ Duplicati.Library.IO
+
diff --git a/Duplicati/Library/Backend/CloudFiles/CloudFiles.cs b/Duplicati/Library/Backend/CloudFiles/CloudFiles.cs
index c8d580be3..eba81377e 100644
--- a/Duplicati/Library/Backend/CloudFiles/CloudFiles.cs
+++ b/Duplicati/Library/Backend/CloudFiles/CloudFiles.cs
@@ -23,7 +23,8 @@ using System.Linq;
using System.Text;
using System.Net;
using Duplicati.Library.Interface;
-
+using Duplicati.Library.IO;
+
namespace Duplicati.Library.Backend
{
public class CloudFiles : IBackend, IStreamingBackend
diff --git a/Duplicati/Library/Backend/CloudFiles/Duplicati.Library.Backend.CloudFiles.csproj b/Duplicati/Library/Backend/CloudFiles/Duplicati.Library.Backend.CloudFiles.csproj
index b1151e757..9a785568a 100644
--- a/Duplicati/Library/Backend/CloudFiles/Duplicati.Library.Backend.CloudFiles.csproj
+++ b/Duplicati/Library/Backend/CloudFiles/Duplicati.Library.Backend.CloudFiles.csproj
@@ -57,6 +57,10 @@
{B68F2214-951F-4F78-8488-66E1ED3F50BF}
Duplicati.Library.Localization
+
+ {D63E53E4-A458-4C2F-914D-92F715F58ACF}
+ Duplicati.Library.IO
+
diff --git a/Duplicati/Library/Backend/Dropbox/Dropbox.cs b/Duplicati/Library/Backend/Dropbox/Dropbox.cs
index 27b88d9c1..9a4e055de 100644
--- a/Duplicati/Library/Backend/Dropbox/Dropbox.cs
+++ b/Duplicati/Library/Backend/Dropbox/Dropbox.cs
@@ -2,7 +2,8 @@
using System.Collections.Generic;
using System.IO;
using Duplicati.Library.Interface;
-
+using Duplicati.Library.IO;
+
namespace Duplicati.Library.Backend
{
public class Dropbox : IBackend, IStreamingBackend
@@ -49,7 +50,7 @@ namespace Duplicati.Library.Backend
get { return "dropbox"; }
}
- private FileEntry ParseEntry(MetaData md)
+ private IFileEntry ParseEntry(MetaData md)
{
var ife = new FileEntry(md.name);
if (md.IsFile)
diff --git a/Duplicati/Library/Backend/Dropbox/Duplicati.Library.Backend.Dropbox.csproj b/Duplicati/Library/Backend/Dropbox/Duplicati.Library.Backend.Dropbox.csproj
index 780fc7a85..8fe7a70be 100644
--- a/Duplicati/Library/Backend/Dropbox/Duplicati.Library.Backend.Dropbox.csproj
+++ b/Duplicati/Library/Backend/Dropbox/Duplicati.Library.Backend.Dropbox.csproj
@@ -61,6 +61,10 @@
{B68F2214-951F-4F78-8488-66E1ED3F50BF}
Duplicati.Library.Localization
+
+ {D63E53E4-A458-4C2F-914D-92F715F58ACF}
+ Duplicati.Library.IO
+
diff --git a/Duplicati/Library/Backend/File/FileBackend.cs b/Duplicati/Library/Backend/File/FileBackend.cs
index 56b1b3566..93eadccda 100644
--- a/Duplicati/Library/Backend/File/FileBackend.cs
+++ b/Duplicati/Library/Backend/File/FileBackend.cs
@@ -39,8 +39,9 @@ namespace Duplicati.Library.Backend
private bool m_hasAutenticated;
private readonly bool m_forceReauth;
- private readonly byte[] m_copybuffer = new byte[Duplicati.Library.Utility.Utility.DEFAULT_BUFFER_SIZE];
+ private readonly byte[] m_copybuffer = new byte[Utility.Utility.DEFAULT_BUFFER_SIZE];
+ private static ISystemIO systemIO = SystemIO.IO_OS(Utility.Utility.IsClientWindows);
public File()
{
@@ -61,12 +62,14 @@ namespace Duplicati.Library.Backend
m_password = uri.Password;
if (!System.IO.Path.IsPathRooted(m_path))
- m_path = System.IO.Path.GetFullPath(m_path);
+ m_path = systemIO.PathGetFullPath(m_path);
if (options.ContainsKey(OPTION_ALTERNATE_PATHS))
{
- List paths = new List();
- paths.Add(m_path);
+ List paths = new List
+ {
+ m_path
+ };
paths.AddRange(options[OPTION_ALTERNATE_PATHS].Split(new string[] { System.IO.Path.PathSeparator.ToString() }, StringSplitOptions.RemoveEmptyEntries));
//On windows we expand the drive letter * to all drives
@@ -101,7 +104,7 @@ namespace Duplicati.Library.Backend
{
try
{
- if (System.IO.Directory.Exists(p) && (markerfile == null || System.IO.File.Exists(System.IO.Path.Combine(p, markerfile))))
+ if (systemIO.DirectoryExists(p) && (markerfile == null || systemIO.FileExists(systemIO.PathCombine(p, markerfile))))
{
m_path = p;
break;
@@ -125,13 +128,10 @@ namespace Duplicati.Library.Backend
{
try
{
- if (!string.IsNullOrEmpty(m_username) && m_password != null)
+ if (!string.IsNullOrEmpty(m_username) && m_password != null && !m_hasAutenticated)
{
- if (!m_hasAutenticated)
- {
- Win32.PreAuthenticate(m_path, m_username, m_password, m_forceReauth);
- m_hasAutenticated = true;
- }
+ Win32.PreAuthenticate(m_path, m_username, m_password, m_forceReauth);
+ m_hasAutenticated = true;
}
}
catch
@@ -142,10 +142,10 @@ namespace Duplicati.Library.Backend
{
PreAuthenticate();
- if (!System.IO.Directory.Exists(m_path))
+ if (!systemIO.DirectoryExists(m_path))
throw new FolderMissingException(Strings.FileBackend.FolderMissingError(m_path));
- return SystemIO.IO_OS(Utility.Utility.IsClientWindows).PathCombine(m_path, remotename);
+ return systemIO.PathCombine(m_path, remotename);
}
#region IBackendInterface Members
@@ -169,21 +169,17 @@ namespace Duplicati.Library.Backend
{
PreAuthenticate();
- if (!System.IO.Directory.Exists(m_path))
+ if (!systemIO.DirectoryExists(m_path))
throw new FolderMissingException(Strings.FileBackend.FolderMissingError(m_path));
- foreach (string s in System.IO.Directory.EnumerateFiles(m_path))
+ foreach (string s in systemIO.EnumerateFileSystemEntries(m_path))
{
- System.IO.FileInfo fi = new System.IO.FileInfo(s);
- yield return new FileEntry(fi.Name, fi.Length, fi.LastAccessTime, fi.LastWriteTime);
+ yield return systemIO.FileEntry(s);
}
- foreach (string s in System.IO.Directory.EnumerateDirectories(m_path))
+ foreach (string s in systemIO.EnumerateDirectories(m_path))
{
- System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(s);
- FileEntry fe = new FileEntry(di.Name, 0, di.LastAccessTime, di.LastWriteTime);
- fe.IsFolder = true;
- yield return fe;
+ yield return systemIO.DirectoryEntry(s);
}
}
@@ -191,7 +187,7 @@ namespace Duplicati.Library.Backend
private static Random random = new Random();
public void Put(string remotename, System.IO.Stream stream)
{
- using(System.IO.FileStream writestream = System.IO.File.Open(GetRemoteName(remotename), System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
+ using(System.IO.FileStream writestream = systemIO.FileOpenWrite(GetRemoteName(remotename)))
{
if (random.NextDouble() > 0.6666)
throw new Exception("Random upload failure");
@@ -201,14 +197,15 @@ namespace Duplicati.Library.Backend
#else
public void Put(string remotename, System.IO.Stream stream)
{
- using(System.IO.FileStream writestream = System.IO.File.Open(GetRemoteName(remotename), System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
+ using(System.IO.FileStream writestream = systemIO.FileOpenWrite(GetRemoteName(remotename)))
Utility.Utility.CopyStream(stream, writestream, true, m_copybuffer);
}
#endif
public void Get(string remotename, System.IO.Stream stream)
{
- using (System.IO.FileStream readstream = System.IO.File.Open(GetRemoteName(remotename), System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read))
+ // FileOpenRead has flags System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read
+ using (System.IO.FileStream readstream = systemIO.FileOpenRead(GetRemoteName(remotename)))
Utility.Utility.CopyStream(readstream, stream, true, m_copybuffer);
}
@@ -217,23 +214,23 @@ namespace Duplicati.Library.Backend
string path = GetRemoteName(remotename);
if (m_moveFile)
{
- if (System.IO.File.Exists(path))
- System.IO.File.Delete(path);
+ if (systemIO.FileExists(path))
+ systemIO.FileDelete(path);
- System.IO.File.Move(filename, path);
+ systemIO.FileMove(filename, path);
}
else
- System.IO.File.Copy(filename, path, true);
+ systemIO.FileCopy(filename, path, true);
}
public void Get(string remotename, string filename)
{
- System.IO.File.Copy(GetRemoteName(remotename), filename, true);
+ systemIO.FileCopy(GetRemoteName(remotename), filename, true);
}
public void Delete(string remotename)
{
- System.IO.File.Delete(GetRemoteName(remotename));
+ systemIO.FileDelete(GetRemoteName(remotename));
}
public IList SupportedCommands
@@ -267,10 +264,10 @@ namespace Duplicati.Library.Backend
public void CreateFolder()
{
- if (System.IO.Directory.Exists(m_path))
+ if (systemIO.DirectoryExists(m_path))
throw new FolderAreadyExistedException();
- System.IO.Directory.CreateDirectory(m_path);
+ systemIO.DirectoryCreate(m_path);
}
#endregion
@@ -278,11 +275,9 @@ namespace Duplicati.Library.Backend
#region IDisposable Members
public void Dispose()
- {
- if (m_username != null)
- m_username = null;
- if (m_password != null)
- m_password = null;
+ {
+ m_username = null;
+ m_password = null;
}
#endregion
@@ -297,7 +292,7 @@ namespace Duplicati.Library.Backend
string root;
if (Utility.Utility.IsClientLinux)
{
- string path = Util.AppendDirSeparator(System.IO.Path.GetFullPath(m_path));
+ string path = Util.AppendDirSeparator(systemIO.PathGetFullPath(m_path));
root = "/";
//Find longest common prefix from mounted devices
@@ -309,7 +304,7 @@ namespace Duplicati.Library.Backend
}
else
{
- root = SystemIO.IO_OS(Utility.Utility.IsClientWindows).GetPathRoot(m_path);
+ root = systemIO.GetPathRoot(m_path);
}
// On Windows, DriveInfo is only valid for lettered drives. (e.g., not for UNC paths and shares)
@@ -338,16 +333,15 @@ namespace Duplicati.Library.Backend
{
return new QuotaInfo(driveInfo.TotalSize, driveInfo.AvailableFreeSpace);
}
- else if (Utility.Utility.IsClientWindows)
+
+ if (Utility.Utility.IsClientWindows)
{
// If we can't get the DriveInfo on Windows, fallback to GetFreeDiskSpaceEx
// https://stackoverflow.com/questions/2050343/programmatically-determining-space-available-from-unc-path
return GetDiskFreeSpace(m_path);
}
- else
- {
- return null;
- }
+
+ return null;
}
}
@@ -360,9 +354,9 @@ namespace Duplicati.Library.Backend
{
var source = GetRemoteName(oldname);
var target = GetRemoteName(newname);
- if (System.IO.File.Exists(target))
- System.IO.File.Delete(target);
- System.IO.File.Move(source, target);
+ if (systemIO.FileExists(target))
+ systemIO.FileDelete(target);
+ systemIO.FileMove(source, target);
}
///
diff --git a/Duplicati/Library/Backend/Mega/Duplicati.Library.Backend.Mega.csproj b/Duplicati/Library/Backend/Mega/Duplicati.Library.Backend.Mega.csproj
index 80da47791..3247ba94a 100644
--- a/Duplicati/Library/Backend/Mega/Duplicati.Library.Backend.Mega.csproj
+++ b/Duplicati/Library/Backend/Mega/Duplicati.Library.Backend.Mega.csproj
@@ -59,6 +59,10 @@
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}
Duplicati.Library.Utility
+
+ {D63E53E4-A458-4C2F-914D-92F715F58ACF}
+ Duplicati.Library.IO
+
diff --git a/Duplicati/Library/Backend/Mega/MegaBackend.cs b/Duplicati/Library/Backend/Mega/MegaBackend.cs
index 694d72ba7..5e7358d40 100644
--- a/Duplicati/Library/Backend/Mega/MegaBackend.cs
+++ b/Duplicati/Library/Backend/Mega/MegaBackend.cs
@@ -19,7 +19,8 @@ using System.Linq;
using System.Collections.Generic;
using Duplicati.Library.Interface;
using CG.Web.MegaApiClient;
-
+using Duplicati.Library.IO;
+
namespace Duplicati.Library.Backend.Mega
{
public class MegaBackend: IBackend, IStreamingBackend
diff --git a/Duplicati/Library/Backend/OneDrive/MicrosoftGraphBackend.cs b/Duplicati/Library/Backend/OneDrive/MicrosoftGraphBackend.cs
index 3205083b3..954b4872b 100644
--- a/Duplicati/Library/Backend/OneDrive/MicrosoftGraphBackend.cs
+++ b/Duplicati/Library/Backend/OneDrive/MicrosoftGraphBackend.cs
@@ -10,6 +10,7 @@ using System.Threading;
using Duplicati.Library.Backend.MicrosoftGraph;
using Duplicati.Library.Interface;
+using Duplicati.Library.IO;
using Duplicati.Library.Utility;
using Newtonsoft.Json;
diff --git a/Duplicati/Library/Backend/Rclone/Duplicati.Library.Backend.Rclone.csproj b/Duplicati/Library/Backend/Rclone/Duplicati.Library.Backend.Rclone.csproj
index 7ff48865b..dfc3d2e2e 100644
--- a/Duplicati/Library/Backend/Rclone/Duplicati.Library.Backend.Rclone.csproj
+++ b/Duplicati/Library/Backend/Rclone/Duplicati.Library.Backend.Rclone.csproj
@@ -54,6 +54,10 @@
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}
Duplicati.Library.Interface
+
+ {D63E53E4-A458-4C2F-914D-92F715F58ACF}
+ Duplicati.Library.IO
+
diff --git a/Duplicati/Library/Backend/Rclone/Rclone.cs b/Duplicati/Library/Backend/Rclone/Rclone.cs
index dbdba63c7..9f73b324f 100644
--- a/Duplicati/Library/Backend/Rclone/Rclone.cs
+++ b/Duplicati/Library/Backend/Rclone/Rclone.cs
@@ -27,7 +27,8 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Globalization;
using System.IO;
-
+using Duplicati.Library.IO;
+
namespace Duplicati.Library.Backend
{
public class Rclone : IBackend
diff --git a/Duplicati/Library/Backend/S3/S3Wrapper.cs b/Duplicati/Library/Backend/S3/S3Wrapper.cs
index 76df7ce71..5288dfbd4 100644
--- a/Duplicati/Library/Backend/S3/S3Wrapper.cs
+++ b/Duplicati/Library/Backend/S3/S3Wrapper.cs
@@ -169,7 +169,7 @@ namespace Duplicati.Library.Backend
{
if (alreadyReturned.Add(obj.Key))
{
- yield return new FileEntry(
+ yield return new IO.FileEntry(
obj.Key,
obj.Size,
obj.LastModified,
diff --git a/Duplicati/Library/Backend/Sia/Duplicati.Library.Backend.Sia.csproj b/Duplicati/Library/Backend/Sia/Duplicati.Library.Backend.Sia.csproj
index 4c67ec09a..d632c39a7 100644
--- a/Duplicati/Library/Backend/Sia/Duplicati.Library.Backend.Sia.csproj
+++ b/Duplicati/Library/Backend/Sia/Duplicati.Library.Backend.Sia.csproj
@@ -58,6 +58,10 @@
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}
Duplicati.Library.Interface
+
+ {D63E53E4-A458-4C2F-914D-92F715F58ACF}
+ Duplicati.Library.IO
+
diff --git a/Duplicati/Library/Backend/Sia/Sia.cs b/Duplicati/Library/Backend/Sia/Sia.cs
index 2576bdd0a..c23892317 100644
--- a/Duplicati/Library/Backend/Sia/Sia.cs
+++ b/Duplicati/Library/Backend/Sia/Sia.cs
@@ -6,6 +6,7 @@ using System.Net;
using Duplicati.Library.Interface;
using Duplicati.Library.Utility;
using Newtonsoft.Json;
+using Duplicati.Library.IO;
namespace Duplicati.Library.Backend.Sia
{
@@ -296,9 +297,11 @@ namespace Duplicati.Library.Backend.Sia
// in our target path
if (f.Siapath.StartsWith(m_targetpath, StringComparison.Ordinal))
{
- FileEntry fe = new FileEntry(f.Siapath.Substring(m_targetpath.Length + 1));
- fe.Size = f.Filesize;
- fe.IsFolder = false;
+ FileEntry fe = new FileEntry(f.Siapath.Substring(m_targetpath.Length + 1))
+ {
+ Size = f.Filesize,
+ IsFolder = false
+ };
yield return fe;
}
}
diff --git a/Duplicati/Library/IO/Duplicati.Library.IO.csproj b/Duplicati/Library/IO/Duplicati.Library.IO.csproj
index a93a16ff6..744b538f3 100644
--- a/Duplicati/Library/IO/Duplicati.Library.IO.csproj
+++ b/Duplicati/Library/IO/Duplicati.Library.IO.csproj
@@ -67,6 +67,7 @@
+
@@ -87,6 +88,10 @@
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}
Duplicati.Library.Logging
+
+ {C5899F45-B0FF-483C-9D38-24A9FCAAB237}
+ Duplicati.Library.Interface
+
diff --git a/Duplicati/Library/Interface/FileEntry.cs b/Duplicati/Library/IO/FileEntry.cs
similarity index 94%
rename from Duplicati/Library/Interface/FileEntry.cs
rename to Duplicati/Library/IO/FileEntry.cs
index 5164a968d..aafeddf0f 100644
--- a/Duplicati/Library/Interface/FileEntry.cs
+++ b/Duplicati/Library/IO/FileEntry.cs
@@ -18,10 +18,9 @@
//
#endregion
using System;
-using System.Collections.Generic;
-using System.Text;
+using Duplicati.Library.Interface;
-namespace Duplicati.Library.Interface
+namespace Duplicati.Library.IO
{
///
/// The primary implementation of the file interface
diff --git a/Duplicati/Library/IO/ISystemIO.cs b/Duplicati/Library/IO/ISystemIO.cs
index 7385dc291..e53d2339f 100644
--- a/Duplicati/Library/IO/ISystemIO.cs
+++ b/Duplicati/Library/IO/ISystemIO.cs
@@ -18,7 +18,8 @@
using System;
using System.IO;
using System.Collections.Generic;
-
+using Duplicati.Library.Interface;
+
namespace Duplicati.Library.IO
{
///
@@ -26,6 +27,7 @@ namespace Duplicati.Library.IO
///
public interface ISystemIO
{
+ IFileEntry DirectoryEntry(string path);
void DirectoryDelete(string path);
void DirectoryDelete(string path, bool recursive);
void DirectoryCreate(string path);
@@ -35,18 +37,21 @@ namespace Duplicati.Library.IO
DateTime DirectoryGetLastWriteTimeUtc(string path);
DateTime DirectoryGetCreationTimeUtc(string path);
+
+ IFileEntry FileEntry(string path);
void FileMove(string source, string target);
void FileDelete(string path);
+ void FileCopy(string source, string target, bool overwrite);
void FileSetLastWriteTimeUtc(string path, DateTime time);
void FileSetCreationTimeUtc(string path, DateTime time);
DateTime FileGetLastWriteTimeUtc(string path);
DateTime FileGetCreationTimeUtc(string path);
bool FileExists(string path);
long FileLength(string path);
- Stream FileOpenRead(string path);
- Stream FileOpenWrite(string path);
- Stream FileOpenReadWrite(string path);
- Stream FileCreate(string path);
+ FileStream FileOpenRead(string path);
+ FileStream FileOpenWrite(string path);
+ FileStream FileOpenReadWrite(string path);
+ FileStream FileCreate(string path);
FileAttributes GetFileAttributes(string path);
void SetFileAttributes(string path, FileAttributes attributes);
void CreateSymlink(string symlinkfile, string target, bool asDir);
@@ -56,6 +61,7 @@ namespace Duplicati.Library.IO
string PathGetExtension(string path);
string PathChangeExtension(string path, string extension);
string PathCombine(params string[] paths);
+ string PathGetFullPath(string path);
string GetPathRoot(string path);
string[] GetDirectories(string path);
string[] GetFiles(string path);
@@ -63,9 +69,11 @@ namespace Duplicati.Library.IO
DateTime GetCreationTimeUtc(string path);
DateTime GetLastWriteTimeUtc(string path);
IEnumerable EnumerateFileSystemEntries(string path);
+ IEnumerable EnumerateDirectories(string path);
void SetMetadata(string path, Dictionary metdata, bool restorePermissions);
Dictionary GetMetadata(string path, bool isSymlink, bool followSymlink);
}
+
}
diff --git a/Duplicati/Library/IO/SystemIOLinux.cs b/Duplicati/Library/IO/SystemIOLinux.cs
index 378376f1f..41586abe3 100644
--- a/Duplicati/Library/IO/SystemIOLinux.cs
+++ b/Duplicati/Library/IO/SystemIOLinux.cs
@@ -19,7 +19,8 @@ using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
-
+using Duplicati.Library.Interface;
+
namespace Duplicati.Library.IO
{
public struct SystemIOLinux : ISystemIO
@@ -70,22 +71,22 @@ namespace Duplicati.Library.IO
return File.Exists(path);
}
- public Stream FileOpenRead(string path)
+ public FileStream FileOpenRead(string path)
{
return File.OpenRead(path);
}
- public Stream FileOpenWrite(string path)
+ public FileStream FileOpenWrite(string path)
{
return File.OpenWrite(path);
}
- public Stream FileOpenReadWrite(string path)
+ public FileStream FileOpenReadWrite(string path)
{
return File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
}
- public Stream FileCreate(string path)
+ public FileStream FileCreate(string path)
{
return File.Create(path);
}
@@ -233,20 +234,6 @@ namespace Duplicati.Library.IO
}
}
}
- #endregion
-
- ///
- /// Normalizes a path, by removing any trailing slash, before calling system methods
- ///
- /// The path to normalize.
- /// The normalized path.
- public static string NormalizePath(string path)
- {
- var p = Path.GetFullPath(path);
-
- // This should not be required, but some versions of Mono apperently do not strip the trailing slash
- return p.Length > 1 && p[p.Length - 1] == Path.DirectorySeparatorChar ? p.Substring(0, p.Length - 1) : p;
- }
public string GetPathRoot(string path)
{
@@ -276,7 +263,52 @@ namespace Duplicati.Library.IO
public DateTime GetLastWriteTimeUtc(string path)
{
return File.GetLastWriteTimeUtc(path);
+ }
+
+ public IEnumerable EnumerateDirectories(string path)
+ {
+ return Directory.EnumerateDirectories(path);
+ }
+
+ public void FileCopy(string source, string target, bool overwrite)
+ {
+ File.Copy(source, target, overwrite);
}
+
+ public string PathGetFullPath(string path)
+ {
+ return Path.GetFullPath(path);
+ }
+
+ #endregion
+
+ ///
+ /// Normalizes a path, by removing any trailing slash, before calling system methods
+ ///
+ /// The path to normalize.
+ /// The normalized path.
+ public static string NormalizePath(string path)
+ {
+ var p = Path.GetFullPath(path);
+
+ // This should not be required, but some versions of Mono apperently do not strip the trailing slash
+ return p.Length > 1 && p[p.Length - 1] == Path.DirectorySeparatorChar ? p.Substring(0, p.Length - 1) : p;
+ }
+
+ public IFileEntry DirectoryEntry(string path)
+ {
+ var dInfo = new DirectoryInfo(path);
+ return new FileEntry(dInfo.Name, 0, dInfo.LastAccessTime, dInfo.LastWriteTime)
+ {
+ IsFolder = true
+ };
+ }
+
+ public IFileEntry FileEntry(string path)
+ {
+ var fileInfo = new FileInfo(path);
+ return new FileEntry(fileInfo.Name, fileInfo.Length, fileInfo.LastAccessTime, fileInfo.LastWriteTime);
+ }
}
}
diff --git a/Duplicati/Library/IO/SystemIOWindows.cs b/Duplicati/Library/IO/SystemIOWindows.cs
index d6b0c8a61..17dae205f 100644
--- a/Duplicati/Library/IO/SystemIOWindows.cs
+++ b/Duplicati/Library/IO/SystemIOWindows.cs
@@ -22,7 +22,7 @@ using System.IO;
using Alphaleonis.Win32.Vss;
using AlphaFS = Alphaleonis.Win32.Filesystem;
-
+using Duplicati.Library.Interface;
namespace Duplicati.Library.IO
{
@@ -180,7 +180,7 @@ namespace Duplicati.Library.IO
return Alphaleonis.Win32.Filesystem.File.Exists(PrefixWithUNC(path));
}
- public System.IO.Stream FileOpenRead(string path)
+ public System.IO.FileStream FileOpenRead(string path)
{
if (!IsPathTooLong(path))
try { return System.IO.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite); }
@@ -190,7 +190,7 @@ namespace Duplicati.Library.IO
return Alphaleonis.Win32.Filesystem.File.Open(PrefixWithUNC(path), FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
}
- public System.IO.Stream FileOpenWrite(string path)
+ public System.IO.FileStream FileOpenWrite(string path)
{
if (!IsPathTooLong(path))
try { return System.IO.File.OpenWrite(path); }
@@ -203,7 +203,7 @@ namespace Duplicati.Library.IO
return FileCreate(path);
}
- public System.IO.Stream FileOpenReadWrite(string path)
+ public System.IO.FileStream FileOpenReadWrite(string path)
{
if (!IsPathTooLong(path))
try { return System.IO.File.Open(path, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, System.IO.FileShare.Read); }
@@ -213,7 +213,7 @@ namespace Duplicati.Library.IO
return Alphaleonis.Win32.Filesystem.File.Open(PrefixWithUNC(path), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
}
- public System.IO.Stream FileCreate(string path)
+ public System.IO.FileStream FileCreate(string path)
{
if (!IsPathTooLong(path))
try { return System.IO.File.Create(path); }
@@ -699,7 +699,84 @@ namespace Duplicati.Library.IO
}
return AlphaFS.File.GetLastWriteTimeUtc(path);
- }
+ }
+
+ public IEnumerable EnumerateDirectories(string path)
+ {
+ if (!IsPathTooLong(path))
+ {
+ try { return Directory.EnumerateDirectories(path); }
+ catch (System.IO.PathTooLongException) { }
+ catch (System.ArgumentException) { }
+ }
+
+ return AlphaFS.Directory.EnumerateDirectories(path);
+ }
+
+ public void FileCopy(string source, string target, bool overwrite)
+ {
+ if (!IsPathTooLong(source) && !IsPathTooLong(target))
+ {
+ try { File.Copy(source, target, overwrite); }
+ catch (System.IO.PathTooLongException) { }
+ catch (System.ArgumentException) { }
+ }
+
+ AlphaFS.File.Copy(source, target, overwrite);
+ }
+
+ public string PathGetFullPath(string path)
+ {
+ if (!IsPathTooLong(path))
+ {
+ try { return System.IO.Path.GetFullPath(path); }
+ catch (System.IO.PathTooLongException) { }
+ catch (System.ArgumentException) { }
+ }
+
+ return AlphaFS.Path.GetFullPath(path);
+ }
+
+ public IFileEntry DirectoryEntry(string path)
+ {
+ if (!IsPathTooLong(path))
+ {
+ try
+ {
+ var dInfo = new DirectoryInfo(path);
+ return new FileEntry(dInfo.Name, 0, dInfo.LastAccessTime, dInfo.LastWriteTime)
+ {
+ IsFolder = true
+ };
+ }
+ catch (System.IO.PathTooLongException) { }
+ catch (System.ArgumentException) { }
+ }
+
+ var dInfoAlphaFS = new AlphaFS.DirectoryInfo(path);
+ return new FileEntry(dInfoAlphaFS.Name, 0, dInfoAlphaFS.LastAccessTime, dInfoAlphaFS.LastWriteTime)
+ {
+ IsFolder = true
+ };
+ }
+
+ public IFileEntry FileEntry(string path)
+ {
+ if (!IsPathTooLong(path))
+ {
+ try
+ {
+ var fileInfo = new FileInfo(path);
+ return new FileEntry(fileInfo.Name, fileInfo.Length, fileInfo.LastAccessTime, fileInfo.LastWriteTime);
+ }
+ catch (System.IO.PathTooLongException) { }
+ catch (System.ArgumentException) { }
+ }
+
+ var fInfoAlphaFS = new AlphaFS.FileInfo(path);
+ return new FileEntry(fInfoAlphaFS.Name, fInfoAlphaFS.Length, fInfoAlphaFS.LastAccessTime, fInfoAlphaFS.LastWriteTime);
+ }
+
#endregion
}
}
diff --git a/Duplicati/Library/Interface/Duplicati.Library.Interface.csproj b/Duplicati/Library/Interface/Duplicati.Library.Interface.csproj
index 6c9bee0eb..a58fd641a 100644
--- a/Duplicati/Library/Interface/Duplicati.Library.Interface.csproj
+++ b/Duplicati/Library/Interface/Duplicati.Library.Interface.csproj
@@ -45,7 +45,6 @@
-
diff --git a/Duplicati/Server/WebServer/RESTMethods/Filesystem.cs b/Duplicati/Server/WebServer/RESTMethods/Filesystem.cs
index 375197de6..f407b641e 100644
--- a/Duplicati/Server/WebServer/RESTMethods/Filesystem.cs
+++ b/Duplicati/Server/WebServer/RESTMethods/Filesystem.cs
@@ -209,7 +209,7 @@ namespace Duplicati.Server.WebServer.RESTMethods
var systemIO = SystemIO.IO_OS(Library.Utility.Utility.IsClientWindows);
- foreach (var s in System.IO.Directory.EnumerateFileSystemEntries(entrypath))
+ foreach (var s in systemIO.EnumerateFileSystemEntries(entrypath))
{
Serializable.TreeNode tn = null;
try
diff --git a/Duplicati/UnitTest/SizeOmittingBackend.cs b/Duplicati/UnitTest/SizeOmittingBackend.cs
index 9f3cb95bf..10480a530 100644
--- a/Duplicati/UnitTest/SizeOmittingBackend.cs
+++ b/Duplicati/UnitTest/SizeOmittingBackend.cs
@@ -19,7 +19,8 @@ using System.Linq;
using Duplicati.Library.Interface;
using System.Collections.Generic;
using System.IO;
-
+using Duplicati.Library.IO;
+
namespace Duplicati.UnitTest
{
public class SizeOmittingBackend : IBackend, IStreamingBackend
@@ -56,7 +57,7 @@ namespace Duplicati.UnitTest
return
from n in m_backend.List()
where !n.IsFolder
- select new Library.Interface.FileEntry(n.Name);
+ select new FileEntry(n.Name);
}
public void Put(string remotename, string filename)
{