checkpoint collections
This commit is contained in:
549
AlpmOld.cs
Normal file
549
AlpmOld.cs
Normal file
@@ -0,0 +1,549 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnassignedReadonlyField
|
||||
// ReSharper disable UnusedMember.Global
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Alpm
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||
public struct alpm_pkg_p
|
||||
{
|
||||
private IntPtr ptr;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct alpm_list_t
|
||||
{
|
||||
public IntPtr data;
|
||||
public unsafe alpm_list_t* prev;
|
||||
public unsafe alpm_list_t* next;
|
||||
}
|
||||
|
||||
public interface IAlpmItemsAccessor<TElement>
|
||||
{
|
||||
SafeAlpmHandle Handle { 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);
|
||||
}
|
||||
|
||||
|
||||
public class SafeAlpmHandle : SafeHandle
|
||||
{
|
||||
private SafeAlpmHandle() : base(IntPtr.Zero, true) { }
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
return alpm.alpm_release(handle) == 0;
|
||||
}
|
||||
|
||||
public override bool IsInvalid => handle == IntPtr.Zero;
|
||||
}
|
||||
|
||||
public sealed class Handle : IDisposable
|
||||
{
|
||||
private readonly SafeAlpmHandle _handle;
|
||||
|
||||
public Handle(string root, string dbpath)
|
||||
{
|
||||
var err = ErrNo.ERR_OK;
|
||||
_handle = alpm.alpm_initialize(root, dbpath, ref err);
|
||||
if (_handle.IsInvalid)
|
||||
{
|
||||
throw new Exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_handle.Dispose();
|
||||
}
|
||||
|
||||
private Database DatabaseAccess(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
throw new Exception(_handle);
|
||||
}
|
||||
|
||||
Database db;
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try { }
|
||||
finally
|
||||
{
|
||||
// adding this ref and getting the Database object the handle must not interrupted
|
||||
var addedRef = false;
|
||||
_handle.DangerousAddRef(ref addedRef);
|
||||
if (!addedRef)
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
db = new Database(_handle, new DatabaseHandle(ptr));
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
public Database LocalDB => DatabaseAccess(alpm.alpm_get_localdb(_handle));
|
||||
|
||||
public Database RegisterSyncDB(string treename, SigLevel sigLevel) =>
|
||||
DatabaseAccess(alpm.alpm_register_syncdb(_handle, treename, sigLevel));
|
||||
|
||||
public readonly struct CacheDirsAccessor : IAlpmItemsAccessor<string>
|
||||
{
|
||||
public CacheDirsAccessor(SafeAlpmHandle handle) => Handle = handle;
|
||||
public SafeAlpmHandle Handle { get; }
|
||||
public IntPtr GetItems() => alpm.alpm_option_get_cachedirs(Handle);
|
||||
public int SetItems(IntPtr list) => alpm.alpm_option_set_cachedirs(Handle, list);
|
||||
public int AddItem(string item) => alpm.alpm_option_add_cachedir(Handle, item);
|
||||
public int RemoveItem(string item) => alpm.alpm_option_remove_cachedir(Handle, item);
|
||||
public IntPtr FindItem(string item) => alpm.alpm_list_find_str(GetItems(), item);
|
||||
public string PtrToItem(IntPtr p) => Marshal.PtrToStringUTF8(p)!;
|
||||
}
|
||||
|
||||
#nullable enable
|
||||
public struct CollectionWrapper<TImpl, TElement> : ICollection<TElement> where TImpl : IAlpmItemsAccessor<TElement>,
|
||||
ICollection<TElement>
|
||||
{
|
||||
private TImpl _impl;
|
||||
|
||||
public CollectionWrapper(TImpl impl)
|
||||
{
|
||||
_impl = impl;
|
||||
}
|
||||
|
||||
IEnumerator<TElement> IEnumerable<TElement>.GetEnumerator()
|
||||
{
|
||||
return (IEnumerator<TElement>) GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
var result = new List<TElement>();
|
||||
var intPtr = _impl.GetItems();
|
||||
unsafe
|
||||
{
|
||||
for (var list = (alpm_list_t*) intPtr; list != null; list = alpm.alpm_list_next(list))
|
||||
{
|
||||
result.Add(_impl.PtrToItem(list->data));
|
||||
}
|
||||
}
|
||||
|
||||
return result.GetEnumerator();
|
||||
}
|
||||
|
||||
|
||||
public void Add(TElement item)
|
||||
{
|
||||
_impl.AddItem(item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_impl.SetItems(IntPtr.Zero);
|
||||
}
|
||||
|
||||
|
||||
public bool Contains(TElement item) =>
|
||||
_impl.FindItem(item) != IntPtr.Zero;
|
||||
|
||||
public void CopyTo(TElement[] array, int arrayIndex)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(TElement item)
|
||||
{
|
||||
var err = _impl.RemoveItem(item);
|
||||
if (err < 0)
|
||||
{
|
||||
throw new Exception(alpm.alpm_errno(_impl.Handle));
|
||||
}
|
||||
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
public int Count => (int) alpm.alpm_list_count(_impl.GetItems());
|
||||
public bool IsReadOnly => false;
|
||||
}
|
||||
|
||||
private readonly struct CacheDirCollection : ICollection<string>
|
||||
{
|
||||
private readonly SafeAlpmHandle _handle;
|
||||
|
||||
public CacheDirCollection(SafeAlpmHandle handle)
|
||||
{
|
||||
_handle = handle;
|
||||
}
|
||||
|
||||
public IEnumerator<string> GetEnumerator()
|
||||
{
|
||||
var result = new List<string>();
|
||||
var intPtr = alpm.alpm_option_get_cachedirs(_handle);
|
||||
unsafe
|
||||
{
|
||||
for (var list = (alpm_list_t*) intPtr; list != null; list = alpm.alpm_list_next(list))
|
||||
{
|
||||
result.Add(Marshal.PtrToStringUTF8(list->data));
|
||||
}
|
||||
}
|
||||
|
||||
return result.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void Add(string item)
|
||||
{
|
||||
var handle = _handle;
|
||||
Alpm.ErrWrap(_handle, () => alpm.alpm_option_add_cachedir(handle, item));
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
var handle = _handle;
|
||||
Alpm.ErrWrap(_handle, () => alpm.alpm_option_set_cachedirs(handle, IntPtr.Zero));
|
||||
}
|
||||
|
||||
public bool Contains(string item) =>
|
||||
alpm.alpm_list_find_str(alpm.alpm_option_get_cachedirs(_handle), item) != IntPtr.Zero;
|
||||
|
||||
public void CopyTo(string[] array, int arrayIndex)
|
||||
{
|
||||
var intPtr = alpm.alpm_option_get_cachedirs(_handle);
|
||||
unsafe
|
||||
{
|
||||
for (var list = (alpm_list_t*) intPtr; list != null; list = alpm.alpm_list_next(list))
|
||||
{
|
||||
array[arrayIndex++] = Marshal.PtrToStringUTF8(list->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(string item)
|
||||
{
|
||||
var err = alpm.alpm_option_remove_cachedir(_handle, item);
|
||||
if (err < 0)
|
||||
{
|
||||
throw new Exception(alpm.alpm_errno(_handle));
|
||||
}
|
||||
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
public int Count => (int) alpm.alpm_list_count(alpm.alpm_option_get_cachedirs(_handle));
|
||||
public bool IsReadOnly => false;
|
||||
}
|
||||
|
||||
public ICollection<string> CacheDirs
|
||||
{
|
||||
get => new CacheDirCollection(_handle);
|
||||
set
|
||||
{
|
||||
foreach (var s in value)
|
||||
{
|
||||
Alpm.ErrWrap(_handle, () => alpm.alpm_option_add_cachedir(_handle, s));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum caps
|
||||
{
|
||||
ALPM_CAPABILITY_NLS = (1 << 0),
|
||||
ALPM_CAPABILITY_DOWNLOADER = (1 << 1),
|
||||
ALPM_CAPABILITY_SIGNATURES = (1 << 2)
|
||||
}
|
||||
|
||||
[Serializable()]
|
||||
public class Exception : System.Exception
|
||||
{
|
||||
public Exception() { }
|
||||
public Exception(SafeAlpmHandle handle) : base(Alpm.StrError(alpm.alpm_errno(handle))) { }
|
||||
public Exception(ErrNo errno) : base(Alpm.StrError(errno)) { }
|
||||
public Exception(ErrNo errno, System.Exception inner) : base(Alpm.StrError(errno), inner) { }
|
||||
|
||||
protected Exception(SerializationInfo info,
|
||||
StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
|
||||
public class DatabaseHandle : SafeHandle
|
||||
{
|
||||
private DatabaseHandle() : base(IntPtr.Zero, true) { }
|
||||
|
||||
public DatabaseHandle(IntPtr h) : this()
|
||||
{
|
||||
SetHandle(h);
|
||||
}
|
||||
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
return alpm.alpm_db_unregister(handle) == 0;
|
||||
}
|
||||
|
||||
public override bool IsInvalid => handle == IntPtr.Zero;
|
||||
}
|
||||
|
||||
public sealed class Database : IDisposable
|
||||
{
|
||||
private SafeAlpmHandle _handle;
|
||||
private DatabaseHandle _db;
|
||||
|
||||
public Database(SafeAlpmHandle handle, DatabaseHandle db)
|
||||
{
|
||||
_handle = handle;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
private readonly struct ServerCollection : ICollection<string>
|
||||
{
|
||||
private readonly SafeAlpmHandle _handle;
|
||||
private readonly DatabaseHandle _db;
|
||||
|
||||
public ServerCollection(SafeAlpmHandle handle, DatabaseHandle db)
|
||||
{
|
||||
_handle = handle;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
public IEnumerator<string> GetEnumerator()
|
||||
{
|
||||
var result = new List<string>();
|
||||
var intPtr = alpm.alpm_db_get_servers(_db);
|
||||
unsafe
|
||||
{
|
||||
for (var list = (alpm_list_t*) intPtr; list != null; list = alpm.alpm_list_next(list))
|
||||
{
|
||||
result.Add(Marshal.PtrToStringUTF8(list->data));
|
||||
}
|
||||
}
|
||||
|
||||
return result.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void Add(string item)
|
||||
{
|
||||
var db = _db;
|
||||
Alpm.ErrWrap(_handle, () => alpm.alpm_db_add_server(db, item));
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
var db = _db;
|
||||
Alpm.ErrWrap(_handle, () => alpm.alpm_db_set_servers(db, IntPtr.Zero));
|
||||
}
|
||||
|
||||
public bool Contains(string item) =>
|
||||
alpm.alpm_list_find_str(alpm.alpm_db_get_servers(_db), item) != IntPtr.Zero;
|
||||
|
||||
public void CopyTo(string[] array, int arrayIndex)
|
||||
{
|
||||
var intPtr = alpm.alpm_db_get_servers(_db);
|
||||
unsafe
|
||||
{
|
||||
for (var list = (alpm_list_t*) intPtr; list != null; list = alpm.alpm_list_next(list))
|
||||
{
|
||||
array[arrayIndex++] = Marshal.PtrToStringUTF8(list->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(string item)
|
||||
{
|
||||
var err = alpm.alpm_db_remove_server(_db, item);
|
||||
if (err < 0)
|
||||
{
|
||||
throw new Exception(alpm.alpm_errno(_handle));
|
||||
}
|
||||
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
|
||||
public int Count => (int) alpm.alpm_list_count(alpm.alpm_db_get_servers(_db));
|
||||
public bool IsReadOnly => false;
|
||||
}
|
||||
|
||||
public ICollection<string> Servers
|
||||
{
|
||||
get => new ServerCollection(_handle, _db);
|
||||
set
|
||||
{
|
||||
foreach (var s in value)
|
||||
{
|
||||
Alpm.ErrWrap(_handle, () => alpm.alpm_db_add_server(_db, s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Name => Marshal.PtrToStringUTF8(alpm.alpm_db_get_name(_db));
|
||||
|
||||
public SigLevel SigLevel => alpm.alpm_db_get_siglevel(_db);
|
||||
|
||||
public ErrNo Valid => alpm.alpm_db_get_valid(_db) != 0 ? alpm.alpm_errno(_handle) : ErrNo.ERR_OK;
|
||||
|
||||
public bool Update(bool force)
|
||||
{
|
||||
var err = alpm.alpm_db_update(force ? 1 : 0, _db);
|
||||
if (err < 0)
|
||||
{
|
||||
throw new Exception(_handle);
|
||||
}
|
||||
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_db.Dispose();
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try { }
|
||||
finally
|
||||
{
|
||||
_handle.DangerousRelease();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class alpm
|
||||
{
|
||||
[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), CharSet = CharSet.Ansi)]
|
||||
public static extern int alpm_option_add_cachedir(SafeAlpmHandle handle, string cachedir);
|
||||
|
||||
[DllImport(nameof(alpm), CharSet = CharSet.Ansi)]
|
||||
public static extern int alpm_option_remove_cachedir(SafeAlpmHandle handle, string cachedir);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern ErrNo alpm_errno(SafeAlpmHandle handle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr 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), CharSet = CharSet.Ansi)]
|
||||
public static extern IntPtr alpm_register_syncdb(SafeAlpmHandle handle, 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), CharSet = CharSet.Ansi)]
|
||||
public static extern IntPtr alpm_list_find_str(IntPtr list, string needle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_unlock(Handle handle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr alpm_version();
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern caps alpm_capabilities();
|
||||
|
||||
[DllImport(nameof(alpm), CharSet = CharSet.Ansi)]
|
||||
public static extern SafeAlpmHandle alpm_initialize(string root, string dbpath, ref ErrNo err);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_release(IntPtr handle);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_remove_server(DatabaseHandle db, string url);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_unregister(IntPtr db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr alpm_db_get_name(DatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern SigLevel alpm_db_get_siglevel(DatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_get_valid(DatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_update(int force, DatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern IntPtr alpm_db_get_servers(DatabaseHandle db);
|
||||
|
||||
[DllImport(nameof(alpm))]
|
||||
public static extern int alpm_db_set_servers(DatabaseHandle db, IntPtr list);
|
||||
|
||||
[DllImport(nameof(alpm), CharSet = CharSet.Ansi)]
|
||||
public static extern int alpm_db_add_server(DatabaseHandle db, string url);
|
||||
}
|
||||
|
||||
internal static class Alpm
|
||||
{
|
||||
|
||||
public static string Version()
|
||||
{
|
||||
return Marshal.PtrToStringUTF8(alpm.alpm_version());
|
||||
}
|
||||
|
||||
public static string StrError(ErrNo err)
|
||||
{
|
||||
return Marshal.PtrToStringUTF8(alpm.alpm_strerror(err));
|
||||
}
|
||||
|
||||
internal static void ErrWrap(SafeAlpmHandle h, Func<int> f)
|
||||
{
|
||||
var err = f();
|
||||
if (err != 0)
|
||||
{
|
||||
throw new Exception(alpm.alpm_errno(h));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user