예제 #1
0
        /// <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);
            }
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        /// <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>();
            }
        }