/// <summary> /// Saves this instance, aka overwrites the file header. /// </summary> public void Save() { var head = new FileHeader { Signature = PackCommon.Header, Revision = (uint)Revision, EntryCount = Count, Path = Root, Ft1 = Created.ToFileTime(), Ft2 = Modified.ToFileTime() }; var pkgHead = new PackageHeader { EntryCount = Count, InfoHeaderSize = 0, DataSectionSize = (uint)(_source.Length - _dataStart), BlankSize = 0, Zero = new byte[16] }; var infos = new List <Tuple <byte[], PackageItemInfo> >(); foreach (var e in _entries.Values) { var info = new PackageItemInfo { CompressedSize = e.SizeInPack, DecompressedSize = e.DecompressedSize, IsCompressed = e.IsCompressed, Offset = (uint)e.DataOffset, Seed = e.CryptoSeed, CreationTime = e.CreatedDate.ToFileTime(), CreationTime2 = e.CreatedDate.ToFileTime(), LastAccessTime = e.AccessDate.ToFileTime(), ModifiedTime = e.ModifiedDate.ToFileTime(), ModifiedTime2 = e.ModifiedDate.ToFileTime(), }; var bytes = PackCommon.EncodeName(e.Name.PadRight(e.MaxNameLength, '\0')); infos.Add(Tuple.Create(bytes, info)); pkgHead.InfoHeaderSize += bytes.Length + StructUtil.SizeOf <PackageItemInfo>(); } pkgHead.BlankSize = (int)(_dataStart - (StructUtil.SizeOf <FileHeader>() + StructUtil.SizeOf <PackageHeader>() + pkgHead.InfoHeaderSize)); pkgHead.InfoHeaderSize += pkgHead.BlankSize; _source.Position = 0; head.WriteToStream(_source); pkgHead.WriteToStream(_source); foreach (var i in infos) { _source.Write(i.Item1, 0, i.Item1.Length); i.Item2.WriteToStream(_source); } }
/// <summary> /// Outputs the pack file to the given stream. /// </summary> /// <param name="dst">The DST.</param> public void SaveTo(Stream dst) { var head = new FileHeader { Signature = PackCommon.Header, Revision = Revision, EntryCount = _entries.Count, Path = Root, Ft1 = DateTime.UtcNow.ToFileTimeUtc(), Ft2 = DateTime.UtcNow.ToFileTimeUtc() }; var pkgHead = new PackageHeader { EntryCount = _entries.Count, InfoHeaderSize = 0, DataSectionSize = (uint)_bodyStream.Position, BlankSize = 0, Zero = new byte[16] }; var infos = new List <Tuple <byte[], PackageItemInfo> >(); foreach (var e in _entries) { var info = new PackageItemInfo() { CompressedSize = e.SizeInPack, DecompressedSize = e.DecompressedSize, IsCompressed = e.IsCompressed, Offset = (uint)e.DataOffset, Seed = e.CryptoSeed, CreationTime = e.CreatedDate.ToFileTime(), CreationTime2 = e.CreatedDate.ToFileTime(), ModifiedTime = e.ModifiedDate.ToFileTime(), ModifiedTime2 = e.ModifiedDate.ToFileTime(), LastAccessTime = e.AccessDate.ToFileTime() }; var bytes = PackCommon.EncodeName(e.Name); infos.Add(Tuple.Create(bytes, info)); pkgHead.InfoHeaderSize += bytes.Length + StructUtil.SizeOf <PackageItemInfo>(); } head.WriteToStream(dst); pkgHead.WriteToStream(dst); foreach (var i in infos) { dst.Write(i.Item1, 0, i.Item1.Length); i.Item2.WriteToStream(dst); } _bodyStream.Position = 0; _bodyStream.CopyTo(dst); }
/// <summary> /// Reads the package infos. /// </summary> /// <param name="packageHeader">The package header.</param> /// <exception cref="System.Exception">Entry ' + name + ' is corrupted!</exception> private void ReadPackageInfos(PackageHeader packageHeader) { var infoHeader = new byte[packageHeader.InfoHeaderSize]; _source.Read(infoHeader, 0, infoHeader.Length); var ptr = 0; for (var i = 0; i < packageHeader.EntryCount; i++) { int nameSectionLength; if (infoHeader[ptr] < 4) { nameSectionLength = 0x10 * (infoHeader[ptr] + 1); } else if (infoHeader[ptr] == 4) { nameSectionLength = 0x60; } else { nameSectionLength = BitConverter.ToInt32(infoHeader, ptr + 1) + 5; } var lengthSize = (infoHeader[ptr] > 4 ? 5 : 1); var nameStart = ptr + lengthSize; var maxNameLength = nameSectionLength - lengthSize - 1; // 1 for the trailing \0, which we don't care about. var name = Encoding.UTF8.GetString(infoHeader, nameStart, maxNameLength).TrimEnd('\0'); ptr += nameSectionLength; var info = infoHeader.GetStruct <PackageItemInfo>(ptr); if (info.Zero != 0) { throw new Exception("Entry '" + name + "' is corrupted!"); } _entries[name.NormalizePath()] = new PackEntry(info, name, maxNameLength); ptr += StructUtil.SizeOf <PackageItemInfo>(); } }