Esempio n. 1
0
        public List<KeyValuePair<BackupEntryBase, Exception>> VerifyBackupChain()
        {
            CommunicationStatistics stats = new CommunicationStatistics(XervBackupOperationMode.Verify);
            SetupCommonOptions(stats);

            List<KeyValuePair<BackupEntryBase, Exception>> results = new List<KeyValuePair<BackupEntryBase, Exception>>();

            if (m_options.DontReadManifests)
                throw new InvalidOperationException(Strings.Interface.ManifestsMustBeRead);
            if (m_options.SkipFileHashChecks)
                throw new InvalidOperationException(Strings.Interface.CannotVerifyWithoutHashes);

            if (!string.IsNullOrEmpty(m_options.SignatureCachePath))
            {
                stats.LogWarning(Strings.Interface.DisablingSignatureCacheForVerification, null);
                m_options.SignatureCachePath = null;
            }

            using (BackendWrapper backend = new BackendWrapper(stats, m_backend, m_options))
            {
                //Find the spot in the chain where we start
                ManifestEntry bestFit = backend.GetBackupSet(m_options.RestoreTime);

                //Get the list of manifests to validate
                List<ManifestEntry> entries = new List<ManifestEntry>();
                entries.Add(bestFit);
                entries.AddRange(bestFit.Incrementals);

                entries.Reverse();

                foreach (ManifestEntry me in entries)
                {
                    Manifestfile mf = null;

                    try
                    {
                        mf = GetManifest(backend, me);
                        VerifyBackupChainWithFiles(backend, me);

                        if (mf.SignatureHashes.Count != me.Volumes.Count)
                            results.Add(new KeyValuePair<BackupEntryBase,Exception>(me, new Exception(string.Format(Strings.Interface.ManifestAndFileCountMismatchError, mf.SelfFilename, mf.SignatureHashes.Count, me.Volumes.Count))));
                        else
                            results.Add(new KeyValuePair<BackupEntryBase,Exception>(me, null));
                    }
                    catch (Exception ex)
                    {
                        results.Add(new KeyValuePair<BackupEntryBase,Exception>(me, ex));
                    }

                    if (mf != null)
                    {
                        int volumes = Math.Min(mf.SignatureHashes.Count, me.Volumes.Count);
                        for(int i = 0; i <volumes; i++)
                        {
                            if (m_options.Verificationlevel == VerificationLevel.Signature || m_options.Verificationlevel == VerificationLevel.Full)
                            {
                                try
                                {
                                    using(Utility.TempFile tf = new XervBackup.Library.Utility.TempFile())
                                        backend.Get(me.Volumes[i].Key, mf, tf, mf.SignatureHashes[i]);
                                    results.Add(new KeyValuePair<BackupEntryBase, Exception>(me.Volumes[i].Key, null));
                                }
                                catch (Exception ex) { results.Add(new KeyValuePair<BackupEntryBase,Exception>(me.Volumes[i].Key, ex)); }
                            }

                            if (m_options.Verificationlevel == VerificationLevel.Full)
                            {
                                try
                                {
                                    using(Utility.TempFile tf = new XervBackup.Library.Utility.TempFile())
                                        backend.Get(me.Volumes[i].Value, mf, tf, mf.ContentHashes[i]);
                                    results.Add(new KeyValuePair<BackupEntryBase, Exception>(me.Volumes[i].Value, null));
                                }
                                catch (Exception ex) { results.Add(new KeyValuePair<BackupEntryBase,Exception>(me.Volumes[i].Value, ex)); }

                            }
                        }
                    }

                }

                //Re-generate verification file
                if (m_options.CreateVerificationFile)
                {
                    //Stop any async operations
                    if (m_options.AsynchronousUpload)
                        backend.ExtractPendingUploads();

                    VerificationFile vf = new VerificationFile(entries, new FilenameStrategy(m_options));
                    using (Utility.TempFile tf = new XervBackup.Library.Utility.TempFile())
                    {
                        vf.Save(tf);
                        tf.Protected = true;
                        backend.Put(new VerificationEntry(entries[entries.Count - 1].Time), tf);
                    }
                }

            }

            return results;
        }
Esempio n. 2
0
        public string Restore(string[] target)
        {
            RestoreStatistics rs = new RestoreStatistics(XervBackupOperationMode.Restore);
            SetupCommonOptions(rs);

            m_progress = 0;
            BackendWrapper backend = null;
            m_restorePatches = 0;

            using (new Logging.Timer("Restore from " + m_backend + " to " + string.Join(System.IO.Path.PathSeparator.ToString(), target)))
            {
                try
                {
                    if (OperationStarted != null)
                        OperationStarted(this, XervBackupOperation.Restore, rs.OperationMode, -1, -1, Strings.Interface.StatusStarted, "");
                    OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, -1, -1, Strings.Interface.StatusStarted, "");

                    Utility.FilenameFilter filter = m_options.Filter;

                    //Filter is prefered, if both file and filter is specified
                    if (!m_options.HasFilter && !string.IsNullOrEmpty(m_options.FileToRestore))
                    {
                        List<Utility.IFilenameFilter> list = new List<XervBackup.Library.Utility.IFilenameFilter>();
                        list.Add(new Utility.FilelistFilter(true, m_options.FileToRestore.Split(System.IO.Path.PathSeparator)));
                        list.Add(new Utility.RegularExpressionFilter(false, ".*"));

                        filter = new XervBackup.Library.Utility.FilenameFilter(list);
                    }

                    backend = new BackendWrapper(rs, m_backend, m_options);
                    backend.ProgressEvent += new XervBackup.Library.Main.RSync.RSyncDir.ProgressEventDelegate(BackupTransfer_ProgressEvent);

                    OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, Strings.Interface.StatusReadingIncrementals, "");

                    ManifestEntry bestFit = backend.GetBackupSet(m_options.RestoreTime);

                    //We will need all the manifests downloaded anyway
                    if (!m_options.DontReadManifests)
                    {
                        if (bestFit.Incrementals.Count > 0)
                            VerifyManifestChain(backend, bestFit.Incrementals[bestFit.Incrementals.Count - 1]);
                        else
                            VerifyManifestChain(backend, bestFit);

                        OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, Strings.Interface.StatusReadingIncrementals, "");
                    }

                    m_progress = INCREMENAL_COST;

                    List<ManifestEntry> entries = new List<ManifestEntry>();
                    entries.Add(bestFit);
                    entries.AddRange(bestFit.Incrementals);
                    int patchno = 0;

                    foreach (ManifestEntry be in entries)
                        m_restorePatches += be.Volumes.Count;

                    Manifestfile rootManifest = GetManifest(backend, bestFit);

                    int sourceDirCount = (rootManifest.SourceDirs == null || rootManifest.SourceDirs.Length == 0) ? 1 : rootManifest.SourceDirs.Length;

                    //After reading the first manifest, we know the source folder count
                    if ((rootManifest.SourceDirs == null || rootManifest.SourceDirs.Length == 0) && target.Length > 1)
                    {
                        //V1 support
                        rs.LogWarning(string.Format(Strings.Interface.TooManyTargetFoldersWarning, 1, target.Length), null);
                        Array.Resize(ref target, 1);
                    }
                    else if (target.Length > sourceDirCount)
                    {
                        //If we get too many, we can just cut them off
                        rs.LogWarning(string.Format(Strings.Interface.TooManyTargetFoldersWarning, sourceDirCount, target.Length), null);
                        Array.Resize(ref target, rootManifest.SourceDirs.Length);
                    }
                    else if (target.Length != 1 && target.Length < sourceDirCount)
                    {
                        //If we get too few, we have to bail
                        throw new Exception(string.Format(Strings.Interface.TooFewTargetFoldersError, sourceDirCount, target.Length));
                    }
                    else if (target.Length == 1 && sourceDirCount > 1)
                    {
                        //If there is just one target folder, we automatically compose target subfolders
                        string[] newtargets = new string[rootManifest.SourceDirs.Length];

                        List<string> suggestions = new List<string>();
                        for (int i = 0; i < rootManifest.SourceDirs.Length; i++)
                        {
                            string s = rootManifest.SourceDirs[i];
                            //HACK: We use a leading / in the path name to detect source OS
                            // all paths are absolute, so this detects all unix like systems
                            string dirSepChar = s.StartsWith("/") ? "/" : "\\";

                            if (s.EndsWith(dirSepChar))
                                s = s.Substring(0, s.Length - 1);

                            int lix = s.LastIndexOf(dirSepChar);
                            if (lix < 0 || lix + 1 >= s.Length)
                                s = i.ToString();
                            else
                                s = s.Substring(lix + 1);

                            foreach (char c in System.IO.Path.GetInvalidFileNameChars())
                                s = s.Replace(c, '_');

                            suggestions.Add(s);
                        }

                        Dictionary<string, int> duplicates = new Dictionary<string, int>(Library.Utility.Utility.ClientFilenameStringComparer);
                        for (int i = 0; i < suggestions.Count; i++)
                            if (duplicates.ContainsKey(suggestions[i]))
                                duplicates[suggestions[i]]++;
                            else
                                duplicates[suggestions[i]] = 1;

                        for (int i = 0; i < newtargets.Length; i++)
                        {
                            string suffix = duplicates[suggestions[i]] > 1 ? i.ToString() : suggestions[i];
                            newtargets[i] = System.IO.Path.Combine(target[0], suffix);
                        }

                        target = newtargets;
                    }

                    //Make sure all targets exist
                    foreach(string s in target)
                        if (!System.IO.Directory.Exists(s))
                            System.IO.Directory.CreateDirectory(s);

                    using (RSync.RSyncDir sync = new XervBackup.Library.Main.RSync.RSyncDir(target, rs, filter))
                    {
                        sync.ProgressEvent += new XervBackup.Library.Main.RSync.RSyncDir.ProgressEventDelegate(RestoreRSyncDir_ProgressEvent);

                        foreach (ManifestEntry be in entries)
                        {
                            m_progress = ((1.0 - INCREMENAL_COST) * (patchno / (double)m_restorePatches)) + INCREMENAL_COST;

                            CheckLiveControl();

                            Manifestfile manifest = be == bestFit ? rootManifest : GetManifest(backend, be);

                            CheckLiveControl();

                            foreach (KeyValuePair<SignatureEntry, ContentEntry> vol in be.Volumes)
                            {
                                ContentEntry contentVol = vol.Value;
                                SignatureEntry signatureVol = vol.Key;

                                m_progress = ((1.0 - INCREMENAL_COST) * (patchno / (double)m_restorePatches)) + INCREMENAL_COST;

                                //Skip nonlisted
                                if (manifest.ContentHashes != null && contentVol.Volumenumber > manifest.ContentHashes.Count)
                                {
                                    Logging.Log.WriteMessage(string.Format(Strings.Interface.SkippedContentVolumeLogMessage, contentVol.Volumenumber), XervBackup.Library.Logging.LogMessageType.Warning);
                                    rs.LogWarning(string.Format(Strings.Interface.SkippedContentVolumeLogMessage, contentVol.Volumenumber), null);
                                    patchno++;
                                    continue;
                                }

                                using (Utility.TempFile patchzip = new XervBackup.Library.Utility.TempFile())
                                {
                                    OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, string.Format(Strings.Interface.StatusPatching, patchno + 1), "");

                                    CheckLiveControl();

                                     if (m_options.HasFilter || !string.IsNullOrEmpty(m_options.FileToRestore))
                                     {
                                         bool hasFiles = false;

                                         using (Utility.TempFile sigFile = new XervBackup.Library.Utility.TempFile())
                                         {
                                             OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, string.Format(Strings.Interface.StatusDownloadingSignatureVolume, patchno + 1), "");

                                             try
                                             {
                                                 using (new Logging.Timer("Get " + signatureVol.Filename))
                                                     backend.Get(signatureVol, manifest, sigFile, manifest.SignatureHashes == null ? null : manifest.SignatureHashes[signatureVol.Volumenumber - 1]);
                                             }
                                             catch (BackendWrapper.HashMismathcException hme)
                                             {
                                                 hasFiles = true;
                                                 rs.LogError(string.Format(Strings.Interface.FileHashFailure, hme.Message), hme);
                                             }

                                             if (!hasFiles)
                                                 using (Library.Interface.ICompression patch = DynamicLoader.CompressionLoader.GetModule(signatureVol.Compression, sigFile, m_options.RawOptions))
                                                 {
                                                     foreach(KeyValuePair<RSync.RSyncDir.PatchFileType, string> k in sync.ListPatchFiles(patch))
                                                         if (filter.ShouldInclude("", System.IO.Path.DirectorySeparatorChar.ToString() + k.Value))
                                                         {
                                                             //TODO: Perhaps a bit much to download the content archive
                                                             // if the file is only marked for deletion?
                                                             hasFiles = true;
                                                             break;
                                                         }
                                                 }
                                         }

                                         if (!hasFiles)
                                         {
                                             //Avoid downloading the content file
                                             patchno++;
                                             continue;
                                         }
                                    }

                                     OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, string.Format(Strings.Interface.StatusDownloadingContentVolume, patchno + 1), "");

                                    using (new Logging.Timer("Get " + contentVol.Filename))
                                        backend.Get(contentVol, manifest, patchzip, manifest.ContentHashes == null ? null : manifest.ContentHashes[contentVol.Volumenumber - 1]);

                                    OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, (int)(m_progress * 100), -1, string.Format(Strings.Interface.StatusPatching, patchno + 1), "");

                                    using (new Logging.Timer((patchno == 0 ? "Full restore to: " : "Incremental restore " + patchno.ToString() + " to: ") + string.Join(System.IO.Path.PathSeparator.ToString(), target)))
                                    using (Library.Interface.ICompression patch = DynamicLoader.CompressionLoader.GetModule(contentVol.Compression, patchzip, m_options.RawOptions))
                                        sync.Patch(target, patch);
                                }
                                patchno++;
                            }

                            //Make sure there are no partial files, as partial files are not allowed to span backup sets
                            sync.FinalizeRestore();
                        }
                    }
                }
                finally
                {
                    if (backend != null)
                        backend.Dispose();

                    if (OperationCompleted != null)
                        OperationCompleted(this, XervBackupOperation.Restore, rs.OperationMode, 100, -1, Strings.Interface.StatusCompleted, "");

                    OperationProgress(this, XervBackupOperation.Restore, rs.OperationMode, 100, -1, Strings.Interface.StatusCompleted, "");
                }
            }

            rs.EndTime = DateTime.Now;
            return rs.ToString();
        }
Esempio n. 3
0
        public IList<string> ListCurrentFiles()
        {
            RestoreStatistics rs = new RestoreStatistics(XervBackupOperationMode.ListCurrentFiles);
            SetupCommonOptions(rs);

            Utility.FilenameFilter filter = m_options.Filter;
            DateTime timelimit = m_options.RestoreTime;

            if (OperationStarted != null)
                OperationStarted(this, XervBackupOperation.List, rs.OperationMode, 0, -1, Strings.Interface.StatusStarted, "");

            List<string> res;

            using (BackendWrapper backend = new BackendWrapper(rs, m_backend, m_options))
            using (Utility.TempFolder basefolder = new XervBackup.Library.Utility.TempFolder())
            {
                ManifestEntry bestFit = backend.GetBackupSet(timelimit);

                List<ManifestEntry> entries = new List<ManifestEntry>();
                entries.Add(bestFit);
                entries.AddRange(bestFit.Incrementals);

                List<KeyValuePair<ManifestEntry, Library.Interface.ICompression>> patches = FindPatches(backend, entries, basefolder, false, rs);

                using (RSync.RSyncDir dir = new XervBackup.Library.Main.RSync.RSyncDir(new string[] { basefolder }, rs, filter, patches))
                    res = dir.UnmatchedFiles();
            }

            if (OperationCompleted != null)
                OperationCompleted(this, XervBackupOperation.List, rs.OperationMode, 100, -1, Strings.Interface.StatusCompleted, "");

            return res;
        }
Esempio n. 4
0
        public string[] ListSourceFolders()
        {
            RestoreStatistics rs = new RestoreStatistics(XervBackupOperationMode.ListSourceFolders);
            SetupCommonOptions(rs);

            if (m_options.DontReadManifests)
                throw new Exception(Strings.Interface.ManifestsMustBeRead);

            DateTime timelimit = m_options.RestoreTime;

            if (OperationStarted != null)
                OperationStarted(this, XervBackupOperation.List, rs.OperationMode, 0, -1, Strings.Interface.StatusStarted, "");

            string[] res;

            using (BackendWrapper backend = new BackendWrapper(rs, m_backend, m_options))
            using (Utility.TempFile mfile = new XervBackup.Library.Utility.TempFile())
            {
                ManifestEntry bestFit = backend.GetBackupSet(timelimit);

                backend.Get(bestFit, null, mfile, null);
                res = new Manifestfile(mfile, m_options.SkipFileHashChecks).SourceDirs;
            }

            if (OperationCompleted != null)
                OperationCompleted(this, XervBackupOperation.List, rs.OperationMode, 100, -1, Strings.Interface.StatusCompleted, "");

            return res;
        }
Esempio n. 5
0
        public List<KeyValuePair<RSync.RSyncDir.PatchFileType, string>> ListActualSignatureFiles()
        {
            CommunicationStatistics stats = new CommunicationStatistics(XervBackupOperationMode.ListActualSignatureFiles);
            SetupCommonOptions(stats);

            using (BackendWrapper backend = new BackendWrapper(stats, m_backend, m_options))
            {
                ManifestEntry bestFit = backend.GetBackupSet(m_options.RestoreTime);
                if (bestFit.Incrementals.Count > 0) //Get the most recent incremental
                    bestFit = bestFit.Incrementals[bestFit.Incrementals.Count - 1];

                using (Utility.TempFolder folder = new XervBackup.Library.Utility.TempFolder())
                {
                    List<Library.Interface.ICompression> patches = new List<XervBackup.Library.Interface.ICompression>();
                    foreach (KeyValuePair<ManifestEntry, Library.Interface.ICompression> entry in FindPatches(backend, new List<ManifestEntry>(new ManifestEntry[] { bestFit }), folder, false, stats))
                        patches.Add(entry.Value);

                    using (RSync.RSyncDir dir = new XervBackup.Library.Main.RSync.RSyncDir(new string[] { folder }, stats, null))
                        return dir.ListPatchFiles(patches);
                }
            }
        }