protected GZipAccess(Stream stream, CompressedArchiveAccessMode mode) { IsReadOnly = mode == CompressedArchiveAccessMode.Read; BaseStream = stream; var fileStream = stream as FileStream; if (fileStream != null) { RootLocation = fileStream.Name; } _entries = GZipMemberEntry.GetMemberEntries(stream, Properties.Settings.Default.MaxGZipEntriesSearch).ToList(); if (IsReadOnly) { if (!_entries.Any()) { throw new InvalidDataException(Resources.Strings.GZipAccess_NoEntriesFound); } } else { if (_entries.Any()) { throw new InvalidOperationException(Resources.Strings.GZipAccess_EntriesAlreadyPresent); } } }
/// <summary> /// Creates an instance of <see cref="GZipMemberEntry"/> with the given name. /// </summary> /// <param name="name">The name for the entry.</param> /// <returns>A new instance of <see cref="GZipMemberEntry"/>.</returns> /// <remarks>NOTE: This instance is a placeholder only, and none of the relevant metadata is set. It is used in implementations of /// ICompressedArchiveAccess that provide a means to create new GZIP files. Note also that only minimal name validation is done.</remarks> /// <exception cref="ArgumentException">Thrown if name is <c>null</c>or empty. Perhaps other more stringent checks could be added.</exception> internal static GZipMemberEntry CreateEmptyEntry(string name) { if (string.IsNullOrEmpty(name)) { throw new ArgumentException("name"); } var entry = new GZipMemberEntry() { _name = name }; return(entry); }
private static long FindNextEntry(Core.Utility.BinaryReader reader, GZipMemberEntry currentEntry) { var foundMagic = false; var positionOfNextEntry = -1L; try { var magic = reader.ReadByte(); while (true) { if (magic == MagicIdentifier[0]) { magic = reader.ReadByte(); if (magic == MagicIdentifier[1]) { foundMagic = true; break; } } else { magic = reader.ReadByte(); } } } catch (EndOfStreamException) { positionOfNextEntry = reader.BaseStream.Length; } catch (IOException) { } if (foundMagic || (positionOfNextEntry == reader.BaseStream.Length)) { // go back 4 (CRC32) + 4 (size mod 2^32) [+ 2 (magic)] var offset = sizeof(uint) + sizeof(int); var origin = SeekOrigin.End; if (foundMagic) { offset += MagicIdentifier.Length; origin = SeekOrigin.Current; } reader.BaseStream.Seek(-offset, origin); currentEntry.Crc32 = reader.ReadUInt32(); currentEntry._length = reader.ReadInt32(); positionOfNextEntry = reader.BaseStream.Position; } return(positionOfNextEntry); }
/// <inheritdoc /> public override ICompressedArchiveEntry CreateEntry(string name) { if (IsReadOnly) { throw new InvalidOperationException(Resources.Strings.GZipAccess_InvalidModeForCreateEntryError); } if (_entries.Count > 0) { throw new NotSupportedException(Resources.Strings.GZipAccess_MultipleMembersNotSupportedError); } var entry = GZipMemberEntry.CreateEmptyEntry(name); _entries.Add(entry); return(entry); }
/// <inheritdoc /> protected override Stream OpenStreamForEntry(GZipMemberEntry entry) { Stream entryStream = null; if (IsReadOnly) { entryStream = new GZipInputStream(BaseStream) { IsStreamOwner = false }; } else { entryStream = new GZipOutputStream(BaseStream) { IsStreamOwner = false }; } return(entryStream); }
/// <summary> /// Opens a stream for the given entry. /// </summary> /// <param name="entry">The entry to open the stream for.</param> /// <returns>The stream to access the entry.</returns> /// <remarks>Note that <see cref="BaseStream"/> will already be position to the beginning of the entry by the caller.</remarks> protected abstract Stream OpenStreamForEntry(GZipMemberEntry entry);
/// <inheritdoc /> protected override Stream OpenStreamForEntry(GZipMemberEntry entry) { var entryStream = new GZipStream(BaseStream, Mode, leaveOpen: true); return(entryStream); }