From 3e626c5e47042c7941a9c52460c72ec98a92ac21 Mon Sep 17 00:00:00 2001 From: cake Date: Wed, 29 Oct 2025 04:49:46 +0100 Subject: [PATCH] Cleanup some code, removed ntfs usage on cache monitor --- LightlessSync/FileCache/CacheMonitor.cs | 2 +- LightlessSync/FileCache/FileCompactor.cs | 143 ++++++++++++++++++----- 2 files changed, 112 insertions(+), 33 deletions(-) diff --git a/LightlessSync/FileCache/CacheMonitor.cs b/LightlessSync/FileCache/CacheMonitor.cs index 23f5c19..c724225 100644 --- a/LightlessSync/FileCache/CacheMonitor.cs +++ b/LightlessSync/FileCache/CacheMonitor.cs @@ -429,7 +429,7 @@ public sealed class CacheMonitor : DisposableMediatorSubscriberBase try { - return _fileCompactor.GetFileSizeOnDisk(f, StorageisNTFS); + return _fileCompactor.GetFileSizeOnDisk(f); } catch { diff --git a/LightlessSync/FileCache/FileCompactor.cs b/LightlessSync/FileCache/FileCompactor.cs index dbc2574..e961fbd 100644 --- a/LightlessSync/FileCache/FileCompactor.cs +++ b/LightlessSync/FileCache/FileCompactor.cs @@ -4,11 +4,8 @@ using LightlessSync.Utils; using Microsoft.Extensions.Logging; using System.Collections.Concurrent; using System.Diagnostics; -using System.IO; using System.Runtime.InteropServices; -using System.Threading; using System.Threading.Channels; -using System.Threading.Tasks; using static LightlessSync.Utils.FileSystemHelper; namespace LightlessSync.FileCache; @@ -89,27 +86,21 @@ public sealed class FileCompactor : IDisposable MassCompactRunning = false; } - public long GetFileSizeOnDisk(FileInfo fileInfo, bool? isNTFS = null) + public long GetFileSizeOnDisk(FileInfo fileInfo) { - var fsType = FileSystemHelper.GetFilesystemType(fileInfo.FullName); + var fsType = GetFilesystemType(fileInfo.FullName); - bool ntfs = isNTFS ?? fsType == FileSystemHelper.FilesystemType.NTFS; - - if (fsType != FileSystemHelper.FilesystemType.Btrfs && !ntfs) + if (fsType != FilesystemType.Btrfs && fsType != FilesystemType.NTFS) { return fileInfo.Length; } - if (ntfs && !_dalamudUtilService.IsWine) + if (fsType == FilesystemType.NTFS && !_dalamudUtilService.IsWine) { - var clusterSize = GetClusterSize(fileInfo); - if (clusterSize == -1) return fileInfo.Length; - var losize = GetCompressedFileSizeW(fileInfo.FullName, out uint hosize); - var size = (long)hosize << 32 | losize; - return ((size + clusterSize - 1) / clusterSize) * clusterSize; + return GetFileSizeOnDisk(fileInfo, GetClusterSize); } - if (fsType == FileSystemHelper.FilesystemType.Btrfs) + if (fsType == FilesystemType.Btrfs) { try { @@ -163,6 +154,41 @@ public sealed class FileCompactor : IDisposable GC.SuppressFinalize(this); } + [DllImport("libc", SetLastError = true)] + private static extern int statvfs(string path, out Statvfs buf); + + [StructLayout(LayoutKind.Sequential)] + private struct Statvfs + { + public ulong f_bsize; + public ulong f_frsize; + public ulong f_blocks; + public ulong f_bfree; + public ulong f_bavail; + public ulong f_files; + public ulong f_ffree; + public ulong f_favail; + public ulong f_fsid; + public ulong f_flag; + public ulong f_namemax; + } + + private static int GetLinuxBlockSize(string path) + { + try + { + int result = statvfs(path, out var buf); + if (result != 0) + return -1; + + return (int)buf.f_frsize; + } + catch + { + return -1; + } + } + [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); @@ -190,7 +216,7 @@ public sealed class FileCompactor : IDisposable return; } - var fsType = FileSystemHelper.GetFilesystemType(filePath); + var fsType = GetFilesystemType(filePath); var oldSize = fi.Length; int clusterSize = GetClusterSize(fi); @@ -201,7 +227,7 @@ public sealed class FileCompactor : IDisposable } // NTFS Compression. - if (fsType == FileSystemHelper.FilesystemType.NTFS && !_dalamudUtilService.IsWine) + if (fsType == FilesystemType.NTFS && !_dalamudUtilService.IsWine) { if (!IsWOFCompactedFile(filePath)) { @@ -250,6 +276,17 @@ public sealed class FileCompactor : IDisposable } } + private static long GetFileSizeOnDisk(FileInfo fileInfo, Func getClusterSize) + { + int clusterSize = getClusterSize(fileInfo); + if (clusterSize <= 0) + return fileInfo.Length; + + uint low = GetCompressedFileSizeW(fileInfo.FullName, out uint high); + long compressed = ((long)high << 32) | low; + return ((compressed + clusterSize - 1) / clusterSize) * clusterSize; + } + private static long RunStatGetBlocks(string path) { var psi = new ProcessStartInfo("stat", $"-c %b \"{path}\"") @@ -280,11 +317,10 @@ public sealed class FileCompactor : IDisposable private void DecompressFile(string path) { _logger.LogDebug("Removing compression from {file}", path); - var fsType = FileSystemHelper.GetFilesystemType(path); - if (fsType == null) return; + var fsType = GetFilesystemType(path); //NTFS Decompression - if (fsType == FileSystemHelper.FilesystemType.NTFS && !_dalamudUtilService.IsWine) + if (fsType == FilesystemType.NTFS && !_dalamudUtilService.IsWine) { try { @@ -304,7 +340,7 @@ public sealed class FileCompactor : IDisposable } //BTRFS Decompression - if (fsType == FileSystemHelper.FilesystemType.Btrfs) + if (fsType == FilesystemType.Btrfs) { try { @@ -360,16 +396,60 @@ public sealed class FileCompactor : IDisposable private int GetClusterSize(FileInfo fi) { - if (!fi.Exists) return -1; - var root = fi.Directory?.Root.FullName.ToLower() ?? string.Empty; - if (string.IsNullOrEmpty(root)) return -1; - if (_clusterSizes.TryGetValue(root, out int value)) return value; - _logger.LogDebug("Getting Cluster Size for {path}, root {root}", fi.FullName, root); - int result = GetDiskFreeSpaceW(root, out uint sectorsPerCluster, out uint bytesPerSector, out _, out _); - if (result == 0) return -1; - _clusterSizes[root] = (int)(sectorsPerCluster * bytesPerSector); - _logger.LogDebug("Determined Cluster Size for root {root}: {cluster}", root, _clusterSizes[root]); - return _clusterSizes[root]; + try + { + if (!fi.Exists) + return -1; + + var root = fi.Directory?.Root.FullName; + if (string.IsNullOrEmpty(root)) + return -1; + + root = root.ToLowerInvariant(); + + if (_clusterSizes.TryGetValue(root, out int cached)) + return cached; + + _logger.LogDebug("Determining cluster/block size for {path} (root: {root})", fi.FullName, root); + + int clusterSize; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + int result = GetDiskFreeSpaceW( + root, + out uint sectorsPerCluster, + out uint bytesPerSector, + out _, + out _); + + if (result == 0) + { + _logger.LogWarning("GetDiskFreeSpaceW failed for {root}", root); + return -1; + } + + clusterSize = (int)(sectorsPerCluster * bytesPerSector); + } + else + { + clusterSize = GetLinuxBlockSize(root); + if (clusterSize <= 0) + { + _logger.LogWarning("Failed to determine block size for {root}", root); + return -1; + } + } + + _clusterSizes[root] = clusterSize; + _logger.LogDebug("Determined cluster/block size for {root}: {cluster} bytes", root, clusterSize); + return clusterSize; + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Error determining cluster size for {file}", fi.FullName); + return -1; + } } public static bool UseSafeHandle(SafeHandle handle, Func action) @@ -418,7 +498,6 @@ public sealed class FileCompactor : IDisposable string output = proc.StandardOutput.ReadToEnd(); proc.WaitForExit(); - // look for "flags: compressed" in the output if (output.Contains("flags: compressed", StringComparison.OrdinalIgnoreCase)) { return true;