/// <summary> /// Implementation of writing an archive directory to the stream. /// </summary> /// <param name="writer">The writer stream.</param> private void WriteArchiveDirectoryToStream(Stream writer) { // Write the directory entries. long startOfDirectory = writer.Position; foreach (ZipArchiveFile entry in _entries.Values) { entry.WriteArchiveDirectoryEntryToStream(writer); } long endOfDirectory = writer.Position; // Write the trailer ByteBuffer trailer = new ByteBuffer(22); trailer.WriteUInt32(ZipArchiveFile.SignatureArchiveDirectoryEnd); trailer.WriteUInt16(ZipArchiveFile.DiskNumberStart); trailer.WriteUInt16(ZipArchiveFile.DiskNumberStart); trailer.WriteUInt16((ushort)_entries.Count); trailer.WriteUInt16((ushort)_entries.Count); trailer.WriteUInt32((uint)(endOfDirectory - startOfDirectory)); // directory size trailer.WriteUInt32((uint)startOfDirectory); // directory start trailer.WriteUInt16((ushort)ZipArchiveFile.FileCommentLength); trailer.WriteContentsTo(writer); }
/// <summary> /// Writes an archive directory entry to stream. /// </summary> /// <param name="writer">The writer stream.</param> internal void WriteArchiveDirectoryEntryToStream(Stream writer) { // File header (in central directory): // // central file header signature 4 bytes (0x02014b50) // version made by 2 bytes // version needed to extract 2 bytes // general purpose bit flag 2 bytes // compression method 2 bytes // last mod file time 2 bytes // last mod file date 2 bytes // crc-32 4 bytes // compressed size 4 bytes // uncompressed size 4 bytes // file name length 2 bytes // extra field length 2 bytes // file comment length 2 bytes // disk number start 2 bytes // internal file attributes 2 bytes // external file attributes 4 bytes // relative offset of local header 4 bytes // // file name (variable size) // extra field (variable size) // file comment (variable size) byte[] fileNameBytes = Encoding.UTF8.GetBytes(_name); ByteBuffer header = new ByteBuffer(46); header.WriteUInt32(SignatureArchiveDirectory); header.WriteUInt16(VersionMadeBy); header.WriteUInt16(VersionNeededToExtract); header.WriteUInt16(GeneralPurposeBitFlag); header.WriteUInt16((ushort)_compressionMethod); header.WriteUInt32(DateTimeToDosTime(_lastWriteTime)); header.WriteUInt32(CheckSum); header.WriteUInt32((uint)_compressedLength); header.WriteUInt32((uint)Length); header.WriteUInt16((ushort)fileNameBytes.Length); header.WriteUInt16(ExtraFieldLength); header.WriteUInt16(FileCommentLength); header.WriteUInt16(DiskNumberStart); header.WriteUInt16(InternalFileAttributes); header.WriteUInt32(ExternalFileAttributes); header.WriteUInt32(_headerOffset); header.WriteContentsTo(writer); writer.Write(fileNameBytes, 0, fileNameBytes.Length); }
/// <summary> /// Writes the Zip file header to the stream. /// </summary> /// <param name="writer">Stream to write to.</param> private void WriteZipFileHeader(Stream writer) { byte[] fileNameBytes = Encoding.UTF8.GetBytes(_name.Replace(Path.DirectorySeparatorChar, '/')); if ((uint)_length != _length) { throw new InvalidOperationException("File length too long."); } // Local file header: // // local file header signature 4 bytes (0x04034b50) // version needed to extract 2 bytes // general purpose bit flag 2 bytes // compression method 2 bytes // last mod file time 2 bytes // last mod file date 2 bytes // crc-32 4 bytes // compressed size 4 bytes // uncompressed size 4 bytes // file name length 2 bytes // extra field length 2 bytes // // file name (variable size) // extra field (variable size) // Save the start of the header file for later use in the dir entry _headerOffset = (uint)writer.Position; ByteBuffer header = new ByteBuffer(30); header.WriteUInt32(SignatureFileEntry); header.WriteUInt16(VersionNeededToExtract); header.WriteUInt16(GeneralPurposeBitFlag); header.WriteUInt16((ushort)_compressionMethod); header.WriteUInt32(DateTimeToDosTime(_lastWriteTime)); header.WriteUInt32(CheckSum); header.WriteUInt32((uint)_compressedLength); header.WriteUInt32((uint)Length); header.WriteUInt16((ushort)fileNameBytes.Length); header.WriteUInt16(ExtraFieldLength); // extra field length (unused) header.WriteContentsTo(writer); writer.Write(fileNameBytes, 0, fileNameBytes.Length); // write the archiveFile name }