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

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;
}