From 83dd49c4ae32acfdd1c070f28f2eada09ad27be2 Mon Sep 17 00:00:00 2001 From: Ben Olden-Cooligan Date: Sat, 22 Oct 2022 17:29:04 -0700 Subject: [PATCH] Fix SANE environment vars --- NAPS2.App.Mac/NAPS2.App.Mac.csproj | 2 +- .../NAPS2.Sdk.ScannerTests.csproj | 2 +- NAPS2.Sdk/Platform/ISystemCompat.cs | 2 ++ NAPS2.Sdk/Platform/LinuxSystemCompat.cs | 2 ++ NAPS2.Sdk/Platform/Mac/MacInterop.cs | 3 +++ NAPS2.Sdk/Platform/MacSystemCompat.cs | 6 +++-- NAPS2.Sdk/Platform/WindowsSystemCompat.cs | 2 ++ .../Internal/Sane/Native/SaneNativeLibrary.cs | 27 +++++++++++++++++++ 8 files changed, 42 insertions(+), 4 deletions(-) diff --git a/NAPS2.App.Mac/NAPS2.App.Mac.csproj b/NAPS2.App.Mac/NAPS2.App.Mac.csproj index 861b3279dc..71f8702810 100644 --- a/NAPS2.App.Mac/NAPS2.App.Mac.csproj +++ b/NAPS2.App.Mac/NAPS2.App.Mac.csproj @@ -25,7 +25,7 @@ - + diff --git a/NAPS2.Sdk.ScannerTests/NAPS2.Sdk.ScannerTests.csproj b/NAPS2.Sdk.ScannerTests/NAPS2.Sdk.ScannerTests.csproj index acfa2e7f74..4994fa7db8 100644 --- a/NAPS2.Sdk.ScannerTests/NAPS2.Sdk.ScannerTests.csproj +++ b/NAPS2.Sdk.ScannerTests/NAPS2.Sdk.ScannerTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/NAPS2.Sdk/Platform/ISystemCompat.cs b/NAPS2.Sdk/Platform/ISystemCompat.cs index 8f857dc9b2..f8fdb94653 100644 --- a/NAPS2.Sdk/Platform/ISystemCompat.cs +++ b/NAPS2.Sdk/Platform/ISystemCompat.cs @@ -37,4 +37,6 @@ public interface ISystemCompat IDisposable? FileReadLock(string path); IDisposable? FileWriteLock(string path); + + void SetEnv(string name, string value); } \ No newline at end of file diff --git a/NAPS2.Sdk/Platform/LinuxSystemCompat.cs b/NAPS2.Sdk/Platform/LinuxSystemCompat.cs index 156c737ed5..486b78a19d 100644 --- a/NAPS2.Sdk/Platform/LinuxSystemCompat.cs +++ b/NAPS2.Sdk/Platform/LinuxSystemCompat.cs @@ -39,6 +39,8 @@ public class LinuxSystemCompat : ISystemCompat public string GetLoadError() => LinuxInterop.dlerror(); + public void SetEnv(string name, string value) => throw new NotSupportedException(); + public IDisposable FileReadLock(string path) => new FileStream(path, FileMode.Open, FileAccess.Read); public IDisposable FileWriteLock(string path) => new FileStream(path, FileMode.Open, FileAccess.Write); diff --git a/NAPS2.Sdk/Platform/Mac/MacInterop.cs b/NAPS2.Sdk/Platform/Mac/MacInterop.cs index ac520aa159..48f2df6314 100644 --- a/NAPS2.Sdk/Platform/Mac/MacInterop.cs +++ b/NAPS2.Sdk/Platform/Mac/MacInterop.cs @@ -12,4 +12,7 @@ public static class MacInterop [DllImport("libSystem.dylib")] public static extern IntPtr dlsym(IntPtr handle, string symbol); + + [DllImport("libSystem.dylib")] + public static extern int setenv(string name, string value, int overwrite); } \ No newline at end of file diff --git a/NAPS2.Sdk/Platform/MacSystemCompat.cs b/NAPS2.Sdk/Platform/MacSystemCompat.cs index 44a2f0d113..bf04ff66f7 100644 --- a/NAPS2.Sdk/Platform/MacSystemCompat.cs +++ b/NAPS2.Sdk/Platform/MacSystemCompat.cs @@ -43,9 +43,9 @@ public string[] LibrarySearchPaths public string PdfiumLibraryName => "libpdfium.dylib"; - public string[] SaneLibraryDeps => new[] { "libusb.dylib", "libjpeg.dylib" }; + public string[] SaneLibraryDeps => new[] { "libusb-1.0.0.dylib", "libjpeg.62.dylib" }; - public string SaneLibraryName => "libsane.dylib"; + public string SaneLibraryName => "libsane.1.dylib"; public IntPtr LoadLibrary(string path) => MacInterop.dlopen(path, RTLD_LAZY | RTLD_GLOBAL); @@ -53,6 +53,8 @@ public string[] LibrarySearchPaths public string GetLoadError() => MacInterop.dlerror(); + public void SetEnv(string name, string value) => MacInterop.setenv(name, value, 1); + public IDisposable FileReadLock(string path) => new FileStream(path, FileMode.Open, FileAccess.Read); public IDisposable FileWriteLock(string path) => new FileStream(path, FileMode.Open, FileAccess.Write); diff --git a/NAPS2.Sdk/Platform/WindowsSystemCompat.cs b/NAPS2.Sdk/Platform/WindowsSystemCompat.cs index 1ed71681c6..6acae14e83 100644 --- a/NAPS2.Sdk/Platform/WindowsSystemCompat.cs +++ b/NAPS2.Sdk/Platform/WindowsSystemCompat.cs @@ -38,6 +38,8 @@ public abstract class WindowsSystemCompat : ISystemCompat public abstract IntPtr LoadSymbol(IntPtr libraryHandle, string symbol); + public void SetEnv(string name, string value) => throw new NotSupportedException(); + public IDisposable? FileReadLock(string path) => null; public IDisposable? FileWriteLock(string path) => null; diff --git a/NAPS2.Sdk/Scan/Internal/Sane/Native/SaneNativeLibrary.cs b/NAPS2.Sdk/Scan/Internal/Sane/Native/SaneNativeLibrary.cs index 0c26e79db6..c3894cd0c0 100644 --- a/NAPS2.Sdk/Scan/Internal/Sane/Native/SaneNativeLibrary.cs +++ b/NAPS2.Sdk/Scan/Internal/Sane/Native/SaneNativeLibrary.cs @@ -10,6 +10,21 @@ public class SaneNativeLibrary : Unmanaged.NativeLibrary var libraryPath = FindPath(PlatformCompat.System.SaneLibraryName, testRoot); var libraryDeps = PlatformCompat.System.SaneLibraryDeps ?.Select(path => FindPath(path, testRoot)).ToArray(); + if (libraryDeps != null) + { + // If we're using a bundled SANE, we will need to manually set the environment + // variables to the appropriate folders. + var backendsFolder = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(libraryPath)!, "sane")); + var configFolder = + Path.GetFullPath(Path.Combine(Path.GetDirectoryName(libraryPath)!, "..", "_config", "sane")); + // We can't use Environment.SetEnvironmentVariable as that will just change the .NET + // env and won't be visible to SANE. Instead we use setenv which is technically not + // thread-safe but in practice should be fine here. + PlatformCompat.System.SetEnv("LD_LIBRARY_PATH", backendsFolder); + PlatformCompat.System.SetEnv("SANE_CONFIG_DIR", configFolder); + // Note: We can add SANE debug variables here + // PlatformCompat.System.SetEnv("SANE_DEBUG_DLL", "255"); + } var nativeLib = new SaneNativeLibrary(libraryPath, libraryDeps); return nativeLib; }); @@ -22,16 +37,26 @@ private SaneNativeLibrary(string libraryPath, string[]? libraryDeps) } public delegate SaneStatus sane_init_delegate(out int version_code, IntPtr authorize); + public delegate void sane_exit_delegate(); + public delegate SaneStatus sane_get_devices_delegate(out IntPtr device_list, int local_only); + public delegate SaneStatus sane_open_delegate(string name, out IntPtr handle); + public delegate void sane_close_delegate(IntPtr handle); + public delegate IntPtr sane_get_option_descriptor_delegate(IntPtr handle, int n); + public delegate SaneStatus sane_control_option_delegate(IntPtr handle, int n, SaneOptionAction a, IntPtr v, out SaneOptionSetInfo i); + public delegate SaneStatus sane_get_parameters_delegate(IntPtr handle, out SaneReadParameters p); + public delegate SaneStatus sane_start_delegate(IntPtr handle); + public delegate SaneStatus sane_read_delegate(IntPtr handle, byte[] buf, int maxlen, out int len); + public delegate void sane_cancel_delegate(IntPtr handle); public sane_init_delegate sane_init => Load(); @@ -39,8 +64,10 @@ public delegate SaneStatus sane_control_option_delegate(IntPtr handle, int n, Sa public sane_get_devices_delegate sane_get_devices => Load(); public sane_open_delegate sane_open => Load(); public sane_close_delegate sane_close => Load(); + public sane_get_option_descriptor_delegate sane_get_option_descriptor => Load(); + public sane_control_option_delegate sane_control_option => Load(); public sane_get_parameters_delegate sane_get_parameters => Load(); public sane_start_delegate sane_start => Load();