checkpoint
This commit is contained in:
33
Alpm/API.cs
Normal file
33
Alpm/API.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
public static class API
|
||||
{
|
||||
public static readonly string Version = alpm.alpm_version();
|
||||
|
||||
internal static void WrapError(SafeAlpmHandle h, Func<int> f)
|
||||
{
|
||||
var err = f();
|
||||
if (err != 0)
|
||||
{
|
||||
throw new Exception(alpm.alpm_errno(h));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles the pattern where <0 is exceptional, but 1 is some "false"
|
||||
* condition.
|
||||
*/
|
||||
internal static bool WrapErrorBool(SafeAlpmHandle h, Func<int> f)
|
||||
{
|
||||
var err = f();
|
||||
if (err < 0)
|
||||
{
|
||||
throw new Exception(alpm.alpm_errno(h));
|
||||
}
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
11
Alpm/Alpm.csproj
Normal file
11
Alpm/Alpm.csproj
Normal file
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Module</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>Foodsoft.Alpm</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
8
Alpm/Backup.cs
Normal file
8
Alpm/Backup.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
public struct Backup
|
||||
{
|
||||
private string _name;
|
||||
private string _hash;
|
||||
}
|
||||
}
|
||||
19
Alpm/CachePackage.cs
Normal file
19
Alpm/CachePackage.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
public class CachePackage : Package
|
||||
{
|
||||
// ReSharper disable once SuggestBaseTypeForParameter
|
||||
internal CachePackage(SafeCachePackageHandle handle, Database db) : base(handle)
|
||||
{
|
||||
DB = db;
|
||||
}
|
||||
|
||||
public override Database? DB { get; }
|
||||
|
||||
public void SetInstallReason(InstallReason reason)
|
||||
{
|
||||
if (alpm.alpm_pkg_set_reason(Handle, reason) != 0)
|
||||
throw new Exception(alpm.alpm_errno(((SafeCachePackageHandle) Handle).SafeAlpmHandle));
|
||||
}
|
||||
}
|
||||
}
|
||||
131
Alpm/CollectionWrapper`2.cs
Normal file
131
Alpm/CollectionWrapper`2.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// FIXME: This is increasing the ref-count on AlpmHandle all the time, so this is NOT correct for database handles,
|
||||
// or other handles that have a dispose that is not a no-op.
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal class CollectionWrapper<TImpl, TElement> : ICollection<TElement> where TImpl : struct,
|
||||
IItemsAccessor<TElement>
|
||||
{
|
||||
private TImpl _impl;
|
||||
|
||||
public CollectionWrapper(TImpl impl)
|
||||
{
|
||||
_impl = impl;
|
||||
}
|
||||
|
||||
private static unsafe IntPtr ListNext(IntPtr list) => ((alpm_list_t*) list)->next;
|
||||
private static unsafe IntPtr ListData(IntPtr list) => ((alpm_list_t*) list)->data;
|
||||
public IEnumerator<TElement> GetEnumerator()
|
||||
{
|
||||
var safeAlpmHandle = _impl.SafeAlpmHandle;
|
||||
var release = false;
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
safeAlpmHandle.DangerousAddRef(ref release);
|
||||
if (!release) throw new ObjectDisposedException(_impl.GetType().FullName);
|
||||
for (var list = _impl.GetItems(); list != IntPtr.Zero; list = ListNext(list))
|
||||
{
|
||||
yield return _impl.PtrToItem(ListData(list));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (release)
|
||||
safeAlpmHandle.DangerousRelease();
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
public void Add(TElement item)
|
||||
{
|
||||
_impl.AddItem(item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_impl.SetItems(IntPtr.Zero);
|
||||
}
|
||||
|
||||
|
||||
public bool Contains(TElement item)
|
||||
{
|
||||
var safeAlpmHandle = _impl.SafeAlpmHandle;
|
||||
var release = false;
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
safeAlpmHandle.DangerousAddRef(ref release);
|
||||
return _impl.FindItem(item) != IntPtr.Zero;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (release)
|
||||
safeAlpmHandle.DangerousRelease();
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyTo(TElement[] array, int arrayIndex)
|
||||
{
|
||||
var safeAlpmHandle = _impl.SafeAlpmHandle;
|
||||
var release = false;
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
safeAlpmHandle.DangerousAddRef(ref release);
|
||||
var intPtr = _impl.GetItems();
|
||||
unsafe
|
||||
{
|
||||
for (var list = (alpm_list_t*) intPtr; list != null; list = alpm.alpm_list_next(list))
|
||||
{
|
||||
array[arrayIndex++] = _impl.PtrToItem(list->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (release)
|
||||
safeAlpmHandle.DangerousRelease();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(TElement item)
|
||||
{
|
||||
var err = _impl.RemoveItem(item);
|
||||
if (err < 0)
|
||||
{
|
||||
throw new Exception(alpm.alpm_errno(_impl.SafeAlpmHandle));
|
||||
}
|
||||
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
var safeAlpmHandle = _impl.SafeAlpmHandle;
|
||||
var release = false;
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
safeAlpmHandle.DangerousAddRef(ref release);
|
||||
return (int) alpm.alpm_list_count(_impl.GetItems());
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (release)
|
||||
safeAlpmHandle.DangerousRelease();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
}
|
||||
}
|
||||
102
Alpm/Database.cs
Normal file
102
Alpm/Database.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
public sealed class Database : IDisposable
|
||||
{
|
||||
private readonly SafeDatabaseHandle _handle;
|
||||
|
||||
internal Database(SafeDatabaseHandle handle) => _handle = handle;
|
||||
|
||||
public void Unregister()
|
||||
{
|
||||
try
|
||||
{
|
||||
API.WrapError(_handle.SafeAlpmHandle, () => alpm.alpm_db_unregister(_handle));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_handle.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private readonly struct ServersAccessor : IItemsReader<string, SafeDatabaseHandle>
|
||||
{
|
||||
internal ServersAccessor(SafeDatabaseHandle handle)
|
||||
{
|
||||
Handle = handle;
|
||||
}
|
||||
|
||||
public SafeDatabaseHandle Handle { get; }
|
||||
public IntPtr GetItems() => alpm.alpm_db_get_servers(Handle);
|
||||
public string PtrToItem(IntPtr p) => Marshal.PtrToStringUTF8(p)!;
|
||||
}
|
||||
|
||||
public void AddServer(string url) => API.WrapError(_handle.SafeAlpmHandle, () => alpm.alpm_db_add_server(_handle, url));
|
||||
|
||||
public bool RemoveServer(string url) => API.WrapErrorBool(_handle.SafeAlpmHandle, () => alpm.alpm_db_remove_server(_handle, url));
|
||||
|
||||
public IEnumerable<string> Servers
|
||||
{
|
||||
get => new EnumerableWrapper<ServersAccessor, string, SafeDatabaseHandle>(new ServersAccessor(_handle));
|
||||
set
|
||||
{
|
||||
foreach (var s in value)
|
||||
{
|
||||
API.WrapError(_handle.SafeAlpmHandle, () => alpm.alpm_db_add_server(_handle, s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Name => alpm.alpm_db_get_name(_handle);
|
||||
|
||||
public SigLevel SigLevel => alpm.alpm_db_get_siglevel(_handle);
|
||||
|
||||
public ErrNo Valid =>
|
||||
alpm.alpm_db_get_valid(_handle) != 0 ? alpm.alpm_errno(_handle.SafeAlpmHandle) : ErrNo.ERR_OK;
|
||||
|
||||
public bool Update(bool force = false)
|
||||
{
|
||||
var err = alpm.alpm_db_update(force ? 1 : 0, _handle);
|
||||
if (err < 0)
|
||||
{
|
||||
throw new Exception(_handle.SafeAlpmHandle);
|
||||
}
|
||||
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
public Package? GetPackage(string name)
|
||||
{
|
||||
var pkgPtr = alpm.alpm_pkg_get_pkg(_handle, name);
|
||||
if (pkgPtr == IntPtr.Zero)
|
||||
{
|
||||
var err = alpm.alpm_errno(_handle.SafeAlpmHandle);
|
||||
if (err == ErrNo.ERR_PKG_NOT_FOUND)
|
||||
return null;
|
||||
throw new Exception(err);
|
||||
}
|
||||
|
||||
return new CachePackage(new SafeCachePackageHandle(pkgPtr, _handle), this);
|
||||
}
|
||||
|
||||
public PackageList PackageCache
|
||||
{
|
||||
get
|
||||
{
|
||||
var listPtr = alpm.alpm_db_get_pkgcache(_handle);
|
||||
if (listPtr == IntPtr.Zero)
|
||||
throw new Exception(alpm.alpm_errno(_handle.SafeAlpmHandle));
|
||||
return new PackageList(new SafeListHandle<SafeDatabaseHandle>(listPtr, _handle), this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_handle.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Alpm/Depend.cs
Normal file
34
Alpm/Depend.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[SuppressMessage("ReSharper", "ConvertToConstant.Local")]
|
||||
public class Depend
|
||||
{
|
||||
public enum ModType
|
||||
{
|
||||
Any = 1,
|
||||
Equal,
|
||||
GreaterThanOrEqual,
|
||||
LessThanOrEqual,
|
||||
GreaterThan,
|
||||
LessThan
|
||||
}
|
||||
|
||||
[field: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public string Name { get; } = null!;
|
||||
|
||||
[field: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public string Version { get; } = null!;
|
||||
|
||||
[field: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public string Description { get; } = null!;
|
||||
|
||||
public ulong NameHash { get; } = 0;
|
||||
public ModType Mod { get; } = ModType.Any;
|
||||
}
|
||||
}
|
||||
44
Alpm/EnumerableWrapper`3.cs
Normal file
44
Alpm/EnumerableWrapper`3.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal struct EnumerableWrapper<TImpl, TElement, THandle> : IEnumerable<TElement> where TImpl : struct,
|
||||
IItemsReader<TElement, THandle>
|
||||
where THandle : SafeHandle
|
||||
{
|
||||
private TImpl _impl;
|
||||
|
||||
public EnumerableWrapper(TImpl impl)
|
||||
{
|
||||
_impl = impl;
|
||||
}
|
||||
|
||||
public IEnumerator<TElement> GetEnumerator()
|
||||
{
|
||||
var handle = _impl.Handle;
|
||||
var release = false;
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
handle.DangerousAddRef(ref release);
|
||||
if (!release) throw new ObjectDisposedException(_impl.GetType().FullName);
|
||||
for (var list = _impl.GetItems(); list != IntPtr.Zero; list = Wrapper.ListNext(list))
|
||||
{
|
||||
yield return _impl.PtrToItem(Wrapper.ListData(list));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (release)
|
||||
handle.DangerousRelease();
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
}
|
||||
81
Alpm/ErrNo.cs
Normal file
81
Alpm/ErrNo.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
public enum ErrNo
|
||||
{
|
||||
ERR_OK = 0,
|
||||
ERR_MEMORY,
|
||||
ERR_SYSTEM,
|
||||
ERR_BADPERMS,
|
||||
ERR_NOT_A_FILE,
|
||||
ERR_NOT_A_DIR,
|
||||
ERR_WRONG_ARGS,
|
||||
ERR_DISK_SPACE,
|
||||
|
||||
/* Interface */
|
||||
ERR_HANDLE_NULL,
|
||||
ERR_HANDLE_NOT_NULL,
|
||||
ERR_HANDLE_LOCK,
|
||||
|
||||
/* Databases */
|
||||
ERR_DB_OPEN,
|
||||
ERR_DB_CREATE,
|
||||
ERR_DB_NULL,
|
||||
ERR_DB_NOT_NULL,
|
||||
ERR_DB_NOT_FOUND,
|
||||
ERR_DB_INVALID,
|
||||
ERR_DB_INVALID_SIG,
|
||||
ERR_DB_VERSION,
|
||||
ERR_DB_WRITE,
|
||||
ERR_DB_REMOVE,
|
||||
|
||||
/* Servers */
|
||||
ERR_SERVER_BAD_URL,
|
||||
ERR_SERVER_NONE,
|
||||
|
||||
/* Transactions */
|
||||
ERR_TRANS_NOT_NULL,
|
||||
ERR_TRANS_NULL,
|
||||
ERR_TRANS_DUP_TARGET,
|
||||
ERR_TRANS_NOT_INITIALIZED,
|
||||
ERR_TRANS_NOT_PREPARED,
|
||||
ERR_TRANS_ABORT,
|
||||
ERR_TRANS_TYPE,
|
||||
ERR_TRANS_NOT_LOCKED,
|
||||
ERR_TRANS_HOOK_FAILED,
|
||||
|
||||
/* Packages */
|
||||
ERR_PKG_NOT_FOUND,
|
||||
ERR_PKG_IGNORED,
|
||||
ERR_PKG_INVALID,
|
||||
ERR_PKG_INVALID_CHECKSUM,
|
||||
ERR_PKG_INVALID_SIG,
|
||||
ERR_PKG_MISSING_SIG,
|
||||
ERR_PKG_OPEN,
|
||||
ERR_PKG_CANT_REMOVE,
|
||||
ERR_PKG_INVALID_NAME,
|
||||
ERR_PKG_INVALID_ARCH,
|
||||
ERR_PKG_REPO_NOT_FOUND,
|
||||
|
||||
/* Signatures */
|
||||
ERR_SIG_MISSING,
|
||||
ERR_SIG_INVALID,
|
||||
|
||||
/* Dependencies */
|
||||
ERR_UNSATISFIED_DEPS,
|
||||
ERR_CONFLICTING_DEPS,
|
||||
ERR_FILE_CONFLICTS,
|
||||
|
||||
/* Misc */
|
||||
ERR_RETRIEVE,
|
||||
ERR_INVALID_REGEX,
|
||||
|
||||
/* External library errors */
|
||||
ERR_LIBARCHIVE,
|
||||
ERR_LIBCURL,
|
||||
ERR_EXTERNAL_DOWNLOAD,
|
||||
ERR_GPGME,
|
||||
|
||||
/* Missing compile-time features */
|
||||
ERR_MISSING_CAPABILITY_SIGNATURES
|
||||
}
|
||||
}
|
||||
18
Alpm/Exception.cs
Normal file
18
Alpm/Exception.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Foodsoft.Alpm;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
[Serializable()]
|
||||
public class Exception : System.Exception
|
||||
{
|
||||
public Exception() { }
|
||||
internal Exception(SafeAlpmHandle handle) : base(alpm.alpm_strerror(alpm.alpm_errno(handle))) { }
|
||||
public Exception(ErrNo errno) : base(alpm.alpm_strerror(errno)) { }
|
||||
public Exception(ErrNo errno, System.Exception inner) : base(alpm.alpm_strerror(errno), inner) { }
|
||||
|
||||
protected Exception(SerializationInfo info,
|
||||
StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
}
|
||||
15
Alpm/File.cs
Normal file
15
Alpm/File.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
[SuppressMessage("ReSharper", "UnassignedGetOnlyAutoProperty")]
|
||||
public readonly struct File
|
||||
{
|
||||
[field: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public string Name { get; }
|
||||
|
||||
public long Size { get; }
|
||||
public uint Mode { get; }
|
||||
}
|
||||
}
|
||||
23
Alpm/FileList.cs
Normal file
23
Alpm/FileList.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
public class FileList : IReadOnlyList<File>
|
||||
{
|
||||
|
||||
public IEnumerator<File> GetEnumerator()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public int Count { get; }
|
||||
|
||||
public File this[int index] => throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
75
Alpm/Handle.cs
Normal file
75
Alpm/Handle.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
public sealed class Handle : IDisposable
|
||||
{
|
||||
private readonly SafeAlpmHandle _handle;
|
||||
|
||||
public Handle(string root, string dbpath)
|
||||
{
|
||||
_handle = alpm.alpm_initialize(root, dbpath, out var err);
|
||||
if (_handle.IsInvalid)
|
||||
{
|
||||
throw new Exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_handle.Dispose();
|
||||
}
|
||||
|
||||
private Database ToDatabase(IntPtr ptr)
|
||||
{
|
||||
// It's ok that the database pointer is kept outside atomic section, because the resource is actually
|
||||
// managed by the alpm handle.
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
throw new Exception(_handle);
|
||||
}
|
||||
|
||||
return new Database(new SafeDatabaseHandle(ptr, _handle));
|
||||
}
|
||||
|
||||
public Database LocalDB => ToDatabase(alpm.alpm_get_localdb(_handle));
|
||||
|
||||
public Database RegisterSyncDB(string treename, SigLevel sigLevel) =>
|
||||
ToDatabase(alpm.alpm_register_syncdb(_handle, treename, sigLevel));
|
||||
|
||||
private readonly struct CacheDirsAccessor : IItemsAccessor<string>
|
||||
{
|
||||
internal CacheDirsAccessor(SafeAlpmHandle safeAlpmHandle)
|
||||
{
|
||||
SafeAlpmHandle = safeAlpmHandle;
|
||||
}
|
||||
|
||||
public SafeAlpmHandle SafeAlpmHandle { get; }
|
||||
public IntPtr GetItems() => alpm.alpm_option_get_cachedirs(SafeAlpmHandle);
|
||||
public int SetItems(IntPtr list) => alpm.alpm_option_set_cachedirs(SafeAlpmHandle, list);
|
||||
public int AddItem(string item) => alpm.alpm_option_add_cachedir(SafeAlpmHandle, item);
|
||||
public int RemoveItem(string item) => alpm.alpm_option_remove_cachedir(SafeAlpmHandle, item);
|
||||
public IntPtr FindItem(string item) => alpm.alpm_list_find_str(GetItems(), item);
|
||||
public string PtrToItem(IntPtr p) => Marshal.PtrToStringUTF8(p)!;
|
||||
}
|
||||
|
||||
public ICollection<string> CacheDirs
|
||||
{
|
||||
get => new CollectionWrapper<CacheDirsAccessor, string>(new CacheDirsAccessor(_handle));
|
||||
set
|
||||
{
|
||||
foreach (var s in value)
|
||||
{
|
||||
API.WrapError(_handle, () => alpm.alpm_option_add_cachedir(_handle, s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShouldIgnorePackage(Package pkg)
|
||||
{
|
||||
return alpm.alpm_pkg_should_ignore(_handle, pkg.Handle) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Alpm/IAlpmItemsAccessor`1.cs
Normal file
15
Alpm/IAlpmItemsAccessor`1.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal interface IItemsAccessor<TElement>
|
||||
{
|
||||
SafeAlpmHandle SafeAlpmHandle { get; }
|
||||
public IntPtr GetItems();
|
||||
public int SetItems(IntPtr list);
|
||||
public int AddItem(TElement item);
|
||||
public int RemoveItem(TElement item);
|
||||
public IntPtr FindItem(TElement item);
|
||||
public TElement PtrToItem(IntPtr p);
|
||||
}
|
||||
}
|
||||
12
Alpm/IItemsReader`2.cs
Normal file
12
Alpm/IItemsReader`2.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal interface IItemsReader<out TElement, out THandle> where THandle : SafeHandle
|
||||
{
|
||||
public THandle Handle { get; }
|
||||
public IntPtr GetItems();
|
||||
public TElement PtrToItem(IntPtr p);
|
||||
}
|
||||
}
|
||||
64
Alpm/IPackageData.cs
Normal file
64
Alpm/IPackageData.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
public enum PackageOrigin
|
||||
{
|
||||
File = 1,
|
||||
LocalDB,
|
||||
SyncDB
|
||||
}
|
||||
|
||||
public enum InstallReason
|
||||
{
|
||||
Explicit = 0,
|
||||
Depend = 1
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ValidationType
|
||||
{
|
||||
Unknown = 0,
|
||||
None = (1 << 0),
|
||||
MD5Sum = (1 << 1),
|
||||
SHA256Sum = (1 << 2),
|
||||
Signature = (1 << 3)
|
||||
}
|
||||
|
||||
public interface IPackageData : IDisposable
|
||||
{
|
||||
public string Filename { get; }
|
||||
public string Base { get; }
|
||||
public string Name { get; }
|
||||
public string Version { get; }
|
||||
public PackageOrigin Origin { get; }
|
||||
public string Description { get; }
|
||||
public string Url { get; }
|
||||
public DateTimeOffset BuildDate { get; }
|
||||
public DateTimeOffset InstallDate { get; }
|
||||
public string Packager { get; }
|
||||
public string MD5Sum { get; }
|
||||
public string SHA256Sum { get; }
|
||||
public string Arch { get; }
|
||||
public long Size { get; }
|
||||
public long InstalledSize { get; }
|
||||
public InstallReason InstallReason { get; }
|
||||
public IEnumerable<string> Licenses { get; }
|
||||
public IReadOnlyCollection<string> Groups { get; }
|
||||
public IReadOnlyCollection<Depend> Depends { get; }
|
||||
public IReadOnlyCollection<Depend> OptDepends { get; }
|
||||
public IReadOnlyCollection<Depend> CheckDepends { get; }
|
||||
public IReadOnlyCollection<Depend> MakeDepends { get; }
|
||||
public IReadOnlyCollection<Depend> Conflicts { get; }
|
||||
public IReadOnlyCollection<Depend> Provides { get; }
|
||||
public IReadOnlyCollection<Depend> Replaces { get; }
|
||||
public IReadOnlyList<File> FileList { get; }
|
||||
public IReadOnlyList<Backup> Backup { get; }
|
||||
public string Base64Signature { get; }
|
||||
public ValidationType Validation { get; }
|
||||
public bool HasScriptlet { get; }
|
||||
public long DownloadSize { get; }
|
||||
public Database? DB { get; }
|
||||
}
|
||||
}
|
||||
345
Alpm/Junk.cs
Normal file
345
Alpm/Junk.cs
Normal file
@@ -0,0 +1,345 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
|
||||
/*
|
||||
* Hooks
|
||||
*/
|
||||
|
||||
enum alpm_hook_when_t
|
||||
{
|
||||
HOOK_PRE_TRANSACTION = 1,
|
||||
HOOK_POST_TRANSACTION
|
||||
}
|
||||
|
||||
/*
|
||||
* Logging facilities
|
||||
*/
|
||||
|
||||
/** Logging Levels */
|
||||
enum _alpm_loglevel_t
|
||||
{
|
||||
LOG_ERROR = 1,
|
||||
LOG_WARNING = (1 << 1),
|
||||
LOG_DEBUG = (1 << 2),
|
||||
LOG_FUNCTION = (1 << 3)
|
||||
}
|
||||
|
||||
|
||||
/** Location a package object was loaded from. */
|
||||
enum alpm_pkgfrom_t
|
||||
{
|
||||
PKG_FROM_FILE = 1,
|
||||
PKG_FROM_LOCALDB,
|
||||
PKG_FROM_SYNCDB
|
||||
}
|
||||
|
||||
/** Method used to validate a package. */
|
||||
enum alpm_pkgvalidation_t
|
||||
{
|
||||
PKG_VALIDATION_UNKNOWN = 0,
|
||||
PKG_VALIDATION_NONE = (1 << 0),
|
||||
PKG_VALIDATION_MD5SUM = (1 << 1),
|
||||
PKG_VALIDATION_SHA256SUM = (1 << 2),
|
||||
PKG_VALIDATION_SIGNATURE = (1 << 3)
|
||||
}
|
||||
|
||||
/** Types of version constraints in dependency specs. */
|
||||
public enum alpm_depmod_t
|
||||
{
|
||||
/** No version constraint */
|
||||
DEP_MOD_ANY = 1,
|
||||
|
||||
/** Test version equality (package=x.y.z) */
|
||||
DEP_MOD_EQ,
|
||||
|
||||
/** Test for at least a version (package>=x.y.z) */
|
||||
DEP_MOD_GE,
|
||||
|
||||
/** Test for at most a version (package<=x.y.z) */
|
||||
DEP_MOD_LE,
|
||||
|
||||
/** Test for greater than some version (package>x.y.z) */
|
||||
DEP_MOD_GT,
|
||||
|
||||
/** Test for less than some version (package<x.y.z) */
|
||||
DEP_MOD_LT
|
||||
}
|
||||
|
||||
/**
|
||||
* File conflict type.
|
||||
* Whether the conflict results from a file existing on the filesystem, or with
|
||||
* another target in the transaction.
|
||||
*/
|
||||
enum alpm_fileconflicttype_t
|
||||
{
|
||||
FILECONFLICT_TARGET = 1,
|
||||
FILECONFLICT_FILESYSTEM
|
||||
}
|
||||
|
||||
/** PGP signature verification options */
|
||||
[Flags]
|
||||
public enum SigLevel
|
||||
{
|
||||
SIG_PACKAGE = (1 << 0),
|
||||
SIG_PACKAGE_OPTIONAL = (1 << 1),
|
||||
SIG_PACKAGE_MARGINAL_OK = (1 << 2),
|
||||
SIG_PACKAGE_UNKNOWN_OK = (1 << 3),
|
||||
|
||||
SIG_DATABASE = (1 << 10),
|
||||
SIG_DATABASE_OPTIONAL = (1 << 11),
|
||||
SIG_DATABASE_MARGINAL_OK = (1 << 12),
|
||||
SIG_DATABASE_UNKNOWN_OK = (1 << 13),
|
||||
SIG_USE_DEFAULT = (1 << 31)
|
||||
}
|
||||
|
||||
/** PGP signature verification status return codes */
|
||||
enum alpm_sigstatus_t
|
||||
{
|
||||
SIGSTATUS_VALID,
|
||||
SIGSTATUS_KEY_EXPIRED,
|
||||
SIGSTATUS_SIG_EXPIRED,
|
||||
SIGSTATUS_KEY_UNKNOWN,
|
||||
SIGSTATUS_KEY_DISABLED,
|
||||
SIGSTATUS_INVALID
|
||||
}
|
||||
|
||||
/** PGP signature verification status return codes */
|
||||
enum alpm_sigvalidity_t
|
||||
{
|
||||
SIGVALIDITY_FULL,
|
||||
SIGVALIDITY_MARGINAL,
|
||||
SIGVALIDITY_NEVER,
|
||||
SIGVALIDITY_UNKNOWN
|
||||
}
|
||||
|
||||
/** Dependency */
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public struct alpm_depend_t
|
||||
{
|
||||
string name;
|
||||
string version;
|
||||
string desc;
|
||||
public ulong name_hash;
|
||||
public alpm_depmod_t mod;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct AlpmDependPtr
|
||||
{
|
||||
private IntPtr ptr;
|
||||
|
||||
public alpm_depend_t Unmarshal()
|
||||
{
|
||||
return Marshal.PtrToStructure<alpm_depend_t>(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/** Missing dependency */
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public struct alpm_depmissing_t
|
||||
{
|
||||
public string target;
|
||||
|
||||
public AlpmDependPtr depend;
|
||||
|
||||
/* this is used only in the case of a remove dependency error */
|
||||
public string causingpkg;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
/** Conflict */
|
||||
public struct alpm_conflict_t
|
||||
{
|
||||
public ulong package1_hash;
|
||||
public ulong package2_hash;
|
||||
public string package1;
|
||||
public string package2;
|
||||
public AlpmDependPtr reason;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
/** File conflict */
|
||||
struct alpm_fileconflict_t
|
||||
{
|
||||
public string target;
|
||||
public alpm_fileconflicttype_t type;
|
||||
public string file;
|
||||
public string ctarget;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
/** Package group */
|
||||
public readonly struct alpm_group_t
|
||||
{
|
||||
/** group name */
|
||||
public readonly string name;
|
||||
|
||||
/** list of alpm_pkg_t packages */
|
||||
private readonly unsafe alpm_list_t* packages;
|
||||
}
|
||||
|
||||
/* TODO: alpm_pkg_get_files - need to wrap */
|
||||
/** File in a package */
|
||||
public readonly struct alpm_file_t
|
||||
{
|
||||
public readonly string name;
|
||||
public readonly UIntPtr size;
|
||||
public readonly uint mode;
|
||||
}
|
||||
|
||||
public enum caps
|
||||
{
|
||||
ALPM_CAPABILITY_NLS = (1 << 0),
|
||||
ALPM_CAPABILITY_DOWNLOADER = (1 << 1),
|
||||
ALPM_CAPABILITY_SIGNATURES = (1 << 2)
|
||||
}
|
||||
|
||||
/** Package filelist container */
|
||||
public struct _alpm_filelist_t
|
||||
{
|
||||
public UIntPtr count;
|
||||
private IntPtr files;
|
||||
|
||||
/* FIXME: This is broken as shit */
|
||||
public alpm_file_t[] Unmarshal()
|
||||
{
|
||||
var iCount = (int) this.count;
|
||||
var byteCount = Marshal.SizeOf<alpm_file_t>() * iCount;
|
||||
var byteBuffer = new byte[byteCount];
|
||||
Marshal.Copy(files, byteBuffer, 0, byteBuffer.Length);
|
||||
var result = new alpm_file_t[iCount];
|
||||
|
||||
Buffer.BlockCopy(byteBuffer, 0, result, 0, byteBuffer.Length);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/** Local package or package file backup entry */
|
||||
public struct _alpm_backup_t
|
||||
{
|
||||
string name;
|
||||
string hash;
|
||||
}
|
||||
|
||||
public class alpm_pgpkey_t
|
||||
{
|
||||
public byte[] data;
|
||||
public string fingerprint;
|
||||
public string uid;
|
||||
public string name;
|
||||
public string email;
|
||||
public long created;
|
||||
public long expires;
|
||||
public uint revoked;
|
||||
public char pubkey_algo;
|
||||
}
|
||||
|
||||
public class PgpKeyInMarshaler : ICustomMarshaler
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
private class NativePgpKey
|
||||
{
|
||||
public IntPtr data;
|
||||
public string fingerprint;
|
||||
public string uid;
|
||||
public string name;
|
||||
public string email;
|
||||
public long created;
|
||||
public long expires;
|
||||
public uint length;
|
||||
public uint revoked;
|
||||
public char pubkey_algo;
|
||||
}
|
||||
|
||||
public void CleanUpManagedData(object ManagedObj) { }
|
||||
public void CleanUpNativeData(IntPtr pNativeData) { }
|
||||
|
||||
public int GetNativeDataSize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IntPtr MarshalManagedToNative(object ManagedObj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object MarshalNativeToManaged(IntPtr pNativeData)
|
||||
{
|
||||
var raw = Marshal.PtrToStructure<NativePgpKey>(pNativeData);
|
||||
var managed = new alpm_pgpkey_t()
|
||||
{
|
||||
data = new byte[raw.length],
|
||||
fingerprint = raw.fingerprint,
|
||||
uid = raw.uid,
|
||||
name = raw.name,
|
||||
email = raw.email,
|
||||
created = raw.created,
|
||||
expires = raw.expires,
|
||||
revoked = raw.revoked,
|
||||
pubkey_algo = raw.pubkey_algo
|
||||
};
|
||||
Marshal.Copy(raw.data, managed.data, 0, (int) raw.length);
|
||||
return managed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signature result. Contains the key, status, and validity of a given
|
||||
* signature.
|
||||
*/
|
||||
public readonly struct alpm_sigresult_t
|
||||
{
|
||||
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PgpKeyInMarshaler))]
|
||||
readonly alpm_pgpkey_t key;
|
||||
|
||||
readonly alpm_sigstatus_t status;
|
||||
readonly alpm_sigvalidity_t validity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signature list. Contains the number of signatures found and a pointer to an
|
||||
* array of results. The array is of size count.
|
||||
*/
|
||||
public class SigListInMarshaler : ICustomMarshaler
|
||||
{
|
||||
public void CleanUpManagedData(object ManagedObj) { }
|
||||
public void CleanUpNativeData(IntPtr pNativeData) { }
|
||||
|
||||
public int GetNativeDataSize()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IntPtr MarshalManagedToNative(object ManagedObj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object MarshalNativeToManaged(IntPtr pNativeData)
|
||||
{
|
||||
UIntPtr count;
|
||||
IntPtr data;
|
||||
unsafe
|
||||
{
|
||||
count = *(UIntPtr*) pNativeData;
|
||||
data = *(IntPtr*) (pNativeData + sizeof(UIntPtr));
|
||||
}
|
||||
|
||||
var iCount = (int) count;
|
||||
var result = new alpm_sigresult_t[iCount];
|
||||
// NOTE: I expect this to fail cuz i didn't implement the above GetNativeDataSize
|
||||
for (var i = 0; i < iCount; ++i, data += Marshal.SizeOf<alpm_sigresult_t>())
|
||||
{
|
||||
result[i] = Marshal.PtrToStructure<alpm_sigresult_t>(data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
73
Alpm/Package.cs
Normal file
73
Alpm/Package.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
public abstract class Package : IPackageData
|
||||
{
|
||||
internal SafePackageHandle Handle { get; }
|
||||
|
||||
internal Package(SafePackageHandle handle)
|
||||
{
|
||||
Handle = handle;
|
||||
}
|
||||
|
||||
public string Filename => alpm.alpm_pkg_get_filename(Handle);
|
||||
public string Base => alpm.alpm_pkg_get_base(Handle);
|
||||
public string Name => alpm.alpm_pkg_get_name(Handle);
|
||||
public string Version => alpm.alpm_pkg_get_version(Handle);
|
||||
public PackageOrigin Origin => alpm.alpm_pkg_get_origin(Handle);
|
||||
public string Description => alpm.alpm_pkg_get_desc(Handle);
|
||||
public string Url => alpm.alpm_pkg_get_url(Handle);
|
||||
|
||||
public DateTimeOffset BuildDate => DateTimeOffset.FromUnixTimeSeconds(alpm.alpm_pkg_get_builddate(Handle));
|
||||
public DateTimeOffset InstallDate => DateTimeOffset.FromUnixTimeSeconds(alpm.alpm_pkg_get_installdate(Handle));
|
||||
public string Packager => alpm.alpm_pkg_get_packager(Handle);
|
||||
public string MD5Sum => alpm.alpm_pkg_get_md5sum(Handle);
|
||||
public string SHA256Sum => alpm.alpm_pkg_get_sha256sum(Handle);
|
||||
public string Arch => alpm.alpm_pkg_get_arch(Handle);
|
||||
public long Size => alpm.alpm_pkg_get_size(Handle);
|
||||
public long InstalledSize => alpm.alpm_pkg_get_isize(Handle);
|
||||
public InstallReason InstallReason => alpm.alpm_pkg_get_reason(Handle);
|
||||
|
||||
public IEnumerable<string> Licenses { get; }
|
||||
public IReadOnlyCollection<string> Groups { get; }
|
||||
public IReadOnlyCollection<Depend> Depends { get; }
|
||||
public IReadOnlyCollection<Depend> OptDepends { get; }
|
||||
public IReadOnlyCollection<Depend> CheckDepends { get; }
|
||||
public IReadOnlyCollection<Depend> MakeDepends { get; }
|
||||
public IReadOnlyCollection<Depend> Conflicts { get; }
|
||||
public IReadOnlyCollection<Depend> Provides { get; }
|
||||
public IReadOnlyCollection<Depend> Replaces { get; }
|
||||
public IReadOnlyList<File> FileList { get; }
|
||||
public IReadOnlyList<Backup> Backup { get; }
|
||||
public string Base64Signature { get; }
|
||||
public ValidationType Validation { get; }
|
||||
public bool HasScriptlet { get; }
|
||||
public long DownloadSize { get; }
|
||||
public bool CheckMD5Sum()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public virtual Database? DB => null;
|
||||
|
||||
public IEnumerator<Package> ComputeRequiredBy()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerator<Package> ComputeOptionalFor()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Handle.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
51
Alpm/PackageList.cs
Normal file
51
Alpm/PackageList.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
public struct PackageList : IEnumerable<Package>, IDisposable
|
||||
{
|
||||
private SafeListHandle<SafeDatabaseHandle> _handle;
|
||||
private Database _db;
|
||||
|
||||
internal PackageList(SafeListHandle<SafeDatabaseHandle> handle, Database db)
|
||||
{
|
||||
_handle = handle;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
public IEnumerator<Package> GetEnumerator()
|
||||
{
|
||||
var release = false;
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
_handle.DangerousAddRef(ref release);
|
||||
if (!release) throw new ObjectDisposedException(_handle.GetType().FullName);
|
||||
for (var list = _handle.DangerousGetHandle(); list != IntPtr.Zero; list = Wrapper.ListNext(list))
|
||||
{
|
||||
yield return new CachePackage(
|
||||
new SafeCachePackageHandle(Wrapper.ListData(list), _handle.ParentHandle), _db);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (release)
|
||||
_handle.DangerousRelease();
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_handle.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Alpm/SafeAlpmHandle.cs
Normal file
21
Alpm/SafeAlpmHandle.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using Foodsoft.Alpm;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal sealed class SafeAlpmHandle : SafeHandle
|
||||
{
|
||||
private SafeAlpmHandle() : base(IntPtr.Zero, true) { }
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), PrePrepareMethod]
|
||||
protected override bool ReleaseHandle() => alpm.alpm_release(handle) == 0;
|
||||
|
||||
public override bool IsInvalid
|
||||
{
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
|
||||
get => handle == IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
Alpm/SafeCachePackageHandle.cs
Normal file
46
Alpm/SafeCachePackageHandle.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal sealed class SafeCachePackageHandle : SafePackageHandle
|
||||
{
|
||||
internal SafeAlpmHandle SafeAlpmHandle => SafeDatabaseHandle.SafeAlpmHandle;
|
||||
internal SafeDatabaseHandle SafeDatabaseHandle { get; } = null!;
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
[PrePrepareMethod]
|
||||
internal SafeCachePackageHandle(IntPtr ptr, SafeDatabaseHandle dbHandle)
|
||||
: base()
|
||||
{
|
||||
var success = false;
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try { }
|
||||
finally
|
||||
{
|
||||
dbHandle.DangerousAddRef(ref success);
|
||||
if (success)
|
||||
{
|
||||
SafeDatabaseHandle = dbHandle;
|
||||
handle = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
SafeDatabaseHandle.DangerousRelease();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool IsInvalid
|
||||
{
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
|
||||
get => handle == IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
Alpm/SafeDatabaseHandle.cs
Normal file
52
Alpm/SafeDatabaseHandle.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal sealed class SafeDatabaseHandle : SafeHandle
|
||||
{
|
||||
internal SafeAlpmHandle SafeAlpmHandle
|
||||
{
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[PrePrepareMethod]
|
||||
get;
|
||||
} = null!; // we always throw in the constructor on failure
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
[PrePrepareMethod]
|
||||
internal SafeDatabaseHandle(IntPtr dbPtr, SafeAlpmHandle safeAlpmHandle)
|
||||
: base(IntPtr.Zero, true)
|
||||
{
|
||||
var success = false;
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try { }
|
||||
finally
|
||||
{
|
||||
safeAlpmHandle.DangerousAddRef(ref success);
|
||||
if (success)
|
||||
{
|
||||
SafeAlpmHandle = safeAlpmHandle;
|
||||
handle = dbPtr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), PrePrepareMethod]
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
SafeAlpmHandle.DangerousRelease();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool IsInvalid
|
||||
{
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
|
||||
get => handle == IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
Alpm/SafeListHandle`1.cs
Normal file
52
Alpm/SafeListHandle`1.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal sealed class SafeListHandle<TParent> : SafeHandle where TParent: SafeHandle
|
||||
{
|
||||
internal TParent ParentHandle
|
||||
{
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
[PrePrepareMethod]
|
||||
get;
|
||||
} = null!;
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
[PrePrepareMethod]
|
||||
internal SafeListHandle(IntPtr listPtr, TParent parentHandle)
|
||||
: base(IntPtr.Zero, true)
|
||||
{
|
||||
var success = false;
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try { }
|
||||
finally
|
||||
{
|
||||
parentHandle.DangerousAddRef(ref success);
|
||||
if (success)
|
||||
{
|
||||
ParentHandle = parentHandle;
|
||||
handle = listPtr;
|
||||
}
|
||||
|
||||
}
|
||||
if (!success)
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
ParentHandle.DangerousRelease();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool IsInvalid
|
||||
{
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
|
||||
get => ParentHandle.IsInvalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Alpm/SafePackageHandle.cs
Normal file
20
Alpm/SafePackageHandle.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal class SafePackageHandle : SafeHandle
|
||||
{
|
||||
protected SafePackageHandle() : base(IntPtr.Zero, true) { }
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), PrePrepareMethod]
|
||||
protected override bool ReleaseHandle() => alpm.alpm_pkg_free(handle) == 0;
|
||||
|
||||
public override bool IsInvalid
|
||||
{
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
|
||||
get => handle == IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
55
Alpm/UTF8InMarshaler.cs
Normal file
55
Alpm/UTF8InMarshaler.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal readonly struct UTF8InMarshaler : ICustomMarshaler
|
||||
{
|
||||
private static readonly UTF8InMarshaler _instance = default;
|
||||
|
||||
public void CleanUpManagedData(object managedObj) { }
|
||||
|
||||
public void CleanUpNativeData(IntPtr pNativeData)
|
||||
{
|
||||
if (pNativeData == IntPtr.Zero)
|
||||
return;
|
||||
Marshal.FreeHGlobal(pNativeData);
|
||||
}
|
||||
|
||||
public int GetNativeDataSize() => -1;
|
||||
|
||||
public unsafe IntPtr MarshalManagedToNative(object? managedObj)
|
||||
{
|
||||
if (managedObj is null) return IntPtr.Zero;
|
||||
|
||||
var s = (string) managedObj;
|
||||
|
||||
var nb = Encoding.UTF8.GetMaxByteCount(s.Length);
|
||||
|
||||
var pMem = Marshal.AllocHGlobal(nb + 1);
|
||||
var pbMem = (byte*) pMem;
|
||||
|
||||
int nbWritten;
|
||||
fixed (char* firstChar = s)
|
||||
{
|
||||
nbWritten = Encoding.UTF8.GetBytes(firstChar, s.Length, pbMem, nb);
|
||||
}
|
||||
|
||||
pbMem[nbWritten] = 0;
|
||||
return pMem;
|
||||
}
|
||||
|
||||
public object MarshalNativeToManaged(IntPtr pNativeData)
|
||||
{
|
||||
return Marshal.PtrToStringUTF8(pNativeData)!;
|
||||
}
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
// ReSharper disable once UnusedParameter.Local
|
||||
private static ICustomMarshaler GetInstance(string cookie)
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Alpm/UTF8OutMarshaler.cs
Normal file
35
Alpm/UTF8OutMarshaler.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
|
||||
internal readonly struct UTF8OutMarshaler : ICustomMarshaler
|
||||
{
|
||||
private static readonly UTF8OutMarshaler _instance = default;
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
// ReSharper disable once UnusedParameter.Local
|
||||
private static ICustomMarshaler GetInstance(string cookie)
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
|
||||
public void CleanUpManagedData(object managedObj) { }
|
||||
|
||||
public void CleanUpNativeData(IntPtr pNativeData) { }
|
||||
|
||||
public int GetNativeDataSize() => -1;
|
||||
|
||||
public object MarshalNativeToManaged(IntPtr pNativeData)
|
||||
{
|
||||
return Marshal.PtrToStringUTF8(pNativeData)!;
|
||||
}
|
||||
|
||||
public IntPtr MarshalManagedToNative(object managedObj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Alpm/Wrapper.cs
Normal file
10
Alpm/Wrapper.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
internal static class Wrapper
|
||||
{
|
||||
internal static unsafe IntPtr ListNext(IntPtr list) => ((alpm_list_t*) list)->next;
|
||||
internal static unsafe IntPtr ListData(IntPtr list) => ((alpm_list_t*) list)->data;
|
||||
}
|
||||
}
|
||||
225
Alpm/alpm.cs
Normal file
225
Alpm/alpm.cs
Normal file
@@ -0,0 +1,225 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Foodsoft.Alpm;
|
||||
|
||||
namespace Foodsoft.Alpm
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct alpm_list_t
|
||||
{
|
||||
internal IntPtr data;
|
||||
internal readonly IntPtr prev;
|
||||
internal readonly IntPtr next;
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal static class alpm
|
||||
{
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_pkg_should_ignore(SafeAlpmHandle handle, SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_filename(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_base(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_name(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_version(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern PackageOrigin alpm_pkg_get_origin(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_desc(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_url(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern long alpm_pkg_get_builddate(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern long alpm_pkg_get_installdate(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_packager(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_md5sum(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_sha256sum(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_arch(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern long alpm_pkg_get_size(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern long alpm_pkg_get_isize(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern InstallReason alpm_pkg_get_reason(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_licenses(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_groups(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_depends(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_optdepends(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_checkdepends(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_makedepends(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_conflicts(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_pkg_get_provides(SafePackageHandle pkg);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_pkg_set_reason(SafePackageHandle pkg, InstallReason reason);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_pkg_free(IntPtr ptr);
|
||||
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr alpm_option_get_cachedirs(SafeAlpmHandle handle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_option_set_cachedirs(SafeAlpmHandle handle, IntPtr cachedirs);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_option_add_cachedir(SafeAlpmHandle handle,
|
||||
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8InMarshaler))] string cachedir);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_option_remove_cachedir(SafeAlpmHandle handle,
|
||||
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8InMarshaler))] string cachedir);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern ErrNo alpm_errno(SafeAlpmHandle handle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_strerror(ErrNo err);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr alpm_get_localdb(SafeAlpmHandle handle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern unsafe alpm_list_t* alpm_option_get_syncdbs();
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr alpm_register_syncdb(SafeAlpmHandle handle, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8InMarshaler))] string treename, SigLevel sigLevel);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_unregister_all_syncdbs(SafeAlpmHandle handle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern unsafe alpm_list_t* alpm_list_next(alpm_list_t* list);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern UIntPtr alpm_list_count(IntPtr list);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern void alpm_list_free(IntPtr list);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr alpm_list_find_str(IntPtr list, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8InMarshaler))] string needle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_unlock(Handle handle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_version();
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern caps alpm_capabilities();
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern SafeAlpmHandle alpm_initialize(
|
||||
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8InMarshaler))]
|
||||
string root, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8InMarshaler))]
|
||||
string dbpath, out ErrNo err);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_release(IntPtr handle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_remove_server(SafeDatabaseHandle db,
|
||||
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8InMarshaler))]
|
||||
string url);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_unregister(SafeDatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))]
|
||||
public static extern string alpm_db_get_name(SafeDatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern SigLevel alpm_db_get_siglevel(SafeDatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_get_valid(SafeDatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_update(int force, SafeDatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr alpm_db_get_servers(SafeDatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_set_servers(SafeDatabaseHandle db, IntPtr list);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_add_server(SafeDatabaseHandle db,
|
||||
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8InMarshaler))]
|
||||
string url);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr alpm_pkg_get_pkg(SafeDatabaseHandle db,
|
||||
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8InMarshaler))]
|
||||
string name);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr alpm_db_get_pkgcache(SafeDatabaseHandle db);
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user