Replaced DirectorySeparatorChar.ToString() calls.

This commit is contained in:
verhoek
2018-11-02 17:45:00 +01:00
parent 71c6aca8a7
commit 1275f14405
14 changed files with 116 additions and 412 deletions
+85 -81
View File
@@ -19,7 +19,8 @@ using System;
using System.Linq;
using System.Collections.Generic;
using System.IO;
using Duplicati.Library.IO;
namespace Duplicati.CommandLine
{
public static class Commands
@@ -33,7 +34,7 @@ namespace Duplicati.CommandLine
private readonly ConsoleOutput m_output;
private System.Threading.Thread m_thread;
private readonly TimeSpan m_updateFrequency;
public PeriodicOutput(ConsoleOutput messageSink, TimeSpan updateFrequency)
{
m_output = messageSink;
@@ -45,27 +46,27 @@ namespace Duplicati.CommandLine
m_thread.Name = "Periodic console writer";
m_thread.Start();
}
public void SetReady() { m_readyEvent.Set(); }
public void SetFinished() { m_finishEvent.Set(); }
public bool Join(TimeSpan wait)
{
if (m_thread != null)
return m_thread.Join(wait);
return true;
}
private void ThreadMain()
{
m_readyEvent.WaitOne();
if (m_finishEvent.WaitOne(TimeSpan.FromMilliseconds(10), true))
return;
var last_count = -1L;
var finished = false;
while (true)
{
Duplicati.Library.Main.OperationPhase phase;
@@ -76,10 +77,10 @@ namespace Duplicati.CommandLine
long filesize;
bool counting;
m_output.OperationProgress.UpdateOverall(out phase, out progress, out filesprocessed, out filesizeprocessed, out filecount, out filesize, out counting);
var files = Math.Max(0, filecount - filesprocessed);
var size = Math.Max(0, filesize - filesizeprocessed);
if (finished)
{
files = 0;
@@ -87,21 +88,21 @@ namespace Duplicati.CommandLine
}
else if (size > 0)
files = Math.Max(1, files);
if (last_count < 0 || files != last_count)
if (WriteOutput != null)
WriteOutput(progress, files, size, counting);
if (!counting)
last_count = files;
if (finished)
return;
finished = m_finishEvent.WaitOne(m_updateFrequency, true);
finished = m_finishEvent.WaitOne(m_updateFrequency, true);
}
}
public void Dispose()
{
if (m_thread != null)
@@ -110,7 +111,7 @@ namespace Duplicati.CommandLine
{
m_finishEvent.Set();
m_readyEvent.Set();
if (m_thread != null && m_thread.IsAlive)
{
m_thread.Abort();
@@ -130,7 +131,7 @@ namespace Duplicati.CommandLine
Duplicati.CommandLine.Help.PrintUsage(outwriter, "example", options);
return 0;
}
public static int Help(TextWriter outwriter, Action<Duplicati.Library.Main.Controller> setup, List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
{
Duplicati.CommandLine.Help.PrintUsage(outwriter, args.Count > 1? args[1] : "help", options);
@@ -172,8 +173,8 @@ namespace Duplicati.CommandLine
using(var i = new Library.Main.Controller(backend, options, console))
{
setup(i);
i.ListAffected(args, res =>
{
i.ListAffected(args, res =>
{
if (res.Filesets != null && res.Filesets.Any())
{
outwriter.WriteLine("The following filesets are affected:");
@@ -233,6 +234,15 @@ namespace Duplicati.CommandLine
return 0;
}
}
public static List<string> PrefixArgsWithAsterisk(IList<string> argList)
{
// Prefix all filenames with "*/" so we search all folders
var specialArgChars = new[] { '*', '?', Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
return argList.Select(arg => arg.IndexOfAny(specialArgChars) < 0
&& !arg.StartsWith("[", StringComparison.Ordinal) ? "*" + Util.DirectorySeparatorString + arg : arg).ToList();
}
public static int List(TextWriter outwriter, Action<Duplicati.Library.Main.Controller> setup, List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
{
filter = filter ?? new Duplicati.Library.Utility.FilterExpression();
@@ -245,7 +255,7 @@ namespace Duplicati.CommandLine
setup(i);
var backend = args[0];
args.RemoveAt(0);
if (args.Count == 1)
{
long v;
@@ -272,12 +282,9 @@ namespace Duplicati.CommandLine
}
}
}
// Prefix all filenames with "*/" so we search all folders
for(var ix = 0; ix < args.Count; ix++)
if (args[ix].IndexOfAny(new char[] { '*', '?', System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar }) < 0 && !args[ix].StartsWith("[", StringComparison.Ordinal))
args[ix] = "*" + System.IO.Path.DirectorySeparatorChar.ToString() + args[ix];
args = PrefixArgsWithAsterisk(args);
// Support for not adding the --auth-username if possible
string dbpath;
options.TryGetValue("dbpath", out dbpath);
@@ -304,20 +311,20 @@ namespace Duplicati.CommandLine
}
}
bool controlFiles = Library.Utility.Utility.ParseBoolOption(options, "control-files");
options.Remove("control-files");
var res = controlFiles ? i.ListControlFiles(args, filter) : i.List(args, filter);
//If there are no files matching, and we are looking for one or more files,
//If there are no files matching, and we are looking for one or more files,
// try again with all-versions set
var compareFilter = Library.Utility.JoinedFilterExpression.Join(new Library.Utility.FilterExpression(args), filter);
var isRequestForFiles =
!controlFiles && res.Filesets.Any() &&
(res.Files == null || !res.Files.Any()) &&
var isRequestForFiles =
!controlFiles && res.Filesets.Any() &&
(res.Files == null || !res.Files.Any()) &&
!compareFilter.Empty;
if (isRequestForFiles && !Library.Utility.Utility.ParseBoolOption(options, "all-versions"))
{
outwriter.WriteLine("No files matching, looking in all versions");
@@ -330,7 +337,7 @@ namespace Duplicati.CommandLine
if (res.Filesets.Any() && (res.Files == null || !res.Files.Any()) && compareFilter.Empty)
{
outwriter.WriteLine("Listing filesets:");
foreach(var e in res.Filesets)
{
if (e.FileCount >= 0)
@@ -357,8 +364,8 @@ namespace Duplicati.CommandLine
{
var f = res.Filesets.First();
outwriter.WriteLine("Listing contents {0} ({1}):", f.Version, f.Time);
foreach(var e in res.Files)
outwriter.WriteLine("{0} {1}", e.Path, e.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) ? "" : "(" + Library.Utility.Utility.FormatSizeString(e.Sizes.First()) + ")");
foreach (var e in res.Files)
outwriter.WriteLine("{0} {1}", e.Path, e.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal) ? "" : "(" + Library.Utility.Utility.FormatSizeString(e.Sizes.First()) + ")");
}
else
{
@@ -368,34 +375,34 @@ namespace Duplicati.CommandLine
outwriter.WriteLine(e.Path);
foreach(var nx in res.Filesets.Zip(e.Sizes, (a, b) => new { Index = a.Version, Time = a.Time, Size = b } ))
outwriter.WriteLine("{0}\t: {1} {2}", nx.Index, nx.Time, nx.Size < 0 ? " - " : Library.Utility.Utility.FormatSizeString(nx.Size));
outwriter.WriteLine();
}
}
}
}
return 0;
}
public static int Delete(TextWriter outwriter, Action<Duplicati.Library.Main.Controller> setup, List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
{
var requiredOptions = new string[] { "keep-time", "keep-versions", "version" };
if (!options.Keys.Any(x => requiredOptions.Contains(x, StringComparer.OrdinalIgnoreCase)))
{
outwriter.WriteLine(Strings.Program.DeleteCommandNeedsOptions("delete", requiredOptions));
outwriter.WriteLine(Strings.Program.DeleteCommandNeedsOptions("delete", requiredOptions));
return 200;
}
using (var console = new ConsoleOutput(outwriter, options))
using(var i = new Library.Main.Controller(args[0], options, console))
{
setup(i);
args.RemoveAt(0);
var res = i.Delete();
if (!res.DeletedSets.Any())
{
outwriter.WriteLine(Strings.Program.NoFilesetsMatching);
@@ -406,14 +413,14 @@ namespace Duplicati.CommandLine
outwriter.WriteLine(Strings.Program.WouldDeleteBackups);
else
outwriter.WriteLine(Strings.Program.DeletedBackups);
foreach(var f in res.DeletedSets)
outwriter.WriteLine(string.Format("{0}: {1}", f.Item1, f.Item2));
}
}
return 0;
}
public static int Repair(TextWriter outwriter, Action<Duplicati.Library.Main.Controller> setup, List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
@@ -435,23 +442,20 @@ namespace Duplicati.CommandLine
{
if (args.Count < 1)
return PrintWrongNumberOfArguments(outwriter, args, 1);
string backend = args[0];
args.RemoveAt(0);
bool controlFiles = Library.Utility.Utility.ParseBoolOption(options, "control-files");
options.Remove("control-files");
// Prefix all filenames with "*/" so we search all folders
for (var ix = 0; ix < args.Count; ix++)
if (args[ix].IndexOfAny(new char[] { '*', '?', System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar }) < 0 && !args[ix].StartsWith("[", StringComparison.Ordinal))
args[ix] = "*" + System.IO.Path.DirectorySeparatorChar.ToString() + args[ix];
args = PrefixArgsWithAsterisk(args);
// suffix all folders with "*" so we restore all contents in the folder
for (var ix = 0; ix < args.Count; ix++)
if (args[ix].IndexOfAny(new char[] { '*', '?' }) < 0 && !args[ix].StartsWith("[", StringComparison.Ordinal) && args[ix].EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
if (args[ix].IndexOfAny(new char[] { '*', '?' }) < 0 && !args[ix].StartsWith("[", StringComparison.Ordinal) && args[ix].EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
args[ix] += "*";
using(var output = new ConsoleOutput(outwriter, options))
using (var i = new Library.Main.Controller(backend, options, output))
{
@@ -524,7 +528,7 @@ namespace Duplicati.CommandLine
}
}
}
return 0;
}
@@ -532,7 +536,7 @@ namespace Duplicati.CommandLine
{
if (args.Count < 2)
return PrintWrongNumberOfArguments(outwriter, args, 2);
var backend = args[0];
args.RemoveAt(0);
var dirs = args.ToArray();
@@ -647,7 +651,7 @@ namespace Duplicati.CommandLine
return 0;
}
}
public static int Compact(TextWriter outwriter, Action<Duplicati.Library.Main.Controller> setup, List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
{
if (args.Count != 1)
@@ -668,7 +672,7 @@ namespace Duplicati.CommandLine
var fullResults = Duplicati.Library.Utility.Utility.ParseBoolOption(options, "full-result");
if (args.Count != 1 && args.Count != 2)
return PrintWrongNumberOfArguments(outwriter, args, 1);
var tests = 1L;
if (args.Count == 2)
{
@@ -677,7 +681,7 @@ namespace Duplicati.CommandLine
else
tests = Convert.ToInt64(args[1]);
}
Library.Interface.ITestResults result;
using (var console = new ConsoleOutput(outwriter, options))
using (var i = new Library.Main.Controller(args[0], options, console))
@@ -685,7 +689,7 @@ namespace Duplicati.CommandLine
setup(i);
result = i.Test(tests);
}
var totalFiles = result.Verifications.Count();
if (totalFiles == 0)
{
@@ -733,7 +737,7 @@ namespace Duplicati.CommandLine
}
}
}
private static int PrintWrongNumberOfArguments(TextWriter outwriter, List<string> args, int expected)
{
outwriter.WriteLine(Strings.Program.WrongNumberOfCommandsError_v2(args.Count, expected, args.Select(n => "\"" + n + "\"").ToArray()));
@@ -755,7 +759,7 @@ namespace Duplicati.CommandLine
{
if (args.Count > 0)
dbpath = Library.Main.DatabaseLocator.GetDatabasePath(args[0], new Duplicati.Library.Main.Options(options), false, true);
if (dbpath == null)
{
outwriter.WriteLine("No local database found, please add --{0}", "dbpath");
@@ -763,9 +767,9 @@ namespace Duplicati.CommandLine
}
else
options["dbpath"] = dbpath;
}
if (args.Count == 0)
args = new List<string>(new string[] { "file://unused", "report" });
else if (args.Count == 1)
@@ -787,14 +791,14 @@ namespace Duplicati.CommandLine
return 0;
}
public static int ListChanges(TextWriter outwriter, Action<Duplicati.Library.Main.Controller> setup, List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
{
var fullresult = Duplicati.Library.Utility.Utility.ParseBoolOption(options, "full-result");
if (args.Count < 1)
return PrintWrongNumberOfArguments(outwriter, args, 1);
// Support for not adding the --auth-username if possible
string dbpath;
options.TryGetValue("dbpath", out dbpath);
@@ -804,7 +808,7 @@ namespace Duplicati.CommandLine
if (dbpath != null)
options["dbpath"] = dbpath;
}
// Don't ask for passphrase if we have a local db
if (!string.IsNullOrEmpty(dbpath) && System.IO.File.Exists(dbpath) && !options.ContainsKey("no-encryption") && !Duplicati.Library.Utility.Utility.ParseBoolOption(options, "no-local-db"))
{
@@ -814,9 +818,9 @@ namespace Duplicati.CommandLine
options["no-encryption"] = "true";
}
Action<Duplicati.Library.Interface.IListChangesResults, IEnumerable<Tuple<Library.Interface.ListChangesChangeType, Library.Interface.ListChangesElementType, string>>> handler =
(result, items) =>
{
Action<Duplicati.Library.Interface.IListChangesResults, IEnumerable<Tuple<Library.Interface.ListChangesChangeType, Library.Interface.ListChangesElementType, string>>> handler =
(result, items) =>
{
outwriter.WriteLine("Listing changes");
outwriter.WriteLine(" {0}: {1}", result.BaseVersionIndex, result.BaseVersionTimestamp);
outwriter.WriteLine(" {0}: {1}", result.CompareVersionIndex, result.CompareVersionTimestamp);
@@ -912,9 +916,9 @@ namespace Duplicati.CommandLine
result.DeletedFolders + result.DeletedSymlinks + result.DeletedFiles == 0)
outwriter.WriteLine(" No changes found");
outwriter.WriteLine("Size of backup {0}: {1}", result.CompareVersionIndex, Library.Utility.Utility.FormatSizeString(result.CurrentSize));
outwriter.WriteLine("Size of backup {0}: {1}", result.CompareVersionIndex, Library.Utility.Utility.FormatSizeString(result.CurrentSize));
};
using (var console = new ConsoleOutput(outwriter, options))
using (var i = new Library.Main.Controller(args[0], options, console))
{
@@ -927,7 +931,7 @@ namespace Duplicati.CommandLine
return 0;
}
public static int TestFilters(TextWriter outwriter, Action<Duplicati.Library.Main.Controller> setup, List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
{
if (args == null || args.Count < 1)
@@ -935,16 +939,16 @@ namespace Duplicati.CommandLine
outwriter.WriteLine("No source paths given");
return 200;
}
using (var console = new ConsoleOutput(outwriter, options))
using(var i = new Library.Main.Controller("dummy://", options, console))
{
setup(i);
var result = i.TestFilter(args.ToArray(), filter);
outwriter.WriteLine("Matched {0} files ({1})", result.FileCount, Duplicati.Library.Utility.Utility.FormatSizeString(result.FileSize));
}
return 0;
}
@@ -1001,7 +1005,7 @@ namespace Duplicati.CommandLine
setup(i);
i.PurgeFiles(filter);
}
return 0;
}
@@ -1078,9 +1082,9 @@ namespace Duplicati.CommandLine
}
public static int Vacuum(
TextWriter outwriter,
TextWriter outwriter,
Action<Duplicati.Library.Main.Controller> setup,
List<string> args, Dictionary<string, string> options,
List<string> args, Dictionary<string, string> options,
Library.Utility.IFilter filter)
{
if (args.Count != 1)
@@ -208,6 +208,10 @@
<Project>{0797AA22-C5DD-4950-BB60-34765AB8C6DD}</Project>
<Name>Duplicati.Tools</Name>
</ProjectReference>
<ProjectReference Include="..\Library\IO\Duplicati.Library.IO.csproj">
<Project>{D63E53E4-A458-4C2F-914D-92F715F58ACF}</Project>
<Name>Duplicati.Library.IO</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.manifest">
@@ -524,7 +524,7 @@ namespace Duplicati.Library.AutoUpdater
continue;
var fullpath = System.IO.Path.Combine(targetfolder, relpath);
if (relpath.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
if (relpath.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal))
System.IO.Directory.CreateDirectory(fullpath);
else
System.IO.File.Copy(e, fullpath);
@@ -721,7 +721,7 @@ namespace Duplicati.Library.AutoUpdater
inputfolder = Util.AppendDirSeparator(inputfolder);
var baselen = inputfolder.Length;
var dirsep = System.IO.Path.DirectorySeparatorChar.ToString();
var dirsep = Util.DirectorySeparatorString;
ignoreMap.Add(UPDATE_MANIFEST_FILENAME, "");
@@ -66,7 +66,6 @@
<Compile Include="VssBackupComponents.cs" />
<Compile Include="Util.cs" />
<Compile Include="DefineDosDevice.cs" />
<Compile Include="WinNativeMethods.cs" />
<Compile Include="FileEntry.cs" />
</ItemGroup>
<ItemGroup>
+2 -2
View File
@@ -1,4 +1,4 @@
// Copyright (C) 2015, The Duplicati Team
// Copyright (C) 2015, The Duplicati Team
// http://www.duplicati.com, info@duplicati.com
//
@@ -31,7 +31,7 @@ namespace Duplicati.Library.IO
private const string UNCPREFIX = @"\\?\";
private const string UNCPREFIX_SERVER = @"\\?\UNC\";
private const string PATHPREFIX_SERVER = @"\\";
private static readonly string DIRSEP = System.IO.Path.DirectorySeparatorChar.ToString();
private static readonly string DIRSEP = Util.DirectorySeparatorString;
private static bool IsPathTooLong(string path)
{
+1
View File
@@ -26,6 +26,7 @@ namespace Duplicati.Library.IO
/// </summary>
public static readonly string DirectorySeparatorString = Path.DirectorySeparatorChar.ToString();
public static readonly string AltDirectorySeparatorString = Path.AltDirectorySeparatorChar.ToString();
/// <summary>
/// Appends the appropriate directory separator to paths, depending on OS.
-306
View File
@@ -1,306 +0,0 @@
//#region Disclaimer / License
//// Copyright (C) 2015, The Duplicati Team
//// http://www.duplicati.com, info@duplicati.com
////
//// This library is free software; you can redistribute it and/or
//// modify it under the terms of the GNU Lesser General Public
//// License as published by the Free Software Foundation; either
//// version 2.1 of the License, or (at your option) any later version.
////
//// This library 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
//// Lesser General Public License for more details.
////
//// You should have received a copy of the GNU Lesser General Public
//// License along with this library; if not, write to the Free Software
//// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
////
//using System.Security.AccessControl;
//#endregion
//using System;
//using System.Text;
//using System.Runtime.InteropServices;
//using System.ComponentModel;
//using Microsoft.Win32.SafeHandles;
//namespace Duplicati.Library.IO
//{
// /// <summary>
// /// This class contains various Windows system calls related to reading locked files.
// /// Some PInvoke signatures are from http://www.pinvoke.net
// /// </summary>
// public static class WinNativeMethods
// {
// [Flags]
// private enum FileAccess : uint
// {
// GenericNone = 0x00000000,
// GenericRead = 0x80000000,
// GenericWrite = 0x40000000,
// GenericExecute = 0x20000000,
// GenericAll = 0x10000000,
// ReadControl = 0x00020000
// }
// [Flags]
// private enum FileShare : uint
// {
// None = 0x00000000,
// Read = 0x00000001,
// Write = 0x00000002,
// ReadWrite = 0x00000003,
// Delete = 0x00000004
// }
// private enum CreationDisposition : uint
// {
// New = 1,
// CreateAlways = 2,
// OpenExisting = 3,
// OpenAlways = 4,
// TruncateExisting = 5
// }
// [Flags]
// private enum FileAttributes : uint
// {
// Readonly = 0x00000001,
// Hidden = 0x00000002,
// System = 0x00000004,
// Directory = 0x00000010,
// Archive = 0x00000020,
// Device = 0x00000040,
// Normal = 0x00000080,
// Temporary = 0x00000100,
// SparseFile = 0x00000200,
// ReparsePoint = 0x00000400,
// Compressed = 0x00000800,
// Offline = 0x00001000,
// NotContentIndexed = 0x00002000,
// Encrypted = 0x00004000,
// Write_Through = 0x80000000,
// Overlapped = 0x40000000,
// NoBuffering = 0x20000000,
// RandomAccess = 0x10000000,
// SequentialScan = 0x08000000,
// DeleteOnClose = 0x04000000,
// BackupSemantics = 0x02000000,
// PosixSemantics = 0x01000000,
// OpenReparsePoint = 0x00200000,
// OpenNoRecall = 0x00100000,
// FirstPipeInstance = 0x00080000
// }
// private const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
// private const int TOKEN_QUERY = 0x00000008;
// private const int SE_PRIVILEGE_ENABLED = 0x00000002;
// private const string SE_BACKUP_NAME = "SeBackupPrivilege";
// private const string SE_RESTORE_NAME = "SeRestorePrivilege";
// private const int TOKEN_INFORMATION_CLASS_PRIVILEGES = 0x3;
// private const int ATTRIBUTE_FIXED_SIZE = 200;
// [StructLayout(LayoutKind.Sequential)]
// private struct LUID
// {
// public UInt32 LowPart;
// public Int32 HighPart;
// }
// [StructLayout(LayoutKind.Sequential)]
// private struct LUID_AND_ATTRIBUTES
// {
// public LUID Luid;
// public UInt32 Attributes;
// }
// [StructLayout(LayoutKind.Sequential)]
// private struct TOKEN_PRIVILEGES
// {
// public UInt32 PrivilegeCount;
// [MarshalAs(UnmanagedType.ByValArray, SizeConst = ATTRIBUTE_FIXED_SIZE)] //We make sure there is enough room
// public LUID_AND_ATTRIBUTES[] Privileges;
// }
// [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
// private static extern int OpenProcessToken(int ProcessHandle, int DesiredAccess, ref int tokenhandle);
// [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
// private static extern int GetCurrentProcess();
// [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
// private static extern int GetTokenInformation(int tokenhandle, int tokeninformationclass, [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES state, int bufferlength, ref int actualsize);
// [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
// private static extern int LookupPrivilegeValue(string lpsystemname, string lpname, [MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid);
// [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
// private static extern int AdjustTokenPrivileges(int tokenhandle, bool disableprivs, [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES newState, int bufferlength, [MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES previousState, ref int actualsize);
// [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
// private static extern int LookupPrivilegeName(string lpSystemName, [MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid, System.Text.StringBuilder lpName, ref int cchName);
// [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
// private static extern SafeFileHandle CreateFile(
// string lpFileName,
// FileAccess dwDesiredAccess,
// FileShare dwShareMode,
// IntPtr lpSecurityAttributes,
// CreationDisposition dwCreationDisposition,
// FileAttributes dwFlagsAndAttributes,
// IntPtr hTemplateFile
// );
// /// <summary>
// /// Opens a file with backup semantics, only works if the caller has the SeBackupPrivilege
// /// </summary>
// /// <param name="filename">The file to open</param>
// /// <returns>The opened backup filestream</returns>
// public static System.IO.Stream OpenAsBackupFile(string filename)
// {
// var hFile = CreateFile(filename, FileAccess.ReadControl, FileShare.None, IntPtr.Zero, CreationDisposition.OpenExisting, FileAttributes.BackupSemantics | FileAttributes.SequentialScan, IntPtr.Zero);
// if (hFile.IsInvalid)
// throw new Win32Exception(Marshal.GetLastWin32Error());
// //TODO: We need to be able to seek to pos 0
// return new Alphaleonis.Win32.Filesystem.BackupFileStream(hFile, FileSystemRights.Read);
// }
// /// <summary>
// /// Internal helper function that returns two values relating to the SeBackupPrivilege
// /// </summary>
// /// <param name="hasPrivilege">True if the calling proccess has the SeBackupPrivilege, false otherwise</param>
// /// <param name="isEnabled">True if the SeBackupPrivilege is enabled, false otherwise</param>
// private static void GetBackupPrivilege(out bool hasPrivilege, out bool isEnabled)
// {
// int token = 0;
// int outsize = 0;
// TOKEN_PRIVILEGES TP = new TOKEN_PRIVILEGES();
// LUID backupLuid = new LUID();
// if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref token) == 0)
// throw new Win32Exception(Marshal.GetLastWin32Error());
// if (LookupPrivilegeValue(null, SE_BACKUP_NAME, ref backupLuid) == 0)
// throw new Win32Exception(Marshal.GetLastWin32Error());
// if (GetTokenInformation(token, TOKEN_INFORMATION_CLASS_PRIVILEGES, ref TP, Marshal.SizeOf(typeof(TOKEN_PRIVILEGES)), ref outsize) == 0)
// throw new Win32Exception(Marshal.GetLastWin32Error());
//#if DEBUG
// Console.WriteLine("Read token information:");
// PrintTokenInformation(TP);
//#endif
// for (int i = 0; i < TP.PrivilegeCount; i++)
// if (TP.Privileges[i].Luid.LowPart == backupLuid.LowPart && TP.Privileges[i].Luid.HighPart == backupLuid.HighPart)
// {
// isEnabled = (TP.Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) == SE_PRIVILEGE_ENABLED;
// hasPrivilege = true;
// return;
// }
// hasPrivilege = false;
// isEnabled = false;
// }
// /// <summary>
// /// Gets a value indicating if the current process can set the SeBackupPrivilege value
// /// </summary>
// public static bool CanEnableBackupPrivilege
// {
// get
// {
// bool hasPrivilege, isEnabled;
// GetBackupPrivilege(out hasPrivilege, out isEnabled);
// return hasPrivilege;
// }
// }
// /// <summary>
// /// Gets or sets a value indicating if the current process has the backup privilege (SE_BACKUP_NAME)
// /// </summary>
// public static bool BackupPrivilege
// {
// get
// {
// bool hasPrivilege, isEnabled;
// GetBackupPrivilege(out hasPrivilege, out isEnabled);
// //if (!hasPrivilege)
// //throw new Duplicati.Library.Interface.UserInformationException(Strings.WinNativeMethod.MissingBackupPrivilegeError, "MissingBackupPrivilege");
// return isEnabled;
// }
// set
// {
// //if (!CanEnableBackupPrivilege)
// //throw new Duplicati.Library.Interface.UserInformationException(Strings.WinNativeMethod.MissingBackupPrivilegeError, "MissingBackupPrivilege");
// int token = 0;
// int outsize = 0;
// TOKEN_PRIVILEGES TP = new TOKEN_PRIVILEGES();
// LUID backupLuid = new LUID();
// LUID restoreLuid = new LUID();
// if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref token) == 0)
// throw new Win32Exception(Marshal.GetLastWin32Error());
// if (LookupPrivilegeValue(null, SE_BACKUP_NAME, ref backupLuid) == 0)
// throw new Win32Exception(Marshal.GetLastWin32Error());
// if (LookupPrivilegeValue(null, SE_RESTORE_NAME, ref restoreLuid) == 0)
// throw new Win32Exception(Marshal.GetLastWin32Error());
// TP.PrivilegeCount = 1;
// TP.Privileges = new LUID_AND_ATTRIBUTES[ATTRIBUTE_FIXED_SIZE];
// TP.Privileges[0].Attributes = value ? SE_PRIVILEGE_ENABLED : 0u;
// TP.Privileges[0].Luid = backupLuid;
// TP.Privileges[1].Attributes = value ? SE_PRIVILEGE_ENABLED : 0u;
// TP.Privileges[1].Luid = restoreLuid;
// TOKEN_PRIVILEGES TPOut = new TOKEN_PRIVILEGES();
// if (AdjustTokenPrivileges(token, false, ref TP, Marshal.SizeOf(typeof(TOKEN_PRIVILEGES)), ref TPOut, ref outsize) == 0)
// throw new Win32Exception(Marshal.GetLastWin32Error());
//#if DEBUG
// Console.WriteLine("Modified token information:");
// PrintTokenInformation(TPOut);
//#endif
// if (Marshal.GetLastWin32Error() != 0)
// throw new Win32Exception(Marshal.GetLastWin32Error());
// }
// }
//#if DEBUG
// private static void PrintTokenInformation(TOKEN_PRIVILEGES tp)
// {
// int outsize;
// StringBuilder sbname = new StringBuilder(1024 * 4);
// for (int i = 0; i < tp.PrivilegeCount; i++)
// {
// LUID id = tp.Privileges[i].Luid;
// outsize = sbname.Capacity;
// if (LookupPrivilegeName(null, ref id, sbname, ref outsize) == 0)
// Console.WriteLine("Invalid LUID {0}:{1}: {2}", id.HighPart, id.LowPart, new Win32Exception(Marshal.GetLastWin32Error()).Message);
// else
// Console.WriteLine("{0}, status {1}", sbname, tp.Privileges[i].Attributes);
// }
// }
//#endif
// }
//}
+1 -1
View File
@@ -942,7 +942,7 @@ namespace Duplicati.Library.Main
//Sanity check for multiple inclusions of the same folder
for (int i = 0; i < sources.Count; i++)
for (int j = 0; j < sources.Count; j++)
if (i != j && sources[i].StartsWith(sources[j], Library.Utility.Utility.ClientFilenameStringComparison) && sources[i].EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), Library.Utility.Utility.ClientFilenameStringComparison))
if (i != j && sources[i].StartsWith(sources[j], Library.Utility.Utility.ClientFilenameStringComparison) && sources[i].EndsWith(Util.DirectorySeparatorString, Library.Utility.Utility.ClientFilenameStringComparison))
{
if (filter != null)
{
@@ -377,7 +377,7 @@ namespace Duplicati.Library.Main.Operation
Utility.VerifyParameters(m_database, m_options);
var probe_path = m_database.GetFirstPath();
if (probe_path != null && Util.GuessDirSeparator(probe_path) != System.IO.Path.DirectorySeparatorChar.ToString())
if (probe_path != null && Util.GuessDirSeparator(probe_path) != Util.DirectorySeparatorString)
throw new UserInformationException(string.Format("The backup contains files that belong to another operating system. Proceeding with a backup would cause the database to contain paths from two different operation systems, which is not supported. To proceed without losing remote data, delete all filesets and make sure the --{0} option is set, then run the backup again to re-use the existing data on the remote store.", "no-auto-compact"), "CrossOsDatabaseReuseNotSupported");
if (m_database.PartiallyRecreated)
@@ -21,7 +21,7 @@ namespace Duplicati.Library.Main.Operation
private byte[] m_blockbuffer;
private readonly RestoreResults m_result;
private static readonly ISystemIO m_systemIO = SystemIO.IO_OS(Duplicati.Library.Utility.Utility.IsClientWindows);
private static readonly string DIRSEP = System.IO.Path.DirectorySeparatorChar.ToString();
private static readonly string DIRSEP = Util.DirectorySeparatorString;
public RestoreHandler(string backendurl, Options options, RestoreResults result)
{
+3 -3
View File
@@ -111,12 +111,12 @@ namespace Duplicati.Library.Utility
/// <summary>
/// Regex escaped string for the AltDirectorySeparatorChar
/// </summary>
private static readonly string RegexEscapedAltDirectorySeparatorChar = System.Text.RegularExpressions.Regex.Escape(System.IO.Path.AltDirectorySeparatorChar.ToString());
private static readonly string RegexEscapedAltDirectorySeparatorChar = System.Text.RegularExpressions.Regex.Escape(Util.AltDirectorySeparatorString);
/// <summary>
/// Regex escaped string for the DirectorySeparatorChar
/// </summary>
private static readonly string RegexEscapedDirectorySeparatorChar = System.Text.RegularExpressions.Regex.Escape(System.IO.Path.DirectorySeparatorChar.ToString());
private static readonly string RegexEscapedDirectorySeparatorChar = System.Text.RegularExpressions.Regex.Escape(Util.DirectorySeparatorString);
/// <summary>
/// Gets the list of alternate aliases which can refer to this group.
@@ -269,7 +269,7 @@ namespace Duplicati.Library.Utility
if (n.Length > 2 && char.IsLetter(n[0]) && n[1] == ':' && wildcardRootWindowsPaths.Contains(n.Substring(2)))
continue;
else if (prev != null && prev.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) && n.StartsWith(prev, Utility.ClientFilenameStringComparison))
else if (prev != null && prev.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal) && n.StartsWith(prev, Utility.ClientFilenameStringComparison))
continue;
else
yield return prev = n;
+2 -2
View File
@@ -163,7 +163,7 @@ namespace Duplicati.Server
try
{
var nx = x;
if (nx.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
if (nx.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal))
nx = nx.Substring(0, nx.Length - 1);
var n = systemIO.PathGetFileName(nx);
if (!string.IsNullOrWhiteSpace(n))
@@ -173,7 +173,7 @@ namespace Duplicati.Server
{
}
if (x.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) && x.Length > 1)
if (x.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal) && x.Length > 1)
return new KeyValuePair<string, string>(x, x.Substring(0, x.Length - 1).Substring(x.Substring(0, x.Length - 1).LastIndexOf("/", StringComparison.Ordinal) + 1));
else
return new KeyValuePair<string, string>(x, x);
@@ -20,7 +20,8 @@ using System.Linq;
using HttpServer;
using HttpServer.HttpModules;
using HttpServer.Exceptions;
using Duplicati.Library.IO;
namespace Duplicati.Server.WebServer
{
internal class IndexHtmlHandler : HttpModule
@@ -28,7 +29,7 @@ namespace Duplicati.Server.WebServer
private readonly string m_webroot;
private static readonly string[] ForbiddenChars = new string[] {"\\", "..", ":"}.Union(from n in System.IO.Path.GetInvalidPathChars() select n.ToString()).Distinct().ToArray();
private static readonly string DirSep = System.IO.Path.DirectorySeparatorChar.ToString();
private static readonly string DirSep = Util.DirectorySeparatorString;
public IndexHtmlHandler(string webroot) { m_webroot = webroot; }
+11 -10
View File
@@ -17,6 +17,7 @@
using System;
using System.IO;
using System.Linq;
using Duplicati.Library.IO;
using NUnit.Framework;
namespace Duplicati.UnitTest
@@ -71,8 +72,8 @@ namespace Duplicati.UnitTest
using (var c = new Library.Main.Controller("file://" + TARGETFOLDER, testopts.Expand(new { version = 0 }), null))
{
var r = c.List("*");
var folders = r.Files.Count(x => x.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal));
var files = r.Files.Count(x => !x.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal));
var folders = r.Files.Count(x => x.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal));
var files = r.Files.Count(x => !x.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal));
if (folders != 7)
throw new Exception($"Initial condition not satisfied, found {folders} folders, but expected 7");
@@ -90,8 +91,8 @@ namespace Duplicati.UnitTest
using (var c = new Library.Main.Controller("file://" + TARGETFOLDER, testopts.Expand(new { version = 0 }), null))
{
var r = c.List("*");
var folders = r.Files.Count(x => x.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal));
var files = r.Files.Count(x => !x.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal));
var folders = r.Files.Count(x => x.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal));
var files = r.Files.Count(x => !x.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal));
if (folders != 6)
throw new Exception($"Initial condition not satisfied, found {folders} folders, but expected 6");
@@ -109,8 +110,8 @@ namespace Duplicati.UnitTest
using (var c = new Library.Main.Controller("file://" + TARGETFOLDER, testopts.Expand(new { version = 0 }), null))
{
var r = c.List("*");
var folders = r.Files.Count(x => x.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal));
var files = r.Files.Count(x => !x.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal));
var folders = r.Files.Count(x => x.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal));
var files = r.Files.Count(x => !x.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal));
if (folders != 4)
throw new Exception($"Empty not satisfied, found {folders} folders, but expected 4");
@@ -128,8 +129,8 @@ namespace Duplicati.UnitTest
using (var c = new Library.Main.Controller("file://" + TARGETFOLDER, testopts.Expand(new { version = 0 }), null))
{
var r = c.List("*");
var folders = r.Files.Count(x => x.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal));
var files = r.Files.Count(x => !x.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal));
var folders = r.Files.Count(x => x.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal));
var files = r.Files.Count(x => !x.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal));
if (folders != 3)
throw new Exception($"Empty not satisfied, found {folders} folders, but expected 3");
@@ -147,8 +148,8 @@ namespace Duplicati.UnitTest
using (var c = new Library.Main.Controller("file://" + TARGETFOLDER, testopts.Expand(new { version = 0 }), null))
{
var r = c.List("*");
var folders = r.Files.Count(x => x.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal));
var files = r.Files.Count(x => !x.Path.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal));
var folders = r.Files.Count(x => x.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal));
var files = r.Files.Count(x => !x.Path.EndsWith(Util.DirectorySeparatorString, StringComparison.Ordinal));
if (folders != 1)
throw new Exception($"Empty not satisfied, found {folders} folders, but expected 1");