From d7e559749da091e4fceec087066dd50dc730a00d Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 29 Jul 2025 21:13:53 -0400 Subject: [PATCH] Normalize extraction methods This does a few things: - Ensures that all output directories are normalized for the current operating system - Ensures that all output files are flushed in case of systematic issues - Brings MS-CAB extraction up to the same return value quality as other extractors --- SabreTools.Serialization/Wrappers/BFPK.cs | 36 +++++++++++---- SabreTools.Serialization/Wrappers/BSP.cs | 13 ++++-- SabreTools.Serialization/Wrappers/GCF.cs | 17 ++++--- .../Wrappers/InstallShieldArchiveV3.cs | 15 ++++-- SabreTools.Serialization/Wrappers/LZKWAJ.cs | 12 +++-- SabreTools.Serialization/Wrappers/LZQBasic.cs | 14 ++++-- SabreTools.Serialization/Wrappers/LZSZDD.cs | 13 ++++-- .../Wrappers/MicrosoftCabinet.cs | 46 ++++++++++++------- SabreTools.Serialization/Wrappers/PAK.cs | 17 ++++--- SabreTools.Serialization/Wrappers/PFF.cs | 20 ++++++-- SabreTools.Serialization/Wrappers/SGA.cs | 13 ++++-- SabreTools.Serialization/Wrappers/VBSP.cs | 19 +++++--- SabreTools.Serialization/Wrappers/VPK.cs | 21 +++++---- SabreTools.Serialization/Wrappers/WAD3.cs | 17 ++++--- SabreTools.Serialization/Wrappers/XZP.cs | 17 ++++--- 15 files changed, 190 insertions(+), 100 deletions(-) diff --git a/SabreTools.Serialization/Wrappers/BFPK.cs b/SabreTools.Serialization/Wrappers/BFPK.cs index e660c13e..096722f5 100644 --- a/SabreTools.Serialization/Wrappers/BFPK.cs +++ b/SabreTools.Serialization/Wrappers/BFPK.cs @@ -139,14 +139,28 @@ namespace SabreTools.Serialization.Wrappers compressedSize = file.UncompressedSize; } + // If we have an invalid output directory + if (string.IsNullOrEmpty(outputDirectory)) + return false; + + // Ensure directory separators are consistent + string filename = file.Name ?? $"file{index}"; + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); + + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); + var directoryName = Path.GetDirectoryName(filename); + if (directoryName != null && !Directory.Exists(directoryName)) + Directory.CreateDirectory(directoryName); + + // Try to write the data try { - // Ensure the output directory exists - Directory.CreateDirectory(outputDirectory); - - // Create the output path - string filePath = Path.Combine(outputDirectory, file.Name ?? $"file{index}"); - using FileStream fs = File.OpenWrite(filePath); + // Open the output file for writing + using FileStream fs = File.OpenWrite(filename); // Read the data block var data = ReadFromDataSource(offset, compressedSize); @@ -157,20 +171,22 @@ namespace SabreTools.Serialization.Wrappers if (compressedSize == file.UncompressedSize) { fs.Write(data, 0, compressedSize); + fs.Flush(); } else { - MemoryStream ms = new MemoryStream(data); - ZlibStream zs = new ZlibStream(ms, CompressionMode.Decompress); + using MemoryStream ms = new MemoryStream(data); + using ZlibStream zs = new ZlibStream(ms, CompressionMode.Decompress); zs.CopyTo(fs); + fs.Flush(); } - - return true; } catch { return false; } + + return true; } #endregion diff --git a/SabreTools.Serialization/Wrappers/BSP.cs b/SabreTools.Serialization/Wrappers/BSP.cs index e90df190..a42051c9 100644 --- a/SabreTools.Serialization/Wrappers/BSP.cs +++ b/SabreTools.Serialization/Wrappers/BSP.cs @@ -137,12 +137,16 @@ namespace SabreTools.Serialization.Wrappers if (string.IsNullOrEmpty(outputDirectory)) return false; - // Create the full output path - filename = Path.Combine(outputDirectory, filename); + // Ensure directory separators are consistent + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); // Try to write the data @@ -151,6 +155,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = File.OpenWrite(filename); fs.Write(data, 0, data.Length); + fs.Flush(); } catch { diff --git a/SabreTools.Serialization/Wrappers/GCF.cs b/SabreTools.Serialization/Wrappers/GCF.cs index 70e14231..069ff9f8 100644 --- a/SabreTools.Serialization/Wrappers/GCF.cs +++ b/SabreTools.Serialization/Wrappers/GCF.cs @@ -287,19 +287,21 @@ namespace SabreTools.Serialization.Wrappers } } - // Create the filename - var filename = file.Path; - // If we have an invalid output directory if (string.IsNullOrEmpty(outputDirectory)) return false; - // Create the full output path - filename = Path.Combine(outputDirectory, filename ?? $"file{index}"); + // Ensure directory separators are consistent + string filename = file.Path ?? $"file{index}"; + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); // Try to write the data @@ -318,6 +320,7 @@ namespace SabreTools.Serialization.Wrappers return false; fs.Write(data, 0, data.Length); + fs.Flush(); } } catch diff --git a/SabreTools.Serialization/Wrappers/InstallShieldArchiveV3.cs b/SabreTools.Serialization/Wrappers/InstallShieldArchiveV3.cs index cbb3728b..35b3ac87 100644 --- a/SabreTools.Serialization/Wrappers/InstallShieldArchiveV3.cs +++ b/SabreTools.Serialization/Wrappers/InstallShieldArchiveV3.cs @@ -250,7 +250,7 @@ namespace SabreTools.Serialization.Wrappers { // Decompress the data var decomp = Decompressor.Create(); - var outData = new MemoryStream(); + using var outData = new MemoryStream(); decomp.CopyTo(compressedData, outData); data = outData.ToArray(); } @@ -259,12 +259,16 @@ namespace SabreTools.Serialization.Wrappers if (string.IsNullOrEmpty(outputDirectory)) return false; - // Create the full output path - filename = Path.Combine(outputDirectory, filename); + // Ensure directory separators are consistent + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !System.IO.Directory.Exists(directoryName)) System.IO.Directory.CreateDirectory(directoryName); // Try to write the data @@ -273,6 +277,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = System.IO.File.OpenWrite(filename); fs.Write(data, 0, data.Length); + fs.Flush(); } catch { diff --git a/SabreTools.Serialization/Wrappers/LZKWAJ.cs b/SabreTools.Serialization/Wrappers/LZKWAJ.cs index 5c828244..79ab1d70 100644 --- a/SabreTools.Serialization/Wrappers/LZKWAJ.cs +++ b/SabreTools.Serialization/Wrappers/LZKWAJ.cs @@ -112,11 +112,16 @@ namespace SabreTools.Serialization.Wrappers if (Model.HeaderExtensions?.FileExtension != null) filename += $".{Model.HeaderExtensions.FileExtension}"; - filename = Path.Combine(outputDirectory, filename); + // Ensure directory separators are consistent + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); // Try to write the data @@ -125,6 +130,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = File.OpenWrite(filename); decompressor.CopyTo(fs); + fs.Flush(); } catch { diff --git a/SabreTools.Serialization/Wrappers/LZQBasic.cs b/SabreTools.Serialization/Wrappers/LZQBasic.cs index fadeab5e..896eac7c 100644 --- a/SabreTools.Serialization/Wrappers/LZQBasic.cs +++ b/SabreTools.Serialization/Wrappers/LZQBasic.cs @@ -106,12 +106,17 @@ namespace SabreTools.Serialization.Wrappers if (string.IsNullOrEmpty(outputDirectory)) return false; - // Create the full output path - string filename = Path.Combine(outputDirectory, "tempfile.bin"); + // Ensure directory separators are consistent + string filename = "tempfile.bin"; + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); // Try to write the data @@ -120,6 +125,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = File.OpenWrite(filename); decompressor.CopyTo(fs); + fs.Flush(); } catch { diff --git a/SabreTools.Serialization/Wrappers/LZSZDD.cs b/SabreTools.Serialization/Wrappers/LZSZDD.cs index 18a8e5f4..7b700167 100644 --- a/SabreTools.Serialization/Wrappers/LZSZDD.cs +++ b/SabreTools.Serialization/Wrappers/LZSZDD.cs @@ -109,12 +109,16 @@ namespace SabreTools.Serialization.Wrappers if (string.IsNullOrEmpty(outputDirectory)) return false; - // Create the full output path - filename = Path.Combine(outputDirectory, filename); + // Ensure directory separators are consistent + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); // Try to write the data @@ -123,6 +127,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = File.OpenWrite(filename); decompressor.CopyTo(fs); + fs.Flush(); } catch { diff --git a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs index 398585ca..56f451b7 100644 --- a/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs +++ b/SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs @@ -148,20 +148,21 @@ namespace SabreTools.Serialization.Wrappers try { // Loop through the cabinets + bool allExtracted = true; do { - current.Extract(filename, outDir, includeDebug); + allExtracted &= current.Extract(filename, outDir, includeDebug); current = current.Next ?? current.OpenNext(filename); } while (current?.Header != null); + + return allExtracted; } catch (Exception ex) { if (includeDebug) Console.WriteLine(ex); return false; } - - return true; } /// @@ -180,13 +181,14 @@ namespace SabreTools.Serialization.Wrappers try { // Loop through the folders + bool allExtracted = true; for (int f = 0; f < Folders.Length; f++) { var folder = Folders[f]; - ExtractFolder(filename, outDir, folder, f, includeDebug); + allExtracted &= ExtractFolder(filename, outDir, folder, f, includeDebug); } - return true; + return allExtracted; } catch (Exception ex) { @@ -203,7 +205,8 @@ namespace SabreTools.Serialization.Wrappers /// Folder containing the blocks to decompress /// Index of the folder in the cabinet /// True to include debug data, false otherwise - private void ExtractFolder(string? filename, + /// True if all files extracted, false otherwise + private bool ExtractFolder(string? filename, string outDir, CFFOLDER? folder, int folderIndex, @@ -212,15 +215,18 @@ namespace SabreTools.Serialization.Wrappers // Decompress the blocks, if possible using var blockStream = DecompressBlocks(filename, folder, folderIndex); if (blockStream == null || blockStream.Length == 0) - return; + return false; // Loop through the files + bool allExtracted = true; var files = GetFiles(folderIndex); for (int i = 0; i < files.Length; i++) { var file = files[i]; - ExtractFile(outDir, blockStream, file, includeDebug); + allExtracted &= ExtractFile(outDir, blockStream, file, includeDebug); } + + return allExtracted; } /// @@ -230,7 +236,8 @@ namespace SabreTools.Serialization.Wrappers /// Stream representing the uncompressed block data /// File information /// True to include debug data, false otherwise - private static void ExtractFile(string outDir, Stream blockStream, CFFILE file, bool includeDebug) + /// True if the file extracted, false otherwise + private static bool ExtractFile(string outDir, Stream blockStream, CFFILE file, bool includeDebug) { try { @@ -238,25 +245,30 @@ namespace SabreTools.Serialization.Wrappers byte[] fileData = blockStream.ReadBytes((int)file.FileSize); // Ensure directory separators are consistent - string fileName = file.Name!; + string filename = file.Name!; if (Path.DirectorySeparatorChar == '\\') - fileName = fileName.Replace('/', '\\'); + filename = filename.Replace('/', '\\'); else if (Path.DirectorySeparatorChar == '/') - fileName = fileName.Replace('\\', '/'); + filename = filename.Replace('\\', '/'); - string tempFile = Path.Combine(outDir, fileName); - var directoryName = Path.GetDirectoryName(tempFile); + // Ensure the full output directory exists + filename = Path.Combine(outDir, filename); + var directoryName = Path.GetDirectoryName(filename); if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); - using var of = File.OpenWrite(tempFile); - of.Write(fileData, 0, fileData.Length); - of.Flush(); + // Open the output file for writing + using var fs = File.OpenWrite(filename); + fs.Write(fileData, 0, fileData.Length); + fs.Flush(); } catch (Exception ex) { if (includeDebug) Console.WriteLine(ex); + return false; } + + return true; } #endregion diff --git a/SabreTools.Serialization/Wrappers/PAK.cs b/SabreTools.Serialization/Wrappers/PAK.cs index 693b0e9c..74bc99a6 100644 --- a/SabreTools.Serialization/Wrappers/PAK.cs +++ b/SabreTools.Serialization/Wrappers/PAK.cs @@ -128,19 +128,21 @@ namespace SabreTools.Serialization.Wrappers if (data == null) return false; - // Create the filename - var filename = directoryItem.ItemName; - // If we have an invalid output directory if (string.IsNullOrEmpty(outputDirectory)) return false; - // Create the full output path - filename = Path.Combine(outputDirectory, filename ?? $"file{index}"); + // Ensure directory separators are consistent + string filename = directoryItem.ItemName ?? $"file{index}"; + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); // Try to write the data @@ -149,6 +151,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = System.IO.File.OpenWrite(filename); fs.Write(data, 0, data.Length); + fs.Flush(); } catch { diff --git a/SabreTools.Serialization/Wrappers/PFF.cs b/SabreTools.Serialization/Wrappers/PFF.cs index f56bc7ce..0104a9d9 100644 --- a/SabreTools.Serialization/Wrappers/PFF.cs +++ b/SabreTools.Serialization/Wrappers/PFF.cs @@ -138,12 +138,21 @@ namespace SabreTools.Serialization.Wrappers try { - // Ensure the output directory exists - Directory.CreateDirectory(outputDirectory); + // Ensure directory separators are consistent + string filename = segment.FileName ?? $"file{index}"; + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Create the output path - string filePath = Path.Combine(outputDirectory, segment.FileName ?? $"file{index}"); - using FileStream fs = File.OpenWrite(filePath); + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); + var directoryName = Path.GetDirectoryName(filename); + if (directoryName != null && !Directory.Exists(directoryName)) + Directory.CreateDirectory(directoryName); + + // Create the output file + using FileStream fs = File.OpenWrite(filename); // Read the data block var data = ReadFromDataSource(offset, size); @@ -152,6 +161,7 @@ namespace SabreTools.Serialization.Wrappers // Write the data -- TODO: Compressed data? fs.Write(data, 0, size); + fs.Flush(); return true; } diff --git a/SabreTools.Serialization/Wrappers/SGA.cs b/SabreTools.Serialization/Wrappers/SGA.cs index f830d0b6..ccaad245 100644 --- a/SabreTools.Serialization/Wrappers/SGA.cs +++ b/SabreTools.Serialization/Wrappers/SGA.cs @@ -239,12 +239,16 @@ namespace SabreTools.Serialization.Wrappers if (string.IsNullOrEmpty(outputDirectory)) return false; - // Create the full output path - filename = Path.Combine(outputDirectory, filename); + // Ensure directory separators are consistent + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !System.IO.Directory.Exists(directoryName)) System.IO.Directory.CreateDirectory(directoryName); // Try to write the data @@ -253,6 +257,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = System.IO.File.OpenWrite(filename); fs.Write(data, 0, data.Length); + fs.Flush(); } catch { diff --git a/SabreTools.Serialization/Wrappers/VBSP.cs b/SabreTools.Serialization/Wrappers/VBSP.cs index b7ae2c25..0bfbd4f3 100644 --- a/SabreTools.Serialization/Wrappers/VBSP.cs +++ b/SabreTools.Serialization/Wrappers/VBSP.cs @@ -121,6 +121,10 @@ namespace SabreTools.Serialization.Wrappers if (data == null) return false; + // If we have an invalid output directory + if (string.IsNullOrEmpty(outputDirectory)) + return false; + // Create the filename string filename = $"lump_{index}.bin"; switch ((LumpType)index) @@ -133,16 +137,16 @@ namespace SabreTools.Serialization.Wrappers break; } - // If we have an invalid output directory - if (string.IsNullOrEmpty(outputDirectory)) - return false; + // Ensure directory separators are consistent + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Create the full output path + // Ensure the full output directory exists filename = Path.Combine(outputDirectory, filename); - - // Ensure the output directory is created var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); // Try to write the data @@ -151,6 +155,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = File.OpenWrite(filename); fs.Write(data, 0, data.Length); + fs.Flush(); } catch { diff --git a/SabreTools.Serialization/Wrappers/VPK.cs b/SabreTools.Serialization/Wrappers/VPK.cs index bd8935d2..96d9a70d 100644 --- a/SabreTools.Serialization/Wrappers/VPK.cs +++ b/SabreTools.Serialization/Wrappers/VPK.cs @@ -249,21 +249,23 @@ namespace SabreTools.Serialization.Wrappers if (data == null) return false; - // Create the filename - string filename = $"{directoryItem.Name}.{directoryItem.Extension}"; - if (!string.IsNullOrEmpty(directoryItem.Path)) - filename = Path.Combine(directoryItem.Path, filename); - // If we have an invalid output directory if (string.IsNullOrEmpty(outputDirectory)) return false; - // Create the full output path - filename = Path.Combine(outputDirectory, filename); + // Ensure directory separators are consistent + string filename = $"{directoryItem.Name}.{directoryItem.Extension}"; + if (!string.IsNullOrEmpty(directoryItem.Path)) + filename = Path.Combine(directoryItem.Path, filename); + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); // Try to write the data @@ -272,6 +274,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = File.OpenWrite(filename); fs.Write(data, 0, data.Length); + fs.Flush(); } catch { diff --git a/SabreTools.Serialization/Wrappers/WAD3.cs b/SabreTools.Serialization/Wrappers/WAD3.cs index 3a71a1b6..a6a4d97f 100644 --- a/SabreTools.Serialization/Wrappers/WAD3.cs +++ b/SabreTools.Serialization/Wrappers/WAD3.cs @@ -120,19 +120,21 @@ namespace SabreTools.Serialization.Wrappers if (data == null) return false; - // Create the filename - string filename = $"{lump.Name}.lmp"; - // If we have an invalid output directory if (string.IsNullOrEmpty(outputDirectory)) return false; - // Create the full output path - filename = Path.Combine(outputDirectory, filename); + // Ensure directory separators are consistent + string filename = $"{lump.Name}.lmp"; + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); // Try to write the data @@ -141,6 +143,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = File.OpenWrite(filename); fs.Write(data, 0, data.Length); + fs.Flush(); } catch { diff --git a/SabreTools.Serialization/Wrappers/XZP.cs b/SabreTools.Serialization/Wrappers/XZP.cs index 6cce9dfc..a9ff4bca 100644 --- a/SabreTools.Serialization/Wrappers/XZP.cs +++ b/SabreTools.Serialization/Wrappers/XZP.cs @@ -130,19 +130,21 @@ namespace SabreTools.Serialization.Wrappers if (data == null) return false; - // Create the filename - var filename = directoryItem.Name; - // If we have an invalid output directory if (string.IsNullOrEmpty(outputDirectory)) return false; - // Create the full output path - filename = Path.Combine(outputDirectory, filename ?? $"file{index}"); + // Ensure directory separators are consistent + string filename = directoryItem.Name ?? $"file{index}"; + if (Path.DirectorySeparatorChar == '\\') + filename = filename.Replace('/', '\\'); + else if (Path.DirectorySeparatorChar == '/') + filename = filename.Replace('\\', '/'); - // Ensure the output directory is created + // Ensure the full output directory exists + filename = Path.Combine(outputDirectory, filename); var directoryName = Path.GetDirectoryName(filename); - if (directoryName != null) + if (directoryName != null && !Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); // Try to write the data @@ -151,6 +153,7 @@ namespace SabreTools.Serialization.Wrappers // Open the output file for writing using Stream fs = File.OpenWrite(filename); fs.Write(data, 0, data.Length); + fs.Flush(); } catch {