New utilities: xbps-{install,pkgdb,query,reconfigure,rindex} (WIP).

This commit is contained in:
Juan RP 2012-11-02 15:04:25 +01:00
parent 7fa8207cf3
commit b05ce9fe57
40 changed files with 5188 additions and 5 deletions

10
.gitignore vendored
View File

@ -4,9 +4,15 @@ config.h
config.mk
bin/xbps-bin/xbps-bin
bin/xbps-repo/xbps-repo
bin/xbps-uhelper/xbps-uhelper
bin/xbps-dgraph/xbps-dgraph
bin/xbps-create/xbps-create
bin/xbps-dgraph/xbps-dgraph
bin/xbps-install/xbps-install
bin/xbps-pkgdb/xbps-pkgdb
bin/xbps-query/xbps-query
bin/xbps-reconfigure/xbps-reconfigure
bin/xbps-remove/xbps-remove
bin/xbps-rindex/xbps-rindex
bin/xbps-uhelper/xbps-uhelper
*.static
*.so*
*.o

View File

@ -1,9 +1,16 @@
-include ../config.mk
SUBDIRS = xbps-bin
SUBDIRS += xbps-bin
SUBDIRS += xbps-repo
SUBDIRS += xbps-dgraph
SUBDIRS += xbps-uhelper
SUBDIRS += xbps-create
SUBDIRS += xbps-dgraph
SUBDIRS += xbps-install
SUBDIRS += xbps-pkgdb
SUBDIRS += xbps-query
SUBDIRS += xbps-reconfigure
SUBDIRS += xbps-remove
SUBDIRS += xbps-rindex
SUBDIRS += xbps-uhelper
include ../mk/subdir.mk

View File

@ -0,0 +1,9 @@
TOPDIR = ../..
-include $(TOPDIR)/config.mk
BIN = xbps-install
OBJS = main.o transaction.o main.o question.o fetch_cb.o state_cb.o
OBJS += unpack_cb.o util.o
#MAN = $(BIN).8
include $(TOPDIR)/mk/prog.mk

69
bin/xbps-install/defs.h Normal file
View File

@ -0,0 +1,69 @@
/*-
* Copyright (c) 2009-2012 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.
*/
#ifndef _XBPS_INSTALL_DEFS_H_
#define _XBPS_INSTALL_DEFS_H_
#include <sys/time.h>
#include <xbps_api.h>
struct xferstat {
struct timeval start;
struct timeval last;
};
/* from transaction.c */
int install_new_pkg(struct xbps_handle *, const char *, bool);
int update_pkg(struct xbps_handle *, const char *);
int dist_upgrade(struct xbps_handle *, size_t, bool, bool);
int exec_transaction(struct xbps_handle *, size_t, bool, bool);
/* from question.c */
bool yesno(const char *, ...);
bool noyes(const char *, ...);
/* from fetch_cb.c */
void fetch_file_progress_cb(struct xbps_handle *,
struct xbps_fetch_cb_data *,
void *);
/* from state_cb.c */
void state_cb(struct xbps_handle *,
struct xbps_state_cb_data *,
void *);
/* from unpack_cb.c */
void unpack_progress_cb_verbose(struct xbps_handle *,
struct xbps_unpack_cb_data *,
void *);
void unpack_progress_cb(struct xbps_handle *,
struct xbps_unpack_cb_data *,
void *);
/* From util.c */
void print_package_line(const char *, size_t, bool);
size_t get_maxcols(void);
#endif /* !_XBPS_INSTALL_DEFS_H_ */

176
bin/xbps-install/fetch_cb.c Normal file
View File

@ -0,0 +1,176 @@
/*-
* Copyright (c) 2009-2012 Juan Romero Pardines
* Copyright (c) 2000-2004 Dag-Erling Coïdan Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* 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.
*
* From FreeBSD fetch(8):
* $FreeBSD: src/usr.bin/fetch/fetch.c,v 1.84.2.1 2009/08/03 08:13:06 kensmith Exp $
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <xbps_api.h>
#include "defs.h"
#include "config.h"
static void
get_time(struct timeval *tvp)
{
#ifdef HAVE_CLOCK_GETTIME
struct timespec ts;
(void)clock_gettime(CLOCK_MONOTONIC, &ts);
tvp->tv_sec = ts.tv_sec;
tvp->tv_usec = ts.tv_nsec / 1000;
#else
(void)gettimeofday(tvp, NULL);
#endif
}
/*
* Compute and display ETA
*/
static const char *
stat_eta(struct xbps_fetch_cb_data *xfpd, void *cbdata)
{
struct xferstat *xfer = cbdata;
static char str[16];
long elapsed, eta;
off_t received, expected;
if (xfpd->file_size == -1)
return "unknown";
elapsed = xfer->last.tv_sec - xfer->start.tv_sec;
received = xfpd->file_dloaded - xfpd->file_offset;
expected = xfpd->file_size - xfpd->file_dloaded;
eta = (long)(elapsed * (long)expected / (long)received);
if (eta > 3600)
snprintf(str, sizeof str, "%02ldh%02ldm",
eta / 3600, (eta % 3600) / 60);
else
snprintf(str, sizeof str, "%02ldm%02lds",
eta / 60, eta % 60);
return str;
}
static inline bool
compare_double(const double a, const double b)
{
const double precision = 0.00001;
if ((a - precision) < b && (a + precision) > b)
return true;
else
return false;
}
/*
* Compute and display transfer rate
*/
static const char *
stat_bps(struct xbps_fetch_cb_data *xfpd, void *cbdata)
{
struct xferstat *xfer = cbdata;
static char str[16];
char size[8];
double delta, bps;
delta = (xfer->last.tv_sec + (xfer->last.tv_usec / 1.e6))
- (xfer->start.tv_sec + (xfer->start.tv_usec / 1.e6));
if (compare_double(delta, 0.0001)) {
snprintf(str, sizeof str, "-- stalled --");
} else {
bps =
((double)(xfpd->file_dloaded - xfpd->file_offset) / delta);
(void)xbps_humanize_number(size, (int64_t)bps);
snprintf(str, sizeof str, "%s/s", size);
}
return str;
}
/*
* Update the stats display
*/
static void
stat_display(struct xbps_fetch_cb_data *xfpd, void *cbdata)
{
struct xferstat *xfer = cbdata;
struct timeval now;
char totsize[8], recvsize[8];
int percentage;
get_time(&now);
if (now.tv_sec <= xfer->last.tv_sec)
return;
xfer->last = now;
if (xfpd->file_size == -1) {
percentage = 0;
snprintf(totsize, 3, "0B");
} else {
percentage = (int)((double)(100.0 *
(double)xfpd->file_dloaded) / (double)xfpd->file_size);
(void)xbps_humanize_number(totsize, (int64_t)xfpd->file_size);
}
(void)xbps_humanize_number(recvsize, (int64_t)xfpd->file_dloaded);
fprintf(stderr, "%s: %s [%d%% of %s] %s ETA: %s\033[K\r",
xfpd->file_name, recvsize, percentage, totsize,
stat_bps(xfpd, xfer), stat_eta(xfpd, xfer));
}
void
fetch_file_progress_cb(struct xbps_handle *xhp,
struct xbps_fetch_cb_data *xfpd,
void *cbdata)
{
struct xferstat *xfer = cbdata;
char size[8];
(void)xhp;
if (xfpd->cb_start) {
/* start transfer stats */
get_time(&xfer->start);
xfer->last.tv_sec = xfer->last.tv_usec = 0;
} else if (xfpd->cb_update) {
/* update transfer stats */
stat_display(xfpd, xfer);
} else if (xfpd->cb_end) {
/* end transfer stats */
(void)xbps_humanize_number(size, (int64_t)xfpd->file_dloaded);
fprintf(stderr,"Downloaded %s for %s [avg rate: %s]\033[K\n",
size, xfpd->file_name, stat_bps(xfpd, xfer));
}
}

242
bin/xbps-install/main.c Normal file
View File

@ -0,0 +1,242 @@
/*-
* Copyright (c) 2008-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include <unistd.h>
#include <getopt.h>
#include <xbps_api.h>
#include "defs.h"
static struct xbps_handle xh;
static void __attribute__((noreturn))
usage(bool fail)
{
fprintf(stdout,
"Usage: xbps-install [OPTIONS] [PKGNAME...]\n\n"
"OPTIONS\n"
" -A --automatic Set automatic installation mode\n"
" -C --config <file> Full path to configuration file\n"
" -c --cachedir <dir> Full path to cachedir\n"
" -d --debug Debug mode shown to stderr\n"
" -f --force Force package installation\n"
" -h --help Print help usage\n"
" -n --dry-run Dry-run mode\n"
" -p --print-format <fmt> Print format for dry-run mode\n"
" -R --repository <uri> Default repository to be used if config not set\n"
" -r --rootdir <dir> Full path to rootdir\n"
" -s --skip-sync Skip remote repository index sync\n"
" -u --update Update target package(s)\n"
" -v --verbose Verbose messages\n"
" -y --yes Assume yes to all questions\n"
" -V --version Show XBPS version\n");
exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
static void __attribute__((noreturn))
cleanup_sighandler(int signum)
{
xbps_end(&xh);
_exit(signum);
}
int
main(int argc, char **argv)
{
const char *shortopts = "AC:c:dfhnp:R:r:suVvy";
const struct option longopts[] = {
{ "automatic", no_argument, NULL, 'A' },
{ "config", required_argument, NULL, 'C' },
{ "cachedir", required_argument, NULL, 'c' },
{ "debug", no_argument, NULL, 'd' },
{ "force", no_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
{ "dry-run", no_argument, NULL, 'n' },
{ "print-format", required_argument, NULL, 'p' },
{ "repository", required_argument, NULL, 'R' },
{ "rootdir", required_argument, NULL, 'r' },
{ "skip-sync", no_argument, NULL, 's' },
{ "update", no_argument, NULL, 'u' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ "yes", no_argument, NULL, 'y' },
{ NULL, 0, NULL, 0 }
};
struct xferstat xfer;
struct sigaction sa;
const char *rootdir, *cachedir, *conffile, *defrepo, *pformat;
int i, c, flags, rv;
bool skip_sync, yes, reinstall, drun, update;
size_t maxcols;
rootdir = cachedir = conffile = defrepo = pformat = NULL;
flags = rv = 0;
skip_sync = yes = reinstall = drun = update = false;
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
switch (c) {
case 'A':
flags |= XBPS_FLAG_INSTALL_AUTO;
break;
case 'C':
conffile = optarg;
break;
case 'c':
cachedir = optarg;
break;
case 'd':
flags |= XBPS_FLAG_DEBUG;
break;
case 'f':
reinstall = true;
break;
case 'h':
usage(false);
/* NOTREACHED */
case 'n':
drun = true;
break;
case 'p':
pformat = optarg;
break;
case 'R':
defrepo = optarg;
break;
case 'r':
rootdir = optarg;
break;
case 's':
skip_sync = true;
break;
case 'u':
update = true;
break;
case 'v':
flags |= XBPS_FLAG_VERBOSE;
break;
case 'V':
printf("%s\n", XBPS_RELVER);
exit(EXIT_SUCCESS);
case 'y':
yes = true;
break;
case '?':
default:
usage(true);
/* NOTREACHED */
}
}
if (!update && (argc == optind))
usage(true);
/*
* Initialize libxbps.
*/
memset(&xh, 0, sizeof(xh));
xh.state_cb = state_cb;
xh.fetch_cb = fetch_file_progress_cb;
xh.fetch_cb_data = &xfer;
xh.rootdir = rootdir;
xh.cachedir = cachedir;
xh.conffile = conffile;
xh.flags = flags;
xh.repository = defrepo;
if (flags & XBPS_FLAG_VERBOSE)
xh.unpack_cb = unpack_progress_cb_verbose;
else
xh.unpack_cb = unpack_progress_cb;
if ((rv = xbps_init(&xh)) != 0) {
xbps_error_printf("Failed to initialize libxbps: %s\n",
strerror(rv));
exit(EXIT_FAILURE);
}
/*
* Register a signal handler to clean up resources used by libxbps.
*/
memset(&sa, 0, sizeof(sa));
sa.sa_handler = cleanup_sighandler;
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
maxcols = get_maxcols();
/*
* Check that we have write permission on rootdir, metadir
* and cachedir.
*/
if ((!drun && ((access(xh.rootdir, W_OK) == -1) ||
(access(xh.metadir, W_OK) == -1) ||
(access(xh.cachedir, W_OK) == -1)))) {
if (errno != ENOENT) {
fprintf(stderr, "Not enough permissions on "
"rootdir/cachedir/metadir: %s\n",
strerror(errno));
rv = errno;
goto out;
}
}
/* Sync remote repository index files by default */
if (!skip_sync || !drun) {
rv = xbps_rpool_sync(&xh, NULL);
if (rv != 0)
goto out;
}
if (update && !argc) {
/* Update all installed packages */
rv = dist_upgrade(&xh, maxcols, yes, drun);
} else if (update && argc) {
/* Update target packages */
for (i = optind; i < argc; i++) {
rv = update_pkg(&xh, argv[i]);
if (rv != 0)
goto out;
}
rv = exec_transaction(&xh, maxcols, yes, drun);
} else if (!update && argc) {
/* Install target packages */
for (i = optind; i < argc; i++) {
rv = install_new_pkg(&xh, argv[i], reinstall);
if (rv != 0)
goto out;
}
rv = exec_transaction(&xh, maxcols, yes, drun);
}
out:
xbps_end(&xh);
exit(rv);
}

110
bin/xbps-install/question.c Normal file
View File

@ -0,0 +1,110 @@
/*-
* Copyright (c) 2008-2010 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include "defs.h"
static char *
strtrim(char *str)
{
char *pch = str;
if (str == NULL || *str == '\0')
return str;
while (isspace((unsigned char)*pch))
pch++;
if (pch != str)
memmove(str, pch, (strlen(pch) + 1));
if (*str == '\0')
return str;
pch = (str + (strlen(str) - 1));
while (isspace((unsigned char)*pch))
pch--;
*++pch = '\0';
return str;
}
static bool
question(bool preset, const char *fmt, va_list ap)
{
char response[32];
vfprintf(stderr, fmt, ap);
if (preset)
fprintf(stderr, " %s ", "[YES/no]");
else
fprintf(stderr, " %s ", "[yes/NO]");
if (fgets(response, sizeof(response), stdin)) {
(void)strtrim(response);
if (strlen(response) == 0)
return preset;
if (strcasecmp(response, "yes") == 0)
return true;
else if (strcasecmp(response, "no") == 0)
return false;
}
return false;
}
bool
yesno(const char *fmt, ...)
{
va_list ap;
bool res;
va_start(ap, fmt);
res = question(1, fmt, ap);
va_end(ap);
return res;
}
bool
noyes(const char *fmt, ...)
{
va_list ap;
bool res;
va_start(ap, fmt);
res = question(0, fmt, ap);
va_end(ap);
return res;
}

160
bin/xbps-install/state_cb.c Normal file
View File

@ -0,0 +1,160 @@
/*-
* Copyright (c) 2011-2012 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 <stdlib.h>
#include <string.h>
#include <errno.h>
#include <syslog.h>
#include <xbps_api.h>
#include "defs.h"
void
state_cb(struct xbps_handle *xhp,
struct xbps_state_cb_data *xscd,
void *cbdata)
{
prop_dictionary_t pkgd;
const char *version;
bool syslog_enabled = false;
(void)cbdata;
if (xhp->flags & XBPS_FLAG_SYSLOG) {
syslog_enabled = true;
openlog("xbps-bin", LOG_CONS, LOG_USER);
}
switch (xscd->state) {
/* notifications */
case XBPS_STATE_TRANS_DOWNLOAD:
printf("[*] Downloading binary packages\n");
break;
case XBPS_STATE_TRANS_VERIFY:
printf("[*] Verifying binary package integrity\n");
break;
case XBPS_STATE_TRANS_RUN:
printf("[*] Running transaction tasks\n");
break;
case XBPS_STATE_TRANS_CONFIGURE:
printf("[*] Configuring unpacked packages\n");
break;
case XBPS_STATE_REPOSYNC:
case XBPS_STATE_DOWNLOAD:
case XBPS_STATE_VERIFY:
case XBPS_STATE_CONFIG_FILE:
if (xscd->desc != NULL)
printf("%s\n", xscd->desc);
break;
case XBPS_STATE_REMOVE:
printf("Removing `%s-%s' ...\n", xscd->pkgname, xscd->version);
break;
case XBPS_STATE_CONFIGURE:
printf("Configuring `%s-%s' ...\n", xscd->pkgname,
xscd->version);
break;
case XBPS_STATE_REGISTER:
case XBPS_STATE_UNREGISTER:
/* empty */
break;
case XBPS_STATE_UNPACK:
printf("Unpacking `%s-%s' ...\n", xscd->pkgname, xscd->version);
break;
case XBPS_STATE_INSTALL:
printf("Installing `%s-%s' ...\n",
xscd->pkgname, xscd->version);
break;
case XBPS_STATE_UPDATE:
pkgd = xbps_find_pkg_dict_installed(xhp,
xscd->pkgname, false);
prop_dictionary_get_cstring_nocopy(pkgd, "version", &version);
printf("Updating `%s' (`%s' to `%s') ...\n", xscd->pkgname,
version, xscd->version);
break;
/* success */
case XBPS_STATE_REMOVE_FILE:
case XBPS_STATE_REMOVE_FILE_OBSOLETE:
if (xhp->flags & XBPS_FLAG_VERBOSE)
printf("%s\n", xscd->desc);
else {
printf("%s\n", xscd->desc);
printf("\033[1A\033[K");
}
break;
case XBPS_STATE_INSTALL_DONE:
printf("Installed `%s-%s' successfully.\n",
xscd->pkgname, xscd->version);
if (syslog_enabled)
syslog(LOG_NOTICE, "Installed `%s-%s' successfully "
"(rootdir: %s).", xscd->pkgname, xscd->version,
xhp->rootdir);
break;
case XBPS_STATE_UPDATE_DONE:
printf("Updated `%s' to `%s' successfully.\n",
xscd->pkgname, xscd->version);
if (syslog_enabled)
syslog(LOG_NOTICE, "Updated `%s' to `%s' successfully "
"(rootdir: %s).", xscd->pkgname, xscd->version,
xhp->rootdir);
break;
case XBPS_STATE_REMOVE_DONE:
printf("Removed `%s-%s' successfully.\n",
xscd->pkgname, xscd->version);
if (syslog_enabled)
syslog(LOG_NOTICE, "Removed `%s-%s' successfully "
"(rootdir: %s).", xscd->pkgname, xscd->version,
xhp->rootdir);
break;
/* errors */
case XBPS_STATE_UNPACK_FAIL:
case XBPS_STATE_UPDATE_FAIL:
case XBPS_STATE_CONFIGURE_FAIL:
case XBPS_STATE_REGISTER_FAIL:
case XBPS_STATE_UNREGISTER_FAIL:
case XBPS_STATE_REMOVE_FAIL:
case XBPS_STATE_VERIFY_FAIL:
case XBPS_STATE_DOWNLOAD_FAIL:
case XBPS_STATE_REPOSYNC_FAIL:
case XBPS_STATE_CONFIG_FILE_FAIL:
xbps_error_printf("%s\n", xscd->desc);
if (syslog_enabled)
syslog(LOG_ERR, "%s", xscd->desc);
break;
case XBPS_STATE_REMOVE_FILE_FAIL:
case XBPS_STATE_REMOVE_FILE_HASH_FAIL:
case XBPS_STATE_REMOVE_FILE_OBSOLETE_FAIL:
/* Ignore errors due to not empty directories */
if (xscd->err == ENOTEMPTY)
return;
xbps_error_printf("%s\n", xscd->desc);
if (syslog_enabled)
syslog(LOG_ERR, "%s", xscd->desc);
break;
default:
xbps_dbg_printf(xhp,
"unknown state %d\n", xscd->state);
break;
}
}

View File

@ -0,0 +1,331 @@
/*-
* Copyright (c) 2009-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#include <limits.h>
#include <xbps_api.h>
#include "compat.h"
#include "defs.h"
#include "../xbps-repo/defs.h"
struct transaction {
prop_dictionary_t d;
prop_object_iterator_t iter;
uint32_t inst_pkgcnt;
uint32_t up_pkgcnt;
uint32_t cf_pkgcnt;
uint32_t rm_pkgcnt;
};
static void
show_missing_deps(prop_array_t a)
{
size_t i;
const char *str;
fprintf(stderr, "Unable to locate some required packages:\n");
for (i = 0; i < prop_array_count(a); i++) {
prop_array_get_cstring_nocopy(a, i, &str);
fprintf(stderr, " %s\n", str);
}
}
static void
show_conflicts(prop_array_t a)
{
size_t i;
const char *str;
fprintf(stderr, "Conflicting packages were found:\n");
for (i = 0; i < prop_array_count(a); i++) {
prop_array_get_cstring_nocopy(a, i, &str);
fprintf(stderr, " %s\n", str);
}
}
static void
show_actions(prop_object_iterator_t iter)
{
prop_object_t obj;
const char *repoloc, *trans, *pkgname, *version, *fname, *arch;
repoloc = trans = pkgname = version = fname = arch = NULL;
while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "transaction", &trans);
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(obj, "version", &version);
printf("%s %s %s", pkgname, trans, version);
prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc);
prop_dictionary_get_cstring_nocopy(obj, "filename", &fname);
prop_dictionary_get_cstring_nocopy(obj, "architecture", &arch);
if (repoloc && fname && arch)
printf(" %s %s %s", repoloc, fname, arch);
printf("\n");
}
}
static void
show_package_list(prop_object_iterator_t iter, const char *match, size_t cols)
{
prop_object_t obj;
const char *pkgver, *tract;
while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
if (strcmp(match, tract))
continue;
print_package_line(pkgver, cols, false);
}
prop_object_iterator_reset(iter);
print_package_line(NULL, cols, true);
}
static int
show_transaction_sizes(struct transaction *trans, size_t cols)
{
uint64_t dlsize = 0, instsize = 0, rmsize = 0;
char size[8];
/*
* Show the list of packages that will be installed.
*/
if (prop_dictionary_get_uint32(trans->d, "total-install-pkgs",
&trans->inst_pkgcnt)) {
printf("%u package%s will be installed:\n",
trans->inst_pkgcnt, trans->inst_pkgcnt == 1 ? "" : "s");
show_package_list(trans->iter, "install", cols);
printf("\n");
}
if (prop_dictionary_get_uint32(trans->d, "total-update-pkgs",
&trans->up_pkgcnt)) {
printf("%u package%s will be updated:\n",
trans->up_pkgcnt, trans->up_pkgcnt == 1 ? "" : "s");
show_package_list(trans->iter, "update", cols);
printf("\n");
}
if (prop_dictionary_get_uint32(trans->d, "total-configure-pkgs",
&trans->cf_pkgcnt)) {
printf("%u package%s will be configured:\n",
trans->cf_pkgcnt, trans->cf_pkgcnt == 1 ? "" : "s");
show_package_list(trans->iter, "configure", cols);
printf("\n");
}
if (prop_dictionary_get_uint32(trans->d, "total-remove-pkgs",
&trans->rm_pkgcnt)) {
printf("%u package%s will be removed:\n",
trans->rm_pkgcnt, trans->rm_pkgcnt == 1 ? "" : "s");
show_package_list(trans->iter, "remove", cols);
printf("\n");
}
/*
* Show total download/installed/removed size for all required packages.
*/
printf("\n");
prop_dictionary_get_uint64(trans->d, "total-download-size", &dlsize);
if (dlsize > 0) {
if (xbps_humanize_number(size, (int64_t)dlsize) == -1) {
xbps_error_printf("humanize_number returns "
"%s\n", strerror(errno));
return -1;
}
printf("Total download size:\t%6s\n", size);
}
prop_dictionary_get_uint64(trans->d, "total-installed-size",
&instsize);
if (instsize > 0) {
if (xbps_humanize_number(size, (int64_t)instsize) == -1) {
xbps_error_printf("humanize_number2 returns "
"%s\n", strerror(errno));
return -1;
}
printf("Total installed size:\t%6s\n", size);
}
prop_dictionary_get_uint64(trans->d, "total-removed-size", &rmsize);
if (rmsize > 0) {
if (xbps_humanize_number(size, (int64_t)rmsize) == -1) {
xbps_error_printf("humanize_number3 returns "
"%s\n", strerror(errno));
return -1;
}
printf("Total freed size:\t%6s\n", size);
}
printf("\n");
return 0;
}
int
dist_upgrade(struct xbps_handle *xhp, size_t cols, bool yes, bool drun)
{
int rv = 0;
if ((rv = xbps_transaction_update_packages(xhp)) != 0) {
if (rv == ENOENT) {
printf("No packages currently registered.\n");
return 0;
} else if (rv == EEXIST) {
return 0;
} else if (rv == ENOTSUP) {
fprintf(stderr, "No repositories currently "
"registered!\n");
return -1;
} else {
fprintf(stderr, "Unexpected error %s\n",
strerror(rv));
return -1;
}
}
return exec_transaction(xhp, cols, yes, drun);
}
int
install_new_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall)
{
int rv;
if ((rv = xbps_transaction_install_pkg(xhp, pkg, reinstall)) != 0) {
if (rv == EEXIST) {
printf("Package `%s' already installed.\n", pkg);
} else if (rv == ENOENT) {
fprintf(stderr, "Unable to locate '%s' in "
"repository pool.\n", pkg);
} else if (rv == ENOTSUP) {
fprintf(stderr, "No repositories "
"currently registered!\n");
} else {
fprintf(stderr, "Unexpected error: %s\n",
strerror(rv));
rv = -1;
}
}
return rv;
}
int
update_pkg(struct xbps_handle *xhp, const char *pkgname)
{
int rv;
rv = xbps_transaction_update_pkg(xhp, pkgname);
if (rv == EEXIST)
printf("Package '%s' is up to date.\n", pkgname);
else if (rv == ENOENT)
fprintf(stderr, "Package '%s' not found in "
"repository pool.\n", pkgname);
else if (rv == ENODEV)
printf("Package '%s' not installed.\n", pkgname);
else if (rv == ENOTSUP)
fprintf(stderr, "No repositories currently registered!\n");
else if (rv != 0) {
fprintf(stderr, "Unexpected error: %s\n", strerror(rv));
return -1;
}
return rv;
}
int
exec_transaction(struct xbps_handle *xhp, size_t maxcols, bool yes, bool drun)
{
prop_array_t mdeps, cflicts;
struct transaction *trans;
int rv = 0;
trans = calloc(1, sizeof(*trans));
if (trans == NULL)
return ENOMEM;
if ((rv = xbps_transaction_prepare(xhp)) != 0) {
if (rv == ENODEV) {
mdeps =
prop_dictionary_get(xhp->transd, "missing_deps");
/* missing packages */
show_missing_deps(mdeps);
goto out;
} else if (rv == EAGAIN) {
/* conflicts */
cflicts = prop_dictionary_get(xhp->transd, "conflicts");
show_conflicts(cflicts);
goto out;
}
xbps_dbg_printf(xhp, "Empty transaction dictionary: %s\n",
strerror(errno));
return rv;
}
xbps_dbg_printf(xhp, "Dictionary before transaction happens:\n");
xbps_dbg_printf_append(xhp, "%s",
prop_dictionary_externalize(xhp->transd));
trans->d = xhp->transd;
trans->iter = xbps_array_iter_from_dict(xhp->transd, "packages");
assert(trans->iter);
/*
* dry-run mode, show what would be done but don't run anything.
*/
if (drun) {
show_actions(trans->iter);
goto out;
}
/*
* Show download/installed size for the transaction.
*/
if ((rv = show_transaction_sizes(trans, maxcols)) != 0)
goto out;
/*
* Ask interactively (if -y not set).
*/
if (!yes && !yesno("Do you want to continue?")) {
printf("Aborting!\n");
goto out;
}
/*
* It's time to run the transaction!
*/
if ((rv = xbps_transaction_commit(xhp)) == 0) {
printf("\n %u installed, %u updated, "
"%u configured, %u removed.\n", trans->inst_pkgcnt,
trans->up_pkgcnt, trans->cf_pkgcnt + trans->inst_pkgcnt,
trans->rm_pkgcnt);
}
out:
if (trans->iter)
prop_object_iterator_release(trans->iter);
if (trans)
free(trans);
return rv;
}

View File

@ -0,0 +1,63 @@
/*-
* Copyright (c) 2008-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 <errno.h>
#include "defs.h"
void
unpack_progress_cb_verbose(struct xbps_handle *xhp,
struct xbps_unpack_cb_data *xpd,
void *cbdata)
{
(void)xhp;
(void)cbdata;
if (xpd->entry == NULL || xpd->entry_total_count <= 0)
return;
printf("%s: unpacked %sfile `%s' (%" PRIi64 " bytes)\n",
xpd->pkgver,
xpd->entry_is_conf ? "configuration " : "", xpd->entry,
xpd->entry_size);
}
void
unpack_progress_cb(struct xbps_handle *xhp,
struct xbps_unpack_cb_data *xpd,
void *cbdata)
{
(void)xhp;
(void)cbdata;
if (xpd->entry_total_count <= 0)
return;
printf("%s: unpacked %zd of %zd files...\n",
xpd->pkgver, xpd->entry_extract_count, xpd->entry_total_count);
printf("\033[1A\033[K");
}

71
bin/xbps-install/util.c Normal file
View File

@ -0,0 +1,71 @@
/*-
* Copyright (c) 2008-2012 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 <stdbool.h>
#include <stdlib.h>
#include <errno.h>
#include <fnmatch.h>
#include <string.h>
#include <strings.h>
#include <sys/ioctl.h>
#include <xbps_api.h>
#include "defs.h"
size_t
get_maxcols(void)
{
struct winsize ws;
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) == 0)
return ws.ws_col;
return 80;
}
void
print_package_line(const char *str, size_t maxcols, bool reset)
{
static size_t cols;
static bool first;
if (reset) {
cols = 0;
first = false;
return;
}
cols += strlen(str) + 4;
if (cols <= maxcols) {
if (first == false) {
printf(" ");
first = true;
}
} else {
printf("\n ");
cols = strlen(str) + 4;
}
printf("%s ", str);
}

11
bin/xbps-pkgdb/Makefile Normal file
View File

@ -0,0 +1,11 @@
TOPDIR = ../..
-include $(TOPDIR)/config.mk
BIN = xbps-pkgdb
OBJS = main.o check.o check_pkg_automatic.o check_pkg_files.o
OBJS += check_pkg_requiredby.o check_pkg_rundeps.o
OBJS += check_pkg_symlinks.o check_pkg_unneeded.o
#MAN = $(BIN).8
include $(TOPDIR)/mk/prog.mk

188
bin/xbps-pkgdb/check.c Normal file
View File

@ -0,0 +1,188 @@
/*-
* Copyright (c) 2009-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/param.h>
#include <xbps_api.h>
#include "defs.h"
struct checkpkg {
size_t totalpkgs;
size_t npkgs;
size_t nbrokenpkgs;
bool flush;
};
static int
cb_pkg_integrity(struct xbps_handle *xhp,
prop_object_t obj,
void *arg,
bool *done)
{
struct checkpkg *cpkg = arg;
const char *pkgname, *version;
bool flush = false;
(void)done;
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(obj, "version", &version);
printf("[%zu/%zu] checking %s-%s ...\n",
cpkg->npkgs, cpkg->totalpkgs, pkgname, version);
if (check_pkg_integrity(xhp, obj, pkgname, false, &flush) != 0)
cpkg->nbrokenpkgs++;
else
printf("\033[1A\033[K");
if (flush && !cpkg->flush)
cpkg->flush = flush;
cpkg->npkgs++;
return 0;
}
int
check_pkg_integrity_all(struct xbps_handle *xhp)
{
struct checkpkg cpkg;
int rv;
memset(&cpkg, 0, sizeof(cpkg));
/* force an update to get total pkg count */
(void)xbps_pkgdb_update(xhp, false);
cpkg.totalpkgs = prop_array_count(xhp->pkgdb);
(void)xbps_pkgdb_foreach_cb(xhp, cb_pkg_integrity, &cpkg);
if (cpkg.flush) {
if ((rv = xbps_pkgdb_update(xhp, true)) != 0) {
xbps_error_printf("failed to write pkgdb: %s\n",
strerror(rv));
return rv;
}
}
printf("%zu package%s processed: %zu broken.\n", cpkg.npkgs,
cpkg.npkgs == 1 ? "" : "s", cpkg.nbrokenpkgs);
return 0;
}
int
check_pkg_integrity(struct xbps_handle *xhp,
prop_dictionary_t pkgd,
const char *pkgname,
bool flush,
bool *setflush)
{
prop_dictionary_t opkgd, propsd, filesd;
int rv = 0;
bool pkgdb_update = false, broken = false;
propsd = filesd = opkgd = NULL;
/* find real pkg by name */
if (pkgd == NULL) {
opkgd = xbps_find_pkg_dict_installed(xhp, pkgname, false);
if (opkgd == NULL) {
/* find virtual pkg by name */
opkgd = xbps_find_virtualpkg_dict_installed(xhp,
pkgname, false);
}
if (opkgd == NULL) {
printf("Package %s is not installed.\n", pkgname);
return 0;
}
}
/*
* Check for props.plist metadata file.
*/
propsd = xbps_dictionary_from_metadata_plist(xhp, pkgname, XBPS_PKGPROPS);
if (propsd == NULL) {
xbps_error_printf("%s: unexistent %s or invalid metadata "
"file.\n", pkgname, XBPS_PKGPROPS);
broken = true;
goto out;
} else if (prop_dictionary_count(propsd) == 0) {
xbps_error_printf("%s: incomplete %s metadata file.\n",
pkgname, XBPS_PKGPROPS);
broken = true;
goto out;
}
/*
* Check for files.plist metadata file.
*/
filesd = xbps_dictionary_from_metadata_plist(xhp, pkgname, XBPS_PKGFILES);
if (filesd == NULL) {
xbps_error_printf("%s: unexistent %s or invalid metadata "
"file.\n", pkgname, XBPS_PKGFILES);
broken = true;
goto out;
}
#define RUN_PKG_CHECK(x, name, arg, arg2) \
do { \
rv = check_pkg_##name(x, pkgname, arg, arg2); \
if (rv) \
broken = true; \
else if (rv == -1) { \
xbps_error_printf("%s: the %s test " \
"returned error!\n", pkgname, #name); \
goto out; \
} \
} while (0)
/* Execute pkg checks */
RUN_PKG_CHECK(xhp, files, filesd, &pkgdb_update);
RUN_PKG_CHECK(xhp, symlinks, filesd, &pkgdb_update);
RUN_PKG_CHECK(xhp, rundeps, propsd, &pkgdb_update);
RUN_PKG_CHECK(xhp, requiredby, pkgd ? pkgd : opkgd, &pkgdb_update);
RUN_PKG_CHECK(xhp, autoinstall, pkgd ? pkgd : opkgd, &pkgdb_update);
RUN_PKG_CHECK(xhp, unneeded, pkgd ? pkgd : opkgd, &pkgdb_update);
if (flush && pkgdb_update) {
if (!xbps_pkgdb_replace_pkgd(xhp, opkgd, pkgname, false, true)) {
rv = EINVAL;
goto out;
}
}
if (setflush && pkgdb_update)
*setflush = true;
#undef RUN_PKG_CHECK
out:
if (prop_object_type(filesd) == PROP_TYPE_DICTIONARY)
prop_object_release(filesd);
if (prop_object_type(propsd) == PROP_TYPE_DICTIONARY)
prop_object_release(propsd);
if (broken)
return 1;
return rv;
}

View File

@ -0,0 +1,77 @@
/*-
* Copyright (c) 2011-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <sys/param.h>
#include <xbps_api.h>
#include "defs.h"
/*
* Checks package integrity of an installed package.
* The following task is accomplished in this file:
*
* o Check if package was installed manually, but currently
* other packages are depending on it. This package shall be
* changed to automatic mode, i.e installed as dependency of
* those packages.
*
* Returns 0 if test ran successfully, 1 otherwise and -1 on error.
*/
int
check_pkg_autoinstall(struct xbps_handle *xhp,
const char *pkgname,
void *arg,
bool *pkgdb_update)
{
prop_dictionary_t pkgd = arg;
prop_array_t reqby;
bool autoinst = false;
(void)xhp;
/*
* Check if package has been installed manually but any other
* package is currently depending on it; in that case the package
* must be in automatic mode.
*/
if (prop_dictionary_get_bool(pkgd, "automatic-install", &autoinst)) {
reqby = prop_dictionary_get(pkgd, "requiredby");
if (reqby != NULL && prop_array_count(reqby) && !autoinst) {
/* pkg has reversedeps and was installed manually */
prop_dictionary_set_bool(pkgd,
"automatic-install", true);
*pkgdb_update = true;
printf("%s: changed to automatic install mode.\n",
pkgname);
}
}
return 0;
}

View File

@ -0,0 +1,153 @@
/*-
* Copyright (c) 2011-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/param.h>
#include <xbps_api.h>
#include "defs.h"
/*
* Checks package integrity of an installed package.
* The following tasks are processed in that order:
*
* o Check for missing installed files.
*
* o Check the hash for all installed files, except
* configuration files (which is expected if they are modified).
*
* Return 0 if test ran successfully, 1 otherwise and -1 on error.
*/
int
check_pkg_files(struct xbps_handle *xhp,
const char *pkgname,
void *arg,
bool *pkgdb_update)
{
prop_array_t array;
prop_object_t obj;
prop_object_iterator_t iter;
prop_dictionary_t pkg_filesd = arg;
const char *file, *sha256;
char *path;
int rv = 0;
bool mutable, broken = false, test_broken = false;
(void)pkgdb_update;
array = prop_dictionary_get(pkg_filesd, "files");
if (array != NULL && prop_array_count(array) > 0) {
iter = xbps_array_iter_from_dict(pkg_filesd, "files");
if (iter == NULL)
return -1;
while ((obj = prop_object_iterator_next(iter))) {
prop_dictionary_get_cstring_nocopy(obj, "file", &file);
path = xbps_xasprintf("%s/%s", xhp->rootdir, file);
if (path == NULL) {
prop_object_iterator_release(iter);
return -1;
}
prop_dictionary_get_cstring_nocopy(obj,
"sha256", &sha256);
rv = xbps_file_hash_check(path, sha256);
switch (rv) {
case 0:
break;
case ENOENT:
xbps_error_printf("%s: unexistent file %s.\n",
pkgname, file);
test_broken = true;
break;
case ERANGE:
mutable = false;
prop_dictionary_get_bool(obj,
"mutable", &mutable);
if (!mutable) {
xbps_error_printf("%s: hash mismatch "
"for %s.\n", pkgname, file);
test_broken = true;
}
break;
default:
xbps_error_printf(
"%s: can't check `%s' (%s)\n",
pkgname, file, strerror(rv));
break;
}
free(path);
}
prop_object_iterator_release(iter);
}
if (test_broken) {
xbps_error_printf("%s: files check FAILED.\n", pkgname);
test_broken = false;
broken = true;
}
/*
* Check for missing configuration files.
*/
array = prop_dictionary_get(pkg_filesd, "conf_files");
if (array != NULL && prop_array_count(array) > 0) {
iter = xbps_array_iter_from_dict(pkg_filesd, "conf_files");
if (iter == NULL)
return -1;
while ((obj = prop_object_iterator_next(iter))) {
prop_dictionary_get_cstring_nocopy(obj, "file", &file);
path = xbps_xasprintf("%s/%s", xhp->rootdir, file);
if (path == NULL) {
prop_object_iterator_release(iter);
return -1;
}
if ((rv = access(path, R_OK)) == -1) {
if (errno == ENOENT) {
xbps_error_printf(
"%s: unexistent file %s\n",
pkgname, file);
test_broken = true;
} else
xbps_error_printf(
"%s: can't check `%s' (%s)\n",
pkgname, file,
strerror(errno));
}
free(path);
}
prop_object_iterator_release(iter);
}
if (test_broken) {
xbps_error_printf("%s: conf files check FAILED.\n", pkgname);
broken = true;
}
return broken;
}

View File

@ -0,0 +1,222 @@
/*-
* Copyright (c) 2011-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/param.h>
#include <xbps_api.h>
#include "defs.h"
struct check_reqby_data {
prop_dictionary_t pkgd;
prop_array_t pkgd_reqby;
const char *pkgname;
const char *pkgver;
bool pkgd_reqby_alloc;
};
static int
check_reqby_pkg_cb(struct xbps_handle *xhp,
prop_object_t obj,
void *arg,
bool *done)
{
struct check_reqby_data *crd = arg;
prop_array_t curpkg_rdeps, provides;
prop_dictionary_t curpkg_propsd;
prop_string_t curpkgver;
const char *curpkgn;
(void)done;
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &curpkgn);
/* skip same pkg */
if (strcmp(curpkgn, crd->pkgname) == 0)
return 0;
/*
* Internalize current pkg props dictionary from its
* installed metadata directory.
*/
curpkg_propsd =
xbps_dictionary_from_metadata_plist(xhp, curpkgn, XBPS_PKGPROPS);
if (curpkg_propsd == NULL) {
xbps_error_printf("%s: missing %s metadata file!\n",
curpkgn, XBPS_PKGPROPS);
return -1;
}
curpkg_rdeps =
prop_dictionary_get(curpkg_propsd, "run_depends");
if (curpkg_rdeps == NULL) {
/* package has no rundeps, skip */
prop_object_release(curpkg_propsd);
return 0;
}
/*
* Check for pkgpattern match with real packages...
*/
if (!xbps_match_pkgdep_in_array(curpkg_rdeps, crd->pkgver)) {
/*
* ... otherwise check if package provides any virtual
* package and is matched against any object in
* run_depends.
*/
provides = prop_dictionary_get(obj, "provides");
if (provides == NULL) {
/* doesn't provide any virtual pkg */
prop_object_release(curpkg_propsd);
return 0;
}
if (!xbps_match_any_virtualpkg_in_rundeps(curpkg_rdeps,
provides)) {
/* doesn't match any virtual pkg */
prop_object_release(curpkg_propsd);
return 0;
}
}
crd->pkgd_reqby = prop_dictionary_get(crd->pkgd, "requiredby");
curpkgver = prop_dictionary_get(curpkg_propsd, "pkgver");
if (crd->pkgd_reqby != NULL) {
/*
* Now check that current pkgver has been registered into
* its requiredby array.
*/
if (xbps_match_string_in_array(crd->pkgd_reqby,
prop_string_cstring_nocopy(curpkgver))) {
/*
* Current package already requires our package,
* this is good so skip it.
*/
prop_object_release(curpkg_propsd);
return 0;
}
} else {
/*
* Missing requiredby array object, create it.
*/
crd->pkgd_reqby = prop_array_create();
if (crd->pkgd_reqby == NULL) {
prop_object_release(curpkg_propsd);
return -1;
}
crd->pkgd_reqby_alloc = true;
}
/*
* Added pkgdep into pkg's requiredby array.
*/
if (!prop_array_add(crd->pkgd_reqby, curpkgver)) {
prop_object_release(curpkg_propsd);
return -1;
}
printf("%s: added missing requiredby entry for %s.\n\n",
crd->pkgver, prop_string_cstring_nocopy(curpkgver));
prop_object_release(curpkg_propsd);
return 1;
}
/*
* Removes unused entries in pkg's requiredby array.
*/
static bool
remove_stale_entries_in_reqby(struct xbps_handle *xhp,
struct check_reqby_data *crd)
{
prop_array_t reqby;
prop_dictionary_t pkgd;
const char *str;
size_t i;
bool needs_update = false;
reqby = prop_dictionary_get(crd->pkgd, "requiredby");
if (reqby == NULL || prop_array_count(reqby) == 0)
return false;
crd->pkgd_reqby = prop_dictionary_get(crd->pkgd, "requiredby");
for (i = 0; i < prop_array_count(reqby); i++) {
prop_array_get_cstring_nocopy(reqby, i, &str);
if ((pkgd = xbps_pkgdb_get_pkgd_by_pkgver(xhp, str)) != NULL)
continue;
printf("%s: found stale entry in requiredby `%s' (fixed)\n",
crd->pkgver, str);
if (xbps_remove_string_from_array(xhp, crd->pkgd_reqby, str))
needs_update = true;
}
if (needs_update) {
prop_dictionary_set(crd->pkgd, "requiredby", crd->pkgd_reqby);
printf("%s: requiredby fix done!\n\n", crd->pkgver);
return true;
}
return false;
}
/*
* Checks package integrity of an installed package.
* The following task is accomplished in this file:
*
* o Check for missing reverse dependencies (aka requiredby)
* entries in pkg's pkgdb dictionary.
*
* Returns 0 if test ran successfully, 1 otherwise and -1 on error.
*/
int
check_pkg_requiredby(struct xbps_handle *xhp,
const char *pkgname,
void *arg,
bool *pkgdb_update)
{
prop_dictionary_t pkgd = arg;
struct check_reqby_data crd;
int rv;
crd.pkgd = pkgd;
crd.pkgd_reqby = NULL;
crd.pkgd_reqby_alloc = false;
crd.pkgname = pkgname;
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &crd.pkgver);
/* missing reqby entries in pkgs */
rv = xbps_pkgdb_foreach_cb(xhp, check_reqby_pkg_cb, &crd);
if (rv < 0) {
return rv;
} else if (rv == 1) {
*pkgdb_update = true;
prop_dictionary_set(pkgd, "requiredby", crd.pkgd_reqby);
if (crd.pkgd_reqby_alloc)
prop_object_release(crd.pkgd_reqby);
printf("%s: requiredby fix done!\n\n", crd.pkgver);
}
/* remove stale entries in pkg's reqby */
if (remove_stale_entries_in_reqby(xhp, &crd))
*pkgdb_update = true;
return 0;
}

View File

@ -0,0 +1,82 @@
/*-
* Copyright (c) 2011-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <sys/param.h>
#include <xbps_api.h>
#include "defs.h"
/*
* Checks package integrity of an installed package.
* The following task is accomplished in this file:
*
* o Check for missing run time dependencies.
*
* Returns 0 if test ran successfully, 1 otherwise and -1 on error.
*/
int
check_pkg_rundeps(struct xbps_handle *xhp,
const char *pkgname,
void *arg,
bool *pkgdb_update)
{
prop_dictionary_t pkg_propsd = arg;
prop_object_t obj;
prop_object_iterator_t iter;
const char *reqpkg;
bool test_broken = false;
(void)pkgdb_update;
if (!xbps_pkg_has_rundeps(pkg_propsd))
return 0;
iter = xbps_array_iter_from_dict(pkg_propsd, "run_depends");
if (iter == NULL)
return -1;
while ((obj = prop_object_iterator_next(iter))) {
reqpkg = prop_string_cstring_nocopy(obj);
if (reqpkg == NULL) {
prop_object_iterator_release(iter);
return -1;
}
if (xbps_check_is_installed_pkg_by_pattern(xhp, reqpkg) <= 0) {
xbps_error_printf("%s: dependency not satisfied: %s\n",
pkgname, reqpkg);
test_broken = true;
}
}
prop_object_iterator_release(iter);
return test_broken;
}

View File

@ -0,0 +1,123 @@
/*-
* Copyright (c) 2011-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/param.h>
#include <xbps_api.h>
#include "defs.h"
/*
* Checks package integrity of an installed package.
* The following task is accomplished in this file:
*
* o Check for target file in symlinks, so that we can check that
* they have not been modified.
*
* returns 0 if test ran successfully, 1 otherwise and -1 on error.
*/
int
check_pkg_symlinks(struct xbps_handle *xhp,
const char *pkgname,
void *arg,
bool *pkgdb_update)
{
prop_array_t array;
prop_object_t obj;
prop_object_iterator_t iter;
prop_dictionary_t pkg_filesd = arg;
const char *file, *tgt = NULL;
char *path, *buf, *buf2, *buf3, *dname, *path_target;
bool broken = false, test_broken = false;
(void)pkgdb_update;
array = prop_dictionary_get(pkg_filesd, "links");
if ((prop_object_type(array) == PROP_TYPE_ARRAY) &&
prop_array_count(array) > 0) {
iter = xbps_array_iter_from_dict(pkg_filesd, "links");
if (iter == NULL)
return -1;
while ((obj = prop_object_iterator_next(iter))) {
if (!prop_dictionary_get_cstring_nocopy(obj, "target", &tgt))
continue;
prop_dictionary_get_cstring_nocopy(obj, "file", &file);
if (strcmp(tgt, "") == 0) {
xbps_warn_printf("%s: `%s' symlink with "
"empty target object!\n", pkgname, file);
continue;
}
path = xbps_xasprintf("%s/%s", xhp->rootdir, file);
if (path == NULL)
return -1;
if ((buf = realpath(path, NULL)) == NULL) {
xbps_error_printf("%s: broken symlink `%s': "
"%s\n", pkgname, file, strerror(errno));
test_broken = true;
continue;
}
if (strncmp(tgt, "../", 3) == 0) {
/* relative symlink target */
dname = dirname(path);
buf2 = xbps_xasprintf("%s/%s", dname, tgt);
assert(buf2);
buf3 = realpath(buf2, NULL);
assert(buf3);
free(buf2);
path_target = buf3;
} else {
path_target = buf;
}
if (strcmp(buf, path_target)) {
xbps_error_printf("%s: modified symlink `%s' "
"points to: `%s' (shall be: `%s')\n",
pkgname, file, buf, path_target);
test_broken = true;
}
free(buf);
free(path);
if (buf3)
free(buf3);
path = buf = buf2 = buf3 = NULL;
}
prop_object_iterator_release(iter);
}
if (test_broken) {
xbps_error_printf("%s: symlinks check FAILED.\n", pkgname);
broken = true;
}
return broken;
}

View File

@ -0,0 +1,65 @@
/*-
* Copyright (c) 2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <sys/param.h>
#include <xbps_api.h>
#include "defs.h"
/*
* Checks package integrity of an installed package.
* The following task is accomplished in this file:
*
* o Check if pkg dictionary from pkgdb contains "unneeded" objects,
* and remove them if that was true.
*/
int
check_pkg_unneeded(struct xbps_handle *xhp,
const char *pkgname,
void *arg,
bool *pkgdb_update)
{
prop_dictionary_t pkgd = arg;
(void)pkgname;
(void)xhp;
if (prop_dictionary_get(pkgd, "remove-and-update")) {
*pkgdb_update = true;
prop_dictionary_remove(pkgd, "remove-and-update");
}
if (prop_dictionary_get(pkgd, "transaction")) {
*pkgdb_update = true;
prop_dictionary_remove(pkgd, "transaction");
}
return 0;
}

50
bin/xbps-pkgdb/defs.h Normal file
View File

@ -0,0 +1,50 @@
/*-
* Copyright (c) 2012 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.
*/
#ifndef _XBPS_PKGDB_DEFS_H_
#define _XBPS_PKGDB_DEFS_H_
#include <sys/time.h>
#include <xbps_api.h>
/* from check.c */
int check_pkg_integrity(struct xbps_handle *,
prop_dictionary_t,
const char *,
bool,
bool *);
int check_pkg_integrity_all(struct xbps_handle *);
#define CHECK_PKG_DECL(type) \
int check_pkg_##type (struct xbps_handle *, const char *, void *, bool *)
CHECK_PKG_DECL(autoinstall);
CHECK_PKG_DECL(unneeded);
CHECK_PKG_DECL(files);
CHECK_PKG_DECL(rundeps);
CHECK_PKG_DECL(symlinks);
CHECK_PKG_DECL(requiredby);
#endif /* !_XBPS_PKGDB_DEFS_H_ */

128
bin/xbps-pkgdb/main.c Normal file
View File

@ -0,0 +1,128 @@
/*-
* Copyright (c) 2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <xbps_api.h>
#include "defs.h"
static void __attribute__((noreturn))
usage(bool fail)
{
fprintf(stdout,
"Usage: xbps-pkgdb [OPTIONS] [PKGNAME...]\n\n"
"OPTIONS\n"
" -a --all Process all packages\n"
" -C --config <file> Full path to configuration file\n"
" -d --debug Debug mode shown to stderr\n"
" -h --help Print usage help\n"
" -r --rootdir <dir> Full path to rootdir\n"
" -v --verbose Verbose messages\n"
" -V --version Show XBPS version\n");
exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
int
main(int argc, char **argv)
{
const char *shortopts = "aC:dhr:Vv";
const struct option longopts[] = {
{ "all", no_argument, NULL, 'a' },
{ "config", required_argument, NULL, 'C' },
{ "debug", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "rootdir", required_argument, NULL, 'r' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
struct xbps_handle xh;
const char *conffile = NULL, *rootdir = NULL;
int c, i, rv, flags = 0;
bool all = false;
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
switch (c) {
case 'a':
all = true;
break;
case 'C':
conffile = optarg;
break;
case 'd':
flags |= XBPS_FLAG_DEBUG;
break;
case 'h':
usage(false);
/* NOTREACHED */
case 'r':
rootdir = optarg;
break;
case 'v':
flags |= XBPS_FLAG_VERBOSE;
break;
case 'V':
printf("%s\n", XBPS_RELVER);
exit(EXIT_SUCCESS);
case '?':
default:
usage(true);
/* NOTREACHED */
}
}
if (!all && (argc == optind))
usage(true);
memset(&xh, 0, sizeof(xh));
xh.rootdir = rootdir;
xh.conffile = conffile;
xh.flags = flags;
if ((rv = xbps_init(&xh)) != 0) {
xbps_error_printf("Failed to initialize libxbps: %s\n",
strerror(rv));
exit(EXIT_FAILURE);
}
if (all) {
rv = check_pkg_integrity_all(&xh);
} else {
for (i = optind; i < argc; i++) {
rv = check_pkg_integrity(&xh, NULL, argv[i],
true, NULL);
if (rv != 0)
fprintf(stderr, "Failed to check "
"`%s': %s\n", argv[i], strerror(rv));
}
}
xbps_end(&xh);
exit(rv ? EXIT_FAILURE : EXIT_SUCCESS);
}

9
bin/xbps-query/Makefile Normal file
View File

@ -0,0 +1,9 @@
TOPDIR = ../..
-include $(TOPDIR)/config.mk
BIN = xbps-query
OBJS = main.o list.o show-deps.o show-info-files.o
OBJS += ownedby.o search.o
#MAN = $(BIN).8
include $(TOPDIR)/mk/prog.mk

68
bin/xbps-query/defs.h Normal file
View File

@ -0,0 +1,68 @@
/*-
* Copyright (c) 2009-2012 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.
*/
#ifndef _XBPS_QUERY_DEFS_H_
#define _XBPS_QUERY_DEFS_H_
#include <xbps_api.h>
/* from show-deps.c */
int show_pkg_deps(struct xbps_handle *, const char *);
int show_pkg_revdeps(struct xbps_handle *, const char *);
int repo_show_pkg_deps(struct xbps_handle *, const char *);
/* from show-info-files.c */
void show_pkg_info(prop_dictionary_t);
void show_pkg_info_one(prop_dictionary_t, const char *);
int show_pkg_info_from_metadir(struct xbps_handle *, const char *,
const char *);
int show_pkg_files(prop_dictionary_t);
int show_pkg_files_from_metadir(struct xbps_handle *, const char *);
int repo_show_pkg_files(struct xbps_handle *, const char *);
int repo_show_pkg_info(struct xbps_handle *, const char *, const char *);
int repo_show_pkg_namedesc(struct xbps_handle *, prop_object_t, void *,
bool *);
/* from ownedby.c */
int ownedby(struct xbps_handle *, int, char **);
int repo_ownedby(struct xbps_handle *, int, char **);
/* From list.c */
size_t get_maxcols(void);
int list_strings_sep_in_array(struct xbps_handle *,
prop_object_t, void *, bool *);
size_t find_longest_pkgver(struct xbps_handle *, prop_object_t);
int list_pkgs_in_dict(struct xbps_handle *, prop_object_t, void *, bool *);
int list_manual_pkgs(struct xbps_handle *, prop_object_t, void *, bool *);
int list_orphans(struct xbps_handle *);
int list_pkgs_pkgdb(struct xbps_handle *);
int repo_list(struct xbps_handle *);
/* from search.c */
int repo_search(struct xbps_handle *, int, char **);
#endif /* !_XBPS_QUERY_DEFS_H_ */

238
bin/xbps-query/list.c Normal file
View File

@ -0,0 +1,238 @@
/*-
* Copyright (c) 2008-2012 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 <stdbool.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <sys/ioctl.h>
#include "defs.h"
struct list_pkgver_cb {
size_t pkgver_len;
size_t maxcols;
};
size_t
get_maxcols(void)
{
struct winsize ws;
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) == 0)
return ws.ws_col;
return 80;
}
int
list_pkgs_in_dict(struct xbps_handle *xhp,
prop_object_t obj,
void *arg,
bool *loop_done)
{
struct list_pkgver_cb *lpc = arg;
const char *pkgver, *short_desc, *arch;
char *tmp = NULL, *out = NULL;
size_t i, len = 0;
bool chkarch;
(void)xhp;
(void)loop_done;
chkarch = prop_dictionary_get_cstring_nocopy(obj, "architecture", &arch);
if (chkarch && !xbps_pkg_arch_match(xhp, arch, NULL))
return 0;
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(obj, "short_desc", &short_desc);
if (!pkgver && !short_desc)
return EINVAL;
tmp = calloc(1, lpc->pkgver_len + 1);
assert(tmp);
memcpy(tmp, pkgver, lpc->pkgver_len);
for (i = strlen(tmp); i < lpc->pkgver_len; i++)
tmp[i] = ' ';
tmp[i] = '\0';
len = strlen(tmp) + strlen(short_desc) + 1;
if (len > lpc->maxcols) {
out = malloc(lpc->maxcols);
assert(out);
snprintf(out, lpc->maxcols-2, "%s %s", tmp, short_desc);
strncat(out, "...", lpc->maxcols);
printf("%s\n", out);
free(out);
} else {
printf("%s %s\n", tmp, short_desc);
}
free(tmp);
return 0;
}
int
list_manual_pkgs(struct xbps_handle *xhp,
prop_object_t obj,
void *arg,
bool *loop_done)
{
const char *pkgver;
bool automatic = false;
(void)xhp;
(void)arg;
(void)loop_done;
prop_dictionary_get_bool(obj, "automatic-install", &automatic);
if (automatic == false) {
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
printf("%s\n", pkgver);
}
return 0;
}
int
list_orphans(struct xbps_handle *xhp)
{
prop_array_t orphans;
prop_object_iterator_t iter;
prop_object_t obj;
const char *pkgver;
orphans = xbps_find_pkg_orphans(xhp, NULL);
if (orphans == NULL)
return EINVAL;
if (prop_array_count(orphans) == 0)
return 0;
iter = prop_array_iterator(orphans);
if (iter == NULL)
return ENOMEM;
while ((obj = prop_object_iterator_next(iter)) != NULL) {
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
printf("%s\n", pkgver);
}
prop_object_iterator_release(iter);
return 0;
}
int
list_pkgs_pkgdb(struct xbps_handle *xhp)
{
struct list_pkgver_cb lpc;
lpc.pkgver_len = find_longest_pkgver(xhp, NULL);
lpc.maxcols = get_maxcols();
return xbps_pkgdb_foreach_cb(xhp, list_pkgs_in_dict, &lpc);
}
static int
repo_list_uri_cb(struct xbps_handle *xhp,
struct xbps_rpool_index *rpi,
void *arg,
bool *done)
{
(void)xhp;
(void)arg;
(void)done;
printf("%s (%zu packages)\n", rpi->uri,
(size_t)prop_array_count(rpi->repo));
return 0;
}
int
repo_list(struct xbps_handle *xhp)
{
int rv;
rv = xbps_rpool_foreach(xhp, repo_list_uri_cb, NULL);
if (rv != 0 && rv != ENOTSUP) {
fprintf(stderr, "Failed to initialize rpool: %s\n",
strerror(rv));
return rv;
}
return 0;
}
static int
_find_longest_pkgver_cb(struct xbps_handle *xhp,
prop_object_t obj,
void *arg,
bool *loop_done)
{
size_t *len = arg;
const char *pkgver;
(void)xhp;
(void)loop_done;
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
if (*len == 0 || strlen(pkgver) > *len)
*len = strlen(pkgver);
return 0;
}
size_t
find_longest_pkgver(struct xbps_handle *xhp, prop_object_t o)
{
size_t len = 0;
if (prop_object_type(o) == PROP_TYPE_ARRAY)
(void)xbps_callback_array_iter(xhp, o,
_find_longest_pkgver_cb, &len);
else
(void)xbps_pkgdb_foreach_cb(xhp,
_find_longest_pkgver_cb, &len);
return len;
}
int
list_strings_sep_in_array(struct xbps_handle *xhp,
prop_object_t obj,
void *arg,
bool *loop_done)
{
const char *sep = arg;
(void)xhp;
(void)loop_done;
printf("%s%s\n", sep ? sep : "", prop_string_cstring_nocopy(obj));
return 0;
}

247
bin/xbps-query/main.c Normal file
View File

@ -0,0 +1,247 @@
/*-
* Copyright (c) 2008-2012 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 <getopt.h>
#include <xbps_api.h>
#include "defs.h"
static void __attribute__((noreturn))
usage(bool fail)
{
fprintf(stdout,
"Usage: xbps-query [OPTIONS...] [PKGNAME]\n"
"\nOPTIONS\n"
" -C --config <file> Full path to configuration file\n"
" -c --cachedir <dir> Full path to cachedir\n"
" -D --defrepo <uri> Default repository to be used if config not set\n"
" -d --debug Debug mode shown to stderr\n"
" -h --help Print help usage\n"
" -R --repository Enable repository mode\n"
" -r --rootdir <dir> Full path to rootdir\n"
" -V --version Show XBPS version\n"
" -v --verbose Verbose messages\n"
"\nMODE [only one mode may be specified]\n"
" -l --list-pkgs List available packages\n"
" -L --list-repos List working repositories\n"
" -m --list-manual-pkgs List packages installed explicitly\n"
" -M --list-orphans List package orphans\n"
" -o --ownedby PATTERN(s) Search for packages owning PATTERN(s)\n"
" -s --search PATTERN(s) Search for packages matching PATTERN(s)\n"
" -f --files Show files for PKGNAME\n"
" -p --property PROP,... Show properties for PKGNAME\n"
" -x --deps Show dependencies for PKGNAME\n"
" -X --revdeps Show reverse dependencies for PKGNAME\n");
exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
int
main(int argc, char **argv)
{
const char *shortopts = "C:c:D:dfhLlmMop:Rr:sVvXx";
const struct option longopts[] = {
{ "config", required_argument, NULL, 'C' },
{ "cachedir", required_argument, NULL, 'c' },
{ "defrepo", required_argument, NULL, 'D' },
{ "debug", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "list-repos", no_argument, NULL, 'L' },
{ "list-pkgs", no_argument, NULL, 'l' },
{ "list-manual-pkgs", no_argument, NULL, 'm' },
{ "list-orphans", no_argument, NULL, 'M' },
{ "ownedby", no_argument, NULL, 'o' },
{ "property", required_argument, NULL, 'p' },
{ "repository-mode", no_argument, NULL, 'R' },
{ "rootdir", required_argument, NULL, 'r' },
{ "search", no_argument, NULL, 's' },
{ "version", no_argument, NULL, 'V' },
{ "verbose", no_argument, NULL, 'v' },
{ "files", no_argument, NULL, 'f' },
{ "deps", no_argument, NULL, 'x' },
{ "revdeps", no_argument, NULL, 'X' },
{ NULL, 0, NULL, 0 },
};
struct xbps_handle xh;
const char *rootdir, *cachedir, *conffile, *props, *defrepo;
int c, flags, rv;
bool list_pkgs, list_repos, orphans, own;
bool list_manual, show_prop, show_files, show_deps, show_rdeps;
bool show, search, repo_mode, opmode;
rootdir = cachedir = conffile = defrepo = props = NULL;
flags = rv = c = 0;
list_pkgs = list_repos = orphans = search = own = false;
list_manual = show_prop = show_files = search = false;
show = show_deps = show_rdeps = false;
repo_mode = opmode = false;
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
switch (c) {
case 'C':
conffile = optarg;
break;
case 'c':
cachedir = optarg;
break;
case 'D':
defrepo = optarg;
break;
case 'd':
flags |= XBPS_FLAG_DEBUG;
break;
case 'f':
show_files = opmode = true;
break;
case 'h':
usage(false);
/* NOTREACHED */
case 'L':
list_repos = opmode = true;
break;
case 'l':
list_pkgs = opmode = true;
break;
case 'm':
list_manual = opmode = true;
break;
case 'M':
orphans = opmode = true;
break;
case 'o':
own = opmode = true;
break;
case 'p':
props = optarg;
show_prop = opmode = true;
break;
case 'R':
repo_mode = true;
break;
case 'r':
rootdir = optarg;
break;
case 's':
search = opmode = true;
break;
case 'v':
flags |= XBPS_FLAG_VERBOSE;
break;
case 'V':
printf("%s\n", XBPS_RELVER);
exit(EXIT_SUCCESS);
case 'x':
show_deps = opmode = true;
break;
case 'X':
show_rdeps = opmode = true;
break;
case '?':
usage(true);
/* NOTREACHED */
}
}
if (!opmode && argc > optind)
show = true;
else if (!opmode && argc == optind)
usage(true);
/*
* Initialize libxbps.
*/
memset(&xh, 0, sizeof(xh));
xh.rootdir = rootdir;
xh.cachedir = cachedir;
xh.conffile = conffile;
xh.flags = flags;
xh.repository = defrepo;
if ((rv = xbps_init(&xh)) != 0) {
xbps_error_printf("Failed to initialize libxbps: %s\n",
strerror(rv));
exit(EXIT_FAILURE);
}
if (list_repos) {
/* list repositories */
rv = repo_list(&xh);
} else if (list_manual) {
/* list manual pkgs */
rv = xbps_pkgdb_foreach_cb(&xh, list_manual_pkgs, NULL);
} else if (list_pkgs) {
/* list available pkgs */
rv = list_pkgs_pkgdb(&xh);
} else if (orphans) {
/* list pkg orphans */
rv = list_orphans(&xh);
} else if (own) {
/* ownedby mode */
if (repo_mode)
rv = repo_ownedby(&xh, argc - optind, argv + optind);
else
rv = ownedby(&xh, argc - optind, argv + optind);
} else if (search) {
/* search mode */
rv = repo_search(&xh, argc - optind, argv + optind);
} else if (show || show_prop) {
/* show mode */
if (repo_mode)
rv = repo_show_pkg_info(&xh, argv[optind], props);
else
rv = show_pkg_info_from_metadir(&xh,
argv[optind], props);
} else if (show_files) {
/* show-files mode */
if (repo_mode)
rv = repo_show_pkg_files(&xh, argv[optind]);
else
rv = show_pkg_files_from_metadir(&xh, argv[optind]);
} else if (show_deps) {
/* show-deps mode */
if (repo_mode)
rv = repo_show_pkg_deps(&xh, argv[optind]);
else
rv = show_pkg_deps(&xh, argv[optind]);
} else if (show_rdeps) {
/* show-rdeps mode */
rv = show_pkg_revdeps(&xh, argv[optind]);
}
xbps_end(&xh);
exit(rv);
}

209
bin/xbps-query/ownedby.c Normal file
View File

@ -0,0 +1,209 @@
/*-
* Copyright (c) 2010-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fnmatch.h>
#include <dirent.h>
#include <xbps_api.h>
#include "defs.h"
static int
match_files_by_pattern(prop_dictionary_t pkg_filesd,
prop_dictionary_keysym_t key,
int npatterns,
char **patterns,
const char *pkgname)
{
prop_object_iterator_t iter;
prop_array_t array;
prop_object_t obj;
const char *keyname, *filestr, *typestr;
int i;
keyname = prop_dictionary_keysym_cstring_nocopy(key);
array = prop_dictionary_get_keysym(pkg_filesd, key);
if (strcmp(keyname, "files") == 0)
typestr = "regular file";
else if (strcmp(keyname, "dirs") == 0)
typestr = "directory";
else if (strcmp(keyname, "links") == 0)
typestr = "link";
else
typestr = "configuration file";
iter = prop_array_iterator(array);
while ((obj = prop_object_iterator_next(iter))) {
prop_dictionary_get_cstring_nocopy(obj, "file", &filestr);
for (i = 0; i < npatterns; i++) {
if ((xbps_pkgpattern_match(filestr, patterns[i])) ||
(strcmp(filestr, patterns[i]) == 0))
printf("%s: %s (%s)\n", pkgname, filestr, typestr);
}
}
prop_object_iterator_release(iter);
return 0;
}
int
ownedby(struct xbps_handle *xhp, int npatterns, char **patterns)
{
prop_dictionary_t pkg_filesd;
prop_array_t files_keys;
DIR *dirp;
struct dirent *dp;
char *path;
int rv = 0;
unsigned int i, count;
path = xbps_xasprintf("%s/metadata", xhp->metadir);
if (path == NULL)
return -1;
if ((dirp = opendir(path)) == NULL) {
free(path);
return -1;
}
while ((dp = readdir(dirp)) != NULL) {
if ((strcmp(dp->d_name, ".") == 0) ||
(strcmp(dp->d_name, "..") == 0))
continue;
pkg_filesd = xbps_dictionary_from_metadata_plist(xhp,
dp->d_name, XBPS_PKGFILES);
if (pkg_filesd == NULL) {
if (errno == ENOENT)
continue;
rv = -1;
break;
}
files_keys = prop_dictionary_all_keys(pkg_filesd);
count = prop_array_count(files_keys);
for (i = 0; i < count; i++) {
rv = match_files_by_pattern(pkg_filesd,
prop_array_get(files_keys, i),
npatterns, patterns, dp->d_name);
if (rv == -1)
break;
}
prop_object_release(files_keys);
prop_object_release(pkg_filesd);
if (rv == -1)
break;
}
(void)closedir(dirp);
free(path);
return rv;
}
struct ffdata {
int npatterns;
char **patterns;
const char *repouri;
};
static void
repo_match_files_by_pattern(struct xbps_handle *xhp,
prop_dictionary_t pkg_filesd,
struct ffdata *ffd)
{
prop_array_t array;
const char *filestr, *pkgver, *arch;
size_t i;
int x;
prop_dictionary_get_cstring_nocopy(pkg_filesd, "architecture", &arch);
if (!xbps_pkg_arch_match(xhp, arch, NULL))
return;
array = prop_dictionary_get(pkg_filesd, "files");
for (i = 0; i < prop_array_count(array); i++) {
prop_array_get_cstring_nocopy(array, i, &filestr);
for (x = 0; x < ffd->npatterns; x++) {
if ((xbps_pkgpattern_match(filestr, ffd->patterns[x])) ||
(strcmp(filestr, ffd->patterns[x]) == 0)) {
prop_dictionary_get_cstring_nocopy(pkg_filesd,
"pkgver", &pkgver);
printf("%s: %s (%s)\n",
pkgver, filestr, ffd->repouri);
}
}
}
}
static int
repo_ownedby_cb(struct xbps_handle *xhp,
struct xbps_rpool_index *rpi,
void *arg,
bool *done)
{
prop_array_t idxfiles;
struct ffdata *ffd = arg;
char *plist;
unsigned int i;
(void)done;
if ((plist = xbps_pkg_index_files_plist(xhp, rpi->uri)) == NULL)
return ENOMEM;
if ((idxfiles = prop_array_internalize_from_zfile(plist)) == NULL) {
free(plist);
if (errno == ENOENT) {
fprintf(stderr, "%s: index-files missing! "
"ignoring...\n", rpi->uri);
return 0;
}
return errno;
}
free(plist);
ffd->repouri = rpi->uri;
for (i = 0; i < prop_array_count(idxfiles); i++)
repo_match_files_by_pattern(xhp,
prop_array_get(idxfiles, i), ffd);
prop_object_release(idxfiles);
return 0;
}
int
repo_ownedby(struct xbps_handle *xhp, int npatterns, char **patterns)
{
struct ffdata ffd;
ffd.npatterns = npatterns;
ffd.patterns = patterns;
return xbps_rpool_foreach(xhp, repo_ownedby_cb, &ffd);
}

175
bin/xbps-query/search.c Normal file
View File

@ -0,0 +1,175 @@
/*-
* Copyright (c) 2008-2012 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_STRCASESTR
# define _GNU_SOURCE /* for strcasestr(3) */
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <libgen.h>
#include <fnmatch.h>
#include <xbps_api.h>
#include "defs.h"
struct repo_search_data {
int npatterns;
char **patterns;
void *arg;
size_t pkgver_len;
size_t maxcols;
};
static int
repo_longest_pkgver(struct xbps_handle *xhp,
struct xbps_rpool_index *rpi,
void *arg,
bool *done)
{
size_t *len = arg, olen = 0;
(void)done;
if (*len == 0) {
*len = find_longest_pkgver(xhp, rpi->repo);
return 0;
}
olen = find_longest_pkgver(xhp, rpi->repo);
if (olen > *len)
*len = olen;
return 0;
}
static size_t
repo_find_longest_pkgver(struct xbps_handle *xhp)
{
size_t len = 0;
xbps_rpool_foreach(xhp, repo_longest_pkgver, &len);
return len;
}
static int
show_pkg_namedesc(struct xbps_handle *xhp,
prop_object_t obj,
void *arg,
bool *loop_done)
{
struct repo_search_data *rsd = arg;
const char *pkgver, *pkgname, *desc, *arch, *inststr;
char *tmp = NULL, *out = NULL;
size_t x, len;
int i;
(void)xhp;
(void)loop_done;
prop_dictionary_get_cstring_nocopy(obj, "architecture", &arch);
if (!xbps_pkg_arch_match(xhp, arch, NULL))
return 0;
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(obj, "short_desc", &desc);
for (i = 0; i < rsd->npatterns; i++) {
if ((xbps_pkgpattern_match(pkgver, rsd->patterns[i]) == 1) ||
(xbps_pkgpattern_match(desc, rsd->patterns[i]) == 1) ||
(strcasecmp(pkgname, rsd->patterns[i]) == 0) ||
(strcasestr(pkgver, rsd->patterns[i])) ||
(strcasestr(desc, rsd->patterns[i]))) {
tmp = calloc(1, rsd->pkgver_len + 1);
assert(tmp);
memcpy(tmp, pkgver, rsd->pkgver_len);
for (x = strlen(tmp); x < rsd->pkgver_len; x++)
tmp[x] = ' ';
tmp[x] = '\0';
if (xbps_pkgdb_get_pkgd_by_pkgver(xhp, pkgver))
inststr = "[*]";
else
inststr = "[-]";
len = strlen(inststr) + strlen(tmp) + strlen(desc) + 1;
if (len > rsd->maxcols) {
out = malloc(rsd->maxcols+1);
assert(out);
snprintf(out, rsd->maxcols-3, "%s %s %s",
inststr, tmp, desc);
strncat(out, "...", rsd->maxcols);
out[rsd->maxcols+1] = '\0';
printf("%s\n", out);
free(out);
} else {
printf("%s %s %s\n", inststr, tmp, desc);
}
}
}
return 0;
}
static int
repo_search_pkgs_cb(struct xbps_handle *xhp,
struct xbps_rpool_index *rpi,
void *arg,
bool *done)
{
struct repo_search_data *rsd = arg;
(void)done;
(void)xbps_callback_array_iter(xhp, rpi->repo, show_pkg_namedesc, rsd);
return 0;
}
int
repo_search(struct xbps_handle *xhp, int npatterns, char **patterns)
{
struct repo_search_data rsd;
int rv;
rsd.npatterns = npatterns;
rsd.patterns = patterns;
rsd.pkgver_len = repo_find_longest_pkgver(xhp);
rsd.maxcols = get_maxcols();
rv = xbps_rpool_foreach(xhp, repo_search_pkgs_cb, &rsd);
if (rv != 0 && rv != ENOTSUP)
fprintf(stderr, "Failed to initialize rpool: %s\n",
strerror(rv));
return rv;
}

View File

@ -0,0 +1,94 @@
/*-
* Copyright (c) 2009-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <xbps_api.h>
#include "defs.h"
int
show_pkg_deps(struct xbps_handle *xhp, const char *pkgname)
{
prop_dictionary_t propsd;
int rv = 0;
assert(pkgname != NULL);
/*
* Check for props.plist metadata file.
*/
propsd = xbps_dictionary_from_metadata_plist(xhp,
pkgname, XBPS_PKGPROPS);
if (propsd == NULL)
return errno;
rv = xbps_callback_array_iter_in_dict(xhp, propsd, "run_depends",
list_strings_sep_in_array, NULL);
prop_object_release(propsd);
return rv;
}
int
show_pkg_revdeps(struct xbps_handle *xhp, const char *pkgname)
{
prop_dictionary_t pkgd;
int rv = 0;
pkgd = xbps_find_virtualpkg_dict_installed(xhp, pkgname, false);
if (pkgd == NULL) {
pkgd = xbps_find_pkg_dict_installed(xhp, pkgname, false);
if (pkgd == NULL)
return 0;
}
rv = xbps_callback_array_iter_in_dict(xhp, pkgd, "requiredby",
list_strings_sep_in_array, NULL);
return rv;
}
int
repo_show_pkg_deps(struct xbps_handle *xhp, const char *pattern)
{
prop_dictionary_t pkgd;
if (xbps_pkgpattern_version(pattern))
pkgd = xbps_rpool_find_pkg(xhp, pattern, true, false);
else
pkgd = xbps_rpool_find_pkg(xhp, pattern, false, true);
if (pkgd == NULL)
return errno;
(void)xbps_callback_array_iter_in_dict(xhp, pkgd,
"run_depends", list_strings_sep_in_array, NULL);
return 0;
}

View File

@ -0,0 +1,259 @@
/*-
* Copyright (c) 2008-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <libgen.h>
#include <fnmatch.h>
#include <xbps_api.h>
#include "defs.h"
static void
print_value_obj(const char *keyname, prop_object_t obj, bool raw)
{
const char *value;
size_t i;
char size[8];
switch (prop_object_type(obj)) {
case PROP_TYPE_STRING:
if (!raw)
printf("%s: ", keyname);
printf("%s\n", prop_string_cstring_nocopy(obj));
break;
case PROP_TYPE_NUMBER:
if (!raw)
printf("%s: ", keyname);
if (xbps_humanize_number(size,
(int64_t)prop_number_unsigned_integer_value(obj)) == -1)
printf("%ju\n",
prop_number_unsigned_integer_value(obj));
else
printf("%s\n", size);
break;
case PROP_TYPE_BOOL:
if (!raw)
printf("%s: ", keyname);
printf("%s\n", prop_bool_true(obj) ? "yes" : "no");
break;
case PROP_TYPE_ARRAY:
if (!raw)
printf("%s:\n", keyname);
for (i = 0; i < prop_array_count(obj); i++) {
prop_array_get_cstring_nocopy(obj, i, &value);
printf("%s%s%s", !raw ? "\t" : "", value,
!raw ? "\n" : " ");
}
if (raw)
printf("\n");
break;
default:
xbps_warn_printf("unknown obj type (key %s)\n",
keyname);
break;
}
}
void
show_pkg_info_one(prop_dictionary_t d, const char *keys)
{
prop_object_t obj;
char *key, *p, *saveptr;
if (strchr(keys, ',') == NULL) {
obj = prop_dictionary_get(d, keys);
if (obj == NULL)
return;
print_value_obj(keys, obj, true);
return;
}
key = strdup(keys);
if (key == NULL)
abort();
for ((p = strtok_r(key, ",", &saveptr)); p;
(p = strtok_r(NULL, ",", &saveptr))) {
obj = prop_dictionary_get(d, p);
if (obj == NULL)
continue;
print_value_obj(p, obj, true);
}
free(key);
}
void
show_pkg_info(prop_dictionary_t dict)
{
prop_array_t all_keys;
prop_object_t obj, keysym;
const char *keyname;
size_t i;
all_keys = prop_dictionary_all_keys(dict);
for (i = 0; i < prop_array_count(all_keys); i++) {
keysym = prop_array_get(all_keys, i);
keyname = prop_dictionary_keysym_cstring_nocopy(keysym);
obj = prop_dictionary_get_keysym(dict, keysym);
/* ignore run_depends, it's shown via 'show-deps' */
if (strcmp(keyname, "run_depends") == 0)
continue;
print_value_obj(keyname, obj, false);
}
prop_object_release(all_keys);
}
int
show_pkg_files(prop_dictionary_t filesd)
{
prop_array_t array, allkeys;
prop_object_t obj;
prop_dictionary_keysym_t ksym;
const char *keyname, *file;
size_t i, x;
allkeys = prop_dictionary_all_keys(filesd);
for (i = 0; i < prop_array_count(allkeys); i++) {
ksym = prop_array_get(allkeys, i);
keyname = prop_dictionary_keysym_cstring_nocopy(ksym);
if (strcmp(keyname, "dirs") == 0)
continue;
array = prop_dictionary_get(filesd, keyname);
if (array == NULL || prop_array_count(array) == 0)
continue;
for (x = 0; x < prop_array_count(array); x++) {
obj = prop_array_get(array, x);
prop_dictionary_get_cstring_nocopy(obj, "file", &file);
printf("%s", file);
if (prop_dictionary_get_cstring_nocopy(obj,
"target", &file))
printf(" -> %s", file);
printf("\n");
}
}
prop_object_release(allkeys);
return 0;
}
int
show_pkg_info_from_metadir(struct xbps_handle *xhp,
const char *pkgname,
const char *option)
{
prop_dictionary_t d, pkgdb_d;
const char *instdate, *pname;
bool autoinst;
d = xbps_dictionary_from_metadata_plist(xhp, pkgname, XBPS_PKGPROPS);
if (d == NULL)
return EINVAL;
prop_dictionary_get_cstring_nocopy(d, "pkgname", &pname);
pkgdb_d = xbps_pkgdb_get_pkgd(xhp, pname, false);
if (pkgdb_d == NULL) {
prop_object_release(d);
return EINVAL;
}
if (prop_dictionary_get_cstring_nocopy(pkgdb_d,
"install-date", &instdate))
prop_dictionary_set_cstring_nocopy(d, "install-date",
instdate);
if (prop_dictionary_get_bool(pkgdb_d, "automatic-install", &autoinst))
prop_dictionary_set_bool(d, "automatic-install", autoinst);
if (option == NULL)
show_pkg_info(d);
else
show_pkg_info_one(d, option);
prop_object_release(d);
return 0;
}
int
show_pkg_files_from_metadir(struct xbps_handle *xhp, const char *pkgname)
{
prop_dictionary_t d;
int rv = 0;
d = xbps_dictionary_from_metadata_plist(xhp, pkgname, XBPS_PKGFILES);
if (d == NULL)
return EINVAL;
rv = show_pkg_files(d);
prop_object_release(d);
return rv;
}
int
repo_show_pkg_info(struct xbps_handle *xhp,
const char *pattern,
const char *option)
{
prop_dictionary_t pkgd;
if (xbps_pkgpattern_version(pattern))
pkgd = xbps_rpool_find_pkg(xhp, pattern, true, false);
else
pkgd = xbps_rpool_find_pkg(xhp, pattern, false, true);
if (pkgd == NULL)
return errno;
if (option)
show_pkg_info_one(pkgd, option);
else
show_pkg_info(pkgd);
return 0;
}
int
repo_show_pkg_files(struct xbps_handle *xhp, const char *pkg)
{
prop_dictionary_t pkgd;
pkgd = xbps_rpool_dictionary_metadata_plist(xhp, pkg,
"./files.plist");
if (pkgd == NULL) {
if (errno != ENOTSUP && errno != ENOENT) {
fprintf(stderr, "Unexpected error: %s\n",
strerror(errno));
return errno;
}
}
return show_pkg_files(pkgd);
}

View File

@ -0,0 +1,8 @@
TOPDIR = ../..
-include $(TOPDIR)/config.mk
BIN = xbps-reconfigure
OBJS = main.o ../xbps-install/state_cb.o
#MAN = $(BIN).8
include $(TOPDIR)/mk/prog.mk

134
bin/xbps-reconfigure/main.c Normal file
View File

@ -0,0 +1,134 @@
/*-
* Copyright (c) 2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <xbps_api.h>
#include "../xbps-bin/defs.h"
static void __attribute__((noreturn))
usage(bool fail)
{
fprintf(stdout,
"Usage: xbps-reconfigure [OPTIONS] [PKGNAME...]\n\n"
"OPTIONS\n"
" -a --all Process all packages\n"
" -C --config <file> Full path to configuration file\n"
" -d --debug Debug mode shown to stderr\n"
" -f --force Force reconfiguration\n"
" -h --help Print usage help\n"
" -r --rootdir <dir> Full path to rootdir\n"
" -v --verbose Verbose messages\n"
" -V --version Show XBPS version\n");
exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
int
main(int argc, char **argv)
{
const char *shortopts = "aC:dfhr:Vv";
const struct option longopts[] = {
{ "all", no_argument, NULL, 'a' },
{ "config", required_argument, NULL, 'C' },
{ "debug", no_argument, NULL, 'd' },
{ "force", no_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
{ "rootdir", required_argument, NULL, 'r' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
struct xbps_handle xh;
const char *conffile = NULL, *rootdir = NULL;
int c, i, rv, flags = 0;
bool all = false;
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
switch (c) {
case 'a':
all = true;
break;
case 'C':
conffile = optarg;
break;
case 'd':
flags |= XBPS_FLAG_DEBUG;
break;
case 'f':
flags |= XBPS_FLAG_FORCE_CONFIGURE;
break;
case 'h':
usage(false);
/* NOTREACHED */
case 'r':
rootdir = optarg;
break;
case 'v':
flags |= XBPS_FLAG_VERBOSE;
break;
case 'V':
printf("%s\n", XBPS_RELVER);
exit(EXIT_SUCCESS);
case '?':
default:
usage(true);
/* NOTREACHED */
}
}
if (!all && (argc == optind))
usage(true);
memset(&xh, 0, sizeof(xh));
xh.state_cb = state_cb;
xh.rootdir = rootdir;
xh.conffile = conffile;
xh.flags = flags;
if ((rv = xbps_init(&xh)) != 0) {
xbps_error_printf("Failed to initialize libxbps: %s\n",
strerror(rv));
exit(EXIT_FAILURE);
}
if (all) {
rv = xbps_configure_packages(&xh, true);
} else {
for (i = optind; i < argc; i++) {
rv = xbps_configure_pkg(&xh, argv[i],
true, false, true);
if (rv != 0)
fprintf(stderr, "Failed to reconfigure "
"`%s': %s\n", argv[i], strerror(rv));
}
}
xbps_end(&xh);
exit(rv ? EXIT_FAILURE : EXIT_SUCCESS);
}

12
bin/xbps-remove/Makefile Normal file
View File

@ -0,0 +1,12 @@
TOPDIR = ../..
-include $(TOPDIR)/config.mk
BIN = xbps-remove
OBJS = main.o
OBJS += ../xbps-install/question.o
OBJS += ../xbps-install/util.o
OBJS += ../xbps-install/transaction.o
OBJS += ../xbps-install/state_cb.o
#MAN = $(BIN).8
include $(TOPDIR)/mk/prog.mk

347
bin/xbps-remove/main.c Normal file
View File

@ -0,0 +1,347 @@
/*-
* Copyright (c) 2008-2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include <unistd.h>
#include <getopt.h>
#include <dirent.h>
#include <xbps_api.h>
#include "../xbps-install/defs.h"
static struct xbps_handle xh;
static void __attribute__((noreturn))
usage(bool fail)
{
fprintf(stdout,
"Usage: xbps-remove [OPTIONS] [PKGNAME...]\n\n"
"OPTIONS\n"
" -C --config <file> Full path to configuration file\n"
" -c --cachedir <dir> Full path to cachedir\n"
" -d --debug Debug mode shown to stderr\n"
" -f --force Force package files removal\n"
" -h --help Print help usage\n"
" -i --ignore-revdeps Ignore reverse deps\n"
" -n --dry-run Dry-run mode\n"
" -O --clean-cache Remove obsolete packages in cachedir\n"
" -o --remove-orphans Remove package orphans\n"
" -p --print-format <fmt> Print format for dry-run mode\n"
" -R --recursive Recursively remove dependencies\n"
" -r --rootdir <dir> Full path to rootdir\n"
" -v --verbose Verbose messages\n"
" -y --yes Assume yes to all questions\n"
" -V --version Show XBPS version\n");
exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
static void __attribute__((noreturn))
cleanup_sighandler(int signum)
{
xbps_end(&xh);
_exit(signum);
}
static int
cachedir_clean(struct xbps_handle *xhp)
{
prop_dictionary_t pkg_propsd, repo_pkgd;
DIR *dirp;
struct dirent *dp;
const char *pkgver, *rsha256;
char *binpkg, *ext;
int rv = 0;
if ((dirp = opendir(xhp->cachedir)) == NULL)
return 0;
while ((dp = readdir(dirp)) != NULL) {
if ((strcmp(dp->d_name, ".") == 0) ||
(strcmp(dp->d_name, "..") == 0))
continue;
/* only process xbps binary packages, ignore something else */
if ((ext = strrchr(dp->d_name, '.')) == NULL)
continue;
if (strcmp(ext, ".xbps")) {
printf("ignoring unknown file: %s\n", dp->d_name);
continue;
}
/* Internalize props.plist dictionary from binary pkg */
binpkg = xbps_xasprintf("%s/%s", xhp->cachedir, dp->d_name);
assert(binpkg != NULL);
pkg_propsd = xbps_dictionary_metadata_plist_by_url(binpkg,
"./props.plist");
if (pkg_propsd == NULL) {
xbps_error_printf("Failed to read from %s: %s\n",
dp->d_name, strerror(errno));
free(binpkg);
rv = errno;
break;
}
prop_dictionary_get_cstring_nocopy(pkg_propsd, "pkgver", &pkgver);
/*
* Remove binary pkg if it's not registered in any repository
* or if hash doesn't match.
*/
repo_pkgd = xbps_rpool_find_pkg_exact(xhp, pkgver);
if (repo_pkgd) {
prop_dictionary_get_cstring_nocopy(repo_pkgd,
"filename-sha256", &rsha256);
if (xbps_file_hash_check(binpkg, rsha256) == ERANGE) {
printf("Removed %s from cachedir (sha256 mismatch)\n",
dp->d_name);
if (unlink(binpkg) == -1)
fprintf(stderr, "Failed to remove "
"`%s': %s\n", binpkg,
strerror(errno));
}
free(binpkg);
continue;
}
printf("Removed %s from cachedir (obsolete)\n", dp->d_name);
if (unlink(binpkg) == -1)
fprintf(stderr, "Failed to remove `%s': %s\n",
binpkg, strerror(errno));
free(binpkg);
}
closedir(dirp);
return rv;
}
static int
remove_pkg(struct xbps_handle *xhp, const char *pkgname, size_t cols,
bool recursive)
{
prop_dictionary_t pkgd;
prop_array_t reqby;
const char *pkgver;
size_t x;
int rv;
rv = xbps_transaction_remove_pkg(xhp, pkgname, recursive);
if (rv == EEXIST) {
/* pkg has revdeps */
pkgd = xbps_find_pkg_dict_installed(xhp, pkgname, false);
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
reqby = prop_dictionary_get(pkgd, "requiredby");
printf("WARNING: %s IS REQUIRED BY %u PACKAGE%s:\n\n",
pkgver, prop_array_count(reqby),
prop_array_count(reqby) > 1 ? "S" : "");
for (x = 0; x < prop_array_count(reqby); x++) {
prop_array_get_cstring_nocopy(reqby, x, &pkgver);
print_package_line(pkgver, cols, false);
}
printf("\n\n");
print_package_line(NULL, cols, true);
return rv;
} else if (rv == ENOENT) {
printf("Package `%s' is not currently installed.\n", pkgname);
return 0;
} else if (rv != 0) {
xbps_error_printf("Failed to queue `%s' for removing: %s\n",
pkgname, strerror(rv));
return rv;
}
return 0;
}
int
main(int argc, char **argv)
{
const char *shortopts = "C:c:dfhinOop:Rr:vVy";
struct option longopts[] = {
{ "config", required_argument, NULL, 'C' },
{ "cachedir", required_argument, NULL, 'c' },
{ "debug", no_argument, NULL, 'd' },
{ "force", no_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
{ "ignore-revdeps", no_argument, NULL, 'i' },
{ "dry-run", no_argument, NULL, 'n' },
{ "clean-cache", no_argument, NULL, 'O' },
{ "remove-orphans", no_argument, NULL, 'o' },
{ "print-format", required_argument, NULL, 'p' },
{ "recursive", no_argument, NULL, 'R' },
{ "rootdir", required_argument, NULL, 'r' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ "yes", no_argument, NULL, 'y' },
{ NULL, 0, NULL, 0 }
};
struct sigaction sa;
const char *rootdir, *cachedir, *conffile, *pformat;
int i, c, flags, rv;
bool yes, drun, recursive, ignore_revdeps, clean_cache;
bool orphans, reqby_force;
size_t maxcols;
rootdir = cachedir = conffile = pformat = NULL;
flags = rv = 0;
drun = recursive = ignore_revdeps = clean_cache = false;
reqby_force = yes = orphans = false;
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
switch (c) {
case 'C':
conffile = optarg;
break;
case 'c':
cachedir = optarg;
break;
case 'd':
flags |= XBPS_FLAG_DEBUG;
break;
case 'f':
flags |= XBPS_FLAG_FORCE_REMOVE_FILES;
break;
case 'h':
usage(false);
/* NOTREACHED */
case 'i':
ignore_revdeps = true;
break;
case 'n':
drun = true;
break;
case 'O':
clean_cache = true;
break;
case 'o':
orphans = true;
break;
case 'p':
pformat = optarg;
break;
case 'R':
recursive = true;
break;
case 'r':
rootdir = optarg;
break;
case 'v':
flags |= XBPS_FLAG_VERBOSE;
break;
case 'V':
printf("%s\n", XBPS_RELVER);
exit(EXIT_SUCCESS);
case 'y':
yes = true;
break;
case '?':
default:
usage(true);
/* NOTREACHED */
}
}
if (!clean_cache && !orphans && (argc == optind))
usage(true);
/*
* Initialize libxbps.
*/
memset(&xh, 0, sizeof(xh));
xh.state_cb = state_cb;
xh.rootdir = rootdir;
xh.cachedir = cachedir;
xh.conffile = conffile;
xh.flags = flags;
if ((rv = xbps_init(&xh)) != 0) {
xbps_error_printf("Failed to initialize libxbps: %s\n",
strerror(rv));
exit(EXIT_FAILURE);
}
/*
* Register a signal handler to clean up resources used by libxbps.
*/
memset(&sa, 0, sizeof(sa));
sa.sa_handler = cleanup_sighandler;
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
maxcols = get_maxcols();
/*
* Check that we have write permission on rootdir, metadir
* and cachedir.
*/
if ((!drun && ((access(xh.rootdir, W_OK) == -1) ||
(access(xh.metadir, W_OK) == -1) ||
(access(xh.cachedir, W_OK) == -1)))) {
if (errno != ENOENT) {
fprintf(stderr, "Not enough permissions on "
"rootdir/cachedir/metadir: %s\n",
strerror(errno));
rv = errno;
goto out;
}
}
if (clean_cache) {
rv = cachedir_clean(&xh);
if (rv != 0)
goto out;
}
if (orphans) {
if ((rv = xbps_transaction_autoremove_pkgs(&xh)) != 0) {
if (rv != ENOENT) {
fprintf(stderr, "Failed to remove package "
"orphans: %s\n", strerror(rv));
goto out;
}
}
}
for (i = optind; i < argc; i++) {
rv = remove_pkg(&xh, argv[i], maxcols, recursive);
if (rv == 0)
continue;
else if (rv != EEXIST)
goto out;
else
reqby_force = true;
}
if (reqby_force && !ignore_revdeps) {
rv = EINVAL;
goto out;
}
if (orphans || argc)
rv = exec_transaction(&xh, maxcols, yes, drun);
out:
xbps_end(&xh);
exit(rv);
}

8
bin/xbps-rindex/Makefile Normal file
View File

@ -0,0 +1,8 @@
TOPDIR = ../..
-include $(TOPDIR)/config.mk
BIN = xbps-rindex
OBJS = main.o index.o index-files.o remove-obsoletes.o common.o
#MAN = $(BIN).8
include $(TOPDIR)/mk/prog.mk

70
bin/xbps-rindex/common.c Normal file
View File

@ -0,0 +1,70 @@
/*-
* Copyright (c) 2012 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 <sys/stat.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <libgen.h>
#include <assert.h>
#include <xbps_api.h>
#include "defs.h"
int
remove_pkg(const char *repodir, const char *arch, const char *file)
{
char *filepath;
int rv;
/* Remove real binpkg */
filepath = xbps_xasprintf("%s/%s/%s", repodir, arch, file);
assert(filepath);
if (remove(filepath) == -1) {
rv = errno;
xbps_error_printf("failed to remove old binpkg `%s': %s\n",
file, strerror(rv));
free(filepath);
return rv;
}
free(filepath);
/* Remove symlink to binpkg */
filepath = xbps_xasprintf("%s/%s", repodir, file);
assert(filepath);
if (remove(filepath) == -1) {
rv = errno;
xbps_error_printf("failed to remove old binpkg `%s': %s\n",
file, strerror(rv));
free(filepath);
return rv;
}
free(filepath);
return 0;
}

45
bin/xbps-rindex/defs.h Normal file
View File

@ -0,0 +1,45 @@
/*-
* Copyright (c) 2012 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.
*/
#ifndef _XBPS_RINDEX_DEFS_H_
#define _XBPS_RINDEX_DEFS_H_
#include <xbps_api.h>
/* From common.c */
int remove_pkg(const char *, const char *, const char *);
/* From index.c */
int index_add(struct xbps_handle *, int, char **);
int index_clean(struct xbps_handle *, const char *);
/* From index-files.c */
int index_files_add(struct xbps_handle *, int, char **);
int index_files_clean(struct xbps_handle *, const char *);
/* From remove-obsoletes.c */
int remove_obsoletes(struct xbps_handle *, const char *);
#endif /* !_XBPS_RINDEX_DEFS_H_ */

View File

@ -0,0 +1,359 @@
/*-
* Copyright (c) 2012 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 <stdbool.h>
#include <errno.h>
#include <libgen.h>
#include <assert.h>
#include <xbps_api.h>
#include "defs.h"
int
index_files_clean(struct xbps_handle *xhp, const char *repodir)
{
prop_object_t obj;
prop_array_t idx, idxfiles, obsoletes;
char *plist, *plistf, *pkgver, *str;
const char *p, *arch, *ipkgver, *iarch;
size_t x, i;
int rv = 0;
bool flush = false;
plist = plistf = pkgver = str = NULL;
idx = idxfiles = obsoletes = NULL;
/* Internalize index-files.plist if found */
if ((plistf = xbps_pkg_index_files_plist(xhp, repodir)) == NULL)
return EINVAL;
if ((idxfiles = prop_array_internalize_from_zfile(plistf)) == NULL) {
free(plistf);
return 0;
}
/* Internalize index.plist */
if ((plist = xbps_pkg_index_plist(xhp, repodir)) == NULL) {
rv = EINVAL;
goto out;
}
if ((idx = prop_array_internalize_from_zfile(plist)) == NULL) {
rv = EINVAL;
goto out;
}
printf("Cleaning `%s' index-files, please wait...\n", repodir);
/*
* Iterate over index-files array to find obsolete entries.
*/
obsoletes = prop_array_create();
assert(obsoletes);
for (x = 0; x < prop_array_count(idxfiles); x++) {
obj = prop_array_get(idxfiles, x);
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &ipkgver);
prop_dictionary_get_cstring_nocopy(obj, "architecture", &iarch);
if (xbps_find_pkg_in_array_by_pkgver(xhp, idx, ipkgver, iarch)) {
/* pkg found, do nothing */
continue;
}
if ((str = xbps_xasprintf("%s,%s", ipkgver, iarch)) == NULL) {
rv = ENOMEM;
goto out;
}
if (!prop_array_add_cstring(obsoletes, str)) {
free(str);
rv = EINVAL;
goto out;
}
free(str);
}
/*
* Iterate over the obsoletes and array and remove entries
* from index-files array.
*/
for (i = 0; i < prop_array_count(obsoletes); i++) {
prop_array_get_cstring_nocopy(obsoletes, i, &p);
pkgver = strdup(p);
for (x = 0; x < strlen(p); x++) {
if ((pkgver[x] = p[x]) == ',') {
pkgver[x] = '\0';
break;
}
}
arch = strchr(p, ',') + 1;
if (!xbps_remove_pkg_from_array_by_pkgver(
xhp, idxfiles, pkgver, arch)) {
free(pkgver);
rv = EINVAL;
goto out;
}
printf("index-files: removed obsolete entry `%s' "
"(%s)\n", pkgver, arch);
free(pkgver);
flush = true;
}
/* Externalize index-files array to plist when necessary */
if (flush && !prop_array_externalize_to_zfile(idxfiles, plistf))
rv = errno;
printf("index-files: %u packages registered.\n",
prop_array_count(idxfiles));
out:
if (obsoletes)
prop_object_release(obsoletes);
if (idx)
prop_object_release(idx);
if (idxfiles)
prop_object_release(idxfiles);
if (plist)
free(plist);
if (plistf)
free(plistf);
return rv;
}
int
index_files_add(struct xbps_handle *xhp, int argc, char **argv)
{
prop_array_t idxfiles = NULL;
prop_object_t obj, fileobj;
prop_dictionary_t pkgprops, pkg_filesd, pkgd;
prop_array_t files, pkg_cffiles, pkg_files, pkg_links;
const char *binpkg, *pkgver, *arch;
char *plist, *repodir, *p;
size_t x;
int i, rv = 0;
bool found, flush;
found = flush = false;
plist = repodir = p = NULL;
obj = fileobj = NULL;
pkgprops = pkg_filesd = pkgd = NULL;
files = NULL;
if ((p = strdup(argv[0])) == NULL) {
rv = ENOMEM;
goto out;
}
repodir = dirname(p);
if ((plist = xbps_pkg_index_files_plist(xhp, repodir)) == NULL) {
rv = ENOMEM;
goto out;
}
/*
* Internalize index-files.plist if found and process argv.
*/
if ((idxfiles = prop_array_internalize_from_zfile(plist)) == NULL) {
if (errno == ENOENT) {
idxfiles = prop_array_create();
assert(idxfiles);
} else {
rv = errno;
goto out;
}
}
for (i = 0; i < argc; i++) {
found = false;
pkgprops = xbps_dictionary_metadata_plist_by_url(argv[i],
"./props.plist");
if (pkgprops == NULL) {
fprintf(stderr, "index-files: cannot internalize "
"%s props.plist: %s\n", argv[i], strerror(errno));
continue;
}
prop_dictionary_get_cstring_nocopy(pkgprops,
"filename", &binpkg);
prop_dictionary_get_cstring_nocopy(pkgprops,
"pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(pkgprops,
"architecture", &arch);
if (xbps_find_pkg_in_array_by_pkgver(xhp, idxfiles,
pkgver, arch)) {
fprintf(stderr, "index-files: skipping `%s' (%s), "
"already registered.\n", pkgver, arch);
prop_object_release(pkgprops);
pkgprops = NULL;
continue;
}
/* internalize files.plist from binary package archive */
pkg_filesd = xbps_dictionary_metadata_plist_by_url(argv[i],
"./files.plist");
if (pkg_filesd == NULL) {
prop_object_release(pkgprops);
rv = EINVAL;
goto out;
}
/* Find out if binary pkg stored in index contain any file */
pkg_cffiles = prop_dictionary_get(pkg_filesd, "conf_files");
if (pkg_cffiles != NULL && prop_array_count(pkg_cffiles))
found = true;
else
pkg_cffiles = NULL;
pkg_files = prop_dictionary_get(pkg_filesd, "files");
if (pkg_files != NULL && prop_array_count(pkg_files))
found = true;
else
pkg_files = NULL;
pkg_links = prop_dictionary_get(pkg_filesd, "links");
if (pkg_links != NULL && prop_array_count(pkg_links))
found = true;
else
pkg_links = NULL;
/* If pkg does not contain any file, ignore it */
if (!found) {
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
continue;
}
/* create pkg dictionary */
if ((pkgd = prop_dictionary_create()) == NULL) {
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
rv = EINVAL;
goto out;
}
/* add pkgver and architecture objects into pkg dictionary */
if (!prop_dictionary_set_cstring(pkgd, "architecture", arch)) {
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
prop_object_release(pkgd);
rv = EINVAL;
goto out;
}
if (!prop_dictionary_set_cstring(pkgd, "pkgver", pkgver)) {
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
prop_object_release(pkgd);
rv = EINVAL;
goto out;
}
/* add files array obj into pkg dictionary */
if ((files = prop_array_create()) == NULL) {
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
prop_object_release(pkgd);
rv = EINVAL;
goto out;
}
if (!prop_dictionary_set(pkgd, "files", files)) {
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
prop_object_release(files);
prop_object_release(pkgd);
rv = EINVAL;
goto out;
}
/* add conf_files in pkgd */
if (pkg_cffiles != NULL) {
for (x = 0; x < prop_array_count(pkg_cffiles); x++) {
obj = prop_array_get(pkg_cffiles, x);
fileobj = prop_dictionary_get(obj, "file");
if (!prop_array_add(files, fileobj)) {
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
prop_object_release(files);
prop_object_release(pkgd);
rv = EINVAL;
goto out;
}
}
}
/* add files array in pkgd */
if (pkg_files != NULL) {
for (x = 0; x < prop_array_count(pkg_files); x++) {
obj = prop_array_get(pkg_files, x);
fileobj = prop_dictionary_get(obj, "file");
if (!prop_array_add(files, fileobj)) {
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
prop_object_release(files);
prop_object_release(pkgd);
rv = EINVAL;
goto out;
}
}
}
/* add links array in pkgd */
if (pkg_links != NULL) {
for (x = 0; x < prop_array_count(pkg_links); x++) {
obj = prop_array_get(pkg_links, x);
fileobj = prop_dictionary_get(obj, "file");
if (!prop_array_add(files, fileobj)) {
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
prop_object_release(files);
prop_object_release(pkgd);
rv = EINVAL;
goto out;
}
}
}
/* add pkgd into the index-files array */
if (!prop_array_add(idxfiles, pkgd)) {
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
prop_object_release(files);
prop_object_release(pkgd);
rv = EINVAL;
goto out;
}
flush = true;
printf("index-files: added `%s' (%s)\n", pkgver, arch);
prop_object_release(pkgprops);
prop_object_release(pkg_filesd);
prop_object_release(files);
prop_object_release(pkgd);
pkgprops = pkg_filesd = pkgd = NULL;
files = NULL;
}
if (flush && !prop_array_externalize_to_zfile(idxfiles, plist)) {
fprintf(stderr, "failed to externalize %s: %s\n",
plist, strerror(errno));
rv = errno;
}
printf("index-files: %u packages registered.\n",
prop_array_count(idxfiles));
out:
if (p)
free(p);
if (plist)
free(plist);
if (idxfiles)
prop_object_release(idxfiles);
return rv;
}

325
bin/xbps-rindex/index.c Normal file
View File

@ -0,0 +1,325 @@
/*-
* Copyright (c) 2012 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 <sys/stat.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <libgen.h>
#include <assert.h>
#include <xbps_api.h>
#include "defs.h"
/*
* Removes stalled pkg entries in repository's index.plist file, if any
* binary package cannot be read (unavailable, not enough perms, etc).
*/
int
index_clean(struct xbps_handle *xhp, const char *repodir)
{
prop_array_t array;
prop_dictionary_t pkgd;
const char *filen, *pkgver, *arch;
char *plist;
size_t i, idx = 0;
int rv = 0;
bool flush = false;
if ((plist = xbps_pkg_index_plist(xhp, repodir)) == NULL)
return -1;
array = prop_array_internalize_from_zfile(plist);
if (array == NULL) {
if (errno != ENOENT) {
xbps_error_printf("xbps-repo: cannot read `%s': %s\n",
plist, strerror(errno));
free(plist);
return -1;
} else {
free(plist);
return 0;
}
}
if (chdir(repodir) == -1) {
fprintf(stderr, "cannot chdir to %s: %s\n",
repodir, strerror(errno));
rv = errno;
goto out;
}
printf("Cleaning `%s' index, please wait...\n", repodir);
again:
for (i = idx; i < prop_array_count(array); i++) {
pkgd = prop_array_get(array, i);
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(pkgd, "filename", &filen);
prop_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch);
if (access(filen, R_OK) == -1) {
printf("index: removed obsolete entry `%s' (%s)\n",
pkgver, arch);
prop_array_remove(array, i);
flush = true;
idx = i;
goto again;
}
}
if (flush && !prop_array_externalize_to_zfile(array, plist)) {
rv = errno;
goto out;
}
printf("index: %u packages registered.\n", prop_array_count(array));
out:
free(plist);
prop_object_release(array);
return rv;
}
/*
* Adds a binary package into the index and removes old binary package
* and entry when it's necessary.
*/
int
index_add(struct xbps_handle *xhp, int argc, char **argv)
{
prop_array_t idx = NULL;
prop_dictionary_t newpkgd = NULL, curpkgd;
struct stat st;
const char *pkgname, *version, *regver, *oldfilen, *oldpkgver;
const char *arch, *oldarch;
char *sha256, *filen, *repodir, *buf, *buf2;
char *tmpfilen = NULL, *tmprepodir = NULL, *plist = NULL;
int i, ret = 0, rv = 0;
bool flush = false;
if ((tmprepodir = strdup(argv[0])) == NULL) {
rv = ENOMEM;
goto out;
}
repodir = dirname(tmprepodir);
/* Internalize plist file or create it if doesn't exist */
if ((plist = xbps_pkg_index_plist(xhp, repodir)) == NULL)
return -1;
if ((idx = prop_array_internalize_from_zfile(plist)) == NULL) {
if (errno != ENOENT) {
xbps_error_printf("xbps-repo: cannot read `%s': %s\n",
plist, strerror(errno));
rv = -1;
goto out;
} else {
idx = prop_array_create();
assert(idx);
}
}
/*
* Process all packages specified in argv.
*/
for (i = 0; i < argc; i++) {
if ((tmpfilen = strdup(argv[i])) == NULL) {
rv = ENOMEM;
goto out;
}
filen = basename(tmpfilen);
/*
* Read metadata props plist dictionary from binary package.
*/
newpkgd = xbps_dictionary_metadata_plist_by_url(argv[i],
"./props.plist");
if (newpkgd == NULL) {
xbps_error_printf("failed to read %s metadata for `%s',"
" skipping!\n", XBPS_PKGPROPS, argv[i]);
free(tmpfilen);
continue;
}
prop_dictionary_get_cstring_nocopy(newpkgd, "pkgname",
&pkgname);
prop_dictionary_get_cstring_nocopy(newpkgd, "version",
&version);
prop_dictionary_get_cstring_nocopy(newpkgd, "architecture",
&arch);
/*
* Check if this package exists already in the index, but first
* checking the version. If current package version is greater
* than current registered package, update the index; otherwise
* pass to the next one.
*/
curpkgd =
xbps_find_pkg_in_array_by_name(xhp, idx, pkgname, arch);
if (curpkgd == NULL) {
if (errno && errno != ENOENT) {
prop_object_release(newpkgd);
free(tmpfilen);
rv = errno;
goto out;
}
} else {
prop_dictionary_get_cstring_nocopy(curpkgd,
"filename", &oldfilen);
prop_dictionary_get_cstring_nocopy(curpkgd,
"pkgver", &oldpkgver);
prop_dictionary_get_cstring_nocopy(curpkgd,
"architecture", &oldarch);
prop_dictionary_get_cstring_nocopy(curpkgd,
"version", &regver);
ret = xbps_cmpver(version, regver);
if (ret == 0) {
/* Same version */
fprintf(stderr, "index: skipping `%s-%s' "
"(%s), already registered.\n",
pkgname, version, arch);
prop_object_release(newpkgd);
free(tmpfilen);
continue;
} else if (ret == -1) {
/*
* Index version is greater, remove current
* package.
*/
buf = xbps_xasprintf("`%s' (%s)",
oldpkgver, oldarch);
assert(buf);
rv = remove_pkg(repodir,
oldarch, oldfilen);
if (rv != 0) {
prop_object_release(newpkgd);
free(tmpfilen);
free(buf);
goto out;
}
printf("index: removed obsolete binpkg %s.\n", buf);
free(buf);
prop_object_release(newpkgd);
free(tmpfilen);
continue;
}
/*
* Current package version is greater than
* index version.
*/
buf = xbps_xasprintf("`%s' (%s)", oldpkgver, oldarch);
assert(buf);
buf2 = strdup(oldpkgver);
assert(buf2);
rv = remove_pkg(repodir, oldarch, oldfilen);
if (rv != 0) {
free(buf);
free(buf2);
prop_object_release(newpkgd);
free(tmpfilen);
goto out;
}
if (!xbps_remove_pkg_from_array_by_pkgver(xhp, idx,
buf2, oldarch)) {
xbps_error_printf("failed to remove %s "
"from plist index: %s\n", buf,
strerror(errno));
rv = errno;
free(buf);
free(buf2);
prop_object_release(newpkgd);
free(tmpfilen);
goto out;
}
free(buf2);
printf("index: removed obsolete entry/binpkg %s.\n", buf);
free(buf);
}
/*
* We have the dictionary now, add the required
* objects for the index.
*/
if (!prop_dictionary_set_cstring(newpkgd, "filename", filen)) {
rv = errno;
prop_object_release(newpkgd);
free(tmpfilen);
goto out;
}
if ((sha256 = xbps_file_hash(argv[i])) == NULL) {
rv = errno;
prop_object_release(newpkgd);
free(tmpfilen);
goto out;
}
if (!prop_dictionary_set_cstring(newpkgd, "filename-sha256",
sha256)) {
free(sha256);
prop_object_release(newpkgd);
free(tmpfilen);
rv = errno;
goto out;
}
free(sha256);
if (stat(argv[i], &st) == -1) {
prop_object_release(newpkgd);
free(tmpfilen);
rv = errno;
goto out;
}
if (!prop_dictionary_set_uint64(newpkgd, "filename-size",
(uint64_t)st.st_size)) {
prop_object_release(newpkgd);
free(tmpfilen);
rv = errno;
goto out;
}
/*
* Add new pkg dictionary into the index.
*/
if (!prop_array_add(idx, newpkgd)) {
prop_object_release(newpkgd);
free(tmpfilen);
rv = EINVAL;
goto out;
}
flush = true;
printf("index: added `%s-%s' (%s).\n", pkgname, version, arch);
free(tmpfilen);
prop_object_release(newpkgd);
}
if (flush && !prop_array_externalize_to_zfile(idx, plist)) {
xbps_error_printf("failed to externalize plist: %s\n",
strerror(errno));
rv = errno;
}
printf("index: %u packages registered.\n", prop_array_count(idx));
out:
if (tmprepodir)
free(tmprepodir);
if (plist)
free(plist);
if (idx)
prop_object_release(idx);
return rv;
}

114
bin/xbps-rindex/main.c Normal file
View File

@ -0,0 +1,114 @@
/*-
* Copyright (c) 2012 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 <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include "defs.h"
static void __attribute__((noreturn))
usage(bool fail)
{
fprintf(stdout,
"Usage: xbps-rindex [OPTIONS] MODE ARGUMENTS\n\n"
"OPTIONS\n"
" -h --help Show help usage\n"
" -V --version Show XBPS version\n\n"
"MODE\n"
" -a --add <repodir/pkg> ... Add package(s) to repository index\n"
" -c --clean <repodir> Cleans obsolete entries in repository index\n"
" -r --remove-obsoletes <repodir> Removes obsolete packages from repository\n\n");
exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
int
main(int argc, char **argv)
{
const char *shortopts = "achrV";
struct option longopts[] = {
{ "add", no_argument, NULL, 'a' },
{ "clean", no_argument, NULL, 'c' },
{ "help", no_argument, NULL, 'h' },
{ "remove-obsoletes", no_argument, NULL, 'r' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
struct xbps_handle xh;
int rv, c;
bool clean_mode = false, add_mode = false, rm_mode = false;
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
switch (c) {
case 'a':
add_mode = true;
break;
case 'c':
clean_mode = true;
break;
case 'h':
usage(false);
/* NOTREACHED */
case 'R':
rm_mode = true;
break;
case 'V':
printf("%s\n", XBPS_RELVER);
exit(EXIT_SUCCESS);
}
}
if ((argc == optind) || (!add_mode && !clean_mode && !rm_mode)) {
usage(true);
} else if ((add_mode && (clean_mode || rm_mode)) ||
(clean_mode && (add_mode || rm_mode)) ||
(rm_mode && (add_mode || clean_mode))) {
fprintf(stderr, "Only one mode can be specified: add, clean "
"or remove-obsoletes.\n");
exit(EXIT_FAILURE);
}
/* initialize libxbps */
memset(&xh, 0, sizeof(xh));
if ((rv = xbps_init(&xh)) != 0) {
fprintf(stderr, "failed to initialize libxbps: %s\n",
strerror(rv));
exit(EXIT_FAILURE);
}
if (add_mode) {
if (index_add(&xh, argc - optind, argv + optind) == 0)
rv = index_files_add(&xh, argc - optind, argv + optind);
} else if (clean_mode) {
if (index_clean(&xh, argv[optind]) == 0)
rv = index_files_clean(&xh, argv[optind]);
} else if (rm_mode) {
rv = remove_obsoletes(&xh, argv[optind]);
}
xbps_end(&xh);
exit(rv ? EXIT_FAILURE : EXIT_SUCCESS);
}

View File

@ -0,0 +1,119 @@
/*-
* Copyright (c) 2012 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 <sys/stat.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <libgen.h>
#include <assert.h>
#include <xbps_api.h>
#include "defs.h"
int
remove_obsoletes(struct xbps_handle *xhp, const char *repodir)
{
prop_dictionary_t pkgd;
prop_array_t idx;
DIR *dirp;
struct dirent *dp;
const char *pkgver, *arch;
char *plist, *ext;
int rv = 0;
if ((plist = xbps_pkg_index_plist(xhp, repodir)) == NULL)
return -1;
idx = prop_array_internalize_from_zfile(plist);
if (idx == NULL) {
if (errno != ENOENT) {
xbps_error_printf("xbps-repo: cannot read `%s': %s\n",
plist, strerror(errno));
free(plist);
return -1;
} else {
free(plist);
return 0;
}
}
if (chdir(repodir) == -1) {
fprintf(stderr, "cannot chdir to %s: %s\n",
repodir, strerror(errno));
prop_object_release(idx);
return errno;
}
if ((dirp = opendir(repodir)) == NULL) {
fprintf(stderr, "failed to open %s: %s\n",
repodir, strerror(errno));
prop_object_release(idx);
return errno;
}
while ((dp = readdir(dirp))) {
if (strcmp(dp->d_name, "..") == 0)
continue;
if ((ext = strrchr(dp->d_name, '.')) == NULL)
continue;
if (strcmp(ext, ".xbps"))
continue;
pkgd = xbps_dictionary_metadata_plist_by_url(dp->d_name,
"./props.plist");
if (pkgd == NULL) {
rv = remove_pkg(repodir, arch, dp->d_name);
if (rv != 0) {
fprintf(stderr, "index: failed to remove "
"package `%s': %s\n", dp->d_name,
strerror(rv));
prop_object_release(pkgd);
break;
}
printf("Removed broken package `%s'.\n", dp->d_name);
}
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch);
/*
* If binpkg is not registered in index, remove binpkg.
*/
if (!xbps_find_pkg_in_array_by_pkgver(xhp, idx, pkgver, arch)) {
rv = remove_pkg(repodir, arch, dp->d_name);
if (rv != 0) {
fprintf(stderr, "index: failed to remove "
"package `%s': %s\n", dp->d_name,
strerror(rv));
prop_object_release(pkgd);
break;
}
printf("Removed obsolete package `%s'.\n", dp->d_name);
}
prop_object_release(pkgd);
}
(void)closedir(dirp);
prop_object_release(idx);
return rv;
}