Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove need for libc6-dev on known linux runtimes #208

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 158 additions & 10 deletions src/Pkcs11Interop/Common/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,34 +101,182 @@ internal static class NativeMethods
/// Human readable string describing the most recent error that occurred from dlopen(), dlsym() or dlclose() since the last call to dlerror().
/// </summary>
/// <returns>Human readable string describing the most recent error or NULL if no errors have occurred since initialization or since it was last called.</returns>
[DllImport("libdl", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr dlerror();

internal static IntPtr dlerror()
{
if (Platform.IsMono)
return UnixMono.dlerror();
if (Platform.IsNetCore)
return UnixNetCore.dlerror();

return Unix.dlerror();
}

/// <summary>
/// Loads the dynamic library
/// </summary>
/// <param name='filename'>Library filename.</param>
/// <param name='flag'>RTLD_LAZY for lazy function call binding or RTLD_NOW immediate function call binding.</param>
/// <returns>Handle for the dynamic library if successful, IntPtr.Zero otherwise.</returns>
[DllImport("libdl", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr dlopen(string filename, int flag);
internal static IntPtr dlopen(string filename, int flag)
{
if (Platform.IsMono)
return UnixMono.dlopen(filename, flag);
if (Platform.IsNetCore)
return UnixNetCore.dlopen(filename, flag);

return Unix.dlopen(filename, flag);
}

/// <summary>
/// Decrements the reference count on the dynamic library handle. If the reference count drops to zero and no other loaded libraries use symbols in it, then the dynamic library is unloaded.
/// </summary>
/// <param name='handle'>Handle for the dynamic library.</param>
/// <returns>Returns 0 on success, and nonzero on error.</returns>
[DllImport("libdl", CallingConvention = CallingConvention.Cdecl)]
internal static extern int dlclose(IntPtr handle);

internal static int dlclose(IntPtr handle)
{
if (Platform.IsMono)
return UnixMono.dlclose(handle);
if (Platform.IsNetCore)
return UnixNetCore.dlclose(handle);

return Unix.dlclose(handle);
}

/// <summary>
/// Returns the address where the symbol is loaded into memory.
/// </summary>
/// <param name='handle'>Handle for the dynamic library.</param>
/// <param name='symbol'>Name of symbol that should be addressed.</param>
/// <returns>Returns 0 on success, and nonzero on error.</returns>
[DllImport("libdl", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr dlsym(IntPtr handle, string symbol);
internal static IntPtr dlsym(IntPtr handle, string symbol)
{
if (Platform.IsMono)
return UnixMono.dlsym(handle, symbol);
if (Platform.IsNetCore)
return UnixNetCore.dlsym(handle, symbol);

return Unix.dlsym(handle, symbol);
}

/// <summary>
/// On Linux systems, using dlopen and dlsym results in
/// DllNotFoundException("libdl.so not found") if libc6-dev
/// is not installed. As a workaround, we load symbols for
/// dlopen and dlsym from the current process as on Linux
/// Mono sure is linked against these symbols.
/// </summary>
static class UnixMono
{
/// <summary>
/// Human readable string describing the most recent error that occurred from dlopen(), dlsym() or dlclose() since the last call to dlerror().
/// </summary>
/// <returns>Human readable string describing the most recent error or NULL if no errors have occurred since initialization or since it was last called.</returns>
[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr dlerror();

/// <summary>
/// Loads the dynamic library
/// </summary>
/// <param name='filename'>Library filename.</param>
/// <param name='flag'>RTLD_LAZY for lazy function call binding or RTLD_NOW immediate function call binding.</param>
/// <returns>Handle for the dynamic library if successful, IntPtr.Zero otherwise.</returns>
[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr dlopen(string filename, int flag);

/// <summary>
/// Decrements the reference count on the dynamic library handle. If the reference count drops to zero and no other loaded libraries use symbols in it, then the dynamic library is unloaded.
/// </summary>
/// <param name='handle'>Handle for the dynamic library.</param>
/// <returns>Returns 0 on success, and nonzero on error.</returns>
[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
internal static extern int dlclose(IntPtr handle);

/// <summary>
/// Returns the address where the symbol is loaded into memory.
/// </summary>
/// <param name='handle'>Handle for the dynamic library.</param>
/// <param name='symbol'>Name of symbol that should be addressed.</param>
/// <returns>Returns 0 on success, and nonzero on error.</returns>
[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr dlsym(IntPtr handle, string symbol);
}

/// <summary>
/// Similarly as for Mono on Linux, we load symbols for
/// dlopen and dlsym from the "libcoreclr.so",
/// to avoid the dependency on libc-dev Linux.
/// </summary>
static class UnixNetCore
{
/// <summary>
/// Human readable string describing the most recent error that occurred from dlopen(), dlsym() or dlclose() since the last call to dlerror().
/// </summary>
/// <returns>Human readable string describing the most recent error or NULL if no errors have occurred since initialization or since it was last called.</returns>
[DllImport("libcoreclr", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr dlerror();

/// <summary>
/// Loads the dynamic library
/// </summary>
/// <param name='filename'>Library filename.</param>
/// <param name='flag'>RTLD_LAZY for lazy function call binding or RTLD_NOW immediate function call binding.</param>
/// <returns>Handle for the dynamic library if successful, IntPtr.Zero otherwise.</returns>
[DllImport("libcoreclr", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr dlopen(string filename, int flag);

/// <summary>
/// Decrements the reference count on the dynamic library handle. If the reference count drops to zero and no other loaded libraries use symbols in it, then the dynamic library is unloaded.
/// </summary>
/// <param name='handle'>Handle for the dynamic library.</param>
/// <returns>Returns 0 on success, and nonzero on error.</returns>
[DllImport("libcoreclr", CallingConvention = CallingConvention.Cdecl)]
internal static extern int dlclose(IntPtr handle);

/// <summary>
/// Returns the address where the symbol is loaded into memory.
/// </summary>
/// <param name='handle'>Handle for the dynamic library.</param>
/// <param name='symbol'>Name of symbol that should be addressed.</param>
/// <returns>Returns 0 on success, and nonzero on error.</returns>
[DllImport("libcoreclr", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr dlsym(IntPtr handle, string symbol);
}

static class Unix
{
/// <summary>
/// Human readable string describing the most recent error that occurred from dlopen(), dlsym() or dlclose() since the last call to dlerror().
/// </summary>
/// <returns>Human readable string describing the most recent error or NULL if no errors have occurred since initialization or since it was last called.</returns>
[DllImport("libdl", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr dlerror();

/// <summary>
/// Loads the dynamic library
/// </summary>
/// <param name='filename'>Library filename.</param>
/// <param name='flag'>RTLD_LAZY for lazy function call binding or RTLD_NOW immediate function call binding.</param>
/// <returns>Handle for the dynamic library if successful, IntPtr.Zero otherwise.</returns>
[DllImport("libdl", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr dlopen(string filename, int flag);

/// <summary>
/// Decrements the reference count on the dynamic library handle. If the reference count drops to zero and no other loaded libraries use symbols in it, then the dynamic library is unloaded.
/// </summary>
/// <param name='handle'>Handle for the dynamic library.</param>
/// <returns>Returns 0 on success, and nonzero on error.</returns>
[DllImport("libdl", CallingConvention = CallingConvention.Cdecl)]
internal static extern int dlclose(IntPtr handle);

/// <summary>
/// Returns the address where the symbol is loaded into memory.
/// </summary>
/// <param name='handle'>Handle for the dynamic library.</param>
/// <param name='symbol'>Name of symbol that should be addressed.</param>
/// <returns>Returns 0 on success, and nonzero on error.</returns>
[DllImport("libdl", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr dlsym(IntPtr handle, string symbol);
}

#endregion
}
Expand Down
60 changes: 60 additions & 0 deletions src/Pkcs11Interop/Common/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,44 @@ public static bool IsMacOsX
}
}

/// <summary>
/// True if runtime is .NET (version >= 5.0) or .NET Core
/// </summary>
private static bool _isNetCore;

/// <summary>
/// True if runtime is .NET (version >= 5.0) or .NET Core
/// </summary>
public static bool IsNetCore
{
get
{
if (!_runtimeDetected)
DetectRuntime();

return _isNetCore;
}
}

/// <summary>
/// True if runtime is Mono
/// </summary>
private static bool _isMono;

/// <summary>
/// True if runtime is Mono
/// </summary>
public static bool IsMono
{
get
{
if (!_runtimeDetected)
DetectRuntime();

return _isMono;
}
}

/// <summary>
/// Size of native (unmanaged) long type
/// </summary>
Expand Down Expand Up @@ -268,5 +306,27 @@ private static void DetectPlatform()

#endif
}

/// <summary>
/// True if runtime detection was performed
/// </summary>
private static bool _runtimeDetected = false;

/// <summary>
/// Performs runtime detection
/// </summary>
private static void DetectRuntime()
{
#if NETSTANDARD
_isNetCore = Environment.Version.Major >= 5 ||
RuntimeInformation.FrameworkDescription.StartsWith(".NET Core");
#else
_isNetCore = false;
#endif

_isMono = Type.GetType("Mono.Runtime") != null;

_runtimeDetected = true;
}
}
}