Beispiel #1
0
        public ArchiveFileStream CreateFile(string name, bool deleteExisting = false)
        {
            if (Files.ContainsKey(name))
            {
                if (!deleteExisting)
                {
                    return(OpenFile(name, true));
                }

                Files[name].CloseAll();
                Files.Remove(name);
                return(OpenFile(name, true));
            }

            var file = new ArchiveFile(this, name, 0, 0);

            file.MarkDirty();
            Files[name] = file;
            return(file.Open(true));
        }
Beispiel #2
0
        internal static Dictionary <string, ArchiveFile> ReadIndex(Archive archive, BinaryReader r)
        {
            int count = (int)(archive.Header.IndexLength / EntrySize);
            var index = new List <ArchiveEntry>();

            r.Seek(archive.Header.IndexOffset);
            for (int i = 0; i < count; i++)
            {
                index.Add(ReadIndexEntry(r));
            }

            var dict = new Dictionary <string, ArchiveFile>(count, StringComparer.InvariantCultureIgnoreCase);

            foreach (var entry in index)
            {
                var name = r.Seek(entry.NameOffset).ReadString(entry.NameLength);
                var file = new ArchiveFile(archive, name, entry.DataOffset, entry.DataLength);
                dict[name] = file;
            }

            return(dict);
        }
Beispiel #3
0
 internal ArchiveFileStream(ArchiveFile file, Stream baseStream)
 {
     File       = file;
     BaseStream = baseStream;
 }
Beispiel #4
0
        internal bool SaveFile(ArchiveFile file, MemoryStream data)
        {
            lock (_syncRoot) {
                var w = new BinaryWriter(Stream);
                switch (SaveMode)
                {
                case ArchiveSaveMode.Explicit:
                    // mark file as dirty, but don't save to disk
                    MarkDirty();
                    file.MarkDirty();
                    file.NewData    = data.ToArray();
                    file.DataLength = file.NewData.Length;
                    return(true);

                case ArchiveSaveMode.Flush:
                    MarkDirty();

                    // if index and the old file data are in the back of the file (this file was last updated), overwrite them.
                    // otherwise, the old file data will be kept until Flush() is called and the entire archive is written again.
                    long newFileOffset = Stream.Length;
                    if (Header.IndexOffset + Header.IndexLength == newFileOffset)
                    {
                        // Index is at the end of the file, overwrite it
                        newFileOffset = Header.IndexOffset;
                    }
                    if (file.DataOffset + file.DataLength == newFileOffset)
                    {
                        // Old file data is at the end, overwrite it
                        newFileOffset = file.DataOffset;
                    }
                    file.DataOffset = newFileOffset;
                    file.DataLength = data.Length;

                    // write file data
                    Stream.SetLength(newFileOffset);
                    Stream.Seek(newFileOffset);
                    data.Seek(0).CopyTo(Stream);

                    // write index
                    Header.IndexOffset = (uint)Stream.Position;
                    ArchiveHelpers.WriteIndex(Files, w);

                    // update header
                    Stream.Seek(0);
                    ArchiveHelpers.WriteHeader(Header, w);
                    Stream.Flush();

                    return(true);

                case ArchiveSaveMode.Immediate:
                    MarkDirty();
                    Stream.Seek(0, SeekOrigin.End);
                    // write file name
                    file.NameOffset = (uint)Stream.Position;
                    w.WriteNullTerminatedString(file.Name);
                    // write file data
                    file.DataOffset = (uint)Stream.Position;
                    data.Seek(0).CopyTo(Stream);
                    file.DataLength = (uint)(Stream.Position - file.DataOffset);
                    return(true);

                default:
                    return(false);
                }
            }
        }