예제 #1
0
 internal void AddEntry(PackArchiveEntry entry)
 {
     if (_mode == PackArchiveMode.Read)
     {
         throw new NotSupportedException(Messages.EntriesInReadMode);
     }
     ThrowIfDisposed();
     _entries.Add(entry);
 }
예제 #2
0
        private void ReadArchiveFile()
        {
            var header = default(PackArchiveData.Header);

            header.Deserialize(_archiveReader);

            if (header.Signature != VFSPackArchiveSignature)
            {
                throw new Exception(Messages.FileHeaderCorrupted);
            }
            if (header.NumEntries < 0 || header.OffsetString < 0 || header.OffsetData < 0 || header.OffsetData < header.OffsetString)
            {
                throw new Exception(Messages.InvalidParameters);
            }

            long position = _archiveStream.Position;

            _archiveStream.Position = header.OffsetString;
            _dataOffset             = header.OffsetData;

            var stringLength = (int)(header.OffsetData - header.OffsetString);
            var entriesCount = (header.OffsetString - position) / PackArchiveData.FileData.Size;
            var stringBuffer = new byte[stringLength];

            if (stringLength != _archiveReader.Read(stringBuffer, 0, stringLength))
            {
                throw new Exception(Messages.InvalidStringTable);
            }
            if (entriesCount != header.NumEntries)
            {
                throw new Exception(Messages.InvalidEntriesTable);
            }

            _stringTable            = Encoding.Unicode.GetString(stringBuffer);
            _archiveStream.Position = position;
            _entriesCount           = header.NumEntries;

            var fileData = new PackArchiveData.FileData[_entriesCount];

            for (long i = 0; i < _entriesCount; i++)
            {
                fileData[i].Deserialize(_archiveReader);
                var type  = (PackArchiveEntry.EntryType)fileData[i].Type;
                var name  = _stringTable.Substring(fileData[i].NameOffset, fileData[i].NameLength);
                var entry = new PackArchiveEntry(type, name, name, fileData[i].DataSize, fileData[i].DataOffset);
                _entries.Add(entry);
            }

            _readEntries = true;
            UpdatePath(_entries[0], String.Empty);
        }
예제 #3
0
        private void UpdatePath(PackArchiveEntry entry, string parent)
        {
            if (entry.Offset == 0)
            {
                return;
            }

            entry.Path = Path.Combine(parent, entry.Name);

            for (int i = 0; i < entry.Count; i++)
            {
                var index = Convert.ToInt32(entry.Offset + i);
                UpdatePath(_entries[index], entry.Path);
            }
        }
예제 #4
0
        public Stream Open(PackArchiveEntry entry)
        {
            if (entry.Type == PackArchiveEntry.EntryType.Directory)
            {
                return(new MemoryStream());
            }

            var size   = entry.Size;
            var offset = _dataOffset + entry.Offset;
            var buffer = new byte[size];

            if (offset + size > _archiveSize)
            {
                throw new InvalidOperationException(Messages.UnexpectedEndOfStream);
            }

            _archiveStream.Position = offset;
            _archiveStream.Read(buffer, 0, size);

            return(new MemoryStream(buffer));
        }
예제 #5
0
        public static void ExtractToFile(this PackArchive source, PackArchiveEntry entry, string destinationFileName, bool overwrite)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (destinationFileName == null)
            {
                throw new ArgumentNullException("destinationFileName");
            }

            var mode = overwrite ? FileMode.Create : FileMode.CreateNew;

            using (var stream = File.Open(destinationFileName, mode, FileAccess.Write, FileShare.None))
            {
                using (var stream2 = source.Open(entry))
                {
                    stream2.CopyTo(stream);
                }
            }
        }
예제 #6
0
        private static void DoCreateFromDirectory(PackArchive archive, PackArchiveEntry rootEntry, DirectoryInfo rootInfo)
        {
            var countBefore = archive.GetEntryCount();
            var directories = rootInfo.GetDirectories();
            var files       = rootInfo.GetFiles();

            var index = 0;

            for (int i = 0; i < directories.Length; i++)
            {
                if (IsNormalDirectory(directories[i].Attributes))
                {
                    archive.AddEntry(CreateDirectory(rootEntry.Path, directories[i].Name, 0));
                    directories[index++] = directories[i];
                }
            }

            for (int j = 0; j < files.Length; j++)
            {
                if (IsNormalFile(files[j].Attributes))
                {
                    archive.AddEntry(CreateFile(rootEntry.Path, files[j].Name, (int)files[j].Length));
                }
            }

            int countAfter = archive.GetEntryCount();

            rootEntry.Offset = countBefore;
            rootEntry.Count  = countAfter - countBefore;

            index = 0;

            for (int i = countBefore; i < countAfter; i++)
            {
                if (archive.GetEntry(i).Type == PackArchiveEntry.EntryType.Directory)
                {
                    DoCreateFromDirectory(archive, archive.GetEntry(i), directories[index++]);
                }
            }
        }