API clean up (part 2), plus misc changes and improvements.

- Rename regpkgs_dictionary to regpkgdb_dictionary to better describe what is is.
- Change some funcs in plist.c to return a boolean rather than int.
- Hide more internal funcs off the API.
- Simplify xbps_repository_update_pkg() and remove its second arg.
- Hide implementation details in xbps_repository_pool, now to iterate over the
  pool you have to use xbps_repository_pool_foreach and its struct
  repository_pool_index.
- Introduce xbps_{init,end}, to initialize/destroy some stuff in the library.
- Introduce xbps_dbg_printf to printf stuff for debugging purposes.
- xbps-{bin,repo}:  added -d arg to enable debugging output.
- Before checking if a config file needs to be installed or such, check that
  package contains the "conf_files" array.
- Remove obsolete dirs as well while updating packages.
- If transaction dictionary is ready remove the "missing_deps" array.

Bump XBPS_RELVER to 20101118.

--HG--
rename : lib/regpkgs_dictionary.c => lib/regpkgdb_dictionary.c
This commit is contained in:
Juan RP 2010-11-19 13:40:13 +01:00
parent ffc255b715
commit fdec663855
33 changed files with 1426 additions and 943 deletions

View File

@ -29,6 +29,7 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <xbps_api.h>
#include "defs.h"
@ -56,7 +57,7 @@ xbps_check_pkg_integrity_all(void)
int rv = 0;
size_t npkgs = 0, nbrokenpkgs = 0;
d = xbps_regpkgs_dictionary_init();
d = xbps_regpkgdb_dictionary_get();
if (d == NULL)
return ENODEV;
@ -82,7 +83,7 @@ out:
if (iter)
prop_object_iterator_release(iter);
xbps_regpkgs_dictionary_release();
xbps_regpkgdb_dictionary_release();
return rv;
}

View File

@ -30,6 +30,7 @@
#include <errno.h>
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#include <xbps_api.h>
#include "defs.h"
@ -102,9 +103,6 @@ download_package_list(prop_object_iterator_t iter)
if (cachedir == NULL)
return EINVAL;
/* Set default limit of global and per-host cached connections */
xbps_fetch_set_cache_connection(0, 0);
while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc);
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
@ -293,11 +291,14 @@ xbps_autoupdate_pkgs(bool yes)
if (rv == ENOENT) {
printf("No packages currently registered.\n");
return 0;
} else if (rv == ENOPKG) {
} else if (rv == ENXIO) {
printf("All packages are up-to-date.\n");
return 0;
} else {
fprintf(stderr, "xbps-bin: unexpected error %s\n",
strerror(rv));
return -1;
}
return rv;
}
return xbps_exec_transaction(yes);
@ -337,15 +338,16 @@ xbps_install_new_pkg(const char *pkg)
free(pkgname);
return 0;
}
rv = xbps_repository_install_pkg(pkgpatt, true);
if (rv == EAGAIN) {
fprintf(stderr, "xbps-bin: unable to locate '%s' in "
"repository pool.\n", pkg);
rv = 1;
} else if (rv != 0 && rv != ENOENT) {
fprintf(stderr, "xbps-bin: unexpected error: %s",
strerror(errno));
rv = -1;
if ((rv = xbps_repository_install_pkg(pkgpatt)) != 0) {
if (rv == EAGAIN) {
fprintf(stderr, "xbps-bin: unable to locate '%s' in "
"repository pool.\n", pkg);
rv = -1;
} else {
fprintf(stderr, "xbps-bin: unexpected error: %s\n",
strerror(rv));
rv = -1;
}
}
if (pkgmatch)
@ -358,28 +360,22 @@ xbps_install_new_pkg(const char *pkg)
int
xbps_update_pkg(const char *pkgname)
{
prop_dictionary_t pkgd;
int rv = 0;
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
printf("Finding new '%s' package...\n", pkgname);
if (pkgd) {
rv = xbps_repository_update_pkg(pkgname, pkgd);
if (rv == EEXIST) {
printf("Package '%s' is up to date.\n", pkgname);
rv = 0;
} else if (rv == ENOENT) {
fprintf(stderr, "Package '%s' not found in "
"repository pool.\n", pkgname);
rv = 0;
}
prop_object_release(pkgd);
} else {
rv = xbps_repository_update_pkg(pkgname);
if (rv == EEXIST)
printf("Package '%s' is up to date.\n", pkgname);
else if (rv == ENOENT)
fprintf(stderr, "Package '%s' not found in "
"repository pool.\n", pkgname);
else if (rv == ENODEV)
printf("Package '%s' not installed.\n", pkgname);
return 0;
else if (rv != 0) {
fprintf(stderr, "xbps-bin: unexpected error %s\n",
strerror(rv));
return -1;
}
return rv;
return 0;
}
static int
@ -435,11 +431,10 @@ replace_packages(prop_dictionary_t trans_dict, prop_dictionary_t pkgd,
prop_object_release(instd);
version = xbps_get_pkg_version(pkgver);
rv = xbps_remove_pkg(reppkgn, version, false);
if (rv != 0) {
if ((rv = xbps_remove_pkg(reppkgn, version, false)) != 0) {
fprintf(stderr, "xbps-bin: couldn't remove %s (%s)\n",
reppkgn, strerror(rv));
return rv;
return -1;
}
}
prop_object_iterator_release(replaces_iter);
@ -552,8 +547,7 @@ exec_transaction(struct transaction *trans)
printf("Replacing %s files (%s -> %s) ...\n",
pkgname, instver, version);
rv = xbps_remove_pkg(pkgname, version, true);
if (rv != 0) {
if ((rv = xbps_remove_pkg(pkgname, version, true)) != 0) {
fprintf(stderr, "xbps-bin: error "
"replacing %s-%s (%s)\n", pkgname,
instver, strerror(rv));
@ -617,14 +611,15 @@ xbps_exec_transaction(bool yes)
return rv;
trans->dict = xbps_repository_get_transaction_dict();
if (trans->dict == NULL)
if (trans->dict == NULL) {
rv = errno;
goto out;
/*
* Bail out if there are unresolved deps.
*/
array = prop_dictionary_get(trans->dict, "missing_deps");
if (prop_array_count(array) > 0) {
}
if (rv == ENOENT) {
/*
* Bail out if there are unresolved deps.
*/
array = prop_dictionary_get(trans->dict, "missing_deps");
show_missing_deps(trans->dict);
goto out;
}
@ -644,9 +639,6 @@ xbps_exec_transaction(bool yes)
trans->yes = yes;
rv = exec_transaction(trans);
DPRINTF(("Dictionary AFTER transaction happened:\n"));
DPRINTF(("%s", prop_dictionary_externalize(trans->dict)));
out:
if (trans->iter)
prop_object_iterator_release(trans->iter);

View File

@ -30,6 +30,7 @@
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include <unistd.h>
#include <xbps_api.h>
#include "defs.h"
@ -44,7 +45,7 @@ usage(void)
" autoremove\n"
" autoupdate\n"
" check\t\t[<pkgname>|<all>]\n"
" find-files\t<pattern>\n"
" find-files\t\t<pattern>\n"
" install\t\t[<pkgname(s)>|<pkgpattern(s)>]\n"
" list\t\t[state]\n"
" list-manual\n"
@ -59,6 +60,7 @@ usage(void)
" update\t\t<pkgname(s)>\n"
" Options shared by all targets:\n"
" -c\t\t<cachedir>\n"
" -d\t\tDebug output\n"
" -r\t\t<rootdir>\n"
" -v\t\tShows verbose messages\n"
" -V\t\tPrints the xbps release version\n"
@ -120,8 +122,7 @@ list_manual_packages(prop_object_t obj, void *arg, bool *loop_done)
static void
cleanup(int signum)
{
xbps_regpkgs_dictionary_release();
xbps_fetch_unset_cache_connection();
xbps_end();
exit(signum);
}
@ -132,15 +133,18 @@ main(int argc, char **argv)
pkg_state_t pkgstate = 0;
struct sigaction sa;
int i = 0, c, flags = 0, rv = 0;
bool yes, purge;
bool yes, purge, with_debug;
yes = purge = false;
yes = purge = with_debug = false;
while ((c = getopt(argc, argv, "Vcfpr:vy")) != -1) {
while ((c = getopt(argc, argv, "Vcdfpr:vy")) != -1) {
switch (c) {
case 'c':
xbps_set_cachedir(optarg);
break;
case 'd':
with_debug = true;
break;
case 'f':
flags |= XBPS_FLAG_FORCE;
break;
@ -184,9 +188,13 @@ main(int argc, char **argv)
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
if ((dict = xbps_regpkgs_dictionary_init()) == NULL) {
if (errno != ENOENT) {
rv = errno;
/*
* Initialize stuff for libxbps.
*/
xbps_init(with_debug);
if ((dict = xbps_regpkgdb_dictionary_get()) == NULL) {
if (errno && errno != ENOENT) {
fprintf(stderr,
"E: couldn't initialize regpkgdb dict: %s\n",
strerror(errno));
@ -194,6 +202,15 @@ main(int argc, char **argv)
}
}
if ((rv = xbps_repository_pool_init()) != 0) {
if (rv != ENOENT) {
fprintf(stderr,
"E: couldn't initialize repository pool: %s\n",
strerror(rv));
goto out;
}
}
if (strcasecmp(argv[0], "list") == 0) {
/* Lists packages currently registered in database. */
if (argc < 1 || argc > 2)
@ -221,11 +238,8 @@ main(int argc, char **argv)
}
}
if (!xbps_callback_array_iter_in_dict(dict, "packages",
list_pkgs_in_dict, &pkgstate)) {
rv = errno;
goto out;
}
rv = xbps_callback_array_iter_in_dict(dict, "packages",
list_pkgs_in_dict, &pkgstate);
} else if (strcasecmp(argv[0], "install") == 0) {
/* Installs a binary package and required deps. */
@ -361,7 +375,7 @@ main(int argc, char **argv)
rv = xbps_callback_array_iter_in_dict(dict, "packages",
list_manual_packages, NULL);
} else if (strcasecmp(argv[0], "show-revdeps") == 0) {
/*
* Show reverse dependencies for a package.

View File

@ -2,12 +2,12 @@
.\" Title: xbps-bin
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
.\" Date: 31/10/2010
.\" Date: 18/11/2010
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "XBPS\-BIN" "8" "31/10/2010" "\ \&" "\ \&"
.TH "XBPS\-BIN" "8" "18/11/2010" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
@ -43,6 +43,11 @@ of
\fI/blah/cachedir\fR\&.
.RE
.PP
\fB\-d\fR
.RS 4
Enables extra debugging output to be shown to stderr.
.RE
.PP
\fB\-f\fR
.RS 4
Used currently in the

View File

@ -29,6 +29,7 @@
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <unistd.h>
#include <xbps_api.h>

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2008-2009 Juan Romero Pardines.
* Copyright (c) 2008-2010 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -30,6 +30,7 @@
#include <errno.h>
#include <limits.h>
#include <libgen.h>
#include <unistd.h>
#include <xbps_api.h>
#include "defs.h"
@ -66,19 +67,44 @@ usage(void)
exit(EXIT_FAILURE);
}
static int
repo_list_uri_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
(void)arg;
(void)done;
printf("%s\n", rpi->rpi_uri);
return 0;
}
static int
repo_search_pkgs_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
char *pattern = arg;
(void)done;
printf("From %s repository ...\n", rpi->rpi_uri);
(void)xbps_callback_array_iter_in_dict(rpi->rpi_repod,
"packages", show_pkg_namedesc, pattern);
return 0;
}
int
main(int argc, char **argv)
{
prop_dictionary_t pkgd;
struct repository_pool *rpool;
char *root;
int c, rv = 0;
bool with_debug = false;
while ((c = getopt(argc, argv, "Vcr:")) != -1) {
while ((c = getopt(argc, argv, "Vcdr:")) != -1) {
switch (c) {
case 'c':
xbps_set_cachedir(optarg);
break;
case 'd':
with_debug = true;
break;
case 'r':
/* To specify the root directory */
root = optarg;
@ -99,11 +125,14 @@ main(int argc, char **argv)
if (argc < 1)
usage();
rv = xbps_repository_pool_init();
if (rv != 0 && rv != ENOENT) {
fprintf(stderr, "E: cannot get repository list pool! %s\n",
strerror(rv));
exit(EXIT_FAILURE);
xbps_init(with_debug);
if ((rv = xbps_repository_pool_init()) != 0) {
if (rv != ENOENT) {
fprintf(stderr, "E: cannot get repository list pool! %s\n",
strerror(rv));
exit(EXIT_FAILURE);
}
}
if (strcasecmp(argv[0], "add") == 0) {
@ -118,8 +147,7 @@ main(int argc, char **argv)
if (argc != 1)
usage();
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries)
printf("%s\n", rpool->rp_uri);
xbps_repository_pool_foreach(repo_list_uri_cb, NULL);
} else if ((strcasecmp(argv[0], "rm") == 0) ||
(strcasecmp(argv[0], "remove") == 0)) {
@ -137,11 +165,7 @@ main(int argc, char **argv)
if (argc != 2)
usage();
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) {
printf("From %s repository ...\n", rpool->rp_uri);
(void)xbps_callback_array_iter_in_dict(rpool->rp_repod,
"packages", show_pkg_namedesc, argv[1]);
}
xbps_repository_pool_foreach(repo_search_pkgs_cb, argv[1]);
} else if (strcasecmp(argv[0], "show") == 0) {
/* Shows info about a binary package. */
@ -179,9 +203,15 @@ main(int argc, char **argv)
pkgd = xbps_repository_get_pkg_plist_dict(argv[1],
XBPS_PKGFILES);
if (pkgd == NULL) {
fprintf(stderr,
"E: couldn't read %s: %s.\n", XBPS_PKGFILES,
strerror(errno));
if (errno != ENOENT) {
fprintf(stderr, "xbps-repo: unexpected "
"error '%s' searching for '%s'\n",
strerror(errno), argv[1]);
} else {
fprintf(stderr,
"Package '%s' not found in repository "
"pool.\n", argv[1]);
}
rv = errno;
goto out;
}
@ -207,6 +237,6 @@ main(int argc, char **argv)
}
out:
xbps_repository_pool_release();
xbps_end();
exit(rv ? EXIT_FAILURE : EXIT_SUCCESS);
}

View File

@ -33,6 +33,7 @@
#include <assert.h>
#include <xbps_api.h>
#include "../xbps-bin/defs.h"
#include "defs.h"
#include "config.h"
@ -147,13 +148,15 @@ unregister_repository(const char *uri)
if ((idxstr = sanitize_url(uri)) == NULL)
return errno;
if ((rv = xbps_repository_unregister(idxstr)) != 0) {
if (rv == ENOENT)
fprintf(stderr, "Repository '%s' not actually "
"registered.\n", idxstr);
else
fprintf(stderr, "E: couldn't unregister "
"repository (%s)\n", strerror(rv));
if ((rv = xbps_repository_unregister(idxstr)) == 0)
return 0;
if (rv == ENOENT) {
fprintf(stderr, "Repository '%s' not actually "
"registered.\n", idxstr);
} else {
fprintf(stderr, "E: couldn't unregister "
"repository (%s)\n", strerror(rv));
}
return rv;
@ -211,14 +214,13 @@ register_repository(const char *uri)
if ((rpi = pkgindex_verify(plist, idxstr)) == NULL)
goto out;
rv = xbps_repository_register(idxstr);
if (rv != 0 && rv != EEXIST) {
fprintf(stderr, "E: couldn't register repository (%s)\n",
strerror(rv));
goto out;
} else if (rv == EEXIST) {
fprintf(stderr, "W: repository already registered.\n");
rv = 0;
if ((rv = xbps_repository_register(idxstr)) != 0) {
if (rv == EEXIST) {
fprintf(stderr, "W: repository already registered.\n");
} else {
fprintf(stderr, "E: couldn't register repository "
"(%s)\n", strerror(errno));
}
goto out;
}
@ -234,110 +236,111 @@ out:
return rv;
}
static int
repo_show_pkg_info_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
prop_dictionary_t repo_pkgd, pkg_propsd;
const char *pkgname = arg;
char *url = NULL;
repo_pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod,
"packages", pkgname);
if (repo_pkgd == NULL)
return errno;
url = xbps_repository_get_path_from_pkg_dict(repo_pkgd, rpi->rpi_uri);
if (url == NULL)
return errno;
printf("Fetching info from: %s\n", rpi->rpi_uri);
pkg_propsd =
xbps_repository_get_pkg_plist_dict_from_url(url, XBPS_PKGPROPS);
if (pkg_propsd == NULL) {
free(url);
return errno;
}
show_pkg_info_only_repo(repo_pkgd);
show_pkg_info(pkg_propsd);
prop_object_release(pkg_propsd);
*done = true;
return 0;
}
int
show_pkg_info_from_repolist(const char *pkgname)
{
struct repository_pool *rp;
prop_dictionary_t repo_pkgd, pkg_propsd;
int rv = 0;
return xbps_repository_pool_foreach(repo_show_pkg_info_cb,
__UNCONST(pkgname));
}
SIMPLEQ_FOREACH(rp, &rp_queue, rp_entries) {
char *url = NULL;
repo_pkgd = xbps_find_pkg_in_dict_by_name(rp->rp_repod,
"packages", pkgname);
if (repo_pkgd == NULL) {
if (errno && errno != ENOENT) {
rv = errno;
break;
}
continue;
}
url = xbps_repository_get_path_from_pkg_dict(repo_pkgd,
rp->rp_uri);
if (url == NULL) {
rv = errno;
break;
}
printf("Fetching info from: %s\n", rp->rp_uri);
pkg_propsd = xbps_repository_get_pkg_plist_dict_from_url(url,
XBPS_PKGPROPS);
if (pkg_propsd == NULL) {
free(url);
rv = errno;
break;
}
show_pkg_info_only_repo(repo_pkgd);
show_pkg_info(pkg_propsd);
prop_object_release(pkg_propsd);
break;
static int
repo_show_pkg_deps_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
prop_dictionary_t pkgd;
const char *ver, *pkgname = arg;
pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod,
"packages", pkgname);
if (pkgd == NULL) {
if (errno && errno != ENOENT)
return errno;
return 0;
}
prop_dictionary_get_cstring_nocopy(pkgd, "version", &ver);
printf("Repository %s [pkgver: %s]\n", rpi->rpi_uri, ver);
(void)xbps_callback_array_iter_in_dict(pkgd,
"run_depends", list_strings_sep_in_array, NULL);
*done = true;
return rv;
return 0;
}
int
show_pkg_deps_from_repolist(const char *pkgname)
{
struct repository_pool *rd;
prop_dictionary_t pkgd;
const char *ver;
return xbps_repository_pool_foreach(repo_show_pkg_deps_cb,
__UNCONST(pkgname));
}
static int
repo_sync_pkg_index_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
struct repoinfo *rp;
char *plist;
int rv = 0;
SIMPLEQ_FOREACH(rd, &rp_queue, rp_entries) {
pkgd = xbps_find_pkg_in_dict_by_name(rd->rp_repod,
"packages", pkgname);
if (pkgd == NULL) {
if (errno != ENOENT) {
rv = errno;
break;
}
continue;
}
prop_dictionary_get_cstring_nocopy(pkgd, "version", &ver);
printf("Repository %s [pkgver: %s]\n", rd->rp_uri, ver);
(void)xbps_callback_array_iter_in_dict(pkgd,
"run_depends", list_strings_sep_in_array, NULL);
}
(void)arg;
(void)done;
return rv;
if (!xbps_check_is_repo_string_remote(rpi->rpi_uri))
return 0;
printf("Syncing package index from: %s\n", rpi->rpi_uri);
rv = xbps_repository_sync_pkg_index(rpi->rpi_uri);
if (rv == -1) {
fprintf(stderr, "E: returned: %s\n", xbps_fetch_error_string());
return rv;
} else if (rv == 0) {
printf("Package index file is already up to date.\n");
return 0;
}
if ((plist = xbps_get_pkg_index_plist(rpi->rpi_uri)) == NULL)
return EINVAL;
if ((rp = pkgindex_verify(plist, rpi->rpi_uri)) == NULL)
return errno;
printf("Updated package index at %s (v%s) with %ju packages.\n",
rpi->rpi_uri, rp->pkgidxver, rp->totalpkgs);
free(rp);
free(plist);
return 0;
}
int
repository_sync(void)
{
struct repository_pool *rp;
char *plist;
int rv = 0;
SIMPLEQ_FOREACH(rp, &rp_queue, rp_entries) {
struct repoinfo *rpi = NULL;
if (!xbps_check_is_repo_string_remote(rp->rp_uri))
continue;
printf("Syncing package index from: %s\n", rp->rp_uri);
rv = xbps_repository_sync_pkg_index(rp->rp_uri);
if (rv == -1) {
fprintf(stderr, "E: returned: %s\n",
xbps_fetch_error_string());
break;
} else if (rv == 0) {
printf("Package index file is already up to date.\n");
continue;
}
if ((plist = xbps_get_pkg_index_plist(rp->rp_uri)) == NULL) {
rv = EINVAL;
break;
}
if ((rpi = pkgindex_verify(plist, rp->rp_uri)) == NULL) {
rv = errno;
break;
}
printf("Updated package index at %s (v%s) with %ju packages.\n",
rp->rp_uri, rpi->pkgidxver, rpi->totalpkgs);
free(rpi);
free(plist);
}
return rv;
return xbps_repository_pool_foreach(repo_sync_pkg_index_cb, NULL);
}

View File

@ -2,12 +2,12 @@
.\" Title: xbps-repo
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
.\" Date: 05/03/2010
.\" Date: 18/11/2010
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "XBPS\-REPO" "8" "05/03/2010" "\ \&" "\ \&"
.TH "XBPS\-REPO" "8" "18/11/2010" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
@ -43,6 +43,11 @@ of
\fI/blah/cachedir\fR\&.
.RE
.PP
\fB\-d\fR
.RS 4
Enables extra debugging output to be shown to stderr.
.RE
.PP
\fB\-r\fR \fIrootdir\fR
.RS 4
Sets the

View File

@ -30,6 +30,7 @@
#include <errno.h>
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#include <xbps_api.h>
@ -131,6 +132,8 @@ main(int argc, char **argv)
if (argc < 1)
usage();
xbps_init(false);
plist = xbps_xasprintf("%s/%s/%s", root, XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL) {
fprintf(stderr,
@ -314,8 +317,6 @@ main(int argc, char **argv)
if (argc != 2)
usage();
xbps_fetch_set_cache_connection(0, 0);
for (i = 1; i < argc; i++) {
rv = xbps_fetch_file(argv[i], ".", false, "v");
if (rv == -1) {
@ -332,5 +333,7 @@ main(int argc, char **argv)
usage();
}
xbps_end();
exit(EXIT_SUCCESS);
}

View File

@ -31,10 +31,6 @@
#include <inttypes.h>
#include <prop/proplib.h>
#include <archive.h>
#include <archive_entry.h>
#include <sys/queue.h>
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
@ -44,7 +40,6 @@
# define __END_DECLS
#endif
/**
* @file include/xbps_api.h
* @brief XBPS Library API header
@ -56,7 +51,7 @@
* @def XBPS_RELVER
* Current library release date.
*/
#define XBPS_RELVER "20101023:0.6.1"
#define XBPS_RELVER "20101118"
/**
* @def XBPS_META_PATH
@ -122,6 +117,30 @@
__BEGIN_DECLS
void xbps_dbg_printf(const char *, ...);
void xbps_dbg_printf_append(const char *, ...);
/** @addtogroup initend */
/*@{*/
/**
* Initialize the XBPS library with the following steps:
*
* - Sets default cache connections for libfetch.
*
* - Initializes the debug printfs.
*
* @param[in] debug If true, debugging output will be shown to stderr.
*/
void xbps_init(bool debug);
/**
* Releases all resources used by the XBPS library.
*/
void xbps_end(void);
/*@}*/
/** @addtogroup configure */
/*@{*/
@ -134,7 +153,7 @@ __BEGIN_DECLS
* in unpacked state.
* @param[in] update Set it to true if this package is being updated.
*
* @return 0 on success, or an appropiate errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_configure_pkg(const char *pkgname,
const char *version,
@ -144,7 +163,7 @@ int xbps_configure_pkg(const char *pkgname,
/**
* Configure (or force reconfiguration of) all packages.
*
* @return 0 on success, or an appropiate errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_configure_all_pkgs(void);
@ -172,20 +191,6 @@ int xbps_cmpver(const char *pkg1, const char *pkg2);
/** @addtogroup download */
/*@{*/
/**
* @def XBPS_FETCH_CACHECONN
*
* Default (global) limit of cached connections used in libfetch.
*/
#define XBPS_FETCH_CACHECONN 6
/**
* @def XBPS_FETCH_CACHECONN_HOST
*
* Default (per host) limit of cached connections used in libfetch.
*/
#define XBPS_FETCH_CACHECONN_HOST 2
/**
* Download a file from a remote URL.
*
@ -203,73 +208,15 @@ int xbps_fetch_file(const char *uri,
bool refetch,
const char *flags);
/**
* Sets the libfetch's cache connection limits.
*
* @param[in] global Number of global cached connections, if set to 0
* by default it's set to XBPS_FETCH_CACHECONN.
* @param[in] per_host Number of per host cached connections, if set to 0
* by default it's set to XBPS_FETCH_CACHECONN_HOST.
*/
void xbps_fetch_set_cache_connection(int global, int per_host);
/**
* Destroys the libfetch's cache connection established.
*/
void xbps_fetch_unset_cache_connection(void);
/**
* Returns last error string reported by xbps_fetch_file().
*
* @return A string with the appropiate error message.
* @}
*/
const char *xbps_fetch_error_string(void);
/*@}*/
/** @addtogroup fexec */
/*@{*/
/**
* Forks and executes a command in the current working directory
* with an arbitrary number of arguments.
*
* @param[in] arg Arguments passed to execvp(3) when forked, the last
* argument must be NULL.
*
* @return 0 on success, -1 on error and errno set appropiately.
*/
int xbps_file_exec(const char *arg, ...);
/**
* Forks and executes a command in the current working directory
* with an arbitrary number of arguments.
*
* @param[in] arg Arguments passed to execvp(3) when forked, does not need
* to be terminated with a NULL argument.
*
* @return 0 on success, -1 on error and errno set appropiately.
*/
int xbps_file_exec_skipempty(const char *arg, ...);
/**
* Forks and executes a command with an arbitrary number of arguments
* in a specified path.
*
* If uid==0 and /bin/sh (relative to path) exists, a chroot(2) call
* will be done, otherwise chdir(2) to path.
*
* @param[in] path Destination path to chroot(2) or chdir(2).
* @param[in] arg Arguments passed to execvp(3) when forked, the last
* argument must be NULL.
*
* @return 0 on success, -1 on error and errno set appropiately.
*/
int xbps_file_chdir_exec(const char *path, const char *arg, ...);
/*@}*/
/* From lib/humanize_number.c */
#define HN_DECIMAL 0x01
#define HN_NOSPACE 0x02
@ -298,7 +245,7 @@ int xbps_mkpath(char *path, mode_t mode);
* Finds all package orphans currently installed.
*
* @return A proplib array of dictionaries with all orphans found,
* on error NULL is returned and errno set appropiately.
* on error NULL is returned and errno is set appropiately.
*/
prop_array_t xbps_find_orphan_packages(void);
@ -336,7 +283,7 @@ bool xbps_add_obj_to_dict(prop_dictionary_t dict,
* @param[in] array Proplib array to insert the object to.
* @param[in] obj Proplib object to be inserted.
*
* @return true on success, false otherwise and errno set appropiately.
* @return true on success, false otherwise and xbps_errno set appropiately.
*/
bool xbps_add_obj_to_array(prop_array_t array, prop_object_t obj);
@ -353,7 +300,7 @@ bool xbps_add_obj_to_array(prop_array_t array, prop_object_t obj);
* @param[in] arg Argument to be passed to the function callback.
*
* @return 0 on success (all objects were processed), otherwise an
* errno value on error.
* errno value is set appropiately.
*/
int xbps_callback_array_iter_in_dict(prop_dictionary_t dict,
const char *key,
@ -373,7 +320,7 @@ int xbps_callback_array_iter_in_dict(prop_dictionary_t dict,
* @param[in] arg Argument to be passed to the function callback.
*
* @return 0 on success (all objects were processed), otherwise an
* errno value on error.
* errno value is set appropiately.
*/
int xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict,
const char *key,
@ -447,8 +394,7 @@ prop_dictionary_t xbps_find_pkg_dict_installed(const char *str,
* @param[in] array The proplib array where to look for.
* @param[in] val The value of string to match.
*
* @return true on success, false otherwise and errno set appropiately
* if there was an unexpected error.
* @return true on success, false otherwise and errno is set appropiately.
*/
bool xbps_find_string_in_array(prop_array_t array, const char *val);
@ -485,9 +431,9 @@ prop_dictionary_t xbps_get_pkg_dict_from_metadata_plist(const char *pkgn,
* @param[in] pkgname Package name to look for.
* @param[in] plist Path to a plist file.
*
* @return 0 on success, or an errno value otherwise.
* @return true on success, false otherwise and errno is set appropiately.
*/
int xbps_remove_pkg_dict_from_file(const char *pkgname, const char *plist);
bool xbps_remove_pkg_dict_from_file(const char *pkgname, const char *plist);
/**
* Removes the package's proplib dictionary matching \a pkgname,
@ -497,11 +443,11 @@ int xbps_remove_pkg_dict_from_file(const char *pkgname, const char *plist);
* @param[in] key Key associated with the proplib array.
* @param[in] pkgname Package name to look for.
*
* @return 0 on success, or an errno value otherwise.
* @return true on success, false otherwise and errno is set appropiately.
*/
int xbps_remove_pkg_from_dict(prop_dictionary_t dict,
const char *key,
const char *pkgname);
bool xbps_remove_pkg_from_dict(prop_dictionary_t dict,
const char *key,
const char *pkgname);
/**
* Removes a string from a proplib's array.
@ -509,9 +455,9 @@ int xbps_remove_pkg_from_dict(prop_dictionary_t dict,
* @param[in] array Proplib array where to look for.
* @param[in] str String to match in the array.
*
* @return 0 on success, or an errno value otherwise.
* @return true on success, false otherwise and errno is set appropiately.
*/
int xbps_remove_string_from_array(prop_array_t array, const char *str);
bool xbps_remove_string_from_array(prop_array_t array, const char *str);
/*@}*/
@ -525,7 +471,7 @@ int xbps_remove_string_from_array(prop_array_t array, const char *str);
* @param[in] check_state Set it to true to check that package
* is in XBPS_PKG_STATE_CONFIG_FILES state.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_purge_pkg(const char *pkgname, bool check_state);
@ -533,7 +479,7 @@ int xbps_purge_pkg(const char *pkgname, bool check_state);
* Purge all installed packages. Packages that aren't in
* XBPS_PKG_STATE_CONFIG_FILES state will be ignored.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_purge_all_pkgs(void);
@ -550,7 +496,7 @@ int xbps_purge_all_pkgs(void);
* @param[in] automatic Set it to true to mark package that has been
* installed by another package, and not explicitly.
*
* @return 0 on success, an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_register_pkg(prop_dictionary_t pkg_dict, bool automatic);
@ -559,7 +505,7 @@ int xbps_register_pkg(prop_dictionary_t pkg_dict, bool automatic);
*
* @param[in] pkgname Package name.
*
* @return 0 on success, an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_unregister_pkg(const char *pkgname);
@ -569,19 +515,20 @@ int xbps_unregister_pkg(const char *pkgname);
/*@{*/
/**
* Initialize resources used by the registered packages database.
* Initialize resources used by the registered packages database dictionary
* and returns the internalized proplib dictionary.
*
* @note This function is reference counted, if the database has
* been initialized previously, the counter will be increased by one
* and dictionary stored in memory will be returned.
*
* @warning Don't forget to always use xbps_regpkgs_dictionary_release()
* @warning Don't forget to always use xbps_regpkgdb_dictionary_release()
* when its dictionary is no longer needed.
*
* @return A dictionary as shown above in the Detailed description
* graph on success, or NULL otherwise and errno is set appropiately.
*/
prop_dictionary_t xbps_regpkgs_dictionary_init(void);
prop_dictionary_t xbps_regpkgdb_dictionary_get(void);
/**
* Release resources used by the registered packages database.
@ -589,7 +536,7 @@ prop_dictionary_t xbps_regpkgs_dictionary_init(void);
* @note This function is reference counted, if the database
* is in use (its reference count number is not 0), won't be released.
*/
void xbps_regpkgs_dictionary_release(void);
void xbps_regpkgdb_dictionary_release(void);
/*@}*/
@ -604,7 +551,7 @@ void xbps_regpkgs_dictionary_release(void);
* @param[in] update If true, some steps will be skipped. See in the
* detailed description above for more information.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_remove_pkg(const char *pkgname, const char *version, bool update);
@ -618,7 +565,7 @@ int xbps_remove_pkg(const char *pkgname, const char *version, bool update);
* @param[in] key Key of the array object to match, valid values are:
* <b>files</b>, <b>dirs</b>, <b>links</b> and <b>conf_files</b>.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_remove_pkg_files(prop_dictionary_t dict, const char *key);
@ -632,7 +579,7 @@ int xbps_remove_pkg_files(prop_dictionary_t dict, const char *key);
*
* @param[in] uri URI pointing to the repository.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_repository_register(const char *uri);
@ -641,7 +588,7 @@ int xbps_repository_register(const char *uri);
*
* @param[in] uri URI pointing to the repository.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_repository_unregister(const char *uri);
@ -651,20 +598,18 @@ int xbps_repository_unregister(const char *uri);
/*@{*/
/**
* Finds a package by its name or by a pattern and enqueues it into
* Finds a package by a pattern and enqueues it into
* the transaction dictionary for future use. The first repository in
* the queue that matched the requirement wins.
* the pool that matched the pattern wins.
*
* @note The function name might be misleading, but is correct because
* if package is found, it will be marked as "going to be installed".
*
* @param pkg Package name or pattern to find.
* @param bypattern If true, a package pattern will be used in \a pkg.
* Otherwise \a pkg will be used as a package name.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_repository_install_pkg(const char *pkg, bool bypattern);
int xbps_repository_install_pkg(const char *pkgpattern);
/**
* Marks a package as "going to be updated" in the transaction dictionary.
@ -672,20 +617,17 @@ int xbps_repository_install_pkg(const char *pkg, bool bypattern);
* is available the package dictionary will be enqueued.
*
* @param pkgname The package name to update.
* @param instpkg Installed package dictionary, as returned by
* xbps_find_pkg_dict_installed().
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_repository_update_pkg(const char *pkgname,
prop_dictionary_t instpkg);
int xbps_repository_update_pkg(const char *pkgname);
/**
* Finds newer versions for all installed packages by looking at the
* repository pool. If a newer version exists, package will be enqueued
* into the transaction dictionary.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_repository_update_allpkgs(void);
@ -702,7 +644,7 @@ int xbps_repository_update_allpkgs(void);
* xbps_repository_update_pkg() functions are not called previously.
*
* @return The transaction dictionary to install/update/replace
* a package list. NULL on failure and errno set appropiately.
* a package list. NULL on failure and errno is set appropiately.
*/
prop_dictionary_t xbps_repository_get_transaction_dict(void);
@ -722,7 +664,7 @@ prop_dictionary_t xbps_repository_get_transaction_dict(void);
* @param[in] uri URI pointing to a repository.
*
* @return A string with the full path, NULL otherwise and errno
* set appropiately.
* is set appropiately.
*/
char *xbps_repository_get_path_from_pkg_dict(prop_dictionary_t d,
const char *uri);
@ -759,8 +701,9 @@ prop_dictionary_t xbps_repository_get_pkg_plist_dict(const char *pkgname,
* @return An internalized proplib dictionary, otherwise NULL and
* errno is set appropiately.
*/
prop_dictionary_t xbps_repository_get_pkg_plist_dict_from_url(const char *url,
const char *plistf);
prop_dictionary_t
xbps_repository_get_pkg_plist_dict_from_url(const char *url,
const char *plistf);
/*@}*/
@ -768,58 +711,39 @@ prop_dictionary_t xbps_repository_get_pkg_plist_dict_from_url(const char *url,
/*@{*/
/**
* @struct repository_pool xbps_api.h "xbps_api.h"
* @brief Repository pool structure
* @struct repository_pool_index xbps_api.h "xbps_api.h"
* @brief Repository pool dictionary structure
*
* Repository object structure registered in the global simple queue
* \a rp_queue. The simple queue must be initialized through
* xbps_repository_pool_init(), and released with
* xbps_repository_pool_release() when it's no longer needed.
* Repository index object structure registered in a private simple queue.
* The structure contains a dictionary and the URI associated with the
* registered repository index.
*/
struct repository_pool {
struct repository_pool_index {
/**
* @var rp_entries
* @var rpi_repod
*
* Structure that connects elements in the simple queue.
* For use with the SIMPLEQ macros.
* Internalized Proplib dictionary of the pkg-index plist file
* associated with repository.
*/
SIMPLEQ_ENTRY(repository_pool) rp_entries;
/**
* @var rp_repod
*
* Proplib dictionary associated with repository.
*/
prop_dictionary_t rp_repod;
prop_dictionary_t rpi_repod;
/**
* @var rp_uri
*
* URI string associated with repository.
*/
char *rp_uri;
char *rpi_uri;
};
/**
* @var rp_queue
* @brief Pointer to the head of global simple queue.
*
* A pointer to the head of the global simple queue to
* use after xbps_repository_pool_init() has been initialized
* successfully.
*/
SIMPLEQ_HEAD(repopool_queue, repository_pool);
struct repopool_queue rp_queue;
/**
* Initializes the repository pool by creating a global simple queue
* \a rp_queue with all registered repositories in the database.
* Initializes the repository pool.
*
* Once it's initialized, access to the repositories can be done
* by the global simple queue \a rp_queue and the \a repository_pool
* structure.
* through the \a xbps_repository_pool_foreach() function.
*
* @note This function is reference counted, don't forget to call
* xbps_repository_pool_release() when it's no longer needed.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_repository_pool_init(void);
@ -832,6 +756,24 @@ int xbps_repository_pool_init(void);
*/
void xbps_repository_pool_release(void);
/**
* Iterates over the repository pool and executes the \a fn function
* callback passing in the void * \a arg argument to it. The bool pointer
* argument can be used in the callbacks to stop immediately the loop if
* set to true, otherwise it will only be stopped if it returns a
* non-zero value.
*
* @param fn Function callback to execute for every repository registered in
* the pool.
* @param arg Opaque data passed in to the \a fn function callback for
* client data.
*
* @return 0 on success, otherwise an errno value.
*/
int xbps_repository_pool_foreach(
int (*fn)(struct repository_pool_index *, void *, bool *),
void *arg);
/*@}*/
/** @addtogroup reposync */
@ -886,7 +828,7 @@ typedef enum pkg_state {
* @param[in] pkgname Package name.
* @param[out] state Package state returned.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_get_pkg_state_installed(const char *pkgname, pkg_state_t *state);
@ -897,7 +839,7 @@ int xbps_get_pkg_state_installed(const char *pkgname, pkg_state_t *state);
* @param[in] dict Package dictionary.
* @param[out] state Package state returned.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_get_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t *state);
@ -907,7 +849,7 @@ int xbps_get_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t *state);
* @param[in] pkgname Package name.
* @param[in] state Package state to be set.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state);
@ -917,7 +859,7 @@ int xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state);
* @param[in] dict Package dictionary.
* @param[in] state Package state to be set.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_set_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t state);
@ -931,7 +873,7 @@ int xbps_set_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t state);
* @param[in] trans_pkg_dict Package proplib dictionary as stored in the
* \a packages array returned by the transaction dictionary.
*
* @return 0 on success, or an errno value otherwise.
* @return 0 on success, otherwise an errno value.
*/
int xbps_unpack_binary_pkg(prop_dictionary_t trans_pkg_dict);

View File

@ -31,6 +31,9 @@
# define NDEBUG
#endif
#include <assert.h>
#include <archive.h>
#include <archive_entry.h>
#include <xbps_api.h>
#define ARCHIVE_READ_BLOCKSIZE 10240
@ -60,17 +63,47 @@
#define HIDDEN
#endif
/**
* @def XBPS_FETCH_CACHECONN
*
* Default (global) limit of cached connections used in libfetch.
*/
#define XBPS_FETCH_CACHECONN 6
/**
* @def XBPS_FETCH_CACHECONN_HOST
*
* Default (per host) limit of cached connections used in libfetch.
*/
#define XBPS_FETCH_CACHECONN_HOST 2
__BEGIN_DECLS
/**
* @private
* Sets the libfetch's cache connection limits.
*
* @param[in] global Number of global cached connections, if set to 0
* by default it's set to XBPS_FETCH_CACHECONN.
* @param[in] per_host Number of per host cached connections, if set to 0
* by default it's set to XBPS_FETCH_CACHECONN_HOST.
*/
void HIDDEN xbps_fetch_set_cache_connection(int global, int per_host);
/**
* Destroys the libfetch's cache connection established.
*/
void HIDDEN xbps_fetch_unset_cache_connection(void);
/**
* @private
* From lib/package_config_files.c
*/
int HIDDEN xbps_config_file_from_archive_entry(prop_dictionary_t,
prop_dictionary_t,
struct archive_entry *,
const char *,
int *,
bool *);
/**
* @private
* From lib/plist.c
@ -119,6 +152,43 @@ int HIDDEN xbps_sort_pkg_deps(prop_dictionary_t);
*/
char HIDDEN *xbps_get_remote_repo_string(const char *);
/**
* Forks and executes a command in the current working directory
* with an arbitrary number of arguments.
*
* @param[in] arg Arguments passed to execvp(3) when forked, the last
* argument must be NULL.
*
* @return 0 on success, -1 on error and errno set appropiately.
*/
int HIDDEN xbps_file_exec(const char *arg, ...);
/**
* Forks and executes a command in the current working directory
* with an arbitrary number of arguments.
*
* @param[in] arg Arguments passed to execvp(3) when forked, does not need
* to be terminated with a NULL argument.
*
* @return 0 on success, -1 on error and errno set appropiately.
*/
int HIDDEN xbps_file_exec_skipempty(const char *arg, ...);
/**
* Forks and executes a command with an arbitrary number of arguments
* in a specified path.
*
* If uid==0 and /bin/sh (relative to path) exists, a chroot(2) call
* will be done, otherwise chdir(2) to path.
*
* @param[in] path Destination path to chroot(2) or chdir(2).
* @param[in] arg Arguments passed to execvp(3) when forked, the last
* argument must be NULL.
*
* @return 0 on success, -1 on error and errno set appropiately.
*/
int HIDDEN xbps_file_chdir_exec(const char *path, const char *arg, ...);
__END_DECLS
#endif /* !_XBPS_API_IMPL_H_ */

View File

@ -35,10 +35,10 @@ LIBFETCH_GEN = fetch/ftperr.h fetch/httperr.h
OBJS = package_configure.o package_config_files.o package_orphans.o
OBJS += package_remove.o package_remove_obsoletes.o package_state.o
OBJS += package_unpack.o package_requiredby.o package_register.o
OBJS += package_purge.o
OBJS += package_purge.o initend.o
OBJS += cmpver.o download.o fexec.o humanize_number.o plist.o
OBJS += sortdeps.o util.o pkgmatch.o mkpath.o
OBJS += regpkgs_dictionary.o repository.o repository_finddeps.o
OBJS += regpkgdb_dictionary.o repository.o repository_finddeps.o
OBJS += repository_findpkg.o repository_plist.o
OBJS += repository_pool.o repository_sync_index.o
OBJS += $(COMPAT_SRCS)

View File

@ -39,7 +39,9 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <xbps_api.h>
#include "xbps_api_impl.h"
#include "fetch.h"
/**
@ -191,7 +193,7 @@ xbps_fetch_error_string(void)
return fetchLastErrString;
}
void
void HIDDEN
xbps_fetch_set_cache_connection(int global, int per_host)
{
if (global == 0)
@ -202,7 +204,7 @@ xbps_fetch_set_cache_connection(int global, int per_host)
fetchConnectionCacheInit(global, per_host);
}
void
void HIDDEN
xbps_fetch_unset_cache_connection(void)
{
fetchConnectionCacheClose();

View File

@ -80,7 +80,7 @@ pfcexec(const char *path, const char *file, const char **argv)
_exit(127);
}
(void)execvp(file, __UNCONST(argv));
(void)execv(file, __UNCONST(argv));
_exit(127);
/* NOTREACHED */
case -1:
@ -138,7 +138,7 @@ vfcexec(const char *path, int skipempty, const char *arg, va_list ap)
return retval;
}
int
int HIDDEN
xbps_file_exec(const char *arg, ...)
{
va_list ap;
@ -151,7 +151,7 @@ xbps_file_exec(const char *arg, ...)
return result;
}
int
int HIDDEN
xbps_file_exec_skipempty(const char *arg, ...)
{
va_list ap;
@ -164,7 +164,7 @@ xbps_file_exec_skipempty(const char *arg, ...)
return result;
}
int
int HIDDEN
xbps_file_chdir_exec(const char *path, const char *arg, ...)
{
va_list ap;

78
lib/initend.c Normal file
View File

@ -0,0 +1,78 @@
/*-
* Copyright (c) 2010 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <xbps_api.h>
#include "xbps_api_impl.h"
static bool with_debug;
void
xbps_init(bool debug)
{
xbps_fetch_set_cache_connection(XBPS_FETCH_CACHECONN,
XBPS_FETCH_CACHECONN_HOST);
with_debug = debug;
}
void
xbps_end(void)
{
xbps_regpkgdb_dictionary_release();
xbps_repository_pool_release();
xbps_fetch_unset_cache_connection();
}
void
xbps_dbg_printf(const char *fmt, ...)
{
va_list ap;
if (!with_debug)
return;
va_start(ap, fmt);
fprintf(stderr, "[DEBUG] ");
vfprintf(stderr, fmt, ap);
va_end(ap);
}
void
xbps_dbg_printf_append(const char *fmt, ...)
{
va_list ap;
if (!with_debug)
return;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}

View File

@ -33,32 +33,82 @@
#include <xbps_api.h>
#include "xbps_api_impl.h"
/*
* Returns 1 if entry is a configuration file, 0 if don't or -1 on error.
*/
static int
entry_is_conf_file(prop_dictionary_t propsd, struct archive_entry *entry)
{
prop_object_t obj;
prop_object_iterator_t iter;
char *entrytmp, *cffile;
int rv = 0;
iter = xbps_get_array_iter_from_dict(propsd, "conf_files");
if (iter == NULL)
return -1;
entrytmp = xbps_xasprintf(".%s", archive_entry_pathname(entry));
if (entrytmp == NULL) {
rv = -1;
goto out;
}
while ((obj = prop_object_iterator_next(iter))) {
cffile = xbps_xasprintf(".%s",
prop_string_cstring_nocopy(obj));
if (cffile == NULL) {
rv = -1;
goto out;
}
if (strcmp(cffile, entrytmp) == 0) {
rv = 1;
free(cffile);
break;
}
free(cffile);
}
out:
prop_object_iterator_release(iter);
if (entrytmp)
free(entrytmp);
return rv;
}
int HIDDEN
xbps_config_file_from_archive_entry(prop_dictionary_t d,
xbps_config_file_from_archive_entry(prop_dictionary_t filesd,
prop_dictionary_t propsd,
struct archive_entry *entry,
const char *pkgname,
int *flags,
bool *skip)
{
prop_dictionary_t forigd;
prop_object_t obj, obj2;
prop_object_iterator_t iter, iter2;
const char *cffile, *sha256_new = NULL;
const char *pkgname, *cffile, *sha256_new = NULL;
char *buf, *sha256_cur = NULL, *sha256_orig = NULL;
int rv = 0;
bool install_new = false;
if (d == NULL)
return 0;
/*
* Check that current entry is really a configuration file.
*/
rv = entry_is_conf_file(propsd, entry);
if (rv == -1 || rv == 0)
return rv;
iter = xbps_get_array_iter_from_dict(d, "conf_files");
rv = 0;
iter = xbps_get_array_iter_from_dict(filesd, "conf_files");
if (iter == NULL)
return 0;
return EINVAL;
/*
* Get original hash for the file from current
* installed package.
*/
prop_dictionary_get_cstring_nocopy(propsd, "pkgname", &pkgname);
forigd = xbps_get_pkg_dict_from_metadata_plist(pkgname, XBPS_PKGFILES);
if (forigd == NULL) {
install_new = true;
@ -73,7 +123,7 @@ xbps_config_file_from_archive_entry(prop_dictionary_t d,
buf = xbps_xasprintf(".%s", cffile);
if (buf == NULL) {
prop_object_iterator_release(iter2);
rv = errno;
rv = ENOMEM;
goto out;
}
if (strcmp(archive_entry_pathname(entry), buf) == 0) {
@ -104,7 +154,7 @@ xbps_config_file_from_archive_entry(prop_dictionary_t d,
buf = xbps_xasprintf(".%s", cffile);
if (buf == NULL) {
prop_object_iterator_release(iter);
return errno;
return ENOMEM;
}
if (strcmp(archive_entry_pathname(entry), buf)) {
free(buf);
@ -180,7 +230,7 @@ xbps_config_file_from_archive_entry(prop_dictionary_t d,
(strcmp(sha256_orig, sha256_new))) {
buf = xbps_xasprintf(".%s.new", cffile);
if (buf == NULL) {
rv = errno;
rv = ENOMEM;
break;
}
printf("Keeping modified file %s.\n", cffile);

View File

@ -57,7 +57,7 @@ xbps_configure_all_pkgs(void)
const char *pkgname, *version;
int rv = 0;
if ((d = xbps_regpkgs_dictionary_init()) == NULL)
if ((d = xbps_regpkgdb_dictionary_get()) == NULL)
return errno;
iter = xbps_get_array_iter_from_dict(d, "packages");
@ -75,29 +75,30 @@ xbps_configure_all_pkgs(void)
}
prop_object_iterator_release(iter);
out:
xbps_regpkgs_dictionary_release();
xbps_regpkgdb_dictionary_release();
return rv;
}
int
xbps_configure_pkg(const char *pkgname, const char *version, bool check_state,
xbps_configure_pkg(const char *pkgname,
const char *version,
bool check_state,
bool update)
{
prop_dictionary_t pkgd;
const char *lver, *rootdir = xbps_get_rootdir();
char *buf;
int rv = 0, flags = 0;
int rv = 0, flags = xbps_get_flags();
pkg_state_t state = 0;
bool reconfigure = false;
assert(pkgname != NULL);
flags = xbps_get_flags();
if (check_state) {
if ((rv = xbps_get_pkg_state_installed(pkgname, &state)) != 0)
return rv;
rv = xbps_get_pkg_state_installed(pkgname, &state);
if (rv != 0)
return EINVAL;
if (state == XBPS_PKG_STATE_INSTALLED) {
if ((flags & XBPS_FLAG_FORCE) == 0)
@ -108,9 +109,6 @@ xbps_configure_pkg(const char *pkgname, const char *version, bool check_state,
return EINVAL;
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
if (pkgd == NULL)
return errno;
prop_dictionary_get_cstring_nocopy(pkgd, "version", &lver);
prop_object_release(pkgd);
} else {
@ -123,20 +121,28 @@ xbps_configure_pkg(const char *pkgname, const char *version, bool check_state,
buf = xbps_xasprintf(".%s/metadata/%s/INSTALL",
XBPS_META_PATH, pkgname);
if (buf == NULL)
return errno;
return ENOMEM;
if (chdir(rootdir) == -1) {
xbps_dbg_printf("%s: [configure] chdir to '%s' returned %s\n",
pkgname, rootdir, strerror(errno));
free(buf);
return errno;
return EINVAL;
}
rv = xbps_file_exec(buf, "post",
pkgname, lver, update ? "yes" : "no", NULL);
if (rv != 0 && errno != ENOENT) {
free(buf);
fprintf(stderr, "%s: post INSTALL action "
"returned: %s\n", pkgname, strerror(errno));
return rv;
if (access(buf, X_OK) == 0) {
if (xbps_file_exec(buf, "post",
pkgname, lver, update ? "yes" : "no", NULL) != 0) {
free(buf);
xbps_dbg_printf("%s: [configure] post INSTALL "
"action returned %s\n", pkgname, strerror(errno));
return errno;
}
} else {
if (errno != ENOENT) {
free(buf);
return errno;
}
}
free(buf);

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2009 Juan Romero Pardines.
* Copyright (c) 2009-2010 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -30,6 +30,8 @@
#include <errno.h>
#include <xbps_api.h>
#include "xbps_api_impl.h"
#include "queue.h"
/**
* @file lib/orphans.c
@ -147,7 +149,7 @@ cleanup(void)
prop_object_release(orphan->dict);
free(orphan);
}
xbps_regpkgs_dictionary_release();
xbps_regpkgdb_dictionary_release();
}
prop_array_t
@ -158,7 +160,7 @@ xbps_find_orphan_packages(void)
struct orphan_pkg *orphan;
int rv = 0;
if ((dict = xbps_regpkgs_dictionary_init()) == NULL)
if ((dict = xbps_regpkgdb_dictionary_get()) == NULL)
return NULL;
/*
* Find out all orphans by looking at the
@ -189,7 +191,7 @@ xbps_find_orphan_packages(void)
prop_object_release(orphan->dict);
free(orphan);
}
xbps_regpkgs_dictionary_release();
xbps_regpkgdb_dictionary_release();
return array;
}

View File

@ -54,16 +54,14 @@ remove_pkg_metadata(const char *pkgname)
struct dirent *dp;
DIR *dirp;
char *metadir, *path;
int flags = 0, rv = 0;
int rv = 0, flags = xbps_get_flags();
assert(pkgname != NULL);
flags = xbps_get_flags();
metadir = xbps_xasprintf("%s/%s/metadata/%s", xbps_get_rootdir(),
XBPS_META_PATH, pkgname);
if (metadir == NULL)
return errno;
return ENOMEM;
dirp = opendir(metadir);
if (dirp == NULL) {
@ -80,7 +78,7 @@ remove_pkg_metadata(const char *pkgname)
if (path == NULL) {
(void)closedir(dirp);
free(metadir);
return -1;
return ENOMEM;
}
if (unlink(path) == -1) {
@ -107,7 +105,7 @@ xbps_purge_all_pkgs(void)
const char *pkgname;
int rv = 0;
if ((d = xbps_regpkgs_dictionary_init()) == NULL)
if ((d = xbps_regpkgdb_dictionary_get()) == NULL)
return errno;
iter = xbps_get_array_iter_from_dict(d, "packages");
@ -123,7 +121,7 @@ xbps_purge_all_pkgs(void)
}
prop_object_iterator_release(iter);
out:
xbps_regpkgs_dictionary_release();
xbps_regpkgdb_dictionary_release();
return rv;
}
@ -132,16 +130,15 @@ int
xbps_purge_pkg(const char *pkgname, bool check_state)
{
prop_dictionary_t dict, pkgd;
int rv = 0, flags;
int rv = 0, flags = xbps_get_flags();
pkg_state_t state = 0;
assert(pkgname != NULL);
flags = xbps_get_flags();
/*
* Firstly let's get the pkg dictionary from regpkgdb.
*/
if ((dict = xbps_regpkgs_dictionary_init()) == NULL)
if ((dict = xbps_regpkgdb_dictionary_get()) == NULL)
return errno;
pkgd = xbps_find_pkg_in_dict_by_name(dict, "packages", pkgname);
@ -157,37 +154,47 @@ xbps_purge_pkg(const char *pkgname, bool check_state)
if ((rv = xbps_get_pkg_state_dictionary(pkgd, &state)) != 0)
goto out;
if (state != XBPS_PKG_STATE_CONFIG_FILES)
if (state != XBPS_PKG_STATE_CONFIG_FILES) {
rv = EINVAL;
goto out;
}
}
/*
* Remove unmodified configuration files.
* Remove unmodified configuration files and directories.
*/
dict = xbps_get_pkg_dict_from_metadata_plist(pkgname, XBPS_PKGFILES);
if (dict == NULL) {
rv = errno;
goto out;
}
if ((rv = xbps_remove_pkg_files(dict, "conf_files")) != 0) {
prop_object_release(dict);
goto out;
if (prop_dictionary_get(dict, "conf_files")) {
if ((rv = xbps_remove_pkg_files(dict, "conf_files")) != 0) {
prop_object_release(dict);
goto out;
}
if ((rv = xbps_remove_pkg_files(dict, "dirs")) != 0) {
prop_object_release(dict);
goto out;
}
}
prop_object_release(dict);
/*
* Remove metadata dir and unregister package.
*/
if ((rv = remove_pkg_metadata(pkgname)) == 0) {
if ((rv = xbps_unregister_pkg(pkgname)) == 0) {
if (flags & XBPS_FLAG_VERBOSE) {
printf("Package %s purged "
"successfully.\n", pkgname);
}
}
}
if ((rv = remove_pkg_metadata(pkgname)) != 0)
goto out;
if ((rv = xbps_unregister_pkg(pkgname)) != 0)
goto out;
if (flags & XBPS_FLAG_VERBOSE)
printf("Package %s purged successfully.\n", pkgname);
out:
xbps_regpkgs_dictionary_release();
xbps_regpkgdb_dictionary_release();
return rv;
}

View File

@ -53,7 +53,7 @@ xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic)
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL)
return EINVAL;
return ENOMEM;
prop_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(pkgrd, "version", &version);
@ -70,29 +70,24 @@ xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic)
"packages", pkgname);
if (pkgd == NULL) {
rv = errno;
DPRINTF(("%s: find_pkg_in_dict_by_name failed: %s\n",
__func__, strerror(rv)));
goto out;
}
if (!prop_dictionary_set_cstring_nocopy(pkgd,
"version", version)) {
prop_object_release(pkgd);
rv = errno;
DPRINTF(("%s: version obj not found!\n", __func__));
rv = EINVAL;
goto out;
}
if (!prop_dictionary_set_cstring_nocopy(pkgd,
"pkgver", pkgver)) {
prop_object_release(pkgd);
rv = errno;
DPRINTF(("%s: pkgver obj not found!\n", __func__));
rv = EINVAL;
goto out;
}
if (!prop_dictionary_set_cstring_nocopy(pkgd,
"short_desc", desc)) {
prop_object_release(pkgd);
rv = errno;
DPRINTF(("%s: short_desc obj not found!\n", __func__));
rv = EINVAL;
goto out;
}
if (!prop_dictionary_get_bool(pkgd,
@ -100,9 +95,7 @@ xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic)
if (!prop_dictionary_set_bool(pkgd,
"automatic-install", automatic)) {
prop_object_release(pkgd);
rv = errno;
DPRINTF(("%s: autoinst obj not found!\n",
__func__));
rv = EINVAL;
goto out;
}
}
@ -114,24 +107,19 @@ xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic)
array = prop_dictionary_get(dict, "packages");
if (array == NULL) {
prop_object_release(pkgd);
rv = ENOENT;
DPRINTF(("%s: packages array obj not found!\n",
__func__));
rv = EINVAL;
goto out;
}
rv = xbps_requiredby_pkg_add(array, pkgrd);
if (rv != 0) {
prop_object_release(pkgd);
DPRINTF(("%s: requiredby_pkg_add failed %d\n",
__func__, rv));
if ((rv = xbps_requiredby_pkg_add(array, pkgrd)) != 0)
goto out;
}
}
/*
* Write plist file to storage.
*/
if (!prop_dictionary_externalize_to_zfile(dict, plist))
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
rv = errno;
goto out;
}
} else {
free(plist);
return ENOENT;
@ -154,9 +142,11 @@ xbps_unregister_pkg(const char *pkgname)
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL)
return EINVAL;
return ENOMEM;
if (!xbps_remove_pkg_dict_from_file(pkgname, plist))
rv = errno;
rv = xbps_remove_pkg_dict_from_file(pkgname, plist);
free(plist);
return rv;

View File

@ -78,7 +78,7 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
prop_object_iterator_t iter;
prop_object_t obj;
const char *file, *sha256, *curobj = NULL;
char *dname = NULL, *path = NULL;
char *path = NULL;
int flags = 0, rv = 0;
assert(dict != NULL);
@ -87,12 +87,14 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
flags = xbps_get_flags();
array = prop_dictionary_get(dict, key);
if (array == NULL || prop_array_count(array) == 0)
if (array == NULL)
return EINVAL;
else if (prop_array_count(array) == 0)
return 0;
iter = xbps_get_array_iter_from_dict(dict, key);
if (iter == NULL)
return errno;
return ENOMEM;
if (strcmp(key, "files") == 0)
curobj = "file";
@ -107,9 +109,10 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
prop_dictionary_get_cstring_nocopy(obj, "file", &file);
path = xbps_xasprintf("%s/%s", xbps_get_rootdir(), file);
if (path == NULL) {
rv = errno;
rv = ENOMEM;
break;
}
if ((strcmp(key, "files") == 0) ||
(strcmp(key, "conf_files") == 0)) {
/*
@ -163,25 +166,6 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
if (flags & XBPS_FLAG_VERBOSE)
printf("Removed %s: %s\n", curobj, file);
}
/*
* When purging a package, also remove the directory where
* the conf_files are living on.
*/
if (strcmp(key, "conf_files") == 0) {
dname = dirname(path);
if (rmdir(dname) == -1) {
if (errno != ENOTEMPTY) {
fprintf(stderr,
"WARNING: can't remove %s %s "
"(%s)\n", curobj, file,
strerror(errno));
}
} else {
if (flags & XBPS_FLAG_VERBOSE)
printf("Removed empty directory: "
"%s\n", dname);
}
}
free(path);
}
prop_object_iterator_release(iter);
@ -195,6 +179,7 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
prop_dictionary_t dict;
char *buf;
int rv = 0;
bool rmfile_exists = false;
assert(pkgname != NULL);
assert(version != NULL);
@ -208,24 +193,31 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
buf = xbps_xasprintf(".%s/metadata/%s/REMOVE",
XBPS_META_PATH, pkgname);
if (buf == NULL)
return errno;
return ENOMEM;
if (chdir(xbps_get_rootdir()) == -1) {
free(buf);
return errno;
return EINVAL;
}
/*
* Run the pre remove action.
*/
rv = xbps_file_exec(buf, "pre", pkgname, version,
update ? "yes" : "no", NULL);
if (rv != 0 && errno != ENOENT) {
fprintf(stderr,
"%s: prerm action target error (%s)\n", pkgname,
strerror(errno));
free(buf);
return rv;
if (access(buf, X_OK) == 0) {
rmfile_exists = true;
if (xbps_file_exec(buf, "pre", pkgname, version,
update ? "yes" : "no", NULL) != 0) {
fprintf(stderr,
"%s: prerm action target error (%s)\n",
pkgname, strerror(errno));
free(buf);
return errno;
}
} else {
if (errno != ENOENT) {
free(buf);
return errno;
}
}
/*
@ -271,13 +263,13 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
* Execute the post REMOVE action if file exists and we aren't
* updating the package.
*/
rv = xbps_file_exec(buf, "post", pkgname, version, "no", NULL);
if (rv != 0 && errno != ENOENT) {
if (rmfile_exists &&
(xbps_file_exec(buf, "post", pkgname, version, "no", NULL) != 0)) {
fprintf(stderr,
"%s: postrm action target error (%s)\n", pkgname,
strerror(errno));
free(buf);
return rv;
return errno;
}
free(buf);
@ -293,5 +285,6 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
rv = xbps_set_pkg_state_installed(pkgname,
XBPS_PKG_STATE_CONFIG_FILES);
return rv;
}

View File

@ -39,15 +39,15 @@
int HIDDEN
xbps_remove_obsoletes(prop_dictionary_t oldd, prop_dictionary_t newd)
{
prop_object_iterator_t iter, iter2 = NULL;
prop_object_t obj, obj2 = NULL;
prop_string_t oldstr = NULL, newstr = NULL;
prop_object_iterator_t iter, iter2;
prop_object_t obj, obj2;
prop_string_t oldstr, newstr;
struct stat st;
const char *array_str = "files";
const char *oldhash = NULL;
char *dname = NULL, *file = NULL;
const char *oldhash;
char *file;
int rv = 0;
bool found, dolinks = false;
bool found, dodirs = false, dolinks = false;
again:
iter = xbps_get_array_iter_from_dict(oldd, array_str);
@ -59,7 +59,7 @@ again:
return errno;
}
/*
* Check for obsolete files, i.e files/links available in
* Check for obsolete files, i.e files/links/dirs available in
* the old package list not found in new package list.
*/
while ((obj = prop_object_iterator_next(iter))) {
@ -89,7 +89,7 @@ again:
rv = 0;
continue;
}
} else {
} else if (strcmp(array_str, "links") == 0) {
/*
* Only remove dangling symlinks.
*/
@ -123,32 +123,18 @@ again:
}
/*
* Obsolete file found, remove it.
* Obsolete obj found, remove it.
*/
if (remove(file) == -1) {
fprintf(stderr,
"WARNING: couldn't remove obsolete %s: %s\n",
dolinks ? "link" : "file",
prop_string_cstring_nocopy(oldstr));
"WARNING: couldn't remove obsolete obj: %s (%s)\n",
prop_string_cstring_nocopy(oldstr),
strerror(errno));
free(file);
continue;
}
printf("Removed obsolete %s: %s\n",
dolinks ? "link" : "file",
printf("Removed obsolete obj: %s\n",
prop_string_cstring_nocopy(oldstr));
/*
* Try to remove the directory where the obsole file or link
* was currently living on.
*/
dname = dirname(file);
if (rmdir(dname) == -1) {
if (errno != 0 && errno != EEXIST && errno != ENOTEMPTY)
fprintf(stderr,
"WARNING: couldn't remove obsolete "
"directory %s: %s\n", dname,
strerror(errno));
}
free(file);
}
if (!dolinks) {
/*
@ -161,6 +147,17 @@ again:
iter2 = NULL;
goto again;
}
if (!dodirs) {
/*
* Look for obsolete dirs.
*/
dodirs = true;
array_str = "dirs";
prop_object_iterator_release(iter2);
prop_object_iterator_release(iter);
iter2 = NULL;
goto again;
}
out:
prop_object_iterator_release(iter2);

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2009 Juan Romero Pardines.
* Copyright (c) 2009-2010 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -54,7 +54,7 @@ add_pkg_into_reqby(prop_dictionary_t pkgd, const char *reqname)
if (reqstr == NULL) {
if (alloc)
prop_object_release(array);
return errno;
return ENOMEM;
}
if (!xbps_add_obj_to_array(array, reqstr)) {
@ -132,20 +132,27 @@ xbps_requiredby_pkg_remove(const char *pkgname)
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL)
return EINVAL;
return ENOMEM;
if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) {
free(plist);
xbps_dbg_printf("[reqby-rm] cannot internalize "
"regpkgdb plist for '%s': %s\n", pkgname, strerror(errno));
return errno;
}
rv = xbps_callback_array_iter_in_dict(dict, "packages",
remove_pkg_from_reqby, __UNCONST(pkgname));
if (rv == 0) {
if (!prop_dictionary_externalize_to_zfile(dict, plist))
rv = errno;
if (rv != 0)
goto out;
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
xbps_dbg_printf("[reqby-rm] cannot externalize plist for "
"'%s': %s\n", pkgname, strerror(errno));
rv = errno;
}
out:
prop_object_release(dict);
free(plist);
@ -174,7 +181,7 @@ xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg)
while ((obj = prop_object_iterator_next(iter)) != NULL) {
str = prop_string_cstring_nocopy(obj);
if (str == NULL) {
rv = errno;
rv = EINVAL;
goto out;
}
rdepname = xbps_get_pkgpattern_name(str);
@ -182,10 +189,11 @@ xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg)
rv = EINVAL;
goto out;
}
iter2 = prop_array_iterator(regar);
if (iter2 == NULL) {
free(rdepname);
rv = ENOMEM;
free(rdepname);
goto out;
}

View File

@ -66,11 +66,11 @@ set_new_state(prop_dictionary_t dict, pkg_state_t state)
}
if (!prop_dictionary_set_cstring_nocopy(dict, "state", state_str))
return -1;
return EINVAL;
if (prop_dictionary_get_cstring_nocopy(dict, "pkgname", &pkgname)) {
DPRINTF(("%s: changed pkg state to '%s'.\n",
pkgname, state_str));
xbps_dbg_printf("%s: changed pkg state to '%s'\n",
pkgname, state_str);
}
return 0;
@ -153,30 +153,31 @@ xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state)
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL)
return EINVAL;
return ENOMEM;
if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) {
dict = prop_dictionary_create();
if (dict == NULL) {
rv = errno;
rv = ENOMEM;
goto out;
}
array = prop_array_create();
if (array == NULL) {
rv = errno;
rv = ENOMEM;
goto out;
}
pkgd = prop_dictionary_create();
if (pkgd == NULL) {
rv = ENOMEM;
prop_object_release(array);
rv = errno;
goto out;
}
if (!prop_dictionary_set_cstring_nocopy(pkgd, "pkgname",
pkgname)) {
rv = EINVAL;
prop_object_release(array);
prop_object_release(pkgd);
rv = errno;
goto out;
}
if ((rv = set_new_state(pkgd, state)) != 0) {
@ -185,14 +186,14 @@ xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state)
goto out;
}
if (!xbps_add_obj_to_array(array, pkgd)) {
rv = EINVAL;
prop_object_release(array);
prop_object_release(pkgd);
rv = errno;
goto out;
}
if (!xbps_add_obj_to_dict(dict, array, "packages")) {
rv = EINVAL;
prop_object_release(array);
rv = errno;
goto out;
}
@ -204,20 +205,21 @@ xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state)
rv = errno;
goto out;
}
newpkg = true;
pkgd = prop_dictionary_create();
if (!prop_dictionary_set_cstring_nocopy(pkgd,
"pkgname", pkgname)) {
rv = EINVAL;
prop_object_release(pkgd);
rv = errno;
goto out;
}
}
array = prop_dictionary_get(dict, "packages");
if (array == NULL) {
rv = EINVAL;
if (newpkg)
prop_object_release(pkgd);
rv = errno;
goto out;
}
if ((rv = set_new_state(pkgd, state)) != 0) {
@ -226,14 +228,17 @@ xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state)
goto out;
}
if (newpkg && !xbps_add_obj_to_array(array, pkgd)) {
rv = EINVAL;
prop_object_release(pkgd);
rv = errno;
goto out;
}
}
if (!prop_dictionary_externalize_to_zfile(dict, plist))
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
rv = errno;
xbps_dbg_printf("[pkgstate] cannot write plist '%s': %s\n",
plist, strerror(errno));
}
out:
if (dict)

View File

@ -91,10 +91,12 @@ set_extract_flags(int *flags, bool update)
* the consumer.
*/
static int
unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
const char *pkgname, const char *version)
unpack_archive_fini(struct archive *ar,
prop_dictionary_t pkg,
const char *pkgname,
const char *version)
{
prop_dictionary_t filesd = NULL, old_filesd = NULL;
prop_dictionary_t propsd, filesd, old_filesd;
struct archive_entry *entry;
size_t entry_idx = 0;
const char *rootdir, *entry_str, *transact;
@ -128,9 +130,10 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
buf = xbps_xasprintf(".%s/metadata/%s/INSTALL",
XBPS_META_PATH, pkgname);
if (buf == NULL)
return errno;
return ENOMEM;
if (unlink(buf) == -1) {
if (errno != ENOENT) {
if (errno && errno != ENOENT) {
free(buf);
return errno;
}
@ -139,9 +142,10 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
buf = xbps_xasprintf(".%s/metadata/%s/REMOVE",
XBPS_META_PATH, pkgname);
if (buf == NULL)
return errno;
return ENOMEM;
if (unlink(buf) == -1) {
if (errno != ENOENT) {
if (errno && errno != ENOENT) {
free(buf);
return errno;
}
@ -161,16 +165,18 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
if (strcmp("./INSTALL", entry_str) == 0) {
buf = xbps_xasprintf(".%s/metadata/%s/INSTALL",
XBPS_META_PATH, pkgname);
if (buf == NULL)
return errno;
if (buf == NULL) {
rv = ENOMEM;
goto out;
}
archive_entry_set_pathname(entry, buf);
archive_entry_set_mode(entry, 0750);
archive_entry_set_perm(entry, 0750);
if (archive_read_extract(ar, entry, lflags) != 0) {
if ((rv = archive_errno(ar)) != EEXIST) {
free(buf);
return rv;
goto out;
}
}
@ -181,7 +187,7 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
fprintf(stderr,
"%s: preinst action target error %s\n",
pkgname, strerror(errno));
return rv;
goto out;
}
/* Pass to the next entry if successful */
free(buf);
@ -194,13 +200,18 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
} else if (strcmp("./REMOVE", entry_str) == 0) {
buf = xbps_xasprintf(".%s/metadata/%s/REMOVE",
XBPS_META_PATH, pkgname);
if (buf == NULL)
return errno;
if (buf == NULL) {
rv = ENOMEM;
goto out;
}
archive_entry_set_pathname(entry, buf);
free(buf);
archive_entry_set_mode(entry, 0750);
if (archive_read_extract(ar, entry, lflags) != 0)
return archive_errno(ar);
archive_entry_set_perm(entry, 0750);
if (archive_read_extract(ar, entry, lflags) != 0) {
if ((rv = archive_errno(ar)) != EEXIST)
goto out;
}
/* Pass to next entry if successful */
entry_idx++;
@ -213,8 +224,10 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
* all files are extracted.
*/
filesd = xbps_read_dict_from_archive_entry(ar, entry);
if (filesd == NULL)
return errno;
if (filesd == NULL) {
rv = errno;
goto out;
}
/* Pass to next entry */
files_plist_found = true;
@ -222,36 +235,30 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
continue;
} else if (strcmp("./props.plist", entry_str) == 0) {
buf = xbps_xasprintf(".%s/metadata/%s/props.plist",
XBPS_META_PATH, pkgname);
if (buf == NULL)
return errno;
buf = xbps_xasprintf(".%s/metadata/%s/%s",
XBPS_META_PATH, pkgname, XBPS_PKGPROPS);
if (buf == NULL) {
rv = ENOMEM;
goto out;
}
archive_entry_set_pathname(entry, buf);
free(buf);
if (archive_read_extract(ar, entry, lflags) != 0)
return archive_errno(ar);
propsd =
xbps_get_pkg_dict_from_metadata_plist(pkgname,
XBPS_PKGPROPS);
if (propsd == NULL) {
rv = errno;
goto out;
}
/* Pass to next entry if successful */
props_plist_found = true;
entry_idx++;
continue;
} else {
/*
* Handle configuration files.
*/
if ((rv = xbps_config_file_from_archive_entry(filesd,
entry, pkgname, &lflags, &skip_entry)) != 0) {
prop_object_release(filesd);
return rv;
}
if (skip_entry) {
archive_read_data_skip(ar);
skip_entry = false;
entry_idx++;
continue;
}
}
/*
@ -266,12 +273,31 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
* This is not an XBPS binary package.
*/
if (entry_idx >= 3)
return ENOPKG;
return ENODEV;
entry_idx++;
continue;
}
/*
* Handle configuration files. Check if current entry is
* a configuration file and take action if required. Skip
* packages that don't have the "conf_files" array in
* the XBPS_PKGPROPS dictionary.
*/
if (prop_dictionary_get(propsd, "conf_files")) {
if ((rv = xbps_config_file_from_archive_entry(filesd,
propsd, entry, &lflags, &skip_entry)) != 0) {
prop_object_release(filesd);
goto out;
}
if (skip_entry) {
archive_read_data_skip(ar);
skip_entry = false;
continue;
}
}
/*
* Account for the following scenario (real example):
*
@ -303,10 +329,10 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
*/
if (archive_read_extract(ar, entry, lflags) != 0) {
rv = archive_errno(ar);
if (rv != EEXIST) {
if (rv && rv != EEXIST) {
fprintf(stderr, "ERROR: %s...exiting!\n",
archive_error_string(ar));
return rv;;
goto out;
} else if (rv == EEXIST) {
if (flags & XBPS_FLAG_VERBOSE) {
fprintf(stderr,
@ -322,33 +348,33 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
}
if ((rv = archive_errno(ar)) == 0) {
buf = xbps_xasprintf(".%s/metadata/%s/files.plist",
XBPS_META_PATH, pkgname);
buf = xbps_xasprintf(".%s/metadata/%s/%s",
XBPS_META_PATH, pkgname, XBPS_PKGFILES);
if (buf == NULL) {
prop_object_release(filesd);
return errno;
return ENOMEM;
}
/*
* Check if files.plist exists and pkg is NOT marked as
* preserve, in that case we need to check for obsolete files
* and remove them if necessary.
*/
if (!preserve && (access(buf, R_OK) == 0)) {
if (!preserve) {
old_filesd =
prop_dictionary_internalize_from_zfile(buf);
if (old_filesd == NULL) {
if (old_filesd) {
rv = xbps_remove_obsoletes(old_filesd, filesd);
if (rv != 0) {
prop_object_release(old_filesd);
prop_object_release(filesd);
free(buf);
return rv;
}
} else if (errno && errno != ENOENT) {
prop_object_release(filesd);
free(buf);
return errno;
}
rv = xbps_remove_obsoletes(old_filesd, filesd);
if (rv != 0) {
prop_object_release(old_filesd);
prop_object_release(filesd);
free(buf);
return rv;
}
prop_object_release(old_filesd);
}
/*
* Now that all files were successfully unpacked, we
@ -362,8 +388,12 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
}
free(buf);
}
out:
if (filesd)
prop_object_release(filesd);
if (propsd)
prop_object_release(propsd);
return rv;
}
@ -388,6 +418,8 @@ xbps_unpack_binary_pkg(prop_dictionary_t pkg)
if ((pkg_fd = open(binfile, O_RDONLY)) == -1) {
rv = errno;
xbps_dbg_printf("cannot open '%s' for unpacking %s\n",
binfile, strerror(errno));
goto out;
}
@ -403,9 +435,11 @@ xbps_unpack_binary_pkg(prop_dictionary_t pkg)
archive_read_support_compression_all(ar);
archive_read_support_format_tar(ar);
if ((rv = archive_read_open_fd(ar, pkg_fd,
ARCHIVE_READ_BLOCKSIZE)) != 0)
if (archive_read_open_fd(ar, pkg_fd,
ARCHIVE_READ_BLOCKSIZE) != 0) {
rv = errno;
goto out;
}
if ((rv = unpack_archive_fini(ar, pkg, pkgname, version)) != 0)
goto out;

View File

@ -51,6 +51,7 @@ xbps_add_obj_to_dict(prop_dictionary_t dict, prop_object_t obj,
if (!prop_dictionary_set(dict, key, obj)) {
prop_object_release(dict);
errno = EINVAL;
return false;
}
@ -66,6 +67,7 @@ xbps_add_obj_to_array(prop_array_t array, prop_object_t obj)
if (!prop_array_add(array, obj)) {
prop_object_release(array);
errno = EINVAL;
return false;
}
@ -98,6 +100,7 @@ xbps_callback_array_iter_in_dict(prop_dictionary_t dict, const char *key,
}
prop_object_iterator_release(iter);
return rv;
}
@ -116,8 +119,10 @@ xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict,
assert(fn != NULL);
array = prop_dictionary_get(dict, key);
if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY)
if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY) {
xbps_dbg_printf("invalid key '%s' for dictionary", key);
return EINVAL;
}
if ((cnt = prop_array_count(array)) == 0)
return 0;
@ -141,8 +146,11 @@ xbps_find_pkg_from_plist(const char *plist, const char *pkgname)
assert(pkgname != NULL);
dict = prop_dictionary_internalize_from_zfile(plist);
if (dict == NULL)
if (dict == NULL) {
xbps_dbg_printf("cannot internalize %s for pkg %s: %s",
plist, pkgname, strerror(errno));
return NULL;
}
obj = xbps_find_pkg_in_dict_by_name(dict, "packages", pkgname);
if (obj == NULL) {
@ -162,7 +170,7 @@ xbps_find_pkg_dict_installed(const char *str, bool bypattern)
prop_dictionary_t d, pkgd, rpkgd = NULL;
pkg_state_t state = 0;
if ((d = xbps_regpkgs_dictionary_init()) == NULL)
if ((d = xbps_regpkgdb_dictionary_get()) == NULL)
return NULL;
if (bypattern)
@ -182,12 +190,14 @@ xbps_find_pkg_dict_installed(const char *str, bool bypattern)
break;
case XBPS_PKG_STATE_CONFIG_FILES:
errno = ENOENT;
xbps_dbg_printf("'%s' installed but its state is "
"config-files\n",str);
break;
default:
break;
}
out:
xbps_regpkgs_dictionary_release();
xbps_regpkgdb_dictionary_release();
return rpkgd;
}
@ -213,8 +223,10 @@ xbps_find_pkg_in_dict_by_name(prop_dictionary_t dict,
break;
}
prop_object_iterator_release(iter);
if (obj == NULL)
if (obj == NULL) {
errno = ENOENT;
return NULL;
}
return obj;
}
@ -241,8 +253,10 @@ xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t dict,
break;
}
prop_object_iterator_release(iter);
if (obj == NULL)
if (obj == NULL) {
errno = ENOENT;
return NULL;
}
return obj;
}
@ -270,6 +284,7 @@ xbps_find_string_in_array(prop_array_t array, const char *val)
}
prop_object_iterator_release(iter);
return false;
}
@ -282,8 +297,10 @@ xbps_get_array_iter_from_dict(prop_dictionary_t dict, const char *key)
assert(key != NULL);
array = prop_dictionary_get(dict, key);
if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY)
if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY) {
errno = EINVAL;
return NULL;
}
return prop_array_iterator(array);
}
@ -304,11 +321,16 @@ xbps_get_pkg_dict_from_metadata_plist(const char *pkgn, const char *plist)
plistd = prop_dictionary_internalize_from_zfile(plistf);
free(plistf);
if (plistd == NULL) {
xbps_dbg_printf("cannot read from plist file %s for %s: %s\n",
plist, pkgn, strerror(errno));
return NULL;
}
return plistd;
}
int
bool
xbps_remove_string_from_array(prop_array_t array, const char *str)
{
prop_object_t obj;
@ -321,7 +343,7 @@ xbps_remove_string_from_array(prop_array_t array, const char *str)
iter = prop_array_iterator(array);
if (iter == NULL)
return errno;
return false;
while ((obj = prop_object_iterator_next(iter)) != NULL) {
if (prop_string_equals_cstring(obj, str)) {
@ -331,16 +353,19 @@ xbps_remove_string_from_array(prop_array_t array, const char *str)
idx++;
}
prop_object_iterator_release(iter);
if (found == false)
return ENOENT;
if (!found) {
errno = ENOENT;
return false;
}
prop_array_remove(array, idx);
return 0;
return true;
}
int
xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key,
bool
xbps_remove_pkg_from_dict(prop_dictionary_t dict,
const char *key,
const char *pkgname)
{
prop_array_t array;
@ -355,12 +380,16 @@ xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key,
assert(pkgname != NULL);
array = prop_dictionary_get(dict, key);
if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY)
return EINVAL;
if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY) {
errno = EINVAL;
xbps_dbg_printf("invalid array type for key: %s pkgname: %s\n",
key, pkgname);
return false;
}
iter = prop_array_iterator(array);
if (iter == NULL)
return errno;
return false;
/* Iterate over the array of dictionaries to find its index. */
while ((obj = prop_object_iterator_next(iter))) {
@ -372,41 +401,46 @@ xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key,
i++;
}
prop_object_iterator_release(iter);
if (found == true)
if (found) {
prop_array_remove(array, i);
else
return ENOENT;
return true;
}
return 0;
errno = ENOENT;
return false;
}
int
bool
xbps_remove_pkg_dict_from_file(const char *pkg, const char *plist)
{
prop_dictionary_t pdict;
int rv = 0;
assert(pkg != NULL);
assert(plist != NULL);
pdict = prop_dictionary_internalize_from_zfile(plist);
if (pdict == NULL)
return errno;
if (pdict == NULL) {
xbps_dbg_printf("'%s' cannot read from file %s: %s\n",
pkg, plist, strerror(errno));
return false;
}
rv = xbps_remove_pkg_from_dict(pdict, "packages", pkg);
if (rv != 0) {
if (!xbps_remove_pkg_from_dict(pdict, "packages", pkg)) {
prop_object_release(pdict);
return rv;
return false;
}
if (!prop_dictionary_externalize_to_zfile(pdict, plist)) {
xbps_dbg_printf("'%s' cannot write plist file %s: %s\n",
pkg, plist, strerror(errno));
prop_object_release(pdict);
return errno;
return false;
}
prop_object_release(pdict);
return 0;
return true;
}
/*

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2008-2009 Juan Romero Pardines.
* Copyright (c) 2008-2010 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -33,7 +33,7 @@
#include "xbps_api_impl.h"
/**
* @file lib/regpkgs_dictionary.c
* @file lib/regpkgdb_dictionary.c
* @brief Package register database routines
* @defgroup regpkgdb Package register database functions
*
@ -57,43 +57,45 @@
* dictionary.
*/
static prop_dictionary_t regpkgs_dict;
static size_t regpkgs_refcount;
static bool regpkgs_initialized;
static prop_dictionary_t regpkgdb_dict;
static size_t regpkgdb_refcount;
static bool regpkgdb_initialized;
prop_dictionary_t
xbps_regpkgs_dictionary_init(void)
xbps_regpkgdb_dictionary_get(void)
{
char *plist;
if (regpkgs_initialized == false) {
if (regpkgdb_initialized == false) {
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL)
return NULL;
regpkgs_dict = prop_dictionary_internalize_from_zfile(plist);
if (regpkgs_dict == NULL) {
regpkgdb_dict = prop_dictionary_internalize_from_zfile(plist);
if (regpkgdb_dict == NULL) {
free(plist);
xbps_dbg_printf("[regpkgdb] cannot internalize "
"regpkgdb_dict %s\n", strerror(errno));
return NULL;
}
free(plist);
regpkgs_initialized = true;
DPRINTF(("%s: initialized ok.\n", __func__));
regpkgdb_initialized = true;
xbps_dbg_printf("%s: initialized ok.\n", __func__);
}
regpkgs_refcount++;
regpkgdb_refcount++;
return regpkgs_dict;
return regpkgdb_dict;
}
void
xbps_regpkgs_dictionary_release(void)
xbps_regpkgdb_dictionary_release(void)
{
if (--regpkgs_refcount > 0)
if (--regpkgdb_refcount > 0)
return;
prop_object_release(regpkgs_dict);
regpkgs_dict = NULL;
regpkgs_initialized = false;
DPRINTF(("%s: released ok.\n", __func__));
prop_object_release(regpkgdb_dict);
regpkgdb_dict = NULL;
regpkgdb_initialized = false;
xbps_dbg_printf("%s: released ok.\n", __func__);
}

View File

@ -69,6 +69,7 @@ xbps_repository_register(const char *uri)
rv = errno;
goto out;
}
if (!prop_array_set_cstring_nocopy(array, 0, uri)) {
rv = errno;
goto out;
@ -78,6 +79,7 @@ xbps_repository_register(const char *uri)
rv = errno;
goto out;
}
xbps_dbg_printf("Added repository into plist: %s\n", uri);
} else {
/* Append into the array, the plist file exists. */
array = prop_dictionary_get(dict, "repository-list");
@ -97,14 +99,16 @@ xbps_repository_register(const char *uri)
rv = errno;
goto out;
}
xbps_dbg_printf("Added repository into plist: %s\n", uri);
}
/* Write dictionary into plist file. */
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
rv = errno;
xbps_dbg_printf("%s: cannot externalize '%s' for '%s': %s\n",
__func__, plist, uri, strerror(errno));
if (obj)
prop_object_release(obj);
rv = errno;
goto out;
}
out:
@ -142,14 +146,18 @@ xbps_repository_unregister(const char *uri)
goto out;
}
if ((rv = xbps_remove_string_from_array(array, uri)) == 0) {
/* Update plist file. */
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
rv = errno;
goto out;
}
if (!xbps_remove_string_from_array(array, uri)) {
rv = errno;
goto out;
}
/* Update plist file. */
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
rv = errno;
goto out;
}
xbps_dbg_printf("Removed repository from plist: %s\n", uri);
/*
* If it's a remote repository, also remove the stored XBPS_PKGINDEX
* file and its directory.
@ -157,26 +165,27 @@ xbps_repository_unregister(const char *uri)
if (xbps_check_is_repo_string_remote(uri)) {
pkgindex = xbps_get_pkg_index_plist(uri);
if (pkgindex == NULL) {
rv = EINVAL;
rv = errno;
goto out;
}
if (unlink(pkgindex) == -1) {
rv = errno;
if (errno == ENOENT) {
free(pkgindex);
goto out;
}
fprintf(stderr, "E: cannot remove pkgindex file at "
"%s: %s\n", pkgindex, strerror(errno));
xbps_dbg_printf("%s cannot remove pkgindex file at "
"%s: %s\n", __func__, pkgindex, strerror(errno));
free(pkgindex);
rv = errno;
goto out;
}
pkgindexdir = dirname(pkgindex);
if (rmdir(pkgindexdir) == -1) {
fprintf(stderr, "E: cannot remove pkgindex dir at "
"%s: %s\n", pkgindexdir, strerror(errno));
free(pkgindex);
rv = errno;
xbps_dbg_printf("%s: cannot remove pkgindex dir at "
"%s: %s\n", __func__, pkgindexdir, strerror(errno));
free(pkgindex);
goto out;
}
free(pkgindex);

View File

@ -38,7 +38,7 @@ store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict,
prop_dictionary_t dict;
prop_array_t array;
const char *pkgname, *pkgver;
int flags = xbps_get_flags(), rv = 0;
int rv = 0;
pkg_state_t state = 0;
assert(trans_dict != NULL);
@ -63,17 +63,18 @@ store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict,
* Always set "not-installed" package state. Will be overwritten
* to its correct state later.
*/
xbps_dbg_printf_append("\n");
rv = xbps_set_pkg_state_dictionary(dict, XBPS_PKG_STATE_NOT_INSTALLED);
if (rv != 0) {
prop_object_release(dict);
return rv;
}
/*
* Overwrite package state in dictionary if it was unpacked
* previously.
*/
rv = xbps_get_pkg_state_installed(pkgname, &state);
if (rv == 0) {
if ((rv = xbps_get_pkg_state_installed(pkgname, &state)) == 0) {
if ((rv = xbps_set_pkg_state_dictionary(dict, state)) != 0) {
prop_object_release(dict);
return rv;
@ -97,9 +98,8 @@ store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict,
prop_object_release(dict);
return EINVAL;
}
if (flags & XBPS_FLAG_VERBOSE)
printf("\n Added package '%s' into the transaction (%s).\n",
pkgver, repoloc);
xbps_dbg_printf("Added package '%s' into "
"the transaction (%s).\n", pkgver, repoloc);
return 0;
}
@ -152,8 +152,8 @@ add_missing_reqdep(prop_dictionary_t trans_dict, const char *reqpkg)
* if new dependency version is greater than current
* one, store it.
*/
DPRINTF(("Missing pkgdep name matched, curver: %s "
"newver: %s\n", curver, pkgver));
xbps_dbg_printf("Missing pkgdep name matched, "
"curver: %s newver: %s\n", curver, pkgver);
if (xbps_cmpver(curver, pkgver) <= 0) {
add_pkgdep = false;
free(curpkgnamedep);
@ -250,7 +250,7 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
pkg_state_t state = 0;
const char *reqpkg, *reqvers, *pkg_queued, *repo_pkgver;
char *pkgname;
int flags = xbps_get_flags(), rv = 0;
int rv = 0;
iter = prop_array_iterator(pkg_rdeps_array);
if (iter == NULL)
@ -266,26 +266,25 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
rv = EINVAL;
break;
}
if (flags & XBPS_FLAG_VERBOSE) {
if (originpkgn)
printf(" %s requires dependency '%s' "
"[direct]: ", originpkgn, reqpkg);
else
printf(" requires dependency '%s' "
"[indirect]: ", reqpkg);
}
if (originpkgn)
xbps_dbg_printf(" %s requires dependency '%s' "
"[direct]: ", originpkgn, reqpkg);
else
xbps_dbg_printf(" requires dependency '%s' "
"[indirect]: ", reqpkg);
/*
* Check if required dep is satisfied and installed.
*/
rv = xbps_check_is_installed_pkg(reqpkg);
if (rv == -1) {
/* There was an error checking it... */
DPRINTF(("Error matching reqdep %s\n", reqpkg));
xbps_dbg_printf_append("error matching reqdep %s\n",
reqpkg);
break;
} else if (rv == 1) {
/* Required pkg dependency is satisfied */
if (flags & XBPS_FLAG_VERBOSE)
printf("satisfied and installed.\n");
xbps_dbg_printf_append("satisfied and installed.\n");
rv = 0;
continue;
}
@ -318,8 +317,8 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
"pkgver", &pkg_queued);
if (xbps_pkgpattern_match(pkg_queued,
__UNCONST(reqpkg))) {
if (flags & XBPS_FLAG_VERBOSE)
printf("queued in the transaction.\n");
xbps_dbg_printf_append(
"queued in the transaction.\n");
free(pkgname);
continue;
}
@ -340,19 +339,19 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
rv = add_missing_reqdep(trans_dict, reqpkg);
if (rv != 0 && rv != EEXIST) {
DPRINTF(("add missing reqdep failed %s\n",
reqpkg));
xbps_dbg_printf_append("add missing reqdep "
"failed %s\n", reqpkg);
free(pkgname);
break;
} else if (rv == EEXIST) {
DPRINTF(("Missing dep %s already added.\n",
reqpkg));
xbps_dbg_printf_append("missing dep %s "
"already added.\n", reqpkg);
rv = 0;
free(pkgname);
continue;
} else {
if (flags & XBPS_FLAG_VERBOSE)
printf("missing package in repository!\n");
xbps_dbg_printf_append(
"missing package in repository!\n");
free(pkgname);
continue;
}
@ -401,9 +400,10 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
/*
* Package is on repo, add it into the dictionary.
*/
if ((rv = store_dependency(trans_dict, curpkgd,
repoloc)) != 0) {
DPRINTF(("store_dependency failed %s\n", reqpkg));
rv = store_dependency(trans_dict, curpkgd, repoloc);
if (rv != 0) {
xbps_dbg_printf("store_dependency failed %s",
reqpkg);
free(pkgname);
break;
}
@ -416,10 +416,10 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
if (rv == ENOENT) {
rv = 0;
} else if (rv == 0) {
DPRINTF(("Removed missing dep %s.\n", reqpkg));
xbps_dbg_printf("Removed missing dep %s.\n", reqpkg);
} else {
DPRINTF(("Removing missing dep %s returned %s\n",
reqpkg, strerror(rv)));
xbps_dbg_printf("Removing missing dep %s "
"returned %s\n", reqpkg, strerror(rv));
free(pkgname);
break;
}
@ -436,15 +436,15 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
/*
* Iterate on required pkg to find more deps.
*/
if (flags & XBPS_FLAG_VERBOSE)
printf(" Finding dependencies for '%s-%s' [%s]:\n",
xbps_dbg_printf_append("\n");
xbps_dbg_printf("Finding dependencies for '%s-%s' [%s]:\n",
pkgname, reqvers, originpkgn ? "direct" : "indirect");
free(pkgname);
if ((rv = find_repo_deps(trans_dict, repo_dict, repoloc,
NULL, curpkg_rdeps)) != 0) {
DPRINTF(("Error checking %s rundeps %s\n",
reqpkg, strerror(errno)));
xbps_dbg_printf("Error checking %s for rundeps: %s\n",
reqpkg, strerror(rv));
break;
}
}
@ -453,14 +453,34 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
return rv;
}
struct rpool_index_data {
prop_dictionary_t transd;
prop_array_t rdeps;
const char *pkgname;
};
static int
find_repo_deps_in_pool(struct repository_pool_index *rpi, void *arg, bool *done)
{
struct rpool_index_data *rid = arg;
int rv;
(void)done;
rv = find_repo_deps(rid->transd, rpi->rpi_repod, rpi->rpi_uri,
rid->pkgname, rid->rdeps);
return rv;
}
int HIDDEN
xbps_repository_find_pkg_deps(prop_dictionary_t trans_dict,
prop_dictionary_t repo_pkg_dict)
{
prop_array_t pkg_rdeps, missing_rdeps;
struct repository_pool *rpool;
struct rpool_index_data *rid;
const char *pkgname, *pkgver;
int flags = xbps_get_flags(), rv = 0;
int rv = 0;
assert(trans_dict != NULL);
assert(repo_pkg_dict != NULL);
@ -469,31 +489,36 @@ xbps_repository_find_pkg_deps(prop_dictionary_t trans_dict,
if (pkg_rdeps == NULL)
return 0;
rid = malloc(sizeof(struct rpool_index_data));
if (rid == NULL)
return ENOMEM;
prop_dictionary_get_cstring_nocopy(repo_pkg_dict, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(repo_pkg_dict, "pkgver", &pkgver);
if ((rv = xbps_repository_pool_init()) != 0)
return rv;
goto out;
if (flags & XBPS_FLAG_VERBOSE)
printf(" Finding required dependencies for '%s':\n", pkgver);
xbps_dbg_printf("Finding required dependencies for '%s':\n", pkgver);
/*
* Iterate over the repository pool and find out if we have
* all available binary packages.
*/
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) {
/*
* This will find direct and indirect deps,
* if any of them is not there it will be added
* into the missing_deps array.
*/
if ((rv = find_repo_deps(trans_dict, rpool->rp_repod,
rpool->rp_uri, pkgname, pkg_rdeps)) != 0) {
DPRINTF(("Error '%s' while checking rundeps!\n",
strerror(rv)));
goto out;
}
rid->transd = trans_dict;
rid->rdeps = pkg_rdeps;
rid->pkgname = pkgname;
/*
* This will find direct and indirect deps,
* if any of them is not there it will be added
* into the missing_deps array.
*/
rv = xbps_repository_pool_foreach(find_repo_deps_in_pool, rid);
if (rv != 0) {
xbps_dbg_printf("Error '%s' while checking rundeps!\n",
strerror(errno));
goto out;
}
/*
@ -507,16 +532,20 @@ xbps_repository_find_pkg_deps(prop_dictionary_t trans_dict,
* Iterate one more time, but this time with missing deps
* that were found in previous pass.
*/
DPRINTF(("Checking for missing deps in %s.\n", pkgname));
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) {
if ((rv = find_repo_deps(trans_dict, rpool->rp_repod,
rpool->rp_uri, pkgname, missing_rdeps)) != 0) {
DPRINTF(("Error '%s' while checking for "
"missing rundeps!\n", strerror(rv)));
goto out;
}
rid->rdeps = missing_rdeps;
rid->pkgname = NULL;
xbps_dbg_printf("Checking for missing deps in %s.\n", pkgname);
rv = xbps_repository_pool_foreach(find_repo_deps_in_pool, rid);
if (rv != 0) {
xbps_dbg_printf("Error '%s' while checking for "
"missing rundeps!\n", strerror(errno));
goto out;
}
out:
if (rid)
free(rid);
xbps_repository_pool_release();
return rv;

View File

@ -56,6 +56,16 @@
static prop_dictionary_t trans_dict;
static bool trans_dict_initialized;
/*
* This creates the transaction dictionary with two arrays, one for
* dependencies not yet sorted and another one for missing dependencies.
*
* Before returning the dictionary to the caller, package dependencies in
* the "unsorted_deps" array will be sorted and moved to another
* array called "packages". If there are no missing dependencies, the
* "missing_deps" array will be removed.
*
*/
static int
create_transaction_dictionary(void)
{
@ -77,31 +87,31 @@ create_transaction_dictionary(void)
unsorted = prop_array_create();
if (unsorted == NULL) {
rv = ENOMEM;
goto fail2;
}
rv = ENOMEM;
goto fail2;
}
if (!xbps_add_obj_to_dict(trans_dict, missing, "missing_deps")) {
rv = EINVAL;
goto fail3;
if (!xbps_add_obj_to_dict(trans_dict, missing, "missing_deps")) {
rv = EINVAL;
goto fail3;
}
if (!xbps_add_obj_to_dict(trans_dict, unsorted, "unsorted_deps")) {
rv = EINVAL;
goto fail3;
}
rv = EINVAL;
goto fail3;
}
trans_dict_initialized = true;
return rv;
return rv;
fail3:
prop_object_release(unsorted);
prop_object_release(unsorted);
fail2:
prop_object_release(missing);
prop_object_release(missing);
fail:
prop_object_release(trans_dict);
prop_object_release(trans_dict);
return rv;
return rv;
}
static int
@ -115,7 +125,7 @@ compute_transaction_sizes(void)
iter = xbps_get_array_iter_from_dict(trans_dict, "packages");
if (iter == NULL)
return -1;
return EINVAL;
while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "trans-action", &tract);
@ -139,7 +149,7 @@ compute_transaction_sizes(void)
*/
if (!prop_dictionary_set_uint64(trans_dict,
"total-installed-size", instsize)) {
rv = -1;
rv = EINVAL;
goto out;
}
/*
@ -148,7 +158,7 @@ compute_transaction_sizes(void)
*/
if (!prop_dictionary_set_uint64(trans_dict,
"total-download-size", dlsize)) {
rv = -1;
rv = EINVAL;
goto out;
}
out:
@ -172,11 +182,14 @@ set_pkg_state(prop_dictionary_t pkgd, const char *pkgname)
*/
rv = xbps_get_pkg_state_installed(pkgname, &state);
if (rv == 0) {
if (state == XBPS_PKG_STATE_INSTALLED)
return 0;
if ((rv = xbps_set_pkg_state_dictionary(pkgd, state)) != 0)
return rv;
} else if (rv == ENOENT)
} else if (rv == ENOENT)
rv = 0;
return rv;
}
@ -186,23 +199,23 @@ xbps_repository_get_transaction_dict(void)
int rv = 0;
if (trans_dict_initialized == false) {
errno = ENOENT;
errno = ENXIO;
return NULL;
}
/*
* Sort package list if necessary.
* Sort package dependencies if necessary.
*/
if ((rv = xbps_sort_pkg_deps(trans_dict)) != 0) {
errno = rv;
/*
* If there are missing deps (errno==ENOENT)
* If there are missing deps (ENOENT)
* return the dictionary, the client should always
* check if that's the case.
*/
if (errno == ENOENT)
if (rv == ENOENT)
return trans_dict;
errno = rv;
return NULL;
}
@ -213,6 +226,11 @@ xbps_repository_get_transaction_dict(void)
if (compute_transaction_sizes() != 0)
return NULL;
/*
* Remove the "missing_deps" array now that it's not needed.
*/
prop_dictionary_remove(trans_dict, "missing_deps");
return trans_dict;
}
@ -229,16 +247,13 @@ xbps_repository_update_allpkgs(void)
/*
* Prepare dictionary with all registered packages.
*/
dict = xbps_regpkgs_dictionary_init();
dict = xbps_regpkgdb_dictionary_get();
if (dict == NULL)
return ENOENT;
if ((rv = xbps_repository_pool_init()) != 0)
goto out;
return errno;
iter = xbps_get_array_iter_from_dict(dict, "packages");
if (iter == NULL) {
rv = EINVAL;
rv = errno;
goto out;
}
@ -248,40 +263,96 @@ xbps_repository_update_allpkgs(void)
*/
while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
rv = xbps_repository_update_pkg(pkgname, obj);
if (rv == ENOENT)
continue;
else if (rv == EEXIST) {
rv = 0;
continue;
} else if (rv != 0)
break;
if ((rv = xbps_repository_update_pkg(pkgname)) != 0) {
if (rv == ENOENT || rv == EEXIST)
continue;
xbps_dbg_printf("[update-all] '%s' returned: %s\n",
pkgname, strerror(rv));
goto out;
}
newpkg_found = true;
}
prop_object_iterator_release(iter);
if (rv != ENOENT && !newpkg_found)
rv = ENOPKG;
if (newpkg_found)
rv = 0;
else
rv = ENXIO;
out:
xbps_repository_pool_release();
xbps_regpkgs_dictionary_release();
xbps_regpkgdb_dictionary_release();
return rv;
}
int
xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg)
struct rpool_index_data {
prop_dictionary_t pkg_repod;
const char *pkgname;
const char *repo_uri;
bool newpkgfound;
};
static int
repo_find_updated_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
prop_dictionary_t pkgrd = NULL;
prop_array_t unsorted;
struct repository_pool *rpool;
struct rpool_index_data *rid = arg;
prop_dictionary_t instpkgd;
const char *repover, *instver;
int flags = xbps_get_flags(), rv = 0;
bool newpkg_found = false;
/*
* Get the package dictionary from current repository.
* If it's not there, pass to the next repository.
*/
rid->pkg_repod = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod,
"packages", rid->pkgname);
if (rid->pkg_repod == NULL) {
if (errno && errno != ENOENT)
return errno;
xbps_dbg_printf("Package '%s' not found in repository "
"'%s'.\n", rid->pkgname, rpi->rpi_uri);
} else {
/*
* Check if version in repository is greater than
* the version currently installed.
*/
instpkgd = xbps_find_pkg_dict_installed(rid->pkgname, false);
prop_dictionary_get_cstring_nocopy(instpkgd,
"version", &instver);
prop_dictionary_get_cstring_nocopy(rid->pkg_repod,
"version", &repover);
prop_object_release(instpkgd);
if (xbps_cmpver(repover, instver) > 0) {
xbps_dbg_printf("Found '%s-%s' (installed: %s) "
"in repository '%s'.\n", rid->pkgname, repover,
instver, rpi->rpi_uri);
/*
* New package version found, exit from the loop.
*/
rid->newpkgfound = true;
rid->repo_uri = rpi->rpi_uri;
*done = true;
return 0;
}
xbps_dbg_printf("Skipping '%s-%s' (installed: %s) "
"from repository '%s'\n", rid->pkgname, repover, instver,
rpi->rpi_uri);
}
return 0;
}
int
xbps_repository_update_pkg(const char *pkgname)
{
prop_array_t unsorted;
prop_dictionary_t pkgd;
struct rpool_index_data *rid;
int rv = 0;
assert(pkgname != NULL);
assert(instpkg != NULL);
/*
* Prepare repository pool queue.
@ -289,51 +360,42 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg)
if ((rv = xbps_repository_pool_init()) != 0)
return rv;
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) {
/*
* Get the package dictionary from current repository.
* If it's not there, pass to the next repository.
*/
pkgrd = xbps_find_pkg_in_dict_by_name(rpool->rp_repod,
"packages", pkgname);
if (pkgrd == NULL) {
if (errno && errno != ENOENT) {
rv = errno;
goto out;
}
if (flags & XBPS_FLAG_VERBOSE)
printf("Package '%s' not found in repository "
"'%s'.\n", pkgname, rpool->rp_uri);
} else if (pkgrd != NULL) {
/*
* Check if version in repository is greater than
* the version currently installed.
*/
prop_dictionary_get_cstring_nocopy(instpkg,
"version", &instver);
prop_dictionary_get_cstring_nocopy(pkgrd,
"version", &repover);
if (xbps_cmpver(repover, instver) > 0) {
if (flags & XBPS_FLAG_VERBOSE) {
printf("Found '%s-%s' in repository "
"'%s'.\n", pkgname, repover,
rpool->rp_uri);
}
newpkg_found = true;
break;
}
if (flags & XBPS_FLAG_VERBOSE)
printf("Skipping '%s-%s' from repository "
"'%s'.\n", pkgname, repover, rpool->rp_uri);
continue;
}
rid = calloc(1, sizeof(struct rpool_index_data));
if (rid == NULL) {
rv = errno;
goto out;
}
if (!newpkg_found) {
/*
* Check if package is not installed.
*/
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
if (pkgd == NULL) {
rv = ENODEV;
goto out;
}
prop_object_release(pkgd);
/*
* Find out if a new package version exists in repositories.
*/
rid->pkgname = pkgname;
rv = xbps_repository_pool_foreach(repo_find_updated_pkg_cb, rid);
if (rv != 0)
goto out;
/*
* No new versions found in repository pool.
*/
if (rid->newpkgfound == false) {
rv = EEXIST;
goto out;
}
if (pkgrd == NULL) {
/*
* Package couldn't be found in repository pool.
*/
if (rid->pkg_repod == NULL) {
rv = ENOENT;
goto out;
}
@ -346,7 +408,8 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg)
/*
* Set repository in pkg dictionary.
*/
if (!prop_dictionary_set_cstring(pkgrd, "repository", rpool->rp_uri)) {
if (!prop_dictionary_set_cstring(rid->pkg_repod,
"repository", rid->repo_uri)) {
rv = errno;
goto out;
}
@ -354,7 +417,8 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg)
/*
* Construct the dependency chain for this package.
*/
if ((rv = xbps_repository_find_pkg_deps(trans_dict, pkgrd)) != 0)
rv = xbps_repository_find_pkg_deps(trans_dict, rid->pkg_repod);
if (rv != 0)
goto out;
/*
@ -363,7 +427,7 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg)
*/
unsorted = prop_dictionary_get(trans_dict, "unsorted_deps");
if (unsorted == NULL) {
rv = EINVAL;
rv = errno;
goto out;
}
@ -371,66 +435,96 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg)
* Always set "not-installed" package state. Will be overwritten
* to its correct state later.
*/
if ((rv = set_pkg_state(pkgrd, pkgname)) != 0)
if ((rv = set_pkg_state(rid->pkg_repod, pkgname)) != 0)
goto out;
if (!prop_dictionary_set_cstring_nocopy(pkgrd,
/*
* Set trans-action obj in pkg dictionary to "update".
*/
if (!prop_dictionary_set_cstring_nocopy(rid->pkg_repod,
"trans-action", "update")) {
rv = errno;
goto out;
}
if (!prop_array_add(unsorted, pkgrd))
/*
* Added package dictionary from repository into the "unsorted"
* array in the transaction dictionary.
*/
if (!prop_array_add(unsorted, rid->pkg_repod)) {
rv = errno;
goto out;
}
out:
if (rid)
free(rid);
xbps_repository_pool_release();
return rv;
}
int
xbps_repository_install_pkg(const char *pkg, bool bypattern)
static int
repo_find_new_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
prop_dictionary_t origin_pkgrd = NULL, pkgrd = NULL;
struct rpool_index_data *rid = arg;
const char *pkgver;
/*
* Finds a package dictionary from a repository pkg-index dictionary.
*/
rid->pkg_repod = xbps_find_pkg_in_dict_by_pattern(
rpi->rpi_repod, "packages", rid->pkgname);
if (rid->pkg_repod == NULL) {
if (errno && errno != ENOENT)
return errno;
} else {
prop_dictionary_get_cstring_nocopy(rid->pkg_repod,
"pkgver", &pkgver);
xbps_dbg_printf("Found package '%s' from repository %s.\n",
pkgver, rpi->rpi_uri);
rid->repo_uri = rpi->rpi_uri;
*done = true;
}
return 0;
}
int
xbps_repository_install_pkg(const char *pkg)
{
prop_dictionary_t origin_pkgrd = NULL;
prop_array_t unsorted;
struct repository_pool *rpool;
const char *pkgname, *pkgver;
int flags = xbps_get_flags(), rv = 0;
struct rpool_index_data *rid;
const char *pkgname;
int rv = 0;
assert(pkg != NULL);
if ((rv = xbps_repository_pool_init()) != 0)
return rv;
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) {
/*
* Get the package dictionary from current repository.
* If it's not there, pass to the next repository.
*/
if (bypattern)
pkgrd = xbps_find_pkg_in_dict_by_pattern(
rpool->rp_repod, "packages", pkg);
else
pkgrd = xbps_find_pkg_in_dict_by_name(
rpool->rp_repod, "packages", pkg);
if (pkgrd == NULL) {
if (errno && errno != ENOENT) {
rv = errno;
goto out;
}
} else if (pkgrd != NULL) {
if (flags & XBPS_FLAG_VERBOSE) {
prop_dictionary_get_cstring_nocopy(pkgrd,
"pkgver", &pkgver);
printf("Found package '%s' (%s).\n",
pkgver, rpool->rp_uri);
}
break;
}
rid = calloc(1, sizeof(struct rpool_index_data));
if (rid == NULL) {
rv = errno;
goto out;
}
if (pkgrd == NULL) {
/*
* Get the package dictionary from current repository.
* If it's not there, pass to the next repository.
*/
rid->pkgname = pkg;
rv = xbps_repository_pool_foreach(repo_find_new_pkg_cb, rid);
if (rv != 0)
goto out;
/*
* Package couldn't be found in repository pool... EAGAIN.
*/
if (rid->pkg_repod == NULL) {
rv = EAGAIN;
goto out;
}
@ -438,44 +532,38 @@ xbps_repository_install_pkg(const char *pkg, bool bypattern)
/*
* Create the transaction dictionary.
*/
if ((rv = create_transaction_dictionary()) != 0)
if ((rv = create_transaction_dictionary()) != 0)
goto out;
/*
* Check that this pkg hasn't been added previously into
* the transaction.
*/
if (bypattern) {
if (xbps_find_pkg_in_dict_by_pattern(trans_dict,
"unsorted_deps", pkg))
goto out;
} else {
if (xbps_find_pkg_in_dict_by_name(trans_dict,
"unsorted_deps", pkg))
goto out;
}
/*
* Set repository in pkg dictionary.
*/
if (!prop_dictionary_set_cstring(pkgrd, "repository", rpool->rp_uri)) {
rv = errno;
goto out;
}
origin_pkgrd = prop_dictionary_copy(pkgrd);
prop_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname);
/*
* Prepare required package dependencies.
*/
if ((rv = xbps_repository_find_pkg_deps(trans_dict, pkgrd)) != 0)
if (xbps_find_pkg_in_dict_by_pattern(trans_dict,
"unsorted_deps", pkg))
goto out;
if (flags & XBPS_FLAG_VERBOSE)
printf("\n");
/*
* Set repository location in pkg dictionary.
*/
if (!prop_dictionary_set_cstring(rid->pkg_repod,
"repository", rid->repo_uri)) {
rv = EINVAL;
goto out;
}
origin_pkgrd = prop_dictionary_copy(rid->pkg_repod);
prop_dictionary_get_cstring_nocopy(rid->pkg_repod, "pkgname", &pkgname);
/*
* Add required package dictionary into the unsorted deps dictionary,
* Prepare required package dependencies and add them into the
* "unsorted" array in transaction dictionary.
*/
rv = xbps_repository_find_pkg_deps(trans_dict, rid->pkg_repod);
if (rv != 0)
goto out;
/*
* Add required package dictionary into the unsorted array and
* set package state as not yet installed.
*/
unsorted = prop_dictionary_get(trans_dict, "unsorted_deps");
@ -486,15 +574,27 @@ xbps_repository_install_pkg(const char *pkg, bool bypattern)
if ((rv = set_pkg_state(origin_pkgrd, pkgname)) != 0)
goto out;
/*
* Set trans-action obj in pkg dictionary to "install".
*/
if (!prop_dictionary_set_cstring_nocopy(origin_pkgrd,
"trans-action", "install")) {
rv = EINVAL;
goto out;
}
/*
* Add the pkg dictionary from repository's index dictionary into
* the "unsorted" array in transaction dictionary.
*/
if (!prop_array_add(unsorted, origin_pkgrd)) {
rv = errno;
goto out;
}
if (!prop_array_add(unsorted, origin_pkgrd))
rv = errno;
out:
if (rid)
free(rid);
if (origin_pkgrd)
prop_object_release(origin_pkgrd);

View File

@ -221,12 +221,45 @@ xbps_repository_get_pkg_plist_dict_from_url(const char *url, const char *plistf)
return plistd;
}
struct rpool_index_data {
prop_dictionary_t plistd;
const char *plistf;
const char *pkgname;
};
static int
repo_find_pkg_plistd_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
struct rpool_index_data *rid = arg;
prop_dictionary_t pkgd;
char *url;
pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod,
"packages", rid->pkgname);
if (pkgd == NULL) {
if (errno != ENOENT)
return errno;
return 0;
}
url = xbps_repository_get_path_from_pkg_dict(pkgd, rpi->rpi_uri);
if (url == NULL)
return EINVAL;
rid->plistd =
xbps_repository_get_pkg_plist_dict_from_url(url, rid->plistf);
free(url);
if (prop_object_type(rid->plistd) == PROP_TYPE_DICTIONARY)
*done = true;
return 0;
}
prop_dictionary_t
xbps_repository_get_pkg_plist_dict(const char *pkgname, const char *plistf)
{
prop_dictionary_t plistd = NULL, pkgd;
struct repository_pool *rpool;
char *url = NULL;
prop_dictionary_t plistd;
struct rpool_index_data *rid;
int rv = 0;
if ((rv = xbps_repository_pool_init()) != 0) {
@ -234,6 +267,10 @@ xbps_repository_get_pkg_plist_dict(const char *pkgname, const char *plistf)
return NULL;
}
rid = malloc(sizeof(struct rpool_index_data));
if (rid == NULL)
goto out;
/*
* Iterate over the the repository pool and search for a plist file
* in the binary package named 'pkgname'. The plist file will be
@ -243,27 +280,12 @@ xbps_repository_get_pkg_plist_dict(const char *pkgname, const char *plistf)
* This will work locally and remotely, thanks to libarchive and
* libfetch!
*/
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) {
pkgd = xbps_find_pkg_in_dict_by_name(rpool->rp_repod,
"packages", pkgname);
if (pkgd == NULL) {
if (errno != ENOENT)
break;
continue;
}
url = xbps_repository_get_path_from_pkg_dict(pkgd,
rpool->rp_uri);
if (url == NULL)
break;
plistd = xbps_repository_get_pkg_plist_dict_from_url(url,
plistf);
if (plistd != NULL) {
free(url);
break;
}
free(url);
}
rid->pkgname = pkgname;
rid->plistf = plistf;
rv = xbps_repository_pool_foreach(repo_find_pkg_plistd_cb, rid);
plistd = rid->plistd;
free(rid);
out:
xbps_repository_pool_release();
if (plistd == NULL)
errno = ENOENT;

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2009 Juan Romero Pardines.
* Copyright (c) 2009-2010 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,6 +31,7 @@
#include <xbps_api.h>
#include "xbps_api_impl.h"
#include "queue.h"
/**
* @file lib/repository_pool.c
@ -38,6 +39,14 @@
* @defgroup repopool Repository pool init/fini functions
*/
struct repository_pool {
SIMPLEQ_ENTRY(repository_pool) rp_entries;
struct repository_pool_index *rpi;
};
static SIMPLEQ_HEAD(rpool_head, repository_pool) rpool_queue =
SIMPLEQ_HEAD_INITIALIZER(rpool_queue);
static size_t repolist_refcnt;
static bool repolist_initialized;
@ -58,19 +67,19 @@ xbps_repository_pool_init(void)
return 0;
}
SIMPLEQ_INIT(&rp_queue);
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REPOLIST);
if (plist == NULL) {
rv = EINVAL;
rv = errno;
goto out;
}
dict = prop_dictionary_internalize_from_zfile(plist);
if (dict == NULL) {
free(plist);
rv = errno;
free(plist);
xbps_dbg_printf("%s: cannot internalize plist %s: %s\n",
__func__, plist, strerror(errno));
goto out;
}
free(plist);
@ -96,7 +105,7 @@ xbps_repository_pool_init(void)
plist =
xbps_get_pkg_index_plist(prop_string_cstring_nocopy(obj));
if (plist == NULL) {
rv = EINVAL;
rv = errno;
goto out;
}
@ -106,16 +115,26 @@ xbps_repository_pool_init(void)
goto out;
}
rpool->rp_uri = prop_string_cstring(obj);
if (rpool->rp_uri == NULL) {
free(rpool);
free(plist);
rpool->rpi = malloc(sizeof(struct repository_pool_index));
if (rpool->rpi == NULL) {
rv = errno;
free(rpool);
goto out;
}
rpool->rp_repod = prop_dictionary_internalize_from_zfile(plist);
if (rpool->rp_repod == NULL) {
free(rpool->rp_uri);
rpool->rpi->rpi_uri = prop_string_cstring(obj);
if (rpool->rpi->rpi_uri == NULL) {
rv = errno;
free(rpool->rpi);
free(rpool);
free(plist);
goto out;
}
rpool->rpi->rpi_repod =
prop_dictionary_internalize_from_zfile(plist);
if (rpool->rpi->rpi_repod == NULL) {
free(rpool->rpi->rpi_uri);
free(rpool->rpi);
free(rpool);
free(plist);
if (errno == ENOENT) {
@ -124,10 +143,14 @@ xbps_repository_pool_init(void)
continue;
}
rv = errno;
xbps_dbg_printf("%s: cannot internalize plist %s: %s\n",
__func__, plist, strerror(errno));
goto out;
}
free(plist);
SIMPLEQ_INSERT_TAIL(&rp_queue, rpool, rp_entries);
xbps_dbg_printf("Registered repository '%s'\n",
rpool->rpi->rpi_uri);
SIMPLEQ_INSERT_TAIL(&rpool_queue, rpool, rp_entries);
}
if (ntotal - nmissing == 0)
@ -135,13 +158,13 @@ xbps_repository_pool_init(void)
repolist_initialized = true;
repolist_refcnt = 1;
DPRINTF(("%s: initialized ok.\n", __func__));
xbps_dbg_printf("%s: initialized ok.\n", __func__);
out:
if (iter)
prop_object_iterator_release(iter);
if (dict)
prop_object_release(dict);
if (rv != 0)
if (rv != 0)
xbps_repository_pool_release();
return rv;
@ -156,13 +179,37 @@ xbps_repository_pool_release(void)
if (--repolist_refcnt > 0)
return;
while ((rpool = SIMPLEQ_FIRST(&rp_queue)) != NULL) {
SIMPLEQ_REMOVE(&rp_queue, rpool, repository_pool, rp_entries);
prop_object_release(rpool->rp_repod);
free(rpool->rp_uri);
while ((rpool = SIMPLEQ_FIRST(&rpool_queue)) != NULL) {
SIMPLEQ_REMOVE(&rpool_queue, rpool, repository_pool, rp_entries);
xbps_dbg_printf("Unregistered repository '%s'\n",
rpool->rpi->rpi_uri);
prop_object_release(rpool->rpi->rpi_repod);
free(rpool->rpi->rpi_uri);
free(rpool->rpi);
free(rpool);
}
repolist_refcnt = 0;
repolist_initialized = false;
DPRINTF(("%s: released ok.\n", __func__));
xbps_dbg_printf("%s: released ok.\n", __func__);
}
int
xbps_repository_pool_foreach(
int (*fn)(struct repository_pool_index *, void *, bool *),
void *arg)
{
struct repository_pool *rpool;
int rv = 0;
bool done = false;
if (!repolist_initialized)
return 0;
SIMPLEQ_FOREACH(rpool, &rpool_queue, rp_entries) {
rv = (*fn)(rpool->rpi, arg, &done);
if (rv != 0 || done)
break;
}
return rv;
}

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2009 Juan Romero Pardines.
* Copyright (c) 2009-2010 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -30,6 +30,7 @@
#include <xbps_api.h>
#include "xbps_api_impl.h"
#include "queue.h"
struct sorted_dependency {
SIMPLEQ_ENTRY(sorted_dependency) chain;
@ -44,20 +45,15 @@ find_sorteddep_by_name(const char *pkgname)
{
struct sorted_dependency *sdep = NULL;
const char *curpkgname;
bool found = false;
SIMPLEQ_FOREACH(sdep, &sdep_list, chain) {
prop_dictionary_get_cstring_nocopy(sdep->dict,
"pkgname", &curpkgname);
if (strcmp(pkgname, curpkgname) == 0) {
found = true;
break;
}
if (strcmp(pkgname, curpkgname) == 0)
return sdep;
}
if (!found)
return NULL;
return sdep;
return NULL;
}
int HIDDEN
@ -107,13 +103,14 @@ again:
while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
DPRINTF(("Sorting package: %s\n", pkgver));
xbps_dbg_printf("Sorting package '%s': ", pkgver);
if (find_sorteddep_by_name(pkgname) != NULL) {
DPRINTF(("Skipping %s already queued.\n", pkgname));
xbps_dbg_printf_append("skipping, already queued.\n",
pkgname);
continue;
}
sdep = malloc(sizeof(*sdep));
sdep = malloc(sizeof(struct sorted_dependency));
if (sdep == NULL) {
rv = ENOMEM;
goto out;
@ -124,8 +121,8 @@ again:
*/
rundeps = prop_dictionary_get(obj, "run_depends");
if (rundeps == NULL || prop_array_count(rundeps) == 0) {
DPRINTF(("Adding %s (no rundeps) into the sorted "
"queue.\n", pkgver));
xbps_dbg_printf_append("added (no rundeps) into "
"the sorted queue.\n");
sdep->dict = prop_dictionary_copy(obj);
SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain);
cnt++;
@ -133,15 +130,18 @@ again:
}
iter2 = prop_array_iterator(rundeps);
if (iter2 == NULL) {
free(sdep);
rv = ENOMEM;
free(sdep);
goto out;
}
/*
* Iterate over the run_depends array, and find out if they
* were already added in the sorted list.
*/
DPRINTF(("Checking %s run_depends for sorting...\n", pkgver));
xbps_dbg_printf_append("\n");
xbps_dbg_printf("Checking '%s' run depends for sorting...\n",
pkgver);
while ((obj2 = prop_object_iterator_next(iter2)) != NULL) {
str = prop_string_cstring_nocopy(obj2);
if (str == NULL) {
@ -152,22 +152,22 @@ again:
pkgnamedep = xbps_get_pkgpattern_name(str);
if (pkgnamedep == NULL) {
free(sdep);
rv = errno;
rv = EINVAL;
goto out;
}
DPRINTF(("Required dependency %s: ", str));
xbps_dbg_printf(" Required dependency '%s': ", str);
/*
* If dependency is already satisfied or queued,
* pass to the next one.
*/
if (xbps_check_is_installed_pkg(str)) {
rundepscnt++;
DPRINTF(("installed.\n"));
xbps_dbg_printf_append("installed.\n");
} else if (find_sorteddep_by_name(pkgnamedep) != NULL) {
DPRINTF(("queued.\n"));
xbps_dbg_printf_append("queued.\n");
rundepscnt++;
} else {
DPRINTF(("not installed or queued.\n"));
xbps_dbg_printf_append("not installed.\n");
}
free(pkgnamedep);
}
@ -175,23 +175,25 @@ again:
/* Add dependency if all its required deps are already added */
if (prop_array_count(rundeps) == rundepscnt) {
DPRINTF(("Adding package %s to the sorted queue.\n",
pkgver));
sdep->dict = prop_dictionary_copy(obj);
SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain);
xbps_dbg_printf("Added package '%s' to the sorted "
"queue (all rundeps satisfied).\n\n", pkgver);
rundepscnt = 0;
cnt++;
continue;
}
DPRINTF(("Unsorted package %s has missing rundeps.\n", pkgver));
xbps_dbg_printf("Unsorted package '%s' has missing "
"rundeps (missing %zu).\n\n", pkgver,
prop_array_count(rundeps) - rundepscnt);
free(sdep);
rundepscnt = 0;
}
/* Iterate until all deps are processed. */
if (cnt < ndeps) {
DPRINTF(("Missing required deps! cnt: %zu ndeps: %zu\n",
cnt, ndeps));
xbps_dbg_printf("Missing required deps! queued: %zu "
"required: %zu.\n", cnt, ndeps);
prop_object_iterator_reset(iter);
goto again;
}
@ -203,7 +205,7 @@ again:
while ((sdep = SIMPLEQ_FIRST(&sdep_list)) != NULL) {
if (!prop_array_add(sorted, sdep->dict)) {
free(sdep);
rv = errno;
rv = EINVAL;
goto out;
}
SIMPLEQ_REMOVE(&sdep_list, sdep, sorted_dependency, chain);