Merged purge code in remove, configurable transaction regpkgdb flushing.
See the NEWS file for info.
This commit is contained in:
23
NEWS
23
NEWS
@ -1,4 +1,25 @@
|
|||||||
xbps-0.11.1 (???):
|
xbps-0.12.0 (???):
|
||||||
|
|
||||||
|
* Renamed some options in xbps.conf to not have dashes, such as:
|
||||||
|
fetch-timeout-connection -> FetchTimeoutConnection
|
||||||
|
fetch-cache-connections-host -> FetchCacheConnections
|
||||||
|
fetch-cache-connections-per-host -> FetchCacheConnectionsPerHost
|
||||||
|
|
||||||
|
* Implemented memory caching for regpkgdb and configurarable transaction
|
||||||
|
flushing. Can be changed in xbps.conf with "TransactionFrequencyFlusing".
|
||||||
|
By default set to 5. That means that every 5 packages processed in
|
||||||
|
a transaction there will be a regpkgdb plist flush to disk.
|
||||||
|
|
||||||
|
Setting it to 0 enables automatic mode which will only flush in
|
||||||
|
two required points. Setting it to 1 makes the behaviour used in XBPS<=0.11,
|
||||||
|
which flushed it on every package.
|
||||||
|
|
||||||
|
That feature provides a 25% (and in some cases even more!) of performance
|
||||||
|
when executing a transaction.
|
||||||
|
|
||||||
|
* Merged purge code into remove. It wasn't necessary to have this splitted,
|
||||||
|
so it now has been merged into xbps_remove_pkg(). That also means that
|
||||||
|
'-p' flag in xbps-bin(8) and xbps-repo(8) doesn't exist anymore.
|
||||||
|
|
||||||
* xbps-repo(8): the 'find-files' target accepts multiple patterns, such as:
|
* xbps-repo(8): the 'find-files' target accepts multiple patterns, such as:
|
||||||
$ xbps-repo find-files /bin/cat '/bin/f*' ...
|
$ xbps-repo find-files /bin/cat '/bin/f*' ...
|
||||||
|
@ -35,44 +35,6 @@
|
|||||||
#include <xbps_api.h>
|
#include <xbps_api.h>
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
static int
|
|
||||||
write_pkgd_to_regpkgdb(prop_dictionary_t pkgd,
|
|
||||||
prop_array_t regpkgs,
|
|
||||||
const char *pkgn)
|
|
||||||
{
|
|
||||||
struct xbps_handle *xhp = xbps_handle_get();
|
|
||||||
char *path;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
rv = xbps_array_replace_dict_by_name(regpkgs, pkgd, pkgn);
|
|
||||||
if (rv != 0) {
|
|
||||||
xbps_error_printf("%s: failed to replace pkgd: %s\n",
|
|
||||||
pkgn, strerror(rv));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!prop_dictionary_set(xhp->regpkgdb_dictionary,
|
|
||||||
"packages", regpkgs)) {
|
|
||||||
xbps_error_printf("%s: failed to set new regpkgdb "
|
|
||||||
"packages array: %s", pkgn, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
path = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
|
||||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
|
||||||
if (path == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!prop_dictionary_externalize_to_zfile(
|
|
||||||
xhp->regpkgdb_dictionary, path)) {
|
|
||||||
xbps_error_printf("%s: failed to write regpkgdb plist:"
|
|
||||||
" %s\n", pkgn, strerror(errno));
|
|
||||||
free(path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks package integrity of an installed package.
|
* Checks package integrity of an installed package.
|
||||||
* The following task is accomplished in this file:
|
* The following task is accomplished in this file:
|
||||||
@ -94,6 +56,8 @@ check_pkg_requiredby(prop_dictionary_t pkgd_regpkgdb,
|
|||||||
struct xbps_handle *xhp = xbps_handle_get();
|
struct xbps_handle *xhp = xbps_handle_get();
|
||||||
const char *curpkgn, *pkgname, *pkgver;
|
const char *curpkgn, *pkgname, *pkgver;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
int rv;
|
||||||
|
bool pkg_fixed = false;
|
||||||
|
|
||||||
(void)pkg_propsd;
|
(void)pkg_propsd;
|
||||||
(void)pkg_filesd;
|
(void)pkg_filesd;
|
||||||
@ -101,7 +65,7 @@ check_pkg_requiredby(prop_dictionary_t pkgd_regpkgdb,
|
|||||||
prop_dictionary_get_cstring_nocopy(pkgd_regpkgdb, "pkgname", &pkgname);
|
prop_dictionary_get_cstring_nocopy(pkgd_regpkgdb, "pkgname", &pkgname);
|
||||||
prop_dictionary_get_cstring_nocopy(pkgd_regpkgdb, "pkgver", &pkgver);
|
prop_dictionary_get_cstring_nocopy(pkgd_regpkgdb, "pkgver", &pkgver);
|
||||||
|
|
||||||
regpkgs = prop_dictionary_get(xhp->regpkgdb_dictionary, "packages");
|
regpkgs = prop_dictionary_get(xhp->regpkgdb, "packages");
|
||||||
|
|
||||||
for (i = 0; i < prop_array_count(regpkgs); i++) {
|
for (i = 0; i < prop_array_count(regpkgs); i++) {
|
||||||
obj = prop_array_get(regpkgs, i);
|
obj = prop_array_get(regpkgs, i);
|
||||||
@ -181,13 +145,30 @@ check_pkg_requiredby(prop_dictionary_t pkgd_regpkgdb,
|
|||||||
*/
|
*/
|
||||||
prop_array_add(reqby, curpkgver);
|
prop_array_add(reqby, curpkgver);
|
||||||
prop_dictionary_set(pkgd_regpkgdb, "requiredby", reqby);
|
prop_dictionary_set(pkgd_regpkgdb, "requiredby", reqby);
|
||||||
if (write_pkgd_to_regpkgdb(pkgd_regpkgdb, regpkgs, pkgname) != 0)
|
rv = xbps_array_replace_dict_by_name(regpkgs, obj, curpkgn);
|
||||||
|
if (rv != 0) {
|
||||||
|
xbps_error_printf("%s: failed to replace pkgd: %s\n",
|
||||||
|
curpkgn, strerror(rv));
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
if (!prop_dictionary_set(xhp->regpkgdb, "packages", regpkgs)) {
|
||||||
|
xbps_error_printf("%s: failed to set new regpkgdb "
|
||||||
|
"packages array: %s", curpkgn, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pkg_fixed = true;
|
||||||
printf("%s: added requiredby entry for %s.\n",
|
printf("%s: added requiredby entry for %s.\n",
|
||||||
pkgver, prop_string_cstring_nocopy(curpkgver));
|
pkgver, prop_string_cstring_nocopy(curpkgver));
|
||||||
prop_object_release(curpkg_propsd);
|
prop_object_release(curpkg_propsd);
|
||||||
}
|
}
|
||||||
|
if (pkg_fixed == false)
|
||||||
|
return rv;
|
||||||
|
|
||||||
return 0;
|
if ((rv = xbps_regpkgdb_update(xhp, true)) != 0) {
|
||||||
|
xbps_error_printf("failed to write regpkgdb plist: "
|
||||||
|
" %s\n", strerror(rv));
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,9 @@ struct list_pkgver_cb {
|
|||||||
/* from transaction.c */
|
/* from transaction.c */
|
||||||
int install_new_pkg(const char *, bool);
|
int install_new_pkg(const char *, bool);
|
||||||
int update_pkg(const char *);
|
int update_pkg(const char *);
|
||||||
int remove_pkg(const char *, bool, bool);
|
int remove_pkg(const char *, bool);
|
||||||
int autoupdate_pkgs(bool, bool);
|
int autoupdate_pkgs(bool, bool);
|
||||||
int autoremove_pkgs(bool, bool);
|
int autoremove_pkgs(bool);
|
||||||
int exec_transaction(bool, bool);
|
int exec_transaction(bool, bool);
|
||||||
|
|
||||||
/* from remove.c */
|
/* from remove.c */
|
||||||
|
@ -68,17 +68,17 @@ main(int argc, char **argv)
|
|||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
const char *rootdir, *cachedir, *conffile, *option;
|
const char *rootdir, *cachedir, *conffile, *option;
|
||||||
int i, c, flags, rv;
|
int i, c, flags, rv;
|
||||||
bool yes, purge, debug, reqby_force, force_rm_with_deps, recursive_rm;
|
bool yes, debug, reqby_force, force_rm_with_deps, recursive_rm;
|
||||||
bool install_auto, install_manual, show_download_pkglist_url;
|
bool install_auto, install_manual, show_download_pkglist_url;
|
||||||
bool reinstall;
|
bool reinstall;
|
||||||
|
|
||||||
rootdir = cachedir = conffile = option = NULL;
|
rootdir = cachedir = conffile = option = NULL;
|
||||||
flags = rv = 0;
|
flags = rv = 0;
|
||||||
reqby_force = yes = purge = force_rm_with_deps = false;
|
reqby_force = yes = force_rm_with_deps = false;
|
||||||
recursive_rm = debug = reinstall = false;
|
recursive_rm = debug = reinstall = false;
|
||||||
install_auto = install_manual = show_download_pkglist_url = false;
|
install_auto = install_manual = show_download_pkglist_url = false;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "AC:c:dDFfMo:pRr:Vvy")) != -1) {
|
while ((c = getopt(argc, argv, "AC:c:dDFfMo:Rr:Vvy")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'A':
|
case 'A':
|
||||||
install_auto = true;
|
install_auto = true;
|
||||||
@ -109,9 +109,6 @@ main(int argc, char **argv)
|
|||||||
case 'o':
|
case 'o':
|
||||||
option = optarg;
|
option = optarg;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
|
||||||
purge = true;
|
|
||||||
break;
|
|
||||||
case 'R':
|
case 'R':
|
||||||
recursive_rm = true;
|
recursive_rm = true;
|
||||||
break;
|
break;
|
||||||
@ -147,15 +144,6 @@ main(int argc, char **argv)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Register a signal handler to clean up resources used by libxbps.
|
|
||||||
*/
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
|
||||||
sa.sa_handler = cleanup;
|
|
||||||
sigaction(SIGINT, &sa, NULL);
|
|
||||||
sigaction(SIGTERM, &sa, NULL);
|
|
||||||
sigaction(SIGQUIT, &sa, NULL);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize libxbps.
|
* Initialize libxbps.
|
||||||
*/
|
*/
|
||||||
@ -185,6 +173,14 @@ main(int argc, char **argv)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a signal handler to clean up resources used by libxbps.
|
||||||
|
*/
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.sa_handler = cleanup;
|
||||||
|
sigaction(SIGINT, &sa, NULL);
|
||||||
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
|
||||||
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)
|
||||||
@ -199,12 +195,12 @@ main(int argc, char **argv)
|
|||||||
lpc.state = XBPS_PKG_STATE_HALF_UNPACKED;
|
lpc.state = XBPS_PKG_STATE_HALF_UNPACKED;
|
||||||
else if (strcmp(argv[1], "unpacked") == 0)
|
else if (strcmp(argv[1], "unpacked") == 0)
|
||||||
lpc.state = XBPS_PKG_STATE_UNPACKED;
|
lpc.state = XBPS_PKG_STATE_UNPACKED;
|
||||||
else if (strcmp(argv[1], "config-files") == 0)
|
else if (strcmp(argv[1], "half-removed") == 0)
|
||||||
lpc.state = XBPS_PKG_STATE_CONFIG_FILES;
|
lpc.state = XBPS_PKG_STATE_HALF_REMOVED;
|
||||||
else {
|
else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"E: invalid state `%s'. Accepted values: "
|
"E: invalid state `%s'. Accepted values: "
|
||||||
"config-files, unpacked, "
|
"half-removed, unpacked, half-unpacked, "
|
||||||
"installed [default]\n", argv[1]);
|
"installed [default]\n", argv[1]);
|
||||||
rv = -1;
|
rv = -1;
|
||||||
goto out;
|
goto out;
|
||||||
@ -249,7 +245,7 @@ main(int argc, char **argv)
|
|||||||
usage(xhp);
|
usage(xhp);
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
rv = remove_pkg(argv[i], purge, recursive_rm);
|
rv = remove_pkg(argv[i], recursive_rm);
|
||||||
if (rv == 0)
|
if (rv == 0)
|
||||||
continue;
|
continue;
|
||||||
else if (rv != EEXIST)
|
else if (rv != EEXIST)
|
||||||
@ -323,19 +319,7 @@ main(int argc, char **argv)
|
|||||||
if (argc != 1)
|
if (argc != 1)
|
||||||
usage(xhp);
|
usage(xhp);
|
||||||
|
|
||||||
rv = autoremove_pkgs(yes, purge);
|
rv = autoremove_pkgs(yes);
|
||||||
|
|
||||||
} else if (strcasecmp(argv[0], "purge") == 0) {
|
|
||||||
/*
|
|
||||||
* Purge a package completely.
|
|
||||||
*/
|
|
||||||
if (argc != 2)
|
|
||||||
usage(xhp);
|
|
||||||
|
|
||||||
if (strcasecmp(argv[1], "all") == 0)
|
|
||||||
rv = xbps_purge_packages();
|
|
||||||
else
|
|
||||||
rv = xbps_purge_pkg(argv[1], true);
|
|
||||||
|
|
||||||
} else if (strcasecmp(argv[0], "reconfigure") == 0) {
|
} else if (strcasecmp(argv[0], "reconfigure") == 0) {
|
||||||
/*
|
/*
|
||||||
|
@ -66,9 +66,6 @@ state_cb(const struct xbps_state_cb_data *xscd, void *cbdata)
|
|||||||
case XBPS_STATE_REMOVE:
|
case XBPS_STATE_REMOVE:
|
||||||
printf("Removing `%s-%s' ...\n", xscd->pkgname, xscd->version);
|
printf("Removing `%s-%s' ...\n", xscd->pkgname, xscd->version);
|
||||||
break;
|
break;
|
||||||
case XBPS_STATE_PURGE:
|
|
||||||
printf("Purging `%s-%s' ...\n", xscd->pkgname, xscd->version);
|
|
||||||
break;
|
|
||||||
case XBPS_STATE_CONFIGURE:
|
case XBPS_STATE_CONFIGURE:
|
||||||
printf("Configuring `%s-%s' ...\n", xscd->pkgname,
|
printf("Configuring `%s-%s' ...\n", xscd->pkgname,
|
||||||
xscd->version);
|
xscd->version);
|
||||||
@ -125,21 +122,12 @@ state_cb(const struct xbps_state_cb_data *xscd, void *cbdata)
|
|||||||
"(rootdir: %s).", xscd->pkgname, xscd->version,
|
"(rootdir: %s).", xscd->pkgname, xscd->version,
|
||||||
xhp->rootdir);
|
xhp->rootdir);
|
||||||
break;
|
break;
|
||||||
case XBPS_STATE_PURGE_DONE:
|
|
||||||
printf("Purged `%s-%s' successfully.\n",
|
|
||||||
xscd->pkgname, xscd->version);
|
|
||||||
if (xhp->syslog_enabled)
|
|
||||||
syslog(LOG_NOTICE, "Purged `%s-%s' successfully "
|
|
||||||
"(rootdir: %s).", xscd->pkgname, xscd->version,
|
|
||||||
xhp->rootdir);
|
|
||||||
break;
|
|
||||||
/* errors */
|
/* errors */
|
||||||
case XBPS_STATE_UNPACK_FAIL:
|
case XBPS_STATE_UNPACK_FAIL:
|
||||||
case XBPS_STATE_UPDATE_FAIL:
|
case XBPS_STATE_UPDATE_FAIL:
|
||||||
case XBPS_STATE_CONFIGURE_FAIL:
|
case XBPS_STATE_CONFIGURE_FAIL:
|
||||||
case XBPS_STATE_REGISTER_FAIL:
|
case XBPS_STATE_REGISTER_FAIL:
|
||||||
case XBPS_STATE_UNREGISTER_FAIL:
|
case XBPS_STATE_UNREGISTER_FAIL:
|
||||||
case XBPS_STATE_PURGE_FAIL:
|
|
||||||
case XBPS_STATE_REMOVE_FAIL:
|
case XBPS_STATE_REMOVE_FAIL:
|
||||||
case XBPS_STATE_VERIFY_FAIL:
|
case XBPS_STATE_VERIFY_FAIL:
|
||||||
case XBPS_STATE_DOWNLOAD_FAIL:
|
case XBPS_STATE_DOWNLOAD_FAIL:
|
||||||
|
@ -222,11 +222,11 @@ autoupdate_pkgs(bool yes, bool show_download_pkglist_url)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
autoremove_pkgs(bool yes, bool purge)
|
autoremove_pkgs(bool yes)
|
||||||
{
|
{
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
if ((rv = xbps_transaction_autoremove_pkgs(purge)) != 0) {
|
if ((rv = xbps_transaction_autoremove_pkgs()) != 0) {
|
||||||
if (rv == ENOENT) {
|
if (rv == ENOENT) {
|
||||||
printf("No package orphans were found.\n");
|
printf("No package orphans were found.\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -328,7 +328,7 @@ update_pkg(const char *pkgname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
remove_pkg(const char *pkgname, bool purge, bool recursive)
|
remove_pkg(const char *pkgname, bool recursive)
|
||||||
{
|
{
|
||||||
prop_dictionary_t pkgd;
|
prop_dictionary_t pkgd;
|
||||||
prop_array_t reqby;
|
prop_array_t reqby;
|
||||||
@ -336,7 +336,7 @@ remove_pkg(const char *pkgname, bool purge, bool recursive)
|
|||||||
size_t x;
|
size_t x;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = xbps_transaction_remove_pkg(pkgname, purge, recursive);
|
rv = xbps_transaction_remove_pkg(pkgname, recursive);
|
||||||
if (rv == EEXIST) {
|
if (rv == EEXIST) {
|
||||||
/* pkg has revdeps */
|
/* pkg has revdeps */
|
||||||
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
|
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.Dd December 22, 2011
|
.Dd December 23, 2011
|
||||||
.Os Void GNU/Linux
|
.Os Void GNU/Linux
|
||||||
.Dt xbps-bin 8
|
.Dt xbps-bin 8
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -60,7 +60,6 @@ depending on it, i.e package is a dependency of any other installed package.
|
|||||||
.It Fl f
|
.It Fl f
|
||||||
Used currently in the
|
Used currently in the
|
||||||
.Em install ,
|
.Em install ,
|
||||||
.Em purge ,
|
|
||||||
.Em reconfigure
|
.Em reconfigure
|
||||||
and
|
and
|
||||||
.Em remove
|
.Em remove
|
||||||
@ -69,10 +68,8 @@ targets. If set, package(s) will be reconfigured regardless of its state in
|
|||||||
target, or to
|
target, or to
|
||||||
.Em force
|
.Em force
|
||||||
removal of package files even if its hash does not match in the
|
removal of package files even if its hash does not match in the
|
||||||
.Em purge
|
|
||||||
and
|
|
||||||
.Em remove
|
.Em remove
|
||||||
targets. If set, package(s) will be reinstalled even if its state is
|
target. If set, package(s) will be reinstalled even if its state is
|
||||||
.Em installed
|
.Em installed
|
||||||
when used with the
|
when used with the
|
||||||
.Em install
|
.Em install
|
||||||
@ -95,13 +92,6 @@ Used currently in the
|
|||||||
target. Prints the value of specified key(s) from
|
target. Prints the value of specified key(s) from
|
||||||
package's properties dictionary. Multiple keys can be specified delimited by
|
package's properties dictionary. Multiple keys can be specified delimited by
|
||||||
the comma character.
|
the comma character.
|
||||||
.It Fl p
|
|
||||||
Used currently in the
|
|
||||||
.Em remove
|
|
||||||
and
|
|
||||||
.Em autoremove
|
|
||||||
targets. If enabled, after removing
|
|
||||||
a package it is also purged.
|
|
||||||
.It Fl R
|
.It Fl R
|
||||||
Used currently in the
|
Used currently in the
|
||||||
.Em remove
|
.Em remove
|
||||||
@ -175,28 +165,14 @@ to list only packages with the specified
|
|||||||
By default only packages fully installed will be listed if
|
By default only packages fully installed will be listed if
|
||||||
.Em state
|
.Em state
|
||||||
has not been specified. Accepted states are:
|
has not been specified. Accepted states are:
|
||||||
.Em config-files ,
|
.Em half-removed ,
|
||||||
.Em half-unpacked ,
|
.Em half-unpacked ,
|
||||||
.Em unpacked ,
|
.Em installed
|
||||||
and
|
and
|
||||||
.Em installed .
|
.Em unpacked .
|
||||||
.It Sy list-manual
|
.It Sy list-manual
|
||||||
Lists packages that were installed manually by the user, i.e not as dependencies
|
Lists packages that were installed manually by the user, i.e not as dependencies
|
||||||
of any other package.
|
of any other package.
|
||||||
.It Sy purge Ar pkgname | Ar all
|
|
||||||
Purge an installed package:
|
|
||||||
.Em pkgname
|
|
||||||
or
|
|
||||||
.Em all
|
|
||||||
packages. The purge stage runs the post-remove action set in the REMOVE script
|
|
||||||
in its metadata directory
|
|
||||||
.Pa (/var/db/xbps/metadata/pkgname)
|
|
||||||
and will remove configuration (if they were not modified by the user) and
|
|
||||||
metadata files. The package will be fully removed from the system once it
|
|
||||||
has been purged. If
|
|
||||||
.Ql -f
|
|
||||||
option is used, configuration files that have been
|
|
||||||
.Em modified WILL BE REMOVED. BEWARE WITH THIS!
|
|
||||||
.It Sy reconfigure Ar pkgname | Ar all
|
.It Sy reconfigure Ar pkgname | Ar all
|
||||||
Reconfigure an unpacked package. Packages in this state are not fully installed,
|
Reconfigure an unpacked package. Packages in this state are not fully installed,
|
||||||
because they were not configured for whatever reason. The configure stage will
|
because they were not configured for whatever reason. The configure stage will
|
||||||
@ -209,16 +185,7 @@ option is used, the package will be reconfigured even if its state is already in
|
|||||||
.It Sy remove Ar pkgname(s)
|
.It Sy remove Ar pkgname(s)
|
||||||
Removes the installed package
|
Removes the installed package
|
||||||
.Em pkgname(s) .
|
.Em pkgname(s) .
|
||||||
Its files will be removed and its state will be changed to
|
Files not matching the original SHA256 hash will be preserved. If
|
||||||
.Em config-files
|
|
||||||
in the package database. Configuration files, its metadata directory/files and its
|
|
||||||
information in the package database are preserved. To fully remove a package in
|
|
||||||
.Em config-files
|
|
||||||
state, it must be purged with the
|
|
||||||
.Em purge
|
|
||||||
command or alternatively use the
|
|
||||||
.Ql -p
|
|
||||||
flag. If
|
|
||||||
.Ql -f
|
.Ql -f
|
||||||
option is used, package files will be
|
option is used, package files will be
|
||||||
.Em removed even if its SHA256 hash don't match .
|
.Em removed even if its SHA256 hash don't match .
|
||||||
@ -257,10 +224,9 @@ target that will update all currently installed packages.
|
|||||||
A package can be in a different state while it is being
|
A package can be in a different state while it is being
|
||||||
.Em installed ,
|
.Em installed ,
|
||||||
.Em removed ,
|
.Em removed ,
|
||||||
.Em unpacked ,
|
.Em unpacked
|
||||||
.Em configured
|
|
||||||
or
|
or
|
||||||
.Em purged .
|
.Em configured .
|
||||||
The following states are available:
|
The following states are available:
|
||||||
.Bl -tag -width ident
|
.Bl -tag -width ident
|
||||||
.It Sy installed
|
.It Sy installed
|
||||||
@ -271,11 +237,13 @@ The package was being unpacked but didn't finish properly for unknown reasons.
|
|||||||
The package has been unpacked in destination root directory, but it is not fully
|
The package has been unpacked in destination root directory, but it is not fully
|
||||||
installed because it was not yet configured. Please note that some packages will
|
installed because it was not yet configured. Please note that some packages will
|
||||||
do not work if they are only unpacked.
|
do not work if they are only unpacked.
|
||||||
.It Sy config-files
|
.It Sy half-remove
|
||||||
The package has been removed but configuration files and its metadata directory
|
The package removal did not finish for unknown reasons (power outage, process killed, etc).
|
||||||
are still available (and it is still registered in the package database).
|
The
|
||||||
You can purge safely packages that are in this state, modified configuration
|
.Em purge
|
||||||
files will be preserved.
|
action in its metadata REMOVE script has not been yet executed. The package
|
||||||
|
metadata directory is still available and it is registered in package database.
|
||||||
|
Packages in this state can be still removed.
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width /var/db/xbps/metadata/<pkgname>/props.plist -compact
|
.Bl -tag -width /var/db/xbps/metadata/<pkgname>/props.plist -compact
|
||||||
.It Pa /etc/xbps/xbps.conf
|
.It Pa /etc/xbps/xbps.conf
|
||||||
|
@ -94,6 +94,7 @@ die(const char *fmt, ...)
|
|||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
fprintf(stderr, " (%s)\n", strerror(save_errno));
|
fprintf(stderr, " (%s)\n", strerror(save_errno));
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
xbps_end(xbps_handle_get());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +215,9 @@ main(int argc, char **argv)
|
|||||||
in_chroot ? "[chroot] " : "" , argv[1], argv[2],
|
in_chroot ? "[chroot] " : "" , argv[1], argv[2],
|
||||||
strerror(rv), MSG_RESET);
|
strerror(rv), MSG_RESET);
|
||||||
} else {
|
} else {
|
||||||
|
if ((rv = xbps_regpkgdb_update(xhp, true)) != 0)
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
printf("%s%s=> %s-%s registered successfully.%s\n",
|
printf("%s%s=> %s-%s registered successfully.%s\n",
|
||||||
MSG_NORMAL, in_chroot ? "[chroot] " : "",
|
MSG_NORMAL, in_chroot ? "[chroot] " : "",
|
||||||
argv[1], argv[2], MSG_RESET);
|
argv[1], argv[2], MSG_RESET);
|
||||||
|
@ -17,11 +17,13 @@ digraph regpkgdb_dictionary {
|
|||||||
pkgdict -> pkgver [label="string"];
|
pkgdict -> pkgver [label="string"];
|
||||||
pkgdict -> state [label="string"];
|
pkgdict -> state [label="string"];
|
||||||
state -> state_inst [label="value"];
|
state -> state_inst [label="value"];
|
||||||
state -> state_cffiles [label="value"];
|
state -> state_hfuned [label="value"];
|
||||||
state -> state_unpack [label="value"];
|
state -> state_unpack [label="value"];
|
||||||
|
state -> state_hfrmed [label="value"];
|
||||||
state_inst [style=filled,fillcolor="yellowgreen",label="installed"];
|
state_inst [style=filled,fillcolor="yellowgreen",label="installed"];
|
||||||
state_cffiles [style=filled,fillcolor="yellowgreen",label="config-files"];
|
state_hfuned [style=filled,fillcolor="yellowgreen",label="half-unpacked"];
|
||||||
state_unpack [style=filled,fillcolor="yellowgreen",label="unpacked"];
|
state_unpack [style=filled,fillcolor="yellowgreen",label="unpacked"];
|
||||||
|
state_hfrmed [style=filled,fillcolor="yellowgreen",label="half-removed"];
|
||||||
pkgdict -> automatic [label="bool"];
|
pkgdict -> automatic [label="bool"];
|
||||||
automatic [label="automatic-install"];
|
automatic [label="automatic-install"];
|
||||||
pkgdict -> short_desc [label="string"]
|
pkgdict -> short_desc [label="string"]
|
||||||
|
BIN
etc/.xbps.conf.swp
Normal file
BIN
etc/.xbps.conf.swp
Normal file
Binary file not shown.
@ -2,24 +2,30 @@
|
|||||||
# ============================
|
# ============================
|
||||||
#
|
#
|
||||||
# Root directory.
|
# Root directory.
|
||||||
#rootdir = /
|
#RootDir = /
|
||||||
#
|
#
|
||||||
# Cache directory to store downloaded binary packages.
|
# Cache directory to store downloaded binary packages.
|
||||||
# If string begins with '/' it will be treated as full path,
|
# If string begins with '/' it will be treated as full path,
|
||||||
# otherwise it will be treated as relative to the root-directory.
|
# otherwise it will be treated as relative to the root-directory.
|
||||||
#cachedir = var/cache/xbps
|
#CacheDir = var/cache/xbps
|
||||||
#
|
#
|
||||||
# Default global limit of cached connections when fetching files.
|
# Default global limit of cached connections when fetching files.
|
||||||
#fetch-cache-connections = 10
|
#FetchCacheConnection = 10
|
||||||
#
|
#
|
||||||
# Default per-host limit of cached connections when fetching files.
|
# Default per-host limit of cached connections when fetching files.
|
||||||
#fetch-cache-connections-per-host = 3
|
#FetchCacheConnectionPerHost = 3
|
||||||
#
|
#
|
||||||
# Default timeout limit for connections, in seconds.
|
# Default timeout limit for connections, in seconds.
|
||||||
#fetch-timeout-connection = 30
|
#FetchTimeoutConnection = 30
|
||||||
#
|
#
|
||||||
# Enable syslog messages, set the value to false or 0 to disable.
|
# Enable syslog messages, set the value to false or 0 to disable.
|
||||||
#syslog = true
|
#Syslog = true
|
||||||
|
|
||||||
|
# Number of packages to be processed in a transaction to trigger
|
||||||
|
# a flush to the master package database. Set it to 0 to make it
|
||||||
|
# only flush at required points.
|
||||||
|
#
|
||||||
|
#TransactionFrequencyFlush = 25
|
||||||
|
|
||||||
# Repositories.
|
# Repositories.
|
||||||
#
|
#
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
*/
|
*/
|
||||||
#define XBPS_PKGINDEX_VERSION "1.3"
|
#define XBPS_PKGINDEX_VERSION "1.3"
|
||||||
|
|
||||||
#define XBPS_API_VERSION "20111223"
|
#define XBPS_API_VERSION "20111224"
|
||||||
#define XBPS_VERSION "0.12"
|
#define XBPS_VERSION "0.12"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -159,6 +159,13 @@
|
|||||||
*/
|
*/
|
||||||
#define XBPS_FETCH_TIMEOUT 30
|
#define XBPS_FETCH_TIMEOUT 30
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def XBPS_TRANS_FLUSH
|
||||||
|
* Default number of packages to be processed in a transaction to
|
||||||
|
* trigger a flush to the master package database XBPS_REGPKGDB.
|
||||||
|
*/
|
||||||
|
#define XBPS_TRANS_FLUSH 5
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
void xbps_dbg_printf(const char *, ...);
|
void xbps_dbg_printf(const char *, ...);
|
||||||
@ -187,8 +194,6 @@ void xbps_warn_printf(const char *, ...);
|
|||||||
* XBPS_STATE_REMOVE_DONE: a package has been removed successfully.
|
* XBPS_STATE_REMOVE_DONE: a package has been removed successfully.
|
||||||
* XBPS_STATE_REMOVE_FILE: a package file is being removed.
|
* XBPS_STATE_REMOVE_FILE: a package file is being removed.
|
||||||
* XBPS_STATE_REMOVE_OBSOLETE: an obsolete package file is being removed.
|
* XBPS_STATE_REMOVE_OBSOLETE: an obsolete package file is being removed.
|
||||||
* XBPS_STATE_PURGE: a package is being purged.
|
|
||||||
* XBPS_STATE_PURGE_DONE: a package has been purged successfully.
|
|
||||||
* XBPS_STATE_REPLACE: a package is being replaced.
|
* XBPS_STATE_REPLACE: a package is being replaced.
|
||||||
* XBPS_STATE_INSTALL: a package is being installed.
|
* XBPS_STATE_INSTALL: a package is being installed.
|
||||||
* XBPS_STATE_INSTALL_DONE: a package has been installed successfully.
|
* XBPS_STATE_INSTALL_DONE: a package has been installed successfully.
|
||||||
@ -209,7 +214,6 @@ void xbps_warn_printf(const char *, ...);
|
|||||||
* its hash has failed.
|
* its hash has failed.
|
||||||
* XBPS_STATE_REMOVE_FILE_OBSOLETE_FAIL: an obsolete package file
|
* XBPS_STATE_REMOVE_FILE_OBSOLETE_FAIL: an obsolete package file
|
||||||
* removal has failed.
|
* removal has failed.
|
||||||
* XBPS_STATE_PURGE_FAIL: package purge has failed.
|
|
||||||
* XBPS_STATE_CONFIGURE_FAIL: package configure has failed.
|
* XBPS_STATE_CONFIGURE_FAIL: package configure has failed.
|
||||||
* XBPS_STATE_CONFIG_FILE_FAIL: package configuration file operation
|
* XBPS_STATE_CONFIG_FILE_FAIL: package configuration file operation
|
||||||
* has failed.
|
* has failed.
|
||||||
@ -419,12 +423,12 @@ struct xbps_handle {
|
|||||||
*/
|
*/
|
||||||
cfg_t *cfg;
|
cfg_t *cfg;
|
||||||
/**
|
/**
|
||||||
* @private regpkgdb_dictionary.
|
* @private regpkgdb.
|
||||||
*
|
*
|
||||||
* Internalized proplib dictionary with the registed package database
|
* Internalized proplib dictionary with the registed package database
|
||||||
* stored in XBPS_META_PATH/XBPS_REGPKGDB.
|
* stored in XBPS_META_PATH/XBPS_REGPKGDB.
|
||||||
*/
|
*/
|
||||||
prop_dictionary_t regpkgdb_dictionary;
|
prop_dictionary_t regpkgdb;
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*
|
*
|
||||||
@ -498,13 +502,20 @@ struct xbps_handle {
|
|||||||
*/
|
*/
|
||||||
const char *conffile;
|
const char *conffile;
|
||||||
/**
|
/**
|
||||||
* @private fetch_timeout
|
* @var fetch_timeout
|
||||||
*
|
*
|
||||||
* Unsigned integer to specify libfetch's timeout limit.
|
* Unsigned integer to specify libfetch's timeout limit.
|
||||||
* If not set, it defaults to 30 (in seconds). This is set internally
|
* If not set, it defaults to 30 (in seconds). This is set internally
|
||||||
* by the API from a setting in configuration file.
|
* by the API from a setting in configuration file.
|
||||||
*/
|
*/
|
||||||
uint16_t fetch_timeout;
|
uint16_t fetch_timeout;
|
||||||
|
/**
|
||||||
|
* @var transaction_frequency_flush
|
||||||
|
*
|
||||||
|
* Number of packages to be processed in a transaction to
|
||||||
|
* trigger a flush to the master databases.
|
||||||
|
*/
|
||||||
|
uint16_t transaction_frequency_flush;
|
||||||
/**
|
/**
|
||||||
* @var flags
|
* @var flags
|
||||||
*
|
*
|
||||||
@ -554,8 +565,8 @@ struct xbps_handle {
|
|||||||
* - Set default cache connections for libfetch.
|
* - Set default cache connections for libfetch.
|
||||||
* - Parse configuration file.
|
* - Parse configuration file.
|
||||||
*
|
*
|
||||||
* @param[in] xhp Pointer to an xbps_handle structure, as returned by
|
* @param[in] xhp The xbps_handle structure previously allocated
|
||||||
* \a xbps_handle_alloc().
|
* by \a xbps_handle_alloc().
|
||||||
* @note It's assumed that \a xhp is a valid pointer.
|
* @note It's assumed that \a xhp is a valid pointer.
|
||||||
*
|
*
|
||||||
* @return 0 on success, an errno value otherwise.
|
* @return 0 on success, an errno value otherwise.
|
||||||
@ -797,6 +808,32 @@ int xbps_regpkgdb_foreach_reverse_pkg_cb(
|
|||||||
int (*fn)(prop_object_t, void *, bool *),
|
int (*fn)(prop_object_t, void *, bool *),
|
||||||
void *arg);
|
void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a package dictionary from regpkgdb plist, matching pkgname or
|
||||||
|
* pkgver specified in \a pkg.
|
||||||
|
*
|
||||||
|
* @param[in] pkg Package name or name-version tuple to match.
|
||||||
|
* @param[in] bypattern If false \a pkg must be a pkgname, otherwise a pkgver.
|
||||||
|
*
|
||||||
|
* @return The matching proplib package dictionary from regpkgdb copied
|
||||||
|
* with \a prop_dictionary_copy() so it must be released when not required
|
||||||
|
* anymore with prop_object_release().
|
||||||
|
*/
|
||||||
|
prop_dictionary_t xbps_regpkgdb_get_pkgd(const char *pkg, bool bypattern);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the regpkgdb plist with new contents from disk to the cached copy
|
||||||
|
* in memory.
|
||||||
|
*
|
||||||
|
* @param[in] xhp Pointer to our xbps_handle struct, as returned by
|
||||||
|
* \a xbps_handle_get() or xbps_handle_alloc().
|
||||||
|
* @param[in] flush If true the regpkgdb plist contents in memory will
|
||||||
|
* be flushed atomically to disk.
|
||||||
|
*
|
||||||
|
* @return 0 on success, otherwise an errno value.
|
||||||
|
*/
|
||||||
|
int xbps_regpkgdb_update(struct xbps_handle *xhp, bool flush);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the proplib's dictionary associated with a package, by looking
|
* Finds the proplib's dictionary associated with a package, by looking
|
||||||
* it via its name in a proplib dictionary.
|
* it via its name in a proplib dictionary.
|
||||||
@ -1097,30 +1134,6 @@ int xbps_array_replace_dict_by_name(prop_array_t array,
|
|||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
/** @addtogroup purge */
|
|
||||||
/*@{*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Purge an installed package.
|
|
||||||
*
|
|
||||||
* @param[in] pkgname Package name to match.
|
|
||||||
* @param[in] check_state Set it to true to check that package
|
|
||||||
* is in XBPS_PKG_STATE_CONFIG_FILES state.
|
|
||||||
*
|
|
||||||
* @return 0 on success, otherwise an errno value.
|
|
||||||
*/
|
|
||||||
int xbps_purge_pkg(const char *pkgname, bool check_state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Purge all installed packages. Packages that aren't in
|
|
||||||
* XBPS_PKG_STATE_CONFIG_FILES state will be ignored.
|
|
||||||
*
|
|
||||||
* @return 0 on success, otherwise an errno value.
|
|
||||||
*/
|
|
||||||
int xbps_purge_packages(void);
|
|
||||||
|
|
||||||
/*@}*/
|
|
||||||
|
|
||||||
/** @addtogroup pkg_register */
|
/** @addtogroup pkg_register */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
|
|
||||||
@ -1220,7 +1233,6 @@ int xbps_transaction_update_packages(void);
|
|||||||
* be added into the transaction dictionary.
|
* be added into the transaction dictionary.
|
||||||
*
|
*
|
||||||
* @param[in] pkgname Package name to be removed.
|
* @param[in] pkgname Package name to be removed.
|
||||||
* @param[in] purge If true package will also be purged.
|
|
||||||
* @param[in] recursive If true, all packages that are currently depending
|
* @param[in] recursive If true, all packages that are currently depending
|
||||||
* on the package to be removed, and if they are orphans, will be added.
|
* on the package to be removed, and if they are orphans, will be added.
|
||||||
*
|
*
|
||||||
@ -1229,19 +1241,16 @@ int xbps_transaction_update_packages(void);
|
|||||||
* process.
|
* process.
|
||||||
*/
|
*/
|
||||||
int xbps_transaction_remove_pkg(const char *pkgname,
|
int xbps_transaction_remove_pkg(const char *pkgname,
|
||||||
bool purge,
|
|
||||||
bool recursive);
|
bool recursive);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds all package orphans currently installed and adds them into
|
* Finds all package orphans currently installed and adds them into
|
||||||
* the transaction dictionary.
|
* the transaction dictionary.
|
||||||
*
|
*
|
||||||
* @param[in] purge If true packages will also be purged.
|
|
||||||
*
|
|
||||||
* @return 0 on succcess, ENOENT if no package orphans were found, ENXIO
|
* @return 0 on succcess, ENOENT if no package orphans were found, ENXIO
|
||||||
* or EINVAL if a problem ocurred in the process.
|
* or EINVAL if a problem ocurred in the process.
|
||||||
*/
|
*/
|
||||||
int xbps_transaction_autoremove_pkgs(bool purge);
|
int xbps_transaction_autoremove_pkgs(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the transaction dictionary, as shown above in the image.
|
* Returns the transaction dictionary, as shown above in the image.
|
||||||
@ -1452,8 +1461,9 @@ int xbps_repository_sync_pkg_index(const char *uri);
|
|||||||
*
|
*
|
||||||
* <b>XBPS_PKG_STATE_BROKEN</b>: not yet used.
|
* <b>XBPS_PKG_STATE_BROKEN</b>: not yet used.
|
||||||
*
|
*
|
||||||
* <b>XBPS_PKG_STATE_CONFIG_FILES</b>: Package has been removed but not
|
* <b>XBPS_PKG_STATE_HALF_REMOVED</b>: Package has been removed but not
|
||||||
* yet purged.
|
* completely: the purge action in REMOVE script wasn't executed, pkg
|
||||||
|
* metadata directory still exists and is registered in package database.
|
||||||
*
|
*
|
||||||
* <b>XBPS_PKG_STATE_NOT_INSTALLED</b>: Package going to be installed in
|
* <b>XBPS_PKG_STATE_NOT_INSTALLED</b>: Package going to be installed in
|
||||||
* a transaction dictionary but that has not been yet unpacked.
|
* a transaction dictionary but that has not been yet unpacked.
|
||||||
@ -1462,7 +1472,7 @@ typedef enum pkg_state {
|
|||||||
XBPS_PKG_STATE_UNPACKED = 1,
|
XBPS_PKG_STATE_UNPACKED = 1,
|
||||||
XBPS_PKG_STATE_INSTALLED,
|
XBPS_PKG_STATE_INSTALLED,
|
||||||
XBPS_PKG_STATE_BROKEN,
|
XBPS_PKG_STATE_BROKEN,
|
||||||
XBPS_PKG_STATE_CONFIG_FILES,
|
XBPS_PKG_STATE_HALF_REMOVED,
|
||||||
XBPS_PKG_STATE_NOT_INSTALLED,
|
XBPS_PKG_STATE_NOT_INSTALLED,
|
||||||
XBPS_PKG_STATE_HALF_UNPACKED
|
XBPS_PKG_STATE_HALF_UNPACKED
|
||||||
} pkg_state_t;
|
} pkg_state_t;
|
||||||
|
@ -128,7 +128,7 @@ int HIDDEN xbps_repository_find_pkg_deps(prop_dictionary_t,
|
|||||||
* @private
|
* @private
|
||||||
* From lib/package_requiredby.c
|
* From lib/package_requiredby.c
|
||||||
*/
|
*/
|
||||||
int HIDDEN xbps_requiredby_pkg_add(prop_array_t, prop_dictionary_t);
|
int HIDDEN xbps_requiredby_pkg_add(struct xbps_handle *, prop_dictionary_t);
|
||||||
int HIDDEN xbps_requiredby_pkg_remove(const char *);
|
int HIDDEN xbps_requiredby_pkg_remove(const char *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,7 +44,7 @@ EXTOBJS += external/match.o external/mkpath.o
|
|||||||
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 transaction_commit.o transaction_package_replace.o
|
OBJS += transaction_commit.o transaction_package_replace.o
|
||||||
OBJS += transaction_dictionary.o transaction_sortdeps.o transaction_ops.o
|
OBJS += transaction_dictionary.o transaction_sortdeps.o transaction_ops.o
|
||||||
OBJS += download.o initend.o
|
OBJS += download.o initend.o
|
||||||
OBJS += plist.o plist_archive_entry.o plist_find.o plist_match.o
|
OBJS += plist.o plist_archive_entry.o plist_find.o plist_match.o
|
||||||
|
@ -88,12 +88,14 @@ xbps_init(struct xbps_handle *xh)
|
|||||||
CFG_STR(__UNCONST("rootdir"), __UNCONST("/"), CFGF_NONE),
|
CFG_STR(__UNCONST("rootdir"), __UNCONST("/"), CFGF_NONE),
|
||||||
CFG_STR(__UNCONST("cachedir"),
|
CFG_STR(__UNCONST("cachedir"),
|
||||||
__UNCONST(XBPS_CACHE_PATH), CFGF_NONE),
|
__UNCONST(XBPS_CACHE_PATH), CFGF_NONE),
|
||||||
CFG_INT(__UNCONST("fetch-cache-connections"),
|
CFG_INT(__UNCONST("FetchCacheConnections"),
|
||||||
XBPS_FETCH_CACHECONN, CFGF_NONE),
|
XBPS_FETCH_CACHECONN, CFGF_NONE),
|
||||||
CFG_INT(__UNCONST("fetch-cache-connections-per-host"),
|
CFG_INT(__UNCONST("FetchCacheConnectionsPerHost"),
|
||||||
XBPS_FETCH_CACHECONN_HOST, CFGF_NONE),
|
XBPS_FETCH_CACHECONN_HOST, CFGF_NONE),
|
||||||
CFG_INT(__UNCONST("fetch-timeout-connection"),
|
CFG_INT(__UNCONST("FetchTimeoutConnection"),
|
||||||
XBPS_FETCH_TIMEOUT, CFGF_NONE),
|
XBPS_FETCH_TIMEOUT, CFGF_NONE),
|
||||||
|
CFG_INT(__UNCONST("TransactionFrequencyFlush"),
|
||||||
|
XBPS_TRANS_FLUSH, CFGF_NONE),
|
||||||
CFG_BOOL(__UNCONST("syslog"), true, CFGF_NONE),
|
CFG_BOOL(__UNCONST("syslog"), true, CFGF_NONE),
|
||||||
CFG_STR_LIST(__UNCONST("repositories"), NULL, CFGF_MULTI),
|
CFG_STR_LIST(__UNCONST("repositories"), NULL, CFGF_MULTI),
|
||||||
CFG_SEC(__UNCONST("virtual-package"),
|
CFG_SEC(__UNCONST("virtual-package"),
|
||||||
@ -161,22 +163,27 @@ xbps_init(struct xbps_handle *xh)
|
|||||||
if (xhp->cfg == NULL) {
|
if (xhp->cfg == NULL) {
|
||||||
xhp->syslog_enabled = true;
|
xhp->syslog_enabled = true;
|
||||||
xhp->fetch_timeout = XBPS_FETCH_TIMEOUT;
|
xhp->fetch_timeout = XBPS_FETCH_TIMEOUT;
|
||||||
|
xhp->transaction_frequency_flush = XBPS_TRANS_FLUSH;
|
||||||
cc = XBPS_FETCH_CACHECONN;
|
cc = XBPS_FETCH_CACHECONN;
|
||||||
cch = XBPS_FETCH_CACHECONN_HOST;
|
cch = XBPS_FETCH_CACHECONN_HOST;
|
||||||
} else {
|
} else {
|
||||||
xhp->syslog_enabled = cfg_getbool(xhp->cfg, "syslog");
|
xhp->syslog_enabled = cfg_getbool(xhp->cfg, "syslog");
|
||||||
xhp->fetch_timeout = cfg_getint(xhp->cfg, "fetch-timeout-connection");
|
xhp->fetch_timeout = cfg_getint(xhp->cfg, "FetchTimeoutConnection");
|
||||||
cc = cfg_getint(xhp->cfg, "fetch-cache-connections");
|
cc = cfg_getint(xhp->cfg, "FetchCacheConnections");
|
||||||
cch = cfg_getint(xhp->cfg, "fetch-cache-connections-per-host");
|
cch = cfg_getint(xhp->cfg, "FetchCacheConnectionsPerHost");
|
||||||
|
xhp->transaction_frequency_flush =
|
||||||
|
cfg_getint(xhp->cfg, "TransactionFrequencyFlush");
|
||||||
}
|
}
|
||||||
xbps_fetch_set_cache_connection(cc, cch);
|
xbps_fetch_set_cache_connection(cc, cch);
|
||||||
|
|
||||||
xbps_dbg_printf("rootdir=%s\n", xhp->rootdir);
|
xbps_dbg_printf("Rootdir=%s\n", xhp->rootdir);
|
||||||
xbps_dbg_printf("cachedir=%s\n", xhp->cachedir);
|
xbps_dbg_printf("Cachedir=%s\n", xhp->cachedir);
|
||||||
xbps_dbg_printf("fetch-timeout=%u\n", xhp->fetch_timeout);
|
xbps_dbg_printf("FetchTimeout=%u\n", xhp->fetch_timeout);
|
||||||
xbps_dbg_printf("fetch-cacheconn=%u\n", cc);
|
xbps_dbg_printf("FetchCacheconn=%u\n", cc);
|
||||||
xbps_dbg_printf("fetch-cacheconn-host=%u\n", cch);
|
xbps_dbg_printf("FetchCacheconnHost=%u\n", cch);
|
||||||
xbps_dbg_printf("syslog=%u\n", xhp->syslog_enabled);
|
xbps_dbg_printf("Syslog=%u\n", xhp->syslog_enabled);
|
||||||
|
xbps_dbg_printf("TransactionFrequencyFlush=%u\n",
|
||||||
|
xhp->transaction_frequency_flush);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -86,8 +86,7 @@ xbps_configure_pkg(const char *pkgname,
|
|||||||
rv = xbps_pkg_state_installed(pkgname, &state);
|
rv = xbps_pkg_state_installed(pkgname, &state);
|
||||||
if (rv == ENOENT) {
|
if (rv == ENOENT) {
|
||||||
/*
|
/*
|
||||||
* package not installed or has been removed
|
* package not installed or has been removed.
|
||||||
* (must be purged) so ignore it.
|
|
||||||
*/
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
} else if (rv != 0) {
|
} else if (rv != 0) {
|
||||||
|
@ -90,9 +90,10 @@ find_orphan_pkg(prop_object_t obj, void *arg, bool *loop_done)
|
|||||||
if ((rv = xbps_pkg_state_dictionary(obj, &state)) != 0)
|
if ((rv = xbps_pkg_state_dictionary(obj, &state)) != 0)
|
||||||
return rv;
|
return rv;
|
||||||
/*
|
/*
|
||||||
* Skip packages that aren't fully installed.
|
* Skip packages that aren't fully installed or half removed.
|
||||||
*/
|
*/
|
||||||
if (state != XBPS_PKG_STATE_INSTALLED)
|
if (state != XBPS_PKG_STATE_INSTALLED &&
|
||||||
|
state != XBPS_PKG_STATE_HALF_REMOVED)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
reqby = prop_dictionary_get(obj, "requiredby");
|
reqby = prop_dictionary_get(obj, "requiredby");
|
||||||
|
@ -1,233 +0,0 @@
|
|||||||
/*-
|
|
||||||
* Copyright (c) 2009-2011 Juan Romero Pardines.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
#include "xbps_api_impl.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file lib/package_purge.c
|
|
||||||
* @brief Package purging routines
|
|
||||||
* @defgroup purge Package purging functions
|
|
||||||
*
|
|
||||||
* These functions will purge an specified package or all packages.
|
|
||||||
* Only packages in XBPS_PKG_STATE_CONFIG_FILES state will be processed
|
|
||||||
* (unless overriden). Package purging steps:
|
|
||||||
*
|
|
||||||
* - Unmodified configuration files will be removed.
|
|
||||||
* - The purge action in the REMOVE script will be executed (if found).
|
|
||||||
* - Metadata files will be removed and package will be unregistered
|
|
||||||
* with xbps_unregister_pkg().
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
remove_pkg_metadata(const char *pkgname,
|
|
||||||
const char *version,
|
|
||||||
const char *pkgver,
|
|
||||||
const char *rootdir)
|
|
||||||
{
|
|
||||||
struct dirent *dp;
|
|
||||||
DIR *dirp;
|
|
||||||
char *metadir, *path;
|
|
||||||
int rv = 0;
|
|
||||||
|
|
||||||
assert(pkgname != NULL);
|
|
||||||
assert(rootdir != NULL);
|
|
||||||
|
|
||||||
metadir = xbps_xasprintf("%s/%s/metadata/%s", rootdir,
|
|
||||||
XBPS_META_PATH, pkgname);
|
|
||||||
if (metadir == NULL)
|
|
||||||
return ENOMEM;
|
|
||||||
|
|
||||||
dirp = opendir(metadir);
|
|
||||||
if (dirp == NULL) {
|
|
||||||
free(metadir);
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((dp = readdir(dirp)) != NULL) {
|
|
||||||
if ((strcmp(dp->d_name, ".") == 0) ||
|
|
||||||
(strcmp(dp->d_name, "..") == 0))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
path = xbps_xasprintf("%s/%s", metadir, dp->d_name);
|
|
||||||
if (path == NULL) {
|
|
||||||
(void)closedir(dirp);
|
|
||||||
free(metadir);
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlink(path) == -1) {
|
|
||||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
|
||||||
errno, pkgname, version,
|
|
||||||
"%s: [purge] failed to remove metafile `%s': %s",
|
|
||||||
pkgver, path, strerror(errno));
|
|
||||||
}
|
|
||||||
free(path);
|
|
||||||
}
|
|
||||||
(void)closedir(dirp);
|
|
||||||
rv = rmdir(metadir);
|
|
||||||
free(metadir);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
purge_pkgs_cb(prop_object_t obj, void *arg, bool *done)
|
|
||||||
{
|
|
||||||
const char *pkgname;
|
|
||||||
|
|
||||||
(void)arg;
|
|
||||||
(void)done;
|
|
||||||
|
|
||||||
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
|
||||||
return xbps_purge_pkg(pkgname, true);
|
|
||||||
}
|
|
||||||
int
|
|
||||||
xbps_purge_packages(void)
|
|
||||||
{
|
|
||||||
return xbps_regpkgdb_foreach_pkg_cb(purge_pkgs_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
xbps_purge_pkg(const char *pkgname, bool check_state)
|
|
||||||
{
|
|
||||||
struct xbps_handle *xhp;
|
|
||||||
prop_dictionary_t dict, pkgd;
|
|
||||||
const char *version, *pkgver;
|
|
||||||
char *buf;
|
|
||||||
int rv = 0;
|
|
||||||
pkg_state_t state;
|
|
||||||
|
|
||||||
assert(pkgname != NULL);
|
|
||||||
xhp = xbps_handle_get();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Firstly let's get the pkg dictionary from regpkgdb.
|
|
||||||
*/
|
|
||||||
pkgd = xbps_find_pkg_in_dict_by_name(xhp->regpkgdb_dictionary,
|
|
||||||
"packages", pkgname);
|
|
||||||
if (pkgd == NULL) {
|
|
||||||
xbps_dbg_printf("[purge] %s: missing pkg dictionary (%s)\n",
|
|
||||||
pkgname, strerror(errno));
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
|
|
||||||
prop_dictionary_get_cstring_nocopy(pkgd, "version", &version);
|
|
||||||
xbps_set_cb_state(XBPS_STATE_PURGE, 0, pkgname, version, NULL);
|
|
||||||
|
|
||||||
if (check_state) {
|
|
||||||
/*
|
|
||||||
* Skip packages that aren't in "config-files" state.
|
|
||||||
*/
|
|
||||||
if ((rv = xbps_pkg_state_dictionary(pkgd, &state)) != 0)
|
|
||||||
return rv;
|
|
||||||
if (state != XBPS_PKG_STATE_CONFIG_FILES) {
|
|
||||||
xbps_dbg_printf("[purge] %s not in config-files "
|
|
||||||
"state.\n", pkgname);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Remove unmodified configuration files.
|
|
||||||
*/
|
|
||||||
dict = xbps_dictionary_from_metadata_plist(pkgname, XBPS_PKGFILES);
|
|
||||||
if (dict == NULL) {
|
|
||||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
|
||||||
errno, pkgname, version,
|
|
||||||
"%s: [purge] failed to read metafile `%s': %s",
|
|
||||||
pkgver, XBPS_PKGFILES, strerror(errno));
|
|
||||||
if (errno != ENOENT)
|
|
||||||
return errno;
|
|
||||||
} else {
|
|
||||||
if (prop_dictionary_get(dict, "conf_files")) {
|
|
||||||
rv = xbps_remove_pkg_files(dict, "conf_files", pkgver);
|
|
||||||
if (rv != 0) {
|
|
||||||
prop_object_release(dict);
|
|
||||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
|
||||||
rv, pkgname, version,
|
|
||||||
"%s: [purge] failed to remove "
|
|
||||||
"configuration files: %s",
|
|
||||||
pkgver, strerror(rv));
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prop_object_release(dict);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Execute the purge action in REMOVE script (if found).
|
|
||||||
*/
|
|
||||||
if (chdir(xhp->rootdir) == -1) {
|
|
||||||
rv = errno;
|
|
||||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
|
||||||
rv, pkgname, version,
|
|
||||||
"%s: [purge] failed to chdir to rootdir `%s': %s",
|
|
||||||
pkgver, xhp->rootdir, strerror(rv));
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
buf = xbps_xasprintf("%s/metadata/%s/REMOVE", XBPS_META_PATH, pkgname);
|
|
||||||
if (buf == NULL) {
|
|
||||||
rv = ENOMEM;
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
if (access(buf, X_OK) == 0) {
|
|
||||||
rv = xbps_file_exec(buf, "purge", pkgname, version,
|
|
||||||
"no", xhp->conffile, NULL);
|
|
||||||
if (rv != 0) {
|
|
||||||
free(buf);
|
|
||||||
if (errno && errno != ENOENT) {
|
|
||||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
|
||||||
errno, pkgname, version,
|
|
||||||
"%s: [purge] REMOVE script failed to "
|
|
||||||
"execute purge ACTION: %s",
|
|
||||||
pkgver, strerror(errno));
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(buf);
|
|
||||||
/*
|
|
||||||
* Remove metadata dir and unregister package.
|
|
||||||
*/
|
|
||||||
if ((rv = remove_pkg_metadata(pkgname, version, pkgver,
|
|
||||||
xhp->rootdir)) != 0) {
|
|
||||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
|
||||||
rv, pkgname, version,
|
|
||||||
"%s: [purge] failed to remove metadata files: %s",
|
|
||||||
pkgver, strerror(rv));
|
|
||||||
if (rv != ENOENT)
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
if ((rv = xbps_unregister_pkg(pkgname, version)) != 0)
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
xbps_set_cb_state(XBPS_STATE_PURGE_DONE, 0, pkgname, version, NULL);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
@ -43,20 +43,15 @@ int
|
|||||||
xbps_register_pkg(prop_dictionary_t pkgrd)
|
xbps_register_pkg(prop_dictionary_t pkgrd)
|
||||||
{
|
{
|
||||||
struct xbps_handle *xhp;
|
struct xbps_handle *xhp;
|
||||||
prop_dictionary_t dict, pkgd;
|
prop_dictionary_t pkgd;
|
||||||
prop_array_t array, provides = NULL, reqby;
|
prop_array_t provides, reqby, array;
|
||||||
const char *pkgname, *version, *desc, *pkgver;
|
const char *pkgname, *version, *desc, *pkgver;
|
||||||
char *plist;
|
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
bool autoinst = false;
|
bool autoinst = false;
|
||||||
|
|
||||||
assert(prop_object_type(pkgrd) == PROP_TYPE_DICTIONARY);
|
assert(prop_object_type(pkgrd) == PROP_TYPE_DICTIONARY);
|
||||||
|
|
||||||
xhp = xbps_handle_get();
|
xhp = xbps_handle_get();
|
||||||
plist = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
|
||||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
|
||||||
if (plist == NULL)
|
|
||||||
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);
|
||||||
@ -72,80 +67,72 @@ xbps_register_pkg(prop_dictionary_t pkgrd)
|
|||||||
assert(version != NULL);
|
assert(version != NULL);
|
||||||
assert(desc != NULL);
|
assert(desc != NULL);
|
||||||
assert(pkgver != NULL);
|
assert(pkgver != NULL);
|
||||||
|
assert(xhp->regpkgdb != NULL);
|
||||||
|
|
||||||
if ((dict = prop_dictionary_internalize_from_zfile(plist)) != NULL) {
|
pkgd = xbps_regpkgdb_get_pkgd(pkgname, false);
|
||||||
pkgd = xbps_find_pkg_in_dict_by_name(dict,
|
if (pkgd == NULL) {
|
||||||
"packages", pkgname);
|
rv = ENOENT;
|
||||||
if (pkgd == NULL) {
|
goto out;
|
||||||
rv = errno;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
|
||||||
"version", version)) {
|
|
||||||
prop_object_release(pkgd);
|
|
||||||
rv = EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
|
||||||
"pkgver", pkgver)) {
|
|
||||||
prop_object_release(pkgd);
|
|
||||||
rv = EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
|
||||||
"short_desc", desc)) {
|
|
||||||
prop_object_release(pkgd);
|
|
||||||
rv = EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (reqby && !prop_dictionary_set(pkgd, "requiredby", reqby)) {
|
|
||||||
prop_object_release(pkgd);
|
|
||||||
rv = EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
prop_dictionary_get_bool(pkgd, "automatic-install", &autoinst);
|
|
||||||
if (xhp->install_reason_auto)
|
|
||||||
autoinst = true;
|
|
||||||
else if (xhp->install_reason_manual)
|
|
||||||
autoinst = false;
|
|
||||||
|
|
||||||
if (!prop_dictionary_set_bool(pkgd,
|
|
||||||
"automatic-install", autoinst)) {
|
|
||||||
prop_object_release(pkgd);
|
|
||||||
rv = EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (provides) {
|
|
||||||
if (!prop_dictionary_set(pkgd, "provides", provides)) {
|
|
||||||
prop_object_release(pkgd);
|
|
||||||
rv = EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Add the requiredby objects for dependent packages.
|
|
||||||
*/
|
|
||||||
if (pkgrd && xbps_pkg_has_rundeps(pkgrd)) {
|
|
||||||
array = prop_dictionary_get(dict, "packages");
|
|
||||||
if (array == NULL) {
|
|
||||||
prop_object_release(pkgd);
|
|
||||||
rv = EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if ((rv = xbps_requiredby_pkg_add(array, pkgrd)) != 0)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Write plist file to storage.
|
|
||||||
*/
|
|
||||||
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
|
|
||||||
rv = errno;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
free(plist);
|
|
||||||
return ENOENT;
|
|
||||||
}
|
}
|
||||||
|
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
||||||
|
"version", version)) {
|
||||||
|
prop_object_release(pkgd);
|
||||||
|
rv = EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
||||||
|
"pkgver", pkgver)) {
|
||||||
|
prop_object_release(pkgd);
|
||||||
|
rv = EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
||||||
|
"short_desc", desc)) {
|
||||||
|
prop_object_release(pkgd);
|
||||||
|
rv = EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (reqby && !prop_dictionary_set(pkgd, "requiredby", reqby)) {
|
||||||
|
prop_object_release(pkgd);
|
||||||
|
rv = EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
prop_dictionary_get_bool(pkgd, "automatic-install", &autoinst);
|
||||||
|
if (xhp->install_reason_auto)
|
||||||
|
autoinst = true;
|
||||||
|
else if (xhp->install_reason_manual)
|
||||||
|
autoinst = false;
|
||||||
|
|
||||||
|
if (!prop_dictionary_set_bool(pkgd,
|
||||||
|
"automatic-install", autoinst)) {
|
||||||
|
prop_object_release(pkgd);
|
||||||
|
rv = EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (provides) {
|
||||||
|
if (!prop_dictionary_set(pkgd, "provides", provides)) {
|
||||||
|
prop_object_release(pkgd);
|
||||||
|
rv = EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array = prop_dictionary_get(xhp->regpkgdb, "packages");
|
||||||
|
rv = xbps_array_replace_dict_by_name(array, pkgd, pkgname);
|
||||||
|
if (rv != 0) {
|
||||||
|
prop_object_release(pkgd);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Add the requiredby objects for dependent packages.
|
||||||
|
*/
|
||||||
|
if (pkgrd && xbps_pkg_has_rundeps(pkgrd)) {
|
||||||
|
if ((rv = xbps_requiredby_pkg_add(xhp, pkgrd)) != 0) {
|
||||||
|
prop_object_release(pkgd);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prop_object_release(pkgd);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
xbps_set_cb_state(XBPS_STATE_REGISTER_FAIL,
|
xbps_set_cb_state(XBPS_STATE_REGISTER_FAIL,
|
||||||
@ -153,8 +140,6 @@ out:
|
|||||||
"%s: failed to register package: %s",
|
"%s: failed to register package: %s",
|
||||||
pkgver, strerror(rv));
|
pkgver, strerror(rv));
|
||||||
}
|
}
|
||||||
prop_object_release(dict);
|
|
||||||
free(plist);
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -163,31 +148,24 @@ int
|
|||||||
xbps_unregister_pkg(const char *pkgname, const char *version)
|
xbps_unregister_pkg(const char *pkgname, const char *version)
|
||||||
{
|
{
|
||||||
struct xbps_handle *xhp;
|
struct xbps_handle *xhp;
|
||||||
char *plist;
|
int rv;
|
||||||
int rv = 0;
|
|
||||||
|
|
||||||
assert(pkgname != NULL);
|
assert(pkgname != NULL);
|
||||||
|
|
||||||
|
xhp = xbps_handle_get();
|
||||||
|
if ((rv = xbps_regpkgdb_dictionary_init(xhp)) != 0)
|
||||||
|
return rv;
|
||||||
|
|
||||||
xbps_set_cb_state(XBPS_STATE_UNREGISTER, 0, pkgname, version, NULL);
|
xbps_set_cb_state(XBPS_STATE_UNREGISTER, 0, pkgname, version, NULL);
|
||||||
|
|
||||||
xhp = xbps_handle_get();
|
if (!xbps_remove_pkg_from_dict_by_name(xhp->regpkgdb,
|
||||||
plist = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
"packages", pkgname)) {
|
||||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
|
||||||
if (plist == NULL) {
|
|
||||||
rv = ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (!xbps_remove_pkg_dict_from_plist_by_name(pkgname, plist)) {
|
|
||||||
rv = errno;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
if (rv != 0) {
|
|
||||||
xbps_set_cb_state(XBPS_STATE_UNREGISTER_FAIL,
|
xbps_set_cb_state(XBPS_STATE_UNREGISTER_FAIL,
|
||||||
rv, pkgname, version,
|
errno, pkgname, version,
|
||||||
"%s: failed to unregister package: %s",
|
"%s: failed to unregister package: %s",
|
||||||
pkgname, strerror(rv));
|
pkgname, strerror(errno));
|
||||||
|
return errno;
|
||||||
}
|
}
|
||||||
free(plist);
|
|
||||||
return rv;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -42,14 +42,18 @@
|
|||||||
* files. Package removal steps:
|
* files. Package removal steps:
|
||||||
* -# Its <b>pre-remove</b> target specified in the REMOVE script
|
* -# Its <b>pre-remove</b> target specified in the REMOVE script
|
||||||
* will be executed.
|
* will be executed.
|
||||||
* -# Its files, dirs and links will be removed. Modified files (not
|
* -# Its links, files, conf_files and dirs will be removed.
|
||||||
* matching its sha256 hash) are preserved, unless
|
* Modified files (not matchings its sha256 hash) are preserved, unless
|
||||||
* XBPS_FLAG_FORCE_REMOVE_FILES flag is set via xbps_init::flags member.
|
* XBPS_FLAG_FORCE_REMOVE_FILES flag is set via xbps_init::flags member.
|
||||||
* -# Its <b>post-remove</b> target specified in the REMOVE script
|
* -# Its <b>post-remove</b> target specified in the REMOVE script
|
||||||
* will be executed.
|
* will be executed.
|
||||||
* -# Its requiredby objects will be removed from the installed packages
|
* -# Its requiredby objects will be removed from the installed packages
|
||||||
* database.
|
* database.
|
||||||
* -# Its state will be changed to XBPS_PKG_STATE_CONFIG_FILES.
|
* -# Its state will be changed to XBPS_PKG_STATE_HALF_UNPACKED.
|
||||||
|
* -# Its <b>purge-remove</b> target specified in the REMOVE script
|
||||||
|
* will be executed.
|
||||||
|
* -# Its package metadata directory will be removed.
|
||||||
|
* -# Package will be unregistered from package database.
|
||||||
*
|
*
|
||||||
* @note
|
* @note
|
||||||
* -# If a package is going to be updated, only steps <b>1</b> and <b>4</b>
|
* -# If a package is going to be updated, only steps <b>1</b> and <b>4</b>
|
||||||
@ -69,6 +73,58 @@
|
|||||||
* Text inside of white boxes are the key associated with the object, its
|
* Text inside of white boxes are the key associated with the object, its
|
||||||
* data type is specified on its edge, i.e string, array, integer, dictionary.
|
* data type is specified on its edge, i.e string, array, integer, dictionary.
|
||||||
*/
|
*/
|
||||||
|
static int
|
||||||
|
remove_pkg_metadata(const char *pkgname,
|
||||||
|
const char *version,
|
||||||
|
const char *pkgver,
|
||||||
|
const char *rootdir)
|
||||||
|
{
|
||||||
|
struct dirent *dp;
|
||||||
|
DIR *dirp;
|
||||||
|
char *metadir, *path;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
assert(pkgname != NULL);
|
||||||
|
assert(rootdir != NULL);
|
||||||
|
|
||||||
|
metadir = xbps_xasprintf("%s/%s/metadata/%s", rootdir,
|
||||||
|
XBPS_META_PATH, pkgname);
|
||||||
|
if (metadir == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
dirp = opendir(metadir);
|
||||||
|
if (dirp == NULL) {
|
||||||
|
free(metadir);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((dp = readdir(dirp)) != NULL) {
|
||||||
|
if ((strcmp(dp->d_name, ".") == 0) ||
|
||||||
|
(strcmp(dp->d_name, "..") == 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
path = xbps_xasprintf("%s/%s", metadir, dp->d_name);
|
||||||
|
if (path == NULL) {
|
||||||
|
(void)closedir(dirp);
|
||||||
|
free(metadir);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlink(path) == -1) {
|
||||||
|
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
||||||
|
errno, pkgname, version,
|
||||||
|
"%s: [purge] failed to remove metafile `%s': %s",
|
||||||
|
pkgver, path, strerror(errno));
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
(void)closedir(dirp);
|
||||||
|
rv = rmdir(metadir);
|
||||||
|
free(metadir);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xbps_remove_pkg_files(prop_dictionary_t dict,
|
xbps_remove_pkg_files(prop_dictionary_t dict,
|
||||||
const char *key,
|
const char *key,
|
||||||
@ -87,9 +143,8 @@ xbps_remove_pkg_files(prop_dictionary_t dict,
|
|||||||
xhp = xbps_handle_get();
|
xhp = xbps_handle_get();
|
||||||
|
|
||||||
array = prop_dictionary_get(dict, key);
|
array = prop_dictionary_get(dict, key);
|
||||||
if (array == NULL)
|
if ((prop_object_type(array) != PROP_TYPE_ARRAY) ||
|
||||||
return EINVAL;
|
prop_array_count(array) == 0)
|
||||||
else if (prop_array_count(array) == 0)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
iter = xbps_array_iter_from_dict(dict, key);
|
iter = xbps_array_iter_from_dict(dict, key);
|
||||||
@ -174,6 +229,7 @@ xbps_remove_pkg_files(prop_dictionary_t dict,
|
|||||||
errno, pkgname, version,
|
errno, pkgname, version,
|
||||||
"%s: failed to remove %s `%s': %s", pkgver,
|
"%s: failed to remove %s `%s': %s", pkgver,
|
||||||
curobj, file, strerror(errno));
|
curobj, file, strerror(errno));
|
||||||
|
errno = 0;
|
||||||
} else {
|
} else {
|
||||||
/* success */
|
/* success */
|
||||||
xbps_set_cb_state(XBPS_STATE_REMOVE_FILE,
|
xbps_set_cb_state(XBPS_STATE_REMOVE_FILE,
|
||||||
@ -193,47 +249,47 @@ int
|
|||||||
xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
||||||
{
|
{
|
||||||
struct xbps_handle *xhp;
|
struct xbps_handle *xhp;
|
||||||
prop_dictionary_t dict;
|
prop_dictionary_t pkgd = NULL;
|
||||||
char *buf, *pkgver;
|
char *buf = NULL, *pkgver = NULL;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
bool rmfile_exists = false;
|
bool rmfile_exists = false;
|
||||||
|
pkg_state_t state = 0;
|
||||||
|
|
||||||
assert(pkgname != NULL);
|
assert(pkgname != NULL);
|
||||||
assert(version != NULL);
|
assert(version != NULL);
|
||||||
|
|
||||||
xhp = xbps_handle_get();
|
xhp = xbps_handle_get();
|
||||||
/*
|
|
||||||
* Check if pkg is installed before anything else.
|
|
||||||
*/
|
|
||||||
if (!xbps_check_is_installed_pkg_by_name(pkgname))
|
|
||||||
return ENOENT;
|
|
||||||
|
|
||||||
pkgver = xbps_xasprintf("%s-%s", pkgname, version);
|
|
||||||
if (pkgver == NULL)
|
|
||||||
return ENOMEM;
|
|
||||||
|
|
||||||
if (!update)
|
|
||||||
xbps_set_cb_state(XBPS_STATE_REMOVE, 0, pkgname, version, NULL);
|
|
||||||
|
|
||||||
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) {
|
||||||
rv = ENOMEM;
|
rv = ENOMEM;
|
||||||
free(pkgver);
|
goto out;
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pkgver = xbps_xasprintf("%s-%s", pkgname, version);
|
||||||
|
if (pkgver == NULL) {
|
||||||
|
rv = ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rv = xbps_pkg_state_installed(pkgname, &state)) != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!update)
|
||||||
|
xbps_set_cb_state(XBPS_STATE_REMOVE, 0, pkgname, version, NULL);
|
||||||
|
|
||||||
if (chdir(xhp->rootdir) == -1) {
|
if (chdir(xhp->rootdir) == -1) {
|
||||||
rv = errno;
|
rv = errno;
|
||||||
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
|
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
|
||||||
rv, pkgname, version,
|
rv, pkgname, version,
|
||||||
"%s: [remove] failed to chdir to rootdir `%s': %s",
|
"%s: [remove] failed to chdir to rootdir `%s': %s",
|
||||||
pkgver, xhp->rootdir, strerror(rv));
|
pkgver, xhp->rootdir, strerror(rv));
|
||||||
free(buf);
|
goto out;
|
||||||
free(pkgver);
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
/* If package was "half-removed", remove it fully. */
|
||||||
|
if (state == XBPS_PKG_STATE_HALF_REMOVED)
|
||||||
|
goto purge;
|
||||||
/*
|
/*
|
||||||
* Run the pre remove action.
|
* Run the pre remove action.
|
||||||
*/
|
*/
|
||||||
@ -246,18 +302,15 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
|||||||
"%s: [remove] REMOVE script failed to "
|
"%s: [remove] REMOVE script failed to "
|
||||||
"execute pre ACTION: %s",
|
"execute pre ACTION: %s",
|
||||||
pkgver, strerror(errno));
|
pkgver, strerror(errno));
|
||||||
free(pkgver);
|
rv = errno;
|
||||||
free(buf);
|
goto out;
|
||||||
return errno;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (errno != ENOENT) {
|
if (errno != ENOENT) {
|
||||||
free(pkgver);
|
rv = errno;
|
||||||
free(buf);
|
goto out;
|
||||||
return errno;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If updating a package, we just need to execute the current
|
* If updating a package, we just need to execute the current
|
||||||
* pre-remove action target, unregister its requiredby entries and
|
* pre-remove action target, unregister its requiredby entries and
|
||||||
@ -269,38 +322,26 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
|||||||
return xbps_requiredby_pkg_remove(pkgname);
|
return xbps_requiredby_pkg_remove(pkgname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
pkgd = xbps_dictionary_from_metadata_plist(pkgname, XBPS_PKGFILES);
|
||||||
* Remove links, files and dirs.
|
if (pkgd == NULL) {
|
||||||
*/
|
rv = errno;
|
||||||
dict = xbps_dictionary_from_metadata_plist(pkgname, XBPS_PKGFILES);
|
goto out;
|
||||||
if (dict == NULL) {
|
|
||||||
free(pkgver);
|
|
||||||
free(buf);
|
|
||||||
return errno;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove links */
|
/* Remove links */
|
||||||
if ((rv = xbps_remove_pkg_files(dict, "links", pkgver)) != 0) {
|
if ((rv = xbps_remove_pkg_files(pkgd, "links", pkgver)) != 0)
|
||||||
prop_object_release(dict);
|
goto out;
|
||||||
free(buf);
|
|
||||||
free(pkgver);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Remove regular files */
|
/* Remove regular files */
|
||||||
if ((rv = xbps_remove_pkg_files(dict, "files", pkgver)) != 0) {
|
if ((rv = xbps_remove_pkg_files(pkgd, "files", pkgver)) != 0)
|
||||||
prop_object_release(dict);
|
goto out;
|
||||||
free(buf);
|
|
||||||
free(pkgver);
|
/* Remove configuration files */
|
||||||
return rv;
|
if ((rv = xbps_remove_pkg_files(pkgd, "conf_files", pkgver)) != 0)
|
||||||
}
|
goto out;
|
||||||
|
|
||||||
/* Remove dirs */
|
/* Remove dirs */
|
||||||
if ((rv = xbps_remove_pkg_files(dict, "dirs", pkgver)) != 0) {
|
if ((rv = xbps_remove_pkg_files(pkgd, "dirs", pkgver)) != 0)
|
||||||
prop_object_release(dict);
|
goto out;
|
||||||
free(buf);
|
|
||||||
free(pkgver);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
prop_object_release(dict);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute the post REMOVE action if file exists and we aren't
|
* Execute the post REMOVE action if file exists and we aren't
|
||||||
@ -313,12 +354,9 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
|||||||
errno, pkgname, version,
|
errno, pkgname, version,
|
||||||
"%s: [remove] REMOVE script failed to execute "
|
"%s: [remove] REMOVE script failed to execute "
|
||||||
"post ACTION: %s", pkgver, strerror(errno));
|
"post ACTION: %s", pkgver, strerror(errno));
|
||||||
free(buf);
|
rv = errno;
|
||||||
free(pkgver);
|
goto out;
|
||||||
return errno;
|
|
||||||
}
|
}
|
||||||
free(buf);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the requiredby array of all required dependencies.
|
* Update the requiredby array of all required dependencies.
|
||||||
*/
|
*/
|
||||||
@ -327,25 +365,64 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
|||||||
rv, pkgname, version,
|
rv, pkgname, version,
|
||||||
"%s: [remove] failed to remove requiredby entries: %s",
|
"%s: [remove] failed to remove requiredby entries: %s",
|
||||||
pkgver, strerror(rv));
|
pkgver, strerror(rv));
|
||||||
free(pkgver);
|
goto out;
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set package state to "config-files".
|
* Set package state to "half-removed".
|
||||||
*/
|
*/
|
||||||
rv = xbps_set_pkg_state_installed(pkgname, version, pkgver,
|
rv = xbps_set_pkg_state_installed(pkgname, version, pkgver,
|
||||||
XBPS_PKG_STATE_CONFIG_FILES);
|
XBPS_PKG_STATE_HALF_REMOVED);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
|
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
|
||||||
rv, pkgname, version,
|
rv, pkgname, version,
|
||||||
"%s: [remove] failed to set state to config-files: %s",
|
"%s: [remove] failed to set state to half-removed: %s",
|
||||||
pkgver, strerror(rv));
|
pkgver, strerror(rv));
|
||||||
} else {
|
goto out;
|
||||||
xbps_set_cb_state(XBPS_STATE_REMOVE_DONE,
|
|
||||||
0, pkgname, version, NULL);
|
|
||||||
}
|
}
|
||||||
free(pkgver);
|
|
||||||
|
purge:
|
||||||
|
/*
|
||||||
|
* Execute the purge REMOVE action if file exists.
|
||||||
|
*/
|
||||||
|
if (access(buf, X_OK) == 0) {
|
||||||
|
if (xbps_file_exec(buf, "purge", pkgname, version, "no",
|
||||||
|
xhp->conffile, NULL) != 0) {
|
||||||
|
rv = errno;
|
||||||
|
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
|
||||||
|
errno, pkgname, version,
|
||||||
|
"%s: REMOVE script failed to execute "
|
||||||
|
"purge ACTION: %s", pkgver, strerror(errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Remove package metadata directory.
|
||||||
|
*/
|
||||||
|
rv = remove_pkg_metadata(pkgname, version, pkgver, xhp->rootdir);
|
||||||
|
if (rv != 0) {
|
||||||
|
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
|
||||||
|
rv, pkgname, version,
|
||||||
|
"%s: failed to remove metadata files: %s",
|
||||||
|
pkgver, strerror(rv));
|
||||||
|
if (rv != ENOENT)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Unregister package from regpkgdb.
|
||||||
|
*/
|
||||||
|
if ((rv = xbps_unregister_pkg(pkgname, version)) != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
xbps_set_cb_state(XBPS_STATE_REMOVE_DONE,
|
||||||
|
0, pkgname, version, NULL);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (buf != NULL)
|
||||||
|
free(buf);
|
||||||
|
if (pkgver != NULL)
|
||||||
|
free(pkgver);
|
||||||
|
if (pkgd != NULL)
|
||||||
|
prop_object_release(pkgd);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -91,9 +91,10 @@ remove_pkg_from_reqby(prop_object_t obj, void *arg, bool *loop_done)
|
|||||||
if (reqby == NULL || prop_array_count(reqby) == 0)
|
if (reqby == NULL || prop_array_count(reqby) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (xbps_match_pkgname_in_array(reqby, pkgname))
|
if (xbps_match_pkgname_in_array(reqby, pkgname)) {
|
||||||
if (!xbps_remove_pkgname_from_array(reqby, pkgname))
|
if (!xbps_remove_pkgname_from_array(reqby, pkgname))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -101,46 +102,12 @@ remove_pkg_from_reqby(prop_object_t obj, void *arg, bool *loop_done)
|
|||||||
int HIDDEN
|
int HIDDEN
|
||||||
xbps_requiredby_pkg_remove(const char *pkgname)
|
xbps_requiredby_pkg_remove(const char *pkgname)
|
||||||
{
|
{
|
||||||
struct xbps_handle *xhp;
|
|
||||||
prop_dictionary_t dict;
|
|
||||||
char *plist;
|
|
||||||
int rv = 0;
|
|
||||||
|
|
||||||
assert(pkgname != NULL);
|
assert(pkgname != NULL);
|
||||||
|
return xbps_regpkgdb_foreach_pkg_cb(remove_pkg_from_reqby, __UNCONST(pkgname));
|
||||||
xhp = xbps_handle_get();
|
|
||||||
plist = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
|
||||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
|
||||||
if (plist == NULL)
|
|
||||||
return ENOMEM;
|
|
||||||
|
|
||||||
if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) {
|
|
||||||
free(plist);
|
|
||||||
xbps_dbg_printf("[reqby-rm] cannot internalize "
|
|
||||||
"regpkgdb plist for '%s': %s\n", pkgname, strerror(errno));
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = xbps_callback_array_iter_in_dict(dict, "packages",
|
|
||||||
remove_pkg_from_reqby, __UNCONST(pkgname));
|
|
||||||
if (rv != 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
|
|
||||||
xbps_dbg_printf("[reqby-rm] cannot externalize plist for "
|
|
||||||
"'%s': %s\n", pkgname, strerror(errno));
|
|
||||||
rv = errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
prop_object_release(dict);
|
|
||||||
free(plist);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int HIDDEN
|
int HIDDEN
|
||||||
xbps_requiredby_pkg_add(prop_array_t pkgs_array, prop_dictionary_t pkgd)
|
xbps_requiredby_pkg_add(struct xbps_handle *xhp, prop_dictionary_t pkgd)
|
||||||
{
|
{
|
||||||
prop_array_t pkg_rdeps;
|
prop_array_t pkg_rdeps;
|
||||||
prop_object_t obj, pkgd_regpkgdb;
|
prop_object_t obj, pkgd_regpkgdb;
|
||||||
@ -148,7 +115,6 @@ xbps_requiredby_pkg_add(prop_array_t pkgs_array, prop_dictionary_t pkgd)
|
|||||||
const char *pkgver, *str;
|
const char *pkgver, *str;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
assert(prop_object_type(pkgs_array) == PROP_TYPE_ARRAY);
|
|
||||||
assert(prop_object_type(pkgd) == PROP_TYPE_DICTIONARY);
|
assert(prop_object_type(pkgd) == PROP_TYPE_DICTIONARY);
|
||||||
|
|
||||||
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
|
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
|
||||||
@ -166,8 +132,8 @@ xbps_requiredby_pkg_add(prop_array_t pkgs_array, prop_dictionary_t pkgd)
|
|||||||
rv = EINVAL;
|
rv = EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pkgd_regpkgdb =
|
pkgd_regpkgdb = xbps_find_virtualpkg_in_dict_by_pattern(
|
||||||
xbps_find_virtualpkg_in_array_by_pattern(pkgs_array, str);
|
xhp->regpkgdb, "packages", str);
|
||||||
if (pkgd_regpkgdb == NULL)
|
if (pkgd_regpkgdb == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ static const struct state states[] = {
|
|||||||
{ "unpacked", XBPS_PKG_STATE_UNPACKED },
|
{ "unpacked", XBPS_PKG_STATE_UNPACKED },
|
||||||
{ "installed", XBPS_PKG_STATE_INSTALLED },
|
{ "installed", XBPS_PKG_STATE_INSTALLED },
|
||||||
{ "broken", XBPS_PKG_STATE_BROKEN },
|
{ "broken", XBPS_PKG_STATE_BROKEN },
|
||||||
{ "config-files", XBPS_PKG_STATE_CONFIG_FILES },
|
{ "half-removed", XBPS_PKG_STATE_HALF_REMOVED },
|
||||||
{ "not-installed", XBPS_PKG_STATE_NOT_INSTALLED },
|
{ "not-installed", XBPS_PKG_STATE_NOT_INSTALLED },
|
||||||
{ "half-unpacked", XBPS_PKG_STATE_HALF_UNPACKED },
|
{ "half-unpacked", XBPS_PKG_STATE_HALF_UNPACKED },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
@ -68,7 +68,7 @@ set_new_state(prop_dictionary_t dict, pkg_state_t state)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (stp->string == NULL)
|
if (stp->string == NULL)
|
||||||
return -1;
|
return EINVAL;
|
||||||
|
|
||||||
if (!prop_dictionary_set_cstring_nocopy(dict, "state", stp->string))
|
if (!prop_dictionary_set_cstring_nocopy(dict, "state", stp->string))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -110,7 +110,7 @@ xbps_pkg_state_installed(const char *pkgname, pkg_state_t *state)
|
|||||||
assert(pkgname != NULL);
|
assert(pkgname != NULL);
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
|
|
||||||
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
|
pkgd = xbps_regpkgdb_get_pkgd(pkgname, false);
|
||||||
if (pkgd == NULL)
|
if (pkgd == NULL)
|
||||||
return ENOENT;
|
return ENOENT;
|
||||||
|
|
||||||
@ -170,127 +170,80 @@ xbps_set_pkg_state_installed(const char *pkgname,
|
|||||||
pkg_state_t state)
|
pkg_state_t state)
|
||||||
{
|
{
|
||||||
struct xbps_handle *xhp;
|
struct xbps_handle *xhp;
|
||||||
prop_dictionary_t dict = NULL, pkgd;
|
prop_dictionary_t pkgd;
|
||||||
prop_array_t array;
|
prop_array_t array;
|
||||||
char *metadir, *plist;
|
|
||||||
int rv = 0;
|
|
||||||
bool newpkg = false;
|
bool newpkg = false;
|
||||||
|
int rv;
|
||||||
|
|
||||||
assert(pkgname != NULL);
|
assert(pkgname != NULL);
|
||||||
xhp = xbps_handle_get();
|
xhp = xbps_handle_get();
|
||||||
|
|
||||||
metadir = xbps_xasprintf("%s/%s", xhp->rootdir, XBPS_META_PATH);
|
if (xhp->regpkgdb == NULL) {
|
||||||
if (metadir == NULL)
|
xhp->regpkgdb = prop_dictionary_create();
|
||||||
return ENOMEM;
|
if (xhp->regpkgdb == NULL)
|
||||||
plist = xbps_xasprintf("%s/%s", metadir, XBPS_REGPKGDB);
|
return ENOMEM;
|
||||||
if (plist == NULL) {
|
|
||||||
free(metadir);
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) {
|
|
||||||
dict = prop_dictionary_create();
|
|
||||||
if (dict == NULL) {
|
|
||||||
rv = ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
array = prop_array_create();
|
array = prop_array_create();
|
||||||
if (array == NULL) {
|
if (array == NULL)
|
||||||
rv = ENOMEM;
|
return ENOMEM;
|
||||||
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);
|
||||||
goto out;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
if ((rv = set_pkg_objs(pkgd, pkgname, version, pkgver)) != 0) {
|
if ((rv = set_pkg_objs(pkgd, pkgname, version, pkgver)) != 0) {
|
||||||
prop_object_release(array);
|
prop_object_release(array);
|
||||||
prop_object_release(pkgd);
|
prop_object_release(pkgd);
|
||||||
goto out;
|
return rv;
|
||||||
}
|
}
|
||||||
if ((rv = set_new_state(pkgd, state)) != 0) {
|
if ((rv = set_new_state(pkgd, state)) != 0) {
|
||||||
prop_object_release(array);
|
prop_object_release(array);
|
||||||
prop_object_release(pkgd);
|
prop_object_release(pkgd);
|
||||||
goto out;
|
return rv;
|
||||||
}
|
}
|
||||||
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);
|
||||||
goto out;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
if (!xbps_add_obj_to_dict(dict, array, "packages")) {
|
if (!xbps_add_obj_to_dict(xhp->regpkgdb, array, "packages")) {
|
||||||
rv = EINVAL;
|
|
||||||
prop_object_release(array);
|
prop_object_release(array);
|
||||||
goto out;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
pkgd = xbps_find_pkg_in_dict_by_name(dict,
|
pkgd = xbps_regpkgdb_get_pkgd(pkgname, false);
|
||||||
"packages", pkgname);
|
|
||||||
if (pkgd == NULL) {
|
if (pkgd == NULL) {
|
||||||
if (errno && errno != ENOENT) {
|
|
||||||
rv = errno;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
newpkg = true;
|
newpkg = true;
|
||||||
pkgd = prop_dictionary_create();
|
pkgd = prop_dictionary_create();
|
||||||
if ((rv = set_pkg_objs(pkgd, pkgname,
|
if ((rv = set_pkg_objs(pkgd, pkgname,
|
||||||
version, pkgver)) != 0) {
|
version, pkgver)) != 0) {
|
||||||
prop_object_release(pkgd);
|
prop_object_release(pkgd);
|
||||||
goto out;
|
return rv;
|
||||||
}
|
|
||||||
}
|
|
||||||
array = prop_dictionary_get(dict, "packages");
|
|
||||||
if (array == NULL) {
|
|
||||||
array = prop_array_create();
|
|
||||||
if (!prop_dictionary_set(dict, "packages", array)) {
|
|
||||||
rv = EINVAL;
|
|
||||||
if (newpkg)
|
|
||||||
prop_object_release(pkgd);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((rv = set_new_state(pkgd, state)) != 0) {
|
if ((rv = set_new_state(pkgd, state)) != 0) {
|
||||||
if (newpkg)
|
if (newpkg)
|
||||||
prop_object_release(pkgd);
|
prop_object_release(pkgd);
|
||||||
goto out;
|
return rv;
|
||||||
}
|
}
|
||||||
if (newpkg && !xbps_add_obj_to_array(array, pkgd)) {
|
array = prop_dictionary_get(xhp->regpkgdb, "packages");
|
||||||
rv = EINVAL;
|
if (newpkg) {
|
||||||
prop_object_release(pkgd);
|
if (!xbps_add_obj_to_array(array, pkgd)) {
|
||||||
goto out;
|
prop_object_release(pkgd);
|
||||||
}
|
return EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
/* Create metadir if doesn't exist */
|
|
||||||
if (access(metadir, X_OK) == -1) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
if (xbps_mkpath(metadir, 0755) != 0) {
|
|
||||||
xbps_dbg_printf("[pkgstate] failed to create "
|
|
||||||
"metadir %s: %s\n", metadir,
|
|
||||||
strerror(errno));
|
|
||||||
rv = errno;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
}
|
if ((rv = xbps_array_replace_dict_by_name(array,
|
||||||
/* Externalize regpkgdb plist file */
|
pkgd, pkgname)) != 0)
|
||||||
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
|
return rv;
|
||||||
rv = errno;
|
|
||||||
xbps_dbg_printf("[pkgstate] cannot write plist '%s': %s\n",
|
|
||||||
plist, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
prop_object_release(pkgd);
|
||||||
if (prop_object_type(dict) == PROP_TYPE_DICTIONARY)
|
}
|
||||||
prop_object_release(dict);
|
if (!prop_dictionary_set(xhp->regpkgdb, "packages", array))
|
||||||
if (metadir)
|
return EINVAL;
|
||||||
free(metadir);
|
}
|
||||||
if (plist)
|
|
||||||
free(plist);
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,16 @@ unpack_archive(prop_dictionary_t pkg_repod, struct archive *ar)
|
|||||||
xucd->entry_extract_count = 0;
|
xucd->entry_extract_count = 0;
|
||||||
xucd->entry_total_count = 0;
|
xucd->entry_total_count = 0;
|
||||||
}
|
}
|
||||||
|
if (access(xhp->rootdir, R_OK) == -1) {
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
rv = errno;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (xbps_mkpath(xhp->rootdir, 0750) == -1) {
|
||||||
|
rv = errno;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (chdir(xhp->rootdir) == -1) {
|
if (chdir(xhp->rootdir) == -1) {
|
||||||
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
|
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
|
||||||
errno, pkgname, version,
|
errno, pkgname, version,
|
||||||
|
@ -231,7 +231,7 @@ xbps_dictionary_from_metadata_plist(const char *pkgname,
|
|||||||
|
|
||||||
if (access(plistf, R_OK) == -1) {
|
if (access(plistf, R_OK) == -1) {
|
||||||
pkgd = xbps_find_virtualpkg_dict_installed(pkgname, false);
|
pkgd = xbps_find_virtualpkg_dict_installed(pkgname, false);
|
||||||
if (pkgd) {
|
if (prop_object_type(pkgd) == PROP_TYPE_DICTIONARY) {
|
||||||
free(plistf);
|
free(plistf);
|
||||||
prop_dictionary_get_cstring_nocopy(pkgd,
|
prop_dictionary_get_cstring_nocopy(pkgd,
|
||||||
"pkgname", &savedpkgname);
|
"pkgname", &savedpkgname);
|
||||||
|
@ -336,15 +336,15 @@ find_pkgd_installed(const char *str, bool bypattern, bool virtual)
|
|||||||
|
|
||||||
/* try normal pkg */
|
/* try normal pkg */
|
||||||
if (virtual == false) {
|
if (virtual == false) {
|
||||||
pkgd = find_pkg_in_dict(xhp->regpkgdb_dictionary,
|
pkgd = find_pkg_in_dict(xhp->regpkgdb,
|
||||||
"packages", str, bypattern, false);
|
"packages", str, bypattern, false);
|
||||||
} else {
|
} else {
|
||||||
/* virtual pkg set by user in conf */
|
/* virtual pkg set by user in conf */
|
||||||
pkgd = find_virtualpkg_user_in_dict(xhp->regpkgdb_dictionary,
|
pkgd = find_virtualpkg_user_in_dict(xhp->regpkgdb,
|
||||||
"packages", str, bypattern);
|
"packages", str, bypattern);
|
||||||
if (pkgd == NULL) {
|
if (pkgd == NULL) {
|
||||||
/* any virtual pkg in dictionary matching pattern */
|
/* any virtual pkg in dictionary matching pattern */
|
||||||
pkgd = find_pkg_in_dict(xhp->regpkgdb_dictionary,
|
pkgd = find_pkg_in_dict(xhp->regpkgdb,
|
||||||
"packages", str, bypattern, true);
|
"packages", str, bypattern, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,16 +42,20 @@
|
|||||||
static bool
|
static bool
|
||||||
remove_string_from_array(prop_array_t array, const char *str, int mode)
|
remove_string_from_array(prop_array_t array, const char *str, int mode)
|
||||||
{
|
{
|
||||||
|
prop_object_iterator_t iter;
|
||||||
prop_object_t obj;
|
prop_object_t obj;
|
||||||
const char *curname, *pkgdep;
|
const char *curname, *pkgdep;
|
||||||
char *curpkgname;
|
char *curpkgname;
|
||||||
size_t i, idx = 0;
|
size_t idx = 0;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
assert(prop_object_type(array) == PROP_TYPE_ARRAY);
|
assert(prop_object_type(array) == PROP_TYPE_ARRAY);
|
||||||
|
|
||||||
for (i = 0; i < prop_array_count(array); i++) {
|
iter = prop_array_iterator(array);
|
||||||
obj = prop_array_get(array, i);
|
if (iter == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while ((obj = prop_object_iterator_next(iter))) {
|
||||||
if (mode == 0) {
|
if (mode == 0) {
|
||||||
/* exact match, obj is a string */
|
/* exact match, obj is a string */
|
||||||
if (prop_string_equals_cstring(obj, str)) {
|
if (prop_string_equals_cstring(obj, str)) {
|
||||||
@ -81,8 +85,12 @@ remove_string_from_array(prop_array_t array, const char *str, int mode)
|
|||||||
}
|
}
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
if (!found)
|
prop_object_iterator_release(iter);
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
errno = ENOENT;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
prop_array_remove(array, idx);
|
prop_array_remove(array, idx);
|
||||||
return true;
|
return true;
|
||||||
@ -121,7 +129,10 @@ xbps_remove_pkg_from_dict_by_name(prop_dictionary_t dict,
|
|||||||
if (array == NULL)
|
if (array == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return xbps_remove_pkg_from_array_by_name(array, pkgname);
|
if (!xbps_remove_pkg_from_array_by_name(array, pkgname))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return prop_dictionary_set(dict, key, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -56,45 +56,94 @@
|
|||||||
* dictionary.
|
* dictionary.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool regpkgdb_initialized;
|
|
||||||
|
|
||||||
int HIDDEN
|
int HIDDEN
|
||||||
xbps_regpkgdb_dictionary_init(struct xbps_handle *xhp)
|
xbps_regpkgdb_dictionary_init(struct xbps_handle *xhp)
|
||||||
{
|
{
|
||||||
char *plist;
|
int rv;
|
||||||
|
|
||||||
if (regpkgdb_initialized)
|
assert(xhp != NULL);
|
||||||
|
|
||||||
|
if (xhp->regpkgdb != NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
rv = xbps_regpkgdb_update(xhp, false);
|
||||||
|
if (rv != 0) {
|
||||||
|
if (rv != ENOENT)
|
||||||
|
xbps_dbg_printf("[regpkgdb] cannot internalize "
|
||||||
|
"regpkgdb dictionary: %s\n", strerror(rv));
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
xbps_dbg_printf("[regpkgdb] initialized ok.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xbps_regpkgdb_update(struct xbps_handle *xhp, bool flush)
|
||||||
|
{
|
||||||
|
char *plist, *metadir;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
plist = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
plist = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
||||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
XBPS_META_PATH, XBPS_REGPKGDB);
|
||||||
if (plist == NULL)
|
if (plist == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
xhp->regpkgdb_dictionary =
|
if (xhp->regpkgdb != NULL && flush) {
|
||||||
prop_dictionary_internalize_from_zfile(plist);
|
metadir = xbps_xasprintf("%s/%s", xhp->rootdir,
|
||||||
if (xhp->regpkgdb_dictionary == NULL) {
|
XBPS_META_PATH);
|
||||||
free(plist);
|
if (metadir == NULL) {
|
||||||
if (errno != ENOENT)
|
free(plist);
|
||||||
xbps_dbg_printf("[regpkgdb] cannot internalize "
|
return ENOMEM;
|
||||||
"regpkgdb dictionary: %s\n", strerror(errno));
|
}
|
||||||
return errno;
|
/* Create metadir if doesn't exist */
|
||||||
|
if (access(metadir, X_OK) == -1) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
if (xbps_mkpath(metadir, 0755) != 0) {
|
||||||
|
xbps_dbg_printf("[regpkgdb] failed to "
|
||||||
|
"create metadir %s: %s\n", metadir,
|
||||||
|
strerror(errno));
|
||||||
|
rv = errno;
|
||||||
|
free(metadir);
|
||||||
|
free(plist);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
free(plist);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(metadir);
|
||||||
|
/* flush dictionary to storage */
|
||||||
|
if (!prop_dictionary_externalize_to_zfile(xhp->regpkgdb,
|
||||||
|
plist)) {
|
||||||
|
free(plist);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
prop_object_release(xhp->regpkgdb);
|
||||||
|
xhp->regpkgdb = NULL;
|
||||||
}
|
}
|
||||||
free(plist);
|
/* update copy in memory */
|
||||||
regpkgdb_initialized = true;
|
xhp->regpkgdb = prop_dictionary_internalize_from_zfile(plist);
|
||||||
xbps_dbg_printf("[regpkgdb] initialized ok.\n");
|
if (xhp->regpkgdb == NULL)
|
||||||
|
rv = errno;
|
||||||
|
|
||||||
return 0;
|
free(plist);
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDDEN
|
void HIDDEN
|
||||||
xbps_regpkgdb_dictionary_release(struct xbps_handle *xhp)
|
xbps_regpkgdb_dictionary_release(struct xbps_handle *xhp)
|
||||||
{
|
{
|
||||||
if (!regpkgdb_initialized)
|
assert(xhp != NULL);
|
||||||
|
|
||||||
|
if (xhp->regpkgdb == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
prop_object_release(xhp->regpkgdb_dictionary);
|
prop_object_release(xhp->regpkgdb);
|
||||||
regpkgdb_initialized = false;
|
xhp->regpkgdb = NULL;
|
||||||
xbps_dbg_printf("[regpkgdb] released ok.\n");
|
xbps_dbg_printf("[regpkgdb] released ok.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,36 +152,19 @@ foreach_pkg_cb(int (*fn)(prop_object_t, void *, bool *),
|
|||||||
void *arg,
|
void *arg,
|
||||||
bool reverse)
|
bool reverse)
|
||||||
{
|
{
|
||||||
prop_array_t array;
|
|
||||||
prop_object_t obj;
|
|
||||||
struct xbps_handle *xhp = xbps_handle_get();
|
struct xbps_handle *xhp = xbps_handle_get();
|
||||||
size_t i, cnt;
|
|
||||||
int rv;
|
int rv;
|
||||||
bool done = false;
|
|
||||||
|
|
||||||
/* initialize regpkgdb */
|
/* initialize regpkgdb */
|
||||||
if ((rv = xbps_regpkgdb_dictionary_init(xhp)) != 0)
|
if ((rv = xbps_regpkgdb_dictionary_init(xhp)) != 0)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
array = prop_dictionary_get(xhp->regpkgdb_dictionary, "packages");
|
|
||||||
if (prop_object_type(array) != PROP_TYPE_ARRAY)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
cnt = prop_array_count(array);
|
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
while (cnt--) {
|
rv = xbps_callback_array_iter_reverse_in_dict(
|
||||||
obj = prop_array_get(array, cnt);
|
xhp->regpkgdb, "packages", fn, arg);
|
||||||
rv = (*fn)(obj, arg, &done);
|
|
||||||
if (rv != 0 || done)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < cnt; i++) {
|
rv = xbps_callback_array_iter_in_dict(
|
||||||
obj = prop_array_get(array, i);
|
xhp->regpkgdb, "packages", fn, arg);
|
||||||
rv = (*fn)(obj, arg, &done);
|
|
||||||
if (rv != 0 || done)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -150,3 +182,22 @@ xbps_regpkgdb_foreach_pkg_cb(int (*fn)(prop_object_t, void *, bool *),
|
|||||||
{
|
{
|
||||||
return foreach_pkg_cb(fn, arg, false);
|
return foreach_pkg_cb(fn, arg, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prop_dictionary_t
|
||||||
|
xbps_regpkgdb_get_pkgd(const char *pkg, bool bypattern)
|
||||||
|
{
|
||||||
|
struct xbps_handle *xhp = xbps_handle_get();
|
||||||
|
prop_dictionary_t pkgd = NULL;
|
||||||
|
|
||||||
|
if (xbps_regpkgdb_dictionary_init(xhp) != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (bypattern)
|
||||||
|
pkgd = xbps_find_pkg_in_dict_by_pattern(xhp->regpkgdb,
|
||||||
|
"packages", pkg);
|
||||||
|
else
|
||||||
|
pkgd = xbps_find_pkg_in_dict_by_name(xhp->regpkgdb,
|
||||||
|
"packages", pkg);
|
||||||
|
|
||||||
|
return prop_dictionary_copy(pkgd);
|
||||||
|
}
|
||||||
|
@ -164,13 +164,14 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
|||||||
struct xbps_handle *xhp;
|
struct xbps_handle *xhp;
|
||||||
prop_object_t obj;
|
prop_object_t obj;
|
||||||
prop_object_iterator_t iter;
|
prop_object_iterator_t iter;
|
||||||
|
size_t i;
|
||||||
const char *pkgname, *version, *pkgver, *tract;
|
const char *pkgname, *version, *pkgver, *tract;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
bool update, install, purge;
|
bool update, install;
|
||||||
|
|
||||||
assert(prop_object_type(transd) == PROP_TYPE_DICTIONARY);
|
assert(prop_object_type(transd) == PROP_TYPE_DICTIONARY);
|
||||||
|
|
||||||
update = install = purge = false;
|
update = install = false;
|
||||||
xhp = xbps_handle_get();
|
xhp = xbps_handle_get();
|
||||||
iter = xbps_array_iter_from_dict(transd, "packages");
|
iter = xbps_array_iter_from_dict(transd, "packages");
|
||||||
if (iter == NULL)
|
if (iter == NULL)
|
||||||
@ -193,7 +194,16 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
|||||||
*/
|
*/
|
||||||
xbps_set_cb_state(XBPS_STATE_TRANS_RUN, 0, NULL, NULL, NULL);
|
xbps_set_cb_state(XBPS_STATE_TRANS_RUN, 0, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||||
|
if ((xhp->transaction_frequency_flush > 0) &&
|
||||||
|
(++i >= xhp->transaction_frequency_flush)) {
|
||||||
|
rv = xbps_regpkgdb_update(xhp, true);
|
||||||
|
if (rv != 0 && rv != ENOENT)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
update = false;
|
update = false;
|
||||||
prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
|
prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
|
||||||
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
||||||
@ -201,22 +211,15 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
|||||||
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
|
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
|
||||||
|
|
||||||
if (strcmp(tract, "remove") == 0) {
|
if (strcmp(tract, "remove") == 0) {
|
||||||
purge = update = false;
|
update = false;
|
||||||
/*
|
/*
|
||||||
* Remove and optionally also purge package.
|
* Remove package.
|
||||||
*/
|
*/
|
||||||
prop_dictionary_get_bool(obj, "remove-and-update",
|
prop_dictionary_get_bool(obj, "remove-and-update",
|
||||||
&update);
|
&update);
|
||||||
prop_dictionary_get_bool(obj, "remove-and-purge",
|
|
||||||
&purge);
|
|
||||||
rv = xbps_remove_pkg(pkgname, version, update);
|
rv = xbps_remove_pkg(pkgname, version, update);
|
||||||
if (rv != 0)
|
if (rv != 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (update || !purge)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((rv = xbps_purge_pkg(pkgname, false)) != 0)
|
|
||||||
goto out;
|
|
||||||
} else if (strcmp(tract, "configure") == 0) {
|
} else if (strcmp(tract, "configure") == 0) {
|
||||||
/*
|
/*
|
||||||
* Reconfigure pending package.
|
* Reconfigure pending package.
|
||||||
@ -269,6 +272,10 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
|||||||
}
|
}
|
||||||
prop_object_iterator_reset(iter);
|
prop_object_iterator_reset(iter);
|
||||||
|
|
||||||
|
/* force a flush now packages were removed/unpacked */
|
||||||
|
if ((rv = xbps_regpkgdb_update(xhp, true)) != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/* if there are no packages to install or update we are done */
|
/* if there are no packages to install or update we are done */
|
||||||
if (!update && !install)
|
if (!update && !install)
|
||||||
goto out;
|
goto out;
|
||||||
@ -277,11 +284,21 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
|||||||
*/
|
*/
|
||||||
xbps_set_cb_state(XBPS_STATE_TRANS_CONFIGURE, 0, NULL, NULL, NULL);
|
xbps_set_cb_state(XBPS_STATE_TRANS_CONFIGURE, 0, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||||
|
if (xhp->transaction_frequency_flush > 0 &&
|
||||||
|
++i >= xhp->transaction_frequency_flush) {
|
||||||
|
if ((rv = xbps_regpkgdb_update(xhp, true)) != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
|
prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
|
||||||
if ((strcmp(tract, "remove") == 0) ||
|
if ((strcmp(tract, "remove") == 0) ||
|
||||||
(strcmp(tract, "configure") == 0))
|
(strcmp(tract, "configure") == 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
||||||
prop_dictionary_get_cstring_nocopy(obj, "version", &version);
|
prop_dictionary_get_cstring_nocopy(obj, "version", &version);
|
||||||
update = false;
|
update = false;
|
||||||
@ -304,6 +321,8 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Force a flush now that packages are configured */
|
||||||
|
rv = xbps_regpkgdb_update(xhp, true);
|
||||||
out:
|
out:
|
||||||
prop_object_iterator_release(iter);
|
prop_object_iterator_release(iter);
|
||||||
|
|
||||||
|
@ -178,6 +178,8 @@ compute_transaction_stats(void)
|
|||||||
pkg_metad =
|
pkg_metad =
|
||||||
xbps_dictionary_from_metadata_plist(pkgname,
|
xbps_dictionary_from_metadata_plist(pkgname,
|
||||||
XBPS_PKGPROPS);
|
XBPS_PKGPROPS);
|
||||||
|
if (pkg_metad == NULL)
|
||||||
|
continue;
|
||||||
prop_dictionary_get_uint64(pkg_metad,
|
prop_dictionary_get_uint64(pkg_metad,
|
||||||
"installed_size", &tsize);
|
"installed_size", &tsize);
|
||||||
prop_object_release(pkg_metad);
|
prop_object_release(pkg_metad);
|
||||||
|
@ -227,7 +227,7 @@ xbps_transaction_install_pkg(const char *pkgpattern)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xbps_transaction_remove_pkg(const char *pkgname, bool purge, bool recursive)
|
xbps_transaction_remove_pkg(const char *pkgname, bool recursive)
|
||||||
{
|
{
|
||||||
prop_dictionary_t transd, pkgd;
|
prop_dictionary_t transd, pkgd;
|
||||||
prop_array_t mdeps, orphans, orphans_pkg, unsorted, reqby;
|
prop_array_t mdeps, orphans, orphans_pkg, unsorted, reqby;
|
||||||
@ -238,11 +238,9 @@ xbps_transaction_remove_pkg(const char *pkgname, bool purge, bool recursive)
|
|||||||
|
|
||||||
assert(pkgname != NULL);
|
assert(pkgname != NULL);
|
||||||
|
|
||||||
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
|
if ((pkgd = xbps_regpkgdb_get_pkgd(pkgname, false)) == NULL) {
|
||||||
if (prop_object_type(pkgd) != PROP_TYPE_DICTIONARY) {
|
|
||||||
/* pkg not installed */
|
/* pkg not installed */
|
||||||
rv = ENOENT;
|
return ENOENT;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Prepare transaction dictionary and missing deps array.
|
* Prepare transaction dictionary and missing deps array.
|
||||||
@ -267,6 +265,7 @@ xbps_transaction_remove_pkg(const char *pkgname, bool purge, bool recursive)
|
|||||||
rv = ENOMEM;
|
rv = ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
prop_array_set_cstring_nocopy(orphans_pkg, 0, pkgname);
|
prop_array_set_cstring_nocopy(orphans_pkg, 0, pkgname);
|
||||||
orphans = xbps_find_pkg_orphans(orphans_pkg);
|
orphans = xbps_find_pkg_orphans(orphans_pkg);
|
||||||
prop_object_release(orphans_pkg);
|
prop_object_release(orphans_pkg);
|
||||||
@ -274,13 +273,12 @@ xbps_transaction_remove_pkg(const char *pkgname, bool purge, bool recursive)
|
|||||||
rv = EINVAL;
|
rv = EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = prop_array_count(orphans);
|
count = prop_array_count(orphans);
|
||||||
while (count--) {
|
while (count--) {
|
||||||
obj = prop_array_get(orphans, count);
|
obj = prop_array_get(orphans, count);
|
||||||
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
|
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
|
||||||
prop_dictionary_set_cstring_nocopy(obj, "transaction", "remove");
|
prop_dictionary_set_cstring_nocopy(obj, "transaction", "remove");
|
||||||
if (purge)
|
|
||||||
prop_dictionary_set_bool(obj, "remove-and-purge", true);
|
|
||||||
prop_array_add(unsorted, obj);
|
prop_array_add(unsorted, obj);
|
||||||
xbps_dbg_printf("%s: added into transaction (remove).\n", pkgver);
|
xbps_dbg_printf("%s: added into transaction (remove).\n", pkgver);
|
||||||
}
|
}
|
||||||
@ -291,8 +289,6 @@ rmpkg:
|
|||||||
*/
|
*/
|
||||||
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
|
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
|
||||||
prop_dictionary_set_cstring_nocopy(pkgd, "transaction", "remove");
|
prop_dictionary_set_cstring_nocopy(pkgd, "transaction", "remove");
|
||||||
if (purge)
|
|
||||||
prop_dictionary_set_bool(pkgd, "remove-and-purge", true);
|
|
||||||
prop_array_add(unsorted, pkgd);
|
prop_array_add(unsorted, pkgd);
|
||||||
xbps_dbg_printf("%s: added into transaction (remove).\n", pkgver);
|
xbps_dbg_printf("%s: added into transaction (remove).\n", pkgver);
|
||||||
reqby = prop_dictionary_get(pkgd, "requiredby");
|
reqby = prop_dictionary_get(pkgd, "requiredby");
|
||||||
@ -303,15 +299,15 @@ rmpkg:
|
|||||||
if ((prop_object_type(reqby) == PROP_TYPE_ARRAY) &&
|
if ((prop_object_type(reqby) == PROP_TYPE_ARRAY) &&
|
||||||
(prop_array_count(reqby) > 0))
|
(prop_array_count(reqby) > 0))
|
||||||
rv = EEXIST;
|
rv = EEXIST;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (prop_object_type(pkgd) == PROP_TYPE_DICTIONARY)
|
prop_object_release(pkgd);
|
||||||
prop_object_release(pkgd);
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xbps_transaction_autoremove_pkgs(bool purge)
|
xbps_transaction_autoremove_pkgs(void)
|
||||||
{
|
{
|
||||||
prop_dictionary_t transd;
|
prop_dictionary_t transd;
|
||||||
prop_array_t orphans, mdeps, unsorted;
|
prop_array_t orphans, mdeps, unsorted;
|
||||||
@ -350,8 +346,6 @@ xbps_transaction_autoremove_pkgs(bool purge)
|
|||||||
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
|
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
|
||||||
prop_dictionary_set_cstring_nocopy(obj,
|
prop_dictionary_set_cstring_nocopy(obj,
|
||||||
"transaction", "remove");
|
"transaction", "remove");
|
||||||
if (purge)
|
|
||||||
prop_dictionary_set_bool(obj, "remove-and-purge", true);
|
|
||||||
prop_array_add(unsorted, obj);
|
prop_array_add(unsorted, obj);
|
||||||
xbps_dbg_printf("%s: added into transaction (remove).\n",
|
xbps_dbg_printf("%s: added into transaction (remove).\n",
|
||||||
pkgver);
|
pkgver);
|
||||||
|
@ -121,8 +121,7 @@ xbps_transaction_package_replace(prop_dictionary_t transd)
|
|||||||
* If new package is providing a virtual package to the
|
* If new package is providing a virtual package to the
|
||||||
* package that we want to replace we should respect
|
* package that we want to replace we should respect
|
||||||
* its requiredby and automatic-install objects, so copy
|
* its requiredby and automatic-install objects, so copy
|
||||||
* them to the pkg's dictionary in transaction. Also
|
* them to the pkg's dictionary in transaction.
|
||||||
* make sure that replaced package is also purged.
|
|
||||||
*/
|
*/
|
||||||
if (xbps_match_virtual_pkg_in_dict(pkg_repod,
|
if (xbps_match_virtual_pkg_in_dict(pkg_repod,
|
||||||
pattern, true) ||
|
pattern, true) ||
|
||||||
@ -135,8 +134,6 @@ xbps_transaction_package_replace(prop_dictionary_t transd)
|
|||||||
}
|
}
|
||||||
prop_dictionary_set_bool(pkg_repod,
|
prop_dictionary_set_bool(pkg_repod,
|
||||||
"automatic-install", instd_auto);
|
"automatic-install", instd_auto);
|
||||||
prop_dictionary_set_bool(instd,
|
|
||||||
"remove-and-purge", true);
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Add package dictionary into the transaction and mark
|
* Add package dictionary into the transaction and mark
|
||||||
|
Reference in New Issue
Block a user