diff --git a/Alpm/API.cs b/Alpm/API.cs index 77ad969..7387d12 100644 --- a/Alpm/API.cs +++ b/Alpm/API.cs @@ -1,5 +1,3 @@ -using System; - namespace Foodsoft.Alpm { public static class API diff --git a/Alpm/AlpmException.cs b/Alpm/AlpmException.cs index ab0cc03..349e6b1 100644 --- a/Alpm/AlpmException.cs +++ b/Alpm/AlpmException.cs @@ -1,16 +1,15 @@ using System; using System.Runtime.Serialization; -using Foodsoft.Alpm; namespace Foodsoft.Alpm { - [Serializable()] - public class AlpmException : System.Exception + [Serializable] + public class AlpmException : Exception { public AlpmException() { } internal AlpmException(SafeAlpmHandle handle) : base(alpm.alpm_strerror(alpm.alpm_errno(handle))) { } - public AlpmException(ErrNo errno) : base(alpm.alpm_strerror(errno)) { } - public AlpmException(ErrNo errno, System.Exception inner) : base(alpm.alpm_strerror(errno), inner) { } + public AlpmException(Error errno) : base(alpm.alpm_strerror(errno)) { } + public AlpmException(Error errno, Exception inner) : base(alpm.alpm_strerror(errno), inner) { } protected AlpmException(SerializationInfo info, StreamingContext context) : base(info, context) { } diff --git a/Alpm/Backup.cs b/Alpm/Backup.cs index f9d0dae..0fbf072 100644 --- a/Alpm/Backup.cs +++ b/Alpm/Backup.cs @@ -8,9 +8,20 @@ namespace Foodsoft.Alpm public string Name { get; } public string Hash { get; } - public bool Equals(Backup other) => Name == other.Name && Hash == other.Hash; - public override bool Equals(object? obj) => obj is Backup other && Equals(other); - public override int GetHashCode() => HashCode.Combine(Name, Hash); + public bool Equals(Backup other) + { + return Name == other.Name && Hash == other.Hash; + } + + public override bool Equals(object? obj) + { + return obj is Backup other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(Name, Hash); + } [StructLayout(LayoutKind.Sequential)] private readonly unsafe struct NativeBackup diff --git a/Alpm/CachePackage.cs b/Alpm/CachePackage.cs index a4468bc..47fbd29 100644 --- a/Alpm/CachePackage.cs +++ b/Alpm/CachePackage.cs @@ -10,6 +10,14 @@ namespace Foodsoft.Alpm public override Database? DB { get; } + public bool CheckMD5Sum() + { + var ret = alpm.alpm_pkg_checkmd5sum(Handle); + if (ret == 0) return true; + var errno = alpm.alpm_errno(Handle.SafeAlpmHandle); + return errno == Error.PkgInvalid ? false : throw new AlpmException(errno); + } + public void SetInstallReason(InstallReason reason) { if (alpm.alpm_pkg_set_reason(Handle, reason) != 0) diff --git a/Alpm/CachePackageList.cs b/Alpm/CachePackageList.cs index f1ad4b3..889f441 100644 --- a/Alpm/CachePackageList.cs +++ b/Alpm/CachePackageList.cs @@ -1,20 +1,16 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; namespace Foodsoft.Alpm { - - public class CachePackageList : IPackageList, ICollection { - private readonly SafeDatabaseHandle _parentHandle; - private readonly IntPtr _listPtr; private readonly Database _db; + private readonly IntPtr _listPtr; + private readonly SafeDatabaseHandle _parentHandle; internal CachePackageList(IntPtr listPtr, SafeDatabaseHandle parentHandle, Database db) { @@ -23,45 +19,15 @@ namespace Foodsoft.Alpm _db = db; } - [PrePrepareMethod] - public IEnumerator GetEnumerator() - { - var release = false; - - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - _parentHandle.DangerousAddRef(ref release); - if (!release) throw new ObjectDisposedException(_parentHandle.GetType().FullName); - for (var list = _listPtr; list != IntPtr.Zero; list = Detail.ListNext(list)) - { - yield return new CachePackage( - new SafeCachePackageHandle(Detail.ListData(list), _parentHandle), _db); - } - } - finally - { - if (release) - _parentHandle.DangerousRelease(); - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - public bool Contains(CachePackage item) { var name = item.Name; - return _parentHandle.UseHandle(_listPtr, (list) => + return _parentHandle.UseHandle(_listPtr, list => { for (; list != IntPtr.Zero; list = Detail.ListNext(list)) - { if (name == alpm.alpm_pkg_get_name(list)) return true; - } return false; }); @@ -69,29 +35,16 @@ namespace Foodsoft.Alpm public void CopyTo(CachePackage[] array, int arrayIndex) { - _parentHandle.UseHandle(_listPtr, (list) => + _parentHandle.UseHandle(_listPtr, list => { for (; list != IntPtr.Zero; list = Detail.ListNext(list)) - { array[arrayIndex++] = new CachePackage( new SafeCachePackageHandle(Detail.ListData(list), _parentHandle), _db); - } return 0; }); } - public CachePackage? FindSatisfier(string depString) - { - return _parentHandle.UseHandle(_listPtr, (list) => - { - var pkgPtr = alpm.alpm_find_satisfier(list, depString); - return pkgPtr != IntPtr.Zero - ? new CachePackage(new SafeCachePackageHandle(pkgPtr, _parentHandle), _db) - : null; - }); - } - public void Add(CachePackage item) { throw new NotSupportedException(); @@ -107,8 +60,49 @@ namespace Foodsoft.Alpm throw new NotSupportedException(); } - public int Count => _parentHandle.UseHandle(_listPtr, (list) => (int) alpm.alpm_list_count(list)); + public int Count => _listPtr == IntPtr.Zero + ? 0 + : _parentHandle.UseHandle(_listPtr, list => (int) alpm.alpm_list_count(list)); public bool IsReadOnly => true; + + [PrePrepareMethod] + public IEnumerator GetEnumerator() + { + if (_listPtr == IntPtr.Zero) + yield break; + var release = false; + + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + _parentHandle.DangerousAddRef(ref release); + if (!release) throw new ObjectDisposedException(_parentHandle.GetType().FullName); + for (var list = _listPtr; list != IntPtr.Zero; list = Detail.ListNext(list)) + yield return new CachePackage( + new SafeCachePackageHandle(Detail.ListData(list), _parentHandle), _db); + } + finally + { + if (release) + _parentHandle.DangerousRelease(); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public CachePackage? FindSatisfier(string depString) + { + return _parentHandle.UseHandle(_listPtr, list => + { + var pkgPtr = alpm.alpm_find_satisfier(list, depString); + return pkgPtr != IntPtr.Zero + ? new CachePackage(new SafeCachePackageHandle(pkgPtr, _parentHandle), _db) + : null; + }); + } } } \ No newline at end of file diff --git a/Alpm/Database.cs b/Alpm/Database.cs index 1ce0fb5..f2c590d 100644 --- a/Alpm/Database.cs +++ b/Alpm/Database.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; +using System.Runtime.ConstrainedExecution; namespace Foodsoft.Alpm { @@ -11,26 +12,22 @@ namespace Foodsoft.Alpm public enum UsageFlags { Sync = 1, - Search = (1 << 1), - Install = (1 << 2), - Upgrade = (1 << 3), - All = (1 << 4) - 1, + Search = 1 << 1, + Install = 1 << 2, + Upgrade = 1 << 3, + All = (1 << 4) - 1 } - + private readonly SafeDatabaseHandle _handle; - internal Database(SafeDatabaseHandle handle) => _handle = handle; - - public void Unregister() => _handle.Close(); - - public void AddServer(string url) => - Detail.WrapError(_handle.SafeAlpmHandle, () => alpm.alpm_db_add_server(_handle, url)); - - public bool RemoveServer(string url) => - Detail.WrapErrorBool(_handle.SafeAlpmHandle, () => alpm.alpm_db_remove_server(_handle, url)); + internal Database(SafeDatabaseHandle handle) + { + _handle = handle; + } // FIXME: This is "bug correct", but probably dumb to do it this way, instead just call add_server // like all the stuff in handle. + // Also this stupid thing leaks the duped strings on failure. public IEnumerable Servers { get => EnumerableWrapper.Create(_handle, alpm.alpm_db_get_servers); @@ -44,10 +41,9 @@ namespace Foodsoft.Alpm { // ReSharper disable once LoopCanBeConvertedToQuery foreach (var s in value) - { if (alpm.alpm_list_append_strdup(ref listPtr, s) == IntPtr.Zero) - throw new AlpmException(ErrNo.ERR_MEMORY); - } + throw new AlpmException(Error.Memory); + success = true; } finally @@ -67,33 +63,8 @@ namespace Foodsoft.Alpm 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 AlpmException(_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 AlpmException(err); - } - - return new CachePackage(new SafeCachePackageHandle(pkgPtr, _handle), this); - } + public Error Valid => + alpm.alpm_db_get_valid(_handle) != 0 ? alpm.alpm_errno(_handle.SafeAlpmHandle) : Error.OK; public CachePackageList PackageCache { @@ -106,16 +77,68 @@ namespace Foodsoft.Alpm } } - public CachePackageList Search() + public UsageFlags Usage { - + get => Detail.WrapErrorOut(_handle.SafeAlpmHandle, _handle, + alpm.alpm_db_get_usage); + set => Detail.WrapErrorIn(_handle.SafeAlpmHandle, _handle, value, alpm.alpm_db_set_usage); } - public UsageFlags Usage => Detail.WrapError(_handle.SafeAlpmHandle, _handle, alpm.alpm_db_get_usage); - public void Dispose() { _handle.Dispose(); } + + public void Unregister() + { + _handle.Close(); + } + + public void AddServer(string url) + { + Detail.WrapError(_handle.SafeAlpmHandle, () => alpm.alpm_db_add_server(_handle, url)); + } + + public bool RemoveServer(string url) + { + return Detail.WrapErrorBool(_handle.SafeAlpmHandle, () => alpm.alpm_db_remove_server(_handle, url)); + } + + public bool Update(bool force = false) + { + var err = alpm.alpm_db_update(force ? 1 : 0, _handle); + if (err < 0) throw new AlpmException(_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 == Error.PkgNotFound) + return null; + throw new AlpmException(err); + } + + return new CachePackage(new SafeCachePackageHandle(pkgPtr, _handle), this); + } + + [PrePrepareMethod] + [SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")] + public CachePackageList Search(IEnumerable needles) + { + var result = Detail.UseStringList(needles, listPtr => alpm.alpm_db_search(_handle, listPtr)); + if (result == IntPtr.Zero) + { + var errNo = alpm.alpm_errno(_handle.SafeAlpmHandle); + if (errNo != Error.OK) + throw new AlpmException(errNo); + } + + return new CachePackageList(result, _handle, this); + } } } \ No newline at end of file diff --git a/Alpm/Depend.cs b/Alpm/Depend.cs index 267b010..7edae39 100644 --- a/Alpm/Depend.cs +++ b/Alpm/Depend.cs @@ -1,6 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; -using System.Drawing; using System.Runtime.InteropServices; namespace Foodsoft.Alpm @@ -16,30 +14,7 @@ namespace Foodsoft.Alpm GreaterThan, LessThan } - - public string Name { get; } - public string Version { get; } - public string Description { get; } - public ulong NameHash { get; } - public ModType Mod { get; } - - public override bool Equals(object? obj) => (obj is Depend other) && this.Equals(other); - - public bool Equals(Depend? other) => !ReferenceEquals(other, null) && ReferenceEquals(this, other) && - Name == other.Name && Version == other.Version && Mod == other.Mod; - - public override int GetHashCode() => HashCode.Combine(Name, Version, (int) Mod); - - [StructLayout(LayoutKind.Sequential)] - private readonly unsafe struct NativeDepend - { - internal readonly sbyte* name; - internal readonly sbyte* version; - internal readonly sbyte* description; - internal readonly ulong name_hash; - internal readonly Depend.ModType mod; - } - + internal unsafe Depend(IntPtr ptr) { var native = (NativeDepend*) ptr; @@ -49,5 +24,37 @@ namespace Foodsoft.Alpm NameHash = native->name_hash; Mod = native->mod; } + + public string Name { get; } + public string Version { get; } + public string Description { get; } + public ulong NameHash { get; } + public ModType Mod { get; } + + public bool Equals(Depend? other) + { + return !ReferenceEquals(other, null) && ReferenceEquals(this, other) && + Name == other.Name && Version == other.Version && Mod == other.Mod; + } + + public override bool Equals(object? obj) + { + return obj is Depend other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(Name, Version, (int) Mod); + } + + [StructLayout(LayoutKind.Sequential)] + private readonly unsafe struct NativeDepend + { + internal readonly sbyte* name; + internal readonly sbyte* version; + internal readonly sbyte* description; + internal readonly ulong name_hash; + internal readonly ModType mod; + } } } \ No newline at end of file diff --git a/Alpm/Detail.cs b/Alpm/Detail.cs index 2bcb7c8..25f9fee 100644 --- a/Alpm/Detail.cs +++ b/Alpm/Detail.cs @@ -1,14 +1,26 @@ using System; +using System.Buffers; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Text; namespace Foodsoft.Alpm { + [SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")] internal static class Detail { - internal static unsafe IntPtr ListNext(IntPtr list) => ((alpm_list_t*) list)->next; - internal static unsafe IntPtr ListData(IntPtr list) => ((alpm_list_t*) list)->data; + internal static unsafe IntPtr ListNext(IntPtr list) + { + return ((alpm_list_t*) list)->next; + } + + internal static unsafe IntPtr ListData(IntPtr list) + { + return ((alpm_list_t*) list)->data; + } internal static TResult UseHandle(this SafeHandle handle, IntPtr ptr, Func op) { @@ -28,16 +40,61 @@ namespace Foodsoft.Alpm } } - internal static TResult UseHandle(this SafeHandle handle, Func op) => - handle.UseHandle(handle.DangerousGetHandle(), op); - - internal static void SetStringCollection(IEnumerable value, SafeAlpmHandle safeAlpmHandle, Func op) + internal static TResult UseHandle(this SafeHandle handle, Func op) + { + return handle.UseHandle(handle.DangerousGetHandle(), op); + } + + internal static void SetStringCollection(IEnumerable value, SafeAlpmHandle safeAlpmHandle, + Func op) { - // ReSharper disable once LoopCanBeConvertedToQuery foreach (var s in value) - { if (op(s) < 0) throw new AlpmException(safeAlpmHandle); + } + + internal static unsafe TResult UseStringList(IEnumerable strings, Func op) + { + var listPtr = IntPtr.Zero; + var strArray = strings as string[] ?? strings.ToArray(); + var numBytes = 0; + + foreach (var s in strArray) numBytes += Encoding.UTF8.GetMaxByteCount(s.Length) + 1; + + var pool = ArrayPool.Shared; + byte[] poolBuffer = pool.Rent(numBytes); + + try + { + fixed (byte* pBuf = poolBuffer) + { + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + var start = 0; + foreach (var s in strArray) + fixed (char* pSrc = s) + { + var pDest = &pBuf[start]; + var nbWritten = + Encoding.UTF8.GetBytes(pSrc, s.Length, pDest, poolBuffer.Length - start); + pDest[nbWritten] = 0; + if (alpm.alpm_list_append(ref listPtr, (IntPtr) pDest) == IntPtr.Zero) + throw new AlpmException(Error.Memory); + start += nbWritten + 1; + } + + return op(listPtr); + } + finally + { + alpm.alpm_list_free(listPtr); + } + } + } + finally + { + pool.Return(poolBuffer); } } @@ -48,9 +105,7 @@ namespace Foodsoft.Alpm throw new AlpmException(alpmHandle); } - internal delegate int OutFunc(THandle handle, out T result); - - internal static T WrapError(SafeAlpmHandle alpmHandle, THandle handle, OutFunc f) + internal static T WrapErrorOut(SafeAlpmHandle alpmHandle, THandle handle, OutFunc f) { var err = f(handle, out var result); if (err != 0) @@ -58,14 +113,22 @@ namespace Foodsoft.Alpm return result; } + internal static void WrapErrorIn(SafeAlpmHandle alpmHandle, THandle handle, T value, + Func f) + { + var err = f(handle, value); + if (err != 0) + throw new AlpmException(alpmHandle); + } + internal static bool WrapErrorBool(SafeAlpmHandle h, Func f) { var err = f(); - if (err < 0) - { - throw new AlpmException(h); - } + if (err < 0) throw new AlpmException(h); + return err == 0; } + + internal delegate int OutFunc(THandle handle, out T result); } } \ No newline at end of file diff --git a/Alpm/EnumerableWrapper.cs b/Alpm/EnumerableWrapper.cs index db0b669..fc915d5 100644 --- a/Alpm/EnumerableWrapper.cs +++ b/Alpm/EnumerableWrapper.cs @@ -1,7 +1,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Dynamic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -14,17 +13,17 @@ namespace Foodsoft.Alpm { return new EnumerableWrapper(handle, getItems, Marshal.PtrToStringUTF8!); } - + internal static EnumerableWrapper CreateForDepend(THandle handle, Func getItems) where THandle : SafeHandle { - return new EnumerableWrapper(handle, getItems, (ptr) => new Depend(ptr)); + return new EnumerableWrapper(handle, getItems, ptr => new Depend(ptr)); } - + internal static EnumerableWrapper CreateForBackup(THandle handle, Func getItems) where THandle : SafeHandle { - return new EnumerableWrapper(handle, getItems, (ptr) => new Backup(ptr)); + return new EnumerableWrapper(handle, getItems, ptr => new Backup(ptr)); } } @@ -41,6 +40,8 @@ namespace Foodsoft.Alpm _getElement = getElement; } + public bool IsReadOnly => true; + public IEnumerator GetEnumerator() { var release = false; @@ -51,9 +52,7 @@ namespace Foodsoft.Alpm _handle.DangerousAddRef(ref release); if (!release) throw new ObjectDisposedException(_handle.GetType().FullName); for (var list = _getItems(_handle); list != IntPtr.Zero; list = Detail.ListNext(list)) - { yield return _getElement(Detail.ListData(list)); - } } finally { @@ -62,7 +61,10 @@ namespace Foodsoft.Alpm } } - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } public int Count { @@ -70,7 +72,7 @@ namespace Foodsoft.Alpm { var getItems = _getItems; var handle = _handle; - return handle.UseHandle((_) => (int) alpm.alpm_list_count(getItems(handle))); + return handle.UseHandle(_ => (int) alpm.alpm_list_count(getItems(handle))); } } @@ -82,16 +84,14 @@ namespace Foodsoft.Alpm switch (item) { case string s: - return handle.UseHandle((_) => alpm.alpm_list_find_str(getItems(handle), s) != (IntPtr.Zero)); + return handle.UseHandle(_ => alpm.alpm_list_find_str(getItems(handle), s) != IntPtr.Zero); default: var comparer = EqualityComparer.Default; - return handle.UseHandle((_) => + return handle.UseHandle(_ => { for (var list = getItems(handle); list != IntPtr.Zero; list = Detail.ListNext(list)) - { if (comparer.Equals(item, getElement(Detail.ListData(list)))) return true; - } return false; }); @@ -103,12 +103,10 @@ namespace Foodsoft.Alpm var getItems = _getItems; var getElement = _getElement; var handle = _handle; - handle.UseHandle((_) => + handle.UseHandle(_ => { for (var list = getItems(handle); list != IntPtr.Zero; list = Detail.ListNext(list)) - { array[arrayIndex++] = getElement(Detail.ListData(list)); - } return arrayIndex; }); @@ -128,7 +126,5 @@ namespace Foodsoft.Alpm { throw new NotSupportedException(); } - - public bool IsReadOnly => true; } } \ No newline at end of file diff --git a/Alpm/Enums.cs b/Alpm/Enums.cs index fb95cbd..c9fee62 100644 --- a/Alpm/Enums.cs +++ b/Alpm/Enums.cs @@ -2,6 +2,85 @@ using System; namespace Foodsoft.Alpm { + public enum Error + { + OK = 0, + Memory, + System, + Badperms, + NotAFile, + NotADir, + WrongArgs, + DiskSpace, + + /* Interface */ + HandleNull, + HandleNotNull, + HandleLock, + + /* Databases */ + DBOpen, + DBCreate, + DBNull, + DBNotNull, + DBNotFound, + DBInvalid, + DBInvalidSig, + DBVersion, + DBWrite, + DBRemove, + + /* Servers */ + ServerBadUrl, + ServerNone, + + /* Transactions */ + TransNotNull, + TransNull, + TransDupTarget, + TransNotInitialized, + TransNotPrepared, + TransAbort, + TransType, + TransNotLocked, + TransHookFailed, + + /* Packages */ + PkgNotFound, + PkgIgnored, + PkgInvalid, + PkgInvalidChecksum, + PkgInvalidSig, + PkgMissingSig, + PkgOpen, + PkgCantRemove, + PkgInvalidName, + PkgInvalidArch, + PkgRepoNotFound, + + /* Signatures */ + SigMissing, + SigInvalid, + + /* Dependencies */ + UnsatisfiedDeps, + ConflictingDeps, + FileConflicts, + + /*Misc*/ + Retrieve, + InvalidRegex, + + /*ExternalLibraryors*/ + Libarchive, + Libcurl, + ExternalDownload, + Gpgme, + + /*MissingCompileTimeFeatures*/ + MissingCapabilitySignatures + } + [Flags] public enum LogLevel { diff --git a/Alpm/ErrNo.cs b/Alpm/ErrNo.cs deleted file mode 100644 index 9be718b..0000000 --- a/Alpm/ErrNo.cs +++ /dev/null @@ -1,81 +0,0 @@ -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 - } -} \ No newline at end of file diff --git a/Alpm/ExtensionMethods.cs b/Alpm/ExtensionMethods.cs index befcf0a..aad94f3 100644 --- a/Alpm/ExtensionMethods.cs +++ b/Alpm/ExtensionMethods.cs @@ -27,7 +27,8 @@ namespace Foodsoft.Alpm if (!release) throw new ObjectDisposedException(handle.GetType().FullName); refs[pkgPtr] = pkg; - listPtr = alpm.alpm_list_add(listPtr, handle.DangerousGetHandle()); + if (alpm.alpm_list_append(ref listPtr, handle.DangerousGetHandle()) == IntPtr.Zero) + throw new AlpmException(Error.Memory); } var foundPtr = alpm.alpm_find_satisfier(listPtr, depString); diff --git a/Alpm/File.cs b/Alpm/File.cs index ea3b02a..5e49501 100644 --- a/Alpm/File.cs +++ b/Alpm/File.cs @@ -1,7 +1,5 @@ using System; -using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; -using Foodsoft.Alpm.Marshalling; namespace Foodsoft.Alpm { @@ -28,5 +26,4 @@ namespace Foodsoft.Alpm Mode = native->mode; } } - } \ No newline at end of file diff --git a/Alpm/FileList.cs b/Alpm/FileList.cs index 73676e7..0140682 100644 --- a/Alpm/FileList.cs +++ b/Alpm/FileList.cs @@ -19,12 +19,13 @@ namespace Foodsoft.Alpm public File? Contains(string path) { - return _handle.UseHandle(_ptr, (ptr) => + return _handle.UseHandle(_ptr, ptr => { var foundPtr = alpm.alpm_filelist_contains(ptr, path); return foundPtr != IntPtr.Zero ? new File(foundPtr) : (File?) null; }); } + public IEnumerator GetEnumerator() { var release = false; @@ -35,10 +36,7 @@ namespace Foodsoft.Alpm _handle.DangerousAddRef(ref release); if (!release) throw new ObjectDisposedException(_handle.GetType().FullName); var arrayPtr = FileArray(_ptr, out var count); - for (var i = 0; i < count; ++i) - { - yield return new File(FilePtr(arrayPtr, i)); - } + for (var i = 0; i < count; ++i) yield return new File(FilePtr(arrayPtr, i)); } finally { @@ -58,7 +56,7 @@ namespace Foodsoft.Alpm { get { - return _handle.UseHandle(_ptr, (ptr) => + return _handle.UseHandle(_ptr, ptr => { var arrayPtr = FileArray(ptr, out var count); if (index >= count || index < 0) @@ -67,8 +65,8 @@ namespace Foodsoft.Alpm }); } } - - + + [StructLayout(LayoutKind.Sequential)] private readonly unsafe struct NativeFileList { diff --git a/Alpm/FilePackage.cs b/Alpm/FilePackage.cs index 85a2fb2..82a4c37 100644 --- a/Alpm/FilePackage.cs +++ b/Alpm/FilePackage.cs @@ -3,9 +3,6 @@ namespace Foodsoft.Alpm public class FilePackage : Package { // ReSharper disable once SuggestBaseTypeForParameter - internal FilePackage(SafeFilePackageHandle handle) : base(handle) - { - - } + internal FilePackage(SafeFilePackageHandle handle) : base(handle) { } } } \ No newline at end of file diff --git a/Alpm/Handle.cs b/Alpm/Handle.cs index 1df2a31..fb0fe1f 100644 --- a/Alpm/Handle.cs +++ b/Alpm/Handle.cs @@ -1,20 +1,25 @@ 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 AlpmException(err); - } + if (_handle.IsInvalid) throw new AlpmException(err); + } + + public Database LocalDB => ToDatabase(alpm.alpm_get_localdb(_handle)); + + public ICollection CacheDirs + { + get => + EnumerableWrapper.Create(_handle, alpm.alpm_option_get_cachedirs); + set => Detail.SetStringCollection(value, _handle, s => alpm.alpm_option_add_cachedir(_handle, s)); } public void Dispose() @@ -26,28 +31,29 @@ namespace Foodsoft.Alpm { // 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 AlpmException(_handle); - } + if (ptr == IntPtr.Zero) throw new AlpmException(_handle); return new Database(new SafeDatabaseHandle(ptr, _handle)); } - public Database LocalDB => ToDatabase(alpm.alpm_get_localdb(_handle)); - - public Database RegisterSyncDB(string treename, SigLevel sigLevel = 0) => - ToDatabase(alpm.alpm_register_syncdb(_handle, treename, sigLevel)); - - public void AddCacheDir(string dir) => Detail.WrapError(_handle, () => alpm.alpm_option_add_cachedir(_handle, dir)); - public bool RemoveCacheDir(string dir) => Detail.WrapErrorBool(_handle, () => alpm.alpm_option_add_cachedir(_handle, dir)); - public ICollection CacheDirs + public Database RegisterSyncDB(string treename, SigLevel sigLevel = 0) { - get => - EnumerableWrapper.Create(_handle, alpm.alpm_option_get_cachedirs); - set => Detail.SetStringCollection(value, _handle, (s) => alpm.alpm_option_add_cachedir(_handle, s)); + return ToDatabase(alpm.alpm_register_syncdb(_handle, treename, sigLevel)); } - public bool ShouldIgnorePackage(Package pkg) => alpm.alpm_pkg_should_ignore(_handle, pkg.Handle) == 0; + public void AddCacheDir(string dir) + { + Detail.WrapError(_handle, () => alpm.alpm_option_add_cachedir(_handle, dir)); + } + + public bool RemoveCacheDir(string dir) + { + return Detail.WrapErrorBool(_handle, () => alpm.alpm_option_add_cachedir(_handle, dir)); + } + + public bool ShouldIgnorePackage(Package pkg) + { + return alpm.alpm_pkg_should_ignore(_handle, pkg.Handle) == 0; + } } } \ No newline at end of file diff --git a/Alpm/IPackageData.cs b/Alpm/IPackageData.cs index bc6b208..f5a26e9 100644 --- a/Alpm/IPackageData.cs +++ b/Alpm/IPackageData.cs @@ -20,10 +20,10 @@ namespace Foodsoft.Alpm public enum ValidationType { Unknown = 0, - None = (1 << 0), - MD5Sum = (1 << 1), - SHA256Sum = (1 << 2), - Signature = (1 << 3) + None = 1 << 0, + MD5Sum = 1 << 1, + SHA256Sum = 1 << 2, + Signature = 1 << 3 } public interface IPackageData : IDisposable @@ -59,6 +59,6 @@ namespace Foodsoft.Alpm public ValidationType Validation { get; } public bool HasScriptlet { get; } public long DownloadSize { get; } - public Database? DB { get; } + public Database? DB { get; } } } \ No newline at end of file diff --git a/Alpm/Marshalling/UTF8In.cs b/Alpm/Marshalling/UTF8In.cs index 6b1e59d..0ab686a 100644 --- a/Alpm/Marshalling/UTF8In.cs +++ b/Alpm/Marshalling/UTF8In.cs @@ -16,7 +16,10 @@ namespace Foodsoft.Alpm.Marshalling Marshal.FreeCoTaskMem(pNativeData); } - public int GetNativeDataSize() => -1; + public int GetNativeDataSize() + { + return -1; + } public IntPtr MarshalManagedToNative(object? managedObj) { diff --git a/Alpm/Marshalling/UTF8Return.cs b/Alpm/Marshalling/UTF8Return.cs index 4ac5f50..39ffb81 100644 --- a/Alpm/Marshalling/UTF8Return.cs +++ b/Alpm/Marshalling/UTF8Return.cs @@ -18,7 +18,10 @@ namespace Foodsoft.Alpm.Marshalling public void CleanUpNativeData(IntPtr pNativeData) { } - public int GetNativeDataSize() => -1; + public int GetNativeDataSize() + { + return -1; + } public object MarshalNativeToManaged(IntPtr pNativeData) { diff --git a/Alpm/Package.cs b/Alpm/Package.cs index 0e2f7c8..83bc8e8 100644 --- a/Alpm/Package.cs +++ b/Alpm/Package.cs @@ -1,18 +1,17 @@ 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; } + internal SafePackageHandle Handle { get; } + 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); @@ -30,16 +29,22 @@ namespace Foodsoft.Alpm 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 Licenses => EnumerableWrapper.Create(Handle, alpm.alpm_pkg_get_licenses); + public IEnumerable Groups => EnumerableWrapper.Create(Handle, alpm.alpm_pkg_get_groups); public IEnumerable Depends => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_depends); + public IEnumerable OptDepends => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_optdepends); + public IEnumerable CheckDepends => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_checkdepends); + public IEnumerable MakeDepends => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_makedepends); + public IEnumerable Conflicts => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_conflicts); public IEnumerable Provides => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_provides); public IEnumerable Replaces => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_replaces); @@ -50,28 +55,23 @@ namespace Foodsoft.Alpm public bool HasScriptlet => alpm.alpm_pkg_has_scriptlet(Handle); public long DownloadSize => alpm.alpm_pkg_download_size(Handle); - public bool CheckMD5Sum() - { - throw new NotImplementedException(); - } - public virtual Database? DB => null; - public IEnumerator ComputeRequiredBy() - { - throw new NotImplementedException(); - } - - public IEnumerator ComputeOptionalFor() - { - throw new NotImplementedException(); - } - public void Dispose() { Handle.Dispose(); } + public IEnumerable ComputeRequiredBy() + { + throw new NotImplementedException(); + } + + public IEnumerable ComputeOptionalFor() + { + throw new NotImplementedException(); + } + public static int VersionCompare(string v1, string v2) { return alpm.alpm_pkg_vercmp(v1, v2); diff --git a/Alpm/SafeAlpmHandle.cs b/Alpm/SafeAlpmHandle.cs index 2d4b59b..64547c6 100644 --- a/Alpm/SafeAlpmHandle.cs +++ b/Alpm/SafeAlpmHandle.cs @@ -1,7 +1,6 @@ using System; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; -using Foodsoft.Alpm; namespace Foodsoft.Alpm { @@ -9,13 +8,18 @@ namespace Foodsoft.Alpm { 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] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [PrePrepareMethod] get => handle == IntPtr.Zero; } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + [PrePrepareMethod] + protected override bool ReleaseHandle() + { + return alpm.alpm_release(handle) == 0; + } } } \ No newline at end of file diff --git a/Alpm/SafeCachePackageHandle.cs b/Alpm/SafeCachePackageHandle.cs index 0f44831..0ed059b 100644 --- a/Alpm/SafeCachePackageHandle.cs +++ b/Alpm/SafeCachePackageHandle.cs @@ -1,30 +1,15 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; namespace Foodsoft.Alpm { internal sealed class SafeCachePackageHandle : SafePackageHandle { - internal SafeAlpmHandle SafeAlpmHandle - { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [PrePrepareMethod] - get => SafeDatabaseHandle.SafeAlpmHandle; - } - - internal SafeDatabaseHandle SafeDatabaseHandle - { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [PrePrepareMethod] - get; - } = null!; - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [PrePrepareMethod] internal SafeCachePackageHandle(IntPtr ptr, SafeDatabaseHandle parentHandle) - : base() + : base(parentHandle.SafeAlpmHandle) { var success = false; @@ -43,6 +28,15 @@ namespace Foodsoft.Alpm if (!success) throw new ObjectDisposedException(GetType().FullName); } + internal SafeDatabaseHandle SafeDatabaseHandle + { + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [PrePrepareMethod] + get; + } = null!; + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [PrePrepareMethod] protected override bool ReleaseHandle() { SafeDatabaseHandle.DangerousRelease(); diff --git a/Alpm/SafeDatabaseHandle.cs b/Alpm/SafeDatabaseHandle.cs index 6dd7152..34130d7 100644 --- a/Alpm/SafeDatabaseHandle.cs +++ b/Alpm/SafeDatabaseHandle.cs @@ -7,13 +7,6 @@ namespace Foodsoft.Alpm { internal sealed class SafeDatabaseHandle : SafeHandle { - internal SafeAlpmHandle SafeAlpmHandle - { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [PrePrepareMethod] - get; - } = null!; - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [PrePrepareMethod] internal SafeDatabaseHandle(IntPtr dbPtr, SafeAlpmHandle safeAlpmHandle) : base(IntPtr.Zero, true) @@ -35,18 +28,27 @@ namespace Foodsoft.Alpm if (!success) throw new ObjectDisposedException(GetType().FullName); } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), PrePrepareMethod] + internal SafeAlpmHandle SafeAlpmHandle + { + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [PrePrepareMethod] + get; + } = null!; + + public override bool IsInvalid + { + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [PrePrepareMethod] + get => handle == IntPtr.Zero; + } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + [PrePrepareMethod] protected override bool ReleaseHandle() { var err = alpm.alpm_db_unregister(handle); SafeAlpmHandle.DangerousRelease(); return err == 0; } - - public override bool IsInvalid - { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod] - get => handle == IntPtr.Zero; - } } } \ No newline at end of file diff --git a/Alpm/SafeFilePackageHandle.cs b/Alpm/SafeFilePackageHandle.cs index 8a37aea..c1229de 100644 --- a/Alpm/SafeFilePackageHandle.cs +++ b/Alpm/SafeFilePackageHandle.cs @@ -1,17 +1,14 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; namespace Foodsoft.Alpm { internal class SafeFilePackageHandle : SafePackageHandle { - internal SafeAlpmHandle SafeAlpmHandle { get; } = null!; - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [PrePrepareMethod] - internal SafeFilePackageHandle(IntPtr ptr, SafeAlpmHandle parentHandle) + internal SafeFilePackageHandle(IntPtr ptr, SafeAlpmHandle parentHandle) : base(parentHandle) { var success = false; @@ -20,20 +17,19 @@ namespace Foodsoft.Alpm finally { parentHandle.DangerousAddRef(ref success); - if (success) - { - SafeAlpmHandle = parentHandle; - handle = ptr; - } + if (success) handle = ptr; } if (!success) throw new ObjectDisposedException(GetType().FullName); } + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + [PrePrepareMethod] protected override bool ReleaseHandle() { + var err = alpm.alpm_pkg_free(handle); SafeAlpmHandle.DangerousRelease(); - return true; + return err == 0; } } } \ No newline at end of file diff --git a/Alpm/SafeListHandle`1.cs b/Alpm/SafeListHandle`1.cs deleted file mode 100644 index 996f971..0000000 --- a/Alpm/SafeListHandle`1.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; - -namespace Foodsoft.Alpm -{ - internal sealed class SafeListHandle : 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; - } - } -} \ No newline at end of file diff --git a/Alpm/SafePackageHandle.cs b/Alpm/SafePackageHandle.cs index 363d4cb..d3da3bf 100644 --- a/Alpm/SafePackageHandle.cs +++ b/Alpm/SafePackageHandle.cs @@ -6,10 +6,22 @@ namespace Foodsoft.Alpm { internal abstract class SafePackageHandle : SafeHandle { - protected SafePackageHandle() : base(IntPtr.Zero, true) { } + protected SafePackageHandle(SafeAlpmHandle safeAlpmHandle) : base(IntPtr.Zero, true) + { + SafeAlpmHandle = safeAlpmHandle; + } + + internal SafeAlpmHandle SafeAlpmHandle + { + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [PrePrepareMethod] + get; + } + public override bool IsInvalid { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [PrePrepareMethod] get => handle == IntPtr.Zero; } } diff --git a/Alpm/alpm.cs b/Alpm/alpm.cs index bf20cce..a744f1d 100644 --- a/Alpm/alpm.cs +++ b/Alpm/alpm.cs @@ -16,6 +16,9 @@ namespace Foodsoft.Alpm // ReSharper disable once InconsistentNaming internal static class alpm { + // ReSharper disable once InconsistentNaming + public delegate void alpm_fn_free(IntPtr ptr); + [DllImport(nameof(alpm))] public static extern int alpm_pkg_should_ignore(SafeAlpmHandle handle, SafePackageHandle pkg); @@ -122,7 +125,7 @@ namespace Foodsoft.Alpm [DllImport(nameof(alpm))] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Return))] public static extern string alpm_pkg_get_base64_sig(SafePackageHandle pkg); - + [DllImport(nameof(alpm))] public static extern ValidationType alpm_pkg_get_validation(SafePackageHandle pkg); @@ -135,12 +138,16 @@ namespace Foodsoft.Alpm [DllImport(nameof(alpm))] public static extern int alpm_pkg_set_reason(SafePackageHandle pkg, InstallReason reason); + [DllImport(nameof(alpm))] + public static extern int alpm_pkg_checkmd5sum(SafePackageHandle pkg); + + [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_add_cachedir(SafeAlpmHandle handle, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))] @@ -152,11 +159,11 @@ namespace Foodsoft.Alpm string cachedir); [DllImport(nameof(alpm))] - public static extern ErrNo alpm_errno(SafeAlpmHandle handle); + public static extern Error alpm_errno(SafeAlpmHandle handle); [DllImport(nameof(alpm))] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Return))] - public static extern string alpm_strerror(ErrNo err); + public static extern string alpm_strerror(Error err); [DllImport(nameof(alpm))] public static extern IntPtr alpm_get_localdb(SafeAlpmHandle handle); @@ -173,7 +180,7 @@ namespace Foodsoft.Alpm public static extern int alpm_db_unregister_all_syncdbs(SafeAlpmHandle handle); [DllImport(nameof(alpm))] - public static extern IntPtr alpm_list_add(IntPtr list, IntPtr item); + public static extern IntPtr alpm_list_append(ref IntPtr list, IntPtr item); [DllImport(nameof(alpm))] public static extern IntPtr alpm_list_append_strdup(ref IntPtr list, @@ -189,9 +196,6 @@ namespace Foodsoft.Alpm [DllImport(nameof(alpm))] public static extern void alpm_list_free(IntPtr list); - // ReSharper disable once InconsistentNaming - public delegate void alpm_fn_free(IntPtr ptr); - [DllImport(nameof(alpm))] public static extern void alpm_list_free_inner(IntPtr list, alpm_fn_free freeFn); @@ -214,7 +218,7 @@ namespace Foodsoft.Alpm public static extern SafeAlpmHandle alpm_initialize( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))] string root, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))] - string dbpath, out ErrNo err); + string dbpath, out Error err); [DllImport(nameof(alpm))] public static extern int alpm_release(IntPtr handle); @@ -257,6 +261,9 @@ namespace Foodsoft.Alpm [DllImport(nameof(alpm))] public static extern int alpm_db_set_usage(SafeDatabaseHandle db, Database.UsageFlags usage); + [DllImport(nameof(alpm))] + public static extern IntPtr alpm_db_search(SafeDatabaseHandle db, IntPtr needles); + [DllImport(nameof(alpm))] public static extern IntPtr alpm_pkg_get_pkg(SafeDatabaseHandle db, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))] @@ -267,7 +274,7 @@ namespace Foodsoft.Alpm [DllImport(nameof(alpm))] public static extern int alpm_pkg_vercmp(string v1, string v2); - + [DllImport(nameof(alpm))] public static extern IntPtr alpm_find_satisfier(IntPtr pkgList, string depstring); } diff --git a/Samples/Program.cs b/Samples/Program.cs index 2be67c5..0eea377 100644 --- a/Samples/Program.cs +++ b/Samples/Program.cs @@ -1,122 +1,128 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using Foodsoft.Alpm; - -// ReSharper disable once UnusedType.Global -namespace Samples -{ - [Example("installed")] - internal class Installed : IExample - { - private static string ModToStr(Depend.ModType modType) - { - return modType switch - { - Depend.ModType.Any => "", - Depend.ModType.Equal => "==", - Depend.ModType.GreaterThanOrEqual => ">=", - Depend.ModType.LessThanOrEqual => "<=", - Depend.ModType.GreaterThan => ">", - Depend.ModType.LessThan => "<", - _ => throw new ArgumentOutOfRangeException(nameof(modType), modType, null) - }; - } - - public int Run(string[] args) - { - using var h = new Handle("/", "/var/lib/pacman"); - using var db = h.LocalDB; - - foreach (var pkg in db.PackageCache) - using (pkg) - { - Console.WriteLine($"Size: {pkg.DownloadSize}"); - foreach (var d in pkg.OptDepends) - { - if (d.Description.Length == 0) continue; - Console.WriteLine("dep({0}): {1} {2} {3} {4}", pkg.Name, d.Name, ModToStr(d.Mod), d.Version, - d.Description); - foreach (var f in pkg.Backup) - Console.WriteLine($"{f.Name} {f.Hash}"); - } - } - - return 0; - } - } - - [Example("search")] - internal class Search : IExample - { - public int Run(string[] args) - { - using var h = new Handle("/", "/var/lib/pacman"); - using var db = h.RegisterSyncDB("core"); - db.Servers = new[] {"http://www.google.com"}; - - - using var pkg = db.PackageCache.FindSatisfier("gcc=9.3.0-1"); - Console.WriteLine($"{pkg?.Name} {pkg?.Version}"); - - return 0; - } - } -} - -namespace Samples -{ - internal static class Program - { - private static int Main(string[] args) - { - var examples = (from t in Assembly.GetExecutingAssembly().GetTypes() - let attribute = (Example?) t.GetCustomAttribute(typeof(Example)) - where attribute != null - select new {Name = attribute.Name, Type = t}).ToImmutableDictionary((e) => e.Name); - - if (args.Length < 1) - { - Console.Error.WriteLine("Sample"); - foreach (var example in examples.Values) - { - Console.Error.WriteLine("{0}", example.Name); - } - - return 1; - } - - int ret; - try - { - ret = ((IExample) Activator.CreateInstance(examples[args[0]].Type)!).Run(args); - } - catch (AlpmException e) - { - Console.Error.WriteLine("{0}", e.Message); - return 1; - } - - return ret; - } - } - - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)] - public class Example : Attribute - { - public string Name { get; } - - public Example(string name) - { - Name = name; - } - } - - public interface IExample - { - public int Run(string[] args); - } +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using Foodsoft.Alpm; + +// ReSharper disable once UnusedType.Global +namespace Samples +{ + [Example("installed")] + internal class Installed : IExample + { + private static string ModToStr(Depend.ModType modType) + { + return modType switch + { + Depend.ModType.Any => "", + Depend.ModType.Equal => "==", + Depend.ModType.GreaterThanOrEqual => ">=", + Depend.ModType.LessThanOrEqual => "<=", + Depend.ModType.GreaterThan => ">", + Depend.ModType.LessThan => "<", + _ => throw new ArgumentOutOfRangeException(nameof(modType), modType, null) + }; + } + + public int Run(string[] args) + { + using var h = new Handle("/", "/var/lib/pacman"); + using var db = h.LocalDB; + + foreach (var pkg in db.PackageCache) + using (pkg) + { + Console.WriteLine($"Size: {pkg.DownloadSize}"); + foreach (var d in pkg.OptDepends) + { + if (d.Description.Length == 0) continue; + Console.WriteLine("dep({0}): {1} {2} {3} {4}", pkg.Name, d.Name, ModToStr(d.Mod), d.Version, + d.Description); + foreach (var f in pkg.Backup) + Console.WriteLine($"{f.Name} {f.Hash}"); + } + } + + return 0; + } + } + + [Example("search")] + internal class Search : IExample + { + public int Run(string[] args) + { + using var h = new Handle("/", "/var/lib/pacman"); + using var db = h.RegisterSyncDB("core"); + db.Servers = new[] {"http://www.google.com"}; + + + //using var pkg = db.PackageCache.FindSatisfier("gcc=9.3.0-1"); + var result = db.Search(new string[] {"gcc", "objc"}); + foreach (var pkg in result) + using (pkg) + { + Console.WriteLine($"{pkg?.Name} {pkg?.Version}"); + } + + + return 0; + } + } +} + +namespace Samples +{ + internal static class Program + { + private static int Main(string[] args) + { + var examples = (from t in Assembly.GetExecutingAssembly().GetTypes() + let attribute = (Example?) t.GetCustomAttribute(typeof(Example)) + where attribute != null + select new {Name = attribute.Name, Type = t}).ToImmutableDictionary((e) => e.Name); + + if (args.Length < 1) + { + Console.Error.WriteLine("Sample"); + foreach (var example in examples.Values) + { + Console.Error.WriteLine("{0}", example.Name); + } + + return 1; + } + + int ret; + try + { + ret = ((IExample) Activator.CreateInstance(examples[args[0]].Type)!).Run(args); + } + catch (AlpmException e) + { + Console.Error.WriteLine("{0}", e.Message); + return 1; + } + + return ret; + } + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)] + public class Example : Attribute + { + public string Name { get; } + + public Example(string name) + { + Name = name; + } + } + + public interface IExample + { + public int Run(string[] args); + } } \ No newline at end of file