Improved callback/states support to make libxbps std{err,out} printf free.

This is a major API/ABI change, documentation has been updated accordingly.
This commit is contained in:
Juan RP
2011-11-24 11:23:08 +01:00
parent 4ed6b5ed2c
commit 3ccfec7054
29 changed files with 910 additions and 726 deletions

View File

@@ -49,7 +49,7 @@ OBJS += transaction_dictionary.o transaction_sortdeps.o download.o
OBJS += plist.o plist_archive_entry.o plist_find.o plist_match.o
OBJS += plist_remove.o plist_fetch.o util.o util_hash.o
OBJS += initend.o regpkgdb_dictionary.o init_virtualpkgs.o
OBJS += repository_findpkg.o repository_finddeps.o
OBJS += repository_findpkg.o repository_finddeps.o cb_util.o
OBJS += repository_pool.o repository_pool_find.o repository_sync_index.o
OBJS += $(EXTOBJS) $(COMPAT_SRCS)

140
lib/cb_util.c Normal file
View File

@@ -0,0 +1,140 @@
/*-
* Copyright (c) 2011 Juan Romero Pardines.
* 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.
* 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 ``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 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.
*/
#ifdef HAVE_VASPRINTF
# define _GNU_SOURCE /* for vasprintf(3) */
#endif
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xbps_api_impl.h"
void HIDDEN
xbps_set_cb_fetch(off_t file_size,
off_t file_offset,
off_t file_dloaded,
const char *file_name,
bool cb_start,
bool cb_update,
bool cb_end)
{
const struct xbps_handle *xhp = xbps_handle_get();
struct xbps_fetch_cb_data *xfcd;
if (xhp->fetch_cb == NULL)
return;
xfcd = malloc(sizeof(*xfcd));
if (xfcd == NULL)
return;
xfcd->file_size = file_size;
xfcd->file_offset = file_offset;
xfcd->file_dloaded = file_dloaded;
xfcd->file_name = file_name;
xfcd->cb_start = cb_start;
xfcd->cb_update = cb_update;
xfcd->cb_end = cb_end;
(*xhp->fetch_cb)(xfcd, xhp->fetch_cb_data);
free(xfcd);
}
void HIDDEN
xbps_set_cb_state(xbps_state_t state,
int err,
const char *pkgname,
const char *version,
const char *fmt,
...)
{
struct xbps_state_cb_data *xscd;
const struct xbps_handle *xhp = xbps_handle_get();
char *buf = NULL;
va_list va;
int retval;
if (xhp->state_cb == NULL)
return;
xscd = malloc(sizeof(*xscd));
if (xscd == NULL)
return;
xscd->state = state;
xscd->err = err;
xscd->pkgname = pkgname;
xscd->version = version;
if (fmt != NULL) {
va_start(va, fmt);
retval = vasprintf(&buf, fmt, va);
va_end(va);
if (retval == -1)
xscd->desc = NULL;
else
xscd->desc = buf;
}
(*xhp->state_cb)(xscd, xhp->fetch_cb_data);
if (buf != NULL)
free(buf);
free(xscd);
}
void HIDDEN
xbps_set_cb_unpack(const char *entry,
int64_t entry_size,
ssize_t entry_extract_count,
ssize_t entry_total_count,
bool entry_is_metadata,
bool entry_is_conf)
{
const struct xbps_handle *xhp = xbps_handle_get();
struct xbps_unpack_cb_data *xucd;
if (xhp->unpack_cb == NULL)
return;
xucd = malloc(sizeof(*xucd));
if (xucd == NULL)
return;
xucd->entry = entry;
xucd->entry_size = entry_size;
xucd->entry_extract_count = entry_extract_count;
xucd->entry_total_count = entry_total_count;
xucd->entry_is_metadata = entry_is_metadata;
xucd->entry_is_conf = entry_is_conf;
(*xhp->unpack_cb)(xucd, xhp->unpack_cb_data);
free(xucd);
}

View File

@@ -1,50 +1,81 @@
/* $NetBSD: asprintf.c,v 1.2 2007/07/20 00:10:06 tnn Exp $ */
/*-
* Copyright (c) 2008-2011 Juan Romero Pardines.
* Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.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.
* 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.
* 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 ``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 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.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``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
* COPYRIGHT HOLDERS OR CONTRIBUTORS 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.
*/
char *
xbps_xasprintf(const char *fmt, ...)
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
int
vasprintf(char **ret, const char *fmt, va_list ap)
{
va_list ap, aq;
char *buf, *new_buf;
size_t len;
int res;
char *buf;
int retval;
va_start(aq, fmt);
va_copy(ap, aq);
len = vsnprintf(NULL, 0, fmt, aq) + 1;
if ((buf = malloc(len)) == NULL) {
va_end(ap);
return NULL;
len = 128;
buf = malloc(len);
if (buf == NULL) {
*ret = NULL;
return -1;
}
va_start(ap, fmt);
res = vsnprintf(buf, len, fmt, ap);
if (res < 0 || res >= (int)len) {
retval = vsnprintf(buf, len, fmt, ap);
if (retval < 0) {
free(buf);
return NULL;
*ret = NULL;
return -1;
}
return buf;
if (retval < len) {
new_buf = realloc(buf, retval + 1);
if (new_buf == NULL)
*ret = buf;
else
*ret = new_buf;
return retval;
}
len = (size_t)retval + 1;
free(buf);
buf = malloc(len);
if (buf == NULL) {
*ret = NULL;
return -1;
}
retval = vsnprintf(buf, len, fmt, ap);
if (retval != len - 1) {
free(buf);
*ret = NULL;
return -1;
}
*ret = buf;
return retval;
}

View File

@@ -231,7 +231,7 @@ xbps_fetch_file(const char *uri,
goto out;
}
if (url_st.size == -1) {
xbps_error_printf("Remote file size is unknown!\n");
xbps_dbg_printf("Remote file size is unknown!\n");
errno = EINVAL;
rv = -1;
goto out;
@@ -240,7 +240,7 @@ xbps_fetch_file(const char *uri,
* Remove local file if bigger than remote, and refetch the
* whole shit again.
*/
xbps_warn_printf("Local file %s is greater than remote, "
xbps_dbg_printf("Local file %s is greater than remote, "
"removing local file and refetching...\n", filename);
(void)remove(destfile);
} else if (restart && url_st.mtime && url_st.size &&
@@ -260,29 +260,20 @@ xbps_fetch_file(const char *uri,
rv = -1;
goto out;
}
/*
* Initialize data for the fetch progress function callback
* and let the user know that the transfer is going to start
* immediately.
*/
if (xhp != NULL && xhp->xbps_fetch_cb != NULL && xhp->xfcd != NULL) {
xhp->xfcd->file_name = filename;
xhp->xfcd->file_size = url_st.size;
xhp->xfcd->file_offset = url->offset;
xhp->xfcd->file_dloaded = -1;
xhp->xfcd->cb_start = true;
xhp->xfcd->cb_update = false;
xhp->xfcd->cb_end = false;
xhp->xbps_fetch_cb(xhp->xfcd);
}
xbps_set_cb_fetch(url_st.size, url->offset, -1,
filename, true, false, false);
/*
* Start fetching requested file.
*/
while ((bytes_read = fetchIO_read(fio, buf, sizeof(buf))) > 0) {
bytes_written = write(fd, buf, (size_t)bytes_read);
if (bytes_written != bytes_read) {
xbps_error_printf("Couldn't write to %s!\n", destfile);
xbps_dbg_printf("Couldn't write to %s!\n", destfile);
rv = -1;
goto out;
}
@@ -291,26 +282,11 @@ xbps_fetch_file(const char *uri,
* Let the fetch progress callback know that
* we are sucking more bytes from it.
*/
if (xhp != NULL && xhp->xbps_fetch_cb != NULL &&
xhp->xfcd != NULL) {
xhp->xfcd->file_dloaded = bytes_dload;
xhp->xfcd->cb_start = false;
xhp->xfcd->cb_update = true;
xhp->xbps_fetch_cb(xhp->xfcd);
}
}
/*
* Let the fetch progress callback know that the file
* has been fetched.
*/
if (xhp != NULL && xhp->xbps_fetch_cb != NULL && xhp->xfcd != NULL) {
xhp->xfcd->cb_update = false;
xhp->xfcd->cb_end = true;
xhp->xbps_fetch_cb(xhp->xfcd);
xbps_set_cb_fetch(url_st.size, url->offset, bytes_dload,
filename, false, true, false);
}
if (bytes_read == -1) {
xbps_error_printf("IO error while fetching %s: %s\n", filename,
xbps_dbg_printf("IO error while fetching %s: %s\n", filename,
fetchLastErrString);
errno = EIO;
rv = -1;
@@ -320,6 +296,12 @@ xbps_fetch_file(const char *uri,
rv = -1;
goto out;
}
/*
* Let the fetch progress callback know that the file
* has been fetched.
*/
xbps_set_cb_fetch(url_st.size, url->offset, bytes_dload,
filename, false, false, true);
/*
* Update mtime in local file to match remote file if transfer
* was successful.
@@ -331,7 +313,6 @@ xbps_fetch_file(const char *uri,
rv = -1;
goto out;
}
/* File downloaded successfully */
rv = 1;

View File

@@ -203,12 +203,6 @@ xbps_end(struct xbps_handle *xh)
prop_object_release(xh->cachedir);
if (prop_object_type(xh->virtualpkgs_array) == PROP_TYPE_ARRAY)
prop_object_release(xh->virtualpkgs_array);
if (xh->xfcd != NULL)
free(xh->xfcd);
if (xh->xucd != NULL)
free(xh->xucd);
if (xh->xscd != NULL)
free(xh->xscd);
free(xh);
xh = NULL;
@@ -225,31 +219,7 @@ xbps_handle_get(void)
struct xbps_handle *
xbps_handle_alloc(void)
{
struct xbps_handle *xh;
xh = malloc(sizeof *xh);
if (xh == NULL)
return NULL;
xh->xscd = malloc(sizeof *xh->xscd);
if (xh->xscd == NULL) {
free(xh);
return NULL;
}
xh->xucd = malloc(sizeof *xh->xucd);
if (xh->xucd == NULL) {
free(xh->xscd);
free(xh);
return NULL;
}
xh->xfcd = malloc(sizeof *xh->xfcd);
if (xh->xfcd == NULL) {
free(xh->xucd);
free(xh->xscd);
free(xh);
return NULL;
}
return xh;
return malloc(sizeof(struct xbps_handle));
}
static void
@@ -306,13 +276,3 @@ xbps_warn_printf(const char *fmt, ...)
common_printf(stderr, "WARNING: ", fmt, ap);
va_end(ap);
}
void
xbps_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
common_printf(stdout, NULL, fmt, ap);
va_end(ap);
}

View File

@@ -179,7 +179,6 @@ xbps_entry_install_conf_file(prop_dictionary_t filesd,
break;
}
}
/*
* Orig = X, Curr = X, New = X
*
@@ -200,38 +199,39 @@ xbps_entry_install_conf_file(prop_dictionary_t filesd,
} else if ((strcmp(sha256_orig, sha256_cur) == 0) &&
(strcmp(sha256_orig, sha256_new)) &&
(strcmp(sha256_cur, sha256_new))) {
xbps_printf("Updating configuration file `%s' "
"with new version.\n", cffile);
xbps_set_cb_state(XBPS_STATE_CONFIG_FILE,
0, pkgname, version,
"Updating configuration file `%s' provided "
"by version `%s'.", cffile, version);
rv = 1;
break;
/*
* Orig = X, Curr = Y, New = X
*
* Keep current file as is.
*/
} else if ((strcmp(sha256_orig, sha256_new) == 0) &&
(strcmp(sha256_cur, sha256_new)) &&
(strcmp(sha256_orig, sha256_cur))) {
xbps_printf("Keeping modified configuration file "
"`%s'.\n", cffile);
xbps_set_cb_state(XBPS_STATE_CONFIG_FILE,
0, pkgname, version,
"Keeping modified configuration file `%s'.",
cffile);
rv = 0;
break;
/*
* Orig = X, Curr = Y, New = Y
*
* Install new file.
* Keep current file as is.
*/
} else if ((strcmp(sha256_cur, sha256_new) == 0) &&
(strcmp(sha256_orig, sha256_new)) &&
(strcmp(sha256_orig, sha256_cur))) {
xbps_dbg_printf("%s: conf_file %s orig = X,"
"cur = Y, new = Y\n", pkgname, entry_pname);
rv = 1;
rv = 0;
break;
/*
* Orig = X, Curr = Y, New = Z
*
* Install new file as file.new-<pkg_version>
* Install new file as <file>.new-<version>
*/
} else if ((strcmp(sha256_orig, sha256_cur)) &&
(strcmp(sha256_cur, sha256_new)) &&
@@ -242,10 +242,10 @@ xbps_entry_install_conf_file(prop_dictionary_t filesd,
rv = -1;
break;
}
xbps_printf("Keeping modified configuration file "
"`%s'.\n", cffile);
xbps_printf("Installing new configuration file as "
"`%s.new-%s'\n", cffile, version);
xbps_set_cb_state(XBPS_STATE_CONFIG_FILE,
0, pkgname, version,
"Installing new configuration file to "
"`%s.new-%s'.", cffile, version);
archive_entry_set_pathname(entry, buf);
free(buf);
rv = 1;

View File

@@ -120,15 +120,8 @@ xbps_configure_pkg(const char *pkgname,
if (pkgver == NULL)
return ENOMEM;
if (xhp->xbps_state_cb) {
xhp->xscd->desc = NULL;
xhp->xscd->binpkg_fname = NULL;
xhp->xscd->repourl = NULL;
xhp->xscd->err = 0;
xhp->xscd->state = XBPS_STATE_CONFIGURE;
xhp->xscd->pkgver = pkgver;
xhp->xbps_state_cb(xhp->xscd);
}
xbps_set_cb_state(XBPS_STATE_CONFIGURE, 0, pkgname, lver,
"Configuring package `%s' ...", pkgver);
buf = xbps_xasprintf(".%s/metadata/%s/INSTALL",
XBPS_META_PATH, pkgname);
@@ -138,8 +131,10 @@ xbps_configure_pkg(const char *pkgname,
}
if (chdir(prop_string_cstring_nocopy(xhp->rootdir)) == -1) {
xbps_dbg_printf("%s: [configure] chdir to '%s' returned %s\n",
pkgname, prop_string_cstring_nocopy(xhp->rootdir),
xbps_set_cb_state(XBPS_STATE_CONFIGURE_FAIL, errno,
pkgname, lver,
"%s: [configure] failed to chdir to rootdir `%s': %s",
pkgver, prop_string_cstring_nocopy(xhp->rootdir),
strerror(errno));
free(buf);
free(pkgver);
@@ -149,10 +144,12 @@ xbps_configure_pkg(const char *pkgname,
if (access(buf, X_OK) == 0) {
if (xbps_file_exec(buf, "post",
pkgname, lver, update ? "yes" : "no", NULL) != 0) {
xbps_set_cb_state(XBPS_STATE_CONFIGURE_FAIL, errno,
pkgname, lver,
"%s: [configure] INSTALL script failed to execute "
"the post ACTION: %s", pkgver, strerror(errno));
free(buf);
free(pkgver);
xbps_error_printf("%s: post install script error: %s\n",
pkgname, strerror(errno));
return errno;
}
} else {
@@ -165,14 +162,13 @@ xbps_configure_pkg(const char *pkgname,
free(buf);
rv = xbps_set_pkg_state_installed(pkgname, lver, pkgver,
XBPS_PKG_STATE_INSTALLED);
free(pkgver);
if (rv != 0 && xhp->xbps_state_cb) {
xhp->xscd->pkgver = pkgver;
xhp->xscd->err = rv;
xhp->xscd->state = XBPS_STATE_CONFIGURE_FAIL;
xhp->xbps_state_cb(xhp->xscd);
if (rv != 0) {
xbps_set_cb_state(XBPS_STATE_CONFIGURE_FAIL, rv,
pkgname, lver,
"%s: [configure] failed to set state to installed: %s",
pkgver, strerror(rv));
}
free(pkgver);
return rv;
}

View File

@@ -47,7 +47,10 @@
*/
static int
remove_pkg_metadata(const char *pkgname, const char *rootdir)
remove_pkg_metadata(const char *pkgname,
const char *version,
const char *pkgver,
const char *rootdir)
{
struct dirent *dp;
DIR *dirp;
@@ -80,10 +83,12 @@ remove_pkg_metadata(const char *pkgname, const char *rootdir)
return ENOMEM;
}
if (unlink(path) == -1)
xbps_warn_printf("can't remove metadata file: "
"`%s': %s\n", dp->d_name, strerror(errno));
if (unlink(path) == -1) {
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
errno, pkgname, version,
"%s: [purge] failed to remove metafile `%s': %s",
pkgver, path, strerror(errno));
}
free(path);
}
(void)closedir(dirp);
@@ -121,13 +126,14 @@ xbps_purge_pkg(const char *pkgname, bool check_state)
{
struct xbps_handle *xhp;
prop_dictionary_t dict, pkgd;
const char *version;
const char *version, *pkgver;
char *buf;
int rv = 0;
pkg_state_t state;
assert(pkgname != NULL);
xhp = xbps_handle_get();
/*
* Firstly let's get the pkg dictionary from regpkgdb.
*/
@@ -138,6 +144,10 @@ xbps_purge_pkg(const char *pkgname, bool check_state)
pkgname, strerror(errno));
return errno;
}
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(pkgd, "version", &version);
xbps_set_cb_state(XBPS_STATE_PURGE, 0, pkgname, version,
"Purging package `%s'...", pkgver);
if (check_state) {
/*
@@ -156,16 +166,24 @@ xbps_purge_pkg(const char *pkgname, bool check_state)
*/
dict = xbps_dictionary_from_metadata_plist(pkgname, XBPS_PKGFILES);
if (dict == NULL) {
xbps_dbg_printf("[purge] %s: failed to read files.plist (%s)\n",
pkgname, strerror(errno));
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
errno, pkgname, version,
"%s: [purge] failed to read metafile `%s': %s",
pkgver, XBPS_PKGFILES, strerror(errno));
if (errno != ENOENT)
return errno;
} else {
if (prop_dictionary_get(dict, "conf_files")) {
rv = xbps_remove_pkg_files(dict, "conf_files");
rv = xbps_remove_pkg_files(dict, "conf_files", pkgver);
prop_object_release(dict);
if (rv != 0)
if (rv != 0) {
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
rv, pkgname, version,
"%s: [purge] failed to remove "
"configuration files: %s",
pkgver, strerror(rv));
return rv;
}
}
}
/*
@@ -173,8 +191,11 @@ xbps_purge_pkg(const char *pkgname, bool check_state)
*/
if (chdir(prop_string_cstring_nocopy(xhp->rootdir)) == -1) {
rv = errno;
xbps_error_printf("[purge] %s: cannot change to rootdir "
"(%s)\n", pkgname, strerror(rv));
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
rv, pkgname, version,
"%s: [purge] failed to chdir to rootdir `%s': %s",
pkgver, prop_string_cstring_nocopy(xhp->rootdir),
strerror(rv));
return rv;
}
buf = xbps_xasprintf(".%s/metadata/%s/REMOVE", XBPS_META_PATH, pkgname);
@@ -183,16 +204,15 @@ xbps_purge_pkg(const char *pkgname, bool check_state)
return rv;
}
if (access(buf, X_OK) == 0) {
prop_dictionary_get_cstring_nocopy(pkgd, "version", &version);
if (xbps_file_exec(buf, "purge",
pkgname, version, "no", NULL) != 0) {
rv = xbps_file_exec(buf, "purge", pkgname, version, "no", NULL);
if (rv != 0) {
free(buf);
if (errno && errno != ENOENT) {
rv = errno;
xbps_error_printf("%s: purge action error in "
"REMOVE script: %s\n", pkgname,
strerror(errno));
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
errno, pkgname, version,
"%s: [purge] REMOVE script failed to "
"execute purge ACTION: %s",
pkgver, strerror(errno));
return rv;
}
}
@@ -201,20 +221,17 @@ xbps_purge_pkg(const char *pkgname, bool check_state)
/*
* Remove metadata dir and unregister package.
*/
if ((rv = remove_pkg_metadata(pkgname,
if ((rv = remove_pkg_metadata(pkgname, version, pkgver,
prop_string_cstring_nocopy(xhp->rootdir))) != 0) {
xbps_dbg_printf("[purge] %s: failed to remove metadata "
"files (%s)\n", pkgname, strerror(rv));
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
rv, pkgname, version,
"%s: [purge] failed to remove metadata files: %s",
pkgver, strerror(rv));
if (rv != ENOENT)
return rv;
}
if ((rv = xbps_unregister_pkg(pkgname)) != 0) {
xbps_error_printf("%s: couldn't unregister package: %s\n",
pkgname, strerror(rv));
if ((rv = xbps_unregister_pkg(pkgname, version)) != 0)
return rv;
}
if (xhp->flags & XBPS_FLAG_VERBOSE)
xbps_printf("Package %s purged successfully.\n", pkgname);
return rv;
}

View File

@@ -67,6 +67,9 @@ xbps_register_pkg(prop_dictionary_t pkgrd)
provides = prop_dictionary_get(pkgrd, "provides");
reqby = prop_dictionary_get(pkgrd, "requiredby");
xbps_set_cb_state(XBPS_STATE_REGISTER, 0, pkgname, version,
"Registering package `%s'...", pkgver);
assert(pkgname != NULL);
assert(version != NULL);
assert(desc != NULL);
@@ -108,9 +111,6 @@ xbps_register_pkg(prop_dictionary_t pkgrd)
else if (xhp->install_reason_manual)
autoinst = false;
xbps_dbg_printf("%s: autoinst %d reason_auto %d reason_manual %d\n",
pkgver, autoinst, xhp->install_reason_auto, xhp->install_reason_manual);
if (!prop_dictionary_set_bool(pkgd,
"automatic-install", autoinst)) {
prop_object_release(pkgd);
@@ -149,6 +149,12 @@ xbps_register_pkg(prop_dictionary_t pkgrd)
return ENOENT;
}
out:
if (rv != 0) {
xbps_set_cb_state(XBPS_STATE_REGISTER_FAIL,
rv, pkgname, version,
"%s: failed to register package: %s",
pkgver, strerror(rv));
}
prop_object_release(dict);
free(plist);
@@ -156,7 +162,7 @@ out:
}
int
xbps_unregister_pkg(const char *pkgname)
xbps_unregister_pkg(const char *pkgname, const char *version)
{
struct xbps_handle *xhp;
char *plist;
@@ -164,17 +170,28 @@ xbps_unregister_pkg(const char *pkgname)
assert(pkgname != NULL);
xbps_set_cb_state(XBPS_STATE_UNREGISTER, 0, pkgname, version,
"Unregistering package `%s'...", pkgname);
xhp = xbps_handle_get();
plist = xbps_xasprintf("%s/%s/%s",
prop_string_cstring_nocopy(xhp->rootdir),
XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL)
return ENOMEM;
if (!xbps_remove_pkg_dict_from_plist_by_name(pkgname, plist))
if (plist == NULL) {
rv = ENOMEM;
goto out;
}
if (!xbps_remove_pkg_dict_from_plist_by_name(pkgname, plist)) {
rv = errno;
goto out;
}
out:
if (rv != 0) {
xbps_set_cb_state(XBPS_STATE_UNREGISTER_FAIL,
rv, pkgname, version,
"%s: failed to unregister package: %s",
pkgname, strerror(rv));
}
free(plist);
return rv;
}

View File

@@ -71,14 +71,16 @@
*/
int
xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
xbps_remove_pkg_files(prop_dictionary_t dict,
const char *key,
const char *pkgver)
{
struct xbps_handle *xhp;
prop_array_t array;
prop_object_iterator_t iter;
prop_object_t obj;
const char *file, *sha256, *curobj = NULL;
char *path = NULL;
const char *file, *sha256, *version, *curobj = NULL;
char *path = NULL, *pkgname = NULL;
int rv = 0;
assert(prop_object_type(dict) == PROP_TYPE_DICTIONARY);
@@ -104,6 +106,9 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
else if (strcmp(key, "dirs") == 0)
curobj = "directory";
pkgname = xbps_pkg_name(pkgver);
version = xbps_pkg_version(pkgver);
while ((obj = prop_object_iterator_next(iter))) {
prop_dictionary_get_cstring_nocopy(obj, "file", &file);
path = xbps_xasprintf("%s/%s",
@@ -123,28 +128,41 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
"sha256", &sha256);
rv = xbps_file_hash_check(path, sha256);
if (rv == ENOENT) {
xbps_warn_printf("'%s' doesn't exist!\n", file);
/* missing file, ignore it */
xbps_set_cb_state(
XBPS_STATE_REMOVE_FILE_HASH_FAIL,
rv, pkgname, version,
"%s: failed to check hash for %s `%s': %s",
pkgver, curobj, file, strerror(rv));
free(path);
rv = 0;
continue;
} else if (rv == ERANGE) {
rv = 0;
if (xhp->flags & XBPS_FLAG_FORCE) {
xbps_warn_printf("'%s': SHA256 "
"mismatch, forcing removal...\n",
file);
} else {
xbps_warn_printf("'%s': SHA256 "
"mismatch, preserving file...\n",
file);
}
if ((xhp->flags & XBPS_FLAG_FORCE) == 0) {
xbps_set_cb_state(
XBPS_STATE_REMOVE_FILE_HASH_FAIL,
0, pkgname, version,
"%s: %s `%s' SHA256 mismatch, "
"preserving file", pkgver,
curobj, file);
free(path);
continue;
} else {
xbps_set_cb_state(
XBPS_STATE_REMOVE_FILE_HASH_FAIL,
0, pkgname, version,
"%s: %s `%s' SHA256 mismatch, "
"forcing removal", pkgver,
curobj, file);
}
} else if (rv != 0 && rv != ERANGE) {
xbps_error_printf("failed to check hash for "
"`%s': %s\n", file, strerror(rv));
xbps_set_cb_state(
XBPS_STATE_REMOVE_FILE_HASH_FAIL,
rv, pkgname, version,
"%s: [remove] failed to check hash for "
"%s `%s': %s", pkgver, curobj, file,
strerror(rv));
free(path);
break;
}
@@ -153,19 +171,21 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
* Remove the object if possible.
*/
if (remove(path) == -1) {
if (errno != EEXIST &&
errno != ENOTEMPTY &&
errno != EBUSY)
xbps_warn_printf("can't remove %s `%s': %s\n",
curobj, file, strerror(errno));
xbps_set_cb_state(XBPS_STATE_REMOVE_FILE_FAIL,
errno, pkgname, version,
"%s: failed to remove %s `%s': %s", pkgver,
curobj, file, strerror(errno));
} else {
/* Success */
if (xhp->flags & XBPS_FLAG_VERBOSE)
xbps_printf("Removed %s: `%s'\n", curobj, file);
/* success */
xbps_set_cb_state(XBPS_STATE_REMOVE_FILE,
0, pkgname, version,
"Removed %s `%s'", curobj, file);
}
free(path);
}
prop_object_iterator_release(iter);
if (pkgname)
free(pkgname);
return rv;
}
@@ -175,8 +195,7 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
{
struct xbps_handle *xhp;
prop_dictionary_t dict;
const char *pkgver;
char *buf;
char *buf, *pkgver;
int rv = 0;
bool rmfile_exists = false;
@@ -190,14 +209,31 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
if (!xbps_check_is_installed_pkg_by_name(pkgname))
return ENOENT;
buf = xbps_xasprintf(".%s/metadata/%s/REMOVE",
XBPS_META_PATH, pkgname);
if (buf == NULL)
pkgver = xbps_xasprintf("%s-%s", pkgname, version);
if (pkgver == NULL)
return ENOMEM;
xbps_set_cb_state(XBPS_STATE_REMOVE, 0, pkgname, version,
"Removing package `%s'...", pkgver);
buf = xbps_xasprintf(".%s/metadata/%s/REMOVE",
XBPS_META_PATH, pkgname);
if (buf == NULL) {
rv = ENOMEM;
free(pkgver);
return rv;
}
if (chdir(prop_string_cstring_nocopy(xhp->rootdir)) == -1) {
rv = errno;
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
rv, pkgname, version,
"%s: [remove] failed to chdir to rootdir `%s': %s",
pkgver, prop_string_cstring_nocopy(xhp->rootdir),
strerror(rv));
free(buf);
return EINVAL;
free(pkgver);
return rv;
}
/*
@@ -207,13 +243,18 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
rmfile_exists = true;
if (xbps_file_exec(buf, "pre", pkgname, version,
update ? "yes" : "no", NULL) != 0) {
xbps_error_printf("%s: pre remove script error: %s\n",
pkgname, strerror(errno));
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
errno, pkgname, version,
"%s: [remove] REMOVE script failed to "
"execute pre ACTION: %s",
pkgver, strerror(errno));
free(pkgver);
free(buf);
return errno;
}
} else {
if (errno != ENOENT) {
free(pkgver);
free(buf);
return errno;
}
@@ -225,6 +266,7 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
* continue. Its files will be overwritten later in unpack phase.
*/
if (update) {
free(pkgver);
free(buf);
return xbps_requiredby_pkg_remove(pkgname);
}
@@ -234,27 +276,30 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
*/
dict = xbps_dictionary_from_metadata_plist(pkgname, XBPS_PKGFILES);
if (dict == NULL) {
free(pkgver);
free(buf);
return errno;
}
prop_dictionary_get_cstring_nocopy(dict, "pkgver", &pkgver);
/* Remove links */
if ((rv = xbps_remove_pkg_files(dict, "links")) != 0) {
if ((rv = xbps_remove_pkg_files(dict, "links", pkgver)) != 0) {
prop_object_release(dict);
free(buf);
free(pkgver);
return rv;
}
/* Remove regular files */
if ((rv = xbps_remove_pkg_files(dict, "files")) != 0) {
if ((rv = xbps_remove_pkg_files(dict, "files", pkgver)) != 0) {
prop_object_release(dict);
free(buf);
free(pkgver);
return rv;
}
/* Remove dirs */
if ((rv = xbps_remove_pkg_files(dict, "dirs")) != 0) {
if ((rv = xbps_remove_pkg_files(dict, "dirs", pkgver)) != 0) {
prop_object_release(dict);
free(buf);
free(pkgver);
return rv;
}
prop_object_release(dict);
@@ -265,9 +310,12 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
*/
if (rmfile_exists &&
(xbps_file_exec(buf, "post", pkgname, version, "no", NULL) != 0)) {
xbps_error_printf("%s: post remove script error: %s\n",
pkgname, strerror(errno));
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
errno, pkgname, version,
"%s: [remove] REMOVE script failed to execute "
"post ACTION: %s", pkgver, strerror(errno));
free(buf);
free(pkgver);
return errno;
}
free(buf);
@@ -275,15 +323,27 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
/*
* Update the requiredby array of all required dependencies.
*/
if ((rv = xbps_requiredby_pkg_remove(pkgname)) != 0)
if ((rv = xbps_requiredby_pkg_remove(pkgname)) != 0) {
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
rv, pkgname, version,
"%s: [remove] failed to remove requiredby entries: %s",
pkgver, strerror(rv));
free(pkgver);
return rv;
}
/*
* Set package state to "config-files".
*/
rv = xbps_set_pkg_state_installed(pkgname, version, pkgver,
XBPS_PKG_STATE_CONFIG_FILES);
if (rv != 0) {
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
rv, pkgname, version,
"%s: [remove] failed to set state to config-files: %s",
pkgver, strerror(rv));
}
free(pkgver);
return rv;
}

View File

@@ -36,7 +36,11 @@
#include "xbps_api_impl.h"
int HIDDEN
xbps_remove_obsoletes(prop_dictionary_t oldd, prop_dictionary_t newd)
xbps_remove_obsoletes(const char *pkgname,
const char *version,
const char *pkgver,
prop_dictionary_t oldd,
prop_dictionary_t newd)
{
prop_object_iterator_t iter, iter2;
prop_object_t obj, obj2;
@@ -127,19 +131,16 @@ again:
* Obsolete obj found, remove it.
*/
if (remove(file) == -1) {
if (errno != EEXIST &&
errno != ENOTEMPTY &&
errno != EBUSY) {
xbps_warn_printf("couldn't remove obsole entry "
"`%s': %s\n",
prop_string_cstring_nocopy(oldstr),
strerror(errno));
}
xbps_set_cb_state(XBPS_STATE_REMOVE_FILE_OBSOLETE_FAIL,
errno, pkgname, version,
"%s: failed to remove obsolete entry `%s': %s",
pkgver, file, strerror(errno));
free(file);
continue;
}
xbps_printf("Removed obsolete entry: %s\n",
prop_string_cstring_nocopy(oldstr));
xbps_set_cb_state(XBPS_STATE_REMOVE_FILE_OBSOLETE,
0, pkgname, version,
"Removed obsolete entry: %s", file);
free(file);
}
if (!dolinks) {

View File

@@ -83,18 +83,25 @@ static int
extract_metafile(struct archive *ar,
struct archive_entry *entry,
const char *file,
const char *pkgname,
const char *version,
const char *pkgver,
bool exec,
int flags)
{
char *buf;
const char *version;
char *buf, *pkgname;
int rv;
pkgname = xbps_pkg_name(pkgver);
if (pkgname == NULL)
return ENOMEM;
version = xbps_pkg_version(pkgver);
buf = xbps_xasprintf(".%s/metadata/%s/%s",
XBPS_META_PATH, pkgname, file);
if (buf == NULL)
if (buf == NULL) {
free(pkgname);
return ENOMEM;
}
archive_entry_set_pathname(entry, buf);
free(buf);
@@ -102,86 +109,99 @@ extract_metafile(struct archive *ar,
archive_entry_set_perm(entry, 0750);
if (archive_read_extract(ar, entry, flags) != 0) {
if ((rv = archive_errno(ar)) != EEXIST) {
xbps_error_printf("failed to extract metadata file `%s'"
"for `%s-%s': %s\n", file, pkgname, version,
strerror(rv));
}
rv = archive_errno(ar);
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
rv, pkgname, version,
"%s: [unpack] failed to extract metafile `%s': %s",
pkgver, file, strerror(rv));
free(pkgname);
return rv;
}
free(pkgname);
return 0;
}
static int
remove_metafile(const char *file, const char *pkgname, const char *version)
remove_metafile(const char *file, const char *pkgver)
{
char *buf;
const char *version;
char *buf, *pkgname;
pkgname = xbps_pkg_name(pkgver);
if (pkgname == NULL)
return ENOMEM;
version = xbps_pkg_version(pkgver);
buf = xbps_xasprintf(".%s/metadata/%s/%s",
XBPS_META_PATH, pkgname, file);
if (buf == NULL)
if (buf == NULL) {
free(pkgname);
return ENOMEM;
}
if (unlink(buf) == -1) {
if (errno && errno != ENOENT) {
xbps_error_printf("failed to remove metadata file "
"`%s' while unpacking `%s-%s': %s\n", file,
pkgname, version, strerror(errno));
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
errno, pkgname, version,
"%s: [unpack] failed to remove metafile `%s': %s",
pkgver, file, strerror(errno));
free(pkgname);
free(buf);
return errno;
}
}
free(buf);
free(pkgname);
return 0;
}
/*
* Execute the unpack progress function callback if set and its
* private data is also set. It's so sad that
* archive_read_set_progress_callback() from libarchive(3) cannot be used
* here because sometimes it misses some entries by unknown reasons.
*/
#define RUN_PROGRESS_CB() \
do { \
if (xhp->xbps_unpack_cb != NULL) \
(*xhp->xbps_unpack_cb)(xhp->xucd); \
} while (0)
static int
unpack_archive(prop_dictionary_t pkg_repod,
struct archive *ar,
const char *pkgname,
const char *version,
struct xbps_handle *xhp)
unpack_archive(prop_dictionary_t pkg_repod, struct archive *ar)
{
prop_dictionary_t propsd = NULL, filesd = NULL, old_filesd = NULL;
prop_array_t array;
const struct xbps_handle *xhp = xbps_handle_get();
const struct stat *entry_statp;
struct xbps_unpack_cb_data *xucd = NULL;
struct archive_entry *entry;
size_t nmetadata = 0, entry_idx = 0;
const char *entry_pname, *transact;
const char *entry_pname, *transact, *pkgname, *version, *pkgver, *fname;
char *buf = NULL, *pkgfilesd = NULL;
int rv, flags;
bool preserve, update, replace;
assert(prop_object_type(pkg_repod) == PROP_TYPE_DICTIONARY);
assert(ar != NULL);
assert(pkgname != NULL);
assert(version != NULL);
preserve = update = false;
if (chdir(prop_string_cstring_nocopy(xhp->rootdir)) == -1) {
xbps_error_printf("cannot chdir to rootdir for "
"`%s-%s': %s\n", pkgname, version, strerror(errno));
return errno;
}
prop_dictionary_get_bool(pkg_repod, "preserve", &preserve);
prop_dictionary_get_cstring_nocopy(pkg_repod,
"transaction", &transact);
assert(transact != NULL);
prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(pkg_repod, "version", &version);
prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(pkg_repod, "filename", &fname);
if (xhp->unpack_cb != NULL) {
/* initialize data for unpack cb */
xucd = malloc(sizeof(*xucd));
if (xucd == NULL)
return ENOMEM;
xucd->entry_extract_count = 0;
xucd->entry_total_count = 0;
}
if (chdir(prop_string_cstring_nocopy(xhp->rootdir)) == -1) {
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
errno, pkgname, version,
"%s: [unpack] failed to chdir to rootdir `%s': %s",
pkgver, prop_string_cstring_nocopy(xhp->rootdir),
strerror(errno));
rv = errno;
goto out;
}
if (strcmp(transact, "update") == 0)
update = true;
@@ -192,10 +212,10 @@ unpack_archive(prop_dictionary_t pkg_repod,
* anymore.
*/
if (update) {
if ((rv = remove_metafile("INSTALL", pkgname, version)) != 0)
return rv;
if ((rv = remove_metafile("REMOVE", pkgname, version)) != 0)
return rv;
if ((rv = remove_metafile("INSTALL", pkgver)) != 0)
goto out;
if ((rv = remove_metafile("REMOVE", pkgver)) != 0)
goto out;
}
/*
* Process the archive files.
@@ -214,11 +234,11 @@ unpack_archive(prop_dictionary_t pkg_repod,
/*
* Prepare unpack callback ops.
*/
if (xhp->xbps_unpack_cb != NULL) {
xhp->xucd->entry = entry_pname;
xhp->xucd->entry_size = archive_entry_size(entry);
xhp->xucd->entry_is_metadata = false;
xhp->xucd->entry_is_conf = false;
if (xucd != NULL) {
xucd->entry = entry_pname;
xucd->entry_size = archive_entry_size(entry);
xucd->entry_is_metadata = false;
xucd->entry_is_conf = false;
}
if (strcmp("./INSTALL", entry_pname) == 0) {
/*
@@ -232,7 +252,7 @@ unpack_archive(prop_dictionary_t pkg_repod,
goto out;
}
rv = extract_metafile(ar, entry, "INSTALL",
pkgname, version, true, flags);
pkgver, true, flags);
if (rv != 0) {
free(buf);
goto out;
@@ -241,27 +261,33 @@ unpack_archive(prop_dictionary_t pkg_repod,
pkgname, version, update ? "yes" : "no", NULL);
free(buf);
if (rv != 0) {
xbps_error_printf("%s-%s: pre-install script "
"error: %s\n", pkgname, version,
strerror(rv));
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
rv, pkgname, version,
"%s: [unpack] INSTALL script failed "
"to execute pre ACTION: %s",
pkgver, strerror(rv));
goto out;
}
nmetadata++;
xhp->xucd->entry_is_metadata = true;
xhp->xucd->entry_extract_count++;
RUN_PROGRESS_CB();
if (xucd != NULL) {
xucd->entry_is_metadata = true;
xucd->entry_extract_count++;
(*xhp->unpack_cb)(xucd, xhp->unpack_cb_data);
}
continue;
} else if (strcmp("./REMOVE", entry_pname) == 0) {
rv = extract_metafile(ar, entry, "REMOVE",
pkgname, version, true, flags);
pkgver, true, flags);
if (rv != 0)
goto out;
nmetadata++;
xhp->xucd->entry_is_metadata = true;
xhp->xucd->entry_extract_count++;
RUN_PROGRESS_CB();
if (xucd != NULL) {
xucd->entry_is_metadata = true;
xucd->entry_extract_count++;
(*xhp->unpack_cb)(xucd, xhp->unpack_cb_data);
}
continue;
} else if (strcmp("./files.plist", entry_pname) == 0) {
@@ -276,14 +302,16 @@ unpack_archive(prop_dictionary_t pkg_repod,
goto out;
}
nmetadata++;
xhp->xucd->entry_is_metadata = true;
xhp->xucd->entry_extract_count++;
RUN_PROGRESS_CB();
if (xucd != NULL) {
xucd->entry_is_metadata = true;
xucd->entry_extract_count++;
(*xhp->unpack_cb)(xucd, xhp->unpack_cb_data);
}
continue;
} else if (strcmp("./props.plist", entry_pname) == 0) {
rv = extract_metafile(ar, entry, XBPS_PKGPROPS,
pkgname, version, false, flags);
pkgver, false, flags);
if (rv != 0)
goto out;
@@ -294,9 +322,11 @@ unpack_archive(prop_dictionary_t pkg_repod,
goto out;
}
nmetadata++;
xhp->xucd->entry_is_metadata = true;
xhp->xucd->entry_extract_count++;
RUN_PROGRESS_CB();
if (xucd != NULL) {
xucd->entry_is_metadata = true;
xucd->entry_extract_count++;
(*xhp->unpack_cb)(xucd, xhp->unpack_cb_data);
}
continue;
}
/*
@@ -311,9 +341,12 @@ unpack_archive(prop_dictionary_t pkg_repod,
* This is not an XBPS binary package.
*/
if (entry_idx >= 3) {
xbps_error_printf("invalid binary pkg archive"
"for `%s-%s'\n", pkgname, version);
return ENODEV;
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
ENODEV, pkgname, version,
"%s: [unpack] invalid binary package `%s'.",
pkgver, fname);
rv = ENODEV;
goto out;
}
entry_idx++;
@@ -323,17 +356,18 @@ unpack_archive(prop_dictionary_t pkg_repod,
* Compute total entries in progress data, if set.
* total_entries = metadata + files + conf_files + links.
*/
xhp->xucd->entry_total_count = nmetadata;
array = prop_dictionary_get(filesd, "files");
xhp->xucd->entry_total_count +=
(ssize_t)prop_array_count(array);
array = prop_dictionary_get(filesd, "conf_files");
xhp->xucd->entry_total_count +=
(ssize_t)prop_array_count(array);
array = prop_dictionary_get(filesd, "links");
xhp->xucd->entry_total_count +=
(ssize_t)prop_array_count(array);
if (xucd != NULL) {
xucd->entry_total_count = nmetadata;
array = prop_dictionary_get(filesd, "files");
xucd->entry_total_count +=
(ssize_t)prop_array_count(array);
array = prop_dictionary_get(filesd, "conf_files");
xucd->entry_total_count +=
(ssize_t)prop_array_count(array);
array = prop_dictionary_get(filesd, "links");
xucd->entry_total_count +=
(ssize_t)prop_array_count(array);
}
replace = false;
if (prop_dictionary_get_bool(pkg_repod,
"replacing-package", &replace) && replace) {
@@ -364,8 +398,8 @@ unpack_archive(prop_dictionary_t pkg_repod,
goto out;
} else if (rv == 1) {
/* configuration file */
if (xhp->xucd != NULL)
xhp->xucd->entry_is_conf = true;
if (xucd != NULL)
xucd->entry_is_conf = true;
rv = xbps_entry_install_conf_file(filesd,
entry, entry_pname, pkgname, version);
@@ -411,25 +445,24 @@ unpack_archive(prop_dictionary_t pkg_repod,
*/
if (archive_read_extract(ar, entry, flags) != 0) {
rv = archive_errno(ar);
if (rv != EEXIST) {
xbps_error_printf("failed to extract `%s' "
"from `%s-%s': %s\n", entry_pname,
pkgname, version, strerror(rv));
goto out;
} else {
xbps_warn_printf("ignoring existing "
"entry: %s\n", entry_pname);
}
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
rv, pkgname, version,
"%s: [unpack] failed to extract file `%s': %s",
pkgver, entry_pname, strerror(rv));
}
if (xucd != NULL) {
xucd->entry_extract_count++;
(*xhp->unpack_cb)(xucd, xhp->unpack_cb_data);
}
xhp->xucd->entry_extract_count++;
RUN_PROGRESS_CB();
}
/*
* If there was any error extracting files from archive, error out.
*/
if ((rv = archive_errno(ar)) != 0) {
xbps_dbg_printf("%s-%s: error extracting pkg files: %s\n",
pkgname, version, archive_errno(ar));
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
rv, pkgname, version,
"%s: [unpack] error while extracting files from `%s': %s",
pkgver, fname, strerror(rv));
goto out;
}
/*
@@ -449,7 +482,9 @@ unpack_archive(prop_dictionary_t pkg_repod,
*/
old_filesd = prop_dictionary_internalize_from_zfile(pkgfilesd);
if (prop_object_type(old_filesd) == PROP_TYPE_DICTIONARY) {
if ((rv = xbps_remove_obsoletes(old_filesd, filesd)) != 0) {
rv = xbps_remove_obsoletes(pkgname, version,
pkgver, old_filesd, filesd);
if (rv != 0) {
prop_object_release(old_filesd);
rv = errno;
goto out;
@@ -469,8 +504,10 @@ out1:
goto out;
}
if (xbps_mkpath(buf, 0755) == -1) {
xbps_dbg_printf("%s-%s: failed to create pkg metadir: %s\n",
pkgname, version, strerror(errno));
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
errno, pkgname, version,
"%s: [unpack] failed to create pkg metadir `%s': %s",
buf, pkgver, strerror(errno));
rv = errno;
goto out;
}
@@ -479,12 +516,15 @@ out1:
*/
if (!prop_dictionary_externalize_to_zfile(filesd, pkgfilesd)) {
rv = errno;
xbps_error_printf("failed to extract metadata %s file"
"for `%s-%s': %s\n", XBPS_PKGFILES, pkgname,
version, strerror(rv));
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
errno, pkgname, version,
"%s: [unpack] failed to extract metadata file `%s': %s",
pkgver, XBPS_PKGFILES, strerror(errno));
goto out;
}
out:
if (xucd != NULL)
free(xucd);
if (pkgfilesd != NULL)
free(pkgfilesd);
if (buf != NULL)
@@ -496,12 +536,10 @@ out:
return rv;
}
#undef RUN_PROGRESS_CB
int
xbps_unpack_binary_pkg(prop_dictionary_t pkg_repod)
{
struct xbps_handle *xhp;
struct archive *ar;
const char *pkgname, *version, *repoloc, *pkgver, *fname;
char *bpkg;
@@ -515,10 +553,16 @@ xbps_unpack_binary_pkg(prop_dictionary_t pkg_repod)
prop_dictionary_get_cstring_nocopy(pkg_repod, "repository", &repoloc);
prop_dictionary_get_cstring_nocopy(pkg_repod, "filename", &fname);
xbps_set_cb_state(XBPS_STATE_UNPACK,
0, pkgname, version,
"Unpacking package `%s'...", pkgver);
bpkg = xbps_path_from_repository_uri(pkg_repod, repoloc);
if (bpkg == NULL) {
xbps_error_printf("cannot determine binary pkg file "
"for `%s-%s': %s\n", pkgname, version, strerror(errno));
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
errno, pkgname, version,
"%s: [unpack] cannot determine binary package "
"file for `%s': %s", pkgver, fname, strerror(errno));
return errno;
}
@@ -534,40 +578,43 @@ xbps_unpack_binary_pkg(prop_dictionary_t pkg_repod)
if (archive_read_open_filename(ar, bpkg, ARCHIVE_READ_BLOCKSIZE) != 0) {
rv = archive_errno(ar);
xbps_error_printf("failed to open `%s' binpkg: %s\n",
fname, strerror(rv));
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
rv, pkgname, version,
"%s: [unpack] failed to open binary package `%s': %s",
pkgver, fname, strerror(rv));
goto out;
}
/*
* Set extract progress callback if specified.
*/
xhp = xbps_handle_get();
if (xhp->xbps_unpack_cb != NULL) {
xhp->xucd->entry_extract_count = 0;
xhp->xucd->entry_total_count = 0;
}
/*
* Set package state to half-unpacked.
*/
if ((rv = xbps_set_pkg_state_installed(pkgname, version, pkgver,
XBPS_PKG_STATE_HALF_UNPACKED)) != 0) {
xbps_error_printf("failed to set `%s' to half-unpacked "
"state: %s\n", pkgver, strerror(rv));
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
rv, pkgname, version,
"%s: [unpack] failed to set state to half-unpacked: %s",
pkgver, strerror(rv));
goto out;
}
/*
* Extract archive files.
*/
if ((rv = unpack_archive(pkg_repod, ar, pkgname, version, xhp)) != 0)
rv = unpack_archive(pkg_repod, ar);
if (rv != 0) {
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
rv, pkgname, version,
"%s: [unpack] failed to unpack files on archive: %s",
pkgver, strerror(rv));
goto out;
}
/*
* Set package state to unpacked.
*/
if ((rv = xbps_set_pkg_state_installed(pkgname, version, pkgver,
XBPS_PKG_STATE_UNPACKED)) != 0) {
xbps_error_printf("failed to set `%s' to unpacked "
"state: %s\n", pkgver, strerror(rv));
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
rv, pkgname, version,
"%s: [unpack] failed to set state to unpacked: %s",
pkgver, strerror(rv));
}
out:
if (bpkg)

View File

@@ -225,7 +225,7 @@ find_repo_deps(prop_dictionary_t transd, /* transaction dictionary */
pkgname = xbps_pkgpattern_name(reqpkg);
if (pkgname == NULL) {
rv = EINVAL;
xbps_error_printf("failed to get "
xbps_dbg_printf("failed to get "
"pkgname from `%s'!", reqpkg);
break;
}
@@ -237,7 +237,7 @@ find_repo_deps(prop_dictionary_t transd, /* transaction dictionary */
if (errno && errno != ENOENT) {
/* error */
rv = errno;
xbps_error_printf("failed to find "
xbps_dbg_printf("failed to find "
"installed pkg for `%s': %s\n",
reqpkg, strerror(errno));
break;
@@ -253,7 +253,7 @@ find_repo_deps(prop_dictionary_t transd, /* transaction dictionary */
if (errno && errno != ENOENT) {
/* error */
rv = errno;
xbps_error_printf("failed to find "
xbps_dbg_printf("failed to find "
"installed virtual pkg for `%s': %s\n",
reqpkg, strerror(errno));
break;
@@ -325,7 +325,7 @@ find_repo_deps(prop_dictionary_t transd, /* transaction dictionary */
} else {
/* error matching pkgpattern */
prop_object_release(tmpd);
xbps_error_printf("failed to match "
xbps_dbg_printf("failed to match "
"pattern %s with %s\n", reqpkg, pkgver_q);
break;
}
@@ -368,7 +368,7 @@ find_repo_deps(prop_dictionary_t transd, /* transaction dictionary */
if (curpkgd == NULL) {
/* pkg not found, there was some error */
if (errno && errno != ENOENT) {
xbps_error_printf("failed to find pkg "
xbps_dbg_printf("failed to find pkg "
"for `%s' in rpool: %s\n",
reqpkg, strerror(errno));
rv = errno;

View File

@@ -92,7 +92,7 @@ xbps_repository_sync_pkg_index(const char *uri)
struct xbps_handle *xhp;
struct url *url = NULL;
struct stat st;
const char *fetch_outputdir;
const char *fetch_outputdir, *fetchstr = NULL;
char *rpidx, *lrepodir, *uri_fixedp;
char *metadir, *tmp_metafile, *lrepofile;
int rv = 0;
@@ -124,8 +124,10 @@ xbps_repository_sync_pkg_index(const char *uri)
goto out;
}
if ((rv = xbps_mkpath(metadir, 0755)) == -1) {
xbps_dbg_printf("[rsyncidx] failed to create metadir `%s': "
"%s\n", metadir, strerror(errno));
xbps_set_cb_state(XBPS_STATE_REPOSYNC_FAIL,
errno, NULL, NULL,
"[reposync] failed to create metadir `%s': %s",
metadir, strerror(errno));
goto out;
}
/*
@@ -166,25 +168,19 @@ xbps_repository_sync_pkg_index(const char *uri)
fetch_outputdir = metadir;
/* reposync start cb */
if (xhp->xbps_state_cb) {
xhp->xscd->state = XBPS_STATE_REPOSYNC;
xhp->xscd->repourl = uri;
xhp->xbps_state_cb(xhp->xscd);
}
xbps_set_cb_state(XBPS_STATE_REPOSYNC, 0, NULL, NULL,
"Synchronizing index for `%s'...", uri);
/*
* Download index.plist file from repository.
*/
if (xbps_fetch_file(rpidx, fetch_outputdir, true, NULL) == -1) {
/* reposync error cb */
if (xhp->xbps_state_cb) {
xhp->xscd->state = XBPS_STATE_REPOSYNC_FAIL;
xhp->xscd->repourl = uri;
if (fetchLastErrCode != 0)
xhp->xscd->err = fetchLastErrCode;
else
xhp->xscd->err = errno;
xhp->xbps_state_cb(xhp->xscd);
}
fetchstr = xbps_fetch_error_string();
xbps_set_cb_state(XBPS_STATE_REPOSYNC_FAIL,
fetchLastErrCode != 0 ? fetchLastErrCode : errno,
NULL, NULL,
"[reposync] failed to fetch file `%s': %s",
rpidx, fetchstr ? fetchstr : strerror(errno));
rv = -1;
goto out;
}
@@ -197,8 +193,8 @@ xbps_repository_sync_pkg_index(const char *uri)
*/
tmpd = prop_dictionary_internalize_from_zfile(tmp_metafile);
if (tmpd == NULL) {
xbps_dbg_printf("[rsyncidx] downloaded index.plist "
"file cannot be read! removing...\n");
xbps_set_cb_state(XBPS_STATE_REPOSYNC_FAIL, 0, NULL, NULL,
"[reposync] downloaded file `%s' is not valid.", rpidx);
(void)unlink(tmp_metafile);
rv = -1;
goto out;
@@ -214,19 +210,22 @@ xbps_repository_sync_pkg_index(const char *uri)
* Create local repodir to store index.plist file.
*/
if ((rv = xbps_mkpath(lrepodir, 0755)) == -1) {
xbps_dbg_printf("[rsyncidx] failed to create repodir "
"`%s': %s\n", lrepodir, strerror(errno));
xbps_set_cb_state(XBPS_STATE_REPOSYNC_FAIL, errno, NULL, NULL,
"[reposync] failed to create repodir for `%s': %s",
lrepodir, strerror(rv));
goto out;
}
/*
* Rename to destination file now it has been fetched successfully.
*/
if ((rv = rename(tmp_metafile, lrepofile)) == -1)
xbps_dbg_printf("[rsyncidx] failed to rename `%s' to "
"`%s': %s\n", tmp_metafile, lrepofile, strerror(errno));
else
if ((rv = rename(tmp_metafile, lrepofile)) == -1) {
xbps_set_cb_state(XBPS_STATE_REPOSYNC_FAIL, errno, NULL, NULL,
"[reposync] failed to rename index file `%s' to `%s': %s",
tmp_metafile, lrepofile, strerror(errno));
} else {
rv = 1; /* success */
}
out:
if (rpidx)

View File

@@ -35,33 +35,12 @@
#include "xbps_api_impl.h"
#define RUN_STATE_CB(s, d, p, bf, burl) \
do { \
if (xhp->xbps_state_cb != NULL) { \
xhp->xscd->state = s; \
xhp->xscd->desc = d; \
xhp->xscd->pkgver = p; \
xhp->xscd->binpkg_fname = bf; \
xhp->xscd->repourl = burl; \
(*xhp->xbps_state_cb)(xhp->xscd); \
} \
} while (0)
#define RUN_STATE_ERR_CB(s, p, r) \
do { \
if (xhp->xbps_state_cb != NULL) { \
xhp->xscd->state = s; \
xhp->xscd->pkgver = p; \
xhp->xscd->err = r; \
(*xhp->xbps_state_cb)(xhp->xscd); \
} \
} while (0)
static int
check_binpkgs_hash(struct xbps_handle *xhp, prop_object_iterator_t iter)
check_binpkgs_hash(prop_object_iterator_t iter)
{
prop_object_t obj;
const char *pkgver, *repoloc, *filen, *sha256, *trans;
const char *pkgname, *version;
char *binfile;
int rv = 0;
@@ -71,6 +50,8 @@ check_binpkgs_hash(struct xbps_handle *xhp, prop_object_iterator_t iter)
(strcmp(trans, "configure") == 0))
continue;
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(obj, "version", &version);
prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc);
assert(repoloc != NULL);
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
@@ -86,11 +67,15 @@ check_binpkgs_hash(struct xbps_handle *xhp, prop_object_iterator_t iter)
rv = EINVAL;
break;
}
RUN_STATE_CB(XBPS_STATE_VERIFY, NULL, pkgver, filen, repoloc);
xbps_set_cb_state(XBPS_STATE_VERIFY, 0, pkgname, version,
"Verifying `%s' package integrity...", filen, repoloc);
rv = xbps_file_hash_check(binfile, sha256);
if (rv != 0) {
free(binfile);
RUN_STATE_ERR_CB(XBPS_STATE_VERIFY_FAIL, pkgver, rv);
xbps_set_cb_state(XBPS_STATE_VERIFY_FAIL,
rv, pkgname, version,
"Failed to verify `%s' package integrity: %s",
filen, strerror(rv));
break;
}
free(binfile);
@@ -105,6 +90,7 @@ download_binpkgs(struct xbps_handle *xhp, prop_object_iterator_t iter)
{
prop_object_t obj;
const char *pkgver, *repoloc, *filen, *trans;
const char *pkgname, *version;
char *binfile;
int rv = 0;
@@ -114,6 +100,8 @@ download_binpkgs(struct xbps_handle *xhp, prop_object_iterator_t iter)
(strcmp(trans, "configure") == 0))
continue;
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(obj, "version", &version);
prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc);
assert(repoloc != NULL);
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
@@ -138,23 +126,30 @@ download_binpkgs(struct xbps_handle *xhp, prop_object_iterator_t iter)
*/
if (xbps_mkpath(prop_string_cstring_nocopy(xhp->cachedir),
0755) == -1) {
xbps_error_printf("xbps-bin: cannot mkdir cachedir "
"`%s': %s.\n",
prop_string_cstring_nocopy(xhp->cachedir),
xbps_set_cb_state(XBPS_STATE_DOWNLOAD_FAIL,
errno, pkgname, version,
"%s: [trans] cannot create cachedir `%s': %s",
pkgver, prop_string_cstring_nocopy(xhp->cachedir),
strerror(errno));
free(binfile);
rv = errno;
break;
}
RUN_STATE_CB(XBPS_STATE_DOWNLOAD, NULL, pkgver, filen, repoloc);
xbps_set_cb_state(XBPS_STATE_DOWNLOAD,
0, pkgname, version,
"Downloading binary package `%s' (from `%s')...",
filen, repoloc);
/*
* Fetch binary package.
*/
rv = xbps_fetch_file(binfile,
prop_string_cstring_nocopy(xhp->cachedir), false, NULL);
if (rv == -1) {
RUN_STATE_ERR_CB(XBPS_STATE_DOWNLOAD_FAIL,
pkgver, errno);
xbps_set_cb_state(XBPS_STATE_DOWNLOAD_FAIL,
errno, pkgname, version,
"%s: [trans] failed to download binary package "
"`%s' from `%s': %s", pkgver, filen, repoloc,
strerror(errno));
free(binfile);
break;
}
@@ -185,23 +180,23 @@ xbps_transaction_commit(prop_dictionary_t transd)
/*
* Download binary packages (if they come from a remote repository).
*/
RUN_STATE_CB(XBPS_STATE_DOWNLOAD,
"[*] Downloading binary packages", NULL, NULL, NULL);
xbps_set_cb_state(XBPS_STATE_TRANS_DOWNLOAD, 0, NULL, NULL,
"[*] Downloading binary packages");
if ((rv = download_binpkgs(xhp, iter)) != 0)
goto out;
/*
* Check SHA256 hashes for binary packages in transaction.
*/
RUN_STATE_CB(XBPS_STATE_VERIFY,
"[*] Verifying binary package integrity", NULL, NULL, NULL);
if ((rv = check_binpkgs_hash(xhp, iter)) != 0)
xbps_set_cb_state(XBPS_STATE_TRANS_VERIFY, 0, NULL, NULL,
"[*] Verifying binary package integrity");
if ((rv = check_binpkgs_hash(iter)) != 0)
goto out;
/*
* Install, update, configure or remove packages as specified
* in the transaction dictionary.
*/
RUN_STATE_CB(XBPS_STATE_INSTALL,
"[*] Running transaction tasks", NULL, NULL, NULL);
xbps_set_cb_state(XBPS_STATE_TRANS_RUN, 0, NULL, NULL,
"[*] Running transaction tasks");
while ((obj = prop_object_iterator_next(iter)) != NULL) {
update = false;
@@ -217,34 +212,21 @@ xbps_transaction_commit(prop_dictionary_t transd)
*/
prop_dictionary_get_bool(obj, "remove-and-update",
&update);
RUN_STATE_CB(XBPS_STATE_REMOVE,
NULL, pkgver, NULL, NULL);
rv = xbps_remove_pkg(pkgname, version, update);
if (rv != 0) {
RUN_STATE_ERR_CB(XBPS_STATE_REMOVE_FAIL,
pkgver, rv);
if (rv != 0)
goto out;
}
if (update)
continue;
RUN_STATE_CB(XBPS_STATE_PURGE,
NULL, pkgver, NULL, NULL);
if ((rv = xbps_purge_pkg(pkgname, false)) != 0) {
RUN_STATE_ERR_CB(XBPS_STATE_PURGE_FAIL,
pkgver, rv);
if ((rv = xbps_purge_pkg(pkgname, false)) != 0)
goto out;
}
} else if (strcmp(tract, "configure") == 0) {
/*
* Reconfigure pending package.
*/
rv = xbps_configure_pkg(pkgname, version, false, false);
if (rv != 0) {
RUN_STATE_ERR_CB(XBPS_STATE_CONFIGURE_FAIL,
pkgver, rv);
if (rv != 0)
goto out;
}
} else {
/*
* Install or update a package.
@@ -257,43 +239,41 @@ xbps_transaction_commit(prop_dictionary_t transd)
* Update a package: execute pre-remove
* action if found before unpacking.
*/
RUN_STATE_CB(XBPS_STATE_UPDATE,
NULL, pkgver, filen, NULL);
xbps_set_cb_state(XBPS_STATE_UPDATE,
0, pkgname, version, NULL);
rv = xbps_remove_pkg(pkgname, version, true);
if (rv != 0) {
RUN_STATE_ERR_CB(XBPS_STATE_UPDATE_FAIL,
pkgver, rv);
xbps_set_cb_state(
XBPS_STATE_UPDATE_FAIL,
rv, pkgname, version,
"%s: [trans] failed to update "
"package to `%s': %s", pkgver,
version, strerror(rv));
goto out;
}
} else {
/* Install a package */
xbps_set_cb_state(XBPS_STATE_INSTALL,
0, pkgname, version, NULL);
}
/*
* Unpack binary package.
*/
RUN_STATE_CB(XBPS_STATE_UNPACK, NULL,
pkgver, filen, NULL);
if ((rv = xbps_unpack_binary_pkg(obj)) != 0) {
RUN_STATE_ERR_CB(XBPS_STATE_UNPACK_FAIL,
pkgver, rv);
if ((rv = xbps_unpack_binary_pkg(obj)) != 0)
goto out;
}
/*
* Register package.
*/
RUN_STATE_CB(XBPS_STATE_REGISTER,
NULL, pkgver, filen, NULL);
if ((rv = xbps_register_pkg(obj)) != 0) {
RUN_STATE_ERR_CB(XBPS_STATE_REGISTER_FAIL,
pkgver, rv);
if ((rv = xbps_register_pkg(obj)) != 0)
goto out;
}
}
}
prop_object_iterator_reset(iter);
/*
* Configure all unpacked packages.
*/
RUN_STATE_CB(XBPS_STATE_CONFIGURE,
"[*] Configuring unpacked packages", NULL, NULL, NULL);
xbps_set_cb_state(XBPS_STATE_TRANS_CONFIGURE, 0, NULL, NULL,
"[*] Configuring unpacked packages");
while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
@@ -306,11 +286,9 @@ xbps_transaction_commit(prop_dictionary_t transd)
if (strcmp(tract, "update") == 0)
update = true;
if ((rv = xbps_configure_pkg(pkgname, version,
false, update)) != 0) {
RUN_STATE_ERR_CB(XBPS_STATE_CONFIGURE_FAIL, pkgver, rv);
rv = xbps_configure_pkg(pkgname, version, false, update);
if (rv != 0)
goto out;
}
}
out:

View File

@@ -341,7 +341,7 @@ xbps_sort_pkg_deps(void)
*/
ndeps = prop_array_count(unsorted);
if (!prop_array_ensure_capacity(sorted, ndeps)) {
xbps_error_printf("failed to set capacity to the sorted "
xbps_dbg_printf("failed to set capacity to the sorted "
"pkgdeps array\n");
return ENOMEM;
}

View File

@@ -35,7 +35,9 @@
#include <errno.h>
#include <ctype.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xbps_api_impl.h"
/**
@@ -281,7 +283,6 @@ xbps_pkg_has_rundeps(prop_dictionary_t pkgd)
return false;
}
#ifdef HAVE_VASPRINTF
char *
xbps_xasprintf(const char *fmt, ...)
{
@@ -297,4 +298,3 @@ xbps_xasprintf(const char *fmt, ...)
return buf;
}
#endif /* HAVE_VASPRINTF */