示例#1
0
 public Archive(MerkleTree tree, BigInteger size, ArchiveFlags flags, byte[] key)
 {
     this.MerkleTree = tree;
     this.Size       = size;
     this.Flags      = flags;
     this.Key        = key;
 }
示例#2
0
        public void Open(string archivePathName, OpenMode openMode)
        {
            IntPtr zero = IntPtr.Zero;

            if (archiveHandle != IntPtr.Zero)
            {
                Close();
            }
            ArchivePathName = archivePathName;
            RAROpenArchiveDataEx archiveData = default(RAROpenArchiveDataEx);

            archiveData.Initialize();
            archiveData.ArcName  = this.archivePathName + "\0";
            archiveData.ArcNameW = this.archivePathName + "\0";
            archiveData.OpenMode = (uint)openMode;
            if (retrieveComment)
            {
                archiveData.CmtBuf     = new string('\0', 65536);
                archiveData.CmtBufSize = 65536u;
            }
            else
            {
                archiveData.CmtBuf     = null;
                archiveData.CmtBufSize = 0u;
            }
            zero = RAROpenArchiveEx(ref archiveData);
            if (archiveData.OpenResult != 0)
            {
                switch (archiveData.OpenResult)
                {
                case 11u:
                    throw new OutOfMemoryException("Insufficient memory to perform operation.");
                    break;

                case 12u:
                    throw new IOException("Archive header broken");
                    break;

                case 13u:
                    throw new IOException("File is not a valid archive.");
                    break;

                case 15u:
                    throw new IOException("File could not be opened.");
                    break;
                }
            }
            archiveHandle = zero;
            archiveFlags  = (ArchiveFlags)archiveData.Flags;
            RARSetCallback(archiveHandle, callback, GetHashCode());
            if (archiveData.CmtState == 1)
            {
                comment = archiveData.CmtBuf.ToString();
            }
            if (password.Length != 0)
            {
                RARSetPassword(archiveHandle, password);
            }
            OnNewVolume(this.archivePathName);
        }
示例#3
0
        public Archive CreateArchive(MerkleTree merkleTree, ArchiveFlags flags)
        {
            var archive = FindArchive(merkleTree.Root);

            if (archive != null)
            {
                return(archive);
            }

            throw new NotImplementedException();
        }
示例#4
0
        public void Open(string archivePathName, OpenMode openMode)
        {
            IntPtr zero = IntPtr.Zero;

            if (this.archiveHandle != IntPtr.Zero)
            {
                this.Close();
            }
            this.ArchivePathName = archivePathName;
            RAROpenArchiveDataEx archiveData = new RAROpenArchiveDataEx();

            archiveData.Initialize();
            archiveData.ArcName  = this.archivePathName + "\0";
            archiveData.ArcNameW = this.archivePathName + "\0";
            archiveData.OpenMode = (uint)openMode;
            if (this.retrieveComment)
            {
                archiveData.CmtBuf     = new string('\0', 0x10000);
                archiveData.CmtBufSize = 0x10000;
            }
            else
            {
                archiveData.CmtBuf     = null;
                archiveData.CmtBufSize = 0;
            }
            zero = RAROpenArchiveEx(ref archiveData);
            switch (archiveData.OpenResult)
            {
            case 11:
                throw new OutOfMemoryException("Insufficient memory to perform operation.");

            case 12:
                throw new IOException("Archive header broken");

            case 13:
                throw new IOException("File is not a valid archive.");

            case 15:
                throw new IOException("File could not be opened.");
            }
            this.archiveHandle = zero;
            this.archiveFlags  = (ArchiveFlags)archiveData.Flags;
            RARSetCallback(this.archiveHandle, this.callback, this.GetHashCode());
            if (archiveData.CmtState == 1)
            {
                this.comment = archiveData.CmtBuf.ToString();
            }
            if (this.password.Length != 0)
            {
                RARSetPassword(this.archiveHandle, this.password);
            }
            this.OnNewVolume(this.archivePathName);
        }
示例#5
0
 public Header(CompressionType compression = CompressionType.zlib,
               uint dataOffset             = 0, uint tocEntrySize = 0x20, uint numFiles = 0, uint maxBlockSize = (1 << 16),
               ArchiveFlags flags          = ArchiveFlags.Relative
               )
 {
     this.magic        = MAGIC;
     this.version      = VERSION;
     this.compression  = compression;
     this.dataOffset   = dataOffset;
     this.tocEntrySize = tocEntrySize;
     this.numFiles     = numFiles;
     this.maxBlockSize = maxBlockSize;
     this.flags        = flags;
 }
示例#6
0
        public Archive CreateArchive(MerkleTree merkleTree, BigInteger size, ArchiveFlags flags, byte[] key)
        {
            var archive = FindArchive(merkleTree.Root);

            if (archive != null)
            {
                return(archive);
            }

            archive = new Archive(merkleTree, size, flags, key);
            var archiveHash = merkleTree.Root;

            _archiveEntries.Set(archiveHash, archive);

            return(archive);
        }
示例#7
0
            public Header(byte[] bytes, int bytesOffset = 0)
            {
                fileId  = Encoding.UTF8.GetString(bytes, bytesOffset + 0, 4);
                version = BitConverter.ToUInt32(bytes, bytesOffset + 4);

                if (fileId != "BSA\0" || version != 105)
                {
                    throw new Exception("Unsupported BSA Version or ID!");
                }

                offset                = BitConverter.ToUInt32(bytes, bytesOffset + 8);
                archiveFlags          = (ArchiveFlags)BitConverter.ToUInt32(bytes, bytesOffset + 12);
                folderCount           = BitConverter.ToUInt32(bytes, bytesOffset + 16);
                fileCount             = BitConverter.ToUInt32(bytes, bytesOffset + 20);
                totalFolderNameLength = BitConverter.ToUInt32(bytes, bytesOffset + 24);
                totalFileNameLength   = BitConverter.ToUInt32(bytes, bytesOffset + 28);
                fileFlags             = (FileFlags)BitConverter.ToUInt32(bytes, bytesOffset + 32);
            }
示例#8
0
        /// <summary>
        /// Creates a new BSAReader instance from a path.
        /// </summary>
        /// <param name="path">Path to the .bsa file.</param>
        /// <exception cref="ArgumentException">The file does not exist.</exception>
        /// <exception cref="InvalidDataException">File is not a BSA archive.</exception>
        /// <exception cref="NotSupportedException">BSA archive is not for TES4.</exception>
        public BSAReader(string path)
        {
            if (!File.Exists(path))
            {
                throw new ArgumentException("File does not exist!", nameof(path));
            }

            var fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);

            _br = new BinaryReader(fs, Encoding.UTF8);

            var magic = Encoding.ASCII.GetString(_br.ReadBytes(4));

            if (magic != "BSA\0")
            {
                throw new InvalidDataException($"Archive at {path} is not a BSA!");
            }

            HeaderType = (VersionType)_br.ReadUInt32();
            if (HeaderType != VersionType.TES4)
            {
                throw new NotSupportedException($"OMODFramework only supports TES4 BSAs not {HeaderType}");
            }

            _folderRecordOffset    = _br.ReadUInt32();
            ArchiveFlags           = (ArchiveFlags)_br.ReadUInt32();
            _folderCount           = _br.ReadUInt32();
            _fileCount             = _br.ReadUInt32();
            _totalFolderNameLength = _br.ReadUInt32();
            _totalFileNameLength   = _br.ReadUInt32();
            FileFlags = (FileFlags)_br.ReadUInt32();

            Folders = GetFolders(_br).ToList();
            Files   = new List <BSAFileInfo>();

            foreach (var folder in Folders)
            {
                if (HasFolderNames)
                {
                    folder.Name = new string(_br.ReadChars(_br.ReadByte())[..^ 1]);
        internal static IEnumerable <RarVolume> GetParts(FileInfo fileInfo, string password, Options options)
        {
            FileInfoRarArchiveVolume part = new FileInfoRarArchiveVolume(fileInfo, password, options);

            yield return(part);

            ArchiveFlags af = part.ArchiveHeader.ArchiveHeaderFlags;

            if (!af_HasFlag(af, ArchiveFlags.VOLUME))
            {
                yield break; //if file isn't volume then there is no reason to look
            }
            ArchiveHeader ah = part.ArchiveHeader;

            fileInfo = GetNextFileInfo(ah, part.FileParts.FirstOrDefault <RarFilePart>() as FileInfoRarFilePart);
            //we use fileinfo because rar is dumb and looks at file names rather than archive info for another volume
            while (fileInfo != null && fileInfo.Exists)
            {
                part = new FileInfoRarArchiveVolume(fileInfo, password, options);

                fileInfo = GetNextFileInfo(ah, part.FileParts.FirstOrDefault <RarFilePart>() as FileInfoRarFilePart);
                yield return(part);
            }
        }
 private static bool af_HasFlag(ArchiveFlags archiveFlags, ArchiveFlags archiveFlags2)
 {
     return((archiveFlags & archiveFlags2) == archiveFlags2);
 }
示例#11
0
 public bool CreateArchive(MerkleTree merkleTree, BigInteger size, ArchiveFlags flags, byte[] key)
 {
     return(Nexus.CreateArchive(this.RootStorage, merkleTree, size, flags, key));
 }
示例#12
0
        public void UploadFile(Address sender, Address target, string fileName, BigInteger fileSize, byte[] contentMerkle, ArchiveFlags flags, byte[] key)
        {
            Runtime.Expect(Runtime.IsWitness(sender), "invalid witness");
            Runtime.Expect(target.IsUser, "destination address must be user address");
            Runtime.Expect(fileSize >= DomainSettings.ArchiveMinSize, "file too small");
            Runtime.Expect(fileSize <= DomainSettings.ArchiveMaxSize, "file too big");

            BigInteger requiredSize = CalculateRequiredSize(fileName, fileSize);

            var targetUsedSize      = GetUsedSpace(target);
            var targetStakedAmount  = Runtime.GetStake(target);
            var targetAvailableSize = CalculateStorageSizeForStake(targetStakedAmount);

            targetAvailableSize -= targetUsedSize;

            if (sender == target)
            {
                Runtime.Expect(targetAvailableSize >= requiredSize, "target account does not have available space");
            }
            else // otherwise we need to run some extra checks in case the sender is not the target
            {
                var foreignSpace = GetForeignSpace(target);
                if (foreignSpace < targetAvailableSize)
                {
                    targetAvailableSize = foreignSpace; // limit available space to max allocated space to foreign addresses
                }

                Runtime.Expect(targetAvailableSize >= requiredSize, "target account does not have available space");

                if (sender.IsUser)
                {
                    // note that here we require sender to have at least free space equal to msg size, mostly a protection against spam
                    var senderUsedSize      = GetUsedSpace(sender);
                    var senderStakedAmount  = Runtime.GetStake(sender);
                    var senderAvailableSize = CalculateStorageSizeForStake(senderStakedAmount);
                    senderAvailableSize -= senderUsedSize;
                    Runtime.Expect(senderAvailableSize >= requiredSize, "sender account does not have available space");
                }
                else
                {
                    Runtime.Expect(sender.IsSystem, "invalid address type for sender");
                }
            }

            var hashes = MerkleTree.FromBytes(contentMerkle);

            Runtime.CreateArchive(sender, target, hashes, fileSize, flags, key);

            var newEntry = new StorageEntry()
            {
                Name    = fileName,
                Hash    = hashes.Root,
                Creator = sender,
            };

            var list = _storageMap.Get <Address, StorageList>(target);

            list.Add <StorageEntry>(newEntry);

            Runtime.Notify(EventKind.FileCreate, target, newEntry);
        }
示例#13
0
 private bool ArchiveHeaderFlags_HasFlag(ArchiveFlags archiveFlags)
 {
     return((this.ArchiveHeaderFlags & archiveFlags) == archiveFlags);
 }
示例#14
0
 private bool ArchiveHeader_HasFlag(ArchiveFlags ahf, ArchiveFlags archiveFlags)
 {
     return((ahf & archiveFlags) == archiveFlags);
 }
示例#15
0
        // this is an helper method to upload smaller files...
        public void UploadData(Address sender, Address target, string fileName, byte[] data, ArchiveFlags flags, byte[] key)
        {
            BigInteger fileSize = data.Length;

            Runtime.Expect(fileSize <= MerkleTree.ChunkSize, "data too big");

            var merkle           = new MerkleTree(data);
            var serializedMerkle = Serialization.Serialize(merkle);

            UploadFile(sender, target, fileName, fileSize, serializedMerkle, flags, key);

            var archive = Runtime.CreateArchive(sender, target, merkle, fileSize, flags, key);

            Runtime.Expect(archive != null, "failed to create archive");

            Runtime.Expect(Runtime.WriteArchive(archive, 0, data), "failed to write archive content");
        }
示例#16
0
 private bool ArchiveHeader_HasFlag(ArchiveFlags ahf, ArchiveFlags archiveFlags)
 {
     return (ahf&archiveFlags)==archiveFlags;
 }
示例#17
0
        /// <summary>
        /// Opens specified archive using the specified mode.
        /// </summary>
        /// <param name="archivePathName">Path of archive to open</param>
        /// <param name="openMode">Mode in which to open archive</param>
        public void Open(string archivePathName, OpenMode openMode)
        {
            IntPtr handle = IntPtr.Zero;

            // Close any previously open archives
            if (this.archiveHandle != IntPtr.Zero)
            {
                this.Close();
            }

            // Prepare extended open archive struct
            this.ArchivePathName = archivePathName;
            RAROpenArchiveDataEx openStruct = new RAROpenArchiveDataEx();

            openStruct.Initialize();
            openStruct.ArcName  = this.archivePathName + "\0";
            openStruct.ArcNameW = this.archivePathName + "\0";
            openStruct.OpenMode = (uint)openMode;
            if (this.retrieveComment)
            {
                openStruct.CmtBuf     = new string((char)0, 65536);
                openStruct.CmtBufSize = 65536;
            }
            else
            {
                openStruct.CmtBuf     = null;
                openStruct.CmtBufSize = 0;
            }

            // Open archive
            handle = Unrar.RAROpenArchiveEx(ref openStruct);

            // Check for success
            if (openStruct.OpenResult != 0)
            {
                switch ((RarError)openStruct.OpenResult)
                {
                case RarError.InsufficientMemory:
                    throw new OutOfMemoryException("Insufficient memory to perform operation.");

                case RarError.BadData:
                    throw new IOException("Archive header broken");

                case RarError.BadArchive:
                    throw new IOException("File is not a valid archive.");

                case RarError.OpenError:
                    throw new IOException("File could not be opened.");
                }
            }

            // Save handle and flags
            this.archiveHandle = handle;
            this.archiveFlags  = (ArchiveFlags)openStruct.Flags;

            // Set callback
            Unrar.RARSetCallback(this.archiveHandle, this.callback, this.GetHashCode());

            // If comment retrieved, save it
            if (openStruct.CmtState == 1)
            {
                this.comment = openStruct.CmtBuf.ToString();
            }

            // If password supplied, set it
            if (this.password.Length != 0)
            {
                Unrar.RARSetPassword(this.archiveHandle, this.password);
            }

            // Fire NewVolume event for first volume
            this.OnNewVolume(this.archivePathName);
        }
示例#18
0
 public void CreateArchive(Address from, MerkleTree merkleTree, BigInteger size, ArchiveFlags flags, byte[] key)
 {
     // TODO validation
     Nexus.CreateArchive(this.RootStorage, merkleTree, size, flags, key);
 }
示例#19
0
        protected override void DoOpen()
        {
            using (CustomBinaryReader reader = new CustomBinaryReader(new FileStream(ArchivePath, FileMode.Open, FileAccess.Read)))
            {
                uint signature = reader.ReadUInt32();
                if (signature != 0x415342)
                {
                    throw new InvalidDataException("File is not BSA");
                }

                uint version = reader.ReadUInt32();
                uint folderOffset = reader.ReadUInt32();
                flags = (ArchiveFlags)reader.ReadUInt32();
                uint folderCount = reader.ReadUInt32();
                uint fileCount = reader.ReadUInt32();
                uint totalFolderNameLength = reader.ReadUInt32();
                uint totalFileNameLength = reader.ReadUInt32();
                uint fileExtensions = reader.ReadUInt32();

                FolderInfo[] folders = new FolderInfo[(int)folderCount];

                // Read folders
                reader.BaseStream.Position = folderOffset;
                for (int i = 0; i < folderCount; i++)
                {
                    ulong hash = reader.ReadUInt64();
                    uint count = reader.ReadUInt32();
                    uint offset = reader.ReadUInt32() - totalFileNameLength;
                    folders[i] = new FolderInfo()
                    {
                        FileCount = count,
                        ContentOffset = offset
                    };
                }

                // Read folder content (name and files)
                foreach (var folder in folders)
                {
                    byte folderNameLength = reader.ReadByte();
                    folder.Path = Encoding.UTF8.GetString(reader.ReadBytes(folderNameLength - 1));
                    byte zero = reader.ReadByte();

                    folder.Files = new FileInfo[folder.FileCount];
                    for (int i = 0; i < folder.FileCount; i++)
                    {
                        ulong hash = reader.ReadUInt64();
                        uint size = reader.ReadUInt32();

                        bool compressed = flags.HasFlag(ArchiveFlags.DefaultCompressed);
                        if ((size & 0xf0000000) != 0)
                        {
                            size &= 0xfffffff;
                            compressed = !compressed;
                        }

                        uint offset = reader.ReadUInt32();
                        folder.Files[i] = new FileInfo()
                        {
                            Size = size,
                            DataOffset = offset,
                            IsCompressed = compressed
                        };
                    }
                }

                long total = fileCount;
                long loaded = 0;
                string filename = Path.GetFileName(ArchivePath);

                // Read file names
                foreach (var folder in folders)
                {
                    foreach (var file in folder.Files)
                    {
                        file.Filename = reader.ReadStringZeroTerminated();
                        loaded++;
                    }
                }

                // Convert to nested sorted dictionary for fast search
                for (int i = 0; i < folderCount; i++)
                {
                    var files = new SortedDictionary<string, FileInfo>();
                    for (int j = 0; j < folders[i].FileCount; j++)
                    {
                        files.Add(folders[i].Files[j].Filename, folders[i].Files[j]);
                    }
                    sorted.Add(folders[i].Path, files);
                }

                return;
            }
        }
示例#20
0
        protected override void DoOpen()
        {
            using (CustomBinaryReader reader = new CustomBinaryReader(new FileStream(ArchivePath, FileMode.Open, FileAccess.Read)))
            {
                uint signature = reader.ReadUInt32();
                if (signature != 0x415342)
                {
                    throw new InvalidDataException("File is not BSA");
                }

                uint version      = reader.ReadUInt32();
                uint folderOffset = reader.ReadUInt32();
                flags = (ArchiveFlags)reader.ReadUInt32();
                uint folderCount           = reader.ReadUInt32();
                uint fileCount             = reader.ReadUInt32();
                uint totalFolderNameLength = reader.ReadUInt32();
                uint totalFileNameLength   = reader.ReadUInt32();
                uint fileExtensions        = reader.ReadUInt32();

                FolderInfo[] folders = new FolderInfo[(int)folderCount];

                // Read folders
                reader.BaseStream.Position = folderOffset;
                for (int i = 0; i < folderCount; i++)
                {
                    ulong hash    = reader.ReadUInt64();
                    uint  count   = reader.ReadUInt32();
                    uint  unknown = reader.ReadUInt32();
                    ulong offset  = reader.ReadUInt64() - totalFileNameLength;
                    folders[i] = new FolderInfo()
                    {
                        FileCount     = count,
                        ContentOffset = offset
                    };
                }

                // Read folder content (name and files)
                foreach (var folder in folders)
                {
                    byte folderNameLength = reader.ReadByte();
                    folder.Path = Encoding.UTF8.GetString(reader.ReadBytes(folderNameLength - 1));
                    byte zero = reader.ReadByte();

                    folder.Files = new FileInfo[folder.FileCount];
                    for (ulong i = 0; i < folder.FileCount; i++)
                    {
                        ulong hash = reader.ReadUInt64();
                        uint  size = reader.ReadUInt32();

                        bool compressed = flags.HasFlag(ArchiveFlags.DefaultCompressed);
                        if ((size & 0xf0000000) != 0)
                        {
                            size      &= 0xfffffff;
                            compressed = !compressed;
                        }

                        uint offset = reader.ReadUInt32();
                        folder.Files[i] = new FileInfo()
                        {
                            Size         = size,
                            DataOffset   = offset,
                            IsCompressed = compressed
                        };
                    }
                }

                long   total    = fileCount;
                long   loaded   = 0;
                string filename = Path.GetFileName(ArchivePath);

                // Read file names
                foreach (var folder in folders)
                {
                    foreach (var file in folder.Files)
                    {
                        file.Filename = reader.ReadStringZeroTerminated();
                        loaded++;
                    }
                }

                // Convert to nested sorted dictionary for fast search
                for (int i = 0; i < folderCount; i++)
                {
                    var files = new SortedDictionary <string, FileInfo>();
                    for (ulong j = 0; j < folders[i].FileCount; j++)
                    {
                        files.Add(folders[i].Files[j].Filename, folders[i].Files[j]);
                    }
                    sorted.Add(folders[i].Path, files);
                }

                return;
            }
        }
示例#21
0
        public void UploadFile(Address from, string name, BigInteger contentSize, byte[] contentMerkle, ArchiveFlags flags, byte[] key)
        {
            Runtime.Expect(Runtime.IsWitness(from), "invalid witness");
            Runtime.Expect(from.IsUser, "address must be user address");
            Runtime.Expect(contentSize >= DomainSettings.ArchiveMinSize, "file too small");
            Runtime.Expect(contentSize <= DomainSettings.ArchiveMaxSize, "file too big");

            BigInteger requiredSize = CalculateRequiredSize(name, contentSize);

            var usedSize = GetUsedSpace(from);

            var stakedAmount  = Runtime.GetStake(from);
            var availableSize = CalculateStorageSizeForStake(stakedAmount);

            availableSize -= usedSize;
            Runtime.Expect(availableSize >= requiredSize, "account does not have available space");

            var hashes = MerkleTree.FromBytes(contentMerkle);

            Runtime.CreateArchive(from, hashes, contentSize, flags, key);

            var newEntry = new StorageEntry()
            {
                Name = name,
                hash = hashes.Root,
            };

            var list = _storageMap.Get <Address, StorageList>(from);

            list.Add <StorageEntry>(newEntry);

            Runtime.Notify(EventKind.FileCreate, from, name);
        }
示例#22
0
 private bool ArchiveHeaderFlags_HasFlag(ArchiveFlags archiveFlags)
 {
     return ((this.ArchiveHeaderFlags & archiveFlags) == archiveFlags);
 }
 private static bool af_HasFlag(ArchiveFlags archiveFlags, ArchiveFlags archiveFlags2)
 {
     return ((archiveFlags & archiveFlags2) == archiveFlags2);
 }
示例#24
0
文件: IrosArc.cs 项目: rodriada000/7h
        public static void Create(System.IO.Stream output, IEnumerable <ArchiveCreateEntry> files, ArchiveFlags flags, CompressType compress, Action <double, string> onProgress)
        {
            if (!files.Any())
            {
                throw new IrosArcException("Can't create an archive that contains no files");
            }
            var sw = new System.Diagnostics.Stopwatch();

            sw.Start();
            double total = files.Count() + 2;
            int    count = 0;

            onProgress(count / total, "");
            ArcHeader h = new ArcHeader()
            {
                Flags = flags, Version = MAX_VERSION, Directory = 16
            };
            List <DirectoryEntry> entries = files.Select(f => new DirectoryEntry()
            {
                Filename = f.Filename, Flags = 0,
            }).ToList();
            int dsize = entries.Select(e => (int)e.GetSize()).Sum();

            h.Save(output);
            output.WriteInt(entries.Count);
            long position = h.Directory + dsize + 4;

            onProgress(++count / total, "Wrote header");
            int index    = 0;
            var combined = entries.Zip(files, (d, e) => new { Dir = d, ACE = e }).ToList();

            var cw = new CompressWork()
            {
                Input      = new System.Collections.Concurrent.ConcurrentBag <CompressEntry>(),
                Compressed = new System.Collections.Concurrent.BlockingCollection <CompressEntry>(8),
                Compress   = compress
            };

            foreach (var comb in combined)
            {
                cw.Input.Add(new CompressEntry()
                {
                    ACE = comb.ACE, Dir = comb.Dir
                });
            }
            foreach (int _ in Enumerable.Range(0, 8))
            {
                System.Threading.ThreadPool.QueueUserWorkItem(CompressWorkThread, cw);
            }

            int filesDone = 0;

            while (filesDone < combined.Count)
            {
                var entry = cw.Compressed.Take();
                entry.Dir.Offset = position;
                var data = entry.DataRec.Data;
                if (entry.DataRec.Compressed)
                {
                    entry.Dir.Flags |= FileFlags.CompressLZMA;
                }
                entry.Dir.Length = data.Length;

                output.Position = position;
                output.Write(data, 0, data.Length);

                position += entry.Dir.Length;
                onProgress(++count / total, "Written " + entry.ACE.Filename);
                index++;
                filesDone++;
            }

            output.Position = h.Directory + 4;
            foreach (var entry in entries)
            {
                entry.Save(output);
            }
            sw.Stop();
            onProgress(++count / total, String.Format("Complete: {0} files, {1:0.0}MB in {2} seconds", entries.Count, output.Length / (1024f * 1024f), sw.Elapsed.TotalSeconds));
        }
示例#25
0
        /// <summary>
        /// Opens specified archive using the specified mode.  
        /// </summary>
        /// <param name="archivePathName">Path of archive to open</param>
        /// <param name="openMode">Mode in which to open archive</param>
        public void Open(string archivePathName, OpenMode openMode)
        {
            IntPtr handle=IntPtr.Zero;

            // Close any previously open archives
            if(this.archiveHandle!=IntPtr.Zero)
                this.Close();

            // Prepare extended open archive struct
            this.ArchivePathName=archivePathName;
            RAROpenArchiveDataEx openStruct=new RAROpenArchiveDataEx();
            openStruct.Initialize();
            openStruct.ArcName=this.archivePathName+"\0";
            openStruct.ArcNameW=this.archivePathName+"\0";
            openStruct.OpenMode=(uint)openMode;
            if(this.retrieveComment)
            {
                openStruct.CmtBuf=new string((char)0,65536);
                openStruct.CmtBufSize=65536;
            }
            else
            {
                openStruct.CmtBuf=null;
                openStruct.CmtBufSize=0;
            }

            // Open archive
            handle=Unrar.RAROpenArchiveEx(ref openStruct);

            // Check for success
            if(openStruct.OpenResult!=0)
            {
                switch((RarError)openStruct.OpenResult)
                {
                    case RarError.InsufficientMemory:
                        throw new OutOfMemoryException("Insufficient memory to perform operation.");

                    case RarError.BadData:
                        throw new IOException("Archive header broken");

                    case RarError.BadArchive:
                        throw new IOException("File is not a valid archive.");

                    case RarError.OpenError:
                        throw new IOException("File could not be opened.");
                }
            }

            // Save handle and flags
            this.archiveHandle=handle;
            this.archiveFlags=(ArchiveFlags)openStruct.Flags;

            // Set callback
            Unrar.RARSetCallback(this.archiveHandle, this.callback, this.GetHashCode());

            // If comment retrieved, save it
            if(openStruct.CmtState==1)
                this.comment=openStruct.CmtBuf.ToString();

            // If password supplied, set it
            if(this.password.Length!=0)
                Unrar.RARSetPassword(this.archiveHandle, this.password);

            // Fire NewVolume event for first volume
            this.OnNewVolume(this.archivePathName);
        }
示例#26
0
        public static string FlagsToString(this ArchiveFlags flags)
        {
            bool isArchiveRelative = (flags & ArchiveFlags.Absolute) == 0;

            return((isArchiveRelative ? $"{ArchiveFlags.Relative} | " : "") + flags.ToString().Replace(", ", " | "));
        }