Extractor.cs 3.3 KB
Newer Older
1 2 3
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
4 5 6 7

using System;
using System.IO;

8
namespace Microsoft.NET.HostModel.Bundle
9 10 11
{
    /// <summary>
    /// Extractor: The functionality to extract the files embedded 
A
Austin Wise 已提交
12
    /// within a bundle to separate files.
13 14 15 16 17 18
    /// </summary>
    public class Extractor
    {
        string OutputDir;
        string BundlePath;

19 20 21 22
        readonly Trace trace;

        public Extractor(string bundlePath, string outputDir,
                         bool diagnosticOutput = false)
23 24
        {
            BundlePath = bundlePath;
25 26
            OutputDir = Path.GetFullPath(string.IsNullOrEmpty(outputDir) ? Environment.CurrentDirectory : outputDir);
            trace = new Trace(diagnosticOutput);
27 28
        }

29 30 31 32 33 34 35 36
        /// <summary>
        /// Extract all files in the bundle to disk
        /// </summary>
        /// <exceptions>
        /// BundleException if the bundle is invalid or malformed.
        /// IOExceptions and ArgumentExceptions from callees flow to the caller.
        /// </exceptions>
        public void ExtractFiles()
37 38 39
        {
            try
            {
40 41 42
                trace.Log($"Bundler version {Bundler.Version}");
                trace.Log($"Extract from file: {BundlePath}");
                trace.Log($"Output Directory: {OutputDir}");
43 44 45 46 47 48 49

                using (BinaryReader reader = new BinaryReader(File.OpenRead(BundlePath)))
                {
                    Manifest manifest = Manifest.Read(reader);

                    foreach (FileEntry entry in manifest.Files)
                    {
50
                        trace.Log($"Extract: {entry}");
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

                        string fileRelativePath = entry.RelativePath.Replace(Manifest.DirectorySeparatorChar, Path.DirectorySeparatorChar);
                        string filePath = Path.Combine(OutputDir, fileRelativePath);
                        string fileDir = Path.GetDirectoryName(filePath);

                        if ((fileDir != null) && !fileDir.Equals(String.Empty))
                        {
                            Directory.CreateDirectory(fileDir);
                        }

                        reader.BaseStream.Position = entry.Offset;
                        using (BinaryWriter file = new BinaryWriter(File.Create(filePath)))
                        {
                            long size = entry.Size;
                            do
                            {
67
                                int copySize = (int)(size <= int.MaxValue ? size : int.MaxValue);
68 69 70 71 72 73 74
                                file.Write(reader.ReadBytes(copySize));
                                size -= copySize;
                            } while (size > 0);
                        }
                    }
                }
            }
75
            catch (EndOfStreamException)
76
            {
77
                // Trying to read non-existant bits in the bundle
78 79 80 81 82 83 84 85 86 87 88
                throw new BundleException("Malformed Bundle");
            }
            catch (ArgumentOutOfRangeException)
            {
                // Trying to set file-stream position to an invalid value
                throw new BundleException("Malformed Bundle");
            }
        }
    }
}