Exemple #1
0
        /// <summary>
        /// Reads an archive file from a given filepath
        /// </summary>
        /// <param name="path"></param>
        /// <param name="hashService"></param>
        /// <returns></returns>
        public static Archive ReadArchive(string path, IHashService hashService)
        {
            var mapName = "ReadArchive_Map";

            var ar = new Archive()
            {
                ArchiveAbsolutePath = path
            };

            using var fs  = new FileStream(ar.ArchiveAbsolutePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
            using var mmf = MemoryMappedFileExtensions.GetMemoryMappedFile(fs, mapName);

            // read header
            uint customDataLength;

            using (var vs = mmf.CreateViewStream(0, Header.EXTENDED_SIZE, MemoryMappedFileAccess.Read))
                using (var br = new BinaryReader(vs))
                {
                    ar.Header        = ReadHeader(br);
                    customDataLength = br.ReadUInt32();
                }

            // read custom
            try
            {
                if (customDataLength != 0)
                {
                    using var vs = mmf.CreateViewStream(Header.EXTENDED_SIZE, customDataLength, MemoryMappedFileAccess.Read);
                    using var br = new BinaryReader(vs);
                    if (br.BaseStream.Length >= LxrsFooter.MIN_LENGTH)
                    {
                        var lxrs = br.ReadLxrsFooter();
                        foreach (var s in lxrs.FileInfos)
                        {
                            hashService.AddCustom(s);
                        }
                    }
                }
            }
            catch (UnauthorizedAccessException)
            {
                //Console.WriteLine(e);
            }

            // read files
            using (var vs = mmf.CreateViewStream((long)ar.Header.IndexPosition, ar.Header.IndexSize,
                                                 MemoryMappedFileAccess.Read))
                using (var br = new BinaryReader(vs))
                {
                    ar.Index = ReadIndex(br, hashService);
                }

            foreach (var file in ar.Index.FileEntries.Values)
            {
                file.Archive = ar;
                ar.Files.Add(file.Key, file);
            }

            return(ar);
        }
Exemple #2
0
        /// <summary>
        /// Extracts all files from an archive to a specified directory.
        /// </summary>
        /// <param name="ar"></param>
        /// <param name="outDir"></param>
        /// <param name="pattern"></param>
        /// <param name="regex"></param>
        /// <param name="decompressBuffers"></param>
        /// <returns></returns>
        public void ExtractAll(Archive ar, DirectoryInfo outDir, string pattern = "", string regex = "", bool decompressBuffers = false)
        {
            var extractedList = new ConcurrentBag <string>();
            var failedList    = new ConcurrentBag <string>();

            var mapName = "ExtractAll_Map";

            // check search pattern then regex
            var finalmatches        = ar.Files.Values.Cast <FileEntry>();
            var totalInArchiveCount = ar.FileCount;

            if (!string.IsNullOrEmpty(pattern))
            {
                finalmatches = ar.Files.Values.Cast <FileEntry>().MatchesWildcard(item => item.FileName, pattern);
            }

            if (!string.IsNullOrEmpty(regex))
            {
                var searchTerm         = new System.Text.RegularExpressions.Regex($@"{regex}");
                var queryMatchingFiles =
                    from file in finalmatches
                    let matches = searchTerm.Matches(file.FileName)
                                  where matches.Count > 0
                                  select file;

                finalmatches = queryMatchingFiles;
            }

            var finalMatchesList = finalmatches.ToList();

            _loggerService.Info($"{ar.ArchiveAbsolutePath}: Found {finalMatchesList.Count}/{totalInArchiveCount} entries to extract.");
            if (finalMatchesList.Count == 0)
            {
                return;
            }

            using var fs  = new FileStream(ar.ArchiveAbsolutePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
            using var mmf = MemoryMappedFileExtensions.GetMemoryMappedFile(fs, mapName);

            var progress = 0;

            // check hashes before parallel unbundling
            for (var i = 0; i < finalMatchesList.Count; i++)
            {
                var item = finalMatchesList[i];
                _hashService.Contains(item.Key);
            }


            Parallel.ForEach(finalMatchesList, info =>
            {
                var extracted = ExtractSingle(ar, info.NameHash64, outDir, decompressBuffers, mmf);

                if (extracted != 0)
                {
                    extractedList.Add(info.FileName);
                }
                else
                {
                    failedList.Add(info.FileName);
                }

                Interlocked.Increment(ref progress);
                _progressService.Report(progress / (float)finalMatchesList.Count);
            });

            //logging
            var msg = $"{ar.ArchiveAbsolutePath}: Unbundled {extractedList.Count}/{finalMatchesList.Count} entries.";

            if (extractedList.Count == finalMatchesList.Count)
            {
                _loggerService.Success(msg);
            }
            else
            {
                _loggerService.Info(msg);
            }
        }