%PDF- %PDF-
Direktori : /usr/local/include/ |
Current File : //usr/local/include/pkg.h |
/*- * Copyright (c) 2011-2016 Baptiste Daroussin <bapt@FreeBSD.org> * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org> * Copyright (c) 2011 Will Andrews <will@FreeBSD.org> * Copyright (c) 2011 Philippe Pepiot <phil@philpep.org> * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com> * Copyright (c) 2013-2014 Matthew Seaman <matthew@FreeBSD.org> * Copyright (c) 2014-2016 Vsevolod Stakhov <vsevolod@FreeBSD.org> * Copyright (c) 2023 Serenity Cyber Security, LLC * Author: Gleb Popov <arrowd@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _PKG_H #define _PKG_H #ifdef __cplusplus extern "C" { #define restrict #endif #include <sys/types.h> #include <sys/param.h> #include <stdarg.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> /* The expected name of the pkg(8) binary executable. */ #ifndef PKG_EXEC_NAME #define PKG_EXEC_NAME "pkg" #endif /* The expected name of the pkg-static(8) binary */ #ifndef PKG_STATIC_NAME #define PKG_STATIC_NAME "pkg-static" #endif #define PKGVERSION "1.20.9" /* PORTVERSION equivalent for proper pkg-static->ports-mgmt/pkg * version comparison in pkgdb_query_newpkgversion() */ #define PKG_PORTVERSION "1.20.9" /* The OS major version at the time of compilation */ #ifdef __FreeBSD__ #define OSMAJOR __FreeBSD__ #endif /* Not supported under DragonFly */ #ifdef __DragonFly__ #undef OSMAJOR #endif #ifdef __NetBSD_Version__ #define OSMAJOR ((__NetBSD_Version__ + 1000000) / 100000000) #endif #ifndef __DECONST #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) #endif #ifndef NELEM #define NELEM(array) (sizeof(array) / sizeof((array)[0])) #endif /* Special exit status for worker processes indicating that a restart * is desired -- eg. after a child has updated pkg(8) itself. */ #define EX_NEEDRESTART 4 struct pkg; struct pkg_dep; struct pkg_conflict; struct pkg_file; struct pkg_dir; struct pkg_option; struct pkg_license; struct pkg_config_file; struct pkg_create; struct pkgdb; struct pkgdb_it; struct pkg_jobs; struct pkg_solve_problem; struct pkg_repo; struct pkg_plugin; struct pkg_manifest_parser; typedef struct ucl_object_s pkg_object; typedef void * pkg_iter; struct pkg_kv { char *key; char *value; }; /** * The system-wide pkg(8) status: ie. is it a) installed or otherwise * available on the sysem, b) database (local.sqlite) initialised and * c) has at least one package installed (which should be pkg * itself). PKG_STATUS_UNINSTALLED logically cannot be returned by * pkg(8) itself, but it can be useful for the pkg bootstrapper * /usr/bin/pkg or for applications that link against libpkg.so */ typedef enum { PKG_STATUS_ACTIVE = 0, /* pkg in use */ PKG_STATUS_NOPACKAGES, /* local.sqlite empty */ PKG_STATUS_NODB, /* local.sqlite not found, unreadable or not initialised */ PKG_STATUS_UNINSTALLED, /* pkg not argv[0] or not on $PATH */ } pkg_status_t; typedef enum { /** * The license logic is OR (dual in the ports) */ LICENSE_OR = '|', /** * The license logic is AND (multi in the ports) */ LICENSE_AND = '&', /** * The license logic un single (default in the ports) */ LICENSE_SINGLE = 1U } lic_t; typedef enum { PKGDB_DEFAULT = 0, PKGDB_REMOTE, PKGDB_MAYBE_REMOTE } pkgdb_t; typedef enum { PKG_INIT_FLAG_USE_IPV4 = (1U << 0), PKG_INIT_FLAG_USE_IPV6 = (1U << 1) } pkg_init_flags; /** * Specify how an argument should be used by query functions. */ typedef enum { /** * The argument does not matter, all items will be matched. */ MATCH_ALL, /** * The argument is the exact pattern. Match will be case * sensitive or case insensitive according to * pkgdb_case_sensitive() */ MATCH_EXACT, /** * The argument is an exact pattern except that matches will * be made case insensitively. Match is always case sensitive */ MATCH_GLOB, /** * The argument is a regular expression ('modern' style * according to re_format(7). Match will be case sensitive or * case insensitive according to pkgdb_case_sensitive() */ MATCH_REGEX, MATCH_INTERNAL } match_t; /** * Specify on which field the pattern will be matched uppon. */ typedef enum { FIELD_NONE, FIELD_ORIGIN, FIELD_NAME, FIELD_NAMEVER, FIELD_COMMENT, FIELD_DESC, FIELD_FLAVOR, } pkgdb_field; /** * The type of package. */ typedef enum { /** * The pkg type can not be determined. */ PKG_NONE = 0, /** * The pkg refers to a local file archive. */ PKG_FILE = (1U << 0), /** * The pkg refers to data read from a non-regular file * (device, pipeline, unix dmain socket etc.) */ PKG_STREAM = (1U << 1), /** * The pkg refers to a package available on the remote repository. * @todo Document which attributes are available. */ PKG_REMOTE = (1U << 2), /** * The pkg refers to a localy installed package. */ PKG_INSTALLED = (1U << 3), /** * The pkg refers to a local file old archive. */ PKG_OLD_FILE = (1U << 4), } pkg_t; /** * Contains keys to refer to a string attribute. * Used by pkg_get() and pkg_set() */ typedef enum { PKG_ATTR_ORIGIN = 1U, PKG_ATTR_NAME, PKG_ATTR_VERSION, PKG_ATTR_COMMENT, PKG_ATTR_DESC, PKG_ATTR_MTREE, PKG_ATTR_MESSAGE, PKG_ATTR_ARCH, PKG_ATTR_ABI, PKG_ATTR_MAINTAINER, PKG_ATTR_WWW, PKG_ATTR_PREFIX, PKG_ATTR_REPOPATH, PKG_ATTR_CKSUM, PKG_ATTR_OLD_VERSION, PKG_ATTR_REPONAME, PKG_ATTR_REPOURL, PKG_ATTR_DIGEST, PKG_ATTR_REASON, PKG_ATTR_FLATSIZE, PKG_ATTR_OLD_FLATSIZE, PKG_ATTR_PKGSIZE, PKG_ATTR_LICENSE_LOGIC, PKG_ATTR_AUTOMATIC, PKG_ATTR_LOCKED, PKG_ATTR_ROWID, PKG_ATTR_TIME, PKG_ATTR_ANNOTATIONS, PKG_ATTR_UNIQUEID, PKG_ATTR_OLD_DIGEST, PKG_ATTR_DEP_FORMULA, PKG_ATTR_VITAL, PKG_ATTR_CATEGORIES, PKG_ATTR_LICENSES, PKG_ATTR_GROUPS, PKG_ATTR_USERS, PKG_ATTR_SHLIBS_REQUIRED, PKG_ATTR_SHLIBS_PROVIDED, PKG_ATTR_PROVIDES, PKG_ATTR_REQUIRES, PKG_ATTR_CONFLICTS, PKG_ATTR_NUM_FIELDS, /* end of fields */ } pkg_attr; typedef enum { PKG_SET_FLATSIZE = 1U, PKG_SET_AUTOMATIC, PKG_SET_LOCKED, PKG_SET_DEPORIGIN, PKG_SET_ORIGIN, PKG_SET_DEPNAME, PKG_SET_NAME, PKG_SET_VITAL, PKG_SET_MAX } pkg_set_attr; /** * contains keys to refer to a string attribute * Used by pkg_dep_get() */ typedef enum { PKG_DEP_NAME = 0, PKG_DEP_ORIGIN, PKG_DEP_VERSION } pkg_dep_attr; typedef enum { PKG_DEPS = 0, PKG_RDEPS, PKG_OPTIONS, PKG_FILES, PKG_DIRS, PKG_USERS, PKG_GROUPS, PKG_SHLIBS_REQUIRED, PKG_SHLIBS_PROVIDED, PKG_CONFLICTS, PKG_PROVIDES, PKG_CONFIG_FILES, PKG_REQUIRES, } pkg_list; typedef enum { SRV, HTTP, NOMIRROR, } mirror_t; typedef enum { SIG_NONE = 0, SIG_PUBKEY, SIG_FINGERPRINT } signature_t; /** * Determine the type of a pkg_script. */ typedef enum { PKG_SCRIPT_PRE_INSTALL = 0, PKG_SCRIPT_POST_INSTALL, PKG_SCRIPT_PRE_DEINSTALL, PKG_SCRIPT_POST_DEINSTALL, __DO_NOT_USE_ME1, __DO_NOT_USE_ME2, PKG_SCRIPT_INSTALL, PKG_SCRIPT_DEINSTALL, __DO_NOT_USE_ME3, PKG_SCRIPT_UNKNOWN } pkg_script; /** * Determine the type of a pkg_lua_script. */ typedef enum { PKG_LUA_PRE_INSTALL = 0, PKG_LUA_POST_INSTALL, PKG_LUA_PRE_DEINSTALL, PKG_LUA_POST_DEINSTALL, PKG_LUA_UNKNOWN } pkg_lua_script; typedef enum _pkg_jobs_t { PKG_JOBS_INSTALL, PKG_JOBS_DEINSTALL, PKG_JOBS_FETCH, PKG_JOBS_AUTOREMOVE, PKG_JOBS_UPGRADE, } pkg_jobs_t; typedef enum _pkg_flags { PKG_FLAG_NONE = 0, PKG_FLAG_DRY_RUN = (1U << 0), PKG_FLAG_FORCE = (1U << 1), PKG_FLAG_RECURSIVE = (1U << 2), PKG_FLAG_AUTOMATIC = (1U << 3), PKG_FLAG_WITH_DEPS = (1U << 4), PKG_FLAG_NOSCRIPT = (1U << 5), PKG_FLAG_PKG_VERSION_TEST = (1U << 6), PKG_FLAG_UPGRADES_FOR_INSTALLED = (1U << 7), PKG_FLAG_SKIP_INSTALL = (1U << 8), PKG_FLAG_FORCE_MISSING = (1U << 9), PKG_FLAG_FETCH_MIRROR = (1U << 10), PKG_FLAG_USE_IPV4 = (1U << 11), PKG_FLAG_USE_IPV6 = (1U << 12), PKG_FLAG_UPGRADE_VULNERABLE = (1U << 13) } pkg_flags; typedef enum _pkg_stats_t { PKG_STATS_LOCAL_COUNT = 0, PKG_STATS_LOCAL_SIZE, PKG_STATS_REMOTE_COUNT, PKG_STATS_REMOTE_UNIQUE, PKG_STATS_REMOTE_SIZE, PKG_STATS_REMOTE_REPOS, } pkg_stats_t; typedef enum { PKG_STRING = 0, PKG_BOOL, PKG_INT, PKG_ARRAY, PKG_OBJECT, PKG_NULL } pkg_object_t; /** * Keys for accessing pkg plugin data */ typedef enum _pkg_plugin_key { PKG_PLUGIN_NAME = 0, PKG_PLUGIN_DESC, PKG_PLUGIN_VERSION, PKG_PLUGIN_PLUGINFILE } pkg_plugin_key; /** * Keys for hooking into the library */ typedef enum _pkg_plugin_hook_t { PKG_PLUGIN_HOOK_PRE_INSTALL = 1, PKG_PLUGIN_HOOK_POST_INSTALL, PKG_PLUGIN_HOOK_PRE_DEINSTALL, PKG_PLUGIN_HOOK_POST_DEINSTALL, PKG_PLUGIN_HOOK_PRE_FETCH, PKG_PLUGIN_HOOK_POST_FETCH, PKG_PLUGIN_HOOK_EVENT, PKG_PLUGIN_HOOK_PRE_UPGRADE, PKG_PLUGIN_HOOK_POST_UPGRADE, PKG_PLUGIN_HOOK_PRE_AUTOREMOVE, PKG_PLUGIN_HOOK_POST_AUTOREMOVE, PKG_PLUGIN_HOOK_PKGDB_CLOSE_RW, PKG_PLUGIN_HOOK_REPO_UPDATE_SUCCESS, PKG_PLUGIN_HOOK_LAST } pkg_plugin_hook_t; /** * Error type used everywhere by libpkg. */ typedef enum { EPKG_OK = 0, /** * No more items available (end of the loop). */ EPKG_END, EPKG_WARN, /** * The function encountered a fatal error. */ EPKG_FATAL, /** * Can not delete the package because it is required by * another package. */ EPKG_REQUIRED, /** * Can not install the package because it is already installed. */ EPKG_INSTALLED, /** * Can not install the package because some dependencies are * unresolved. */ EPKG_DEPENDENCY, /** * Can not operate on package because it is locked */ EPKG_LOCKED, /** * Can not create local database or database non-existent */ EPKG_ENODB, /** * local file newer than remote */ EPKG_UPTODATE, /** * unkown keyword */ EPKG_UNKNOWN, /** * repo DB schema incompatible version */ EPKG_REPOSCHEMA, /** * Insufficient privilege for action */ EPKG_ENOACCESS, /** * Insecure permissions on any component of * $PKGDB_DIR/local.sqlite or any of the repo database bits */ EPKG_INSECURE, /** * A conflict between packages found */ EPKG_CONFLICT, /** * Need to repeat operation */ EPKG_AGAIN, /** * Not installed */ EPKG_NOTINSTALLED, /** * Can not delete the package because it is vital, i.e. a kernel */ EPKG_VITAL, /** * the package already exist */ EPKG_EXIST, /** * the operation was cancelled */ EPKG_CANCEL } pkg_error_t; /** * Upgrade, downgrade or reinstall? */ typedef enum { PKG_DOWNGRADE = 0, PKG_REINSTALL, PKG_UPGRADE, } pkg_change_t; /** * Locking types for database: * `PKGDB_LOCK_READONLY`: lock for read only queries (can be nested) * `PKGDB_LOCK_ADVISORY`: write to DB inside a transaction (allows `PKGDB_LOCK_READONLY`) * `PKGDB_LOCK_EXCLUSIVE`: possibly destructive operations (does not allow other locks) */ typedef enum { PKGDB_LOCK_READONLY, PKGDB_LOCK_ADVISORY, PKGDB_LOCK_EXCLUSIVE } pkgdb_lock_t; typedef enum { PKG_SOLVED_INSTALL, PKG_SOLVED_DELETE, PKG_SOLVED_UPGRADE, PKG_SOLVED_UPGRADE_REMOVE, PKG_SOLVED_FETCH, PKG_SOLVED_UPGRADE_INSTALL } pkg_solved_t; struct pkg_kvlist; struct pkg_stringlist; typedef enum { PKG_KVLIST = 1U, PKG_STRINGLIST, PKG_STR, PKG_INTEGER, PKG_BOOLEAN, } pkg_el_t; struct pkg_el { union { struct pkg_kvlist *kvlist; struct pkg_stringlist *stringlist; const char *string; int64_t integer; bool boolean; }; pkg_el_t type; }; #define PKG_OPEN_MANIFEST_ONLY 0x1 #define PKG_OPEN_MANIFEST_COMPACT (0x1 << 1) #define PKG_OPEN_TRY (0x1 << 2) /** * test if pkg is installed and activated. * @param count If all the tests pass, and count is non-NULL, * write the number of installed packages into *count */ pkg_status_t pkg_status(int *count); /** * Allocate a new pkg. * Allocated pkg must be deallocated by pkg_free(). */ int pkg_new(struct pkg **, pkg_t type); /** * Deallocate a pkg */ void pkg_free(struct pkg *); /** * Check if a package is valid according to its type. */ int pkg_is_valid(const struct pkg * restrict); /** * Open a package file archive and retrive informations. * @param p A pointer to pkg allocated by pkg_new(), or if it points to a * NULL pointer, the function allocate a new pkg using pkg_new(). * @param path The path to the local package archive. * @param keys manifest keys that should be initialised * @param flags open flags */ int pkg_open(struct pkg **p, const char *path, int flags); int pkg_open_fd(struct pkg **p, int fd, int flags); /** * @return the type of the package. * @warning returns PKG_NONE on error. */ pkg_t pkg_type(const struct pkg * restrict); int pkg_list_count(const struct pkg *, pkg_list); /** * Iterates over the dependencies of the package. * @param dep Must be set to NULL for the first call. * @return An error code. */ int pkg_deps(const struct pkg *, struct pkg_dep **dep); /** * Iterates over the reverse dependencies of the package. * That is, the packages which require this package. * @param dep Must be set to NULL for the first call. * @return An error code. */ int pkg_rdeps(const struct pkg *, struct pkg_dep **dep); /** * Iterates over the files of the package. * @param file Must be set to NULL for the first call. * @return An error code. */ int pkg_files(const struct pkg *, struct pkg_file **file); /** * Iterates over the directories of the package. * @param Must be set to NULL for the first call. * @return An error code. */ int pkg_dirs(const struct pkg *pkg, struct pkg_dir **dir); /** * Iterates over the options of the package. * @param option Must be set to NULL for the first call. * @return An error code. */ int pkg_options(const struct pkg *, struct pkg_option **option); /** * Iterates over the conflicts registered in the package. * @param conflict must be set to NULL for the first call. * @return An error code */ int pkg_conflicts(const struct pkg *pkg, struct pkg_conflict **conflict); int pkg_licenses(const struct pkg *pkg, char **licenses); /** * Iterates over the config files registered in the package. * @param provide must be set to NULL for the first call. * @return An error code */ int pkg_config_files(const struct pkg *pkg, struct pkg_config_file **cf); /** * Iterate over all of the files within the package pkg, ensuring the * dependency list contains all applicable packages providing the * shared objects used by pkg. * Also add all the shared object into the shlibs. * It respects the SHLIBS options from configuration * @return An error code */ /* Don't conflict with PKG_LOAD_* q.v. */ #define PKG_CONTAINS_ELF_OBJECTS (1U << 24) #define PKG_CONTAINS_STATIC_LIBS (1U << 25) #define PKG_CONTAINS_LA (1U << 26) int pkg_analyse_files(struct pkgdb *, struct pkg *, const char *); int pkgdb_set2(struct pkgdb *db, struct pkg *pkg, ...); #define pkgdb_set(db, pkg, ...) pkgdb_set2(db, pkg, __VA_ARGS__, -1) /** * Set a new debug level used inside of pkg. * @param debug_level Debug level between 0 (no debugging) and 4 (max debugging). * @return Previous debug level. */ int64_t pkg_set_debug_level(int64_t debug_level); int pkg_set_rootdir(const char *rootdir); int pkg_open_devnull(void); void pkg_close_devnull(void); /** * Allocate a new struct pkg and add it to the deps of pkg. * @return An error code. */ int pkg_adddep(struct pkg *pkg, const char *name, const char *origin, const char *version, bool locked); int pkg_addrdep(struct pkg *pkg, const char *name, const char *origin, const char *version, bool locked); /** * Helper which call pkg_addscript() with the content of the file and * with the correct type. */ int pkg_addscript_fileat(int fd, struct pkg *pkg, const char *path); int pkg_addluascript_fileat(int fd, struct pkg *pkg, const char *path); /** * Parse a manifest and set the attributes of pkg accordingly. * @param buf An NULL-terminated buffer containing the manifest data. * @return An error code. */ int pkg_parse_manifest(struct pkg *pkg, const char *buf, size_t len); int pkg_parse_manifest_file(struct pkg *pkg, const char *); int pkg_parse_manifest_fileat(int fd, struct pkg *pkg, const char *); #define PKG_MANIFEST_EMIT_COMPACT 0x1 #define PKG_MANIFEST_EMIT_NOFILES (0x1 << 1) #define PKG_MANIFEST_EMIT_PRETTY (0x1 << 2) #define PKG_MANIFEST_EMIT_JSON (0x1 << 3) #define PKG_MANIFEST_EMIT_UCL (0x1 << 4) #define PKG_MANIFEST_EMIT_LOCAL_METADATA (0x1 << 5) /** * Emit a manifest according to the attributes of pkg. * @param buf A pointer which will hold the allocated buffer containing the * manifest. To be free'ed. * @param flags Flags for manifest emitting. * @param pdigest A pointer that will hold digest of manifest produced, ignored * if NULL. To be free'ed if not NULL. * @return An error code. */ int pkg_emit_manifest(struct pkg *pkg, char **buf, short flags, char **pdigest); int pkg_emit_manifest_file(struct pkg*, FILE *, short, char **pdigest); /* pkg_dep */ const char *pkg_dep_get(struct pkg_dep const * const , const pkg_dep_attr); #define pkg_dep_name(d) pkg_dep_get(d, PKG_DEP_NAME) #define pkg_dep_origin(d) pkg_dep_get(d, PKG_DEP_ORIGIN) #define pkg_dep_version(d) pkg_dep_get(d, PKG_DEP_VERSION) bool pkg_dep_is_locked(struct pkg_dep const * const); bool pkg_has_dir(struct pkg *, const char *); bool pkg_has_file(struct pkg *, const char *); struct pkg_file *pkg_get_file(struct pkg *p, const char *path); struct pkg_dir *pkg_get_dir(struct pkg *p, const char *path); /* pkg_license */ const char *pkg_license_name(struct pkg_license const * const); /* pkg_script */ const char *pkg_script_get(struct pkg const * const, pkg_script); /** * @param db A pointer to a struct pkgdb object * @param origin Package origin * @param pkg An allocated struct pkg or a pointer to a NULL pointer. In the * last case, the function take care of the allocation. * @param flags OR'ed PKG_LOAD_* * @return EPKG_OK if the package is installed, * and != EPKG_OK if the package is not installed or an error occurred * Match will be case sensitive or insensitive depending on * pkgdb_case_sensitive() */ int pkg_try_installed(struct pkgdb *db, const char *origin, struct pkg **pkg, unsigned flags); /** * @param db A pointer to a struct pkgdb object * @param origin Package origin * @return EPKG_OK if the package is installed, * and != EPKG_OK if the package is not installed or an error occurred * Match will be case sensitive or insensitive depending on * pkgdb_case_sensitive() */ int pkg_is_installed(struct pkgdb *db, const char *name); /** * Create a repository database. * @param path The path where the repository live. * @param output_dir The path where the package repository should be created. * @param force If true, rebuild the repository catalogue from scratch * @param filesite If true, create a list of all files in repo * @param metafile Open meta from the specified file */ typedef int(pkg_password_cb)(char *, int, int, void*); int pkg_create_repo(char *path, const char *output_dir, bool filelist, const char *metafile, bool hash, bool hash_symlink); int pkg_finish_repo(const char *output_dir, pkg_password_cb *cb, char **argv, int argc, bool filelist); /** * Test if the EUID has sufficient privilege to carry out some * operation (mode is a bitmap indicating READ, WRITE, CREATE) on the * databases indicated in the database bitmap. */ #define PKGDB_MODE_READ (0x1<<0) #define PKGDB_MODE_WRITE (0x1<<1) #define PKGDB_MODE_CREATE (0x1<<2) #define PKGDB_DB_LOCAL (0x1<<0) #define PKGDB_DB_REPO (0x1<<1) int pkgdb_access(unsigned mode, unsigned database); /** * Open the local package database. * The db must be free'ed with pkgdb_close(). * @return An error code. */ int pkgdb_open(struct pkgdb **db, pkgdb_t type); /** * Open the local package database and repositories, possibly * overriding configured repositories and replacing with the given * reponame if not NULL * @return An error code */ int pkgdb_open_all(struct pkgdb **db, pkgdb_t type, const char *reponame); /** * Locking functions */ int pkgdb_obtain_lock(struct pkgdb *db, pkgdb_lock_t type); int pkgdb_upgrade_lock(struct pkgdb *db, pkgdb_lock_t old_type, pkgdb_lock_t new_type); int pkgdb_downgrade_lock(struct pkgdb *db, pkgdb_lock_t old_type, pkgdb_lock_t new_type); int pkgdb_release_lock(struct pkgdb *db, pkgdb_lock_t type); /** * Transaction/savepoint handling. * @param savepoint -- if NULL or an empty string, use BEGIN, ROLLBACK, COMMIT * otherwise use SAVEPOINT, ROLLBACK TO, RELEASE. * @return an error code. */ int pkgdb_transaction_begin(struct pkgdb *db, const char *savepoint); int pkgdb_transaction_commit(struct pkgdb *db, const char *savepoint); int pkgdb_transaction_rollback(struct pkgdb *db, const char *savepoint); /** * Close and free the struct pkgdb. */ void pkgdb_close(struct pkgdb *db); /** * Set the case sensitivity flag on or off. Defaults to * true (case_sensitive) */ void pkgdb_set_case_sensitivity(bool); /** * Query the state of the case sensitity setting. */ bool pkgdb_case_sensitive(void); /** * Query the local package database. * @param type Describe how pattern should be used. * @warning Returns NULL on failure. */ struct pkgdb_it * pkgdb_query(struct pkgdb *db, const char *pattern, match_t type); struct pkgdb_it * pkgdb_query_cond(struct pkgdb *db, const char *cond, const char *pattern, match_t type); struct pkgdb_it * pkgdb_repo_query(struct pkgdb *db, const char *pattern, match_t type, const char *reponame); struct pkgdb_it *pkgdb_repo_query_cond(struct pkgdb *db, const char *cond, const char *pattern, match_t type, const char *reponame); struct pkgdb_it * pkgdb_repo_search(struct pkgdb *db, const char *pattern, match_t type, pkgdb_field field, pkgdb_field sort, const char *reponame); struct pkgdb_it * pkgdb_all_search(struct pkgdb *db, const char *pattern, match_t type, pkgdb_field field, pkgdb_field sort, const char *reponame); /** * @todo Return directly the struct pkg? */ struct pkgdb_it * pkgdb_query_which(struct pkgdb *db, const char *path, bool glob); struct pkgdb_it * pkgdb_query_shlib_require(struct pkgdb *db, const char *shlib); struct pkgdb_it * pkgdb_query_shlib_provide(struct pkgdb *db, const char *shlib); struct pkgdb_it * pkgdb_query_require(struct pkgdb *db, const char *req); struct pkgdb_it * pkgdb_query_provide(struct pkgdb *db, const char *req); /** * Add/Modify/Delete an annotation for a package * @param tag -- tag for the annotation * @param value -- text of the annotation * @return An error code */ int pkgdb_add_annotation(struct pkgdb *db, struct pkg *pkg, const char *tag, const char *value); int pkgdb_modify_annotation(struct pkgdb *db, struct pkg *pkg, const char *tag, const char *value); int pkgdb_delete_annotation(struct pkgdb *db, struct pkg *pkg, const char *tag); #define PKG_LOAD_BASIC 0 #define PKG_LOAD_DEPS (1U << 0) #define PKG_LOAD_RDEPS (1U << 1) #define PKG_LOAD_FILES (1U << 2) #define PKG_LOAD_SCRIPTS (1U << 3) #define PKG_LOAD_OPTIONS (1U << 4) #define PKG_LOAD_DIRS (1U << 5) #define PKG_LOAD_CATEGORIES (1U << 6) #define PKG_LOAD_LICENSES (1U << 7) #define PKG_LOAD_USERS (1U << 8) #define PKG_LOAD_GROUPS (1U << 9) #define PKG_LOAD_SHLIBS_REQUIRED (1U << 10) #define PKG_LOAD_SHLIBS_PROVIDED (1U << 11) #define PKG_LOAD_ANNOTATIONS (1U << 12) #define PKG_LOAD_CONFLICTS (1U << 13) #define PKG_LOAD_PROVIDES (1U << 14) #define PKG_LOAD_REQUIRES (1U << 15) #define PKG_LOAD_LUA_SCRIPTS (1u << 16) /* Make sure new PKG_LOAD don't conflict with PKG_CONTAINS_* */ /** * Get the next pkg. * @param pkg An allocated struct pkg or a pointer to a NULL pointer. In the * last case, the function take care of the allocation. * @param flags OR'ed PKG_LOAD_* * @return An error code. */ int pkgdb_it_next(struct pkgdb_it *, struct pkg **pkg, unsigned flags); /** * Reset the pkgdb_it iterator, allowing for re-iterating over it */ void pkgdb_it_reset(struct pkgdb_it *); /** * Return the number of rows found. * @return -1 on error */ int pkgdb_it_count(struct pkgdb_it *); /** * Free a struct pkgdb_it. */ void pkgdb_it_free(struct pkgdb_it *); /** * Compact the database to save space. * Note that the function will really compact the database only if some * internal criterias are met. * @return An error code. */ int pkgdb_compact(struct pkgdb *db); /** * Install and register a new package. * @param db An opened pkgdb * @param path The path to the package archive file on the local disk * @return An error code. */ int pkg_add(struct pkgdb *db, const char *path, unsigned flags, const char *location); #define PKG_ADD_UPGRADE (1U << 0) /* (1U << 1) removed intentionally */ #define PKG_ADD_AUTOMATIC (1U << 2) #define PKG_ADD_FORCE (1U << 3) #define PKG_ADD_NOSCRIPT (1U << 4) #define PKG_ADD_FORCE_MISSING (1U << 5) #define PKG_ADD_SPLITTED_UPGRADE (1U << 6) /** * Allocate a new pkg_jobs. * @param db A pkgdb open with PKGDB_REMOTE. * @return An error code. */ int pkg_jobs_new(struct pkg_jobs **jobs, pkg_jobs_t type, struct pkgdb *db); /** * Free a pkg_jobs */ void pkg_jobs_free(struct pkg_jobs *jobs); /** * Add a pkg to the jobs queue. * @return An error code. */ int pkg_jobs_add(struct pkg_jobs *j, match_t match, char **argv, int argc); int pkg_jobs_solve(struct pkg_jobs *j); int pkg_jobs_set_repository(struct pkg_jobs *j, const char *name); const char* pkg_jobs_destdir(struct pkg_jobs *j); int pkg_jobs_set_destdir(struct pkg_jobs *j, const char *name); void pkg_jobs_set_flags(struct pkg_jobs *j, pkg_flags f); pkg_jobs_t pkg_jobs_type(struct pkg_jobs *j); /** * Returns the number of elements in the job queue */ int pkg_jobs_count(struct pkg_jobs *jobs); /** * Returns the number of total elements in pkg universe */ int pkg_jobs_total(struct pkg_jobs *jobs); /** * Iterates over the packages in the jobs queue. * @param iter Must be set to NULL for the first call. * @return A next pkg or NULL. */ bool pkg_jobs_iter(struct pkg_jobs *jobs, void **iter, struct pkg **n, struct pkg **o, int *type); /** * Apply the jobs in the queue (fetch and install). * @return An error code. */ int pkg_jobs_apply(struct pkg_jobs *jobs); /** * Emit CUDF spec to a file for a specified jobs request * @return error code */ int pkg_jobs_cudf_emit_file(struct pkg_jobs *, pkg_jobs_t , FILE *); /** * Parse the output of an external CUDF solver * @return error code */ int pkg_jobs_cudf_parse_output(struct pkg_jobs *j, FILE *f); /** * Check if there are locked packages * @return true if locked packages exist, false if not */ bool pkg_jobs_has_lockedpkgs(struct pkg_jobs *j); /** * Iterate through the locked packages, calling the passed in function pointer * on each. */ typedef int(*locked_pkgs_cb)(struct pkg *, void *); void pkg_jobs_iter_lockedpkgs(struct pkg_jobs *j, locked_pkgs_cb, void *); /** * Solve a SAT problem * @return true if a problem is solvable */ int pkg_solve_sat_problem(struct pkg_solve_problem *problem); /** * Export SAT problem to a dot graph description */ void pkg_solve_dot_export(struct pkg_solve_problem *problem, FILE *file); /** * Convert package jobs to a SAT problem * @return SAT problem or NULL if failed */ struct pkg_solve_problem * pkg_solve_jobs_to_sat(struct pkg_jobs *j); /** * Export sat problem to the DIMACS format * @return error code */ int pkg_solve_dimacs_export(struct pkg_solve_problem *problem, FILE *f); /** * Move solved problem to the jobs structure * @return error code */ int pkg_solve_sat_to_jobs(struct pkg_solve_problem *problem); /** * Parse SAT solver output and convert it to jobs * @return error code */ int pkg_solve_parse_sat_output(FILE *f, struct pkg_solve_problem *problem); /** * Free a SAT problem structure */ void pkg_solve_problem_free(struct pkg_solve_problem *problem); /** * Archive formats options. */ typedef enum pkg_formats { TAR, TGZ, TBZ, TXZ, TZS } pkg_formats; int pkg_load_metadata(struct pkg *, const char *, const char *, const char *, const char *, bool); /** * Download the latest repo db file and checks its signature if any * @param force Always download the repo catalogue */ int pkg_update(struct pkg_repo *repo, bool force); /** * Get statistics information from the package database(s) * @param db A valid database object as returned by pkgdb_open() * @param type Type of statistics to be returned * @return The statistic information requested */ int64_t pkgdb_stats(struct pkgdb *db, pkg_stats_t type); /** * pkg plugin functions * @todo Document */ int pkg_plugins_init(void); void pkg_plugins_shutdown(void); int pkg_plugins(struct pkg_plugin **plugin); int pkg_plugin_set(struct pkg_plugin *p, pkg_plugin_key key, const char *str); const char *pkg_plugin_get(struct pkg_plugin *p, pkg_plugin_key key); void *pkg_plugin_func(struct pkg_plugin *p, const char *func); int pkg_plugin_conf_add(struct pkg_plugin *p, pkg_object_t type, const char *key, const char *def); const pkg_object *pkg_plugin_conf(struct pkg_plugin *p); int pkg_plugin_parse(struct pkg_plugin *p); void pkg_plugin_errno(struct pkg_plugin *p, const char *func, const char *arg); void pkg_plugin_error(struct pkg_plugin *p, const char *fmt, ...); void pkg_plugin_info(struct pkg_plugin *p, const char *fmt, ...); /** * This is where plugin hook into the library using pkg_plugin_hook() * @todo: Document */ typedef int(*pkg_plugin_callback)(void *data, struct pkgdb *db); int pkg_plugins_hook_run(pkg_plugin_hook_t hook, void *data, struct pkgdb *db); int pkg_plugin_hook_register(struct pkg_plugin *p, pkg_plugin_hook_t hook, pkg_plugin_callback callback); /** * Get the value of a configuration key */ const pkg_object *pkg_config_get(const char *); pkg_object_t pkg_object_type(const pkg_object *); int64_t pkg_object_int(const pkg_object *o); bool pkg_object_bool(const pkg_object *o); const char *pkg_object_string(const pkg_object *o); void pkg_object_free(pkg_object *o); const char *pkg_object_key(const pkg_object *); const pkg_object *pkg_object_iterate(const pkg_object *, pkg_iter *); char *pkg_object_dump(const pkg_object *o); char *pkg_config_dump(void); /** * @todo Document */ int pkg_version_cmp(const char * const , const char * const); pkg_change_t pkg_version_change_between(const struct pkg * pkg1, const struct pkg *pkg2); /** * Fetch a file. * @return An error code. */ int pkg_fetch_file(struct pkg_repo *repo, const char *url, char *dest, time_t t, ssize_t offset, int64_t size); /** * Fetch a file to temporary destination */ int pkg_fetch_file_tmp(struct pkg_repo *repo, const char *url, char *dest, time_t t); /** * Get cached name of a package */ int pkg_repo_cached_name(struct pkg *pkg, char *dest, size_t destlen); /* glue to deal with ports */ int ports_parse_plist(struct pkg *, const char *, const char *); /** * Special structure to report about conflicts */ struct pkg_event_conflict { char *uid; struct pkg_event_conflict *next; }; /* * Capsicum sandbox callbacks */ typedef int (*pkg_sandbox_cb)(int fd, void *user_data); /** * Event type used to report progress or problems. */ typedef enum { /* informational */ PKG_EVENT_INSTALL_BEGIN = 0, PKG_EVENT_INSTALL_FINISHED, PKG_EVENT_DEINSTALL_BEGIN, PKG_EVENT_DEINSTALL_FINISHED, PKG_EVENT_UPGRADE_BEGIN, PKG_EVENT_UPGRADE_FINISHED, PKG_EVENT_EXTRACT_BEGIN, PKG_EVENT_EXTRACT_FINISHED, PKG_EVENT_DELETE_FILES_BEGIN, PKG_EVENT_DELETE_FILES_FINISHED, PKG_EVENT_ADD_DEPS_BEGIN, PKG_EVENT_ADD_DEPS_FINISHED, PKG_EVENT_FETCHING, PKG_EVENT_FETCH_BEGIN, PKG_EVENT_FETCH_FINISHED, PKG_EVENT_UPDATE_ADD, PKG_EVENT_UPDATE_REMOVE, PKG_EVENT_INTEGRITYCHECK_BEGIN, PKG_EVENT_INTEGRITYCHECK_FINISHED, PKG_EVENT_INTEGRITYCHECK_CONFLICT, PKG_EVENT_NEWPKGVERSION, PKG_EVENT_NOTICE, PKG_EVENT_DEBUG, PKG_EVENT_INCREMENTAL_UPDATE_BEGIN, PKG_EVENT_INCREMENTAL_UPDATE, // _FINISHED PKG_EVENT_QUERY_YESNO, PKG_EVENT_QUERY_SELECT, PKG_EVENT_SANDBOX_CALL, PKG_EVENT_SANDBOX_GET_STRING, PKG_EVENT_PROGRESS_START, PKG_EVENT_PROGRESS_TICK, PKG_EVENT_BACKUP, PKG_EVENT_RESTORE, /* errors */ PKG_EVENT_ERROR, PKG_EVENT_ERRNO, PKG_EVENT_ARCHIVE_COMP_UNSUP = 65536, PKG_EVENT_ALREADY_INSTALLED, PKG_EVENT_FAILED_CKSUM, PKG_EVENT_CREATE_DB_ERROR, PKG_EVENT_LOCKED, PKG_EVENT_REQUIRED, PKG_EVENT_MISSING_DEP, PKG_EVENT_NOREMOTEDB, PKG_EVENT_NOLOCALDB, PKG_EVENT_FILE_MISMATCH, PKG_EVENT_DEVELOPER_MODE, PKG_EVENT_PLUGIN_ERRNO, PKG_EVENT_PLUGIN_ERROR, PKG_EVENT_PLUGIN_INFO, PKG_EVENT_NOT_FOUND, PKG_EVENT_NEW_ACTION, PKG_EVENT_MESSAGE, PKG_EVENT_FILE_MISSING, PKG_EVENT_CLEANUP_CALLBACK_REGISTER, PKG_EVENT_CLEANUP_CALLBACK_UNREGISTER, PKG_EVENT_CONFLICTS, PKG_EVENT_TRIGGERS_BEGIN, PKG_EVENT_TRIGGER, PKG_EVENT_TRIGGERS_FINISHED } pkg_event_t; struct pkg_event { pkg_event_t type; union { struct { const char *func; const char *arg; int no; } e_errno; struct { char *msg; } e_pkg_error; struct { char *msg; } e_pkg_notice; struct { int total; int done; } e_upd_add; struct { int total; int done; } e_upd_remove; struct { const char *url; } e_fetching; struct { struct pkg *pkg; } e_already_installed; struct { struct pkg *pkg; } e_install_begin; struct { struct pkg *pkg; struct pkg *old; } e_install_finished; struct { struct pkg *pkg; } e_deinstall_begin; struct { struct pkg *pkg; } e_deinstall_finished; struct { struct pkg *n; struct pkg *o; } e_upgrade_begin; struct { struct pkg *n; struct pkg *o; } e_upgrade_finished; struct { struct pkg *pkg; } e_extract_begin; struct { struct pkg *pkg; } e_extract_finished; struct { struct pkg *pkg; } e_delete_files_begin; struct { struct pkg *pkg; } e_delete_files_finished; struct { struct pkg *pkg; } e_add_deps_begin; struct { struct pkg *pkg; } e_add_deps_finished; struct { struct pkg *pkg; struct pkg_dep *dep; } e_missing_dep; struct { struct pkg *pkg; } e_locked; struct { struct pkg *pkg; int force; } e_required; struct { const char *repo; } e_remotedb; struct { struct pkg *pkg; struct pkg_file *file; const char *newsum; } e_file_mismatch; struct { struct pkg_plugin *plugin; char *msg; } e_plugin_info; struct { struct pkg_plugin *plugin; const char *func; const char *arg; int no; } e_plugin_errno; struct { struct pkg_plugin *plugin; char *msg; } e_plugin_error; struct { const char *pkg_name; } e_not_found; struct { const char *pkg_uid; const char *pkg_path; struct pkg_event_conflict *conflicts; } e_integrity_conflict; struct { int conflicting; } e_integrity_finished; struct { const char *reponame; int processed; } e_incremental_update; struct { int level; char *msg; } e_debug; struct { const char *msg; int deft; } e_query_yesno; struct { const char *msg; const char **items; int ncnt; int deft; } e_query_select; struct { pkg_sandbox_cb call; int fd; void *userdata; } e_sandbox_call; struct { pkg_sandbox_cb call; void *userdata; char **result; int64_t *len; } e_sandbox_call_str; struct { char *msg; } e_progress_start; struct { int64_t current; int64_t total; } e_progress_tick; struct { const char *msg; } e_pkg_message; struct { struct pkg *pkg; struct pkg_file *file; } e_file_missing; struct { void *data; void (*cleanup_cb)(void *data); } e_cleanup_callback; struct { struct pkg *p1; struct pkg *p2; const char *path; } e_conflicts; struct { const char *name; bool cleanup; } e_trigger; }; }; /** * Event callback mechanism. Events will be reported using this callback, * providing an event identifier and up to two event-specific pointers. */ typedef int(*pkg_event_cb)(void *, struct pkg_event *); void pkg_event_register(pkg_event_cb cb, void *data); bool pkg_compiled_for_same_os_major(void); int pkg_ini(const char *, const char *, pkg_init_flags); int pkg_init(const char *, const char *); int pkg_initialized(void); void pkg_shutdown(void); int pkg_test_filesum(struct pkg *); int pkg_recompute(struct pkgdb *, struct pkg *); int pkgdb_reanalyse_shlibs(struct pkgdb *, struct pkg *); void pkgdb_cmd(int argc, char **argv); int pkg_sshserve(int fd); int pkg_repos_total_count(void); int pkg_repos_activated_count(void); int pkg_repos(struct pkg_repo **); const char *pkg_repo_url(struct pkg_repo *r); const char *pkg_repo_name(struct pkg_repo *r); const char *pkg_repo_key(struct pkg_repo *r); const char *pkg_repo_fingerprints(struct pkg_repo *r); signature_t pkg_repo_signature_type(struct pkg_repo *r); bool pkg_repo_enabled(struct pkg_repo *r); mirror_t pkg_repo_mirror_type(struct pkg_repo *r); unsigned pkg_repo_priority(struct pkg_repo *r); unsigned pkg_repo_ip_version(struct pkg_repo *r); struct pkg_repo *pkg_repo_find(const char *name); int pkg_repo_fetch_remote_tmp(struct pkg_repo *repo, const char *filename, const char *extension, time_t *t, int *rc, bool silent); /** * pkg_printf() and friends. These parallel the similarly named libc * functions printf(), fprintf() etc. */ /** * print to stdout data from pkg as indicated by the format code format * @param ... Varargs list of struct pkg etc. supplying the data * @param format String with embedded %-escapes indicating what to print * @return count of the number of characters printed */ int pkg_printf(const char * restrict format, ...); /** * print to stdout data from pkg as indicated by the format code format * @param ap Varargs list of struct pkg etc. supplying the data * @param format String with embedded %-escapes indicating what to print * @return count of the number of characters printed */ int pkg_vprintf(const char * restrict format, va_list ap); /** * print to named stream from pkg as indicated by the format code format * @param ... Varargs list of struct pkg etc. supplying the data * @param format String with embedded %-escapes indicating what to output * @return count of the number of characters printed */ int pkg_fprintf(FILE * restrict stream, const char * restrict format, ...); /** * print to named stream from pkg as indicated by the format code format * @param ap varargs arglist * @param format String with embedded %-escapes indicating what to output * @return count of the number of characters printed */ int pkg_vfprintf(FILE * restrict stream, const char * restrict format, va_list ap); /** * print to file descriptor fd data from pkg as indicated by the format * code format * @param fd Previously opened file descriptor to print to * @param ... Varargs list of struct pkg etc. supplying the data * @param format String with embedded %-escapes indicating what to print * @return count of the number of characters printed */ int pkg_dprintf(int fd, const char * restrict format, ...); /** * print to file descriptor fd data from pkg as indicated by the format * code format * @param fd Previously opened file descriptor to print to * @param ap Varargs list of struct pkg etc. supplying the data * @param format String with embedded %-escapes indicating what to print * @return count of the number of characters printed */ int pkg_vdprintf(int fd, const char * restrict format, va_list ap); /** * print to buffer str of given size data from pkg as indicated by the * format code format as a NULL-terminated string * @param str Character array buffer to receive output * @param size Length of the buffer str * @param ... Varargs list of struct pkg etc. supplying the data * @param format String with embedded %-escapes indicating what to output * @return count of the number of characters that would have been output * disregarding truncation to fit size */ int pkg_snprintf(char * restrict str, size_t size, const char * restrict format, ...); /** * print to buffer str of given size data from pkg as indicated by the * format code format as a NULL-terminated string * @param str Character array buffer to receive output * @param size Length of the buffer str * @param ap Varargs list of struct pkg etc. supplying the data * @param format String with embedded %-escapes indicating what to output * @return count of the number of characters that would have been output * disregarding truncation to fit size */ int pkg_vsnprintf(char * restrict str, size_t size, const char * restrict format,va_list ap); /** * Allocate a string buffer ret sufficiently big to contain formatted * data data from pkg as indicated by the format code format * @param ret location of pointer to be set to point to buffer containing * result * @param ... Varargs list of struct pkg etc. supplying the data * @param format String with embedded %-escapes indicating what to output * @return count of the number of characters printed */ int pkg_asprintf(char **ret, const char * restrict format, ...); /** * Allocate a string buffer ret sufficiently big to contain formatted * data data from pkg as indicated by the format code format * @param ret location of pointer to be set to point to buffer containing * result * @param ap Varargs list of struct pkg etc. supplying the data * @param format String with embedded %-escapes indicating what to output * @return count of the number of characters printed */ int pkg_vasprintf(char **ret, const char * restrict format, va_list ap); bool pkg_has_message(struct pkg *p); bool pkg_is_locked(const struct pkg * restrict p); /** * Defines how many chars of checksum are there in a package's name * We define this number as sufficient for 24k packages. * To find out probability of collision it is possible to use the following * python function to calculate 'birthday paradox' probability: * def bp(m, n): * power = -(n * n) / (2. * m) * return 1. - exp(power) * * For our choice of 2^40 (or 10 hex characters) it is: * >>> bp(float(2 ** 40), 24500.) * 0.00027292484660568217 * * And it is negligible probability */ #define PKG_FILE_CKSUM_CHARS 10 char *pkg_utils_tokenize(char **); int pkg_utils_count_spaces(const char *); int pkg_mkdirs(const char *path); bool pkg_copy_file(int from, int to); int pkg_add_port(struct pkgdb *db, struct pkg *pkg, const char *root, \ const char *locationn, bool testing); char *pkg_absolutepath(const char *src, char *dest, size_t dest_len, bool fromroot); void pkg_cache_full_clean(void); const char *pkg_get_cachedir(void); int pkg_get_cachedirfd(void); int pkg_get_dbdirfd(void); int pkg_namecmp(struct pkg *, struct pkg *); #ifndef PKG_FORMAT_ATTRIBUTE #ifdef __GNUC__ #define PKG_FORMAT_ATTRIBUTE(x, y) __attribute__ ((format (printf, (x), (y)))); #else #define PKG_FORMAT_ATTRIBUTE(x, y) #endif #endif void pkg_emit_error(const char *fmt, ...) PKG_FORMAT_ATTRIBUTE(1, 2); void pkg_emit_notice(const char *fmt, ...) PKG_FORMAT_ATTRIBUTE(1, 2); struct pkg_create *pkg_create_new(void); void pkg_create_free(struct pkg_create *); bool pkg_create_set_format(struct pkg_create *, const char *); void pkg_create_set_compression_level(struct pkg_create *, int); void pkg_create_set_overwrite(struct pkg_create *, bool); void pkg_create_set_rootdir(struct pkg_create *, const char *); void pkg_create_set_output_dir(struct pkg_create *, const char *); void pkg_create_set_timestamp(struct pkg_create *, time_t); void pkg_create_set_expand_manifest(struct pkg_create *, bool); int pkg_create(struct pkg_create *, const char *, const char *, bool); int pkg_create_i(struct pkg_create *, struct pkg *, bool); /* deprecated */ int pkg_create_from_manifest(const char *, pkg_formats, const char *, const char *, const char *) __attribute__((deprecated)); int pkg_create_staged(const char *, pkg_formats, const char *, const char *, char *, bool) __attribute__((deprecated)); int pkg_create_installed(const char *, pkg_formats, struct pkg *) __attribute__((deprecated)); int pkgdb_register_ports(struct pkgdb *db, struct pkg *pkg) __attribute__((deprecated));; int pkg_execute_deferred_triggers(void); int pkg_add_triggers(void); struct pkg_kvlist_iterator *pkg_kvlist_iterator(struct pkg_kvlist *l); struct pkg_kv *pkg_kvlist_next(struct pkg_kvlist_iterator *it); struct pkg_stringlist_iterator *pkg_stringlist_iterator(struct pkg_stringlist *l); const char *pkg_stringlist_next(struct pkg_stringlist_iterator *it); struct pkg_el *pkg_get_element(struct pkg *p, pkg_attr a); static inline void pkg_get_s(struct pkg *p, pkg_attr a, const char **val) { struct pkg_el *e = pkg_get_element(p, a); *val = NULL; switch (e->type) { case PKG_STR: *val = e->string; break; case PKG_BOOLEAN: *val = e->boolean ? "true" : "false"; break; case PKG_INTEGER: break; case PKG_KVLIST: free(e->stringlist); case PKG_STRINGLIST: free(e->kvlist); break; } free(e); }; static inline void pkg_get_i(struct pkg *p, pkg_attr a, int64_t *val) { struct pkg_el *e = pkg_get_element(p, a); int64_t ret = -1; switch (e->type) { case PKG_STR: ret = e->string != NULL; break; case PKG_BOOLEAN: ret = e->boolean; break; case PKG_INTEGER: ret = e->integer; break; case PKG_KVLIST: free(e->stringlist); case PKG_STRINGLIST: free(e->kvlist); break; } free(e); *val = ret; }; static inline void pkg_get_b(struct pkg *p, pkg_attr a, bool *val) { struct pkg_el *e = pkg_get_element(p, a); bool ret = false; switch (e->type) { case PKG_STR: ret = e->string != NULL; break; case PKG_BOOLEAN: ret = e->boolean; break; case PKG_INTEGER: ret = e->integer > 0; break; case PKG_KVLIST: free(e->stringlist); case PKG_STRINGLIST: free(e->kvlist); break; } free(e); *val = ret; }; static inline void pkg_get_kv(struct pkg *p, pkg_attr a, struct pkg_kvlist **val) { struct pkg_el *e = pkg_get_element(p, a); struct pkg_kvlist *kv = NULL; if (e->type == PKG_KVLIST) kv = e->kvlist; free(e); *val = kv; } static inline void pkg_get_sl(struct pkg *p, pkg_attr a, struct pkg_stringlist **val) { struct pkg_el *e = pkg_get_element(p, a); struct pkg_stringlist *sl = NULL; if (e->type == PKG_STRINGLIST) sl = e->stringlist; free(e); *val = sl; } static inline void pkg_get_invalid(struct pkg *p __attribute__((__unused__)), pkg_attr a __attribute__((__unused__)), void *v __attribute__((__unused__))) { fprintf(stderr, "invalid attribute type for pkg_get\n"); abort(); } int pkg_set_s(struct pkg *pkg, pkg_attr a, const char *val); int pkg_set_i(struct pkg *pkg, pkg_attr a, int64_t i); int pkg_set_b(struct pkg *pkg, pkg_attr a, bool b); static inline int pkg_set_invalid(struct pkg *p __attribute__((__unused__)), pkg_attr a __attribute__((__unused__)), void *v __attribute__((__unused__))) { fprintf(stderr, "Invalid attribute type for pkg_set\n"); abort(); } #define pkg_get(p, t, a) _Generic((a), \ const char **: pkg_get_s, \ int64_t *: pkg_get_i, \ bool *: pkg_get_b, \ struct pkg_kvlist **: pkg_get_kv, \ struct pkg_stringlist **: pkg_get_sl, \ default: pkg_get_invalid)(p, t, a) #define pkg_set(p, t, a) _Generic((a), \ const char *: pkg_set_s, \ char *: pkg_set_s, \ int64_t: pkg_set_i, \ bool: pkg_set_b, \ default: pkg_set_invalid)(p, t, a) #ifdef __cplusplus } #endif #endif