diff --git a/.gitignore b/.gitignore index 2cbe3861460..c77c1009060 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,8 @@ depot/ destdir/ srcdistdir/ builddir/ +utils/xbps-bin utils/xbps-cmpver -utils/xbps-pkgdb utils/xbps-digest +utils/xbps-pkgdb packages/ diff --git a/utils/Makefile b/utils/Makefile index 1fab7130b14..d0fac22773c 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -3,7 +3,7 @@ CFLAGS += -Wall -Werror -O3 -I$(PREFIX)/include CFLAGS += -funroll-all-loops -ftree-loop-linear LDFLAGS += -lprop -all: xbps_digest xbps_pkgdb xbps-cmpver clean_objs +all: xbps_digest xbps_pkgdb xbps_bin xbps-cmpver clean_objs xbps-cmpver: xbps-cmpver.o $(CC) $(CFLAGS) $< -o $@ @@ -26,6 +26,12 @@ plist_utils: xbps_pkgdb: xbps-pkgdb.o plist_utils.o $(CC) $(LDFLAGS) -o xbps-pkgdb xbps-pkgdb.o plist_utils.o +xbps-bin: + $(CC) $(CFLAGS) -c $@ + +xbps_bin: xbps-bin.o plist_utils.o + $(CC) $(LDFLAGS) -o xbps-bin xbps-bin.o plist_utils.o + clean_objs: -rm -f *.o diff --git a/utils/plist_utils.c b/utils/plist_utils.c index ef6488394df..0bfe801569c 100644 --- a/utils/plist_utils.c +++ b/utils/plist_utils.c @@ -31,7 +31,36 @@ #include #include -#include "plist_utils.h" +#include "xbps_api.h" + +bool +xbps_add_array_to_dict(prop_dictionary_t dict, prop_array_t array, + const char *key) +{ + if (dict == NULL || array == NULL || key == NULL) + return false; + + if (!prop_dictionary_set(dict, key, array)) + return false; + + prop_object_release(array); + return true; +} + +bool +xbps_add_obj_to_array(prop_array_t array, prop_object_t obj) +{ + if (array == NULL || obj == NULL) + return false; + + if (!prop_array_add(array, obj)) { + prop_object_release(array); + return false; + } + + prop_object_release(obj); + return true; +} prop_dictionary_t xbps_find_pkg_in_dict(prop_dictionary_t dict, const char *key, @@ -64,32 +93,105 @@ xbps_find_pkg_in_dict(prop_dictionary_t dict, const char *key, } bool -xbps_add_obj_to_array(prop_array_t array, prop_object_t obj) +xbps_find_string_in_array(prop_array_t array, const char *val) { - if (array == NULL || obj == NULL) + prop_object_iterator_t iter; + prop_object_t obj; + + if (array == NULL || val == NULL) return false; - if (!prop_array_add(array, obj)) { - prop_object_release(array); + iter = prop_array_iterator(array); + if (iter == NULL) return false; + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + if (prop_object_type(obj) != PROP_TYPE_STRING) + continue; + if (prop_string_equals_cstring(obj, val)) { + prop_object_iterator_release(iter); + return true; + } } - prop_object_release(obj); - return true; + prop_object_iterator_release(iter); + return false; } bool -xbps_add_array_to_dict(prop_dictionary_t dict, prop_array_t array, - const char *key) +xbps_register_repository(const char *uri) { - if (dict == NULL || array == NULL || key == NULL) + prop_dictionary_t dict; + prop_array_t array = NULL; + prop_object_t obj; + + if (uri == NULL) return false; - if (!prop_dictionary_set(dict, key, array)) - return false; + /* First check if we have the repository plist file. */ + dict = prop_dictionary_internalize_from_file(XBPS_REPOLIST_PATH); + if (dict == NULL) { + /* Looks like not, create it. */ + dict = prop_dictionary_create(); + if (dict == NULL) + return false; + + /* Create the array and add the repository URI on it. */ + array = prop_array_create(); + if (array == NULL) { + prop_object_release(dict); + return false; + } + + if (!prop_array_set_cstring_nocopy(array, 0, uri)) + goto fail; + + /* Add the array obj into the main dictionary. */ + if (!xbps_add_array_to_dict(dict, array, "repository-list")) + goto fail; + + /* Write dictionary into plist file. */ + if (!prop_dictionary_externalize_to_file(dict, + XBPS_REPOLIST_PATH)) + goto fail; + + prop_object_release(array); + } else { + /* Append into the array, the plist file exists. */ + array = prop_dictionary_get(dict, "repository-list"); + if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY) + return false; + + /* It seems that this object is already there */ + if (xbps_find_string_in_array(array, uri)) { + errno = EEXIST; + return false; + } + + obj = prop_string_create_cstring(uri); + if (!xbps_add_obj_to_array(array, obj)) { + prop_object_release(obj); + return false; + } + + /* Write dictionary into plist file. */ + if (!prop_dictionary_externalize_to_file(dict, + XBPS_REPOLIST_PATH)) { + prop_object_release(obj); + return false; + } + + prop_object_release(obj); + } - prop_object_release(array); return true; + +fail: + if (array) + prop_object_release(array); + if (dict) + prop_object_release(dict); + return false; } void diff --git a/utils/plist_utils.h b/utils/plist_utils.h index f9afed13cb4..0aa42c10a22 100644 --- a/utils/plist_utils.h +++ b/utils/plist_utils.h @@ -64,6 +64,18 @@ xbps_add_obj_to_array(prop_array_t, prop_object_t); prop_dictionary_t xbps_find_pkg_in_dict(prop_dictionary_t, const char *, const char *); +/* + * Finds a string object in an array. + * + * Arguments: + * - prop_array_t: array to search for the string. + * - const char *: string value of the object to be found. + * + * Returns true on success, false on failure. + */ +bool +xbps_find_string_in_array(prop_array_t, const char *); + /* * Lists information about all packages found in a dictionary, by * using a triplet: pkgname, version and short_desc. @@ -75,4 +87,15 @@ xbps_find_pkg_in_dict(prop_dictionary_t, const char *, const char *); void xbps_list_pkgs_in_dict(prop_dictionary_t, const char *); +/* + * Registers a repository specified by an URI into the pool. + * + * Arguments: + * - const char *: URI to register. + * + * Returns true on success, false on failure. + */ +bool +xbps_register_repository(const char *); + #endif /* !_XBPS_PLIST_UTILS_H_ */ diff --git a/utils/xbps-bin.c b/utils/xbps-bin.c new file mode 100644 index 00000000000..de41001adcb --- /dev/null +++ b/utils/xbps-bin.c @@ -0,0 +1,139 @@ +/*- + * Copyright (c) 2008 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 +#include +#include +#include +#include +#include + +#include "xbps_api.h" + +typedef struct repository_info { + const char *index_version; + const char *location_local; + const char *location_remote; + size_t total_pkgs; +} repo_info_t; + +static bool pkgindex_getinfo(prop_dictionary_t, repo_info_t *); +static void usage(void); + +static void +usage(void) +{ + printf("Usage: xbps-bin [action] [pkg|url]\n\n" + " Available actions: add-repo, show\n\n" + " Examples:\n" + " $ xbps-bin add-repo /path/to/directory\n" + " $ xbps-bin add-repo http://www.location.org/xbps-repo\n" + " $ xbps-bin show klibc\n"); + exit(1); +} + +static bool +pkgindex_getinfo(prop_dictionary_t dict, repo_info_t *ri) +{ + if (dict == NULL || ri == NULL) + return false; + + if (!prop_dictionary_get_cstring_nocopy(dict, + "pkgindex-version", &ri->index_version)) + return false; + + if (!prop_dictionary_get_cstring_nocopy(dict, + "location-local", &ri->location_local)) + return false; + + /* This one is optional, thus don't panic */ + prop_dictionary_get_cstring_nocopy(dict, "location-remote", + &ri->location_remote); + + if (!prop_dictionary_get_uint64(dict, "total-pkgs", + &ri->total_pkgs)) + return false; + + /* Reject empty repositories, how could this happen? :-) */ + if (ri->total_pkgs <= 0) + return false; + + return true; +} + +int +main(int argc, char **argv) +{ + prop_dictionary_t dict; + repo_info_t *rinfo = NULL; + char pkgindex[PATH_MAX], *tmp; + + if (argc != 3) + usage(); + + /* Adds a new repository to the pool. */ + if (strcmp(argv[1], "add-repo") == 0) { + tmp = strncpy(pkgindex, argv[2], sizeof(pkgindex)); + if (sizeof(*tmp) >= sizeof(pkgindex)) + exit(ENAMETOOLONG); + + /* Append trailing slash if needed */ + if (pkgindex[strlen(pkgindex) - 1] != '/') + strncat(pkgindex, "/", sizeof(pkgindex)); + + tmp = strncat(pkgindex, XBPS_PKGINDEX, sizeof(pkgindex)); + if (sizeof(*tmp) >= sizeof(pkgindex)) + exit(ENAMETOOLONG); + + dict = prop_dictionary_internalize_from_file(pkgindex); + if (dict == NULL) { + printf("Directory %s does not contain any " + "xbps pkgindex file.\n", argv[2]); + exit(EINVAL); + } + + rinfo = malloc(sizeof(*rinfo)); + if (rinfo == NULL) + exit(ENOMEM); + + if (!pkgindex_getinfo(dict, rinfo)) { + printf("'%s' is incomplete.\n", pkgindex); + exit(EINVAL); + } + + if (!xbps_register_repository((const char *)&pkgindex)) { + printf("ERROR: couldn't register repository (%s)\n", + strerror(errno)); + exit(EINVAL); + } + + printf("Added repository at %s (%s) with %zu packages.\n", + rinfo->location_local, rinfo->index_version, + rinfo->total_pkgs); + free(rinfo); + } + + exit(0); +} diff --git a/utils/xbps_api.h b/utils/xbps_api.h index cdb07a7d493..ed9dd022d68 100644 --- a/utils/xbps_api.h +++ b/utils/xbps_api.h @@ -31,6 +31,9 @@ #include +/* Default PATH for the repositories plist file. */ +#define XBPS_REPOLIST_PATH "/var/cache/xbps/repositories.plist" + /* Filename of the package index plist for a repository. */ #define XBPS_PKGINDEX "pkg-index.plist"