Exemplo n.º 1
0
        static bool Run(List<string> args, Dictionary<string, string> options, bool first)
        {
            string allowedChars = ValidFilenameChars;
            if (options.ContainsKey("extended-chars"))
                allowedChars += options["extended-chars"];
            else
                allowedChars += ExtendedChars;

            bool autoCreateFolders = Library.Utility.Utility.ParseBoolOption(options, "auto-create-folder");

            Library.Interface.IBackend backend = Library.DynamicLoader.BackendLoader.GetBackend(args[0], options);
            if (backend == null)
            {
                Console.WriteLine("Unsupported backend");
                Console.WriteLine();
                Console.WriteLine("Supported backends: " + string.Join(",", Duplicati.Library.DynamicLoader.BackendLoader.Keys));
                return false;
            }

            string disabledModulesValue;
            string enabledModulesValue;
            options.TryGetValue("enable-module", out enabledModulesValue);
            options.TryGetValue("disable-module", out disabledModulesValue);
            string[] enabledModules = enabledModulesValue == null ? new string[0] : enabledModulesValue.Trim().ToLower().Split(',');
            string[] disabledModules = disabledModulesValue == null ? new string[0] : disabledModulesValue.Trim().ToLower().Split(',');

            List<Library.Interface.IGenericModule> loadedModules = new List<IGenericModule>();
            foreach (Library.Interface.IGenericModule m in Library.DynamicLoader.GenericLoader.Modules)
                if (Array.IndexOf<string>(disabledModules, m.Key.ToLower()) < 0 && (m.LoadAsDefault || Array.IndexOf<string>(enabledModules, m.Key.ToLower()) >= 0))
                {
                    m.Configure(options);
                    loadedModules.Add(m);
                }

            try
            {
                List<Library.Interface.IFileEntry> curlist = null;
                try
                {
                    curlist = backend.List();
                }
                catch (FolderMissingException fex)
                {
                    if (autoCreateFolders)
                    {
                        try
                        {
                            backend.CreateFolder();
                            curlist = backend.List();
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Autocreate folder failed with message: " + ex.Message);
                        }
                    }

                    if (curlist == null)
                        throw fex;
                }

                foreach (Library.Interface.IFileEntry fe in curlist)
                    if (!fe.IsFolder)
                    {
                        if (Library.Utility.Utility.ParseBoolOption(options, "auto-clean") && first)
                            if (Library.Utility.Utility.ParseBoolOption(options, "force"))
                            {
                                Console.WriteLine("Auto clean, removing file: {0}", fe.Name);
                                backend.Delete(fe.Name);
                                continue;
                            }
                            else
                                Console.WriteLine("Specify the --force flag to actually delete files");

                        Console.WriteLine("*** Remote folder is not empty, aborting");
                        return false;
                    }


                int number_of_files = 10;
                int min_file_size = 1024;
                int max_file_size = 1024 * 1024 * 50;
                int min_filename_size = 5;
                int max_filename_size = 80;
                bool disableStreaming = Library.Utility.Utility.ParseBoolOption(options, "disable-streaming-transfers");
                bool skipOverwriteTest = Library.Utility.Utility.ParseBoolOption(options, "skip-overwrite-test");

                if (options.ContainsKey("number-of-files"))
                    number_of_files = int.Parse(options["number-of-files"]);
                if (options.ContainsKey("min-file-size"))
                    min_file_size = (int)Duplicati.Library.Utility.Sizeparser.ParseSize(options["min-file-size"], "mb");
                if (options.ContainsKey("max-file-size"))
                    max_file_size = (int)Duplicati.Library.Utility.Sizeparser.ParseSize(options["max-file-size"], "mb");

                if (options.ContainsKey("min-filename-length"))
                    min_filename_size = int.Parse(options["min-filename-length"]);
                if (options.ContainsKey("max-filename-length"))
                    max_filename_size = int.Parse(options["max-filename-length"]);

                Random rnd = new Random();
                System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create();

                //Create random files
                using (Library.Utility.TempFolder tf = new Duplicati.Library.Utility.TempFolder())
                {
                    List<TempFile> files = new List<TempFile>();
                    for (int i = 0; i < number_of_files; i++)
                    {

                        StringBuilder filename = new StringBuilder();
                        int filenamelen = rnd.Next(min_filename_size, max_filename_size);
                        for (int j = 0; j < filenamelen; j++)
                            filename.Append(allowedChars[rnd.Next(0, allowedChars.Length)]);

                        string localfilename = CreateRandomFile(tf, i, min_file_size, max_file_size, rnd);

                        //Calculate local hash and length
                        using (System.IO.FileStream fs = new System.IO.FileStream(localfilename, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                            files.Add(new TempFile(filename.ToString(), localfilename, sha.ComputeHash(fs), fs.Length));
                    }

                    byte[] dummyFileHash = null;
                    if (!skipOverwriteTest)
                    {
                        Console.WriteLine("Uploading wrong files ...");
                        using (Library.Utility.TempFile dummy = Library.Utility.TempFile.WrapExistingFile(CreateRandomFile(tf, files.Count, 1024, 2048, rnd)))
                        {
                            using (System.IO.FileStream fs = new System.IO.FileStream(dummy, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                                dummyFileHash = sha.ComputeHash(fs);

                            //Upload a dummy file for entry 0 and the last one, they will be replaced by the real files afterwards
                            //We upload entry 0 twice just to try to freak any internal cache list
                            Uploadfile(dummy, 0, files[0].remotefilename, backend, disableStreaming);
                            Uploadfile(dummy, 0, files[0].remotefilename, backend, disableStreaming);
                            Uploadfile(dummy, files.Count - 1, files[files.Count - 1].remotefilename, backend, disableStreaming);
                        }

                    }

                    Console.WriteLine("Uploading files ...");

                    for (int i = 0; i < files.Count; i++)
                        Uploadfile(files[i].localfilename, i, files[i].remotefilename, backend, disableStreaming);

                    Console.WriteLine("Verifying file list ...");

                    curlist = backend.List();
                    foreach (Library.Interface.IFileEntry fe in curlist)
                        if (!fe.IsFolder)
                        {
                            bool found = false;
                            foreach (TempFile tx in files)
                                if (tx.remotefilename == fe.Name)
                                {
                                    if (tx.found)
                                        Console.WriteLine("*** File with name {0} was found more than once", tx.remotefilename);
                                    found = true;
                                    tx.found = true;

                                    if (fe.Size > 0 && tx.length != fe.Size)
                                        Console.WriteLine("*** File with name {0} has size {1} but the size was reported as {2}", tx.remotefilename, tx.length, fe.Size);

                                    break;
                                }

                            if (!found)
                                Console.WriteLine("*** File with name {0} was found on server but not uploaded!", fe.Name);
                        }

                    foreach (TempFile tx in files)
                        if (!tx.found)
                            Console.WriteLine("*** File with name {0} was uploaded but not found afterwards", tx.remotefilename);

                    Console.WriteLine("Downloading files");

                    for (int i = 0; i < files.Count; i++)
                    {
                        using (Duplicati.Library.Utility.TempFile cf = new Duplicati.Library.Utility.TempFile())
                        {
                            Exception e = null;
                            Console.Write("Downloading file {0} ... ", i);

                            try
                            {
                                if (backend is Library.Interface.IStreamingBackend && !disableStreaming)
                                {
                                    using (System.IO.FileStream fs = new System.IO.FileStream(cf, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
                                    using (NonSeekableStream nss = new NonSeekableStream(fs))
                                        (backend as Library.Interface.IStreamingBackend).Get(files[i].remotefilename, nss);
                                }
                                else
                                    backend.Get(files[i].remotefilename, cf);

                                e = null;
                            }
                            catch (Exception ex)
                            {
                                e = ex;
                            }

                            if (e != null)
                                Console.WriteLine("failed\n*** Error: {0}", e.ToString());
                            else
                                Console.WriteLine("done");

                            Console.Write("Checking hash ... ");

                            using (System.IO.FileStream fs = new System.IO.FileStream(cf, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                                if (Convert.ToBase64String(sha.ComputeHash(fs)) != Convert.ToBase64String(files[i].hash))
                                {
                                    if (dummyFileHash != null && Convert.ToBase64String(sha.ComputeHash(fs)) == Convert.ToBase64String(dummyFileHash))
                                        Console.WriteLine("failed\n*** Downloaded file was the dummy file");
                                    else
                                        Console.WriteLine("failed\n*** Downloaded file was corrupt");
                                }
                                else
                                    Console.WriteLine("done");
                        }
                    }

                    Console.WriteLine("Deleting files...");

                    foreach (TempFile tx in files)
                        try { backend.Delete(tx.remotefilename); }
                        catch (Exception ex)
                        {
                            Console.WriteLine("*** Failed to delete file {0}, message: {1}", tx.remotefilename, ex.ToString());
                        }

                    curlist = backend.List();
                    foreach (Library.Interface.IFileEntry fe in curlist)
                        if (!fe.IsFolder)
                        {
                            Console.WriteLine("*** Remote folder contains {0} after cleanup", fe.Name);
                        }

                }
            }
            finally
            {
                foreach (Library.Interface.IGenericModule m in loadedModules)
                    if (m is IDisposable)
                        ((IDisposable)m).Dispose();
            }

            return true;
        }
Exemplo n.º 2
0
        public void ExecuteTask(IDuplicityTask task)
        {
            Dictionary<string, string> options = new Dictionary<string,string>();

            //Set the log level to be that of the GUI
            options["log-level"] = Duplicati.Library.Logging.Log.LogLevel.ToString();

            string destination = task.GetConfiguration(options);

            string results = "";
            string parsedMessage = "";
            m_isAborted = false;

            try
            {
                //TODO: Its a bit dirty to set the options after creating the instance
                using (Interface i = new Interface(destination, options))
                {
                    lock (m_lock)
                    {
                        m_stopReason = System.Windows.Forms.CloseReason.None;
                        m_currentBackupControlInterface = i;
                    }

                    SetupControlInterface();

                    i.OperationProgress += new OperationProgressEvent(Duplicati_OperationProgress);

                    switch (task.TaskType)
                    {
                        case DuplicityTaskType.FullBackup:
                        case DuplicityTaskType.IncrementalBackup:
                            {
                                //Activate auto-cleanup
                                options["auto-cleanup"] = "";
                                options["force"] = "";
                                if (task.Schedule.Task.KeepFull > 0)
                                    m_extraOperations++;
                                if (!string.IsNullOrEmpty(task.Schedule.Task.KeepTime))
                                    m_extraOperations++;

                                Library.Utility.TempFolder tf = null;
                                try
                                {
                                    if (ProgressEvent != null)
                                        ProgressEvent(DuplicatiOperation.Backup, RunnerState.Started, task.Schedule.Name, "", 0, -1);

                                    if (task.Task.IncludeSetup)
                                    {
                                        //Make a copy of the current database
                                        tf = new Duplicati.Library.Utility.TempFolder();
                                        string filename = System.IO.Path.Combine(tf, System.IO.Path.GetFileName(Program.DatabasePath));

                                        System.IO.File.Copy(Program.DatabasePath, filename, true);
                                        using (System.Data.IDbConnection con = (System.Data.IDbConnection)Activator.CreateInstance(SQLiteLoader.SQLiteConnectionType))
                                        {
                                            con.ConnectionString = "Data Source=" + filename;

                                            //Open the database, handle any encryption issues automatically
                                            Program.OpenDatabase(con);

                                            using (System.Data.IDbCommand cmd = con.CreateCommand())
                                            {
                                                //Remove all log data to minimize the size of the database
                                                cmd.CommandText = "DELETE FROM CommandQueue;";
                                                cmd.ExecuteNonQuery();
                                                cmd.CommandText = "DELETE FROM Log;";
                                                cmd.ExecuteNonQuery();
                                                cmd.CommandText = "DELETE FROM LogBlob;";
                                                cmd.ExecuteNonQuery();

                                                //Free up unused space
                                                cmd.CommandText = "VACUUM;";
                                                cmd.ExecuteNonQuery();
                                            }
                                        }

                                        options["signature-control-files"] = filename;
                                    }

                                    options["full-if-sourcefolder-changed"] = "";

                                    List<KeyValuePair<bool, string>> filters = new List<KeyValuePair<bool, string>>();
                                    string[] sourceFolders = DynamicSetupHelper.GetSourceFolders(task.Task, new ApplicationSettings(task.Task.DataParent), filters);

                                    if (options.ContainsKey("filter"))
                                        filters.AddRange(Library.Utility.FilenameFilter.DecodeFilter(options["filter"]));

                                    options["filter"] = Library.Utility.FilenameFilter.EncodeAsFilter(filters);

                                    //At this point we register the backup as being in progress
                                    ((FullOrIncrementalTask)task).WriteBackupInProgress(Strings.DuplicatiRunner.ShutdownWhileBackupInprogress);

                                    results = i.Backup(sourceFolders);
                                }
                                finally
                                {
                                    if (tf != null)
                                        tf.Dispose();

                                    if (ProgressEvent != null)
                                        ProgressEvent(DuplicatiOperation.Backup, RunnerState.Stopped, task.Schedule.Name, "", 100, -1);
                                }
                                break;
                            }
                        case DuplicityTaskType.ListBackups:

                            List<string> res = new List<string>();
                            foreach (ManifestEntry be in i.GetBackupSets())
                            {
                                res.Add(be.Time.ToString());
                                foreach (ManifestEntry bei in be.Incrementals)
                                    res.Add(bei.Time.ToString());
                            }

                            (task as ListBackupsTask).Backups = res.ToArray();
                            break;
                        case DuplicityTaskType.ListBackupEntries:
                            (task as ListBackupEntriesTask).Backups = i.GetBackupSets();
                            break;
                        case DuplicityTaskType.ListFiles:
                            (task as ListFilesTask).Files = i.ListCurrentFiles();
                            break;
                        case DuplicityTaskType.ListSourceFolders:
                            (task as ListSourceFoldersTask).Files = new List<string>(i.ListSourceFolders() ?? new string[0]);
                            break;
                        case DuplicityTaskType.ListActualFiles:
                            (task as ListActualFilesTask).Files = i.ListActualSignatureFiles();
                            break;
                        case DuplicityTaskType.RemoveAllButNFull:
                            results = i.DeleteAllButNFull();
                            break;
                        case DuplicityTaskType.RemoveOlderThan:
                            results = i.DeleteOlderThan();
                            break;
                        case DuplicityTaskType.Restore:
                            options["file-to-restore"] = ((RestoreTask)task).SourceFiles;
                            if (options.ContainsKey("filter"))
                                options.Remove("filter");

                            try
                            {
                                if (ProgressEvent != null)
                                    ProgressEvent(DuplicatiOperation.Restore, RunnerState.Started, task.Schedule.Name, "", 0, -1);
                                results = i.Restore(task.LocalPath.Split(System.IO.Path.PathSeparator));
                            }
                            finally
                            {
                                if (ProgressEvent != null)
                                    ProgressEvent(DuplicatiOperation.Restore, RunnerState.Stopped, task.Schedule.Name, "", 100, -1);
                            }
                            break;

                        case DuplicityTaskType.RestoreSetup:
                            i.RestoreControlFiles(task.LocalPath);
                            break;
                        default:
                            return;
                    }
                }
            }
            catch (Exception ex)
            {
                while (ex is System.Reflection.TargetInvocationException && ex.InnerException != null)
                    ex = ex.InnerException;

                if (ex is System.Threading.ThreadAbortException)
                {
                    m_isAborted = true;
                    System.Threading.Thread.ResetAbort();
                }
                else if (ex is Library.Main.LiveControl.ExecutionStoppedException)
                    m_isAborted = true;

                if (m_isAborted && m_stopReason != System.Windows.Forms.CloseReason.None)
                {
                    //If the user has stopped the backup for some reason, write a nicer message
                    switch (m_stopReason)
                    {
                        case System.Windows.Forms.CloseReason.ApplicationExitCall:
                            parsedMessage = Strings.DuplicatiRunner.ApplicationExitLogMesssage;
                            break;
                        case System.Windows.Forms.CloseReason.TaskManagerClosing:
                            parsedMessage = Strings.DuplicatiRunner.TaskManagerCloseMessage;
                            break;
                        case System.Windows.Forms.CloseReason.UserClosing:
                            parsedMessage = Strings.DuplicatiRunner.UserClosingMessage;
                            break;
                        case System.Windows.Forms.CloseReason.WindowsShutDown:
                            parsedMessage = Strings.DuplicatiRunner.WindowsShutdownMessage;
                            break;
                        default:
                            parsedMessage = string.Format(Strings.DuplicatiRunner.OtherAbortMessage, m_stopReason);
                            break;
                    }

                    if (task.Schedule != null)
                    {
                        //If the application is going down, the backup should resume on next launch
                        switch (m_stopReason)
                        {
                            case System.Windows.Forms.CloseReason.ApplicationExitCall:
                            case System.Windows.Forms.CloseReason.TaskManagerClosing:
                            case System.Windows.Forms.CloseReason.WindowsShutDown:
                                task.Schedule.ScheduledRunFailed();
                                break;
                        }
                    }
                }
                else
                    parsedMessage = string.Format(Strings.DuplicatiRunner.ErrorMessage, ex.Message);

                results = "Error: " + ex.ToString(); //Don't localize

                while (ex.InnerException != null)
                {
                    ex = ex.InnerException;
                    results += Environment.NewLine + "InnerError: " + ex.ToString(); //Don't localize
                }

            }
            finally
            {
                lock (m_lock)
                    m_currentBackupControlInterface = null;
            }

            try
            {
                if (!m_isAborted && (task.TaskType == DuplicityTaskType.FullBackup || task.TaskType == DuplicityTaskType.IncrementalBackup))
                {
                    if (task.Schedule.Task.KeepFull > 0)
                    {
                        m_lastPGProgress = 100;
                        m_lastPGmessage = Strings.DuplicatiRunner.CleaningUpMessage;
                        m_lastPGSubmessage = "";
                        m_lastPGSubprogress = -1;

                        ReinvokeLastProgressEvent();
                        m_extraOperations--;

                        RemoveAllButNFullTask tmpTask = new RemoveAllButNFullTask(task.Schedule, (int)task.Schedule.Task.KeepFull);
                        ExecuteTask(tmpTask);
                        results += Environment.NewLine + Strings.DuplicatiRunner.CleanupLogdataHeader + Environment.NewLine + tmpTask.Result;
                    }

                    if (!string.IsNullOrEmpty(task.Schedule.Task.KeepTime))
                    {
                        m_lastPGProgress = 100;
                        m_lastPGmessage = Strings.DuplicatiRunner.CleaningUpMessage;
                        m_lastPGSubmessage = "";
                        m_lastPGSubprogress = -1;

                        ReinvokeLastProgressEvent();
                        m_extraOperations--;

                        RemoveOlderThanTask tmpTask = new RemoveOlderThanTask(task.Schedule, task.Schedule.Task.KeepTime);
                        ExecuteTask(tmpTask);
                        results += Environment.NewLine + Strings.DuplicatiRunner.CleanupLogdataHeader + Environment.NewLine + tmpTask.Result;
                    }

                    if (task.Schedule.Task.KeepFull > 0 || !string.IsNullOrEmpty(task.Schedule.Task.KeepTime))
                        ReinvokeLastProgressEvent();

                    if (ProgressEvent != null)
                        ProgressEvent(DuplicatiOperation.Backup, RunnerState.Stopped, task.Schedule.Name, "", 100, -1);
                }
            }
            catch (Exception ex)
            {
                results += Environment.NewLine + string.Format(Strings.DuplicatiRunner.CleanupError, ex.Message);
            }

            task.IsAborted = m_isAborted;
            task.Result = results;
            task.RaiseTaskCompleted(results, parsedMessage);

            if (ResultEvent != null && task is FullBackupTask || task is IncrementalBackupTask)
            {
                Log[] logs = Program.DataConnection.GetObjects<Log>("TaskID = ? AND SubAction LIKE ? ORDER BY EndTime DESC", task.Task.ID, "Primary");
                if (logs != null && logs.Length > 0)
                {
                    Datamodel.Log l = logs[0];
                    RunnerResult r = RunnerResult.Error;
                    if (l.ParsedStatus == DuplicatiOutputParser.ErrorStatus)
                        r = RunnerResult.Error;
                    else if (l.ParsedStatus == DuplicatiOutputParser.OKStatus || l.ParsedStatus == DuplicatiOutputParser.NoChangedFiles)
                        r = RunnerResult.OK;
                    else if (l.ParsedStatus == DuplicatiOutputParser.PartialStatus)
                        r = RunnerResult.Partial;
                    else if (l.ParsedStatus == DuplicatiOutputParser.WarningStatus)
                        r = RunnerResult.Warning;

                    ResultEvent(r, parsedMessage, results);
                }
            }

            if (task.Schedule != null && !m_isAborted)
                task.Schedule.ScheduledRunCompleted(); //Register as completed if not aborted
        }
Exemplo n.º 3
0
        public static bool DownloadAndUnpackUpdate(UpdateInfo version, Action<double> progress = null)
        {
            if (INSTALLDIR == null)
                return false;

            var updates = version.RemoteURLS.ToList();

            // If alternate update URLs are specified,
            // we look for packages there as well
            if (AutoUpdateSettings.UsesAlternateURLs)
            {
                var packagepath = new Library.Utility.Uri(updates[0]).Path;
                var packagename = packagepath.Split('/').Last();

                foreach(var alt_url in AutoUpdateSettings.URLs.Reverse())
                {
                    var alt_uri = new Library.Utility.Uri(alt_url);
                    var path_components = alt_uri.Path.Split('/');
                    var path = string.Join("/", path_components.Take(path_components.Count() - 1).Union(new string[] { packagename}));

                    var new_path = alt_uri.SetPath(path);
                    updates.Insert(0, new_path.ToString());
                }
            }

            using(var tempfile = new Library.Utility.TempFile())
            {
                foreach(var url in updates)
                {
                    try
                    {
                        Action<long> cb = null;
                        if (progress != null)
                            cb = (s) => { progress(Math.Min(1.0, Math.Max(0.0, (double)s / version.CompressedSize))); };

                        var wreq = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
                        wreq.UserAgent = string.Format("{0} v{1}", APPNAME, SelfVersion.Version);
                        wreq.Headers.Add("X-Install-ID", InstallID);

                        using(var resp = wreq.GetResponse())
                        using(var rss = resp.GetResponseStream())
                        using(var pgs = new Duplicati.Library.Utility.ProgressReportingStream(rss, version.CompressedSize, cb))
                        using(var fs = System.IO.File.Open(tempfile, System.IO.FileMode.Create))
                            Duplicati.Library.Utility.Utility.CopyStream(pgs, fs);

                        var sha256 = System.Security.Cryptography.SHA256.Create();
                        var md5 =  System.Security.Cryptography.MD5.Create();

                        using(var s = System.IO.File.OpenRead(tempfile))
                        {
                            if (s.Length != version.CompressedSize)
                                throw new Exception(string.Format("Invalid file size {0}, expected {1} for {2}", s.Length, version.CompressedSize, url));

                            var sha256hash = Convert.ToBase64String(sha256.ComputeHash(s));
                            if (sha256hash != version.SHA256)
                                throw new Exception(string.Format("Damaged or corrupted file, sha256 mismatch for {0}", url));
                        }

                        using(var s = System.IO.File.OpenRead(tempfile))
                        {
                            var md5hash = Convert.ToBase64String(md5.ComputeHash(s));
                            if (md5hash != version.MD5)
                                throw new Exception(string.Format("Damaged or corrupted file, md5 mismatch for {0}", url));
                        }

                        using(var tempfolder = new Duplicati.Library.Utility.TempFolder())
                        using(var zip = new Duplicati.Library.Compression.FileArchiveZip(tempfile, new Dictionary<string, string>()))
                        {
                            foreach(var file in zip.ListFilesWithSize(""))
                            {
                                if (System.IO.Path.IsPathRooted(file.Key) || file.Key.Trim().StartsWith("..", StringComparison.InvariantCultureIgnoreCase))
                                    throw new Exception(string.Format("Out-of-place file path detected: {0}", file.Key));

                                var targetpath = System.IO.Path.Combine(tempfolder, file.Key);
                                var targetfolder = System.IO.Path.GetDirectoryName(targetpath);
                                if (!System.IO.Directory.Exists(targetfolder))
                                    System.IO.Directory.CreateDirectory(targetfolder);

                                using(var zs = zip.OpenRead(file.Key))
                                using(var fs = System.IO.File.Create(targetpath))
                                    zs.CopyTo(fs);
                            }

                            if (VerifyUnpackedFolder(tempfolder, version))
                            {
                                var versionstring = TryParseVersion(version.Version).ToString();
                                var targetfolder = System.IO.Path.Combine(INSTALLDIR, versionstring);
                                if (System.IO.Directory.Exists(targetfolder))
                                    System.IO.Directory.Delete(targetfolder, true);

                                System.IO.Directory.CreateDirectory(targetfolder);

                                var tempfolderpath = Duplicati.Library.Utility.Utility.AppendDirSeparator(tempfolder);
                                var tempfolderlength = tempfolderpath.Length;

                                // Would be nice, but does not work :(
                                //System.IO.Directory.Move(tempfolder, targetfolder);

                                foreach(var e in Duplicati.Library.Utility.Utility.EnumerateFileSystemEntries(tempfolder))
                                {
                                    var relpath = e.Substring(tempfolderlength);
                                    if (string.IsNullOrWhiteSpace(relpath))
                                        continue;

                                    var fullpath = System.IO.Path.Combine(targetfolder, relpath);
                                    if (relpath.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()))
                                        System.IO.Directory.CreateDirectory(fullpath);
                                    else
                                        System.IO.File.Copy(e, fullpath);
                                }

                                // Verification will kick in when we list the installed updates
                                //VerifyUnpackedFolder(targetfolder, version);
                                System.IO.File.WriteAllText(System.IO.Path.Combine(INSTALLDIR, CURRENT_FILE), versionstring);

                                m_hasUpdateInstalled = null;

                                var obsolete = (from n in FindInstalledVersions()
                                    where n.Value.Version != version.Version && n.Value.Version != SelfVersion.Version
                                    let x = TryParseVersion(n.Value.Version)
                                    orderby x descending
                                    select n).Skip(1).ToArray();

                                foreach(var f in obsolete)
                                    try { System.IO.Directory.Delete(f.Key, true); }
                                    catch { }

                                return true;
                            }
                            else
                            {
                                throw new Exception(string.Format("Unable to verify unpacked folder for url: {0}", url));
                            }
                        }
                    }
                    catch(Exception ex)
                    {
                        if (OnError != null)
                            OnError(ex);
                    }
                }
            }

            return false;
        }
Exemplo n.º 4
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.º 5
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, GetCommonOptions());
                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, GetCommonFilter());
                                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, null);
                                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("dbpath", 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.º 6
0
        private void Restore(object sender, DoWorkEventArgs args)
        {
            System.Data.LightDatamodel.DataFetcherNested con = new System.Data.LightDatamodel.DataFetcherNested(Program.DataConnection);
            Schedule s = con.Add<Schedule>();
            s.Task = con.Add<Task>();
            m_wrapper.UpdateSchedule(s);

            using (Library.Utility.TempFolder tf = new Duplicati.Library.Utility.TempFolder())
            {
                RestoreSetupTask task = new RestoreSetupTask(s, tf);
                Dictionary<string, string> options = new Dictionary<string, string>();
                string destination  = task.GetConfiguration(options);
                Library.Main.Interface.RestoreControlFiles(destination, task.LocalPath, options);

                string filename = System.IO.Path.Combine(tf, System.IO.Path.GetFileName(Program.DatabasePath));
                if (System.IO.File.Exists(filename))
                {
                    //Connect to the downloaded database
                    using (System.Data.IDbConnection scon = (System.Data.IDbConnection)Activator.CreateInstance(SQLiteLoader.SQLiteConnectionType))
                    {
                        scon.ConnectionString = "Data Source=" + filename;

                        //Make sure encryption etc is handled correctly
                        Program.OpenDatabase(scon);

                        //Upgrade the database to the current version
                        DatabaseUpgrader.UpgradeDatabase(scon, filename);
                    }

                    //Shut down this connection
                    Program.LiveControl.Pause();
                    Program.DataConnection.ClearCache();
                    //We also need to remove any dirty objects as the ClearCache maintains those
                    foreach (System.Data.LightDatamodel.IDataClass o in Program.DataConnection.LocalCache.GetAllChanged())
                        Program.DataConnection.DiscardObject(o);
                    Program.DataConnection.Provider.Connection.Close();

                    //Replace the existing database with this one
                    System.IO.File.Copy(filename, Program.DatabasePath, true);

                    //Re-start the connection, using the new file
                    Program.DataConnection.Provider.Connection = (System.Data.IDbConnection)Activator.CreateInstance(SQLiteLoader.SQLiteConnectionType);
                    Program.DataConnection.Provider.Connection.ConnectionString = "Data Source=" + Program.DatabasePath;
                    Program.OpenDatabase(Program.DataConnection.Provider.Connection);

                    //Remove the downloaded database
                    try { System.IO.File.Delete(filename); }
                    catch { }
                }
                else
                    throw new Exception(Strings.FinishedRestoreSetup.SetupFileMissingError);

                NormalizeApplicationSettings();

                Program.Scheduler.Reschedule();
            }
        }
Exemplo n.º 7
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.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;
                Program.LogHandler.RemoveOperationFile();
            }
        }
Exemplo n.º 8
0
        public static bool DownloadAndUnpackUpdate(UpdateInfo version, Action <double> progress = null)
        {
            if (INSTALLDIR == null)
            {
                return(false);
            }


            var updates = version.RemoteURLS.ToList();

            // If alternate update URLs are specified,
            // we look for packages there as well
            if (AutoUpdateSettings.UsesAlternateURLs)
            {
                var packagepath = new Library.Utility.Uri(updates[0]).Path;
                var packagename = packagepath.Split('/').Last();

                foreach (var alt_url in AutoUpdateSettings.URLs.Reverse())
                {
                    var alt_uri         = new Library.Utility.Uri(alt_url);
                    var path_components = alt_uri.Path.Split('/');
                    var path            = string.Join("/", path_components.Take(path_components.Count() - 1).Union(new string[] { packagename }));

                    var new_path = alt_uri.SetPath(path);
                    updates.Insert(0, new_path.ToString());
                }
            }

            using (var tempfile = new Library.Utility.TempFile())
            {
                foreach (var url in updates)
                {
                    try
                    {
                        Action <long> cb = null;
                        if (progress != null)
                        {
                            cb = (s) => { progress(Math.Min(1.0, Math.Max(0.0, (double)s / version.CompressedSize))); }
                        }
                        ;

                        var wreq = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
                        wreq.UserAgent = string.Format("{0} v{1}", APPNAME, SelfVersion.Version);
                        wreq.Headers.Add("X-Install-ID", InstallID);

                        using (var resp = wreq.GetResponse())
                            using (var rss = resp.GetResponseStream())
                                using (var pgs = new Duplicati.Library.Utility.ProgressReportingStream(rss, version.CompressedSize, cb))
                                    using (var fs = System.IO.File.Open(tempfile, System.IO.FileMode.Create))
                                        Duplicati.Library.Utility.Utility.CopyStream(pgs, fs);

                        var sha256 = System.Security.Cryptography.SHA256.Create();
                        var md5    = System.Security.Cryptography.MD5.Create();

                        using (var s = System.IO.File.OpenRead(tempfile))
                        {
                            if (s.Length != version.CompressedSize)
                            {
                                throw new Exception(string.Format("Invalid file size {0}, expected {1} for {2}", s.Length, version.CompressedSize, url));
                            }

                            var sha256hash = Convert.ToBase64String(sha256.ComputeHash(s));
                            if (sha256hash != version.SHA256)
                            {
                                throw new Exception(string.Format("Damaged or corrupted file, sha256 mismatch for {0}", url));
                            }
                        }

                        using (var s = System.IO.File.OpenRead(tempfile))
                        {
                            var md5hash = Convert.ToBase64String(md5.ComputeHash(s));
                            if (md5hash != version.MD5)
                            {
                                throw new Exception(string.Format("Damaged or corrupted file, md5 mismatch for {0}", url));
                            }
                        }

                        using (var tempfolder = new Duplicati.Library.Utility.TempFolder())
                            using (var zip = new Duplicati.Library.Compression.FileArchiveZip(tempfile, new Dictionary <string, string>()))
                            {
                                foreach (var file in zip.ListFilesWithSize(""))
                                {
                                    if (System.IO.Path.IsPathRooted(file.Key) || file.Key.Trim().StartsWith("..", StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        throw new Exception(string.Format("Out-of-place file path detected: {0}", file.Key));
                                    }

                                    var targetpath   = System.IO.Path.Combine(tempfolder, file.Key);
                                    var targetfolder = System.IO.Path.GetDirectoryName(targetpath);
                                    if (!System.IO.Directory.Exists(targetfolder))
                                    {
                                        System.IO.Directory.CreateDirectory(targetfolder);
                                    }

                                    using (var zs = zip.OpenRead(file.Key))
                                        using (var fs = System.IO.File.Create(targetpath))
                                            zs.CopyTo(fs);
                                }

                                if (VerifyUnpackedFolder(tempfolder, version))
                                {
                                    var versionstring = TryParseVersion(version.Version).ToString();
                                    var targetfolder  = System.IO.Path.Combine(INSTALLDIR, versionstring);
                                    if (System.IO.Directory.Exists(targetfolder))
                                    {
                                        System.IO.Directory.Delete(targetfolder, true);
                                    }

                                    System.IO.Directory.CreateDirectory(targetfolder);

                                    var tempfolderpath   = Duplicati.Library.Utility.Utility.AppendDirSeparator(tempfolder);
                                    var tempfolderlength = tempfolderpath.Length;

                                    // Would be nice, but does not work :(
                                    //System.IO.Directory.Move(tempfolder, targetfolder);

                                    foreach (var e in Duplicati.Library.Utility.Utility.EnumerateFileSystemEntries(tempfolder))
                                    {
                                        var relpath = e.Substring(tempfolderlength);
                                        if (string.IsNullOrWhiteSpace(relpath))
                                        {
                                            continue;
                                        }

                                        var fullpath = System.IO.Path.Combine(targetfolder, relpath);
                                        if (relpath.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()))
                                        {
                                            System.IO.Directory.CreateDirectory(fullpath);
                                        }
                                        else
                                        {
                                            System.IO.File.Copy(e, fullpath);
                                        }
                                    }

                                    // Verification will kick in when we list the installed updates
                                    //VerifyUnpackedFolder(targetfolder, version);
                                    System.IO.File.WriteAllText(System.IO.Path.Combine(INSTALLDIR, CURRENT_FILE), versionstring);

                                    m_hasUpdateInstalled = null;

                                    var obsolete = (from n in FindInstalledVersions()
                                                    where n.Value.Version != version.Version && n.Value.Version != SelfVersion.Version
                                                    let x = TryParseVersion(n.Value.Version)
                                                            orderby x descending
                                                            select n).Skip(1).ToArray();

                                    foreach (var f in obsolete)
                                    {
                                        try { System.IO.Directory.Delete(f.Key, true); }
                                        catch { }
                                    }

                                    return(true);
                                }
                                else
                                {
                                    throw new Exception(string.Format("Unable to verify unpacked folder for url: {0}", url));
                                }
                            }
                    }
                    catch (Exception ex)
                    {
                        if (OnError != null)
                        {
                            OnError(ex);
                        }
                    }
                }
            }

            return(false);
        }
Exemplo n.º 9
0
        static bool Run(List <string> args, Dictionary <string, string> options, bool first)
        {
            string allowedChars = ValidFilenameChars;

            if (options.ContainsKey("extended-chars"))
            {
                allowedChars += options["extended-chars"];
            }
            else
            {
                allowedChars += ExtendedChars;
            }

            bool autoCreateFolders = Library.Utility.Utility.ParseBoolOption(options, "auto-create-folder");

            Library.Interface.IBackend backend = Library.DynamicLoader.BackendLoader.GetBackend(args[0], options);
            if (backend == null)
            {
                Console.WriteLine("Unsupported backend");
                Console.WriteLine();
                Console.WriteLine("Supported backends: " + string.Join(",", Duplicati.Library.DynamicLoader.BackendLoader.Keys));
                return(false);
            }

            string disabledModulesValue;
            string enabledModulesValue;

            options.TryGetValue("enable-module", out enabledModulesValue);
            options.TryGetValue("disable-module", out disabledModulesValue);
            string[] enabledModules  = enabledModulesValue == null ? new string[0] : enabledModulesValue.Trim().ToLower().Split(',');
            string[] disabledModules = disabledModulesValue == null ? new string[0] : disabledModulesValue.Trim().ToLower().Split(',');

            List <Library.Interface.IGenericModule> loadedModules = new List <IGenericModule>();

            foreach (Library.Interface.IGenericModule m in Library.DynamicLoader.GenericLoader.Modules)
            {
                if (Array.IndexOf <string>(disabledModules, m.Key.ToLower()) < 0 && (m.LoadAsDefault || Array.IndexOf <string>(enabledModules, m.Key.ToLower()) >= 0))
                {
                    m.Configure(options);
                    loadedModules.Add(m);
                }
            }

            try
            {
                List <Library.Interface.IFileEntry> curlist = null;
                try
                {
                    curlist = backend.List();
                }
                catch (FolderMissingException fex)
                {
                    if (autoCreateFolders)
                    {
                        try
                        {
                            backend.CreateFolder();
                            curlist = backend.List();
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Autocreate folder failed with message: " + ex.Message);
                        }
                    }

                    if (curlist == null)
                    {
                        throw fex;
                    }
                }

                foreach (Library.Interface.IFileEntry fe in curlist)
                {
                    if (!fe.IsFolder)
                    {
                        if (Library.Utility.Utility.ParseBoolOption(options, "auto-clean") && first)
                        {
                            if (Library.Utility.Utility.ParseBoolOption(options, "force"))
                            {
                                Console.WriteLine("Auto clean, removing file: {0}", fe.Name);
                                backend.Delete(fe.Name);
                                continue;
                            }
                            else
                            {
                                Console.WriteLine("Specify the --force flag to actually delete files");
                            }
                        }

                        Console.WriteLine("*** Remote folder is not empty, aborting");
                        return(false);
                    }
                }


                int  number_of_files   = 10;
                int  min_file_size     = 1024;
                int  max_file_size     = 1024 * 1024 * 50;
                int  min_filename_size = 5;
                int  max_filename_size = 80;
                bool disableStreaming  = Library.Utility.Utility.ParseBoolOption(options, "disable-streaming-transfers");
                bool skipOverwriteTest = Library.Utility.Utility.ParseBoolOption(options, "skip-overwrite-test");

                if (options.ContainsKey("number-of-files"))
                {
                    number_of_files = int.Parse(options["number-of-files"]);
                }
                if (options.ContainsKey("min-file-size"))
                {
                    min_file_size = (int)Duplicati.Library.Utility.Sizeparser.ParseSize(options["min-file-size"], "mb");
                }
                if (options.ContainsKey("max-file-size"))
                {
                    max_file_size = (int)Duplicati.Library.Utility.Sizeparser.ParseSize(options["max-file-size"], "mb");
                }

                if (options.ContainsKey("min-filename-length"))
                {
                    min_filename_size = int.Parse(options["min-filename-length"]);
                }
                if (options.ContainsKey("max-filename-length"))
                {
                    max_filename_size = int.Parse(options["max-filename-length"]);
                }

                Random rnd = new Random();
                System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create();

                //Create random files
                using (Library.Utility.TempFolder tf = new Duplicati.Library.Utility.TempFolder())
                {
                    List <TempFile> files = new List <TempFile>();
                    for (int i = 0; i < number_of_files; i++)
                    {
                        StringBuilder filename    = new StringBuilder();
                        int           filenamelen = rnd.Next(min_filename_size, max_filename_size);
                        for (int j = 0; j < filenamelen; j++)
                        {
                            filename.Append(allowedChars[rnd.Next(0, allowedChars.Length)]);
                        }

                        string localfilename = CreateRandomFile(tf, i, min_file_size, max_file_size, rnd);

                        //Calculate local hash and length
                        using (System.IO.FileStream fs = new System.IO.FileStream(localfilename, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                            files.Add(new TempFile(filename.ToString(), localfilename, sha.ComputeHash(fs), fs.Length));
                    }

                    byte[] dummyFileHash = null;
                    if (!skipOverwriteTest)
                    {
                        Console.WriteLine("Uploading wrong files ...");
                        using (Library.Utility.TempFile dummy = Library.Utility.TempFile.WrapExistingFile(CreateRandomFile(tf, files.Count, 1024, 2048, rnd)))
                        {
                            using (System.IO.FileStream fs = new System.IO.FileStream(dummy, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                                dummyFileHash = sha.ComputeHash(fs);

                            //Upload a dummy file for entry 0 and the last one, they will be replaced by the real files afterwards
                            //We upload entry 0 twice just to try to freak any internal cache list
                            Uploadfile(dummy, 0, files[0].remotefilename, backend, disableStreaming);
                            Uploadfile(dummy, 0, files[0].remotefilename, backend, disableStreaming);
                            Uploadfile(dummy, files.Count - 1, files[files.Count - 1].remotefilename, backend, disableStreaming);
                        }
                    }

                    Console.WriteLine("Uploading files ...");

                    for (int i = 0; i < files.Count; i++)
                    {
                        Uploadfile(files[i].localfilename, i, files[i].remotefilename, backend, disableStreaming);
                    }

                    Console.WriteLine("Verifying file list ...");

                    curlist = backend.List();
                    foreach (Library.Interface.IFileEntry fe in curlist)
                    {
                        if (!fe.IsFolder)
                        {
                            bool found = false;
                            foreach (TempFile tx in files)
                            {
                                if (tx.remotefilename == fe.Name)
                                {
                                    if (tx.found)
                                    {
                                        Console.WriteLine("*** File with name {0} was found more than once", tx.remotefilename);
                                    }
                                    found    = true;
                                    tx.found = true;

                                    if (fe.Size > 0 && tx.length != fe.Size)
                                    {
                                        Console.WriteLine("*** File with name {0} has size {1} but the size was reported as {2}", tx.remotefilename, tx.length, fe.Size);
                                    }

                                    break;
                                }
                            }

                            if (!found)
                            {
                                Console.WriteLine("*** File with name {0} was found on server but not uploaded!", fe.Name);
                            }
                        }
                    }

                    foreach (TempFile tx in files)
                    {
                        if (!tx.found)
                        {
                            Console.WriteLine("*** File with name {0} was uploaded but not found afterwards", tx.remotefilename);
                        }
                    }

                    Console.WriteLine("Downloading files");

                    for (int i = 0; i < files.Count; i++)
                    {
                        using (Duplicati.Library.Utility.TempFile cf = new Duplicati.Library.Utility.TempFile())
                        {
                            Exception e = null;
                            Console.Write("Downloading file {0} ... ", i);

                            try
                            {
                                if (backend is Library.Interface.IStreamingBackend && !disableStreaming)
                                {
                                    using (System.IO.FileStream fs = new System.IO.FileStream(cf, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
                                        using (NonSeekableStream nss = new NonSeekableStream(fs))
                                            (backend as Library.Interface.IStreamingBackend).Get(files[i].remotefilename, nss);
                                }
                                else
                                {
                                    backend.Get(files[i].remotefilename, cf);
                                }

                                e = null;
                            }
                            catch (Exception ex)
                            {
                                e = ex;
                            }

                            if (e != null)
                            {
                                Console.WriteLine("failed\n*** Error: {0}", e.ToString());
                            }
                            else
                            {
                                Console.WriteLine("done");
                            }

                            Console.Write("Checking hash ... ");

                            using (System.IO.FileStream fs = new System.IO.FileStream(cf, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                                if (Convert.ToBase64String(sha.ComputeHash(fs)) != Convert.ToBase64String(files[i].hash))
                                {
                                    if (dummyFileHash != null && Convert.ToBase64String(sha.ComputeHash(fs)) == Convert.ToBase64String(dummyFileHash))
                                    {
                                        Console.WriteLine("failed\n*** Downloaded file was the dummy file");
                                    }
                                    else
                                    {
                                        Console.WriteLine("failed\n*** Downloaded file was corrupt");
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("done");
                                }
                        }
                    }

                    Console.WriteLine("Deleting files...");

                    foreach (TempFile tx in files)
                    {
                        try { backend.Delete(tx.remotefilename); }
                        catch (Exception ex)
                        {
                            Console.WriteLine("*** Failed to delete file {0}, message: {1}", tx.remotefilename, ex.ToString());
                        }
                    }

                    curlist = backend.List();
                    foreach (Library.Interface.IFileEntry fe in curlist)
                    {
                        if (!fe.IsFolder)
                        {
                            Console.WriteLine("*** Remote folder contains {0} after cleanup", fe.Name);
                        }
                    }
                }
            }
            finally
            {
                foreach (Library.Interface.IGenericModule m in loadedModules)
                {
                    if (m is IDisposable)
                    {
                        ((IDisposable)m).Dispose();
                    }
                }
            }

            return(true);
        }
Exemplo n.º 10
0
        static bool Run(List <string> args, Dictionary <string, string> options, bool first)
        {
            Library.Interface.IBackend backend = Library.DynamicLoader.BackendLoader.GetBackend(args[0], options);
            if (backend == null)
            {
                Console.WriteLine("Unsupported backend");
                Console.WriteLine();
                Console.WriteLine("Supported backends: " + string.Join(",", Duplicati.Library.DynamicLoader.BackendLoader.Keys));
                return(false);
            }

            string allowedChars = ValidFilenameChars;

            if (options.ContainsKey("extended-chars"))
            {
                allowedChars += String.IsNullOrEmpty(options["extended-chars"]) ? ExtendedChars : options["extended-chars"];
            }

            bool autoCreateFolders = Library.Utility.Utility.ParseBoolOption(options, "auto-create-folder");

            string disabledModulesValue;
            string enabledModulesValue;

            options.TryGetValue("enable-module", out enabledModulesValue);
            options.TryGetValue("disable-module", out disabledModulesValue);
            string[] enabledModules  = enabledModulesValue == null ? new string[0] : enabledModulesValue.Trim().ToLower().Split(',');
            string[] disabledModules = disabledModulesValue == null ? new string[0] : disabledModulesValue.Trim().ToLower().Split(',');

            List <Library.Interface.IGenericModule> loadedModules = new List <IGenericModule>();

            foreach (Library.Interface.IGenericModule m in Library.DynamicLoader.GenericLoader.Modules)
            {
                if (!disabledModules.Contains(m.Key, StringComparer.OrdinalIgnoreCase) && (m.LoadAsDefault || enabledModules.Contains(m.Key, StringComparer.OrdinalIgnoreCase)))
                {
                    m.Configure(options);
                    loadedModules.Add(m);
                }
            }

            try
            {
                IEnumerable <Library.Interface.IFileEntry> curlist = null;
                try
                {
                    backend.Test();
                    curlist = backend.List();
                }
                catch (FolderMissingException fex)
                {
                    if (autoCreateFolders)
                    {
                        try
                        {
                            backend.CreateFolder();
                            curlist = backend.List();
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Autocreate folder failed with message: " + ex.Message);
                        }
                    }

                    if (curlist == null)
                    {
                        throw fex;
                    }
                }

                foreach (Library.Interface.IFileEntry fe in curlist)
                {
                    if (!fe.IsFolder)
                    {
                        if (Library.Utility.Utility.ParseBoolOption(options, "auto-clean") && first)
                        {
                            if (Library.Utility.Utility.ParseBoolOption(options, "force"))
                            {
                                Console.WriteLine("Auto clean, removing file: {0}", fe.Name);
                                backend.Delete(fe.Name);
                                continue;
                            }
                            else
                            {
                                Console.WriteLine("Specify the --force flag to actually delete files");
                            }
                        }

                        Console.WriteLine("*** Remote folder is not empty, aborting");
                        return(false);
                    }
                }


                int  number_of_files    = 10;
                int  min_file_size      = 1024;
                int  max_file_size      = 1024 * 1024 * 50;
                int  min_filename_size  = 5;
                int  max_filename_size  = 80;
                bool disableStreaming   = Library.Utility.Utility.ParseBoolOption(options, "disable-streaming-transfers");
                bool skipOverwriteTest  = Library.Utility.Utility.ParseBoolOption(options, "skip-overwrite-test");
                bool trimFilenameSpaces = Library.Utility.Utility.ParseBoolOption(options, "trim-filename-spaces");

                if (options.ContainsKey("number-of-files"))
                {
                    number_of_files = int.Parse(options["number-of-files"]);
                }
                if (options.ContainsKey("min-file-size"))
                {
                    min_file_size = (int)Duplicati.Library.Utility.Sizeparser.ParseSize(options["min-file-size"], "mb");
                }
                if (options.ContainsKey("max-file-size"))
                {
                    max_file_size = (int)Duplicati.Library.Utility.Sizeparser.ParseSize(options["max-file-size"], "mb");
                }

                if (options.ContainsKey("min-filename-length"))
                {
                    min_filename_size = int.Parse(options["min-filename-length"]);
                }
                if (options.ContainsKey("max-filename-length"))
                {
                    max_filename_size = int.Parse(options["max-filename-length"]);
                }

                Random rnd = new Random();
                System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create();

                //Create random files
                using (Library.Utility.TempFolder tf = new Duplicati.Library.Utility.TempFolder())
                {
                    List <TempFile> files = new List <TempFile>();
                    for (int i = 0; i < number_of_files; i++)
                    {
                        string filename = CreateRandomRemoteFileName(min_filename_size, max_filename_size, allowedChars, trimFilenameSpaces, rnd);

                        string localfilename = CreateRandomFile(tf, i, min_file_size, max_file_size, rnd);

                        //Calculate local hash and length
                        using (System.IO.FileStream fs = new System.IO.FileStream(localfilename, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                            files.Add(new TempFile(filename, localfilename, sha.ComputeHash(fs), fs.Length));
                    }

                    byte[] dummyFileHash = null;
                    if (!skipOverwriteTest)
                    {
                        Console.WriteLine("Uploading wrong files ...");
                        using (Library.Utility.TempFile dummy = Library.Utility.TempFile.WrapExistingFile(CreateRandomFile(tf, files.Count, 1024, 2048, rnd)))
                        {
                            using (System.IO.FileStream fs = new System.IO.FileStream(dummy, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                                dummyFileHash = sha.ComputeHash(fs);

                            //Upload a dummy file for entry 0 and the last one, they will be replaced by the real files afterwards
                            //We upload entry 0 twice just to try to freak any internal cache list
                            Uploadfile(dummy, 0, files[0].remotefilename, backend, disableStreaming);
                            Uploadfile(dummy, 0, files[0].remotefilename, backend, disableStreaming);
                            Uploadfile(dummy, files.Count - 1, files[files.Count - 1].remotefilename, backend, disableStreaming);
                        }
                    }

                    Console.WriteLine("Uploading files ...");

                    for (int i = 0; i < files.Count; i++)
                    {
                        Uploadfile(files[i].localfilename, i, files[i].remotefilename, backend, disableStreaming);
                    }

                    TempFile originalRenamedFile = null;
                    string   renamedFileNewName  = null;
                    IRenameEnabledBackend renameEnabledBackend = backend as IRenameEnabledBackend;
                    if (renameEnabledBackend != null)
                    {
                        // Rename the second file in the list, if there are more than one. If not, just do the first one.
                        int renameIndex = files.Count > 1 ? 1 : 0;
                        originalRenamedFile = files[renameIndex];

                        renamedFileNewName = CreateRandomRemoteFileName(min_filename_size, max_filename_size, allowedChars, trimFilenameSpaces, rnd);

                        Console.WriteLine("Renaming file {0} from {1} to {2}", renameIndex, originalRenamedFile.remotefilename, renamedFileNewName);

                        renameEnabledBackend.Rename(originalRenamedFile.remotefilename, renamedFileNewName);
                        files[renameIndex] = new TempFile(renamedFileNewName, originalRenamedFile.localfilename, originalRenamedFile.hash, originalRenamedFile.length);
                    }

                    Console.WriteLine("Verifying file list ...");

                    curlist = backend.List();
                    foreach (Library.Interface.IFileEntry fe in curlist)
                    {
                        if (!fe.IsFolder)
                        {
                            bool found = false;
                            foreach (TempFile tx in files)
                            {
                                if (tx.remotefilename == fe.Name)
                                {
                                    if (tx.found)
                                    {
                                        Console.WriteLine("*** File with name {0} was found more than once", tx.remotefilename);
                                    }
                                    found    = true;
                                    tx.found = true;

                                    if (fe.Size > 0 && tx.length != fe.Size)
                                    {
                                        Console.WriteLine("*** File with name {0} has size {1} but the size was reported as {2}", tx.remotefilename, tx.length, fe.Size);
                                    }

                                    break;
                                }
                            }

                            if (!found)
                            {
                                if (originalRenamedFile != null && renamedFileNewName != null && originalRenamedFile.remotefilename == fe.Name)
                                {
                                    Console.WriteLine("*** File with name {0} was found on server but was supposed to have been renamed to {1}!", fe.Name, renamedFileNewName);
                                }
                                else
                                {
                                    Console.WriteLine("*** File with name {0} was found on server but not uploaded!", fe.Name);
                                }
                            }
                        }
                    }

                    foreach (TempFile tx in files)
                    {
                        if (!tx.found)
                        {
                            Console.WriteLine("*** File with name {0} was uploaded but not found afterwards", tx.remotefilename);
                        }
                    }

                    Console.WriteLine("Downloading files");

                    for (int i = 0; i < files.Count; i++)
                    {
                        using (Duplicati.Library.Utility.TempFile cf = new Duplicati.Library.Utility.TempFile())
                        {
                            Exception e = null;
                            Console.Write("Downloading file {0} ... ", i);

                            try
                            {
                                if (backend is Library.Interface.IStreamingBackend && !disableStreaming)
                                {
                                    using (System.IO.FileStream fs = new System.IO.FileStream(cf, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
                                        using (NonSeekableStream nss = new NonSeekableStream(fs))
                                            (backend as Library.Interface.IStreamingBackend).Get(files[i].remotefilename, nss);
                                }
                                else
                                {
                                    backend.Get(files[i].remotefilename, cf);
                                }

                                e = null;
                            }
                            catch (Exception ex)
                            {
                                e = ex;
                            }

                            if (e != null)
                            {
                                Console.WriteLine("failed\n*** Error: {0}", e);
                            }
                            else
                            {
                                Console.WriteLine("done");
                            }

                            Console.Write("Checking hash ... ");

                            using (System.IO.FileStream fs = new System.IO.FileStream(cf, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                                if (Convert.ToBase64String(sha.ComputeHash(fs)) != Convert.ToBase64String(files[i].hash))
                                {
                                    if (dummyFileHash != null && Convert.ToBase64String(sha.ComputeHash(fs)) == Convert.ToBase64String(dummyFileHash))
                                    {
                                        Console.WriteLine("failed\n*** Downloaded file was the dummy file");
                                    }
                                    else
                                    {
                                        Console.WriteLine("failed\n*** Downloaded file was corrupt");
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("done");
                                }
                        }
                    }

                    Console.WriteLine("Deleting files...");

                    foreach (TempFile tx in files)
                    {
                        try { backend.Delete(tx.remotefilename); }
                        catch (Exception ex)
                        {
                            Console.WriteLine("*** Failed to delete file {0}, message: {1}", tx.remotefilename, ex);
                        }
                    }

                    curlist = backend.List();
                    foreach (Library.Interface.IFileEntry fe in curlist)
                    {
                        if (!fe.IsFolder)
                        {
                            Console.WriteLine("*** Remote folder contains {0} after cleanup", fe.Name);
                        }
                    }
                }

                // Test quota retrieval
                IQuotaEnabledBackend quotaEnabledBackend = backend as IQuotaEnabledBackend;
                if (quotaEnabledBackend != null)
                {
                    Console.WriteLine("Checking quota...");
                    IQuotaInfo quota = null;
                    bool       noException;
                    try
                    {
                        quota       = quotaEnabledBackend.Quota;
                        noException = true;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("*** Checking quota information failed: {0}", ex);
                        noException = false;
                    }

                    if (noException)
                    {
                        if (quota != null)
                        {
                            Console.WriteLine("Free Space:  {0}", Library.Utility.Utility.FormatSizeString(quota.FreeQuotaSpace));
                            Console.WriteLine("Total Space: {0}", Library.Utility.Utility.FormatSizeString(quota.TotalQuotaSpace));
                        }
                        else
                        {
                            Console.WriteLine("Unable to retrieve quota information");
                        }
                    }
                }

                // Test DNSName lookup
                Console.WriteLine("Checking DNS names used by this backend...");
                try
                {
                    string[] dnsNames = backend.DNSName;
                    if (dnsNames != null)
                    {
                        foreach (string dnsName in dnsNames)
                        {
                            Console.WriteLine(dnsName);
                        }
                    }
                    else
                    {
                        Console.WriteLine("No DNS names reported");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("*** Checking DNSName failed: {0}", ex);
                }
            }
            finally
            {
                foreach (Library.Interface.IGenericModule m in loadedModules)
                {
                    if (m is IDisposable)
                    {
                        ((IDisposable)m).Dispose();
                    }
                }
            }

            return(true);
        }
Exemplo n.º 11
0
        public void ExecuteTask(IDuplicityTask task)
        {
            Dictionary <string, string> options = new Dictionary <string, string>();

            //Set the log level to be that of the GUI
            options["log-level"] = Duplicati.Library.Logging.Log.LogLevel.ToString();

            string destination = task.GetConfiguration(options);

            string results       = "";
            string parsedMessage = "";

            m_isAborted = false;

            try
            {
                //TODO: Its a bit dirty to set the options after creating the instance
                using (Interface i = new Interface(destination, options))
                {
                    lock (m_lock)
                    {
                        m_stopReason = System.Windows.Forms.CloseReason.None;
                        m_currentBackupControlInterface = i;
                    }

                    SetupControlInterface();

                    i.OperationProgress += new OperationProgressEvent(Duplicati_OperationProgress);

                    switch (task.TaskType)
                    {
                    case DuplicityTaskType.FullBackup:
                    case DuplicityTaskType.IncrementalBackup:
                    {
                        //Activate auto-cleanup
                        options["auto-cleanup"] = "";
                        options["force"]        = "";
                        if (task.Schedule.Task.KeepFull > 0)
                        {
                            m_extraOperations++;
                        }
                        if (!string.IsNullOrEmpty(task.Schedule.Task.KeepTime))
                        {
                            m_extraOperations++;
                        }

                        Library.Utility.TempFolder tf = null;
                        try
                        {
                            if (ProgressEvent != null)
                            {
                                ProgressEvent(DuplicatiOperation.Backup, RunnerState.Started, task.Schedule.Name, "", 0, -1);
                            }

                            if (task.Task.IncludeSetup)
                            {
                                //Make a copy of the current database
                                tf = new Duplicati.Library.Utility.TempFolder();
                                string filename = System.IO.Path.Combine(tf, System.IO.Path.GetFileName(Program.DatabasePath));

                                System.IO.File.Copy(Program.DatabasePath, filename, true);
                                using (System.Data.IDbConnection con = (System.Data.IDbConnection)Activator.CreateInstance(SQLiteLoader.SQLiteConnectionType))
                                {
                                    con.ConnectionString = "Data Source=" + filename;

                                    //Open the database, handle any encryption issues automatically
                                    Program.OpenDatabase(con);

                                    using (System.Data.IDbCommand cmd = con.CreateCommand())
                                    {
                                        //Remove all log data to minimize the size of the database
                                        cmd.CommandText = "DELETE FROM CommandQueue;";
                                        cmd.ExecuteNonQuery();
                                        cmd.CommandText = "DELETE FROM Log;";
                                        cmd.ExecuteNonQuery();
                                        cmd.CommandText = "DELETE FROM LogBlob;";
                                        cmd.ExecuteNonQuery();

                                        //Free up unused space
                                        cmd.CommandText = "VACUUM;";
                                        cmd.ExecuteNonQuery();
                                    }
                                }

                                options["signature-control-files"] = filename;
                            }

                            options["full-if-sourcefolder-changed"] = "";

                            List <KeyValuePair <bool, string> > filters = new List <KeyValuePair <bool, string> >();
                            string[] sourceFolders = DynamicSetupHelper.GetSourceFolders(task.Task, new ApplicationSettings(task.Task.DataParent), filters);

                            if (options.ContainsKey("filter"))
                            {
                                filters.AddRange(Library.Utility.FilenameFilter.DecodeFilter(options["filter"]));
                            }

                            options["filter"] = Library.Utility.FilenameFilter.EncodeAsFilter(filters);

                            //At this point we register the backup as being in progress
                            ((FullOrIncrementalTask)task).WriteBackupInProgress(Strings.DuplicatiRunner.ShutdownWhileBackupInprogress);

                            results = i.Backup(sourceFolders);
                        }
                        finally
                        {
                            if (tf != null)
                            {
                                tf.Dispose();
                            }

                            if (ProgressEvent != null)
                            {
                                ProgressEvent(DuplicatiOperation.Backup, RunnerState.Stopped, task.Schedule.Name, "", 100, -1);
                            }
                        }
                        break;
                    }

                    case DuplicityTaskType.ListBackups:

                        List <string> res = new List <string>();
                        foreach (ManifestEntry be in i.GetBackupSets())
                        {
                            res.Add(be.Time.ToString());
                            foreach (ManifestEntry bei in be.Incrementals)
                            {
                                res.Add(bei.Time.ToString());
                            }
                        }

                        (task as ListBackupsTask).Backups = res.ToArray();
                        break;

                    case DuplicityTaskType.ListBackupEntries:
                        (task as ListBackupEntriesTask).Backups = i.GetBackupSets();
                        break;

                    case DuplicityTaskType.ListFiles:
                        (task as ListFilesTask).Files = i.ListCurrentFiles();
                        break;

                    case DuplicityTaskType.ListSourceFolders:
                        (task as ListSourceFoldersTask).Files = new List <string>(i.ListSourceFolders() ?? new string[0]);
                        break;

                    case DuplicityTaskType.ListActualFiles:
                        (task as ListActualFilesTask).Files = i.ListActualSignatureFiles();
                        break;

                    case DuplicityTaskType.RemoveAllButNFull:
                        results = i.DeleteAllButNFull();
                        break;

                    case DuplicityTaskType.RemoveOlderThan:
                        results = i.DeleteOlderThan();
                        break;

                    case DuplicityTaskType.Restore:
                        options["file-to-restore"] = ((RestoreTask)task).SourceFiles;
                        if (options.ContainsKey("filter"))
                        {
                            options.Remove("filter");
                        }

                        try
                        {
                            if (ProgressEvent != null)
                            {
                                ProgressEvent(DuplicatiOperation.Restore, RunnerState.Started, task.Schedule.Name, "", 0, -1);
                            }
                            results = i.Restore(task.LocalPath.Split(System.IO.Path.PathSeparator));
                        }
                        finally
                        {
                            if (ProgressEvent != null)
                            {
                                ProgressEvent(DuplicatiOperation.Restore, RunnerState.Stopped, task.Schedule.Name, "", 100, -1);
                            }
                        }
                        break;

                    case DuplicityTaskType.RestoreSetup:
                        i.RestoreControlFiles(task.LocalPath);
                        break;

                    default:
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                while (ex is System.Reflection.TargetInvocationException && ex.InnerException != null)
                {
                    ex = ex.InnerException;
                }

                if (ex is System.Threading.ThreadAbortException)
                {
                    m_isAborted = true;
                    System.Threading.Thread.ResetAbort();
                }
                else if (ex is Library.Main.LiveControl.ExecutionStoppedException)
                {
                    m_isAborted = true;
                }

                if (m_isAborted && m_stopReason != System.Windows.Forms.CloseReason.None)
                {
                    //If the user has stopped the backup for some reason, write a nicer message
                    switch (m_stopReason)
                    {
                    case System.Windows.Forms.CloseReason.ApplicationExitCall:
                        parsedMessage = Strings.DuplicatiRunner.ApplicationExitLogMesssage;
                        break;

                    case System.Windows.Forms.CloseReason.TaskManagerClosing:
                        parsedMessage = Strings.DuplicatiRunner.TaskManagerCloseMessage;
                        break;

                    case System.Windows.Forms.CloseReason.UserClosing:
                        parsedMessage = Strings.DuplicatiRunner.UserClosingMessage;
                        break;

                    case System.Windows.Forms.CloseReason.WindowsShutDown:
                        parsedMessage = Strings.DuplicatiRunner.WindowsShutdownMessage;
                        break;

                    default:
                        parsedMessage = string.Format(Strings.DuplicatiRunner.OtherAbortMessage, m_stopReason);
                        break;
                    }

                    if (task.Schedule != null)
                    {
                        //If the application is going down, the backup should resume on next launch
                        switch (m_stopReason)
                        {
                        case System.Windows.Forms.CloseReason.ApplicationExitCall:
                        case System.Windows.Forms.CloseReason.TaskManagerClosing:
                        case System.Windows.Forms.CloseReason.WindowsShutDown:
                            task.Schedule.ScheduledRunFailed();
                            break;
                        }
                    }
                }
                else
                {
                    parsedMessage = string.Format(Strings.DuplicatiRunner.ErrorMessage, ex.Message);
                }

                results = "Error: " + ex.ToString(); //Don't localize

                while (ex.InnerException != null)
                {
                    ex       = ex.InnerException;
                    results += Environment.NewLine + "InnerError: " + ex.ToString(); //Don't localize
                }
            }
            finally
            {
                lock (m_lock)
                    m_currentBackupControlInterface = null;
            }

            try
            {
                if (!m_isAborted && (task.TaskType == DuplicityTaskType.FullBackup || task.TaskType == DuplicityTaskType.IncrementalBackup))
                {
                    if (task.Schedule.Task.KeepFull > 0)
                    {
                        m_lastPGProgress    = 100;
                        m_lastPGmessage     = Strings.DuplicatiRunner.CleaningUpMessage;
                        m_lastPGSubmessage  = "";
                        m_lastPGSubprogress = -1;

                        ReinvokeLastProgressEvent();
                        m_extraOperations--;

                        RemoveAllButNFullTask tmpTask = new RemoveAllButNFullTask(task.Schedule, (int)task.Schedule.Task.KeepFull);
                        ExecuteTask(tmpTask);
                        results += Environment.NewLine + Strings.DuplicatiRunner.CleanupLogdataHeader + Environment.NewLine + tmpTask.Result;
                    }

                    if (!string.IsNullOrEmpty(task.Schedule.Task.KeepTime))
                    {
                        m_lastPGProgress    = 100;
                        m_lastPGmessage     = Strings.DuplicatiRunner.CleaningUpMessage;
                        m_lastPGSubmessage  = "";
                        m_lastPGSubprogress = -1;

                        ReinvokeLastProgressEvent();
                        m_extraOperations--;

                        RemoveOlderThanTask tmpTask = new RemoveOlderThanTask(task.Schedule, task.Schedule.Task.KeepTime);
                        ExecuteTask(tmpTask);
                        results += Environment.NewLine + Strings.DuplicatiRunner.CleanupLogdataHeader + Environment.NewLine + tmpTask.Result;
                    }

                    if (task.Schedule.Task.KeepFull > 0 || !string.IsNullOrEmpty(task.Schedule.Task.KeepTime))
                    {
                        ReinvokeLastProgressEvent();
                    }

                    if (ProgressEvent != null)
                    {
                        ProgressEvent(DuplicatiOperation.Backup, RunnerState.Stopped, task.Schedule.Name, "", 100, -1);
                    }
                }
            }
            catch (Exception ex)
            {
                results += Environment.NewLine + string.Format(Strings.DuplicatiRunner.CleanupError, ex.Message);
            }

            task.IsAborted = m_isAborted;
            task.Result    = results;
            task.RaiseTaskCompleted(results, parsedMessage);

            if (ResultEvent != null && task is FullBackupTask || task is IncrementalBackupTask)
            {
                Log[] logs = Program.DataConnection.GetObjects <Log>("TaskID = ? AND SubAction LIKE ? ORDER BY EndTime DESC", task.Task.ID, "Primary");
                if (logs != null && logs.Length > 0)
                {
                    Datamodel.Log l = logs[0];
                    RunnerResult  r = RunnerResult.Error;
                    if (l.ParsedStatus == DuplicatiOutputParser.ErrorStatus)
                    {
                        r = RunnerResult.Error;
                    }
                    else if (l.ParsedStatus == DuplicatiOutputParser.OKStatus || l.ParsedStatus == DuplicatiOutputParser.NoChangedFiles)
                    {
                        r = RunnerResult.OK;
                    }
                    else if (l.ParsedStatus == DuplicatiOutputParser.PartialStatus)
                    {
                        r = RunnerResult.Partial;
                    }
                    else if (l.ParsedStatus == DuplicatiOutputParser.WarningStatus)
                    {
                        r = RunnerResult.Warning;
                    }

                    ResultEvent(r, parsedMessage, results);
                }
            }

            if (task.Schedule != null && !m_isAborted)
            {
                task.Schedule.ScheduledRunCompleted(); //Register as completed if not aborted
            }
        }