Exemplo n.º 1
0
 private static void RunBackup(string source, string target, Dictionary <string, string> options, string sourcename)
 {
     Console.WriteLine("Backing up the copy: " + sourcename);
     using (new Timer("Backup of " + sourcename))
         using (var i = new Duplicati.Library.Main.Controller(target, options, new CommandLine.ConsoleOutput(options)))
             Log.WriteMessage(i.Backup(source.Split(System.IO.Path.PathSeparator)).ToString(), LogMessageType.Information);
 }
Exemplo n.º 2
0
 private static void RunBackup(string source, string target, Dictionary <string, string> options, string sourcename)
 {
     BasicSetupHelper.ProgressWriteLine("Backing up the copy: " + sourcename);
     using (new Timer(LOGTAG, "BackupRun", "Backup of " + sourcename))
         using (var console = new CommandLine.ConsoleOutput(Console.Out, options))
             using (var i = new Duplicati.Library.Main.Controller(target, options, console))
                 Log.WriteInformationMessage(LOGTAG, "BackupOutput", i.Backup(source.Split(System.IO.Path.PathSeparator)).ToString());
 }
Exemplo n.º 3
0
 private static void RunPartialRestore(string source, string target, string tempfolder, Dictionary<string, string> options, string[] files)
 {
 	var tops = new Dictionary<string, string>(options);
 	tops["restore-path"] = tempfolder;
     using (new Timer("Partial restore of " + source))
     using(var i = new Duplicati.Library.Main.Controller(target, tops, new CommandLine.ConsoleOutput(options)))
         Log.WriteMessage(i.Restore(files).ToString(), LogMessageType.Information);
 }
Exemplo n.º 4
0
        private static void RunPartialRestore(string source, string target, string tempfolder, Dictionary <string, string> options, string[] files)
        {
            var tops = new Dictionary <string, string>(options);

            tops["restore-path"] = tempfolder;
            using (new Timer(LOGTAG, "PartialRestore", "Partial restore of " + source))
                using (var console = new CommandLine.ConsoleOutput(Console.Out, options))
                    using (var i = new Duplicati.Library.Main.Controller(target, tops, console))
                        Log.WriteInformationMessage(LOGTAG, "PartialRestoreOutput", i.Restore(files).ToString());
        }
Exemplo n.º 5
0
        public static int Repair(List <string> args, Dictionary <string, string> options, Library.Utility.IFilter filter)
        {
            if (args.Count != 1)
            {
                return(PrintWrongNumberOfArguments(args, 1));
            }

            using (var i = new Duplicati.Library.Main.Controller(args[0], options, new ConsoleOutput(options)))
                i.Repair();

            return(0);
        }
Exemplo n.º 6
0
 public void SetController(Duplicati.Library.Main.Controller controller)
 {
     Controller = controller;
 }
Exemplo n.º 7
0
        public static Duplicati.Library.Interface.IBasicResults Run(IRunnerData data, bool fromQueue)
        {
            if (data is CustomRunnerTask)
            {
                try
                {
                    var sink = new MessageSink(data.TaskID, null);
                    Program.GenerateProgressState = () => sink.Copy();
                    Program.StatusEventNotifyer.SignalNewEvent();

                    ((CustomRunnerTask)data).Run(sink);
                }
                catch (Exception ex)
                {
                    Program.DataConnection.LogError(string.Empty, "Failed while executing custom task", ex);
                }

                return(null);
            }


            var backup = data.Backup;

            Duplicati.Library.Utility.TempFolder tempfolder = null;

            if (backup.Metadata == null)
            {
                backup.Metadata = new Dictionary <string, string>();
            }

            try
            {
                var sink = new MessageSink(data.TaskID, backup.ID);
                if (fromQueue)
                {
                    Program.GenerateProgressState = () => sink.Copy();
                    Program.StatusEventNotifyer.SignalNewEvent();
                }

                var options = ApplyOptions(backup, data.Operation, GetCommonOptions(backup, data.Operation));
                if (data.ExtraOptions != null)
                {
                    foreach (var k in data.ExtraOptions)
                    {
                        options[k.Key] = k.Value;
                    }
                }

                // Pack in the system or task config for easy restore
                if (data.Operation == DuplicatiOperation.Backup && options.ContainsKey("store-task-config"))
                {
                    var all_tasks = string.Equals(options["store-task-config"], "all", StringComparison.InvariantCultureIgnoreCase) || string.Equals(options["store-task-config"], "*", StringComparison.InvariantCultureIgnoreCase);
                    var this_task = Duplicati.Library.Utility.Utility.ParseBool(options["store-task-config"], false);

                    options.Remove("store-task-config");

                    if (all_tasks || this_task)
                    {
                        if (tempfolder == null)
                        {
                            tempfolder = new Duplicati.Library.Utility.TempFolder();
                        }

                        var temppath = System.IO.Path.Combine(tempfolder, "task-setup.json");
                        using (var tempfile = Duplicati.Library.Utility.TempFile.WrapExistingFile(temppath))
                        {
                            object taskdata = null;
                            if (all_tasks)
                            {
                                taskdata = Program.DataConnection.Backups.Where(x => !x.IsTemporary).Select(x => Program.DataConnection.PrepareBackupForExport(Program.DataConnection.GetBackup(x.ID)));
                            }
                            else
                            {
                                taskdata = new [] { Program.DataConnection.PrepareBackupForExport(data.Backup) }
                            };

                            using (var fs = System.IO.File.OpenWrite(tempfile))
                                using (var sw = new System.IO.StreamWriter(fs, System.Text.Encoding.UTF8))
                                    Serializer.SerializeJson(sw, taskdata, true);

                            tempfile.Protected = true;

                            string controlfiles = null;
                            options.TryGetValue("control-files", out controlfiles);

                            if (string.IsNullOrWhiteSpace(controlfiles))
                            {
                                controlfiles = tempfile;
                            }
                            else
                            {
                                controlfiles += System.IO.Path.PathSeparator + tempfile;
                            }

                            options["control-files"] = controlfiles;
                        }
                    }
                }

                using (tempfolder)
                    using (var controller = new Duplicati.Library.Main.Controller(backup.TargetURL, options, sink))
                    {
                        ((RunnerData)data).Controller = controller;

                        switch (data.Operation)
                        {
                        case DuplicatiOperation.Backup:
                        {
                            var filter  = ApplyFilter(backup, data.Operation, GetCommonFilter(backup, data.Operation));
                            var sources =
                                (from n in backup.Sources
                                 let p = SpecialFolders.ExpandEnvironmentVariables(n)
                                         where !string.IsNullOrWhiteSpace(p)
                                         select p).ToArray();

                            var r = controller.Backup(sources, filter);
                            UpdateMetadata(backup, r);
                            return(r);
                        }

                        case DuplicatiOperation.List:
                        {
                            var r = controller.List(data.FilterStrings);
                            UpdateMetadata(backup, r);
                            return(r);
                        }

                        case DuplicatiOperation.Repair:
                        {
                            var r = controller.Repair(data.FilterStrings == null ? null : new Library.Utility.FilterExpression(data.FilterStrings));
                            UpdateMetadata(backup, r);
                            return(r);
                        }

                        case DuplicatiOperation.RepairUpdate:
                        {
                            var r = controller.UpdateDatabaseWithVersions();
                            UpdateMetadata(backup, r);
                            return(r);
                        }

                        case DuplicatiOperation.Remove:
                        {
                            var r = controller.Delete();
                            UpdateMetadata(backup, r);
                            return(r);
                        }

                        case DuplicatiOperation.Restore:
                        {
                            var r = controller.Restore(data.FilterStrings);
                            UpdateMetadata(backup, r);
                            return(r);
                        }

                        case DuplicatiOperation.Verify:
                        {
                            var r = controller.Test();
                            UpdateMetadata(backup, r);
                            return(r);
                        }

                        case DuplicatiOperation.Compact:
                        {
                            var r = controller.Compact();
                            UpdateMetadata(backup, r);
                            return(r);
                        }

                        case DuplicatiOperation.CreateReport:
                        {
                            using (var tf = new Duplicati.Library.Utility.TempFile())
                            {
                                var r      = controller.CreateLogDatabase(tf);
                                var tempid = Program.DataConnection.RegisterTempFile("create-bug-report", r.TargetPath, DateTime.Now.AddDays(3));

                                if (string.Equals(tf, r.TargetPath, Library.Utility.Utility.ClientFilenameStringComparision))
                                {
                                    tf.Protected = true;
                                }

                                Program.DataConnection.RegisterNotification(
                                    NotificationType.Information,
                                    "Bugreport ready",
                                    "Bugreport is ready for download",
                                    null,
                                    null,
                                    "bug-report:created:" + tempid,
                                    (n, a) => n
                                    );

                                return(r);
                            }
                        }

                        case DuplicatiOperation.ListRemote:
                        {
                            var r = controller.ListRemote();
                            UpdateMetadata(backup, r);
                            return(r);
                        }

                        case DuplicatiOperation.Delete:
                        {
                            if (Library.Utility.Utility.ParseBoolOption(data.ExtraOptions, "delete-remote-files"))
                            {
                                controller.DeleteAllRemoteFiles();
                            }

                            if (Library.Utility.Utility.ParseBoolOption(data.ExtraOptions, "delete-local-db"))
                            {
                                string dbpath;
                                options.TryGetValue("db-path", out dbpath);

                                if (!string.IsNullOrWhiteSpace(dbpath) && System.IO.File.Exists(dbpath))
                                {
                                    System.IO.File.Delete(dbpath);
                                }
                            }
                            Program.DataConnection.DeleteBackup(backup);
                            Program.Scheduler.Reschedule();
                            return(null);
                        }

                        default:
                            //TODO: Log this
                            return(null);
                        }
                    }
            }
            catch (Exception ex)
            {
                Program.DataConnection.LogError(data.Backup.ID, string.Format("Failed while executing \"{0}\" with id: {1}", data.Operation, data.Backup.ID), ex);
                UpdateMetadataError(data.Backup, ex);
                Library.UsageReporter.Reporter.Report(ex);

                if (!fromQueue)
                {
                    throw;
                }

                return(null);
            }
            finally
            {
                ((RunnerData)data).Controller = null;
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Running the unit test confirms the correctness of duplicati
        /// </summary>
        /// <param name="folders">The folders to backup. Folder at index 0 is the base, all others are incrementals</param>
        /// <param name="target">The target destination for the backups</param>
        public static void RunTest(string[] folders, Dictionary <string, string> options, string target)
        {
            string tempdir     = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "tempdir");
            string logfilename = System.IO.Path.Combine(tempdir, string.Format("unittest-{0}.log", Library.Utility.Utility.SerializeDateTime(DateTime.Now)));

            try
            {
                if (System.IO.Directory.Exists(tempdir))
                {
                    System.IO.Directory.Delete(tempdir, true);
                }

                System.IO.Directory.CreateDirectory(tempdir);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to clean tempdir: {0}", ex);
            }

            using (var log = new LogHelper(logfilename))
                using (Log.StartScope(log, LogMessageType.Profiling))
                {
                    //Filter empty entries, commonly occuring with copy/paste and newlines
                    folders = (from x in folders
                               where !string.IsNullOrWhiteSpace(x)
                               select Environment.ExpandEnvironmentVariables(x)).ToArray();

                    foreach (var f in folders)
                    {
                        foreach (var n in f.Split(new char[] { System.IO.Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            if (!System.IO.Directory.Exists(n))
                            {
                                throw new Exception(string.Format("Missing source folder: {0}", n));
                            }
                        }
                    }


                    Duplicati.Library.Utility.TempFolder.SystemTempPath = tempdir;

                    //Set some defaults
                    if (!options.ContainsKey("passphrase"))
                    {
                        options["passphrase"] = "secret password!";
                    }

                    if (!options.ContainsKey("prefix"))
                    {
                        options["prefix"] = "duplicati_unittest";
                    }

                    //We want all messages in the log
                    options["log-file-log-level"] = LogMessageType.Profiling.ToString();
                    //We cannot rely on USN numbering, but we can use USN enumeration
                    //options["disable-usn-diff-check"] = "true";

                    //We use precise times
                    options["disable-time-tolerance"] = "true";

                    //We need all sets, even if they are unchanged
                    options["upload-unchanged-backups"] = "true";

                    bool skipfullrestore    = false;
                    bool skippartialrestore = false;
                    bool skipverify         = false;

                    if (Utility.ParseBoolOption(options, "unittest-backuponly"))
                    {
                        skipfullrestore    = true;
                        skippartialrestore = true;
                        options.Remove("unittest-backuponly");
                    }

                    if (Utility.ParseBoolOption(options, "unittest-skip-partial-restore"))
                    {
                        skippartialrestore = true;
                        options.Remove("unittest-skip-partial-restore");
                    }

                    if (Utility.ParseBoolOption(options, "unittest-skip-full-restore"))
                    {
                        skipfullrestore = true;
                        options.Remove("unittest-skip-full-restore");
                    }

                    if (Utility.ParseBoolOption(options, "unittest-skip-verify"))
                    {
                        skipverify = true;
                        options.Remove("unittest-skip-verify");
                    }

                    var verifymetadata = !Utility.ParseBoolOption(options, "skip-metadata");

                    using (new Timer(LOGTAG, "UnitTest", "Total unittest"))
                        using (TempFolder tf = new TempFolder())
                        {
                            options["dbpath"] = System.IO.Path.Combine(tempdir, "unittest.sqlite");
                            if (System.IO.File.Exists(options["dbpath"]))
                            {
                                System.IO.File.Delete(options["dbpath"]);
                            }

                            if (string.IsNullOrEmpty(target))
                            {
                                target = "file://" + tf;
                            }
                            else
                            {
                                BasicSetupHelper.ProgressWriteLine("Removing old backups");
                                Dictionary <string, string> tmp = new Dictionary <string, string>(options);
                                tmp["keep-versions"]      = "0";
                                tmp["force"]              = "";
                                tmp["allow-full-removal"] = "";

                                using (new Timer(LOGTAG, "CleanupExisting", "Cleaning up any existing backups"))
                                    try
                                    {
                                        using (var bk = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(target, options))
                                            foreach (var f in bk.List())
                                            {
                                                if (!f.IsFolder)
                                                {
                                                    bk.Delete(f.Name);
                                                }
                                            }
                                    }
                                    catch (Duplicati.Library.Interface.FolderMissingException)
                                    {
                                    }
                            }

                            log.Backupset = "Backup " + folders[0];
                            string fhtempsource = null;

                            bool usingFHWithRestore = (!skipfullrestore || !skippartialrestore);

                            using (var fhsourcefolder = usingFHWithRestore ? new Library.Utility.TempFolder() : null)
                            {
                                if (usingFHWithRestore)
                                {
                                    fhtempsource = fhsourcefolder;
                                    TestUtils.CopyDirectoryRecursive(folders[0], fhsourcefolder);
                                }

                                RunBackup(usingFHWithRestore ? (string)fhsourcefolder : folders[0], target, options, folders[0]);

                                for (int i = 1; i < folders.Length; i++)
                                {
                                    //options["passphrase"] = "bad password";
                                    //If the backups are too close, we can't pick the right one :(
                                    System.Threading.Thread.Sleep(1000 * 5);
                                    log.Backupset = "Backup " + folders[i];

                                    if (usingFHWithRestore)
                                    {
                                        System.IO.Directory.Delete(fhsourcefolder, true);
                                        TestUtils.CopyDirectoryRecursive(folders[i], fhsourcefolder);
                                    }

                                    //Call function to simplify profiling
                                    RunBackup(usingFHWithRestore ? (string)fhsourcefolder : folders[i], target, options, folders[i]);
                                }
                            }

                            Duplicati.Library.Main.Options opts = new Duplicati.Library.Main.Options(options);
                            using (Duplicati.Library.Interface.IBackend bk = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(target, options))
                                foreach (Duplicati.Library.Interface.IFileEntry fe in bk.List())
                                {
                                    if (fe.Size > opts.VolumeSize)
                                    {
                                        string msg = string.Format("The file {0} is {1} bytes larger than allowed", fe.Name, fe.Size - opts.VolumeSize);
                                        BasicSetupHelper.ProgressWriteLine(msg);
                                        Log.WriteErrorMessage(LOGTAG, "RemoteTargetSize", null, msg);
                                    }
                                }

                            IList <DateTime> entries;
                            using (var console = new CommandLine.ConsoleOutput(Console.Out, options))
                                using (var i = new Duplicati.Library.Main.Controller(target, options, console))
                                    entries = (from n in i.List().Filesets select n.Time.ToLocalTime()).ToList();

                            if (entries.Count != folders.Length)
                            {
                                StringBuilder sb = new StringBuilder();
                                sb.AppendLine("Entry count: " + entries.Count.ToString());
                                sb.Append(string.Format("Found {0} filelists but there were {1} source folders", entries.Count, folders.Length));
                                throw new Exception("Filename parsing problem, or corrupt storage: " + sb);
                            }

                            if (!skipfullrestore || !skippartialrestore)
                            {
                                for (int i = 0; i < entries.Count; i++)
                                {
                                    using (TempFolder ttf = new TempFolder())
                                    {
                                        log.Backupset = "Restore " + folders[i];
                                        BasicSetupHelper.ProgressWriteLine("Restoring the copy: " + folders[i]);

                                        options["time"] = entries[entries.Count - i - 1].ToString();

                                        string[] actualfolders = folders[i].Split(System.IO.Path.PathSeparator);
                                        if (!skippartialrestore)
                                        {
                                            BasicSetupHelper.ProgressWriteLine("Partial restore of: " + folders[i]);
                                            using (TempFolder ptf = new TempFolder())
                                            {
                                                List <string> testfiles = new List <string>();
                                                using (new Timer(LOGTAG, "ExtractFileList", "Extract list of files from" + folders[i]))
                                                {
                                                    List <string> sourcefiles;
                                                    using (var console = new CommandLine.ConsoleOutput(Console.Out, options))
                                                        using (var inst = new Library.Main.Controller(target, options, console))
                                                            sourcefiles = (from n in inst.List("*").Files select n.Path).ToList();

                                                    //Remove all folders from list
                                                    for (int j = 0; j < sourcefiles.Count; j++)
                                                    {
                                                        if (sourcefiles[j].EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
                                                        {
                                                            sourcefiles.RemoveAt(j);
                                                            j--;
                                                        }
                                                    }


                                                    int    testfilecount = 15;
                                                    Random r             = new Random();
                                                    while (testfilecount-- > 0 && sourcefiles.Count > 0)
                                                    {
                                                        int rn = r.Next(0, sourcefiles.Count);
                                                        testfiles.Add(sourcefiles[rn]);
                                                        sourcefiles.RemoveAt(rn);
                                                    }
                                                }


                                                //Add all folders to avoid warnings in restore log
                                                int c = testfiles.Count;
                                                Dictionary <string, string> partialFolders = new Dictionary <string, string>(Utility.ClientFilenameStringComparer);

                                                for (int j = 0; j < c; j++)
                                                {
                                                    string f = testfiles[j];

                                                    if (!f.StartsWith(usingFHWithRestore ? fhtempsource : folders[i], Utility.ClientFilenameStringComparison))
                                                    {
                                                        throw new Exception(string.Format("Unexpected file found: {0}, path is not a subfolder for {1}", f, folders[i]));
                                                    }

                                                    f = f.Substring(Utility.AppendDirSeparator(usingFHWithRestore ? fhtempsource : folders[i]).Length);

                                                    do
                                                    {
                                                        f = System.IO.Path.GetDirectoryName(f);
                                                        partialFolders[Utility.AppendDirSeparator(f)] = null;
                                                    } while (f.IndexOf(System.IO.Path.DirectorySeparatorChar) > 0);
                                                }

                                                if (partialFolders.ContainsKey(""))
                                                {
                                                    partialFolders.Remove("");
                                                }
                                                if (partialFolders.ContainsKey(System.IO.Path.DirectorySeparatorChar.ToString()))
                                                {
                                                    partialFolders.Remove(System.IO.Path.DirectorySeparatorChar.ToString());
                                                }

                                                List <string> filterlist;

                                                var tfe = Utility.AppendDirSeparator(usingFHWithRestore ? fhtempsource : folders[i]);

                                                filterlist = (from n in partialFolders.Keys
                                                              where !string.IsNullOrWhiteSpace(n) && n != System.IO.Path.DirectorySeparatorChar.ToString()
                                                              select Utility.AppendDirSeparator(System.IO.Path.Combine(tfe, n)))
                                                             .Union(testfiles)            //Add files with full path
                                                             .Union(new string[] { tfe }) //Ensure root folder is included
                                                             .Distinct()
                                                             .ToList();

                                                testfiles = (from n in testfiles select n.Substring(tfe.Length)).ToList();

                                                //Call function to simplify profiling
                                                RunPartialRestore(folders[i], target, ptf, options, filterlist.ToArray());

                                                if (!skipverify)
                                                {
                                                    //Call function to simplify profiling
                                                    BasicSetupHelper.ProgressWriteLine("Verifying partial restore of: " + folders[i]);
                                                    VerifyPartialRestore(folders[i], testfiles, actualfolders, ptf, folders[0], verifymetadata);
                                                }
                                            }
                                        }

                                        if (!skipfullrestore)
                                        {
                                            //Call function to simplify profiling
                                            RunRestore(folders[i], target, ttf, options);

                                            if (!skipverify)
                                            {
                                                //Call function to simplify profiling
                                                BasicSetupHelper.ProgressWriteLine("Verifying the copy: " + folders[i]);
                                                VerifyFullRestore(folders[i], actualfolders, new string[] { ttf }, verifymetadata);
                                            }
                                        }
                                    }
                                }
                            }

                            foreach (string s in Utility.EnumerateFiles(tempdir))
                            {
                                if (s == options["dbpath"])
                                {
                                    continue;
                                }
                                if (s == logfilename)
                                {
                                    continue;
                                }
                                if (s.StartsWith(Utility.AppendDirSeparator(tf), StringComparison.Ordinal))
                                {
                                    continue;
                                }

                                Log.WriteWarningMessage(LOGTAG, "LeftOverTempFile", null, "Found left-over temp file: {0}", s.Substring(tempdir.Length));
                                BasicSetupHelper.ProgressWriteLine("Found left-over temp file: {0} -> {1}", s.Substring(tempdir.Length),
#if DEBUG
                                                                   TempFile.GetStackTraceForTempFile(System.IO.Path.GetFileName(s))
#else
                                                                   System.IO.Path.GetFileName(s)
#endif
                                                                   );
                            }

                            foreach (string s in Utility.EnumerateFolders(tempdir))
                            {
                                if (!s.StartsWith(Utility.AppendDirSeparator(tf), StringComparison.Ordinal) && Utility.AppendDirSeparator(s) != Utility.AppendDirSeparator(tf) && Utility.AppendDirSeparator(s) != Utility.AppendDirSeparator(tempdir))
                                {
                                    Log.WriteWarningMessage(LOGTAG, "LeftOverTempFolder", null, "Found left-over temp folder: {0}", s.Substring(tempdir.Length));
                                    BasicSetupHelper.ProgressWriteLine("Found left-over temp folder: {0}", s.Substring(tempdir.Length));
                                }
                            }
                        }
                }

            if (LogHelper.ErrorCount > 0)
            {
                BasicSetupHelper.ProgressWriteLine("Unittest completed, but with {0} errors, see logfile for details", LogHelper.ErrorCount);
            }
            else if (LogHelper.WarningCount > 0)
            {
                BasicSetupHelper.ProgressWriteLine("Unittest completed, but with {0} warnings, see logfile for details", LogHelper.WarningCount);
            }
            else
            {
                BasicSetupHelper.ProgressWriteLine("Unittest completed successfully - Have some cake!");
            }

            System.Diagnostics.Debug.Assert(LogHelper.ErrorCount == 0);
        }
Exemplo n.º 9
0
        public static Duplicati.Library.Interface.IBasicResults Run(IRunnerData data, bool fromQueue)
        {
            if (data is CustomRunnerTask)
            {
                try
                {
                    var sink = new MessageSink(data.TaskID, null);
                    Program.GenerateProgressState = () => sink.Copy();
                    Program.StatusEventNotifyer.SignalNewEvent();

                    ((CustomRunnerTask)data).Run(sink);
                }
                catch (Exception ex)
                {
                    Program.DataConnection.LogError(string.Empty, "Failed while executing custom task", ex);
                }

                return(null);
            }

            var backup = data.Backup;

            if (backup.Metadata == null)
            {
                backup.Metadata = new Dictionary <string, string>();
            }

            Duplicati.Library.Utility.TempFolder tempfolder = null;

            try
            {
                var sink = new MessageSink(data.TaskID, backup.ID);
                if (fromQueue)
                {
                    Program.GenerateProgressState = () => sink.Copy();
                    Program.StatusEventNotifyer.SignalNewEvent();
                }

                var options = ApplyOptions(backup, data.Operation, GetCommonOptions(backup, data.Operation));
                if (data.ExtraOptions != null)
                {
                    foreach (var k in data.ExtraOptions)
                    {
                        options[k.Key] = k.Value;
                    }
                }

                // Pack in the system or task config for easy restore
                if (data.Operation == DuplicatiOperation.Backup && options.ContainsKey("store-task-config"))
                {
                    tempfolder = StoreTaskConfigAndGetTempFolder(data, options);
                }

                // Attach a log scope that tags all messages to relay the TaskID and BackupID
                using (Library.Logging.Log.StartScope(log => {
                    log[LogWriteHandler.LOG_EXTRA_TASKID] = data.TaskID.ToString();
                    log[LogWriteHandler.LOG_EXTRA_BACKUPID] = data.BackupID;
                }))

                    using (tempfolder)
                        using (var controller = new Duplicati.Library.Main.Controller(backup.TargetURL, options, sink))
                        {
                            try
                            {
                                if (options.ContainsKey("throttle-upload"))
                                {
                                    ((RunnerData)data).OriginalUploadSpeed = Duplicati.Library.Utility.Sizeparser.ParseSize(options["throttle-upload"], "kb");
                                }
                            }
                            catch { }

                            try
                            {
                                if (options.ContainsKey("throttle-download"))
                                {
                                    ((RunnerData)data).OriginalDownloadSpeed = Duplicati.Library.Utility.Sizeparser.ParseSize(options["throttle-download"], "kb");
                                }
                            }
                            catch { }

                            ((RunnerData)data).Controller = controller;
                            data.UpdateThrottleSpeed();

                            switch (data.Operation)
                            {
                            case DuplicatiOperation.Backup:
                            {
                                var filter  = ApplyFilter(backup, data.Operation, GetCommonFilter(backup, data.Operation));
                                var sources =
                                    (from n in backup.Sources
                                     let p = SpecialFolders.ExpandEnvironmentVariables(n)
                                             where !string.IsNullOrWhiteSpace(p)
                                             select p).ToArray();

                                var r = controller.Backup(sources, filter);
                                UpdateMetadata(backup, r);
                                return(r);
                            }

                            case DuplicatiOperation.List:
                            {
                                var r = controller.List(data.FilterStrings);
                                UpdateMetadata(backup, r);
                                return(r);
                            }

                            case DuplicatiOperation.Repair:
                            {
                                var r = controller.Repair(data.FilterStrings == null ? null : new Library.Utility.FilterExpression(data.FilterStrings));
                                UpdateMetadata(backup, r);
                                return(r);
                            }

                            case DuplicatiOperation.RepairUpdate:
                            {
                                var r = controller.UpdateDatabaseWithVersions();
                                UpdateMetadata(backup, r);
                                return(r);
                            }

                            case DuplicatiOperation.Remove:
                            {
                                var r = controller.Delete();
                                UpdateMetadata(backup, r);
                                return(r);
                            }

                            case DuplicatiOperation.Restore:
                            {
                                var r = controller.Restore(data.FilterStrings);
                                UpdateMetadata(backup, r);
                                return(r);
                            }

                            case DuplicatiOperation.Verify:
                            {
                                var r = controller.Test();
                                UpdateMetadata(backup, r);
                                return(r);
                            }

                            case DuplicatiOperation.Compact:
                            {
                                var r = controller.Compact();
                                UpdateMetadata(backup, r);
                                return(r);
                            }

                            case DuplicatiOperation.CreateReport:
                            {
                                using (var tf = new Duplicati.Library.Utility.TempFile())
                                {
                                    var r      = controller.CreateLogDatabase(tf);
                                    var tempid = Program.DataConnection.RegisterTempFile("create-bug-report", r.TargetPath, DateTime.Now.AddDays(3));

                                    if (string.Equals(tf, r.TargetPath, Library.Utility.Utility.ClientFilenameStringComparison))
                                    {
                                        tf.Protected = true;
                                    }

                                    Program.DataConnection.RegisterNotification(
                                        NotificationType.Information,
                                        "Bugreport ready",
                                        "Bugreport is ready for download",
                                        null,
                                        null,
                                        "bug-report:created:" + tempid,
                                        null,
                                        "BugreportCreatedReady",
                                        "",
                                        (n, a) => n
                                        );

                                    return(r);
                                }
                            }

                            case DuplicatiOperation.ListRemote:
                            {
                                var r = controller.ListRemote();
                                UpdateMetadata(backup, r);
                                return(r);
                            }

                            case DuplicatiOperation.Delete:
                            {
                                if (Library.Utility.Utility.ParseBoolOption(data.ExtraOptions, "delete-remote-files"))
                                {
                                    controller.DeleteAllRemoteFiles();
                                }

                                if (Library.Utility.Utility.ParseBoolOption(data.ExtraOptions, "delete-local-db"))
                                {
                                    string dbpath;
                                    options.TryGetValue("db-path", out dbpath);

                                    if (!string.IsNullOrWhiteSpace(dbpath) && System.IO.File.Exists(dbpath))
                                    {
                                        System.IO.File.Delete(dbpath);
                                    }
                                }
                                Program.DataConnection.DeleteBackup(backup);
                                Program.Scheduler.Reschedule();
                                return(null);
                            }

                            case DuplicatiOperation.Vacuum:
                            {
                                var r = controller.Vacuum();
                                UpdateMetadata(backup, r);
                                return(r);
                            }

                            default:
                                //TODO: Log this
                                return(null);
                            }
                        }
            }
            catch (Exception ex)
            {
                Program.DataConnection.LogError(data.Backup.ID, string.Format("Failed while executing \"{0}\" with id: {1}", data.Operation, data.Backup.ID), ex);
                UpdateMetadataError(data.Backup, ex);
                Library.UsageReporter.Reporter.Report(ex);

                if (!fromQueue)
                {
                    throw;
                }

                return(null);
            }
            finally
            {
                ((RunnerData)data).Controller = null;
            }
        }
Exemplo n.º 10
0
        public static Duplicati.Library.Interface.IBasicResults Run(IRunnerData data, bool fromQueue)
        {
            var backup = data.Backup;
            Duplicati.Library.Utility.TempFolder tempfolder = null;

            if (backup.Metadata == null)
                backup.Metadata = new Dictionary<string, string>();

            try
            {
                var options = ApplyOptions(backup, data.Operation, GetCommonOptions(backup, data.Operation));
                var sink = new MessageSink(data.TaskID, backup.ID);
                if (fromQueue)
                {
                    Program.GenerateProgressState = () => sink.Copy();
                    Program.StatusEventNotifyer.SignalNewEvent();
                }

                if (data.ExtraOptions != null)
                    foreach(var k in data.ExtraOptions)
                        options[k.Key] = k.Value;

                // Log file is using the internal log-handler
                // so we can display output in the GUI as well as log
                // into the given file
                if (options.ContainsKey("log-file"))
                {
                    var file = options["log-file"];

                    string o;
                    Library.Logging.LogMessageType level;
                    options.TryGetValue("log-level", out o);
                    Enum.TryParse<Library.Logging.LogMessageType>(o, true, out level);

                    options.Remove("log-file");
                    options.Remove("log-level");

                    Program.LogHandler.SetOperationFile(file, level);
                }

                // Pack in the system or task config for easy restore
                if (data.Operation == DuplicatiOperation.Backup && options.ContainsKey("store-task-config"))
                {
                    var all_tasks = string.Equals(options["store-task-config"], "all", StringComparison.InvariantCultureIgnoreCase) || string.Equals(options["store-task-config"], "*", StringComparison.InvariantCultureIgnoreCase);
                    var this_task = Duplicati.Library.Utility.Utility.ParseBool(options["store-task-config"], false);

                    options.Remove("store-task-config");

                    if (all_tasks || this_task)
                    {
                        if (tempfolder == null)
                            tempfolder = new Duplicati.Library.Utility.TempFolder();

                        var temppath = System.IO.Path.Combine(tempfolder, "task-setup.json");
                        using(var tempfile = Duplicati.Library.Utility.TempFile.WrapExistingFile(temppath))
                        {
                            object taskdata = null;
                            if (all_tasks)
                                taskdata = Program.DataConnection.Backups.Where(x => !x.IsTemporary).Select(x => Program.DataConnection.PrepareBackupForExport(Program.DataConnection.GetBackup(x.ID)));
                            else
                                taskdata = new [] { Program.DataConnection.PrepareBackupForExport(data.Backup) };

                            using(var fs = System.IO.File.OpenWrite(tempfile))
                            using(var sw = new System.IO.StreamWriter(fs, System.Text.Encoding.UTF8))
                                Serializer.SerializeJson(sw, taskdata, true);

                            tempfile.Protected = true;

                            string controlfiles = null;
                            options.TryGetValue("control-files", out controlfiles);

                            if (string.IsNullOrWhiteSpace(controlfiles))
                                controlfiles = tempfile;
                            else
                                controlfiles += System.IO.Path.PathSeparator + tempfile;

                            options["control-files"] = controlfiles;
                        }
                    }
                }

                using(tempfolder)
                using(var controller = new Duplicati.Library.Main.Controller(backup.TargetURL, options, sink))
                {
                    ((RunnerData)data).Controller = controller;

                    switch (data.Operation)
                    {
                        case DuplicatiOperation.Backup:
                            {
                                var filter = ApplyFilter(backup, data.Operation, GetCommonFilter(backup, data.Operation));
                                var sources =
                                    (from n in backup.Sources
                                        let p = SpecialFolders.ExpandEnvironmentVariables(n)
                                        where !string.IsNullOrWhiteSpace(p)
                                        select p).ToArray();

                                var r = controller.Backup(sources, filter);
                                UpdateMetadata(backup, r);
                                return r;
                            }
                        case DuplicatiOperation.List:
                            {
                                var r = controller.List(data.FilterStrings);
                                UpdateMetadata(backup, r);
                                return r;
                            }
                        case DuplicatiOperation.Repair:
                            {
                                var r = controller.Repair(data.FilterStrings == null ? null : new Library.Utility.FilterExpression(data.FilterStrings));
                                UpdateMetadata(backup, r);
                                return r;
                            }
                        case DuplicatiOperation.RepairUpdate:
                            {
                                var r = controller.UpdateDatabaseWithVersions();
                                UpdateMetadata(backup, r);
                                return r;
                            }
                        case DuplicatiOperation.Remove:
                            {
                                var r = controller.Delete();
                                UpdateMetadata(backup, r);
                                return r;
                            }
                        case DuplicatiOperation.Restore:
                            {
                                var r = controller.Restore(data.FilterStrings);
                                UpdateMetadata(backup, r);
                                return r;
                            }
                        case DuplicatiOperation.Verify:
                            {
                                var r = controller.Test();
                                UpdateMetadata(backup, r);
                                return r;
                            }

                        case DuplicatiOperation.CreateReport:
                            {
                                using(var tf = new Duplicati.Library.Utility.TempFile())
                                {
                                    var r = controller.CreateLogDatabase(tf);
                                    var tempid = Program.DataConnection.RegisterTempFile("create-bug-report", r.TargetPath, DateTime.Now.AddDays(3));

                                    if (string.Equals(tf, r.TargetPath, Library.Utility.Utility.ClientFilenameStringComparision))
                                        tf.Protected = true;

                                    Program.DataConnection.RegisterNotification(
                                        NotificationType.Information,
                                        "Bugreport ready",
                                        "Bugreport is ready for download",
                                         null,
                                         null,
                                         "bug-report:created:" + tempid,
                                         (n, a) => n
                                     );

                                    return r;
                                }
                            }
                        default:
                            //TODO: Log this
                            return null;
                    }
                }
            }
            catch (Exception ex)
            {
                Program.DataConnection.LogError(data.Backup.ID, string.Format("Failed while executing \"{0}\" with id: {1}", data.Operation, data.Backup.ID), ex);
                UpdateMetadataError(data.Backup, ex);
                Library.UsageReporter.Reporter.Report(ex);

                if (!fromQueue)
                    throw;

                return null;
            }
            finally
            {
                ((RunnerData)data).Controller = null;
                Program.LogHandler.RemoveOperationFile();
            }
        }
Exemplo n.º 11
0
        public static Duplicati.Library.Interface.IBasicResults Run(IRunnerData data, bool fromQueue)
        {
            var backup = data.Backup;

            try
            {
                var options = ApplyOptions(backup, data.Operation, GetCommonOptions(backup, data.Operation));
                var sink    = new MessageSink(data.TaskID, backup.ID);
                if (fromQueue)
                {
                    Program.GenerateProgressState = () => sink.Copy();
                    Program.StatusEventNotifyer.SignalNewEvent();
                }

                if (data.ExtraOptions != null)
                {
                    foreach (var k in data.ExtraOptions)
                    {
                        options[k.Key] = k.Value;
                    }
                }

                if (options.ContainsKey("log-file"))
                {
                    var file = options["log-file"];

                    string o;
                    Library.Logging.LogMessageType level;
                    options.TryGetValue("log-level", out o);
                    Enum.TryParse <Library.Logging.LogMessageType>(o, true, out level);

                    options.Remove("log-file");
                    options.Remove("log-level");

                    Program.LogHandler.SetOperationFile(file, level);
                }

                using (var controller = new Duplicati.Library.Main.Controller(backup.TargetURL, options, sink))
                {
                    ((RunnerData)data).Controller = controller;

                    switch (data.Operation)
                    {
                    case DuplicatiOperation.Backup:
                    {
                        var filter  = ApplyFilter(backup, data.Operation, GetCommonFilter(backup, data.Operation));
                        var sources =
                            (from n in backup.Sources
                             let p = SpecialFolders.ExpandEnvironmentVariables(n)
                                     where !string.IsNullOrWhiteSpace(p)
                                     select p).ToArray();

                        var r = controller.Backup(sources, filter);
                        UpdateMetadata(backup, r);
                        return(r);
                    }

                    case DuplicatiOperation.List:
                    {
                        var r = controller.List(data.FilterStrings);
                        UpdateMetadata(backup, r);
                        return(r);
                    }

                    case DuplicatiOperation.Repair:
                    {
                        var r = controller.Repair();
                        UpdateMetadata(backup, r);
                        return(r);
                    }

                    case DuplicatiOperation.Remove:
                    {
                        var r = controller.Delete();
                        UpdateMetadata(backup, r);
                        return(r);
                    }

                    case DuplicatiOperation.Restore:
                    {
                        var r = controller.Restore(data.FilterStrings);
                        UpdateMetadata(backup, r);
                        return(r);
                    }

                    case DuplicatiOperation.Verify:
                    {
                        var r = controller.Test();
                        UpdateMetadata(backup, r);
                        return(r);
                    }

                    case DuplicatiOperation.CreateReport:
                    {
                        using (var tf = new Duplicati.Library.Utility.TempFile())
                        {
                            var r      = controller.CreateLogDatabase(tf);
                            var tempid = Program.DataConnection.RegisterTempFile("create-bug-report", r.TargetPath, DateTime.Now.AddDays(3));

                            if (string.Equals(tf, r.TargetPath, Library.Utility.Utility.ClientFilenameStringComparision))
                            {
                                tf.Protected = true;
                            }

                            Program.DataConnection.RegisterNotification(
                                NotificationType.Information,
                                "Bugreport ready",
                                "Bugreport is ready for download",
                                null,
                                null,
                                "bug-report:created:" + tempid,
                                (n, a) => n
                                );

                            return(r);
                        }
                    }

                    default:
                        //TODO: Log this
                        return(null);
                    }
                }
            }
            catch (Exception ex)
            {
                Program.DataConnection.LogError(data.Backup.ID, string.Format("Failed while executing \"{0}\" with id: {1}", data.Operation, data.Backup.ID), ex);
                UpdateMetadataError(data.Backup, ex);

                if (!fromQueue)
                {
                    throw;
                }

                return(null);
            }
            finally
            {
                ((RunnerData)data).Controller = null;
                Program.LogHandler.RemoveOperationFile();
            }
        }
Exemplo n.º 12
0
        public static int Repair(List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
        {
            if (args.Count != 1)
                return PrintWrongNumberOfArguments(args, 1);

            using(var i = new Duplicati.Library.Main.Controller(args[0], options, new ConsoleOutput(options)))
                i.Repair(filter);

            return 0;
        }
Exemplo n.º 13
0
        /// <summary>
        /// Running the unit test confirms the correctness of duplicati
        /// </summary>
        /// <param name="folders">The folders to backup. Folder at index 0 is the base, all others are incrementals</param>
        /// <param name="target">The target destination for the backups</param>
        public static void RunTest(string[] folders, Dictionary<string, string> options, string target)
        {
            var oldlog = Log.CurrentLog as IDisposable;
            Log.CurrentLog = null;
            if (oldlog != null)
                try { oldlog.Dispose(); }
                catch { }

            LogHelper log = new LogHelper(string.Format("unittest-{0}.log", Library.Utility.Utility.SerializeDateTime(DateTime.Now)));
            Log.CurrentLog = log;
            Log.LogLevel = Duplicati.Library.Logging.LogMessageType.Profiling;

            string tempdir = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "tempdir");

            //Filter empty entries, commonly occuring with copy/paste and newlines
            folders = (from x in folders 
                      where !string.IsNullOrWhiteSpace(x)
                      select Library.Utility.Utility.ExpandEnvironmentVariables(x)).ToArray();

            //Expand the tilde to home folder on Linux/OSX
            if (Utility.IsClientLinux)
                folders = (from x in folders
                            select x.Replace("~", Environment.GetFolderPath(Environment.SpecialFolder.Personal))).ToArray();

            foreach(var f in folders)
                foreach(var n in f.Split(new char[] {System.IO.Path.PathSeparator}, StringSplitOptions.RemoveEmptyEntries))
                    if (!System.IO.Directory.Exists(n))
                        throw new Exception(string.Format("Missing source folder: {0}", n));

            try
            {
                if (System.IO.Directory.Exists(tempdir))
                    System.IO.Directory.Delete(tempdir, true);

                System.IO.Directory.CreateDirectory(tempdir);
            }
            catch(Exception ex)
            {
                Log.WriteMessage("Failed to clean tempdir", LogMessageType.Error, ex);
            }

            Duplicati.Library.Utility.TempFolder.SystemTempPath = tempdir;

            //Set some defaults
            if (!options.ContainsKey("passphrase"))
                options["passphrase"] = "secret password!";

            if (!options.ContainsKey("prefix"))
                options["prefix"] = "duplicati_unittest";

            //We want all messages in the log
            options["log-level"] = LogMessageType.Profiling.ToString();
            //We cannot rely on USN numbering, but we can use USN enumeration
            //options["disable-usn-diff-check"] = "true";
            
            //We use precise times
            options["disable-time-tolerance"] = "true";

            //We need all sets, even if they are unchanged
            options["upload-unchanged-backups"] = "true";
            
            bool skipfullrestore = false;
            bool skippartialrestore = false;
            bool skipverify = false;
            
            if (Utility.ParseBoolOption(options, "unittest-backuponly"))
            {
                skipfullrestore = true;
                skippartialrestore = true;
                options.Remove("unittest-backuponly");
            }
            
            if (Utility.ParseBoolOption(options, "unittest-skip-partial-restore"))
            {
                skippartialrestore = true;
                options.Remove("unittest-skip-partial-restore");
            }
            
            if (Utility.ParseBoolOption(options, "unittest-skip-full-restore"))
            {
                skipfullrestore = true;
                options.Remove("unittest-skip-full-restore");
            }
            
            if (Utility.ParseBoolOption(options, "unittest-skip-verify"))
            {
                skipverify = true;
                options.Remove("unittest-skip-verify");
            }

            var verifymetadata = !Utility.ParseBoolOption(options, "skip-metadata");
            
            using(new Timer("Total unittest"))
            using(TempFolder tf = new TempFolder())
            {
                options["dbpath"] = System.IO.Path.Combine(tempdir, "unittest.sqlite");
                if (System.IO.File.Exists(options["dbpath"]))
                    System.IO.File.Delete(options["dbpath"]);

                if (string.IsNullOrEmpty(target))
                {
                    target = "file://" + tf;
                }
                else
                {
                    Console.WriteLine("Removing old backups");
                    Dictionary<string, string> tmp = new Dictionary<string, string>(options);
                    tmp["keep-versions"] = "0";
                    tmp["force"] = "";
                    tmp["allow-full-removal"] = "";

                    using(new Timer("Cleaning up any existing backups"))
                    try
                    {
                        using(var bk = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(target, options))
                            foreach(var f in bk.List())
                                if (!f.IsFolder)
                                    bk.Delete(f.Name);
                    }
                    catch(Duplicati.Library.Interface.FolderMissingException)
                    {
                    }
                }

                log.Backupset = "Backup " + folders[0];
                string fhtempsource = null;
                
                bool usingFHWithRestore = (!skipfullrestore || !skippartialrestore);

                using(var fhsourcefolder = usingFHWithRestore ? new Library.Utility.TempFolder() : null)
                {
                    if (usingFHWithRestore)
                    {
                        fhtempsource = fhsourcefolder;
                        TestUtils.CopyDirectoryRecursive(folders[0], fhsourcefolder);
                    }

                    RunBackup(usingFHWithRestore ? (string)fhsourcefolder : folders[0], target, options, folders[0]);
    
                    for (int i = 1; i < folders.Length; i++)
                    {
                        //options["passphrase"] = "bad password";
                        //If the backups are too close, we can't pick the right one :(
                        System.Threading.Thread.Sleep(1000 * 5);
                        log.Backupset = "Backup " + folders[i];
    
                        if (usingFHWithRestore)
                        {
                            System.IO.Directory.Delete(fhsourcefolder, true);
                            TestUtils.CopyDirectoryRecursive(folders[i], fhsourcefolder);
                        }
                        
                        //Call function to simplify profiling
                        RunBackup(usingFHWithRestore ? (string)fhsourcefolder : folders[i], target, options, folders[i]);
                    }
                }

                Duplicati.Library.Main.Options opts = new Duplicati.Library.Main.Options(options);
                using (Duplicati.Library.Interface.IBackend bk = Duplicati.Library.DynamicLoader.BackendLoader.GetBackend(target, options))
                    foreach (Duplicati.Library.Interface.IFileEntry fe in bk.List())
                        if (fe.Size > opts.VolumeSize)
                        {
                            string msg = string.Format("The file {0} is {1} bytes larger than allowed", fe.Name, fe.Size - opts.VolumeSize);
                            Console.WriteLine(msg);
                            Log.WriteMessage(msg, LogMessageType.Error);
                        }

                IList<DateTime> entries;
                using(var i = new Duplicati.Library.Main.Controller(target, options, new CommandLine.ConsoleOutput(options)))
                    entries = (from n in i.List().Filesets select n.Time.ToLocalTime()).ToList();

                if (entries.Count != folders.Length)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("Entry count: " + entries.Count.ToString());
                    sb.Append(string.Format("Found {0} filelists but there were {1} source folders", entries.Count, folders.Length));
                    throw new Exception("Filename parsing problem, or corrupt storage: " + sb.ToString());
                }

                if (!skipfullrestore || !skippartialrestore)
                {
                    for (int i = 0; i < entries.Count; i++)
                    {
                        using (TempFolder ttf = new TempFolder())
                        {
                            log.Backupset = "Restore " + folders[i];
                            Console.WriteLine("Restoring the copy: " + folders[i]);
    
                            options["time"] = entries[entries.Count - i - 1].ToString();
    
                            string[] actualfolders = folders[i].Split(System.IO.Path.PathSeparator);    
                            if (!skippartialrestore)
                            {
                                Console.WriteLine("Partial restore of: " + folders[i]);
                                using (TempFolder ptf = new TempFolder())
                                {
                                    List<string> testfiles = new List<string>();
                                    using (new Timer("Extract list of files from" + folders[i]))
                                    {
                                        List<string> sourcefiles;
                                        using(var inst = new Library.Main.Controller(target, options, new CommandLine.ConsoleOutput(options)))
                                            sourcefiles = (from n in inst.List("*").Files select n.Path).ToList();
        
                                        //Remove all folders from list
                                        for (int j = 0; j < sourcefiles.Count; j++)
                                            if (sourcefiles[j].EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()))
                                            {
                                                sourcefiles.RemoveAt(j);
                                                j--;
                                            }
        
        
                                        int testfilecount = 15;
                                        Random r = new Random();
                                        while (testfilecount-- > 0 && sourcefiles.Count > 0)
                                        {
                                            int rn = r.Next(0, sourcefiles.Count);
                                            testfiles.Add(sourcefiles[rn]);
                                            sourcefiles.RemoveAt(rn);
                                        }
        
                                    }
        
        
                                    //Add all folders to avoid warnings in restore log
                                    int c = testfiles.Count;
                                    Dictionary<string, string> partialFolders = new Dictionary<string, string>(Utility.ClientFilenameStringComparer);
        
                                    for (int j = 0; j < c; j++)
                                    {
                                        string f = testfiles[j];
        
                                        if (!f.StartsWith(usingFHWithRestore ? fhtempsource : folders[i], Utility.ClientFilenameStringComparision))
                                            throw new Exception(string.Format("Unexpected file found: {0}, path is not a subfolder for {1}", f, folders[i]));
        
                                        f = f.Substring(Utility.AppendDirSeparator(usingFHWithRestore ? fhtempsource : folders[i]).Length);
        
                                        do
                                        {
                                            f = System.IO.Path.GetDirectoryName(f);
                                            partialFolders[Utility.AppendDirSeparator(f)] = null;
                                        } while (f.IndexOf(System.IO.Path.DirectorySeparatorChar) > 0);
                                    }
        
                                    if (partialFolders.ContainsKey(""))
                                        partialFolders.Remove("");
                                    if (partialFolders.ContainsKey(System.IO.Path.DirectorySeparatorChar.ToString()))
                                        partialFolders.Remove(System.IO.Path.DirectorySeparatorChar.ToString());
        
                                    List<string> filterlist;
        
                                    var tfe = Utility.AppendDirSeparator(usingFHWithRestore ? fhtempsource : folders[i]);
                                    
                                    filterlist = (from n in partialFolders.Keys
                                                  where !string.IsNullOrWhiteSpace(n) && n != System.IO.Path.DirectorySeparatorChar.ToString()
                                                  select Utility.AppendDirSeparator(System.IO.Path.Combine(tfe, n)))
                                                  .Union(testfiles) //Add files with full path
                                                  .Union(new string[] { tfe }) //Ensure root folder is included
                                                  .Distinct()
                                                  .ToList();
    
                                    testfiles = (from n in testfiles select n.Substring(tfe.Length)).ToList();
                
                                    //Call function to simplify profiling
                                    RunPartialRestore(folders[i], target, ptf, options, filterlist.ToArray());
        
                                    if (!skipverify)
                                    {
                                        //Call function to simplify profiling
                                        Console.WriteLine("Verifying partial restore of: " + folders[i]);
                                        VerifyPartialRestore(folders[i], testfiles, actualfolders, ptf, folders[0], verifymetadata);
                                    }
                                }
                            }
    
                            if (!skipfullrestore)
                            {
                                //Call function to simplify profiling
                                RunRestore(folders[i], target, ttf, options);
        
                                if (!skipverify)
                                {
                                    //Call function to simplify profiling
                                    Console.WriteLine("Verifying the copy: " + folders[i]);
                                    VerifyFullRestore(folders[i], actualfolders, new string[] { ttf }, verifymetadata);
                                }
                            }
                        }
                    }
                }   
                
                foreach(string s in Utility.EnumerateFiles(tempdir))
                {
                	if (s == options["dbpath"])
                		continue;
                	if (s.StartsWith(Utility.AppendDirSeparator(tf)))
                		continue;
                		
                	Log.WriteMessage(string.Format("Found left-over temp file: {0}", s.Substring(tempdir.Length)), LogMessageType.Warning);
                	Console.WriteLine("Found left-over temp file: {0} -> {1}", s.Substring(tempdir.Length), 
#if DEBUG
                        TempFile.GetStackTraceForTempFile(System.IO.Path.GetFileName(s))
#else
                        System.IO.Path.GetFileName(s)
#endif
                    );
                }
                
                foreach(string s in Utility.EnumerateFolders(tempdir))
                	if (!s.StartsWith(Utility.AppendDirSeparator(tf)) && Utility.AppendDirSeparator(s) != Utility.AppendDirSeparator(tf) && Utility.AppendDirSeparator(s) != Utility.AppendDirSeparator(tempdir))
                	{
                		Log.WriteMessage(string.Format("Found left-over temp folder: {0}", s.Substring(tempdir.Length)), LogMessageType.Warning);
                		Console.WriteLine("Found left-over temp folder: {0}", s.Substring(tempdir.Length));
                	}
            }

            (Log.CurrentLog as StreamLog).Dispose();
            Log.CurrentLog = null;
            
            if (LogHelper.ErrorCount > 0)
        		Console.WriteLine("Unittest completed, but with {0} errors, see logfile for details", LogHelper.ErrorCount);
            else if (LogHelper.WarningCount > 0)
        		Console.WriteLine("Unittest completed, but with {0} warnings, see logfile for details", LogHelper.WarningCount);
        	else
        		Console.WriteLine("Unittest completed successfully - Have some cake!");            	
        }
Exemplo n.º 14
0
 private static void RunPartialRestore(string source, string target, string tempfolder, Dictionary<string, string> options, string[] files)
 {
 	var tops = new Dictionary<string, string>(options);
 	tops["restore-path"] = tempfolder;
     using (new Timer("Partial restore of " + source))
     using(var i = new Duplicati.Library.Main.Controller(target, tops, new CommandLine.ConsoleOutput(options)))
         Log.WriteMessage(i.Restore(files).ToString(), LogMessageType.Information);
 }
Exemplo n.º 15
0
 private static void RunBackup(string source, string target, Dictionary<string, string> options, string sourcename)
 {
     Console.WriteLine("Backing up the copy: " + sourcename);
     using (new Timer("Backup of " + sourcename))
     using(var i = new Duplicati.Library.Main.Controller(target, options, new CommandLine.ConsoleOutput(options)))
         Log.WriteMessage(i.Backup(source.Split(System.IO.Path.PathSeparator)).ToString(), LogMessageType.Information);
 }
Exemplo n.º 16
0
        public static Duplicati.Library.Interface.IBasicResults Run(IRunnerData data, bool fromQueue)
        {
            var backup = data.Backup;

            if (backup.Metadata == null)
                backup.Metadata = new Dictionary<string, string>();
            
            try
            {                
                var options = ApplyOptions(backup, data.Operation, GetCommonOptions(backup, data.Operation));
                var sink = new MessageSink(data.TaskID, backup.ID);
                if (fromQueue)
                {
                    Program.GenerateProgressState = () => sink.Copy();
                    Program.StatusEventNotifyer.SignalNewEvent();            
                }
                
                if (data.ExtraOptions != null)
                    foreach(var k in data.ExtraOptions)
                        options[k.Key] = k.Value;

                if (options.ContainsKey("log-file"))
                {
                    var file = options["log-file"];

                    string o;
                    Library.Logging.LogMessageType level;
                    options.TryGetValue("log-level", out o);
                    Enum.TryParse<Library.Logging.LogMessageType>(o, true, out level);

                    options.Remove("log-file");
                    options.Remove("log-level");

                    Program.LogHandler.SetOperationFile(file, level);
                }
                
                using(var controller = new Duplicati.Library.Main.Controller(backup.TargetURL, options, sink))
                {
                    ((RunnerData)data).Controller = controller;
                    
                    switch (data.Operation)
                    {
                        case DuplicatiOperation.Backup:
                            {
                                var filter = ApplyFilter(backup, data.Operation, GetCommonFilter(backup, data.Operation));
                                var sources = 
                                    (from n in backup.Sources
                                        let p = SpecialFolders.ExpandEnvironmentVariables(n)
                                        where !string.IsNullOrWhiteSpace(p)
                                        select p).ToArray();
                                
                                var r = controller.Backup(sources, filter);
                                UpdateMetadata(backup, r);
                                return r;
                            }                          
                        case DuplicatiOperation.List:
                            {
                                var r = controller.List(data.FilterStrings);
                                UpdateMetadata(backup, r);
                                return r;
                            }
                        case DuplicatiOperation.Repair:
                            {
                                var r = controller.Repair();
                                UpdateMetadata(backup, r);
                                return r;
                            }
                        case DuplicatiOperation.Remove:
                            {
                                var r = controller.Delete();
                                UpdateMetadata(backup, r);
                                return r;
                            }
                        case DuplicatiOperation.Restore:
                            {
                                var r = controller.Restore(data.FilterStrings);
                                UpdateMetadata(backup, r);
                                return r;
                            }
                        case DuplicatiOperation.Verify:
                            {
                                var r = controller.Test();
                                UpdateMetadata(backup, r);
                                return r;
                            }

                        case DuplicatiOperation.CreateReport:
                            {
                                using(var tf = new Duplicati.Library.Utility.TempFile())
                                {
                                    var r = controller.CreateLogDatabase(tf);
                                    var tempid = Program.DataConnection.RegisterTempFile("create-bug-report", r.TargetPath, DateTime.Now.AddDays(3));

                                    if (string.Equals(tf, r.TargetPath, Library.Utility.Utility.ClientFilenameStringComparision))
                                        tf.Protected = true;

                                    Program.DataConnection.RegisterNotification(
                                        NotificationType.Information,
                                        "Bugreport ready",
                                        "Bugreport is ready for download",
                                         null,
                                         null,
                                         "bug-report:created:" + tempid,
                                         (n, a) => n
                                     );

                                    return r;
                                }
                            }
                        default:
                            //TODO: Log this
                            return null;
                    }
                }
            }
            catch (Exception ex)
            {
                Program.DataConnection.LogError(data.Backup.ID, string.Format("Failed while executing \"{0}\" with id: {1}", data.Operation, data.Backup.ID), ex);
                UpdateMetadataError(data.Backup, ex);
                
                if (!fromQueue)
                    throw;
                
                return null;
            }
            finally
            {
                ((RunnerData)data).Controller = null;
                Program.LogHandler.RemoveOperationFile();
            }
        }