internal GZipWritableArchiveEntry(GZipArchive archive, Stream stream, string path, long size, DateTime? lastModified, bool closeStream)
     : base(archive, null)
 {
     this.stream = stream;
     this.path = path;
     this.size = size;
     this.lastModified = lastModified;
     this.closeStream = closeStream;
 }
 internal GZipWritableArchiveEntry(int index, GZipArchive archive, Stream stream,
     string path, long size, DateTime? lastModified)
     : base(index, archive, null)
 {
     this.Stream = stream;
     this.path = path;
     this.size = size;
     this.lastModified = lastModified;
 }
 internal GZipArchiveEntry(GZipArchive archive, GZipFilePart part)
     : base(part)
 {
     this.archive = archive;
 }
Exemple #4
0
        /// <summary>
        /// Process the DAT and find all matches in input files and folders assuming they're a depot
        /// </summary>
        /// <param name="datFile">Current DatFile object to rebuild from</param>
        /// <param name="inputs">List of input files/folders to check</param>
        /// <param name="outDir">Output directory to use to build to</param>
        /// <param name="date">True if the date from the DAT should be used if available, false otherwise</param>
        /// <param name="delete">True if input files should be deleted, false otherwise</param>
        /// <param name="inverse">True if the DAT should be used as a filter instead of a template, false otherwise</param>
        /// <param name="outputFormat">Output format that files should be written to</param>
        /// <returns>True if rebuilding was a success, false otherwise</returns>
        public static bool RebuildDepot(
            DatFile datFile,
            List <string> inputs,
            string outDir,
            bool date    = false,
            bool delete  = false,
            bool inverse = false,
            OutputFormat outputFormat = OutputFormat.Folder)
        {
            #region Perform setup

            // If the DAT is not populated and inverse is not set, inform the user and quit
            if (datFile.Items.TotalCount == 0 && !inverse)
            {
                logger.User("No entries were found to rebuild, exiting...");
                return(false);
            }

            // Check that the output directory exists
            outDir = outDir.Ensure(create: true);

            // Now we want to get forcepack flag if it's not overridden
            if (outputFormat == OutputFormat.Folder && datFile.Header.ForcePacking != PackingFlag.None)
            {
                outputFormat = GetOutputFormat(datFile.Header.ForcePacking);
            }

            #endregion

            bool success = true;

            #region Rebuild from depots in order

            string            format = FromOutputFormat(outputFormat) ?? string.Empty;
            InternalStopwatch watch  = new InternalStopwatch($"Rebuilding all files to {format}");

            // Now loop through and get only directories from the input paths
            List <string> directories = new List <string>();
            Parallel.ForEach(inputs, Globals.ParallelOptions, input =>
            {
                // Add to the list if the input is a directory
                if (Directory.Exists(input))
                {
                    logger.Verbose($"Adding depot: {input}");
                    lock (directories)
                    {
                        directories.Add(input);
                    }
                }
            });

            // If we don't have any directories, we want to exit
            if (directories.Count == 0)
            {
                return(success);
            }

            // Now that we have a list of depots, we want to bucket the input DAT by SHA-1
            datFile.Items.BucketBy(ItemKey.SHA1, DedupeType.None);

            // Then we want to loop through each of the hashes and see if we can rebuild
            var keys = datFile.Items.SortedKeys.ToList();
            foreach (string hash in keys)
            {
                // Pre-empt any issues that could arise from string length
                if (hash.Length != Constants.SHA1Length)
                {
                    continue;
                }

                logger.User($"Checking hash '{hash}'");

                // Get the extension path for the hash
                string subpath = Utilities.GetDepotPath(hash, datFile.Header.InputDepot.Depth);

                // Find the first depot that includes the hash
                string foundpath = null;
                foreach (string directory in directories)
                {
                    if (File.Exists(Path.Combine(directory, subpath)))
                    {
                        foundpath = Path.Combine(directory, subpath);
                        break;
                    }
                }

                // If we didn't find a path, then we continue
                if (foundpath == null)
                {
                    continue;
                }

                // If we have a path, we want to try to get the rom information
                GZipArchive archive  = new GZipArchive(foundpath);
                BaseFile    fileinfo = archive.GetTorrentGZFileInfo();

                // If the file information is null, then we continue
                if (fileinfo == null)
                {
                    continue;
                }

                // Ensure we are sorted correctly (some other calls can change this)
                datFile.Items.BucketBy(ItemKey.SHA1, DedupeType.None);

                // If there are no items in the hash, we continue
                if (datFile.Items[hash] == null || datFile.Items[hash].Count == 0)
                {
                    continue;
                }

                // Otherwise, we rebuild that file to all locations that we need to
                bool usedInternally;
                if (datFile.Items[hash][0].ItemType == ItemType.Disk)
                {
                    usedInternally = RebuildIndividualFile(datFile, new Disk(fileinfo), foundpath, outDir, date, inverse, outputFormat, false /* isZip */);
                }
                else if (datFile.Items[hash][0].ItemType == ItemType.Media)
                {
                    usedInternally = RebuildIndividualFile(datFile, new Media(fileinfo), foundpath, outDir, date, inverse, outputFormat, false /* isZip */);
                }
                else
                {
                    usedInternally = RebuildIndividualFile(datFile, new Rom(fileinfo), foundpath, outDir, date, inverse, outputFormat, false /* isZip */);
                }

                // If we are supposed to delete the depot file, do so
                if (delete && usedInternally)
                {
                    File.Delete(foundpath);
                }
            }

            watch.Stop();

            #endregion

            return(success);
        }
Exemple #5
0
        /// <summary>
        /// Opens a Reader for Non-seeking usage
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public static IReader Open(Stream stream, ReaderOptions options = null)
        {
            stream.CheckNotNull(nameof(stream));
            options = options ?? new ReaderOptions()
            {
                LeaveStreamOpen = false
            };
            RewindableStream rewindableStream = new RewindableStream(stream);

            rewindableStream.StartRecording();
            if (ZipArchive.IsZipFile(rewindableStream, options.Password))
            {
                rewindableStream.Rewind(true);
                return(ZipReader.Open(rewindableStream, options));
            }
            rewindableStream.Rewind(false);
            if (GZipArchive.IsGZipFile(rewindableStream))
            {
                rewindableStream.Rewind(false);
                GZipStream testStream = new GZipStream(rewindableStream, CompressionMode.Decompress);
                if (TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    return(new TarReader(rewindableStream, options, CompressionType.GZip));
                }
                rewindableStream.Rewind(true);
                return(GZipReader.Open(rewindableStream, options));
            }

            rewindableStream.Rewind(false);
            if (BZip2Stream.IsBZip2(rewindableStream))
            {
                rewindableStream.Rewind(false);
                BZip2Stream testStream = new BZip2Stream(new NonDisposingStream(rewindableStream), CompressionMode.Decompress, false);
                if (TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    return(new TarReader(rewindableStream, options, CompressionType.BZip2));
                }
            }

            rewindableStream.Rewind(false);
            if (LZipStream.IsLZipFile(rewindableStream))
            {
                rewindableStream.Rewind(false);
                LZipStream testStream = new LZipStream(new NonDisposingStream(rewindableStream), CompressionMode.Decompress);
                if (TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    return(new TarReader(rewindableStream, options, CompressionType.LZip));
                }
            }
            rewindableStream.Rewind(false);
            if (RarArchive.IsRarFile(rewindableStream, options))
            {
                rewindableStream.Rewind(true);
                return(RarReader.Open(rewindableStream, options));
            }

            rewindableStream.Rewind(false);
            if (TarArchive.IsTarFile(rewindableStream))
            {
                rewindableStream.Rewind(true);
                return(TarReader.Open(rewindableStream, options));
            }
            rewindableStream.Rewind(false);
            if (XZStream.IsXZStream(rewindableStream))
            {
                rewindableStream.Rewind(true);
                XZStream testStream = new XZStream(rewindableStream);
                if (TarArchive.IsTarFile(testStream))
                {
                    rewindableStream.Rewind(true);
                    return(new TarReader(rewindableStream, options, CompressionType.Xz));
                }
            }
            throw new InvalidOperationException("Cannot determine compressed stream type.  Supported Reader Formats: Zip, GZip, BZip2, Tar, Rar, LZip, XZ");
        }
Exemple #6
0
        /// <summary>
        /// Attempt to add a file to the output if it matches
        /// </summary>
        /// <param name="datFile">Current DatFile object to rebuild from</param>
        /// <param name="file">Name of the file to process</param>
        /// <param name="outDir">Output directory to use to build to</param>
        /// <param name="quickScan">True to enable external scanning of archives, false otherwise</param>
        /// <param name="date">True if the date from the DAT should be used if available, false otherwise</param>
        /// <param name="inverse">True if the DAT should be used as a filter instead of a template, false otherwise</param>
        /// <param name="outputFormat">Output format that files should be written to</param>
        /// <param name="asFiles">TreatAsFiles representing special format scanning</param>
        /// <returns>True if the file was used to rebuild, false otherwise</returns>
        private static bool RebuildGenericHelper(
            DatFile datFile,
            string file,
            string outDir,
            bool quickScan,
            bool date,
            bool inverse,
            OutputFormat outputFormat,
            TreatAsFile asFiles)
        {
            // If we somehow have a null filename, return
            if (file == null)
            {
                return(false);
            }

            // Set the deletion variables
            bool usedExternally = false, usedInternally = false;

            // Create an empty list of BaseFile for archive entries
            List <BaseFile> entries = null;

            // Get the TGZ and TXZ status for later
            GZipArchive tgz             = new GZipArchive(file);
            XZArchive   txz             = new XZArchive(file);
            bool        isSingleTorrent = tgz.IsTorrent() || txz.IsTorrent();

            // Get the base archive first
            BaseArchive archive = BaseArchive.Create(file);

            // Now get all extracted items from the archive
            if (archive != null)
            {
                archive.AvailableHashes = quickScan ? Hash.CRC : Hash.Standard;
                entries = archive.GetChildren();
            }

            // If the entries list is null, we encountered an error or have a file and should scan externally
            if (entries == null && File.Exists(file))
            {
                BaseFile internalFileInfo = BaseFile.GetInfo(file, asFiles: asFiles);

                // Create the correct DatItem
                DatItem internalDatItem;
                if (internalFileInfo.Type == FileType.AaruFormat && !asFiles.HasFlag(TreatAsFile.AaruFormat))
                {
                    internalDatItem = new Media(internalFileInfo);
                }
                else if (internalFileInfo.Type == FileType.CHD && !asFiles.HasFlag(TreatAsFile.CHD))
                {
                    internalDatItem = new Disk(internalFileInfo);
                }
                else
                {
                    internalDatItem = new Rom(internalFileInfo);
                }

                usedExternally = RebuildIndividualFile(datFile, internalDatItem, file, outDir, date, inverse, outputFormat);
            }
            // Otherwise, loop through the entries and try to match
            else
            {
                foreach (BaseFile entry in entries)
                {
                    DatItem internalDatItem = DatItem.Create(entry);
                    usedInternally |= RebuildIndividualFile(datFile, internalDatItem, file, outDir, date, inverse, outputFormat, !isSingleTorrent /* isZip */);
                }
            }

            return(usedExternally || usedInternally);
        }
 private static void TryUnpackArchive(IAbsoluteFilePath destFile, ITProgress progress, GZipArchive archive) {
     destFile.RemoveReadonlyWhenExists();
     var entry = archive.Entries.First();
     if (progress != null) {
         var startTime = DateTime.UtcNow;
         archive.CompressedBytesRead += (sender, args) => {
             double prog = args.CompressedBytesRead/(float) archive.TotalSize;
             if (prog > 1)
                 prog = 1;
             var totalMilliseconds = (DateTime.UtcNow - startTime).TotalMilliseconds;
             progress.Update(
                 totalMilliseconds > 0 ? (long?) (args.CompressedBytesRead/(totalMilliseconds/1000.0)) : null,
                 prog*100);
         };
     }
     entry.WriteToFile(destFile.ToString());
     progress?.Update(null, 100);
 }
Exemple #8
0
 public static bool isArchive(FileInfo file)
 {
     //FIXME This is broken and detects .gba ROMs as stuff
     return(GZipArchive.IsGZipFile(file) || RarArchive.IsRarFile(file) || SevenZipArchive.IsSevenZipFile(file) ||
            TarArchive.IsTarFile(file) || ZipArchive.IsZipFile(file));
 }
        private static void TryUnpackArchive(IAbsoluteFilePath destFile, ITProgress progress, GZipArchive archive)
        {
            destFile.RemoveReadonlyWhenExists();
            var entry = archive.Entries.First();

            if (progress != null)
            {
                var startTime = DateTime.UtcNow;
                archive.CompressedBytesRead += (sender, args) => {
                    double prog = args.CompressedBytesRead / (float)archive.TotalSize;
                    if (prog > 1)
                    {
                        prog = 1;
                    }
                    var totalMilliseconds = (DateTime.UtcNow - startTime).TotalMilliseconds;
                    progress.Update(
                        totalMilliseconds > 0 ? (long?)(args.CompressedBytesRead / (totalMilliseconds / 1000.0)) : null,
                        prog * 100);
                };
            }
            entry.WriteToFile(destFile.ToString());
            progress?.Update(null, 100);
        }
 private IArchive GetArchiveWithGzWorkaround(IAbsoluteFilePath sourceFile, string ext)
 => ext.Equals(".gz", StringComparison.OrdinalIgnoreCase)
         ? GZipArchive.Open(sourceFile.ToString())
         : ArchiveFactory.Open(sourceFile.ToString());