Added wine checks, path fixing on wine -> linux
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
using LightlessSync.LightlessConfiguration;
|
using LightlessSync.LightlessConfiguration;
|
||||||
using LightlessSync.Services;
|
using LightlessSync.Services;
|
||||||
using LightlessSync.Utils;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -191,6 +190,16 @@ public sealed class FileCompactor : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string ConvertWinePathToLinux(string winePath)
|
||||||
|
{
|
||||||
|
if (winePath.StartsWith("Z:\\", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return "/" + winePath.Substring(3).Replace('\\', '/');
|
||||||
|
if (winePath.StartsWith("C:\\", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal),
|
||||||
|
winePath.Substring(3).Replace('\\', '/')).Replace('\\', '/');
|
||||||
|
return winePath.Replace('\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
[DllImport("kernel32.dll")]
|
||||||
private static extern int DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, uint nOutBufferSize, out IntPtr lpBytesReturned, out IntPtr lpOverlapped);
|
private static extern int DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, uint nOutBufferSize, out IntPtr lpBytesReturned, out IntPtr lpOverlapped);
|
||||||
|
|
||||||
@@ -347,18 +356,42 @@ public sealed class FileCompactor : IDisposable
|
|||||||
var mountOptions = GetMountOptionsForPath(path);
|
var mountOptions = GetMountOptionsForPath(path);
|
||||||
if (mountOptions.Contains("compress", StringComparison.OrdinalIgnoreCase))
|
if (mountOptions.Contains("compress", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Cannot safely decompress {file}: filesystem mounted with compression ({opts}). Remount with 'compress=no' before running decompression.", path, mountOptions);
|
_logger.LogWarning(
|
||||||
|
"Cannot safely decompress {file}: filesystem mounted with compression ({opts}). Remount with 'compress=no' before running decompression.",
|
||||||
|
path, mountOptions);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("Rewriting {file} to remove btrfs compression...", path);
|
string realPath = path;
|
||||||
|
bool isWine = _dalamudUtilService?.IsWine ?? false;
|
||||||
var psi = new ProcessStartInfo("btrfs", $"filesystem defragment -- \"{path}\"")
|
if (isWine)
|
||||||
{
|
{
|
||||||
|
if (path.StartsWith("Z:\\", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
realPath = "/" + path.Substring(3).Replace('\\', '/');
|
||||||
|
}
|
||||||
|
else if (path.StartsWith("C:\\", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// fallback for Wine's C:\ mapping
|
||||||
|
realPath = Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
|
||||||
|
path.Substring(3).Replace('\\', '/')
|
||||||
|
).Replace('\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogTrace("Detected Wine environment. Converted path for decompression: {realPath}", realPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
string command = $"btrfs filesystem defragment -- \"{realPath}\"";
|
||||||
|
var psi = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = isWine ? "/bin/bash" : "btrfs",
|
||||||
|
Arguments = isWine ? $"-c \"{command}\"" : $"filesystem defragment -- \"{realPath}\"",
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true
|
CreateNoWindow = true,
|
||||||
|
WorkingDirectory = "/"
|
||||||
};
|
};
|
||||||
|
|
||||||
using var proc = Process.Start(psi);
|
using var proc = Process.Start(psi);
|
||||||
@@ -368,7 +401,7 @@ public sealed class FileCompactor : IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//End stream of process to read the files
|
// 4️⃣ Read process output
|
||||||
var stdout = proc.StandardOutput.ReadToEnd();
|
var stdout = proc.StandardOutput.ReadToEnd();
|
||||||
var stderr = proc.StandardError.ReadToEnd();
|
var stderr = proc.StandardError.ReadToEnd();
|
||||||
proc.WaitForExit();
|
proc.WaitForExit();
|
||||||
@@ -495,12 +528,36 @@ public sealed class FileCompactor : IDisposable
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var psi = new ProcessStartInfo("filefrag", $"-v \"{path}\"")
|
bool isWine = _dalamudUtilService?.IsWine ?? false;
|
||||||
|
string realPath = path;
|
||||||
|
|
||||||
|
if (isWine)
|
||||||
{
|
{
|
||||||
|
if (path.StartsWith("Z:\\", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
realPath = "/" + path.Substring(3).Replace('\\', '/');
|
||||||
|
}
|
||||||
|
else if (path.StartsWith("C:\\", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
realPath = Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
|
||||||
|
path.Substring(3).Replace('\\', '/')
|
||||||
|
).Replace('\\', '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogTrace("Detected Wine environment. Converted path for filefrag: {realPath}", realPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
string command = $"filefrag -v -- \"{realPath}\"";
|
||||||
|
var psi = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = isWine ? "/bin/bash" : "filefrag",
|
||||||
|
Arguments = isWine ? $"-c \"{command}\"" : $"-v -- \"{realPath}\"",
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true
|
CreateNoWindow = true,
|
||||||
|
WorkingDirectory = "/"
|
||||||
};
|
};
|
||||||
|
|
||||||
using var proc = Process.Start(psi);
|
using var proc = Process.Start(psi);
|
||||||
@@ -511,10 +568,17 @@ public sealed class FileCompactor : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
string output = proc.StandardOutput.ReadToEnd();
|
string output = proc.StandardOutput.ReadToEnd();
|
||||||
|
string stderr = proc.StandardError.ReadToEnd();
|
||||||
proc.WaitForExit();
|
proc.WaitForExit();
|
||||||
|
|
||||||
bool compressed = output.Contains("flags: compressed", StringComparison.OrdinalIgnoreCase);
|
if (proc.ExitCode != 0)
|
||||||
|
{
|
||||||
|
_logger.LogDebug("filefrag exited with {code} for {file}. stderr: {stderr}",
|
||||||
|
proc.ExitCode, path, stderr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compressed = output.Contains("flags: compressed", StringComparison.OrdinalIgnoreCase);
|
||||||
_logger.LogTrace("Btrfs compression check for {file}: {compressed}", path, compressed);
|
_logger.LogTrace("Btrfs compression check for {file}: {compressed}", path, compressed);
|
||||||
return compressed;
|
return compressed;
|
||||||
}
|
}
|
||||||
@@ -567,7 +631,20 @@ public sealed class FileCompactor : IDisposable
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var psi = new ProcessStartInfo("btrfs", $"filesystem defragment -czstd -- \"{path}\"")
|
string realPath = path;
|
||||||
|
if (_dalamudUtilService.IsWine)
|
||||||
|
{
|
||||||
|
realPath = ConvertWinePathToLinux(path);
|
||||||
|
_logger.LogTrace("Detected Wine environment, remapped path: {realPath}", realPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists("/usr/bin/btrfs") && !File.Exists("/bin/btrfs"))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Skipping Btrfs compression — btrfs binary not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var psi = new ProcessStartInfo("btrfs", $"filesystem defragment -czstd -- \"{realPath}\"")
|
||||||
{
|
{
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
@@ -578,7 +655,7 @@ public sealed class FileCompactor : IDisposable
|
|||||||
using var proc = Process.Start(psi);
|
using var proc = Process.Start(psi);
|
||||||
if (proc == null)
|
if (proc == null)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Failed to start btrfs process for {file}", path);
|
_logger.LogWarning("Failed to start btrfs process for {file}", realPath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,7 +665,7 @@ public sealed class FileCompactor : IDisposable
|
|||||||
|
|
||||||
if (proc.ExitCode != 0)
|
if (proc.ExitCode != 0)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("btrfs defrag returned {code} for {file}: {err}", proc.ExitCode, path, stderr);
|
_logger.LogWarning("btrfs defrag returned {code} for {file}: {err}", proc.ExitCode, realPath, stderr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,7 +674,7 @@ public sealed class FileCompactor : IDisposable
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogWarning(ex, "Error running btrfs defragment for {file}", path);
|
_logger.LogWarning(ex, "Error running btrfs defragment for {file}", realPath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user