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

View File

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

View File

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

View File

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

View File

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

View File

@ -33,6 +33,7 @@
#include <assert.h> #include <assert.h>
#include <xbps_api.h> #include <xbps_api.h>
#include "../xbps-bin/defs.h"
#include "defs.h" #include "defs.h"
#include "config.h" #include "config.h"
@ -147,13 +148,15 @@ unregister_repository(const char *uri)
if ((idxstr = sanitize_url(uri)) == NULL) if ((idxstr = sanitize_url(uri)) == NULL)
return errno; return errno;
if ((rv = xbps_repository_unregister(idxstr)) != 0) { if ((rv = xbps_repository_unregister(idxstr)) == 0)
if (rv == ENOENT) return 0;
fprintf(stderr, "Repository '%s' not actually "
"registered.\n", idxstr); if (rv == ENOENT) {
else fprintf(stderr, "Repository '%s' not actually "
fprintf(stderr, "E: couldn't unregister " "registered.\n", idxstr);
"repository (%s)\n", strerror(rv)); } else {
fprintf(stderr, "E: couldn't unregister "
"repository (%s)\n", strerror(rv));
} }
return rv; return rv;
@ -211,14 +214,13 @@ register_repository(const char *uri)
if ((rpi = pkgindex_verify(plist, idxstr)) == NULL) if ((rpi = pkgindex_verify(plist, idxstr)) == NULL)
goto out; goto out;
rv = xbps_repository_register(idxstr); if ((rv = xbps_repository_register(idxstr)) != 0) {
if (rv != 0 && rv != EEXIST) { if (rv == EEXIST) {
fprintf(stderr, "E: couldn't register repository (%s)\n", fprintf(stderr, "W: repository already registered.\n");
strerror(rv)); } else {
goto out; fprintf(stderr, "E: couldn't register repository "
} else if (rv == EEXIST) { "(%s)\n", strerror(errno));
fprintf(stderr, "W: repository already registered.\n"); }
rv = 0;
goto out; goto out;
} }
@ -234,110 +236,111 @@ out:
return rv; 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 int
show_pkg_info_from_repolist(const char *pkgname) show_pkg_info_from_repolist(const char *pkgname)
{ {
struct repository_pool *rp; return xbps_repository_pool_foreach(repo_show_pkg_info_cb,
prop_dictionary_t repo_pkgd, pkg_propsd; __UNCONST(pkgname));
int rv = 0; }
SIMPLEQ_FOREACH(rp, &rp_queue, rp_entries) { static int
char *url = NULL; repo_show_pkg_deps_cb(struct repository_pool_index *rpi, void *arg, bool *done)
repo_pkgd = xbps_find_pkg_in_dict_by_name(rp->rp_repod, {
"packages", pkgname); prop_dictionary_t pkgd;
if (repo_pkgd == NULL) { const char *ver, *pkgname = arg;
if (errno && errno != ENOENT) {
rv = errno; pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod,
break; "packages", pkgname);
} if (pkgd == NULL) {
continue; if (errno && errno != ENOENT)
} return errno;
url = xbps_repository_get_path_from_pkg_dict(repo_pkgd,
rp->rp_uri); return 0;
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;
} }
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 int
show_pkg_deps_from_repolist(const char *pkgname) show_pkg_deps_from_repolist(const char *pkgname)
{ {
struct repository_pool *rd; return xbps_repository_pool_foreach(repo_show_pkg_deps_cb,
prop_dictionary_t pkgd; __UNCONST(pkgname));
const char *ver; }
static int
repo_sync_pkg_index_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
struct repoinfo *rp;
char *plist;
int rv = 0; int rv = 0;
SIMPLEQ_FOREACH(rd, &rp_queue, rp_entries) { (void)arg;
pkgd = xbps_find_pkg_in_dict_by_name(rd->rp_repod, (void)done;
"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);
}
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 int
repository_sync(void) repository_sync(void)
{ {
struct repository_pool *rp; return xbps_repository_pool_foreach(repo_sync_pkg_index_cb, NULL);
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;
} }

View File

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

View File

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

View File

@ -31,10 +31,6 @@
#include <inttypes.h> #include <inttypes.h>
#include <prop/proplib.h> #include <prop/proplib.h>
#include <archive.h>
#include <archive_entry.h>
#include <sys/queue.h>
#ifdef __cplusplus #ifdef __cplusplus
# define __BEGIN_DECLS extern "C" { # define __BEGIN_DECLS extern "C" {
@ -44,7 +40,6 @@
# define __END_DECLS # define __END_DECLS
#endif #endif
/** /**
* @file include/xbps_api.h * @file include/xbps_api.h
* @brief XBPS Library API header * @brief XBPS Library API header
@ -56,7 +51,7 @@
* @def XBPS_RELVER * @def XBPS_RELVER
* Current library release date. * Current library release date.
*/ */
#define XBPS_RELVER "20101023:0.6.1" #define XBPS_RELVER "20101118"
/** /**
* @def XBPS_META_PATH * @def XBPS_META_PATH
@ -122,6 +117,30 @@
__BEGIN_DECLS __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 */ /** @addtogroup configure */
/*@{*/ /*@{*/
@ -134,7 +153,7 @@ __BEGIN_DECLS
* in unpacked state. * in unpacked state.
* @param[in] update Set it to true if this package is being updated. * @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, int xbps_configure_pkg(const char *pkgname,
const char *version, const char *version,
@ -144,7 +163,7 @@ int xbps_configure_pkg(const char *pkgname,
/** /**
* Configure (or force reconfiguration of) all packages. * 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); int xbps_configure_all_pkgs(void);
@ -172,20 +191,6 @@ int xbps_cmpver(const char *pkg1, const char *pkg2);
/** @addtogroup download */ /** @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. * Download a file from a remote URL.
* *
@ -203,73 +208,15 @@ int xbps_fetch_file(const char *uri,
bool refetch, bool refetch,
const char *flags); 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(). * Returns last error string reported by xbps_fetch_file().
* *
* @return A string with the appropiate error message. * @return A string with the appropiate error message.
* @}
*/ */
const char *xbps_fetch_error_string(void); 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 */ /* From lib/humanize_number.c */
#define HN_DECIMAL 0x01 #define HN_DECIMAL 0x01
#define HN_NOSPACE 0x02 #define HN_NOSPACE 0x02
@ -298,7 +245,7 @@ int xbps_mkpath(char *path, mode_t mode);
* Finds all package orphans currently installed. * Finds all package orphans currently installed.
* *
* @return A proplib array of dictionaries with all orphans found, * @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); 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] array Proplib array to insert the object to.
* @param[in] obj Proplib object to be inserted. * @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); 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. * @param[in] arg Argument to be passed to the function callback.
* *
* @return 0 on success (all objects were processed), otherwise an * @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, int xbps_callback_array_iter_in_dict(prop_dictionary_t dict,
const char *key, 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. * @param[in] arg Argument to be passed to the function callback.
* *
* @return 0 on success (all objects were processed), otherwise an * @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, int xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict,
const char *key, 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] array The proplib array where to look for.
* @param[in] val The value of string to match. * @param[in] val The value of string to match.
* *
* @return true on success, false otherwise and errno set appropiately * @return true on success, false otherwise and errno is set appropiately.
* if there was an unexpected error.
*/ */
bool xbps_find_string_in_array(prop_array_t array, const char *val); 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] pkgname Package name to look for.
* @param[in] plist Path to a plist file. * @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, * 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] key Key associated with the proplib array.
* @param[in] pkgname Package name to look for. * @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, bool xbps_remove_pkg_from_dict(prop_dictionary_t dict,
const char *key, const char *key,
const char *pkgname); const char *pkgname);
/** /**
* Removes a string from a proplib's array. * 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] array Proplib array where to look for.
* @param[in] str String to match in the array. * @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 * @param[in] check_state Set it to true to check that package
* is in XBPS_PKG_STATE_CONFIG_FILES state. * 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); 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 * Purge all installed packages. Packages that aren't in
* XBPS_PKG_STATE_CONFIG_FILES state will be ignored. * 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); 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 * @param[in] automatic Set it to true to mark package that has been
* installed by another package, and not explicitly. * 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); 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. * @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); 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 * @note This function is reference counted, if the database has
* been initialized previously, the counter will be increased by one * been initialized previously, the counter will be increased by one
* and dictionary stored in memory will be returned. * 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. * when its dictionary is no longer needed.
* *
* @return A dictionary as shown above in the Detailed description * @return A dictionary as shown above in the Detailed description
* graph on success, or NULL otherwise and errno is set appropiately. * 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. * 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 * @note This function is reference counted, if the database
* is in use (its reference count number is not 0), won't be released. * 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 * @param[in] update If true, some steps will be skipped. See in the
* detailed description above for more information. * 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); 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: * @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>. * <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); 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. * @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); 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. * @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); 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 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 * @note The function name might be misleading, but is correct because
* if package is found, it will be marked as "going to be installed". * if package is found, it will be marked as "going to be installed".
* *
* @param pkg Package name or pattern to find. * @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. * 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. * is available the package dictionary will be enqueued.
* *
* @param pkgname The package name to update. * @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, int xbps_repository_update_pkg(const char *pkgname);
prop_dictionary_t instpkg);
/** /**
* Finds newer versions for all installed packages by looking at the * Finds newer versions for all installed packages by looking at the
* repository pool. If a newer version exists, package will be enqueued * repository pool. If a newer version exists, package will be enqueued
* into the transaction dictionary. * 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); 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. * xbps_repository_update_pkg() functions are not called previously.
* *
* @return The transaction dictionary to install/update/replace * @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); 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. * @param[in] uri URI pointing to a repository.
* *
* @return A string with the full path, NULL otherwise and errno * @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, char *xbps_repository_get_path_from_pkg_dict(prop_dictionary_t d,
const char *uri); 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 * @return An internalized proplib dictionary, otherwise NULL and
* errno is set appropiately. * errno is set appropiately.
*/ */
prop_dictionary_t xbps_repository_get_pkg_plist_dict_from_url(const char *url, prop_dictionary_t
const char *plistf); 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" * @struct repository_pool_index xbps_api.h "xbps_api.h"
* @brief Repository pool structure * @brief Repository pool dictionary structure
* *
* Repository object structure registered in the global simple queue * Repository index object structure registered in a private simple queue.
* \a rp_queue. The simple queue must be initialized through * The structure contains a dictionary and the URI associated with the
* xbps_repository_pool_init(), and released with * registered repository index.
* xbps_repository_pool_release() when it's no longer needed.
*/ */
struct repository_pool { struct repository_pool_index {
/** /**
* @var rp_entries * @var rpi_repod
* *
* Structure that connects elements in the simple queue. * Internalized Proplib dictionary of the pkg-index plist file
* For use with the SIMPLEQ macros. * associated with repository.
*/ */
SIMPLEQ_ENTRY(repository_pool) rp_entries; prop_dictionary_t rpi_repod;
/**
* @var rp_repod
*
* Proplib dictionary associated with repository.
*/
prop_dictionary_t rp_repod;
/** /**
* @var rp_uri * @var rp_uri
* *
* URI string associated with repository. * 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 * Initializes the repository pool.
* \a rp_queue with all registered repositories in the database.
* *
* Once it's initialized, access to the repositories can be done * Once it's initialized, access to the repositories can be done
* by the global simple queue \a rp_queue and the \a repository_pool * through the \a xbps_repository_pool_foreach() function.
* structure.
* *
* @note This function is reference counted, don't forget to call * @note This function is reference counted, don't forget to call
* xbps_repository_pool_release() when it's no longer needed. * 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); int xbps_repository_pool_init(void);
@ -832,6 +756,24 @@ int xbps_repository_pool_init(void);
*/ */
void xbps_repository_pool_release(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 */ /** @addtogroup reposync */
@ -886,7 +828,7 @@ typedef enum pkg_state {
* @param[in] pkgname Package name. * @param[in] pkgname Package name.
* @param[out] state Package state returned. * @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); 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[in] dict Package dictionary.
* @param[out] state Package state returned. * @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); 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] pkgname Package name.
* @param[in] state Package state to be set. * @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); 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] dict Package dictionary.
* @param[in] state Package state to be set. * @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); 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 * @param[in] trans_pkg_dict Package proplib dictionary as stored in the
* \a packages array returned by the transaction dictionary. * \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); int xbps_unpack_binary_pkg(prop_dictionary_t trans_pkg_dict);

View File

@ -31,6 +31,9 @@
# define NDEBUG # define NDEBUG
#endif #endif
#include <assert.h> #include <assert.h>
#include <archive.h>
#include <archive_entry.h>
#include <xbps_api.h> #include <xbps_api.h>
#define ARCHIVE_READ_BLOCKSIZE 10240 #define ARCHIVE_READ_BLOCKSIZE 10240
@ -60,17 +63,47 @@
#define HIDDEN #define HIDDEN
#endif #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 __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 * @private
* From lib/package_config_files.c * From lib/package_config_files.c
*/ */
int HIDDEN xbps_config_file_from_archive_entry(prop_dictionary_t, int HIDDEN xbps_config_file_from_archive_entry(prop_dictionary_t,
prop_dictionary_t,
struct archive_entry *, struct archive_entry *,
const char *,
int *, int *,
bool *); bool *);
/** /**
* @private * @private
* From lib/plist.c * 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 *); 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 __END_DECLS
#endif /* !_XBPS_API_IMPL_H_ */ #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_configure.o package_config_files.o package_orphans.o
OBJS += package_remove.o package_remove_obsoletes.o package_state.o OBJS += package_remove.o package_remove_obsoletes.o package_state.o
OBJS += package_unpack.o package_requiredby.o package_register.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 += cmpver.o download.o fexec.o humanize_number.o plist.o
OBJS += sortdeps.o util.o pkgmatch.o mkpath.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_findpkg.o repository_plist.o
OBJS += repository_pool.o repository_sync_index.o OBJS += repository_pool.o repository_sync_index.o
OBJS += $(COMPAT_SRCS) OBJS += $(COMPAT_SRCS)

View File

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

View File

@ -80,7 +80,7 @@ pfcexec(const char *path, const char *file, const char **argv)
_exit(127); _exit(127);
} }
(void)execvp(file, __UNCONST(argv)); (void)execv(file, __UNCONST(argv));
_exit(127); _exit(127);
/* NOTREACHED */ /* NOTREACHED */
case -1: case -1:
@ -138,7 +138,7 @@ vfcexec(const char *path, int skipempty, const char *arg, va_list ap)
return retval; return retval;
} }
int int HIDDEN
xbps_file_exec(const char *arg, ...) xbps_file_exec(const char *arg, ...)
{ {
va_list ap; va_list ap;
@ -151,7 +151,7 @@ xbps_file_exec(const char *arg, ...)
return result; return result;
} }
int int HIDDEN
xbps_file_exec_skipempty(const char *arg, ...) xbps_file_exec_skipempty(const char *arg, ...)
{ {
va_list ap; va_list ap;
@ -164,7 +164,7 @@ xbps_file_exec_skipempty(const char *arg, ...)
return result; return result;
} }
int int HIDDEN
xbps_file_chdir_exec(const char *path, const char *arg, ...) xbps_file_chdir_exec(const char *path, const char *arg, ...)
{ {
va_list ap; 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.h>
#include "xbps_api_impl.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 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, struct archive_entry *entry,
const char *pkgname,
int *flags, int *flags,
bool *skip) bool *skip)
{ {
prop_dictionary_t forigd; prop_dictionary_t forigd;
prop_object_t obj, obj2; prop_object_t obj, obj2;
prop_object_iterator_t iter, iter2; 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; char *buf, *sha256_cur = NULL, *sha256_orig = NULL;
int rv = 0; int rv = 0;
bool install_new = false; 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) if (iter == NULL)
return 0; return EINVAL;
/* /*
* Get original hash for the file from current * Get original hash for the file from current
* installed package. * installed package.
*/ */
prop_dictionary_get_cstring_nocopy(propsd, "pkgname", &pkgname);
forigd = xbps_get_pkg_dict_from_metadata_plist(pkgname, XBPS_PKGFILES); forigd = xbps_get_pkg_dict_from_metadata_plist(pkgname, XBPS_PKGFILES);
if (forigd == NULL) { if (forigd == NULL) {
install_new = true; install_new = true;
@ -73,7 +123,7 @@ xbps_config_file_from_archive_entry(prop_dictionary_t d,
buf = xbps_xasprintf(".%s", cffile); buf = xbps_xasprintf(".%s", cffile);
if (buf == NULL) { if (buf == NULL) {
prop_object_iterator_release(iter2); prop_object_iterator_release(iter2);
rv = errno; rv = ENOMEM;
goto out; goto out;
} }
if (strcmp(archive_entry_pathname(entry), buf) == 0) { 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); buf = xbps_xasprintf(".%s", cffile);
if (buf == NULL) { if (buf == NULL) {
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
return errno; return ENOMEM;
} }
if (strcmp(archive_entry_pathname(entry), buf)) { if (strcmp(archive_entry_pathname(entry), buf)) {
free(buf); free(buf);
@ -180,7 +230,7 @@ xbps_config_file_from_archive_entry(prop_dictionary_t d,
(strcmp(sha256_orig, sha256_new))) { (strcmp(sha256_orig, sha256_new))) {
buf = xbps_xasprintf(".%s.new", cffile); buf = xbps_xasprintf(".%s.new", cffile);
if (buf == NULL) { if (buf == NULL) {
rv = errno; rv = ENOMEM;
break; break;
} }
printf("Keeping modified file %s.\n", cffile); printf("Keeping modified file %s.\n", cffile);

View File

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

View File

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

View File

@ -54,16 +54,14 @@ remove_pkg_metadata(const char *pkgname)
struct dirent *dp; struct dirent *dp;
DIR *dirp; DIR *dirp;
char *metadir, *path; char *metadir, *path;
int flags = 0, rv = 0; int rv = 0, flags = xbps_get_flags();
assert(pkgname != NULL); assert(pkgname != NULL);
flags = xbps_get_flags();
metadir = xbps_xasprintf("%s/%s/metadata/%s", xbps_get_rootdir(), metadir = xbps_xasprintf("%s/%s/metadata/%s", xbps_get_rootdir(),
XBPS_META_PATH, pkgname); XBPS_META_PATH, pkgname);
if (metadir == NULL) if (metadir == NULL)
return errno; return ENOMEM;
dirp = opendir(metadir); dirp = opendir(metadir);
if (dirp == NULL) { if (dirp == NULL) {
@ -80,7 +78,7 @@ remove_pkg_metadata(const char *pkgname)
if (path == NULL) { if (path == NULL) {
(void)closedir(dirp); (void)closedir(dirp);
free(metadir); free(metadir);
return -1; return ENOMEM;
} }
if (unlink(path) == -1) { if (unlink(path) == -1) {
@ -107,7 +105,7 @@ xbps_purge_all_pkgs(void)
const char *pkgname; const char *pkgname;
int rv = 0; int rv = 0;
if ((d = xbps_regpkgs_dictionary_init()) == NULL) if ((d = xbps_regpkgdb_dictionary_get()) == NULL)
return errno; return errno;
iter = xbps_get_array_iter_from_dict(d, "packages"); iter = xbps_get_array_iter_from_dict(d, "packages");
@ -123,7 +121,7 @@ xbps_purge_all_pkgs(void)
} }
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
out: out:
xbps_regpkgs_dictionary_release(); xbps_regpkgdb_dictionary_release();
return rv; return rv;
} }
@ -132,16 +130,15 @@ int
xbps_purge_pkg(const char *pkgname, bool check_state) xbps_purge_pkg(const char *pkgname, bool check_state)
{ {
prop_dictionary_t dict, pkgd; prop_dictionary_t dict, pkgd;
int rv = 0, flags; int rv = 0, flags = xbps_get_flags();
pkg_state_t state = 0; pkg_state_t state = 0;
assert(pkgname != NULL); assert(pkgname != NULL);
flags = xbps_get_flags();
/* /*
* Firstly let's get the pkg dictionary from regpkgdb. * 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; return errno;
pkgd = xbps_find_pkg_in_dict_by_name(dict, "packages", pkgname); 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) if ((rv = xbps_get_pkg_state_dictionary(pkgd, &state)) != 0)
goto out; goto out;
if (state != XBPS_PKG_STATE_CONFIG_FILES) if (state != XBPS_PKG_STATE_CONFIG_FILES) {
rv = EINVAL;
goto out; goto out;
}
} }
/* /*
* Remove unmodified configuration files. * Remove unmodified configuration files and directories.
*/ */
dict = xbps_get_pkg_dict_from_metadata_plist(pkgname, XBPS_PKGFILES); dict = xbps_get_pkg_dict_from_metadata_plist(pkgname, XBPS_PKGFILES);
if (dict == NULL) { if (dict == NULL) {
rv = errno; rv = errno;
goto out; goto out;
} }
if ((rv = xbps_remove_pkg_files(dict, "conf_files")) != 0) {
prop_object_release(dict); if (prop_dictionary_get(dict, "conf_files")) {
goto out; 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); prop_object_release(dict);
/* /*
* Remove metadata dir and unregister package. * Remove metadata dir and unregister package.
*/ */
if ((rv = remove_pkg_metadata(pkgname)) == 0) { if ((rv = remove_pkg_metadata(pkgname)) != 0)
if ((rv = xbps_unregister_pkg(pkgname)) == 0) { goto out;
if (flags & XBPS_FLAG_VERBOSE) {
printf("Package %s purged " if ((rv = xbps_unregister_pkg(pkgname)) != 0)
"successfully.\n", pkgname); goto out;
}
} if (flags & XBPS_FLAG_VERBOSE)
} printf("Package %s purged successfully.\n", pkgname);
out: out:
xbps_regpkgs_dictionary_release(); xbps_regpkgdb_dictionary_release();
return rv; 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(), plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REGPKGDB); XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL) if (plist == NULL)
return EINVAL; return ENOMEM;
prop_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname); prop_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(pkgrd, "version", &version); prop_dictionary_get_cstring_nocopy(pkgrd, "version", &version);
@ -70,29 +70,24 @@ xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic)
"packages", pkgname); "packages", pkgname);
if (pkgd == NULL) { if (pkgd == NULL) {
rv = errno; rv = errno;
DPRINTF(("%s: find_pkg_in_dict_by_name failed: %s\n",
__func__, strerror(rv)));
goto out; goto out;
} }
if (!prop_dictionary_set_cstring_nocopy(pkgd, if (!prop_dictionary_set_cstring_nocopy(pkgd,
"version", version)) { "version", version)) {
prop_object_release(pkgd); prop_object_release(pkgd);
rv = errno; rv = EINVAL;
DPRINTF(("%s: version obj not found!\n", __func__));
goto out; goto out;
} }
if (!prop_dictionary_set_cstring_nocopy(pkgd, if (!prop_dictionary_set_cstring_nocopy(pkgd,
"pkgver", pkgver)) { "pkgver", pkgver)) {
prop_object_release(pkgd); prop_object_release(pkgd);
rv = errno; rv = EINVAL;
DPRINTF(("%s: pkgver obj not found!\n", __func__));
goto out; goto out;
} }
if (!prop_dictionary_set_cstring_nocopy(pkgd, if (!prop_dictionary_set_cstring_nocopy(pkgd,
"short_desc", desc)) { "short_desc", desc)) {
prop_object_release(pkgd); prop_object_release(pkgd);
rv = errno; rv = EINVAL;
DPRINTF(("%s: short_desc obj not found!\n", __func__));
goto out; goto out;
} }
if (!prop_dictionary_get_bool(pkgd, 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, if (!prop_dictionary_set_bool(pkgd,
"automatic-install", automatic)) { "automatic-install", automatic)) {
prop_object_release(pkgd); prop_object_release(pkgd);
rv = errno; rv = EINVAL;
DPRINTF(("%s: autoinst obj not found!\n",
__func__));
goto out; goto out;
} }
} }
@ -114,24 +107,19 @@ xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic)
array = prop_dictionary_get(dict, "packages"); array = prop_dictionary_get(dict, "packages");
if (array == NULL) { if (array == NULL) {
prop_object_release(pkgd); prop_object_release(pkgd);
rv = ENOENT; rv = EINVAL;
DPRINTF(("%s: packages array obj not found!\n",
__func__));
goto out; goto out;
} }
rv = xbps_requiredby_pkg_add(array, pkgrd); if ((rv = xbps_requiredby_pkg_add(array, pkgrd)) != 0)
if (rv != 0) {
prop_object_release(pkgd);
DPRINTF(("%s: requiredby_pkg_add failed %d\n",
__func__, rv));
goto out; goto out;
}
} }
/* /*
* Write plist file to storage. * Write plist file to storage.
*/ */
if (!prop_dictionary_externalize_to_zfile(dict, plist)) if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
rv = errno; rv = errno;
goto out;
}
} else { } else {
free(plist); free(plist);
return ENOENT; return ENOENT;
@ -154,9 +142,11 @@ xbps_unregister_pkg(const char *pkgname)
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(), plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REGPKGDB); XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL) 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); free(plist);
return rv; 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_iterator_t iter;
prop_object_t obj; prop_object_t obj;
const char *file, *sha256, *curobj = NULL; const char *file, *sha256, *curobj = NULL;
char *dname = NULL, *path = NULL; char *path = NULL;
int flags = 0, rv = 0; int flags = 0, rv = 0;
assert(dict != NULL); assert(dict != NULL);
@ -87,12 +87,14 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key)
flags = xbps_get_flags(); flags = xbps_get_flags();
array = prop_dictionary_get(dict, key); 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; return 0;
iter = xbps_get_array_iter_from_dict(dict, key); iter = xbps_get_array_iter_from_dict(dict, key);
if (iter == NULL) if (iter == NULL)
return errno; return ENOMEM;
if (strcmp(key, "files") == 0) if (strcmp(key, "files") == 0)
curobj = "file"; 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); prop_dictionary_get_cstring_nocopy(obj, "file", &file);
path = xbps_xasprintf("%s/%s", xbps_get_rootdir(), file); path = xbps_xasprintf("%s/%s", xbps_get_rootdir(), file);
if (path == NULL) { if (path == NULL) {
rv = errno; rv = ENOMEM;
break; break;
} }
if ((strcmp(key, "files") == 0) || if ((strcmp(key, "files") == 0) ||
(strcmp(key, "conf_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) if (flags & XBPS_FLAG_VERBOSE)
printf("Removed %s: %s\n", curobj, file); 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); free(path);
} }
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
@ -195,6 +179,7 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
prop_dictionary_t dict; prop_dictionary_t dict;
char *buf; char *buf;
int rv = 0; int rv = 0;
bool rmfile_exists = false;
assert(pkgname != NULL); assert(pkgname != NULL);
assert(version != 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", buf = xbps_xasprintf(".%s/metadata/%s/REMOVE",
XBPS_META_PATH, pkgname); XBPS_META_PATH, pkgname);
if (buf == NULL) if (buf == NULL)
return errno; return ENOMEM;
if (chdir(xbps_get_rootdir()) == -1) { if (chdir(xbps_get_rootdir()) == -1) {
free(buf); free(buf);
return errno; return EINVAL;
} }
/* /*
* Run the pre remove action. * Run the pre remove action.
*/ */
rv = xbps_file_exec(buf, "pre", pkgname, version, if (access(buf, X_OK) == 0) {
update ? "yes" : "no", NULL); rmfile_exists = true;
if (rv != 0 && errno != ENOENT) { if (xbps_file_exec(buf, "pre", pkgname, version,
fprintf(stderr, update ? "yes" : "no", NULL) != 0) {
"%s: prerm action target error (%s)\n", pkgname, fprintf(stderr,
strerror(errno)); "%s: prerm action target error (%s)\n",
free(buf); pkgname, strerror(errno));
return rv; 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 * Execute the post REMOVE action if file exists and we aren't
* updating the package. * updating the package.
*/ */
rv = xbps_file_exec(buf, "post", pkgname, version, "no", NULL); if (rmfile_exists &&
if (rv != 0 && errno != ENOENT) { (xbps_file_exec(buf, "post", pkgname, version, "no", NULL) != 0)) {
fprintf(stderr, fprintf(stderr,
"%s: postrm action target error (%s)\n", pkgname, "%s: postrm action target error (%s)\n", pkgname,
strerror(errno)); strerror(errno));
free(buf); free(buf);
return rv; return errno;
} }
free(buf); free(buf);
@ -293,5 +285,6 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
rv = xbps_set_pkg_state_installed(pkgname, rv = xbps_set_pkg_state_installed(pkgname,
XBPS_PKG_STATE_CONFIG_FILES); XBPS_PKG_STATE_CONFIG_FILES);
return rv; return rv;
} }

View File

@ -39,15 +39,15 @@
int HIDDEN int HIDDEN
xbps_remove_obsoletes(prop_dictionary_t oldd, prop_dictionary_t newd) xbps_remove_obsoletes(prop_dictionary_t oldd, prop_dictionary_t newd)
{ {
prop_object_iterator_t iter, iter2 = NULL; prop_object_iterator_t iter, iter2;
prop_object_t obj, obj2 = NULL; prop_object_t obj, obj2;
prop_string_t oldstr = NULL, newstr = NULL; prop_string_t oldstr, newstr;
struct stat st; struct stat st;
const char *array_str = "files"; const char *array_str = "files";
const char *oldhash = NULL; const char *oldhash;
char *dname = NULL, *file = NULL; char *file;
int rv = 0; int rv = 0;
bool found, dolinks = false; bool found, dodirs = false, dolinks = false;
again: again:
iter = xbps_get_array_iter_from_dict(oldd, array_str); iter = xbps_get_array_iter_from_dict(oldd, array_str);
@ -59,7 +59,7 @@ again:
return errno; 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. * the old package list not found in new package list.
*/ */
while ((obj = prop_object_iterator_next(iter))) { while ((obj = prop_object_iterator_next(iter))) {
@ -89,7 +89,7 @@ again:
rv = 0; rv = 0;
continue; continue;
} }
} else { } else if (strcmp(array_str, "links") == 0) {
/* /*
* Only remove dangling symlinks. * Only remove dangling symlinks.
*/ */
@ -123,32 +123,18 @@ again:
} }
/* /*
* Obsolete file found, remove it. * Obsolete obj found, remove it.
*/ */
if (remove(file) == -1) { if (remove(file) == -1) {
fprintf(stderr, fprintf(stderr,
"WARNING: couldn't remove obsolete %s: %s\n", "WARNING: couldn't remove obsolete obj: %s (%s)\n",
dolinks ? "link" : "file", prop_string_cstring_nocopy(oldstr),
prop_string_cstring_nocopy(oldstr)); strerror(errno));
free(file); free(file);
continue; continue;
} }
printf("Removed obsolete %s: %s\n", printf("Removed obsolete obj: %s\n",
dolinks ? "link" : "file",
prop_string_cstring_nocopy(oldstr)); 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) { if (!dolinks) {
/* /*
@ -161,6 +147,17 @@ again:
iter2 = NULL; iter2 = NULL;
goto again; 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: out:
prop_object_iterator_release(iter2); 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 (reqstr == NULL) {
if (alloc) if (alloc)
prop_object_release(array); prop_object_release(array);
return errno; return ENOMEM;
} }
if (!xbps_add_obj_to_array(array, reqstr)) { 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(), plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REGPKGDB); XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL) if (plist == NULL)
return EINVAL; return ENOMEM;
if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) { if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) {
free(plist); free(plist);
xbps_dbg_printf("[reqby-rm] cannot internalize "
"regpkgdb plist for '%s': %s\n", pkgname, strerror(errno));
return errno; return errno;
} }
rv = xbps_callback_array_iter_in_dict(dict, "packages", rv = xbps_callback_array_iter_in_dict(dict, "packages",
remove_pkg_from_reqby, __UNCONST(pkgname)); remove_pkg_from_reqby, __UNCONST(pkgname));
if (rv == 0) { if (rv != 0)
if (!prop_dictionary_externalize_to_zfile(dict, plist)) goto out;
rv = errno;
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); prop_object_release(dict);
free(plist); 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) { while ((obj = prop_object_iterator_next(iter)) != NULL) {
str = prop_string_cstring_nocopy(obj); str = prop_string_cstring_nocopy(obj);
if (str == NULL) { if (str == NULL) {
rv = errno; rv = EINVAL;
goto out; goto out;
} }
rdepname = xbps_get_pkgpattern_name(str); rdepname = xbps_get_pkgpattern_name(str);
@ -182,10 +189,11 @@ xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg)
rv = EINVAL; rv = EINVAL;
goto out; goto out;
} }
iter2 = prop_array_iterator(regar); iter2 = prop_array_iterator(regar);
if (iter2 == NULL) { if (iter2 == NULL) {
free(rdepname);
rv = ENOMEM; rv = ENOMEM;
free(rdepname);
goto out; 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)) if (!prop_dictionary_set_cstring_nocopy(dict, "state", state_str))
return -1; return EINVAL;
if (prop_dictionary_get_cstring_nocopy(dict, "pkgname", &pkgname)) { if (prop_dictionary_get_cstring_nocopy(dict, "pkgname", &pkgname)) {
DPRINTF(("%s: changed pkg state to '%s'.\n", xbps_dbg_printf("%s: changed pkg state to '%s'\n",
pkgname, state_str)); pkgname, state_str);
} }
return 0; 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(), plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REGPKGDB); XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL) if (plist == NULL)
return EINVAL; return ENOMEM;
if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) { if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) {
dict = prop_dictionary_create(); dict = prop_dictionary_create();
if (dict == NULL) { if (dict == NULL) {
rv = errno; rv = ENOMEM;
goto out; goto out;
} }
array = prop_array_create(); array = prop_array_create();
if (array == NULL) { if (array == NULL) {
rv = errno; rv = ENOMEM;
goto out; goto out;
} }
pkgd = prop_dictionary_create(); pkgd = prop_dictionary_create();
if (pkgd == NULL) { if (pkgd == NULL) {
rv = ENOMEM;
prop_object_release(array); prop_object_release(array);
rv = errno;
goto out; goto out;
} }
if (!prop_dictionary_set_cstring_nocopy(pkgd, "pkgname", if (!prop_dictionary_set_cstring_nocopy(pkgd, "pkgname",
pkgname)) { pkgname)) {
rv = EINVAL;
prop_object_release(array); prop_object_release(array);
prop_object_release(pkgd); prop_object_release(pkgd);
rv = errno;
goto out; goto out;
} }
if ((rv = set_new_state(pkgd, state)) != 0) { 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; goto out;
} }
if (!xbps_add_obj_to_array(array, pkgd)) { if (!xbps_add_obj_to_array(array, pkgd)) {
rv = EINVAL;
prop_object_release(array); prop_object_release(array);
prop_object_release(pkgd); prop_object_release(pkgd);
rv = errno;
goto out; goto out;
} }
if (!xbps_add_obj_to_dict(dict, array, "packages")) { if (!xbps_add_obj_to_dict(dict, array, "packages")) {
rv = EINVAL;
prop_object_release(array); prop_object_release(array);
rv = errno;
goto out; goto out;
} }
@ -204,20 +205,21 @@ xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state)
rv = errno; rv = errno;
goto out; goto out;
} }
newpkg = true; newpkg = true;
pkgd = prop_dictionary_create(); pkgd = prop_dictionary_create();
if (!prop_dictionary_set_cstring_nocopy(pkgd, if (!prop_dictionary_set_cstring_nocopy(pkgd,
"pkgname", pkgname)) { "pkgname", pkgname)) {
rv = EINVAL;
prop_object_release(pkgd); prop_object_release(pkgd);
rv = errno;
goto out; goto out;
} }
} }
array = prop_dictionary_get(dict, "packages"); array = prop_dictionary_get(dict, "packages");
if (array == NULL) { if (array == NULL) {
rv = EINVAL;
if (newpkg) if (newpkg)
prop_object_release(pkgd); prop_object_release(pkgd);
rv = errno;
goto out; goto out;
} }
if ((rv = set_new_state(pkgd, state)) != 0) { 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; goto out;
} }
if (newpkg && !xbps_add_obj_to_array(array, pkgd)) { if (newpkg && !xbps_add_obj_to_array(array, pkgd)) {
rv = EINVAL;
prop_object_release(pkgd); prop_object_release(pkgd);
rv = errno;
goto out; goto out;
} }
} }
if (!prop_dictionary_externalize_to_zfile(dict, plist)) if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
rv = errno; rv = errno;
xbps_dbg_printf("[pkgstate] cannot write plist '%s': %s\n",
plist, strerror(errno));
}
out: out:
if (dict) if (dict)

View File

@ -91,10 +91,12 @@ set_extract_flags(int *flags, bool update)
* the consumer. * the consumer.
*/ */
static int static int
unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, unpack_archive_fini(struct archive *ar,
const char *pkgname, const char *version) 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; struct archive_entry *entry;
size_t entry_idx = 0; size_t entry_idx = 0;
const char *rootdir, *entry_str, *transact; 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", buf = xbps_xasprintf(".%s/metadata/%s/INSTALL",
XBPS_META_PATH, pkgname); XBPS_META_PATH, pkgname);
if (buf == NULL) if (buf == NULL)
return errno; return ENOMEM;
if (unlink(buf) == -1) { if (unlink(buf) == -1) {
if (errno != ENOENT) { if (errno && errno != ENOENT) {
free(buf); free(buf);
return errno; return errno;
} }
@ -139,9 +142,10 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
buf = xbps_xasprintf(".%s/metadata/%s/REMOVE", buf = xbps_xasprintf(".%s/metadata/%s/REMOVE",
XBPS_META_PATH, pkgname); XBPS_META_PATH, pkgname);
if (buf == NULL) if (buf == NULL)
return errno; return ENOMEM;
if (unlink(buf) == -1) { if (unlink(buf) == -1) {
if (errno != ENOENT) { if (errno && errno != ENOENT) {
free(buf); free(buf);
return errno; return errno;
} }
@ -161,16 +165,18 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
if (strcmp("./INSTALL", entry_str) == 0) { if (strcmp("./INSTALL", entry_str) == 0) {
buf = xbps_xasprintf(".%s/metadata/%s/INSTALL", buf = xbps_xasprintf(".%s/metadata/%s/INSTALL",
XBPS_META_PATH, pkgname); XBPS_META_PATH, pkgname);
if (buf == NULL) if (buf == NULL) {
return errno; rv = ENOMEM;
goto out;
}
archive_entry_set_pathname(entry, buf); 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 (archive_read_extract(ar, entry, lflags) != 0) {
if ((rv = archive_errno(ar)) != EEXIST) { if ((rv = archive_errno(ar)) != EEXIST) {
free(buf); free(buf);
return rv; goto out;
} }
} }
@ -181,7 +187,7 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
fprintf(stderr, fprintf(stderr,
"%s: preinst action target error %s\n", "%s: preinst action target error %s\n",
pkgname, strerror(errno)); pkgname, strerror(errno));
return rv; goto out;
} }
/* Pass to the next entry if successful */ /* Pass to the next entry if successful */
free(buf); free(buf);
@ -194,13 +200,18 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
} else if (strcmp("./REMOVE", entry_str) == 0) { } else if (strcmp("./REMOVE", entry_str) == 0) {
buf = xbps_xasprintf(".%s/metadata/%s/REMOVE", buf = xbps_xasprintf(".%s/metadata/%s/REMOVE",
XBPS_META_PATH, pkgname); XBPS_META_PATH, pkgname);
if (buf == NULL) if (buf == NULL) {
return errno; rv = ENOMEM;
goto out;
}
archive_entry_set_pathname(entry, buf); archive_entry_set_pathname(entry, buf);
free(buf); free(buf);
archive_entry_set_mode(entry, 0750); archive_entry_set_perm(entry, 0750);
if (archive_read_extract(ar, entry, lflags) != 0) if (archive_read_extract(ar, entry, lflags) != 0) {
return archive_errno(ar); if ((rv = archive_errno(ar)) != EEXIST)
goto out;
}
/* Pass to next entry if successful */ /* Pass to next entry if successful */
entry_idx++; entry_idx++;
@ -213,8 +224,10 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
* all files are extracted. * all files are extracted.
*/ */
filesd = xbps_read_dict_from_archive_entry(ar, entry); filesd = xbps_read_dict_from_archive_entry(ar, entry);
if (filesd == NULL) if (filesd == NULL) {
return errno; rv = errno;
goto out;
}
/* Pass to next entry */ /* Pass to next entry */
files_plist_found = true; files_plist_found = true;
@ -222,36 +235,30 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
continue; continue;
} else if (strcmp("./props.plist", entry_str) == 0) { } else if (strcmp("./props.plist", entry_str) == 0) {
buf = xbps_xasprintf(".%s/metadata/%s/props.plist", buf = xbps_xasprintf(".%s/metadata/%s/%s",
XBPS_META_PATH, pkgname); XBPS_META_PATH, pkgname, XBPS_PKGPROPS);
if (buf == NULL) if (buf == NULL) {
return errno; rv = ENOMEM;
goto out;
}
archive_entry_set_pathname(entry, buf); archive_entry_set_pathname(entry, buf);
free(buf); free(buf);
if (archive_read_extract(ar, entry, lflags) != 0) if (archive_read_extract(ar, entry, lflags) != 0)
return archive_errno(ar); 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 */ /* Pass to next entry if successful */
props_plist_found = true; props_plist_found = true;
entry_idx++; entry_idx++;
continue; 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. * This is not an XBPS binary package.
*/ */
if (entry_idx >= 3) if (entry_idx >= 3)
return ENOPKG; return ENODEV;
entry_idx++; entry_idx++;
continue; 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): * 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) { if (archive_read_extract(ar, entry, lflags) != 0) {
rv = archive_errno(ar); rv = archive_errno(ar);
if (rv != EEXIST) { if (rv && rv != EEXIST) {
fprintf(stderr, "ERROR: %s...exiting!\n", fprintf(stderr, "ERROR: %s...exiting!\n",
archive_error_string(ar)); archive_error_string(ar));
return rv;; goto out;
} else if (rv == EEXIST) { } else if (rv == EEXIST) {
if (flags & XBPS_FLAG_VERBOSE) { if (flags & XBPS_FLAG_VERBOSE) {
fprintf(stderr, fprintf(stderr,
@ -322,33 +348,33 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
} }
if ((rv = archive_errno(ar)) == 0) { if ((rv = archive_errno(ar)) == 0) {
buf = xbps_xasprintf(".%s/metadata/%s/files.plist", buf = xbps_xasprintf(".%s/metadata/%s/%s",
XBPS_META_PATH, pkgname); XBPS_META_PATH, pkgname, XBPS_PKGFILES);
if (buf == NULL) { if (buf == NULL) {
prop_object_release(filesd); prop_object_release(filesd);
return errno; return ENOMEM;
} }
/* /*
* Check if files.plist exists and pkg is NOT marked as * Check if files.plist exists and pkg is NOT marked as
* preserve, in that case we need to check for obsolete files * preserve, in that case we need to check for obsolete files
* and remove them if necessary. * and remove them if necessary.
*/ */
if (!preserve && (access(buf, R_OK) == 0)) { if (!preserve) {
old_filesd = old_filesd =
prop_dictionary_internalize_from_zfile(buf); 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); prop_object_release(filesd);
free(buf); free(buf);
return errno; 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 * Now that all files were successfully unpacked, we
@ -362,8 +388,12 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg,
} }
free(buf); free(buf);
} }
out:
if (filesd) if (filesd)
prop_object_release(filesd); prop_object_release(filesd);
if (propsd)
prop_object_release(propsd);
return rv; return rv;
} }
@ -388,6 +418,8 @@ xbps_unpack_binary_pkg(prop_dictionary_t pkg)
if ((pkg_fd = open(binfile, O_RDONLY)) == -1) { if ((pkg_fd = open(binfile, O_RDONLY)) == -1) {
rv = errno; rv = errno;
xbps_dbg_printf("cannot open '%s' for unpacking %s\n",
binfile, strerror(errno));
goto out; goto out;
} }
@ -403,9 +435,11 @@ xbps_unpack_binary_pkg(prop_dictionary_t pkg)
archive_read_support_compression_all(ar); archive_read_support_compression_all(ar);
archive_read_support_format_tar(ar); archive_read_support_format_tar(ar);
if ((rv = archive_read_open_fd(ar, pkg_fd, if (archive_read_open_fd(ar, pkg_fd,
ARCHIVE_READ_BLOCKSIZE)) != 0) ARCHIVE_READ_BLOCKSIZE) != 0) {
rv = errno;
goto out; goto out;
}
if ((rv = unpack_archive_fini(ar, pkg, pkgname, version)) != 0) if ((rv = unpack_archive_fini(ar, pkg, pkgname, version)) != 0)
goto out; 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)) { if (!prop_dictionary_set(dict, key, obj)) {
prop_object_release(dict); prop_object_release(dict);
errno = EINVAL;
return false; 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)) { if (!prop_array_add(array, obj)) {
prop_object_release(array); prop_object_release(array);
errno = EINVAL;
return false; return false;
} }
@ -98,6 +100,7 @@ xbps_callback_array_iter_in_dict(prop_dictionary_t dict, const char *key,
} }
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
return rv; return rv;
} }
@ -116,8 +119,10 @@ xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict,
assert(fn != NULL); assert(fn != NULL);
array = prop_dictionary_get(dict, key); 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; return EINVAL;
}
if ((cnt = prop_array_count(array)) == 0) if ((cnt = prop_array_count(array)) == 0)
return 0; return 0;
@ -141,8 +146,11 @@ xbps_find_pkg_from_plist(const char *plist, const char *pkgname)
assert(pkgname != NULL); assert(pkgname != NULL);
dict = prop_dictionary_internalize_from_zfile(plist); 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; return NULL;
}
obj = xbps_find_pkg_in_dict_by_name(dict, "packages", pkgname); obj = xbps_find_pkg_in_dict_by_name(dict, "packages", pkgname);
if (obj == NULL) { if (obj == NULL) {
@ -162,7 +170,7 @@ xbps_find_pkg_dict_installed(const char *str, bool bypattern)
prop_dictionary_t d, pkgd, rpkgd = NULL; prop_dictionary_t d, pkgd, rpkgd = NULL;
pkg_state_t state = 0; pkg_state_t state = 0;
if ((d = xbps_regpkgs_dictionary_init()) == NULL) if ((d = xbps_regpkgdb_dictionary_get()) == NULL)
return NULL; return NULL;
if (bypattern) if (bypattern)
@ -182,12 +190,14 @@ xbps_find_pkg_dict_installed(const char *str, bool bypattern)
break; break;
case XBPS_PKG_STATE_CONFIG_FILES: case XBPS_PKG_STATE_CONFIG_FILES:
errno = ENOENT; errno = ENOENT;
xbps_dbg_printf("'%s' installed but its state is "
"config-files\n",str);
break; break;
default: default:
break; break;
} }
out: out:
xbps_regpkgs_dictionary_release(); xbps_regpkgdb_dictionary_release();
return rpkgd; return rpkgd;
} }
@ -213,8 +223,10 @@ xbps_find_pkg_in_dict_by_name(prop_dictionary_t dict,
break; break;
} }
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
if (obj == NULL) if (obj == NULL) {
errno = ENOENT; errno = ENOENT;
return NULL;
}
return obj; return obj;
} }
@ -241,8 +253,10 @@ xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t dict,
break; break;
} }
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
if (obj == NULL) if (obj == NULL) {
errno = ENOENT; errno = ENOENT;
return NULL;
}
return obj; return obj;
} }
@ -270,6 +284,7 @@ xbps_find_string_in_array(prop_array_t array, const char *val)
} }
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
return false; return false;
} }
@ -282,8 +297,10 @@ xbps_get_array_iter_from_dict(prop_dictionary_t dict, const char *key)
assert(key != NULL); assert(key != NULL);
array = prop_dictionary_get(dict, key); 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 NULL;
}
return prop_array_iterator(array); 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); plistd = prop_dictionary_internalize_from_zfile(plistf);
free(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; return plistd;
} }
int bool
xbps_remove_string_from_array(prop_array_t array, const char *str) xbps_remove_string_from_array(prop_array_t array, const char *str)
{ {
prop_object_t obj; 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); iter = prop_array_iterator(array);
if (iter == NULL) if (iter == NULL)
return errno; return false;
while ((obj = prop_object_iterator_next(iter)) != NULL) { while ((obj = prop_object_iterator_next(iter)) != NULL) {
if (prop_string_equals_cstring(obj, str)) { if (prop_string_equals_cstring(obj, str)) {
@ -331,16 +353,19 @@ xbps_remove_string_from_array(prop_array_t array, const char *str)
idx++; idx++;
} }
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
if (found == false) if (!found) {
return ENOENT; errno = ENOENT;
return false;
}
prop_array_remove(array, idx); prop_array_remove(array, idx);
return 0; return true;
} }
int bool
xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key, xbps_remove_pkg_from_dict(prop_dictionary_t dict,
const char *key,
const char *pkgname) const char *pkgname)
{ {
prop_array_t array; prop_array_t array;
@ -355,12 +380,16 @@ xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key,
assert(pkgname != NULL); assert(pkgname != NULL);
array = prop_dictionary_get(dict, key); 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) {
return EINVAL; errno = EINVAL;
xbps_dbg_printf("invalid array type for key: %s pkgname: %s\n",
key, pkgname);
return false;
}
iter = prop_array_iterator(array); iter = prop_array_iterator(array);
if (iter == NULL) if (iter == NULL)
return errno; return false;
/* Iterate over the array of dictionaries to find its index. */ /* Iterate over the array of dictionaries to find its index. */
while ((obj = prop_object_iterator_next(iter))) { while ((obj = prop_object_iterator_next(iter))) {
@ -372,41 +401,46 @@ xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key,
i++; i++;
} }
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
if (found == true) if (found) {
prop_array_remove(array, i); prop_array_remove(array, i);
else return true;
return ENOENT; }
return 0; errno = ENOENT;
return false;
} }
int bool
xbps_remove_pkg_dict_from_file(const char *pkg, const char *plist) xbps_remove_pkg_dict_from_file(const char *pkg, const char *plist)
{ {
prop_dictionary_t pdict; prop_dictionary_t pdict;
int rv = 0;
assert(pkg != NULL); assert(pkg != NULL);
assert(plist != NULL); assert(plist != NULL);
pdict = prop_dictionary_internalize_from_zfile(plist); pdict = prop_dictionary_internalize_from_zfile(plist);
if (pdict == NULL) if (pdict == NULL) {
return errno; 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 (!xbps_remove_pkg_from_dict(pdict, "packages", pkg)) {
if (rv != 0) {
prop_object_release(pdict); prop_object_release(pdict);
return rv; return false;
} }
if (!prop_dictionary_externalize_to_zfile(pdict, plist)) { 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); prop_object_release(pdict);
return errno; return false;
} }
prop_object_release(pdict); 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -33,7 +33,7 @@
#include "xbps_api_impl.h" #include "xbps_api_impl.h"
/** /**
* @file lib/regpkgs_dictionary.c * @file lib/regpkgdb_dictionary.c
* @brief Package register database routines * @brief Package register database routines
* @defgroup regpkgdb Package register database functions * @defgroup regpkgdb Package register database functions
* *
@ -57,43 +57,45 @@
* dictionary. * dictionary.
*/ */
static prop_dictionary_t regpkgs_dict; static prop_dictionary_t regpkgdb_dict;
static size_t regpkgs_refcount; static size_t regpkgdb_refcount;
static bool regpkgs_initialized; static bool regpkgdb_initialized;
prop_dictionary_t prop_dictionary_t
xbps_regpkgs_dictionary_init(void) xbps_regpkgdb_dictionary_get(void)
{ {
char *plist; char *plist;
if (regpkgs_initialized == false) { if (regpkgdb_initialized == false) {
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(), plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REGPKGDB); XBPS_META_PATH, XBPS_REGPKGDB);
if (plist == NULL) if (plist == NULL)
return NULL; return NULL;
regpkgs_dict = prop_dictionary_internalize_from_zfile(plist); regpkgdb_dict = prop_dictionary_internalize_from_zfile(plist);
if (regpkgs_dict == NULL) { if (regpkgdb_dict == NULL) {
free(plist); free(plist);
xbps_dbg_printf("[regpkgdb] cannot internalize "
"regpkgdb_dict %s\n", strerror(errno));
return NULL; return NULL;
} }
free(plist); free(plist);
regpkgs_initialized = true; regpkgdb_initialized = true;
DPRINTF(("%s: initialized ok.\n", __func__)); xbps_dbg_printf("%s: initialized ok.\n", __func__);
} }
regpkgs_refcount++; regpkgdb_refcount++;
return regpkgs_dict; return regpkgdb_dict;
} }
void void
xbps_regpkgs_dictionary_release(void) xbps_regpkgdb_dictionary_release(void)
{ {
if (--regpkgs_refcount > 0) if (--regpkgdb_refcount > 0)
return; return;
prop_object_release(regpkgs_dict); prop_object_release(regpkgdb_dict);
regpkgs_dict = NULL; regpkgdb_dict = NULL;
regpkgs_initialized = false; regpkgdb_initialized = false;
DPRINTF(("%s: released ok.\n", __func__)); xbps_dbg_printf("%s: released ok.\n", __func__);
} }

View File

@ -69,6 +69,7 @@ xbps_repository_register(const char *uri)
rv = errno; rv = errno;
goto out; goto out;
} }
if (!prop_array_set_cstring_nocopy(array, 0, uri)) { if (!prop_array_set_cstring_nocopy(array, 0, uri)) {
rv = errno; rv = errno;
goto out; goto out;
@ -78,6 +79,7 @@ xbps_repository_register(const char *uri)
rv = errno; rv = errno;
goto out; goto out;
} }
xbps_dbg_printf("Added repository into plist: %s\n", uri);
} else { } else {
/* Append into the array, the plist file exists. */ /* Append into the array, the plist file exists. */
array = prop_dictionary_get(dict, "repository-list"); array = prop_dictionary_get(dict, "repository-list");
@ -97,14 +99,16 @@ xbps_repository_register(const char *uri)
rv = errno; rv = errno;
goto out; goto out;
} }
xbps_dbg_printf("Added repository into plist: %s\n", uri);
} }
/* Write dictionary into plist file. */ /* Write dictionary into plist file. */
if (!prop_dictionary_externalize_to_zfile(dict, plist)) { 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) if (obj)
prop_object_release(obj); prop_object_release(obj);
rv = errno;
goto out;
} }
out: out:
@ -142,14 +146,18 @@ xbps_repository_unregister(const char *uri)
goto out; goto out;
} }
if ((rv = xbps_remove_string_from_array(array, uri)) == 0) { if (!xbps_remove_string_from_array(array, uri)) {
/* Update plist file. */ rv = errno;
if (!prop_dictionary_externalize_to_zfile(dict, plist)) { goto out;
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 * If it's a remote repository, also remove the stored XBPS_PKGINDEX
* file and its directory. * file and its directory.
@ -157,26 +165,27 @@ xbps_repository_unregister(const char *uri)
if (xbps_check_is_repo_string_remote(uri)) { if (xbps_check_is_repo_string_remote(uri)) {
pkgindex = xbps_get_pkg_index_plist(uri); pkgindex = xbps_get_pkg_index_plist(uri);
if (pkgindex == NULL) { if (pkgindex == NULL) {
rv = EINVAL; rv = errno;
goto out; goto out;
} }
if (unlink(pkgindex) == -1) { if (unlink(pkgindex) == -1) {
rv = errno;
if (errno == ENOENT) { if (errno == ENOENT) {
free(pkgindex); free(pkgindex);
goto out; goto out;
} }
fprintf(stderr, "E: cannot remove pkgindex file at " xbps_dbg_printf("%s cannot remove pkgindex file at "
"%s: %s\n", pkgindex, strerror(errno)); "%s: %s\n", __func__, pkgindex, strerror(errno));
free(pkgindex); free(pkgindex);
rv = errno;
goto out; goto out;
} }
pkgindexdir = dirname(pkgindex); pkgindexdir = dirname(pkgindex);
if (rmdir(pkgindexdir) == -1) { if (rmdir(pkgindexdir) == -1) {
fprintf(stderr, "E: cannot remove pkgindex dir at "
"%s: %s\n", pkgindexdir, strerror(errno));
free(pkgindex);
rv = errno; rv = errno;
xbps_dbg_printf("%s: cannot remove pkgindex dir at "
"%s: %s\n", __func__, pkgindexdir, strerror(errno));
free(pkgindex);
goto out; goto out;
} }
free(pkgindex); 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_dictionary_t dict;
prop_array_t array; prop_array_t array;
const char *pkgname, *pkgver; const char *pkgname, *pkgver;
int flags = xbps_get_flags(), rv = 0; int rv = 0;
pkg_state_t state = 0; pkg_state_t state = 0;
assert(trans_dict != NULL); 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 * Always set "not-installed" package state. Will be overwritten
* to its correct state later. * to its correct state later.
*/ */
xbps_dbg_printf_append("\n");
rv = xbps_set_pkg_state_dictionary(dict, XBPS_PKG_STATE_NOT_INSTALLED); rv = xbps_set_pkg_state_dictionary(dict, XBPS_PKG_STATE_NOT_INSTALLED);
if (rv != 0) { if (rv != 0) {
prop_object_release(dict); prop_object_release(dict);
return rv; return rv;
} }
/* /*
* Overwrite package state in dictionary if it was unpacked * Overwrite package state in dictionary if it was unpacked
* previously. * previously.
*/ */
rv = xbps_get_pkg_state_installed(pkgname, &state); if ((rv = xbps_get_pkg_state_installed(pkgname, &state)) == 0) {
if (rv == 0) {
if ((rv = xbps_set_pkg_state_dictionary(dict, state)) != 0) { if ((rv = xbps_set_pkg_state_dictionary(dict, state)) != 0) {
prop_object_release(dict); prop_object_release(dict);
return rv; return rv;
@ -97,9 +98,8 @@ store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict,
prop_object_release(dict); prop_object_release(dict);
return EINVAL; return EINVAL;
} }
if (flags & XBPS_FLAG_VERBOSE) xbps_dbg_printf("Added package '%s' into "
printf("\n Added package '%s' into the transaction (%s).\n", "the transaction (%s).\n", pkgver, repoloc);
pkgver, repoloc);
return 0; 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 * if new dependency version is greater than current
* one, store it. * one, store it.
*/ */
DPRINTF(("Missing pkgdep name matched, curver: %s " xbps_dbg_printf("Missing pkgdep name matched, "
"newver: %s\n", curver, pkgver)); "curver: %s newver: %s\n", curver, pkgver);
if (xbps_cmpver(curver, pkgver) <= 0) { if (xbps_cmpver(curver, pkgver) <= 0) {
add_pkgdep = false; add_pkgdep = false;
free(curpkgnamedep); free(curpkgnamedep);
@ -250,7 +250,7 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
pkg_state_t state = 0; pkg_state_t state = 0;
const char *reqpkg, *reqvers, *pkg_queued, *repo_pkgver; const char *reqpkg, *reqvers, *pkg_queued, *repo_pkgver;
char *pkgname; char *pkgname;
int flags = xbps_get_flags(), rv = 0; int rv = 0;
iter = prop_array_iterator(pkg_rdeps_array); iter = prop_array_iterator(pkg_rdeps_array);
if (iter == NULL) if (iter == NULL)
@ -266,26 +266,25 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
rv = EINVAL; rv = EINVAL;
break; break;
} }
if (flags & XBPS_FLAG_VERBOSE) { if (originpkgn)
if (originpkgn) xbps_dbg_printf(" %s requires dependency '%s' "
printf(" %s requires dependency '%s' " "[direct]: ", originpkgn, reqpkg);
"[direct]: ", originpkgn, reqpkg); else
else xbps_dbg_printf(" requires dependency '%s' "
printf(" requires dependency '%s' " "[indirect]: ", reqpkg);
"[indirect]: ", reqpkg);
}
/* /*
* Check if required dep is satisfied and installed. * Check if required dep is satisfied and installed.
*/ */
rv = xbps_check_is_installed_pkg(reqpkg); rv = xbps_check_is_installed_pkg(reqpkg);
if (rv == -1) { if (rv == -1) {
/* There was an error checking it... */ /* There was an error checking it... */
DPRINTF(("Error matching reqdep %s\n", reqpkg)); xbps_dbg_printf_append("error matching reqdep %s\n",
reqpkg);
break; break;
} else if (rv == 1) { } else if (rv == 1) {
/* Required pkg dependency is satisfied */ /* Required pkg dependency is satisfied */
if (flags & XBPS_FLAG_VERBOSE) xbps_dbg_printf_append("satisfied and installed.\n");
printf("satisfied and installed.\n");
rv = 0; rv = 0;
continue; continue;
} }
@ -318,8 +317,8 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
"pkgver", &pkg_queued); "pkgver", &pkg_queued);
if (xbps_pkgpattern_match(pkg_queued, if (xbps_pkgpattern_match(pkg_queued,
__UNCONST(reqpkg))) { __UNCONST(reqpkg))) {
if (flags & XBPS_FLAG_VERBOSE) xbps_dbg_printf_append(
printf("queued in the transaction.\n"); "queued in the transaction.\n");
free(pkgname); free(pkgname);
continue; 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); rv = add_missing_reqdep(trans_dict, reqpkg);
if (rv != 0 && rv != EEXIST) { if (rv != 0 && rv != EEXIST) {
DPRINTF(("add missing reqdep failed %s\n", xbps_dbg_printf_append("add missing reqdep "
reqpkg)); "failed %s\n", reqpkg);
free(pkgname); free(pkgname);
break; break;
} else if (rv == EEXIST) { } else if (rv == EEXIST) {
DPRINTF(("Missing dep %s already added.\n", xbps_dbg_printf_append("missing dep %s "
reqpkg)); "already added.\n", reqpkg);
rv = 0; rv = 0;
free(pkgname); free(pkgname);
continue; continue;
} else { } else {
if (flags & XBPS_FLAG_VERBOSE) xbps_dbg_printf_append(
printf("missing package in repository!\n"); "missing package in repository!\n");
free(pkgname); free(pkgname);
continue; 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. * Package is on repo, add it into the dictionary.
*/ */
if ((rv = store_dependency(trans_dict, curpkgd, rv = store_dependency(trans_dict, curpkgd, repoloc);
repoloc)) != 0) { if (rv != 0) {
DPRINTF(("store_dependency failed %s\n", reqpkg)); xbps_dbg_printf("store_dependency failed %s",
reqpkg);
free(pkgname); free(pkgname);
break; break;
} }
@ -416,10 +416,10 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
if (rv == ENOENT) { if (rv == ENOENT) {
rv = 0; rv = 0;
} else if (rv == 0) { } else if (rv == 0) {
DPRINTF(("Removed missing dep %s.\n", reqpkg)); xbps_dbg_printf("Removed missing dep %s.\n", reqpkg);
} else { } else {
DPRINTF(("Removing missing dep %s returned %s\n", xbps_dbg_printf("Removing missing dep %s "
reqpkg, strerror(rv))); "returned %s\n", reqpkg, strerror(rv));
free(pkgname); free(pkgname);
break; 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. * Iterate on required pkg to find more deps.
*/ */
if (flags & XBPS_FLAG_VERBOSE) xbps_dbg_printf_append("\n");
printf(" Finding dependencies for '%s-%s' [%s]:\n", xbps_dbg_printf("Finding dependencies for '%s-%s' [%s]:\n",
pkgname, reqvers, originpkgn ? "direct" : "indirect"); pkgname, reqvers, originpkgn ? "direct" : "indirect");
free(pkgname); free(pkgname);
if ((rv = find_repo_deps(trans_dict, repo_dict, repoloc, if ((rv = find_repo_deps(trans_dict, repo_dict, repoloc,
NULL, curpkg_rdeps)) != 0) { NULL, curpkg_rdeps)) != 0) {
DPRINTF(("Error checking %s rundeps %s\n", xbps_dbg_printf("Error checking %s for rundeps: %s\n",
reqpkg, strerror(errno))); reqpkg, strerror(rv));
break; break;
} }
} }
@ -453,14 +453,34 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
return rv; 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 int HIDDEN
xbps_repository_find_pkg_deps(prop_dictionary_t trans_dict, xbps_repository_find_pkg_deps(prop_dictionary_t trans_dict,
prop_dictionary_t repo_pkg_dict) prop_dictionary_t repo_pkg_dict)
{ {
prop_array_t pkg_rdeps, missing_rdeps; prop_array_t pkg_rdeps, missing_rdeps;
struct repository_pool *rpool; struct rpool_index_data *rid;
const char *pkgname, *pkgver; const char *pkgname, *pkgver;
int flags = xbps_get_flags(), rv = 0; int rv = 0;
assert(trans_dict != NULL); assert(trans_dict != NULL);
assert(repo_pkg_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) if (pkg_rdeps == NULL)
return 0; 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, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(repo_pkg_dict, "pkgver", &pkgver); prop_dictionary_get_cstring_nocopy(repo_pkg_dict, "pkgver", &pkgver);
if ((rv = xbps_repository_pool_init()) != 0) if ((rv = xbps_repository_pool_init()) != 0)
return rv; goto out;
if (flags & XBPS_FLAG_VERBOSE) xbps_dbg_printf("Finding required dependencies for '%s':\n", pkgver);
printf(" Finding required dependencies for '%s':\n", pkgver);
/* /*
* Iterate over the repository pool and find out if we have * Iterate over the repository pool and find out if we have
* all available binary packages. * all available binary packages.
*/ */
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { rid->transd = trans_dict;
/* rid->rdeps = pkg_rdeps;
* This will find direct and indirect deps, rid->pkgname = pkgname;
* if any of them is not there it will be added
* into the missing_deps array. /*
*/ * This will find direct and indirect deps,
if ((rv = find_repo_deps(trans_dict, rpool->rp_repod, * if any of them is not there it will be added
rpool->rp_uri, pkgname, pkg_rdeps)) != 0) { * into the missing_deps array.
DPRINTF(("Error '%s' while checking rundeps!\n", */
strerror(rv))); rv = xbps_repository_pool_foreach(find_repo_deps_in_pool, rid);
goto out; 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 * Iterate one more time, but this time with missing deps
* that were found in previous pass. * that were found in previous pass.
*/ */
DPRINTF(("Checking for missing deps in %s.\n", pkgname)); rid->rdeps = missing_rdeps;
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { rid->pkgname = NULL;
if ((rv = find_repo_deps(trans_dict, rpool->rp_repod,
rpool->rp_uri, pkgname, missing_rdeps)) != 0) { xbps_dbg_printf("Checking for missing deps in %s.\n", pkgname);
DPRINTF(("Error '%s' while checking for " rv = xbps_repository_pool_foreach(find_repo_deps_in_pool, rid);
"missing rundeps!\n", strerror(rv))); if (rv != 0) {
goto out; xbps_dbg_printf("Error '%s' while checking for "
} "missing rundeps!\n", strerror(errno));
goto out;
} }
out: out:
if (rid)
free(rid);
xbps_repository_pool_release(); xbps_repository_pool_release();
return rv; return rv;

View File

@ -56,6 +56,16 @@
static prop_dictionary_t trans_dict; static prop_dictionary_t trans_dict;
static bool trans_dict_initialized; 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 static int
create_transaction_dictionary(void) create_transaction_dictionary(void)
{ {
@ -77,31 +87,31 @@ create_transaction_dictionary(void)
unsorted = prop_array_create(); unsorted = prop_array_create();
if (unsorted == NULL) { if (unsorted == NULL) {
rv = ENOMEM; rv = ENOMEM;
goto fail2; goto fail2;
} }
if (!xbps_add_obj_to_dict(trans_dict, missing, "missing_deps")) { if (!xbps_add_obj_to_dict(trans_dict, missing, "missing_deps")) {
rv = EINVAL; rv = EINVAL;
goto fail3; goto fail3;
} }
if (!xbps_add_obj_to_dict(trans_dict, unsorted, "unsorted_deps")) { if (!xbps_add_obj_to_dict(trans_dict, unsorted, "unsorted_deps")) {
rv = EINVAL; rv = EINVAL;
goto fail3; goto fail3;
} }
trans_dict_initialized = true; trans_dict_initialized = true;
return rv; return rv;
fail3: fail3:
prop_object_release(unsorted); prop_object_release(unsorted);
fail2: fail2:
prop_object_release(missing); prop_object_release(missing);
fail: fail:
prop_object_release(trans_dict); prop_object_release(trans_dict);
return rv; return rv;
} }
static int static int
@ -115,7 +125,7 @@ compute_transaction_sizes(void)
iter = xbps_get_array_iter_from_dict(trans_dict, "packages"); iter = xbps_get_array_iter_from_dict(trans_dict, "packages");
if (iter == NULL) if (iter == NULL)
return -1; return EINVAL;
while ((obj = prop_object_iterator_next(iter)) != NULL) { while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "trans-action", &tract); prop_dictionary_get_cstring_nocopy(obj, "trans-action", &tract);
@ -139,7 +149,7 @@ compute_transaction_sizes(void)
*/ */
if (!prop_dictionary_set_uint64(trans_dict, if (!prop_dictionary_set_uint64(trans_dict,
"total-installed-size", instsize)) { "total-installed-size", instsize)) {
rv = -1; rv = EINVAL;
goto out; goto out;
} }
/* /*
@ -148,7 +158,7 @@ compute_transaction_sizes(void)
*/ */
if (!prop_dictionary_set_uint64(trans_dict, if (!prop_dictionary_set_uint64(trans_dict,
"total-download-size", dlsize)) { "total-download-size", dlsize)) {
rv = -1; rv = EINVAL;
goto out; goto out;
} }
out: out:
@ -172,11 +182,14 @@ set_pkg_state(prop_dictionary_t pkgd, const char *pkgname)
*/ */
rv = xbps_get_pkg_state_installed(pkgname, &state); rv = xbps_get_pkg_state_installed(pkgname, &state);
if (rv == 0) { if (rv == 0) {
if (state == XBPS_PKG_STATE_INSTALLED)
return 0;
if ((rv = xbps_set_pkg_state_dictionary(pkgd, state)) != 0) if ((rv = xbps_set_pkg_state_dictionary(pkgd, state)) != 0)
return rv; return rv;
} else if (rv == ENOENT) } else if (rv == ENOENT)
rv = 0; rv = 0;
return rv; return rv;
} }
@ -186,23 +199,23 @@ xbps_repository_get_transaction_dict(void)
int rv = 0; int rv = 0;
if (trans_dict_initialized == false) { if (trans_dict_initialized == false) {
errno = ENOENT; errno = ENXIO;
return NULL; return NULL;
} }
/* /*
* Sort package list if necessary. * Sort package dependencies if necessary.
*/ */
if ((rv = xbps_sort_pkg_deps(trans_dict)) != 0) { 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 * return the dictionary, the client should always
* check if that's the case. * check if that's the case.
*/ */
if (errno == ENOENT) if (rv == ENOENT)
return trans_dict; return trans_dict;
errno = rv;
return NULL; return NULL;
} }
@ -213,6 +226,11 @@ xbps_repository_get_transaction_dict(void)
if (compute_transaction_sizes() != 0) if (compute_transaction_sizes() != 0)
return NULL; return NULL;
/*
* Remove the "missing_deps" array now that it's not needed.
*/
prop_dictionary_remove(trans_dict, "missing_deps");
return trans_dict; return trans_dict;
} }
@ -229,16 +247,13 @@ xbps_repository_update_allpkgs(void)
/* /*
* Prepare dictionary with all registered packages. * Prepare dictionary with all registered packages.
*/ */
dict = xbps_regpkgs_dictionary_init(); dict = xbps_regpkgdb_dictionary_get();
if (dict == NULL) if (dict == NULL)
return ENOENT; return errno;
if ((rv = xbps_repository_pool_init()) != 0)
goto out;
iter = xbps_get_array_iter_from_dict(dict, "packages"); iter = xbps_get_array_iter_from_dict(dict, "packages");
if (iter == NULL) { if (iter == NULL) {
rv = EINVAL; rv = errno;
goto out; goto out;
} }
@ -248,40 +263,96 @@ xbps_repository_update_allpkgs(void)
*/ */
while ((obj = prop_object_iterator_next(iter)) != NULL) { while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
rv = xbps_repository_update_pkg(pkgname, obj); if ((rv = xbps_repository_update_pkg(pkgname)) != 0) {
if (rv == ENOENT) if (rv == ENOENT || rv == EEXIST)
continue; continue;
else if (rv == EEXIST) {
rv = 0;
continue;
} else if (rv != 0)
break;
xbps_dbg_printf("[update-all] '%s' returned: %s\n",
pkgname, strerror(rv));
goto out;
}
newpkg_found = true; newpkg_found = true;
} }
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
if (rv != ENOENT && !newpkg_found) if (newpkg_found)
rv = ENOPKG; rv = 0;
else
rv = ENXIO;
out: out:
xbps_repository_pool_release(); xbps_regpkgdb_dictionary_release();
xbps_regpkgs_dictionary_release();
return rv; return rv;
} }
int struct rpool_index_data {
xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg) 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; struct rpool_index_data *rid = arg;
prop_array_t unsorted; prop_dictionary_t instpkgd;
struct repository_pool *rpool;
const char *repover, *instver; 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(pkgname != NULL);
assert(instpkg != NULL);
/* /*
* Prepare repository pool queue. * 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) if ((rv = xbps_repository_pool_init()) != 0)
return rv; return rv;
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { rid = calloc(1, sizeof(struct rpool_index_data));
/* if (rid == NULL) {
* Get the package dictionary from current repository. rv = errno;
* If it's not there, pass to the next repository. goto out;
*/
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;
}
} }
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; rv = EEXIST;
goto out; goto out;
} }
if (pkgrd == NULL) { /*
* Package couldn't be found in repository pool.
*/
if (rid->pkg_repod == NULL) {
rv = ENOENT; rv = ENOENT;
goto out; goto out;
} }
@ -346,7 +408,8 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg)
/* /*
* Set repository in pkg dictionary. * 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; rv = errno;
goto out; goto out;
} }
@ -354,7 +417,8 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg)
/* /*
* Construct the dependency chain for this package. * 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; 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"); unsorted = prop_dictionary_get(trans_dict, "unsorted_deps");
if (unsorted == NULL) { if (unsorted == NULL) {
rv = EINVAL; rv = errno;
goto out; 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 * Always set "not-installed" package state. Will be overwritten
* to its correct state later. * 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; 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")) { "trans-action", "update")) {
rv = errno; rv = errno;
goto out; 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; rv = errno;
goto out;
}
out: out:
if (rid)
free(rid);
xbps_repository_pool_release(); xbps_repository_pool_release();
return rv; return rv;
} }
int static int
xbps_repository_install_pkg(const char *pkg, bool bypattern) 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; prop_array_t unsorted;
struct repository_pool *rpool; struct rpool_index_data *rid;
const char *pkgname, *pkgver; const char *pkgname;
int flags = xbps_get_flags(), rv = 0; int rv = 0;
assert(pkg != NULL); assert(pkg != NULL);
if ((rv = xbps_repository_pool_init()) != 0) if ((rv = xbps_repository_pool_init()) != 0)
return rv; return rv;
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { rid = calloc(1, sizeof(struct rpool_index_data));
/* if (rid == NULL) {
* Get the package dictionary from current repository. rv = errno;
* If it's not there, pass to the next repository. goto out;
*/
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;
}
} }
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; rv = EAGAIN;
goto out; goto out;
} }
@ -438,44 +532,38 @@ xbps_repository_install_pkg(const char *pkg, bool bypattern)
/* /*
* Create the transaction dictionary. * Create the transaction dictionary.
*/ */
if ((rv = create_transaction_dictionary()) != 0) if ((rv = create_transaction_dictionary()) != 0)
goto out; goto out;
/* /*
* Check that this pkg hasn't been added previously into * Check that this pkg hasn't been added previously into
* the transaction. * the transaction.
*/ */
if (bypattern) { if (xbps_find_pkg_in_dict_by_pattern(trans_dict,
if (xbps_find_pkg_in_dict_by_pattern(trans_dict, "unsorted_deps", pkg))
"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)
goto out; 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. * set package state as not yet installed.
*/ */
unsorted = prop_dictionary_get(trans_dict, "unsorted_deps"); 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) if ((rv = set_pkg_state(origin_pkgrd, pkgname)) != 0)
goto out; goto out;
/*
* Set trans-action obj in pkg dictionary to "install".
*/
if (!prop_dictionary_set_cstring_nocopy(origin_pkgrd, if (!prop_dictionary_set_cstring_nocopy(origin_pkgrd,
"trans-action", "install")) { "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; rv = errno;
goto out; goto out;
} }
if (!prop_array_add(unsorted, origin_pkgrd))
rv = errno;
out: out:
if (rid)
free(rid);
if (origin_pkgrd) if (origin_pkgrd)
prop_object_release(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; 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 prop_dictionary_t
xbps_repository_get_pkg_plist_dict(const char *pkgname, const char *plistf) xbps_repository_get_pkg_plist_dict(const char *pkgname, const char *plistf)
{ {
prop_dictionary_t plistd = NULL, pkgd; prop_dictionary_t plistd;
struct repository_pool *rpool; struct rpool_index_data *rid;
char *url = NULL;
int rv = 0; int rv = 0;
if ((rv = xbps_repository_pool_init()) != 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; 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 * Iterate over the the repository pool and search for a plist file
* in the binary package named 'pkgname'. The plist file will be * 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 * This will work locally and remotely, thanks to libarchive and
* libfetch! * libfetch!
*/ */
SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { rid->pkgname = pkgname;
pkgd = xbps_find_pkg_in_dict_by_name(rpool->rp_repod, rid->plistf = plistf;
"packages", pkgname); rv = xbps_repository_pool_foreach(repo_find_pkg_plistd_cb, rid);
if (pkgd == NULL) { plistd = rid->plistd;
if (errno != ENOENT) free(rid);
break; out:
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);
}
xbps_repository_pool_release(); xbps_repository_pool_release();
if (plistd == NULL) if (plistd == NULL)
errno = ENOENT; errno = ENOENT;

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2009 Juan Romero Pardines. * Copyright (c) 2009-2010 Juan Romero Pardines.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,6 +31,7 @@
#include <xbps_api.h> #include <xbps_api.h>
#include "xbps_api_impl.h" #include "xbps_api_impl.h"
#include "queue.h"
/** /**
* @file lib/repository_pool.c * @file lib/repository_pool.c
@ -38,6 +39,14 @@
* @defgroup repopool Repository pool init/fini functions * @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 size_t repolist_refcnt;
static bool repolist_initialized; static bool repolist_initialized;
@ -58,19 +67,19 @@ xbps_repository_pool_init(void)
return 0; return 0;
} }
SIMPLEQ_INIT(&rp_queue);
plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(), plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(),
XBPS_META_PATH, XBPS_REPOLIST); XBPS_META_PATH, XBPS_REPOLIST);
if (plist == NULL) { if (plist == NULL) {
rv = EINVAL; rv = errno;
goto out; goto out;
} }
dict = prop_dictionary_internalize_from_zfile(plist); dict = prop_dictionary_internalize_from_zfile(plist);
if (dict == NULL) { if (dict == NULL) {
free(plist);
rv = errno; rv = errno;
free(plist);
xbps_dbg_printf("%s: cannot internalize plist %s: %s\n",
__func__, plist, strerror(errno));
goto out; goto out;
} }
free(plist); free(plist);
@ -96,7 +105,7 @@ xbps_repository_pool_init(void)
plist = plist =
xbps_get_pkg_index_plist(prop_string_cstring_nocopy(obj)); xbps_get_pkg_index_plist(prop_string_cstring_nocopy(obj));
if (plist == NULL) { if (plist == NULL) {
rv = EINVAL; rv = errno;
goto out; goto out;
} }
@ -106,16 +115,26 @@ xbps_repository_pool_init(void)
goto out; goto out;
} }
rpool->rp_uri = prop_string_cstring(obj); rpool->rpi = malloc(sizeof(struct repository_pool_index));
if (rpool->rp_uri == NULL) { if (rpool->rpi == NULL) {
free(rpool);
free(plist);
rv = errno; rv = errno;
free(rpool);
goto out; goto out;
} }
rpool->rp_repod = prop_dictionary_internalize_from_zfile(plist);
if (rpool->rp_repod == NULL) { rpool->rpi->rpi_uri = prop_string_cstring(obj);
free(rpool->rp_uri); 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(rpool);
free(plist); free(plist);
if (errno == ENOENT) { if (errno == ENOENT) {
@ -124,10 +143,14 @@ xbps_repository_pool_init(void)
continue; continue;
} }
rv = errno; rv = errno;
xbps_dbg_printf("%s: cannot internalize plist %s: %s\n",
__func__, plist, strerror(errno));
goto out; goto out;
} }
free(plist); 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) if (ntotal - nmissing == 0)
@ -135,13 +158,13 @@ xbps_repository_pool_init(void)
repolist_initialized = true; repolist_initialized = true;
repolist_refcnt = 1; repolist_refcnt = 1;
DPRINTF(("%s: initialized ok.\n", __func__)); xbps_dbg_printf("%s: initialized ok.\n", __func__);
out: out:
if (iter) if (iter)
prop_object_iterator_release(iter); prop_object_iterator_release(iter);
if (dict) if (dict)
prop_object_release(dict); prop_object_release(dict);
if (rv != 0) if (rv != 0)
xbps_repository_pool_release(); xbps_repository_pool_release();
return rv; return rv;
@ -156,13 +179,37 @@ xbps_repository_pool_release(void)
if (--repolist_refcnt > 0) if (--repolist_refcnt > 0)
return; return;
while ((rpool = SIMPLEQ_FIRST(&rp_queue)) != NULL) { while ((rpool = SIMPLEQ_FIRST(&rpool_queue)) != NULL) {
SIMPLEQ_REMOVE(&rp_queue, rpool, repository_pool, rp_entries); SIMPLEQ_REMOVE(&rpool_queue, rpool, repository_pool, rp_entries);
prop_object_release(rpool->rp_repod); xbps_dbg_printf("Unregistered repository '%s'\n",
free(rpool->rp_uri); rpool->rpi->rpi_uri);
prop_object_release(rpool->rpi->rpi_repod);
free(rpool->rpi->rpi_uri);
free(rpool->rpi);
free(rpool); free(rpool);
} }
repolist_refcnt = 0; repolist_refcnt = 0;
repolist_initialized = false; 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. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,6 +30,7 @@
#include <xbps_api.h> #include <xbps_api.h>
#include "xbps_api_impl.h" #include "xbps_api_impl.h"
#include "queue.h"
struct sorted_dependency { struct sorted_dependency {
SIMPLEQ_ENTRY(sorted_dependency) chain; SIMPLEQ_ENTRY(sorted_dependency) chain;
@ -44,20 +45,15 @@ find_sorteddep_by_name(const char *pkgname)
{ {
struct sorted_dependency *sdep = NULL; struct sorted_dependency *sdep = NULL;
const char *curpkgname; const char *curpkgname;
bool found = false;
SIMPLEQ_FOREACH(sdep, &sdep_list, chain) { SIMPLEQ_FOREACH(sdep, &sdep_list, chain) {
prop_dictionary_get_cstring_nocopy(sdep->dict, prop_dictionary_get_cstring_nocopy(sdep->dict,
"pkgname", &curpkgname); "pkgname", &curpkgname);
if (strcmp(pkgname, curpkgname) == 0) { if (strcmp(pkgname, curpkgname) == 0)
found = true; return sdep;
break;
}
} }
if (!found)
return NULL;
return sdep; return NULL;
} }
int HIDDEN int HIDDEN
@ -107,13 +103,14 @@ again:
while ((obj = prop_object_iterator_next(iter)) != NULL) { while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); 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) { if (find_sorteddep_by_name(pkgname) != NULL) {
DPRINTF(("Skipping %s already queued.\n", pkgname)); xbps_dbg_printf_append("skipping, already queued.\n",
pkgname);
continue; continue;
} }
sdep = malloc(sizeof(*sdep)); sdep = malloc(sizeof(struct sorted_dependency));
if (sdep == NULL) { if (sdep == NULL) {
rv = ENOMEM; rv = ENOMEM;
goto out; goto out;
@ -124,8 +121,8 @@ again:
*/ */
rundeps = prop_dictionary_get(obj, "run_depends"); rundeps = prop_dictionary_get(obj, "run_depends");
if (rundeps == NULL || prop_array_count(rundeps) == 0) { if (rundeps == NULL || prop_array_count(rundeps) == 0) {
DPRINTF(("Adding %s (no rundeps) into the sorted " xbps_dbg_printf_append("added (no rundeps) into "
"queue.\n", pkgver)); "the sorted queue.\n");
sdep->dict = prop_dictionary_copy(obj); sdep->dict = prop_dictionary_copy(obj);
SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain); SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain);
cnt++; cnt++;
@ -133,15 +130,18 @@ again:
} }
iter2 = prop_array_iterator(rundeps); iter2 = prop_array_iterator(rundeps);
if (iter2 == NULL) { if (iter2 == NULL) {
free(sdep);
rv = ENOMEM; rv = ENOMEM;
free(sdep);
goto out; goto out;
} }
/* /*
* Iterate over the run_depends array, and find out if they * Iterate over the run_depends array, and find out if they
* were already added in the sorted list. * 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) { while ((obj2 = prop_object_iterator_next(iter2)) != NULL) {
str = prop_string_cstring_nocopy(obj2); str = prop_string_cstring_nocopy(obj2);
if (str == NULL) { if (str == NULL) {
@ -152,22 +152,22 @@ again:
pkgnamedep = xbps_get_pkgpattern_name(str); pkgnamedep = xbps_get_pkgpattern_name(str);
if (pkgnamedep == NULL) { if (pkgnamedep == NULL) {
free(sdep); free(sdep);
rv = errno; rv = EINVAL;
goto out; goto out;
} }
DPRINTF(("Required dependency %s: ", str)); xbps_dbg_printf(" Required dependency '%s': ", str);
/* /*
* If dependency is already satisfied or queued, * If dependency is already satisfied or queued,
* pass to the next one. * pass to the next one.
*/ */
if (xbps_check_is_installed_pkg(str)) { if (xbps_check_is_installed_pkg(str)) {
rundepscnt++; rundepscnt++;
DPRINTF(("installed.\n")); xbps_dbg_printf_append("installed.\n");
} else if (find_sorteddep_by_name(pkgnamedep) != NULL) { } else if (find_sorteddep_by_name(pkgnamedep) != NULL) {
DPRINTF(("queued.\n")); xbps_dbg_printf_append("queued.\n");
rundepscnt++; rundepscnt++;
} else { } else {
DPRINTF(("not installed or queued.\n")); xbps_dbg_printf_append("not installed.\n");
} }
free(pkgnamedep); free(pkgnamedep);
} }
@ -175,23 +175,25 @@ again:
/* Add dependency if all its required deps are already added */ /* Add dependency if all its required deps are already added */
if (prop_array_count(rundeps) == rundepscnt) { if (prop_array_count(rundeps) == rundepscnt) {
DPRINTF(("Adding package %s to the sorted queue.\n",
pkgver));
sdep->dict = prop_dictionary_copy(obj); sdep->dict = prop_dictionary_copy(obj);
SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain); 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; rundepscnt = 0;
cnt++; cnt++;
continue; 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); free(sdep);
rundepscnt = 0; rundepscnt = 0;
} }
/* Iterate until all deps are processed. */ /* Iterate until all deps are processed. */
if (cnt < ndeps) { if (cnt < ndeps) {
DPRINTF(("Missing required deps! cnt: %zu ndeps: %zu\n", xbps_dbg_printf("Missing required deps! queued: %zu "
cnt, ndeps)); "required: %zu.\n", cnt, ndeps);
prop_object_iterator_reset(iter); prop_object_iterator_reset(iter);
goto again; goto again;
} }
@ -203,7 +205,7 @@ again:
while ((sdep = SIMPLEQ_FIRST(&sdep_list)) != NULL) { while ((sdep = SIMPLEQ_FIRST(&sdep_list)) != NULL) {
if (!prop_array_add(sorted, sdep->dict)) { if (!prop_array_add(sorted, sdep->dict)) {
free(sdep); free(sdep);
rv = errno; rv = EINVAL;
goto out; goto out;
} }
SIMPLEQ_REMOVE(&sdep_list, sdep, sorted_dependency, chain); SIMPLEQ_REMOVE(&sdep_list, sdep, sorted_dependency, chain);