public void ArcEntryTypesAreAllKnown()
        {
            var gdInstallPath = FindGrimDawnInstallPath();

            #if DEBUG
            Debug.WriteLine("GD install path: " + gdInstallPath, TestContext.TestName);
            #endif

            // Pass the test if it can't find the install location
            if (gdInstallPath == null)
                return;

            foreach (var file in Directory.GetFiles(Path.Combine(gdInstallPath, "resources"), "*.arc")) {
            #if DEBUG
                Debug.WriteLine(string.Format("Checking {0} ...", file), TestContext.TestName);
            #endif
                using (var arc = new Arc(new FileStream(file, FileMode.Open, FileAccess.Read))) {
                    foreach (var entry in arc.Entries) {
            #if DEBUG
                        Debug.WriteLine(entry.Path);
                        Debug.WriteLine("  StorageMode: " + entry.StorageMode.ToString());
                        Debug.WriteLine("  CompressedSize: " + entry.CompressedSize);
                        Debug.WriteLine("  PlainSize: " + entry.PlainSize);
                        Debug.WriteLine("  Adler32: " + entry.Adler32);
                        Debug.WriteLine("  LastWriteTime: " + entry.LastWriteTime);
                        Debug.WriteLine("");
            #endif
                        Assert.IsTrue(Enum.IsDefined(typeof(StorageMode), entry.StorageMode));
                    }
                }
            }
        }
        public void ExistingArc()
        {
            var testArcPath = CopyArcFile();

            if (testArcPath == null)
                return;

            int finalEntryCount;

            using (var questsArc = new Arc(new FileStream(testArcPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))) {
                var initialEntryCount = questsArc.Entries.Count;

                Assert.IsTrue(initialEntryCount > 0);
            #if DEBUG
                Debug.WriteLine("Entry count: " + questsArc.Entries.Count, TestContext.TestName);
            #endif
                var entry = questsArc.Entries[0];

                var data = questsArc.ReadEntry(entry);
                Assert.IsTrue(data.Length == entry.PlainSize);
            #if DEBUG
                Debug.WriteLine("Entry size: " + data.Length);
                Debug.WriteLine("Entry path: " + entry.Path);
            #endif
                var sum = Arc.Checksum(data);

                Assert.IsTrue(sum == entry.Adler32);
            #if DEBUG
                Debug.WriteLine("Entry checksum: " + entry.Adler32);
            #endif
                questsArc.MoveEntry(entry, @"/new/location.ext");
                Assert.IsTrue(entry.Path == @"new/location.ext");

                questsArc.DeleteEntry(entry);

                try {
                    var shouldThrowCauseDisposed = entry.PlainSize;

                    Assert.Fail();
                }
                catch (ObjectDisposedException)
                { }

                var entry2 = questsArc.CreateEntry(@"/p**n.stash", data, StorageMode.Lz4Compressed);
                Assert.IsTrue(entry2.Adler32 == sum);

                finalEntryCount = questsArc.Entries.Count;
                Assert.IsTrue(finalEntryCount == initialEntryCount);
            }

            // Reopen the file to see if it's still valid
            using (var questsArc = new Arc(new FileStream(testArcPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))) {
                Assert.IsTrue(questsArc.Entries.Count == finalEntryCount);

                var entry = questsArc.Entries[0];

                var data = questsArc.ReadEntry(entry);
                Assert.IsTrue(Arc.Checksum(data) == entry.Adler32);
            }
        }
        private bool disposedValue = false; // To detect redundant calls

        #endregion Fields

        #region Constructors

        internal ArcEntry(Arc parent, ArcStruct.Entry entryStruct, string entryPath, ArcStruct.Chunk[] chunks)
        {
            ParentArc = parent;
            EntryStruct = entryStruct;
            EntryPath = entryPath;
            LastWrite = DateTime.FromFileTime((long)EntryStruct.FileTime);
            Chunks = chunks;
        }
        private void CloseFile()
        {
            if (_arc != null) {
                lock (_arc) {
                    _arc.Dispose();
                    _arc = null;
                }
            }

            if (_arz != null) {
                lock (_arz) {
                    _arz.Dispose();
                    _arz = null;
                }
            }

            _openFilePath = null;
            _mode = Mode.None;
            entryTree.Nodes.Clear();
            closeToolStripMenuItem.Enabled = false;
            extractSelectedToolStripMenuItem.Enabled = false;
            extractAllToolStripMenuItem.Enabled = false;
            renameToolStripMenuItem.Enabled = false;
            entrySizeLabel.Text = "";
            entryStorageLabel.Text = "";
            entryFiletimeLabel.Text = "";
            entryChecksumLabel.Text = "";
            Text = Properties.Resources.STR_TITLE;
        }
        private void ChooseAndOpenFile(object sender, EventArgs e)
        {
            fileSelect.Title = "Open ARC file";
            if (fileSelect.ShowDialog() != DialogResult.OK)
                return;

            CloseFile();
            _mode = Mode.None;
            Status = Action.Loading;

            try {
                _arc = new Arc(new FileStream(
                    fileSelect.FileName,
                    FileMode.Open, fileSelect.ReadOnlyChecked ? FileAccess.Read : FileAccess.ReadWrite,
                    FileShare.None
                ), false, Properties.Settings.Default.MaxAlloc);
            }
            catch (Exception exc) {
            #if DEBUG
                throw exc;
            #endif
                CloseFile();

                MessageBox.Show(
                    string.Format(
                        exc is InvalidDataException ?
                            "The file \"{0}\" is not valid." : "The file \"{0}\" could not be opened."
                        , fileSelect.FileName),
                    "", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }
            finally {
                Status = Action.Idle;
            }

            _mode = Mode.Arc;
            _openFilePath = fileSelect.FileName;

            _arc.Entries.All(x => {
                AddPathToTree(entryTree.Nodes, x.Path);
                return true;
            });
            entryTree.Sort();

            Text = string.Format(Properties.Resources.STR_FMT_TITLE_OPENED, Path.GetFileName(_openFilePath));
            closeToolStripMenuItem.Enabled = true;
            extractSelectedToolStripMenuItem.Enabled = true;
            extractAllToolStripMenuItem.Enabled = true;
            renameToolStripMenuItem.Enabled = true;

            Status = Action.Idle;
        }
 // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
 // ~ArcEntry() {
 //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
 //   Dispose(false);
 // }
 // This code added to correctly implement the disposable pattern.
 internal void Dispose(Arc parent)
 {
     // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
     Dispose(true);
     // TODO: uncomment the following line if the finalizer is overridden above.
     // GC.SuppressFinalize(this);
 }