From 170467031d2f1380c128dc495253dc1cb16826cb Mon Sep 17 00:00:00 2001 From: Hajin Jang Date: Sun, 20 Oct 2019 23:49:30 +0900 Subject: [PATCH 1/3] Update docs --- ManagedWimLib/ManagedWimLib.csproj | 5 +++-- README.md | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ManagedWimLib/ManagedWimLib.csproj b/ManagedWimLib/ManagedWimLib.csproj index 0a37c34..d8606cc 100644 --- a/ManagedWimLib/ManagedWimLib.csproj +++ b/ManagedWimLib/ManagedWimLib.csproj @@ -23,13 +23,14 @@ Supports Windows, Linux and macOS. + - + - + diff --git a/README.md b/README.md index 61d8419..077350a 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,8 @@ If you need .Net Standard 1.3 support, use [1.2.x version](https://www.nuget.org | Architecture | Distribution | Note | |--------------|--------------|------| | x64 | Ubuntu 18.04 | Tested on AppVeyor CI | -| armhf | Debian 9 | Emulated on QEMU's virt board | -| arm64 | Debian 9 | Emulated on QEMU's virt board | +| armhf | Debian 10 | Emulated on QEMU's virt board | +| arm64 | Debian 10 | Emulated on QEMU's virt board | ### Supported wimlib version From 7492a1a7c81e69e7151e7d71b3a6bdad14e997d3 Mon Sep 17 00:00:00 2001 From: Hajin Jang Date: Mon, 21 Oct 2019 01:33:20 +0900 Subject: [PATCH 2/3] Fix error message query methods regression - Fix Wim.GetErrors(), Wim.GetLastError() regression - Fix Wim.RootPath, Wim.PathSeparator regression - Error print state is now readable from Wim.ErrorPrintState --- ManagedWimLib.Tests/AddTests.cs | 2 +- ManagedWimLib.Tests/DeleteTests.cs | 2 +- ManagedWimLib.Tests/ErrorTests.cs | 142 +++++++++++++++++++ ManagedWimLib.Tests/ExportTests.cs | 2 +- ManagedWimLib.Tests/ExtractTests.cs | 2 +- ManagedWimLib.Tests/GetInfoTests.cs | 2 +- ManagedWimLib.Tests/GetVersionTests.cs | 2 +- ManagedWimLib.Tests/IterateTests.cs | 6 +- ManagedWimLib.Tests/JoinTests.cs | 2 +- ManagedWimLib.Tests/ReferenceTests.cs | 4 +- ManagedWimLib.Tests/RenameTests.cs | 2 +- ManagedWimLib.Tests/SetInfoTests.cs | 2 +- ManagedWimLib.Tests/SetOutputTests.cs | 2 +- ManagedWimLib.Tests/SplitTests.cs | 4 +- ManagedWimLib.Tests/TestSetup.cs | 15 +-- ManagedWimLib.Tests/UpdateTests.cs | 10 +- ManagedWimLib.Tests/VerifyTests.cs | 2 +- ManagedWimLib/ManagedWimLib.csproj | 8 +- ManagedWimLib/WimLibLoader.cs | 180 +++++++++++++++++++++++-- ManagedWimLib/WimStruct.cs | 97 +++++++------ 20 files changed, 399 insertions(+), 89 deletions(-) create mode 100644 ManagedWimLib.Tests/ErrorTests.cs diff --git a/ManagedWimLib.Tests/AddTests.cs b/ManagedWimLib.Tests/AddTests.cs index f4277c1..5640b1c 100644 --- a/ManagedWimLib.Tests/AddTests.cs +++ b/ManagedWimLib.Tests/AddTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib.Tests/DeleteTests.cs b/ManagedWimLib.Tests/DeleteTests.cs index fc63b10..9d30165 100644 --- a/ManagedWimLib.Tests/DeleteTests.cs +++ b/ManagedWimLib.Tests/DeleteTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib.Tests/ErrorTests.cs b/ManagedWimLib.Tests/ErrorTests.cs new file mode 100644 index 0000000..144d722 --- /dev/null +++ b/ManagedWimLib.Tests/ErrorTests.cs @@ -0,0 +1,142 @@ +/* + Licensed under LGPLv3 + + Derived from wimlib's original header files + Copyright (C) 2012-2018 Eric Biggers + + C# Wrapper written by Hajin Jang + Copyright (C) 2019 Hajin Jang + + This file is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your option) any + later version. + + This file is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License + along with this file; if not, see http://www.gnu.org/licenses/. +*/ + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.IO; +using System.Linq; + + +namespace ManagedWimLib.Tests +{ + [TestClass] + [TestCategory("WimLib")] + public class ErrorTests + { + [TestMethod] + public void GetLastError() + { + string[] paths = new string[] { @"\NOTEXIST.bin", @"NOTGLOB?.cue" }; + CheckErrorTemplate("XPRESS.wim", paths); + CheckErrorTemplate("XPRESS.wim", paths); + } + + public void CheckErrorTemplate(string fileName, string[] paths) + { + string destDir = TestHelper.GetTempDir(); + try + { + Directory.CreateDirectory(destDir); + + bool[] _checked = new bool[5]; + for (int i = 0; i < _checked.Length; i++) + _checked[i] = false; + CallbackStatus ProgressCallback(ProgressMsg msg, object info, object progctx) + { + switch (msg) + { + case ProgressMsg.EXTRACT_TREE_BEGIN: + { + ProgressInfo_Extract m = (ProgressInfo_Extract)info; + Assert.IsNotNull(m); + + _checked[0] = true; + } + break; + case ProgressMsg.EXTRACT_TREE_END: + { + ProgressInfo_Extract m = (ProgressInfo_Extract)info; + Assert.IsNotNull(m); + + _checked[1] = true; + } + break; + case ProgressMsg.EXTRACT_FILE_STRUCTURE: + { + ProgressInfo_Extract m = (ProgressInfo_Extract)info; + Assert.IsNotNull(m); + + _checked[2] = true; + } + break; + case ProgressMsg.EXTRACT_STREAMS: + { + ProgressInfo_Extract m = (ProgressInfo_Extract)info; + Assert.IsNotNull(m); + + _checked[3] = true; + } + break; + case ProgressMsg.EXTRACT_METADATA: + { + ProgressInfo_Extract m = (ProgressInfo_Extract)info; + Assert.IsNotNull(m); + + _checked[4] = true; + } + break; + } + return CallbackStatus.CONTINUE; + } + + string wimFile = Path.Combine(TestSetup.SampleDir, fileName); + using (Wim wim = Wim.OpenWim(wimFile, OpenFlags.DEFAULT)) + { + wim.RegisterCallback(ProgressCallback); + + wim.ExtractPaths(1, destDir, paths, ExtractFlags.GLOB_PATHS); + } + + // The callback must not have been called + Assert.IsFalse(_checked.Any(x => x)); + + // The files must not exist + foreach (string path in paths.Select(x => TestHelper.NormalizePath(x.TrimStart('\\')))) + { + if (path.IndexOfAny(new char[] { '*', '?' }) == -1) + { // No wlidcard + Assert.IsFalse(File.Exists(Path.Combine(destDir, path))); + } + else + { // With wildcard + string destFullPath = Path.Combine(destDir, path); + string[] files = Directory.GetFiles(Path.GetDirectoryName(destFullPath), Path.GetFileName(destFullPath), SearchOption.AllDirectories); + Assert.IsFalse(0 < files.Length); + } + } + + // Read error message + string[] errorMsgs = Wim.GetErrors(); + Assert.IsNotNull(errorMsgs); + Assert.IsTrue(0 < errorMsgs.Length); + foreach (string errorMsg in errorMsgs) + Console.WriteLine(errorMsg); + } + finally + { + if (Directory.Exists(destDir)) + Directory.Delete(destDir, true); + } + } + } +} diff --git a/ManagedWimLib.Tests/ExportTests.cs b/ManagedWimLib.Tests/ExportTests.cs index 59a68a2..b6b2c8f 100644 --- a/ManagedWimLib.Tests/ExportTests.cs +++ b/ManagedWimLib.Tests/ExportTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib.Tests/ExtractTests.cs b/ManagedWimLib.Tests/ExtractTests.cs index d08b0a3..768eeda 100644 --- a/ManagedWimLib.Tests/ExtractTests.cs +++ b/ManagedWimLib.Tests/ExtractTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib.Tests/GetInfoTests.cs b/ManagedWimLib.Tests/GetInfoTests.cs index 3bffe4b..c249b8e 100644 --- a/ManagedWimLib.Tests/GetInfoTests.cs +++ b/ManagedWimLib.Tests/GetInfoTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib.Tests/GetVersionTests.cs b/ManagedWimLib.Tests/GetVersionTests.cs index bc798fa..f41d622 100644 --- a/ManagedWimLib.Tests/GetVersionTests.cs +++ b/ManagedWimLib.Tests/GetVersionTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib.Tests/IterateTests.cs b/ManagedWimLib.Tests/IterateTests.cs index 7c11a6a..138112c 100644 --- a/ManagedWimLib.Tests/IterateTests.cs +++ b/ManagedWimLib.Tests/IterateTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free @@ -29,11 +29,11 @@ You should have received a copy of the GNU Lesser General Public License namespace ManagedWimLib.Tests { [TestClass] + [TestCategory("WimLib")] public class IterateTests { #region IterateDirTree [TestMethod] - [TestCategory("WimLib")] public void IterateDirTree() { IterateDirTree_Template("XPRESS.wim"); @@ -57,7 +57,7 @@ CallbackStatus IterateCallback(DirEntry dentry, object userData) string wimFile = Path.Combine(TestSetup.SampleDir, wimFileName); using (Wim wim = Wim.OpenWim(wimFile, OpenFlags.DEFAULT)) { - wim.IterateDirTree(1, TestHelper.RootPath, IterateFlags.RECURSIVE, IterateCallback); + wim.IterateDirTree(1, Wim.RootPath, IterateFlags.RECURSIVE, IterateCallback); } TestHelper.CheckPathList(SampleSet.Src01, entries); diff --git a/ManagedWimLib.Tests/JoinTests.cs b/ManagedWimLib.Tests/JoinTests.cs index c393856..58e1bf9 100644 --- a/ManagedWimLib.Tests/JoinTests.cs +++ b/ManagedWimLib.Tests/JoinTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib.Tests/ReferenceTests.cs b/ManagedWimLib.Tests/ReferenceTests.cs index 0757fbc..73438fc 100644 --- a/ManagedWimLib.Tests/ReferenceTests.cs +++ b/ManagedWimLib.Tests/ReferenceTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free @@ -78,7 +78,7 @@ CallbackStatus IterateCallback(DirEntry dentry, object userData) string wimFile = Path.Combine(TestSetup.SampleDir, wimFileName); using (Wim wim = Wim.OpenWim(destWimFile, OpenFlags.DEFAULT)) { - wim.IterateDirTree(imageCount + 1, TestHelper.RootPath, IterateFlags.RECURSIVE, IterateCallback); + wim.IterateDirTree(imageCount + 1, Wim.RootPath, IterateFlags.RECURSIVE, IterateCallback); } TestHelper.CheckPathList(set, entries); diff --git a/ManagedWimLib.Tests/RenameTests.cs b/ManagedWimLib.Tests/RenameTests.cs index bc2c448..ed01476 100644 --- a/ManagedWimLib.Tests/RenameTests.cs +++ b/ManagedWimLib.Tests/RenameTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib.Tests/SetInfoTests.cs b/ManagedWimLib.Tests/SetInfoTests.cs index 5a27102..f0012e2 100644 --- a/ManagedWimLib.Tests/SetInfoTests.cs +++ b/ManagedWimLib.Tests/SetInfoTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib.Tests/SetOutputTests.cs b/ManagedWimLib.Tests/SetOutputTests.cs index 3b2cef4..e7e37ec 100644 --- a/ManagedWimLib.Tests/SetOutputTests.cs +++ b/ManagedWimLib.Tests/SetOutputTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib.Tests/SplitTests.cs b/ManagedWimLib.Tests/SplitTests.cs index 90cb01b..b5d12b7 100644 --- a/ManagedWimLib.Tests/SplitTests.cs +++ b/ManagedWimLib.Tests/SplitTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free @@ -111,7 +111,7 @@ CallbackStatus IterateCallback(DirEntry dentry, object userData) WimInfo wi = wim.GetWimInfo(); Assert.IsTrue(wi.ImageCount == 1); - wim.IterateDirTree(1, TestHelper.RootPath, IterateFlags.RECURSIVE, IterateCallback); + wim.IterateDirTree(1, Wim.RootPath, IterateFlags.RECURSIVE, IterateCallback); } TestHelper.CheckPathList(SampleSet.Src03, entries); diff --git a/ManagedWimLib.Tests/TestSetup.cs b/ManagedWimLib.Tests/TestSetup.cs index 12e88a0..784e016 100644 --- a/ManagedWimLib.Tests/TestSetup.cs +++ b/ManagedWimLib.Tests/TestSetup.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free @@ -146,17 +146,6 @@ public static Tuple[] NormalizePaths(IEnumerable new Tuple(NormalizePath(x.Item1), x.Item2)).ToArray(); } - - public static string RootPath - { - get - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - return @"\"; - else - return @"/"; - } - } #endregion #region File Check @@ -384,7 +373,7 @@ CallbackStatus IterateCallback(DirEntry dentry, object userData) using (Wim wim = Wim.OpenWim(wimFile, OpenFlags.DEFAULT)) { - wim.IterateDirTree(1, TestHelper.RootPath, IterateFlags.RECURSIVE, IterateCallback); + wim.IterateDirTree(1, Wim.RootPath, IterateFlags.RECURSIVE, IterateCallback); } return entries; diff --git a/ManagedWimLib.Tests/UpdateTests.cs b/ManagedWimLib.Tests/UpdateTests.cs index 797db18..f0dbbe8 100644 --- a/ManagedWimLib.Tests/UpdateTests.cs +++ b/ManagedWimLib.Tests/UpdateTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free @@ -130,7 +130,7 @@ CallbackStatus IterateCallback(DirEntry dentry, object userData) using (Wim wim = Wim.OpenWim(destWimFile, OpenFlags.DEFAULT)) { - wim.IterateDirTree(1, TestHelper.RootPath, IterateFlags.RECURSIVE, IterateCallback, entries); + wim.IterateDirTree(1, Wim.RootPath, IterateFlags.RECURSIVE, IterateCallback, entries); } Assert.IsTrue(tested.Value); @@ -141,19 +141,19 @@ CallbackStatus IterateCallback(DirEntry dentry, object userData) case UpdateOp.ADD: { UpdateCommand.UpdateAdd add = cmd.Add; - Assert.IsTrue(entries.Contains(Path.Combine(TestHelper.RootPath, add.WimTargetPath), StringComparer.Ordinal)); + Assert.IsTrue(entries.Contains(Path.Combine(Wim.RootPath, add.WimTargetPath), StringComparer.Ordinal)); } break; case UpdateOp.DELETE: { UpdateCommand.UpdateDelete del = cmd.Delete; - Assert.IsFalse(entries.Contains(Path.Combine(TestHelper.RootPath, del.WimPath), StringComparer.Ordinal)); + Assert.IsFalse(entries.Contains(Path.Combine(Wim.RootPath, del.WimPath), StringComparer.Ordinal)); } break; case UpdateOp.RENAME: { UpdateCommand.UpdateRename ren = cmd.Rename; - Assert.IsTrue(entries.Contains(Path.Combine(TestHelper.RootPath, ren.WimTargetPath), StringComparer.Ordinal)); + Assert.IsTrue(entries.Contains(Path.Combine(Wim.RootPath, ren.WimTargetPath), StringComparer.Ordinal)); } break; } diff --git a/ManagedWimLib.Tests/VerifyTests.cs b/ManagedWimLib.Tests/VerifyTests.cs index 28f2805..86e8aee 100644 --- a/ManagedWimLib.Tests/VerifyTests.cs +++ b/ManagedWimLib.Tests/VerifyTests.cs @@ -5,7 +5,7 @@ Derived from wimlib's original header files Copyright (C) 2012-2018 Eric Biggers C# Wrapper written by Hajin Jang - Copyright (C) 2017-2018 Hajin Jang + Copyright (C) 2017-2019 Hajin Jang This file is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free diff --git a/ManagedWimLib/ManagedWimLib.csproj b/ManagedWimLib/ManagedWimLib.csproj index d8606cc..a5fbc71 100644 --- a/ManagedWimLib/ManagedWimLib.csproj +++ b/ManagedWimLib/ManagedWimLib.csproj @@ -5,7 +5,7 @@ ManagedWimLib ManagedWimLib latest - 1.4.0 + 1.4.1 Eric Biggers, Hajin Jang Joveler Native wimlib wrapper library for .Net. @@ -16,8 +16,10 @@ Supports Windows, Linux and macOS. https://github.com/ied206/ManagedWimLib images\Logo.png https://github.com/ied206/ManagedWimLib - - Support macOS platform -- Apply improved native library loader (Joveler.DynLoader) + - (v1.4) Support macOS platform +- Fix Wim.GetErrors(), Wim.GetLastError() regression +- Fix Wim.RootPath, Wim.PathSeparator regression +- Error print state is now readable from Wim.ErrorPrintState wim wimlib dism imagex archive native pinvoke interop diff --git a/ManagedWimLib/WimLibLoader.cs b/ManagedWimLib/WimLibLoader.cs index 48d49c9..a6aeaa7 100644 --- a/ManagedWimLib/WimLibLoader.cs +++ b/ManagedWimLib/WimLibLoader.cs @@ -24,6 +24,8 @@ You should have received a copy of the GNU Lesser General Public License using Joveler.DynLoader; using System; using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; using System.Runtime.InteropServices; // ReSharper disable FieldCanBeMadeReadOnly.Global // ReSharper disable MemberCanBePrivate.Global @@ -60,7 +62,8 @@ public WimLibLoader(string libPath) : base(libPath) { } #region Error Settings internal string ErrorFile = null; - internal bool PrintErrorsEnabled = false; + internal ErrorPrintState ErrorPrintState = ErrorPrintState.PrintOff; + internal static readonly object _errorFileLock = new object(); #endregion #region (override) DefaultLibFileName @@ -261,7 +264,7 @@ protected override void LoadFunctions() #region Error - GetErrorString, SetPrintErrors GetErrorString = GetFuncPtr(nameof(wimlib_get_error_string)); - SetPrintErrors = GetFuncPtr(nameof(wimlib_set_print_errors)); + SetPrintErrorsPtr = GetFuncPtr(nameof(wimlib_set_print_errors)); #endregion #region Create - CreateWim @@ -327,6 +330,10 @@ protected override void LoadFunctions() #region Write - Overwrite Overwrite = GetFuncPtr(nameof(wimlib_overwrite)); #endregion + + #region (Code) Set ErrorFile and PrintError + SetupErrorFile(); + #endregion } protected override void ResetFunctions() @@ -340,7 +347,7 @@ protected override void ResetFunctions() GetErrorString = null; Utf16.SetErrorFile = null; Utf8.SetErrorFile = null; - SetPrintErrors = null; + SetPrintErrorsPtr = null; #endregion #region Add - AddEmptyImage, AddImage, AddImageMultiSource, AddTree @@ -491,6 +498,25 @@ protected override void ResetFunctions() Utf8.Write = null; Overwrite = null; #endregion + + #region (Code) Cleanup ErrorFile + CleanupErrorFile(); + #endregion + } + #endregion + + #region ErrorFile Handling + private void SetupErrorFile() + { + ErrorFile = Path.GetTempFileName(); + SetErrorFile(ErrorFile); + } + + private void CleanupErrorFile() + { + SetPrintErrors(false); + if (File.Exists(ErrorFile)) + File.Delete(ErrorFile); } #endregion @@ -502,6 +528,17 @@ internal class Utf16d internal const CharSet StructCharSet = CharSet.Unicode; #region Error - SetErrorFile + /// + /// Set the path to the file to which the library will print error and warning messages. + /// The library will open this file for appending. + /// + /// This also enables error messages, as if by a call to wimlib_set_print_errors(true). + /// + /// + /// WIMLIB_ERR_OPEN: The file named by @p path could not be opened for appending. + /// WIMLIB_ERR_UNSUPPORTED: wimlib was compiled using the --without-error-messages option. + /// + /// 0 on success; a ::wimlib_error_code value on failure. [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate ErrorCode wimlib_set_error_file_by_name( [MarshalAs(StrType)] string path); @@ -853,6 +890,17 @@ internal class Utf8d internal const CharSet StructCharSet = CharSet.Ansi; #region Error - SetErrorFile + /// + /// Set the path to the file to which the library will print error and warning messages. + /// The library will open this file for appending. + /// + /// This also enables error messages, as if by a call to wimlib_set_print_errors(true). + /// + /// + /// WIMLIB_ERR_OPEN: The file named by @p path could not be opened for appending. + /// WIMLIB_ERR_UNSUPPORTED: wimlib was compiled using the --without-error-messages option. + /// + /// 0 on success; a ::wimlib_error_code value on failure. [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate ErrorCode wimlib_set_error_file_by_name( [MarshalAs(StrType)] string path); @@ -1232,27 +1280,130 @@ internal delegate void wimlib_register_progress_function( internal wimlib_register_progress_function RegisterProgressFunction; #endregion - #region Error - GetErrorString, SetErrorFile, SetPrintErrors + #region Error - GetErrorString, SetErrorFile, SetPrintErrors and Helpers [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate IntPtr wimlib_get_error_string(ErrorCode code); internal wimlib_get_error_string GetErrorString; - internal ErrorCode SetErrorFile(string path) + internal void SetErrorFile(string path) { + if (path == null) + throw new ArgumentNullException(nameof(path)); + + // wimlib_set_error_file_by_name(string path) internally calls wimlib_set_print_errors(true). + ErrorCode ret; switch (UnicodeConvention) { case UnicodeConvention.Utf16: - return Utf16.SetErrorFile(path); + ret = Utf16.SetErrorFile(path); + break; case UnicodeConvention.Utf8: default: - return Utf8.SetErrorFile(path); + ret = Utf8.SetErrorFile(path); + break; + } + + // When ret is ErrorCode.UNSUPPORTED, wimlib was compiled using the --without-error-messages option. + // In that case, ManagedWimLib must not throw WimLibException. + if (ret == ErrorCode.UNSUPPORTED) + { + ErrorPrintState = ErrorPrintState.NotSupported; + } + else + { + WimLibException.CheckWimLibError(ret); + ErrorPrintState = ErrorPrintState.PrintOn; } } + /// + /// Set whether wimlib can print error and warning messages to the error file, which defaults to standard error. + /// Error and warning messages may provide information that cannot be determined only from returned error codes. + /// + /// By default, error messages are not printed. + /// This setting applies globally (it is not per-WIM). + /// This can be called before wimlib_global_init(). + /// + /// + /// WIMLIB_ERR_UNSUPPORTED: wimlib was compiled using the --without-error-messages option. + /// + /// [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate ErrorCode wimlib_set_print_errors( - bool showMessages); - internal wimlib_set_print_errors SetPrintErrors; + internal delegate ErrorCode wimlib_set_print_errors(bool showMessages); + private wimlib_set_print_errors SetPrintErrorsPtr; + + internal void SetPrintErrors(bool showMessages) + { + lock (_errorFileLock) + { + ErrorCode ret = SetPrintErrorsPtr(showMessages); + + // When ret is ErrorCode.UNSUPPORTED, wimlib was compiled using the --without-error-messages option. + // In that case, ManagedWimLib must not throw WimLibException. + if (ret == ErrorCode.UNSUPPORTED) + { + ErrorPrintState = ErrorPrintState.NotSupported; + } + else + { + WimLibException.CheckWimLibError(ret); + ErrorPrintState = showMessages ? ErrorPrintState.PrintOn : ErrorPrintState.PrintOff; + } + } + } + + internal string[] GetErrors() + { + lock (_errorFileLock) + { + if (ErrorFile == null) + return null; + if (ErrorPrintState != ErrorPrintState.PrintOn) + return null; + + using (FileStream fs = new FileStream(ErrorFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (StreamReader r = new StreamReader(fs, UnicodeEncoding, false)) + { + return r.ReadToEnd().Split('\n').Select(x => x.Trim()).Where(x => 0 < x.Length).ToArray(); + } + } + } + + internal string GetLastError() + { + lock (_errorFileLock) + { + if (ErrorFile == null) + return null; + if (ErrorPrintState != ErrorPrintState.PrintOn) + return null; + + using (FileStream fs = new FileStream(ErrorFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (StreamReader r = new StreamReader(fs, UnicodeEncoding, false)) + { + var lines = r.ReadToEnd().Split('\n').Select(x => x.Trim()).Where(x => 0 < x.Length); + return lines.LastOrDefault(); + } + } + } + + internal void ResetErrorFile() + { + lock (_errorFileLock) + { + if (ErrorFile == null) + return; + if (ErrorPrintState != ErrorPrintState.PrintOn) + return; + + // Overwrite to Empty File + using (FileStream fs = new FileStream(ErrorFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) + using (StreamWriter w = new StreamWriter(fs, UnicodeEncoding)) + { + w.WriteLine(); + } + } + } #endregion #region Add - AddEmptyImage, AddImage, AddImageMultiSource, AddTree @@ -1861,4 +2012,13 @@ internal static bool GetBitField(uint bitField, int bitShift) } #endregion } + + #region enum ErrorPrintState + public enum ErrorPrintState + { + PrintOff = 0, + PrintOn = 1, + NotSupported = 2, + } + #endregion } diff --git a/ManagedWimLib/WimStruct.cs b/ManagedWimLib/WimStruct.cs index 9930299..d748d7c 100644 --- a/ManagedWimLib/WimStruct.cs +++ b/ManagedWimLib/WimStruct.cs @@ -23,8 +23,6 @@ You should have received a copy of the GNU Lesser General Public License using System; using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; @@ -54,11 +52,36 @@ public class Wim : IDisposable public const int DefaultThreads = 0; #endregion - #region Field + #region Fields private IntPtr _ptr; private ManagedProgressCallback _managedCallback; #endregion + #region Properties + public static string ErrorFile => Lib.ErrorFile; + public static ErrorPrintState ErrorPrintState => Lib.ErrorPrintState; + + public static string PathSeparator + { + get + { +#if !NET451 + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) +#endif + { + return @"\"; + } +#if !NET451 + else + { + return @"/"; + } +#endif + } + } + public static string RootPath => PathSeparator; + #endregion + #region Constructor (private) private Wim(IntPtr ptr) { @@ -93,7 +116,7 @@ protected virtual void Dispose(bool disposing) } #endregion - #region Error - (Static) GetErrorString, GetLastError, SetPrintErrors + #region Error - (Static) GetErrorString, GetErrors, GetLastError, SetPrintErrors /// /// Convert a wimlib error code into a string describing it. /// @@ -110,56 +133,53 @@ public static string GetErrorString(ErrorCode code) return Lib.PtrToStringAuto(ptr); } + /// + /// Returns a list of every error messages generated. + /// If error logging was turned off by SetPrintErrors(false), null is returned. + /// + /// + /// Calling this method does not clear old error messages. + /// Call ResetErrorFile() to clear them. + /// + /// An array of error string. If SetPrintErrors(false) was called, null is returned. public static string[] GetErrors() { - if (Lib.ErrorFile == null) - return null; - if (!Lib.PrintErrorsEnabled) - return null; + Manager.EnsureLoaded(); - using (FileStream fs = new FileStream(Lib.ErrorFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - using (StreamReader r = new StreamReader(fs, Lib.UnicodeEncoding, false)) - { - return r.ReadToEnd().Split('\n').Select(x => x.Trim()).Where(x => 0 < x.Length).ToArray(); - } + return Lib.GetErrors(); } + /// + /// Returns last error message. + /// If error logging was turned off by SetPrintErrors(false), null is returned. + /// + /// + /// Calling this method does not clear old error messages. + /// Call ResetErrorFile() to clear them. + /// + /// If error had been created, an error string is returned. If error had not been generated or SetPrintErrors(false) was called, null is returned. public static string GetLastError() { - if (Lib.ErrorFile == null) - return null; - if (!Lib.PrintErrorsEnabled) - return null; + Manager.EnsureLoaded(); - using (FileStream fs = new FileStream(Lib.ErrorFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - using (StreamReader r = new StreamReader(fs, Lib.UnicodeEncoding, false)) - { - var lines = r.ReadToEnd().Split('\n').Select(x => x.Trim()).Where(x => 0 < x.Length); - return lines.LastOrDefault(); - } + return Lib.GetLastError(); } + /// + /// Clear old error messages. + /// public static void ResetErrorFile() { - if (Lib.ErrorFile == null) - return; - if (!Lib.PrintErrorsEnabled) - return; + Manager.EnsureLoaded(); - // Overwrite to Empty File - using (FileStream fs = new FileStream(Lib.ErrorFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) - using (StreamWriter w = new StreamWriter(fs, Lib.UnicodeEncoding)) - { - w.WriteLine(); - } + Lib.ResetErrorFile(); } /// - /// Set whether wimlib can print error and warning messages to the error file, which defaults to standard error. + /// Set whether wimlib can print error and warning messages to the error file, which can be retreived with GetErrors(). /// Error and warning messages may provide information that cannot be determined only from returned error codes. /// - /// By default, error messages are not printed. - /// This setting applies globally (it is not per-WIM). + /// This setting applies globally (not per-WIM). /// This can be called before Wim.GlobalInit(). /// /// @@ -171,10 +191,7 @@ public static void SetPrintErrors(bool showMessages) { Manager.EnsureLoaded(); - ErrorCode ret = Lib.SetPrintErrors(showMessages); - WimLibException.CheckWimLibError(ret); - - Lib.PrintErrorsEnabled = showMessages; + Lib.SetPrintErrors(showMessages); } #endregion From 47210041b2551bcb4a26da37fc77f37f061f7aae Mon Sep 17 00:00:00 2001 From: Hajin Jang Date: Mon, 21 Oct 2019 01:58:22 +0900 Subject: [PATCH 3/3] Provide Wim.ErrorPrintState - Add more locking for stability - More error print tests --- ManagedWimLib.Tests/ErrorTests.cs | 31 ++++++++--- ManagedWimLib/WimLibLoader.cs | 93 ++++++++++++++++++++----------- ManagedWimLib/WimStruct.cs | 19 ++++++- 3 files changed, 102 insertions(+), 41 deletions(-) diff --git a/ManagedWimLib.Tests/ErrorTests.cs b/ManagedWimLib.Tests/ErrorTests.cs index 144d722..5ed4af3 100644 --- a/ManagedWimLib.Tests/ErrorTests.cs +++ b/ManagedWimLib.Tests/ErrorTests.cs @@ -37,11 +37,18 @@ public class ErrorTests public void GetLastError() { string[] paths = new string[] { @"\NOTEXIST.bin", @"NOTGLOB?.cue" }; - CheckErrorTemplate("XPRESS.wim", paths); - CheckErrorTemplate("XPRESS.wim", paths); + + // Default is Wim.SetPrintErrors(true); + CheckErrorTemplate("XPRESS.wim", paths, true); + + Wim.SetPrintErrors(false); + CheckErrorTemplate("LZX.wim", paths, false); + + Wim.SetPrintErrors(true); + CheckErrorTemplate("LZMS.wim", paths, true); } - public void CheckErrorTemplate(string fileName, string[] paths) + public void CheckErrorTemplate(string fileName, string[] paths, bool printError) { string destDir = TestHelper.GetTempDir(); try @@ -127,10 +134,20 @@ CallbackStatus ProgressCallback(ProgressMsg msg, object info, object progctx) // Read error message string[] errorMsgs = Wim.GetErrors(); - Assert.IsNotNull(errorMsgs); - Assert.IsTrue(0 < errorMsgs.Length); - foreach (string errorMsg in errorMsgs) - Console.WriteLine(errorMsg); + ErrorPrintState printState = Wim.ErrorPrintState; + if (printError) + { + Assert.IsNotNull(errorMsgs); + Assert.AreEqual(ErrorPrintState.PrintOn, printState); + Assert.IsTrue(0 < errorMsgs.Length); + foreach (string errorMsg in errorMsgs) + Console.WriteLine(errorMsg); + } + else + { + Assert.IsNull(errorMsgs); + Assert.AreEqual(ErrorPrintState.PrintOff, printState); + } } finally { diff --git a/ManagedWimLib/WimLibLoader.cs b/ManagedWimLib/WimLibLoader.cs index a6aeaa7..6d28cd9 100644 --- a/ManagedWimLib/WimLibLoader.cs +++ b/ManagedWimLib/WimLibLoader.cs @@ -61,9 +61,24 @@ public WimLibLoader(string libPath) : base(libPath) { } #endregion #region Error Settings - internal string ErrorFile = null; - internal ErrorPrintState ErrorPrintState = ErrorPrintState.PrintOff; + private string _errorFile = null; + private ErrorPrintState _errorPrintState = ErrorPrintState.PrintOff; + internal static readonly object _errorFileLock = new object(); + internal string GetErrorFilePath() + { + lock (_errorFileLock) + { + return _errorFile; + } + } + internal ErrorPrintState GetErrorPrintState() + { + lock (_errorFileLock) + { + return _errorPrintState; + } + } #endregion #region (override) DefaultLibFileName @@ -332,7 +347,7 @@ protected override void LoadFunctions() #endregion #region (Code) Set ErrorFile and PrintError - SetupErrorFile(); + SetErrorFile(); #endregion } @@ -500,23 +515,8 @@ protected override void ResetFunctions() #endregion #region (Code) Cleanup ErrorFile - CleanupErrorFile(); - #endregion - } - #endregion - - #region ErrorFile Handling - private void SetupErrorFile() - { - ErrorFile = Path.GetTempFileName(); - SetErrorFile(ErrorFile); - } - - private void CleanupErrorFile() - { SetPrintErrors(false); - if (File.Exists(ErrorFile)) - File.Delete(ErrorFile); + #endregion } #endregion @@ -1285,6 +1285,12 @@ internal delegate void wimlib_register_progress_function( internal delegate IntPtr wimlib_get_error_string(ErrorCode code); internal wimlib_get_error_string GetErrorString; + internal void SetErrorFile() + { + string errorFile = Path.GetTempFileName(); + SetErrorFile(errorFile); + } + internal void SetErrorFile(string path) { if (path == null) @@ -1307,12 +1313,23 @@ internal void SetErrorFile(string path) // In that case, ManagedWimLib must not throw WimLibException. if (ret == ErrorCode.UNSUPPORTED) { - ErrorPrintState = ErrorPrintState.NotSupported; + _errorPrintState = ErrorPrintState.NotSupported; + + // ErrorFile is no longer used, delete it + if (_errorFile != null) + { + if (File.Exists(_errorFile)) + File.Delete(_errorFile); + _errorFile = null; + } } else { WimLibException.CheckWimLibError(ret); - ErrorPrintState = ErrorPrintState.PrintOn; + + // Set new ErrorFile and report state as ErrorPrintState.PrintOn. + _errorPrintState = ErrorPrintState.PrintOn; + _errorFile = path; } } @@ -1342,12 +1359,12 @@ internal void SetPrintErrors(bool showMessages) // In that case, ManagedWimLib must not throw WimLibException. if (ret == ErrorCode.UNSUPPORTED) { - ErrorPrintState = ErrorPrintState.NotSupported; + _errorPrintState = ErrorPrintState.NotSupported; } else { WimLibException.CheckWimLibError(ret); - ErrorPrintState = showMessages ? ErrorPrintState.PrintOn : ErrorPrintState.PrintOff; + _errorPrintState = showMessages ? ErrorPrintState.PrintOn : ErrorPrintState.PrintOff; } } } @@ -1356,12 +1373,12 @@ internal string[] GetErrors() { lock (_errorFileLock) { - if (ErrorFile == null) + if (_errorFile == null) return null; - if (ErrorPrintState != ErrorPrintState.PrintOn) + if (_errorPrintState != ErrorPrintState.PrintOn) return null; - using (FileStream fs = new FileStream(ErrorFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (FileStream fs = new FileStream(_errorFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (StreamReader r = new StreamReader(fs, UnicodeEncoding, false)) { return r.ReadToEnd().Split('\n').Select(x => x.Trim()).Where(x => 0 < x.Length).ToArray(); @@ -1373,12 +1390,12 @@ internal string GetLastError() { lock (_errorFileLock) { - if (ErrorFile == null) + if (_errorFile == null) return null; - if (ErrorPrintState != ErrorPrintState.PrintOn) + if (_errorPrintState != ErrorPrintState.PrintOn) return null; - using (FileStream fs = new FileStream(ErrorFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (FileStream fs = new FileStream(_errorFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (StreamReader r = new StreamReader(fs, UnicodeEncoding, false)) { var lines = r.ReadToEnd().Split('\n').Select(x => x.Trim()).Where(x => 0 < x.Length); @@ -1391,13 +1408,13 @@ internal void ResetErrorFile() { lock (_errorFileLock) { - if (ErrorFile == null) + if (_errorFile == null) return; - if (ErrorPrintState != ErrorPrintState.PrintOn) + if (_errorPrintState != ErrorPrintState.PrintOn) return; // Overwrite to Empty File - using (FileStream fs = new FileStream(ErrorFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) + using (FileStream fs = new FileStream(_errorFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) using (StreamWriter w = new StreamWriter(fs, UnicodeEncoding)) { w.WriteLine(); @@ -2014,10 +2031,22 @@ internal static bool GetBitField(uint bitField, int bitShift) } #region enum ErrorPrintState + /// + /// Represents whether wimlib is printing error messages or not. + /// public enum ErrorPrintState { + /// + /// Error messages are not being printed to ErrorFile. + /// PrintOff = 0, + /// + /// Error messages are being printed to ErrorFile. + /// PrintOn = 1, + /// + /// wimlib was not built with --without-error-messages option. + /// NotSupported = 2, } #endregion diff --git a/ManagedWimLib/WimStruct.cs b/ManagedWimLib/WimStruct.cs index d748d7c..fcc349e 100644 --- a/ManagedWimLib/WimStruct.cs +++ b/ManagedWimLib/WimStruct.cs @@ -49,6 +49,9 @@ public class Wim : IDisposable #region Const public const int NoImage = 0; public const int AllImages = -1; + /// + /// Let wimlib determine best thread count to use. + /// public const int DefaultThreads = 0; #endregion @@ -58,9 +61,18 @@ public class Wim : IDisposable #endregion #region Properties - public static string ErrorFile => Lib.ErrorFile; - public static ErrorPrintState ErrorPrintState => Lib.ErrorPrintState; + /// + /// The error file which wimlib prints error message to. Valid only if ErrorPrintState is PrintOn, else the property returns null. + /// + public static string ErrorFile => Lib.GetErrorFilePath(); + /// + /// Represents whether wimlib is printing error messages or not. + /// + public static ErrorPrintState ErrorPrintState => Lib.GetErrorPrintState(); + /// + /// Does the same job with Path.DirectorySeparatorChar, as string. Provided for the compatibility with old releases. + /// public static string PathSeparator { get @@ -79,6 +91,9 @@ public static string PathSeparator #endif } } + /// + /// Does the same job with Path.DirectorySeparatorChar, as string. Provided for the compatibility with old releases. + /// public static string RootPath => PathSeparator; #endregion