コード例 #1
0
    /// <summary>
    /// Checks whether an implementation directory matches the expected digest.
    /// Throws <see cref="DigestMismatchException"/> if it does not match.
    /// </summary>
    /// <param name="path">The path of the directory ot check.</param>
    /// <param name="manifestDigest">The expected digest.</param>
    /// <param name="handler">A callback object used when the the user is to be informed about progress.</param>
    /// <exception cref="OperationCanceledException">The user canceled the task.</exception>
    /// <exception cref="NotSupportedException"><paramref name="manifestDigest"/> does not list any supported digests.</exception>
    /// <exception cref="IOException">The directory could not be processed.</exception>
    /// <exception cref="UnauthorizedAccessException">Read access to the directory is not permitted.</exception>
    /// <exception cref="DigestMismatchException">The directory does not match the expected digest</exception>
    public static void Verify(string path, ManifestDigest manifestDigest, ITaskHandler handler)
    {
        #region Sanity checks
        if (string.IsNullOrEmpty(path))
        {
            throw new ArgumentNullException(nameof(path));
        }
        if (handler == null)
        {
            throw new ArgumentNullException(nameof(handler));
        }
        #endregion

        string expectedDigest = manifestDigest.Best ?? throw new NotSupportedException(Resources.NoKnownDigestMethod);
        var    format         = ManifestFormat.FromPrefix(expectedDigest);

        var builder = new ManifestBuilder(format);
        handler.RunTask(new ReadDirectory(path, builder));
        if (Verify(builder.Manifest, expectedDigest) == null)
        {
            string manifestFilePath = Path.Combine(path, Manifest.ManifestFile);
            var    expectedManifest = File.Exists(manifestFilePath) ? Manifest.Load(manifestFilePath, format) : null;
            throw new DigestMismatchException(
                      expectedDigest, actualDigest: builder.Manifest.CalculateDigest(),
                      expectedManifest, actualManifest: builder.Manifest);
        }
    }
コード例 #2
0
    /// <inheritdoc/>
    public void Add(ManifestDigest manifestDigest, Action <IBuilder> build)
    {
        #region Sanity checks
        if (build == null)
        {
            throw new ArgumentNullException(nameof(build));
        }
        #endregion

        if (manifestDigest.AvailableDigests.Any(digest => Directory.Exists(System.IO.Path.Combine(Path, digest))))
        {
            throw new ImplementationAlreadyInStoreException(manifestDigest);
        }
        string expectedDigest = manifestDigest.Best ?? throw new NotSupportedException(Resources.NoKnownDigestMethod);
        Log.Debug($"Storing implementation {expectedDigest} in {this}");
        var format = ManifestFormat.FromPrefix(manifestDigest.Best);

        // Place files in temp directory until digest is verified
        string tempDir = GetTempDir();
        using var _ = new Disposable(() => DeleteTempDir(tempDir));

        var builder = new ManifestBuilder(format);
        build(new DirectoryBuilder(tempDir, builder));
        var manifest = ImplementationStoreUtils.Verify(builder.Manifest, expectedDigest);

        if (manifest == null)
        {
            throw new DigestMismatchException(
                      expectedDigest, actualDigest: builder.Manifest.CalculateDigest(),
                      actualManifest: builder.Manifest);
        }
        manifest.Save(System.IO.Path.Combine(tempDir, Manifest.ManifestFile));

        string target = System.IO.Path.Combine(Path, expectedDigest);
        lock (_renameLock) // Prevent race-conditions when adding the same digest twice
        {
            if (Directory.Exists(target))
            {
                throw new ImplementationAlreadyInStoreException(manifestDigest);
            }

            // Move directory to final destination
            try
            {
                Directory.Move(tempDir, target);
            }
            catch (IOException ex) when(ex.Message.Contains("already exists") || Directory.Exists(target))
            {
                throw new ImplementationAlreadyInStoreException(manifestDigest);
            }
        }

        // Prevent any further changes to the directory
        if (UseWriteProtection)
        {
            EnableWriteProtection(target);
        }
    }
コード例 #3
0
 /// <inheritdoc/>
 public Digest([NotNull] ICommandHandler handler) : base(handler)
 {
     Options.Add("manifest", () => Resources.OptionManifest, _ => _printManifest = true);
     Options.Add("digest", () => Resources.OptionDigest, _ => _printDigest       = true);
     Options.Add("algorithm=", () => Resources.OptionAlgorithm + Environment.NewLine + SupportedValues(ManifestFormat.All),
                 delegate(string algorithm)
     {
         try
         {
             _algorithm = ManifestFormat.FromPrefix(algorithm);
         }
         #region Error handling
         catch (ArgumentException ex)
         {
             // Wrap exception since only certain exception types are allowed
             throw new OptionException(ex.Message, algorithm);
         }
         #endregion
     });
 }
コード例 #4
0
        /// <summary>
        /// Creates a new implementation node.
        /// </summary>
        /// <param name="digest">The digest identifying the implementation.</param>
        /// <param name="store">The <see cref="IStore"/> the implementation is located in.</param>
        /// <exception cref="FormatException">The manifest file is not valid.</exception>
        /// <exception cref="IOException">The manifest file could not be read.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the file is not permitted.</exception>
        protected ImplementationNode(ManifestDigest digest, [NotNull] IStore store)
            : base(store)
        {
            #region Sanity checks
            if (store == null)
            {
                throw new ArgumentNullException("store");
            }
            #endregion

            _digest = digest;

            // Determine the total size of an implementation via its manifest file
            string path = store.GetPath(digest);
            if (path == null)
            {
                return;
            }
            string manifestPath = System.IO.Path.Combine(path, Manifest.ManifestFile);
            Size = Manifest.Load(manifestPath, ManifestFormat.FromPrefix(digest.AvailableDigests.FirstOrDefault())).TotalSize;
        }
コード例 #5
0
 public void FromPrefix()
 {
     ManifestFormat.FromPrefix("sha1new=abc").Should().BeSameAs(ManifestFormat.Sha1New);
     ManifestFormat.FromPrefix("sha256=abc").Should().BeSameAs(ManifestFormat.Sha256);
     ManifestFormat.FromPrefix("sha256new_abc").Should().BeSameAs(ManifestFormat.Sha256New);
 }