Пример #1
0
        /// <summary>
        /// Retrieves information about a file in the archive.
        /// </summary>
        /// <param name="filePath">The virual path to the file.</param>
        /// <returns>The <see cref="AegisFileInfo"/> about the file, or null if it isn't found.</returns>
        public AegisFileInfo GetFileInfo(AegisVirtualFilePath filePath)
        {
            ArgCheck.NotNull(filePath, nameof(filePath));
            this.ThrowIfLocked();

            return(this.FileIndex.GetFileInfo(filePath));
        }
Пример #2
0
        /// <summary>
        /// Removes a file from the archive.
        /// </summary>
        /// <param name="filePath">The virtual path to the file.</param>
        /// <remarks>If no file exists at that path, this operation is a silent no-op.</remarks>
        public void RemoveFile(AegisVirtualFilePath filePath)
        {
            ArgCheck.NotNull(filePath, nameof(filePath));
            this.ThrowIfLocked();

            var fileInfo = this.GetFileInfo(filePath);

            if (fileInfo != null)
            {
                this.RemoveFile(fileInfo.FileId);
            }
        }
Пример #3
0
        /// <summary>
        /// Adds a file to the archive.
        /// </summary>
        /// <param name="virtualPath">The virtual path to add the file at.</param>
        /// <param name="fileStream">The file data stream.</param>
        /// <param name="overwriteIfExists">
        ///     Whether or not to overwrite existing files at that path.
        ///     If false, an <see cref="InvalidOperationException"/> is thrown if a file already exists at the path.
        /// </param>
        /// <returns>Metadata about the file added to the archive.</returns>
        public AegisFileInfo PutFile(AegisVirtualFilePath virtualPath, Stream fileStream, bool overwriteIfExists = false)
        {
            ArgCheck.NotNull(virtualPath, nameof(virtualPath));
            ArgCheck.NotNull(fileStream, nameof(fileStream));
            this.ThrowIfLocked();

            // Remove any existing files stored at the path, if we're allowed to.
            var existingFileInfo = this.FileIndex.GetFileInfo(virtualPath);

            if (existingFileInfo != null)
            {
                if (!overwriteIfExists)
                {
                    throw new InvalidOperationException(
                              $"A file with ID '{existingFileInfo.FileId}' already exists at virtual path '{virtualPath}'!");
                }

                this.RemoveFile(existingFileInfo.FileId);
            }

            var currentTime = DateTimeOffset.UtcNow;

            var fileInfo = existingFileInfo ?? new AegisFileInfo(
                virtualPath,
                new FileIndexEntry
            {
                FileId           = Guid.NewGuid(),
                FilePath         = virtualPath.ToString(),
                AddedTime        = currentTime,
                LastModifiedTime = currentTime,
            });

            fileInfo.IndexEntry.LastModifiedTime = currentTime;

            // Encrypt the file.
            // This mechanism won't work for very large files since it loads the whole thing into memory.
            // For now, this is an acceptable limit for Aegis file archiving.
            using var memoryStream = new MemoryStream();
            fileStream.CopyTo(memoryStream);
            var encryptedFile = this.ArchiveKey.Encrypt(
                this.CryptoStrategy,
                memoryStream.ToArray());

            encryptedFile.WriteToBinaryStream(this.SecureArchive.GetEntryWriteStream(fileInfo.ArchiveEntryName));

            try
            {
                this.FileIndex.Add(fileInfo);
                this.PersistMetadata();
            }
            catch
            {
                // Creating file metadata failed.
                // Revert adding file to keep the archive to keep it consistent.
                this.SecureArchive.DeleteEntryIfExists(fileInfo.ArchiveEntryName);

                throw;
            }

            this.FlushArchive();

            return(fileInfo);
        }