diff --git a/NEWS b/NEWS index cac45897..48afd96a 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,11 @@ xbps-0.25 (???): + * Use a single zlib compressed file to store repository data `-repodata`. + This will allow us to extend repositories with more metadata if needed, and + simplifies the API. This is just the starting point to add PGP signatures. + The struct xbps_rindex has been replaced by xbps_repo, thus, the major + libxbps SONAME has been bumped to 2. + * xbps-create(8): correctly calculate target file for relative symlinks. * xbps-pkgdb(8): removed old code that isn't needed anymore in the 'check' mode. diff --git a/bin/xbps-create/main.c b/bin/xbps-create/main.c index 5d0a2659..c1a06823 100644 --- a/bin/xbps-create/main.c +++ b/bin/xbps-create/main.c @@ -468,34 +468,6 @@ process_entry_file(struct archive *ar, write_entry(ar, sparse_entry); } -static void -process_entry_memory(struct archive *ar, const void *src, const char *file) -{ - struct archive_entry *entry; - time_t tm; - - assert(ar); - assert(src); - assert(file); - - tm = time(NULL); - - entry = archive_entry_new(); - assert(entry); - archive_entry_set_filetype(entry, AE_IFREG); - archive_entry_set_perm(entry, 0644); - archive_entry_set_uname(entry, "root"); - archive_entry_set_gname(entry, "root"); - archive_entry_set_pathname(entry, file); - archive_entry_set_size(entry, strlen(src)); - archive_entry_set_atime(entry, tm, 0); - archive_entry_set_mtime(entry, tm, 0); - archive_entry_set_ctime(entry, tm, 0); - archive_write_header(ar, entry); - archive_write_data(ar, src, strlen(src)); - archive_entry_free(entry); -} - static void process_archive(struct archive *ar, struct archive_entry_linkresolver *resolver, @@ -517,13 +489,15 @@ process_archive(struct archive *ar, /* Add props.plist metadata file */ xml = prop_dictionary_externalize(pkg_propsd); assert(xml); - process_entry_memory(ar, xml, "./props.plist"); + xbps_archive_append_buf(ar, xml, strlen(xml), "./props.plist", + 0644, "root", "root"); free(xml); /* Add files.plist metadata file */ xml = prop_dictionary_externalize(pkg_filesd); assert(xml); - process_entry_memory(ar, xml, "./files.plist"); + xbps_archive_append_buf(ar, xml, strlen(xml), "./files.plist", + 0644, "root", "root"); free(xml); /* Add all package data files and release resources */ diff --git a/bin/xbps-install/main.c b/bin/xbps-install/main.c index 2c4d490c..32c528c9 100644 --- a/bin/xbps-install/main.c +++ b/bin/xbps-install/main.c @@ -201,13 +201,9 @@ main(int argc, char **argv) } } - /* Sync remote repository index files by default */ + /* Sync remote repository data by default */ if (sync && !drun) { - rv = xbps_rpool_sync(&xh, XBPS_PKGINDEX, NULL); - if (rv != 0) - exit(rv); - rv = xbps_rpool_sync(&xh, XBPS_PKGINDEX_FILES, NULL); - if (rv != 0) + if ((rv = xbps_rpool_sync(&xh, NULL)) != 0) exit(rv); } diff --git a/bin/xbps-query/list.c b/bin/xbps-query/list.c index 7b9fc1d1..5e27e497 100644 --- a/bin/xbps-query/list.c +++ b/bin/xbps-query/list.c @@ -162,13 +162,13 @@ list_pkgs_pkgdb(struct xbps_handle *xhp) } static int -repo_list_uri_cb(struct xbps_rindex *rpi, void *arg, bool *done) +repo_list_uri_cb(struct xbps_repo *repo, void *arg, bool *done) { (void)arg; (void)done; - printf("%s (%zu packages)\n", rpi->uri, - (size_t)prop_dictionary_count(rpi->repod)); + printf("%s (%zu packages)\n", repo->uri, + (size_t)prop_dictionary_count(repo->idx)); return 0; } diff --git a/bin/xbps-query/ownedby.c b/bin/xbps-query/ownedby.c index fb4f540a..ab819e7c 100644 --- a/bin/xbps-query/ownedby.c +++ b/bin/xbps-query/ownedby.c @@ -123,21 +123,18 @@ ownedby(struct xbps_handle *xhp, int npatterns, char **patterns) } static void -repo_match_files_by_pattern(prop_dictionary_t pkgd, - struct ffdata *ffd) +repo_match_files_by_pattern(prop_array_t files, + const char *pkgver, + struct ffdata *ffd) { - prop_array_t array; - const char *filestr, *pkgver; + const char *filestr; size_t i; int x; - array = prop_dictionary_get(pkgd, "files"); - for (i = 0; i < prop_array_count(array); i++) { - prop_array_get_cstring_nocopy(array, i, &filestr); + for (i = 0; i < prop_array_count(files); i++) { + prop_array_get_cstring_nocopy(files, i, &filestr); for (x = 0; x < ffd->npatterns; x++) { if ((fnmatch(ffd->patterns[x], filestr, FNM_PERIOD)) == 0) { - prop_dictionary_get_cstring_nocopy(pkgd, - "pkgver", &pkgver); printf("%s: %s (%s)\n", pkgver, filestr, ffd->repouri); } @@ -146,35 +143,26 @@ repo_match_files_by_pattern(prop_dictionary_t pkgd, } static int -repo_ownedby_cb(struct xbps_rindex *rpi, void *arg, bool *done) +repo_ownedby_cb(struct xbps_repo *repo, void *arg, bool *done) { - prop_array_t allkeys; - prop_dictionary_t pkgd, idxfiles; + prop_array_t allkeys, pkgar; + prop_dictionary_t filesd; prop_dictionary_keysym_t ksym; struct ffdata *ffd = arg; - char *plist; + const char *pkgver; unsigned int i; (void)done; - if ((plist = xbps_pkg_index_files_plist(rpi->xhp, rpi->uri)) == NULL) - return ENOMEM; - - if ((idxfiles = prop_dictionary_internalize_from_zfile(plist)) == NULL) { - if (errno == ENOENT) { - fprintf(stderr, "%s: index-files missing! " - "ignoring...\n", rpi->uri); - return 0; - } - return errno; - } - ffd->repouri = rpi->uri; - allkeys = prop_dictionary_all_keys(idxfiles); + filesd = xbps_repo_get_plist(repo, XBPS_PKGINDEX_FILES); + ffd->repouri = repo->uri; + allkeys = prop_dictionary_all_keys(filesd); for (i = 0; i < prop_array_count(allkeys); i++) { ksym = prop_array_get(allkeys, i); - pkgd = prop_dictionary_get_keysym(idxfiles, ksym); - repo_match_files_by_pattern(pkgd, ffd); + pkgar = prop_dictionary_get_keysym(filesd, ksym); + pkgver = prop_dictionary_keysym_cstring_nocopy(ksym); + repo_match_files_by_pattern(pkgar, pkgver, ffd); } return 0; diff --git a/bin/xbps-query/search.c b/bin/xbps-query/search.c index 78820db8..b09014bb 100644 --- a/bin/xbps-query/search.c +++ b/bin/xbps-query/search.c @@ -96,7 +96,7 @@ print_results(struct xbps_handle *xhp, struct search_data *sd) } static int -search_pkgs_cb(struct xbps_rindex *rpi, void *arg, bool *done) +search_pkgs_cb(struct xbps_repo *repo, void *arg, bool *done) { prop_array_t allkeys; prop_dictionary_t pkgd; @@ -108,12 +108,12 @@ search_pkgs_cb(struct xbps_rindex *rpi, void *arg, bool *done) (void)done; - allkeys = prop_dictionary_all_keys(rpi->repod); + allkeys = prop_dictionary_all_keys(repo->idx); for (i = 0; i < prop_array_count(allkeys); i++) { prop_array_t provides = NULL; ksym = prop_array_get(allkeys, i); - pkgd = prop_dictionary_get_keysym(rpi->repod, ksym); + pkgd = prop_dictionary_get_keysym(repo->idx, ksym); prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); prop_dictionary_get_cstring_nocopy(pkgd, "short_desc", &desc); diff --git a/bin/xbps-query/show-deps.c b/bin/xbps-query/show-deps.c index 7603179c..f0fdb887 100644 --- a/bin/xbps-query/show-deps.c +++ b/bin/xbps-query/show-deps.c @@ -128,7 +128,7 @@ repo_show_pkg_deps(struct xbps_handle *xhp, const char *pattern, bool full) } static int -repo_revdeps_cb(struct xbps_rindex *rpi, void *arg, bool *done) +repo_revdeps_cb(struct xbps_repo *repo, void *arg, bool *done) { prop_dictionary_t pkgd; prop_array_t pkgdeps; @@ -138,10 +138,10 @@ repo_revdeps_cb(struct xbps_rindex *rpi, void *arg, bool *done) (void)done; - iter = prop_dictionary_iterator(rpi->repod); + iter = prop_dictionary_iterator(repo->idx); assert(iter); while ((obj = prop_object_iterator_next(iter))) { - pkgd = prop_dictionary_get_keysym(rpi->repod, obj); + pkgd = prop_dictionary_get_keysym(repo->idx, obj); pkgdeps = prop_dictionary_get(pkgd, "run_depends"); if (pkgdeps == NULL || prop_array_count(pkgdeps) == 0) continue; @@ -149,7 +149,7 @@ repo_revdeps_cb(struct xbps_rindex *rpi, void *arg, bool *done) if (xbps_match_pkgdep_in_array(pkgdeps, pattern)) { prop_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch); - if (xbps_pkg_arch_match(rpi->xhp, arch, NULL)) { + if (xbps_pkg_arch_match(repo->xhp, arch, NULL)) { prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); printf("%s\n", pkgver); diff --git a/bin/xbps-rindex/Makefile b/bin/xbps-rindex/Makefile index b5b17148..7aeb9126 100644 --- a/bin/xbps-rindex/Makefile +++ b/bin/xbps-rindex/Makefile @@ -2,7 +2,7 @@ TOPDIR = ../.. -include $(TOPDIR)/config.mk BIN = xbps-rindex -OBJS = main.o index-add.o index-clean.o remove-obsoletes.o +OBJS = main.o index-add.o index-clean.o remove-obsoletes.o repoflush.o MAN = $(BIN).8 include $(TOPDIR)/mk/prog.mk diff --git a/bin/xbps-rindex/defs.h b/bin/xbps-rindex/defs.h index c9cee5c1..02614cc9 100644 --- a/bin/xbps-rindex/defs.h +++ b/bin/xbps-rindex/defs.h @@ -41,4 +41,8 @@ int index_files_clean(struct xbps_handle *, const char *); /* From remove-obsoletes.c */ int remove_obsoletes(struct xbps_handle *, const char *); +/* From repoflush.c */ +int repodata_flush(struct xbps_handle *, const char *, + prop_dictionary_t, prop_dictionary_t); + #endif /* !_XBPS_RINDEX_DEFS_H_ */ diff --git a/bin/xbps-rindex/index-add.c b/bin/xbps-rindex/index-add.c index 14925c19..b497b8fb 100644 --- a/bin/xbps-rindex/index-add.c +++ b/bin/xbps-rindex/index-add.c @@ -32,8 +32,11 @@ #include #include #include +#include #include +#include +#include #include "defs.h" /* @@ -45,56 +48,37 @@ index_add(struct xbps_handle *xhp, int argc, char **argv, bool force) { prop_array_t filespkgar, pkg_files, pkg_links, pkg_cffiles; prop_dictionary_t idx, idxfiles, newpkgd, newpkgfilesd, curpkgd; - prop_dictionary_t filespkgd; prop_object_t obj, fileobj; + struct xbps_repo *repo; struct stat st; const char *oldpkgver, *arch, *oldarch; char *pkgver, *pkgname, *sha256, *repodir, *buf; - char *tmprepodir, *plist, *plistf; + char *tmprepodir; size_t x; - int i, ret = 0; - bool files_flush = false, found = false, flush = false; + int i, rv, ret = 0; + bool flush = false, found = false; idx = idxfiles = newpkgd = newpkgfilesd = curpkgd = NULL; - tmprepodir = plist = plistf = NULL; if ((tmprepodir = strdup(argv[0])) == NULL) return ENOMEM; + /* + * Read the repository data or create index dictionaries otherwise. + */ repodir = dirname(tmprepodir); - /* Internalize index or create it if doesn't exist */ - if ((plist = xbps_pkg_index_plist(xhp, repodir)) == NULL) { - free(tmprepodir); - return -1; - } - - if ((idx = prop_dictionary_internalize_from_zfile(plist)) == NULL) { - if (errno != ENOENT) { - fprintf(stderr, "index: cannot read `%s': %s\n", - plist, strerror(errno)); - return -1; - } else { - idx = prop_dictionary_create(); - assert(idx); - } - } - /* Internalize index-files or create it if doesn't exist */ - if ((plistf = xbps_pkg_index_files_plist(xhp, repodir)) == NULL) - return -1; - - free(tmprepodir); - - if ((idxfiles = prop_dictionary_internalize_from_zfile(plistf)) == NULL) { - if (errno != ENOENT) { - fprintf(stderr, "index: cannot read `%s': %s\n", - plistf, strerror(errno)); - return -1; - } else { - idxfiles = prop_dictionary_create(); - assert(idx); - } + repo = xbps_repo_open(xhp, repodir); + if (repo != NULL) { + idx = xbps_repo_get_plist(repo, XBPS_PKGINDEX); + idxfiles = xbps_repo_get_plist(repo, XBPS_PKGINDEX_FILES); } + if (idx == NULL) + idx = prop_dictionary_create(); + if (idxfiles == NULL) + idxfiles = prop_dictionary_create(); + if (repo != NULL) + xbps_repo_close(repo); /* * Process all packages specified in argv. @@ -212,7 +196,6 @@ index_add(struct xbps_handle *xhp, int argc, char **argv, bool force) free(pkgname); return EINVAL; } - flush = true; printf("index: added `%s' (%s).\n", pkgver, arch); /* @@ -284,43 +267,29 @@ index_add(struct xbps_handle *xhp, int argc, char **argv, bool force) } prop_object_release(newpkgfilesd); - /* create pkg dictionary */ - filespkgd = prop_dictionary_create(); - assert(filespkgd); - - /* add pkg files array into pkg dictionary */ - prop_dictionary_set(filespkgd, "files", filespkgar); + /* add pkg files array into index-files */ + prop_dictionary_set(idxfiles, pkgver, filespkgar); prop_object_release(filespkgar); - /* set pkgver obj into pkg dictionary */ - prop_dictionary_set_cstring(filespkgd, "pkgver", pkgver); - - /* add pkg dictionary into index-files */ - prop_dictionary_set(idxfiles, pkgname, filespkgd); - prop_object_release(filespkgd); - printf("index-files: added `%s' (%s)\n", pkgver, arch); - files_flush = true; prop_object_release(newpkgd); free(pkgver); free(pkgname); } - - if (flush && !prop_dictionary_externalize_to_zfile(idx, plist)) { - fprintf(stderr, "index: failed to externalize plist: %s\n", - strerror(errno)); - return -1; - } - if (files_flush && - !prop_dictionary_externalize_to_zfile(idxfiles, plistf)) { - fprintf(stderr, "index-files: failed to externalize " - "plist: %s\n", strerror(errno)); - return -1; + /* + * Generate repository data file. + */ + if (flush) { + rv = repodata_flush(xhp, repodir, idx, idxfiles); + if (rv != 0) + return rv; } printf("index: %u packages registered.\n", prop_dictionary_count(idx)); printf("index-files: %u packages registered.\n", prop_dictionary_count(idxfiles)); + prop_object_release(idx); + prop_object_release(idxfiles); return 0; } diff --git a/bin/xbps-rindex/index-clean.c b/bin/xbps-rindex/index-clean.c index cd46126f..ef6aa32e 100644 --- a/bin/xbps-rindex/index-clean.c +++ b/bin/xbps-rindex/index-clean.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "defs.h" @@ -99,8 +100,10 @@ cleaner_files_thread(void *arg) { prop_object_t obj; prop_array_t array; + prop_dictionary_t ipkgd; struct thread_data *thd = arg; - const char *pkgname; + const char *pkgver, *ipkgver; + char *pkgname; unsigned int i; /* process pkgs from start until end */ @@ -108,10 +111,20 @@ cleaner_files_thread(void *arg) for (i = thd->start; i < thd->end; i++) { obj = prop_array_get(array, i); - pkgname = prop_dictionary_keysym_cstring_nocopy(obj); + pkgver = prop_dictionary_keysym_cstring_nocopy(obj); + pkgname = xbps_pkg_name(pkgver); + assert(pkgname); + ipkgd = prop_dictionary_get(thd->idx, pkgname); /* If pkg is not registered in index, remove it */ - if (!prop_dictionary_get(thd->idx, pkgname)) - prop_array_add_cstring_nocopy(thd->result_files, pkgname); + if (ipkgd == NULL) + prop_array_add_cstring_nocopy(thd->result_files, pkgver); + /* if another version is registered in index, remove it */ + else { + prop_dictionary_get_cstring_nocopy(ipkgd, "pkgver", &ipkgver); + if (strcmp(ipkgver, pkgver)) + prop_array_add_cstring_nocopy(thd->result_files, pkgver); + } + free(pkgname); } prop_object_release(array); @@ -125,36 +138,28 @@ cleaner_files_thread(void *arg) int index_clean(struct xbps_handle *xhp, const char *repodir) { + struct xbps_repo *repo; struct thread_data *thd; prop_dictionary_t idx, idxfiles; const char *keyname; - char *plist, *plistf, *pkgname; + char *pkgname; size_t x, pkgcount, slicecount; int i, maxthreads, rv = 0; bool flush = false; - plist = xbps_pkg_index_plist(xhp, repodir); - assert(plist); - plistf = xbps_pkg_index_files_plist(xhp, repodir); - assert(plistf); - - idx = prop_dictionary_internalize_from_zfile(plist); - if (idx == NULL) { - if (errno != ENOENT) { - fprintf(stderr, "index: cannot read `%s': %s\n", - plist, strerror(errno)); - return -1; - } else + repo = xbps_repo_open(xhp, repodir); + if (repo == NULL) { + if (errno == ENOENT) return 0; + fprintf(stderr, "index: cannot read repository data: %s\n", strerror(errno)); + return -1; } - idxfiles = prop_dictionary_internalize_from_zfile(plistf); - if (idxfiles == NULL) { - if (errno != ENOENT) { - fprintf(stderr, "index: cannot read `%s': %s\n", - plistf, strerror(errno)); - return -1; - } else - return 0; + idx = xbps_repo_get_plist(repo, XBPS_PKGINDEX); + idxfiles = xbps_repo_get_plist(repo, XBPS_PKGINDEX_FILES); + xbps_repo_close(repo); + if (idx == NULL || idxfiles == NULL) { + fprintf(stderr, "incomplete repository data file!"); + return -1; } if (chdir(repodir) == -1) { fprintf(stderr, "index: cannot chdir to %s: %s\n", @@ -216,7 +221,7 @@ index_clean(struct xbps_handle *xhp, const char *repodir) printf("index: removed entry %s\n", keyname); pkgname = xbps_pkg_name(keyname); prop_dictionary_remove(idx, pkgname); - prop_dictionary_remove(idxfiles, pkgname); + prop_dictionary_remove(idxfiles, keyname); free(pkgname); flush = true; } @@ -228,23 +233,17 @@ index_clean(struct xbps_handle *xhp, const char *repodir) flush = true; } } - - if (!flush) - goto out; - - if (!prop_dictionary_externalize_to_zfile(idx, plist)) - fprintf(stderr, "index: failed to externalize %s: %s\n", - plist, strerror(errno)); - - if (!prop_dictionary_externalize_to_zfile(idxfiles, plistf)) - fprintf(stderr, "index-files: failed to externalize %s: %s\n", - plistf, strerror(errno)); - -out: + if (flush) { + rv = repodata_flush(xhp, repodir, idx, idxfiles); + if (rv != 0) + return rv; + } printf("index: %u packages registered.\n", prop_dictionary_count(idx)); printf("index-files: %u packages registered.\n", prop_dictionary_count(idxfiles)); + prop_object_release(idx); + prop_object_release(idxfiles); return rv; } diff --git a/bin/xbps-rindex/remove-obsoletes.c b/bin/xbps-rindex/remove-obsoletes.c index 5796872a..0256de2b 100644 --- a/bin/xbps-rindex/remove-obsoletes.c +++ b/bin/xbps-rindex/remove-obsoletes.c @@ -40,7 +40,7 @@ struct thread_data { pthread_t thread; prop_array_t array; - struct xbps_rindex *ri; + struct xbps_repo *repo; unsigned int start; unsigned int end; int thread_num; @@ -95,7 +95,7 @@ cleaner_thread(void *arg) prop_array_get_cstring_nocopy(thd->array, i, &binpkg); pkgd = xbps_get_pkg_plist_from_binpkg(binpkg, "./props.plist"); if (pkgd == NULL) { - rv = remove_pkg(thd->ri->uri, arch, binpkg); + rv = remove_pkg(thd->repo->uri, arch, binpkg); if (rv != 0) { prop_object_release(pkgd); continue; @@ -105,17 +105,17 @@ cleaner_thread(void *arg) prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); prop_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch); /* ignore pkgs from other archs */ - if (!xbps_pkg_arch_match(thd->ri->xhp, arch, NULL)) { + if (!xbps_pkg_arch_match(thd->repo->xhp, arch, NULL)) { prop_object_release(pkgd); continue; } - xbps_dbg_printf(thd->ri->xhp, "thread[%d] checking %s (%s)\n", + xbps_dbg_printf(thd->repo->xhp, "thread[%d] checking %s (%s)\n", thd->thread_num, pkgver, binpkg); /* * If binpkg is not registered in index, remove binpkg. */ - if (!xbps_rindex_get_pkg(thd->ri, pkgver)) { - rv = remove_pkg(thd->ri->uri, arch, binpkg); + if (!xbps_repo_get_pkg(thd->repo, pkgver)) { + rv = remove_pkg(thd->repo->uri, arch, binpkg); if (rv != 0) { prop_object_release(pkgd); continue; @@ -131,33 +131,28 @@ cleaner_thread(void *arg) int remove_obsoletes(struct xbps_handle *xhp, const char *repodir) { - prop_dictionary_t idx; prop_array_t array = NULL; - struct xbps_rindex ri; + struct xbps_repo *repo; struct thread_data *thd; DIR *dirp; struct dirent *dp; - char *plist, *ext; + char *ext; int i, maxthreads, rv = 0; size_t slicecount, pkgcount; - if ((plist = xbps_pkg_index_plist(xhp, repodir)) == NULL) - return -1; - - idx = prop_dictionary_internalize_from_zfile(plist); - if (idx == NULL) { + repo = xbps_repo_open(xhp, repodir); + if (repo == NULL) { if (errno != ENOENT) { - fprintf(stderr, "xbps-rindex: cannot read `%s': %s\n", - plist, strerror(errno)); + fprintf(stderr, "xbps-rindex: cannot read repository data: %s\n", + strerror(errno)); return -1; - } else - return 0; + } + return 0; + } + if ((repo->idx = xbps_repo_get_plist(repo, XBPS_PKGINDEX)) == NULL) { + xbps_repo_close(repo); + return -1; } - /* initialize repository index */ - ri.repod = idx; - ri.uri = repodir; - ri.xhp = xhp; - if (chdir(repodir) == -1) { fprintf(stderr, "xbps-rindex: cannot chdir to %s: %s\n", repodir, strerror(errno)); @@ -191,7 +186,7 @@ remove_obsoletes(struct xbps_handle *xhp, const char *repodir) for (i = 0; i < maxthreads; i++) { thd[i].thread_num = i; thd[i].array = array; - thd[i].ri = &ri; + thd[i].repo = repo; thd[i].start = pkgcount; if (i + 1 >= maxthreads) thd[i].end = prop_array_count(array); @@ -205,5 +200,7 @@ remove_obsoletes(struct xbps_handle *xhp, const char *repodir) for (i = 0; i < maxthreads; i++) pthread_join(thd[i].thread, NULL); + xbps_repo_close(repo); + return rv; } diff --git a/bin/xbps-rindex/repoflush.c b/bin/xbps-rindex/repoflush.c new file mode 100644 index 00000000..a6149aa9 --- /dev/null +++ b/bin/xbps-rindex/repoflush.c @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 2013 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 +#include +#include +#include + +#include +#include "defs.h" + +int +repodata_flush(struct xbps_handle *xhp, const char *repodir, + prop_dictionary_t idx, prop_dictionary_t idxfiles) +{ + struct archive *ar; + mode_t myumask; + char *repofile, *tname, *xml; + int repofd; + + /* Create a tempfile for our repository archive */ + repofile = xbps_repo_path(xhp, repodir); + tname = xbps_xasprintf("%s.XXXXXXXXXX", repofile); + if ((repofd = mkstemp(tname)) == -1) + return errno; + + /* Create and write our repository archive */ + ar = archive_write_new(); + assert(ar); + archive_write_add_filter_gzip(ar); + archive_write_set_format_pax_restricted(ar); + archive_write_set_options(ar, "compression-level=9"); + archive_write_open_fd(ar, repofd); + + xml = prop_dictionary_externalize(idx); + assert(xml); + if (xbps_archive_append_buf(ar, xml, strlen(xml), + XBPS_PKGINDEX, 0644, "root", "root") != 0) { + free(xml); + return -1; + } + free(xml); + + xml = prop_dictionary_externalize(idxfiles); + assert(xml); + if (xbps_archive_append_buf(ar, xml, strlen(xml), + XBPS_PKGINDEX_FILES, 0644, "root", "root") != 0) { + free(xml); + return -1; + } + free(xml); + + archive_write_free(ar); + + /* Write data to tempfile and rename */ + fdatasync(repofd); + myumask = umask(0); + (void)umask(myumask); + assert(fchmod(repofd, 0666 & ~myumask) != -1); + close(repofd); + rename(tname, repofile); + free(repofile); + free(tname); + + return 0; +} diff --git a/include/xbps_api.h.in b/include/xbps_api.h.in index a778c700..45315516 100644 --- a/include/xbps_api.h.in +++ b/include/xbps_api.h.in @@ -41,14 +41,7 @@ * * This header documents the full API for the XBPS Library. */ - -/** - * @def XBPS_PKGINDEX_VERSION - * Current version for the repository package index format. - */ -#define XBPS_PKGINDEX_VERSION "1.7" - -#define XBPS_API_VERSION "20130418" +#define XBPS_API_VERSION "20130609" #ifndef XBPS_VERSION #define XBPS_VERSION "UNSET" @@ -62,7 +55,6 @@ */ #define XBPS_RELVER "XBPS: " XBPS_VERSION \ " API: " XBPS_API_VERSION \ - " INDEX: " XBPS_PKGINDEX_VERSION \ " GIT: " XBPS_GIT /** @@ -99,7 +91,7 @@ * @def XBPS_PKGINDEX * Filename for the repository package index property list. */ -#define XBPS_PKGINDEX "index-" XBPS_PKGINDEX_VERSION ".plist" +#define XBPS_PKGINDEX "index.plist" /** * @def XBPS_PKGINDEX_FILES @@ -452,13 +444,7 @@ struct xbps_handle { */ cfg_t *cfg; /** - * @private - * - * Array of dictionaries with all registered repositories. - */ - prop_array_t repo_pool; - /** - * @private pkgdb. + * @var pkgdb * * Internalized proplib dictionary with the master package database * stored in XBPS_META_PATH/XBPS_PKGDB. @@ -466,19 +452,14 @@ struct xbps_handle { prop_dictionary_t pkgdb; /** * @private - * - * Proplib dictionary with pkg metafiles. */ prop_dictionary_t pkg_metad; /** - * @private pkgdb_revdeps. - * - * Proplib dictionary with full reverse dependencies from pkgdb. + * @private */ prop_dictionary_t pkgdb_revdeps; - /** - * @var transd; + * @var transd * * Proplib dictionary with transaction details, required by * xbps_transaction_commit(). @@ -490,6 +471,8 @@ struct xbps_handle { */ void (*state_cb)(struct xbps_state_cb_data *, void *); /** + * @var state_cb_data + * * Pointer to user supplied data to be passed as argument to * the \a xbps_state_cb function callback. */ @@ -500,6 +483,8 @@ struct xbps_handle { */ void (*unpack_cb)(struct xbps_unpack_cb_data *, void *); /** + * @var unpack_cb_data + * * Pointer to user supplied data to be passed as argument to * the \a xbps_unpack_cb function callback. */ @@ -581,6 +566,7 @@ struct xbps_handle { * @private */ bool initialized; + bool rpool_initialized; }; void xbps_dbg_printf(struct xbps_handle *, const char *, ...); @@ -1135,21 +1121,29 @@ prop_dictionary_t xbps_get_pkg_plist_from_binpkg(const char *fname, /*@{*/ /** - * @struct xbps_rindex xbps_api.h "xbps_api.h" - * @brief Repository pool index structure + * @struct xbps_repo xbps_api.h "xbps_api.h" + * @brief Repository structure * - * Repository index object structure registered in a private simple queue. - * The structure contains a dictionary and the URI associated with the - * registered repository index. + * Repository object structure registered in a private simple queue. + * The structure contains repository data: uri and dictionaries associated. */ -struct xbps_rindex { +struct xbps_repo { /** - * @var repod - * - * Internalized proplib dictionary of the index plist file - * associated with repository. + * @private */ - prop_dictionary_t repod; + struct archive *ar; + /** + * @var idx + * + * Proplib dictionary associated with the repository index. + */ + prop_dictionary_t idx; + /** + * @var idxfiles + * + * Proplib dictionary associated with the repository index files. + */ + prop_dictionary_t idxfiles; /** * @var uri * @@ -1166,18 +1160,17 @@ struct xbps_rindex { }; /** - * Synchronizes \a file for all remote repositories + * Synchronizes repository data for all remote repositories * as specified in the configuration file or if \a uri argument is - * set, just sync \a file for that repository. + * set, just sync for that repository. * * @param[in] xhp Pointer to the xbps_handle struct. - * @param[in] file File to synchronize. * @param[in] uri Repository URI to match for sync (optional). * * @return 0 on success, ENOTSUP if no repositories were found in * the configuration file. */ -int xbps_rpool_sync(struct xbps_handle *xhp, const char *file, const char *uri); +int xbps_rpool_sync(struct xbps_handle *xhp, const char *uri); /** * Iterates over the repository pool and executes the \a fn function @@ -1195,7 +1188,7 @@ int xbps_rpool_sync(struct xbps_handle *xhp, const char *file, const char *uri); * @return 0 on success, otherwise an errno value. */ int xbps_rpool_foreach(struct xbps_handle *xhp, - int (*fn)(struct xbps_rindex *, void *, bool *), + int (*fn)(struct xbps_repo *, void *, bool *), void *arg); /** @@ -1251,35 +1244,108 @@ prop_dictionary_t xbps_rpool_get_pkg_plist(struct xbps_handle *xhp, /*@}*/ -/** @addtogroup rindex */ +/** @addtogroup repo */ /*@{*/ /** - * Returns a pkg dictionary from a repository index \a ri matching + * Opens a repository and returns an xbps_repo object. + * + * @param[in] xhp Pointer to the xbps_handle struct. + * @param[in] uri Repository URI to match. + * + * @return The matching repository object, NULL otherwise. + */ +struct xbps_repo *xbps_repo_open(struct xbps_handle *xhp, const char *url); + +/** + * Returns a proplib dictionary associated with a repository object. + * + * @param[in] repo Pointer to the xbps_repo object. + * @param[in] file Filename of proplib dictionary stored in the + * repository object. + * + * @return The matching proplib dictionary on success, NULL otherwise. + */ +prop_dictionary_t xbps_repo_get_plist(struct xbps_repo *repo, const char *file); + +/** + * Closes a repository object and releases resources. + * + * @param[in] repo The repository object to close. + */ +void xbps_repo_close(struct xbps_repo *repo); + +/** + * + * Returns a heap-allocated string with the repository local path. + * + * @param[in] xhp The xbps_handle object. + * @param[in] url The repository URL to match. + * + * @return A heap allocated string that must be free(3)d when it's unneeded. + */ +char *xbps_repo_path(struct xbps_handle *xhp, const char *url); + +/** + * Returns a pkg dictionary from a repository \a repo matching * the expression \a pkg. * - * @param[in] ri Pointer to an xbps_rindex structure. + * @param[in] repo Pointer to an xbps_repo structure. * @param[in] pkg Package expression to match in this repository index. * * @return The pkg dictionary on success, NULL otherwise. */ -prop_dictionary_t xbps_rindex_get_pkg(struct xbps_rindex *ri, const char *pkg); +prop_dictionary_t xbps_repo_get_pkg(struct xbps_repo *repo, const char *pkg); /** - * Returns a pkg dictionary from a repository index \a ri matching + * Returns a pkg dictionary from a repository \a repo matching * the expression \a pkg. On match the first package matching the virtual * package expression will be returned. * - * @param[in] ri Pointer to an xbps_rindex structure. + * @param[in] repo Pointer to an xbps_repo structure. * @param[in] pkg Package expression to match in this repository index. * * @return The pkg dictionary on success, NULL otherwise. */ -prop_dictionary_t xbps_rindex_get_virtualpkg(struct xbps_rindex *ri, +prop_dictionary_t xbps_repo_get_virtualpkg(struct xbps_repo *repo, const char *pkg); /*@}*/ +/** @addtogroup archive_util */ +/*@{*/ + +/** + * Returns a proplib dictionary if \a entry is matched in the \a ar archive. + * + * @param[in] ar The archive object. + * @param[in] entry The archive_entry object (must be filled in properly). + * + * @return The internalized proplib dictionary, NULL otherwise. + */ +prop_dictionary_t xbps_archive_get_dictionary(struct archive *ar, + struct archive_entry *entry); + +/** + * Appends a file to the \a ar archive by using a memory buffer \a buf of + * size \a sizelen. + * + * @param[in] ar The archive object. + * @param[in] buf The memory buffer to be used as file data. + * @param[in] buflen The size of the memory buffer. + * @param[in] fname The filename to be used for the entry. + * @param[in] mode The mode to be used in the entry. + * @param[in] uname The user name to be used in the entry. + * @param[in] gname The group name to be used in the entry. + * + * @return 0 on success, or any negative or errno value otherwise. + */ +int xbps_archive_append_buf(struct archive *ar, const void *buf, + const size_t buflen, const char *fname, const mode_t mode, + const char *uname, const char *gname); + +/*@}*/ + /** @addtogroup pkgstates */ /*@{*/ @@ -1425,32 +1491,6 @@ int xbps_pkg_is_installed(struct xbps_handle *xhp, const char *pkg); */ bool xbps_repository_is_remote(const char *uri); -/** - * Gets the full path to a repository package index plist file, as - * specified by \a uri. - * - * @param[in] xhp The pointer to an xbps_handle struct. - * @param[in] uri Repository URI. - * - * @return A pointer to a malloc(3)d string, NULL otherwise and - * errno is set appropiately. The pointer should be free(3)d when it's - * no longer needed. - */ -char *xbps_pkg_index_plist(struct xbps_handle *xhp, const char *uri); - -/** - * Returns the full path to a repository package index files plist file, - * as specified by \a uri. - * - * @param[in] xhp The pointer to an xbps_handle struct. - * @param[in] uri Repository URI. - * - * @return A pointer to a malloc(3)ed string, NULL otherwise and - * errno is set appropiately. The pointer should be free(3)d when it's - * no longer needded. - */ -char *xbps_pkg_index_files_plist(struct xbps_handle *xhp, const char *uri); - /** * Gets the name of a package string. Package strings are composed * by a @/@ pair and separated by the minus diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index a36d65a7..86743581 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -27,6 +27,10 @@ #ifndef _XBPS_API_IMPL_H_ #define _XBPS_API_IMPL_H_ +#ifndef DEBUG +#define NDEBUG +#endif + #include #include /* @@ -151,15 +155,7 @@ int HIDDEN xbps_entry_install_conf_file(struct xbps_handle *, const char *); /** * @private - * From lib/plist_archive_entry.c - */ -prop_dictionary_t HIDDEN - xbps_dictionary_from_archive_entry(struct archive *, - struct archive_entry *); - -/** - * @private - * From lib/rindex_pkgdeps.c + * From lib/repo_pkgdeps.c */ int HIDDEN xbps_repository_find_deps(struct xbps_handle *, prop_array_t, @@ -191,10 +187,10 @@ int HIDDEN xbps_transaction_init(struct xbps_handle *); /** * @private - * From lib/rindex_sync.c + * From lib/repo_sync.c */ char HIDDEN *xbps_get_remote_repo_string(const char *); -int HIDDEN xbps_rindex_sync(struct xbps_handle *, const char *, const char *); +int HIDDEN xbps_repo_sync(struct xbps_handle *, const char *); /** * @private diff --git a/lib/Makefile b/lib/Makefile index c4a63ff3..4403d2b8 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,6 +1,6 @@ -include ../config.mk -LIBXBPS_MAJOR = 1 +LIBXBPS_MAJOR = 2 LIBXBPS_MINOR = 0 LIBXBPS_MICRO = 0 LIBXBPS_SHLIB = libxbps.so.$(LIBXBPS_MAJOR).$(LIBXBPS_MINOR).$(LIBXBPS_MICRO) @@ -46,9 +46,9 @@ OBJS += package_unpack.o package_register.o package_script.o OBJS += transaction_commit.o transaction_package_replace.o OBJS += transaction_dictionary.o transaction_sortdeps.o transaction_ops.o OBJS += download.o initend.o pkgdb.o package_conflicts.o -OBJS += plist.o plist_archive_entry.o plist_find.o plist_match.o +OBJS += plist.o plist_find.o plist_match.o archive.o OBJS += plist_remove.o plist_fetch.o util.o util_hash.o -OBJS += rindex_pkgdeps.o rindex_sync.o rindex_get.o +OBJS += repo.o repo_pkgdeps.o repo_sync.o OBJS += rpool.o rpool_get.o cb_util.o OBJS += $(EXTOBJS) $(COMPAT_SRCS) diff --git a/lib/plist_archive_entry.c b/lib/archive.c similarity index 71% rename from lib/plist_archive_entry.c rename to lib/archive.c index 25f04fc4..65e803a4 100644 --- a/lib/plist_archive_entry.c +++ b/lib/archive.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2012 Juan Romero Pardines. + * Copyright (c) 2008-2013 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,7 +39,7 @@ #define _READ_CHUNK 8192 static char * -_xbps_uncompress_plist_data(char *xml, size_t len) +uncompress_plist_data(char *xml, size_t len) { z_stream strm; unsigned char *out; @@ -83,16 +83,16 @@ _xbps_uncompress_plist_data(char *xml, size_t len) strm.next_out = out; rv = inflate(&strm, Z_NO_FLUSH); switch (rv) { - case Z_DATA_ERROR: - case Z_STREAM_ERROR: - case Z_NEED_DICT: - case Z_MEM_ERROR: - case Z_BUF_ERROR: - case Z_VERSION_ERROR: - (void)inflateEnd(&strm); - free(uncomp_xml); - free(out); - return NULL; + case Z_DATA_ERROR: + case Z_STREAM_ERROR: + case Z_NEED_DICT: + case Z_MEM_ERROR: + case Z_BUF_ERROR: + case Z_VERSION_ERROR: + (void)inflateEnd(&strm); + free(uncomp_xml); + free(out); + return NULL; } have = _READ_CHUNK - strm.avail_out; totalsize += have; @@ -109,8 +109,7 @@ _xbps_uncompress_plist_data(char *xml, size_t len) #undef _READ_CHUNK prop_dictionary_t HIDDEN -xbps_dictionary_from_archive_entry(struct archive *ar, - struct archive_entry *entry) +xbps_archive_get_dictionary(struct archive *ar, struct archive_entry *entry) { prop_dictionary_t d = NULL; size_t buflen; @@ -137,7 +136,7 @@ xbps_dictionary_from_archive_entry(struct archive *ar, goto out; /* Try to uncompress blob */ - uncomp_buf = _xbps_uncompress_plist_data(buf, buflen); + uncomp_buf = uncompress_plist_data(buf, buflen); if (uncomp_buf == NULL) { /* Error while decompressing */ free(buf); @@ -152,3 +151,42 @@ out: free(buf); return d; } + +int +xbps_archive_append_buf(struct archive *ar, const void *buf, const size_t buflen, + const char *fname, const mode_t mode, const char *uname, const char *gname) +{ + struct archive_entry *entry; + time_t tm; + + assert(ar); + assert(buf); + assert(fname); + assert(uname); + assert(gname); + + tm = time(NULL); + entry = archive_entry_new(); + assert(entry); + + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_perm(entry, mode); + archive_entry_set_uname(entry, uname); + archive_entry_set_gname(entry, gname); + archive_entry_set_pathname(entry, fname); + archive_entry_set_size(entry, buflen); + archive_entry_set_atime(entry, tm, 0); + archive_entry_set_mtime(entry, tm, 0); + archive_entry_set_ctime(entry, tm, 0); + + if (archive_write_header(ar, entry) != ARCHIVE_OK) + return archive_errno(ar); + + if (archive_write_data(ar, buf, buflen) != ARCHIVE_OK) + return archive_errno(ar); + + archive_write_finish_entry(ar); + archive_entry_free(entry); + + return 0; +} diff --git a/lib/package_remove.c b/lib/package_remove.c index 036dacd8..57877d65 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -172,7 +172,6 @@ xbps_remove_pkg(struct xbps_handle *xhp, { prop_dictionary_t pkgd = NULL; char *pkgname, *buf = NULL; - const char *version; int rv = 0; pkg_state_t state = 0; @@ -181,8 +180,6 @@ xbps_remove_pkg(struct xbps_handle *xhp, pkgname = xbps_pkg_name(pkgver); assert(pkgname); - version = xbps_pkg_version(pkgver); - assert(version); if ((rv = xbps_pkg_state_installed(xhp, pkgname, &state)) != 0) goto out; diff --git a/lib/package_unpack.c b/lib/package_unpack.c index e8b2e18a..390e9220 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -281,14 +281,14 @@ unpack_archive(struct xbps_handle *xhp, continue; } else if (strcmp("./files.plist", entry_pname) == 0) { - filesd = xbps_dictionary_from_archive_entry(ar, entry); + filesd = xbps_archive_get_dictionary(ar, entry); if (filesd == NULL) { rv = errno; goto out; } continue; } else if (strcmp("./props.plist", entry_pname) == 0) { - propsd = xbps_dictionary_from_archive_entry(ar, entry); + propsd = xbps_archive_get_dictionary(ar, entry); if (propsd == NULL) { rv = errno; goto out; diff --git a/lib/plist_fetch.c b/lib/plist_fetch.c index 402e7e4f..55209cbb 100644 --- a/lib/plist_fetch.c +++ b/lib/plist_fetch.c @@ -180,7 +180,7 @@ xbps_get_pkg_plist_from_binpkg(const char *fname, const char *plistf) i++; continue; } - plistd = xbps_dictionary_from_archive_entry(a, entry); + plistd = xbps_archive_get_dictionary(a, entry); if (plistd == NULL) { errno = EINVAL; break; diff --git a/lib/repo.c b/lib/repo.c new file mode 100644 index 00000000..3896eed6 --- /dev/null +++ b/lib/repo.c @@ -0,0 +1,191 @@ +/*- + * Copyright (c) 2012-2013 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 "xbps_api_impl.h" + +/** + * @file lib/repo.c + * @brief Repository functions + * @defgroup repo Repository functions + */ +char * +xbps_repo_path(struct xbps_handle *xhp, const char *url) +{ + assert(xhp); + assert(url); + + return xbps_xasprintf("%s/%s-repodata", + url, xhp->target_arch ? xhp->target_arch : xhp->native_arch); +} + +struct xbps_repo * +xbps_repo_open(struct xbps_handle *xhp, const char *url) +{ + struct xbps_repo *repo; + const char *arch; + char *repofile; + + assert(xhp); + assert(url); + + if (xhp->target_arch) + arch = xhp->target_arch; + else + arch = xhp->native_arch; + + if (xbps_repository_is_remote(url)) { + /* remote repository */ + char *rpath; + + if ((rpath = xbps_get_remote_repo_string(url)) == NULL) + return NULL; + repofile = xbps_xasprintf("%s/%s/%s-repodata", xhp->metadir, rpath, arch); + free(rpath); + } else { + /* local repository */ + repofile = xbps_repo_path(xhp, url); + } + + repo = calloc(1, sizeof(struct xbps_repo)); + assert(repo); + + repo->xhp = xhp; + repo->uri = url; + repo->ar = archive_read_new(); + archive_read_support_filter_gzip(repo->ar); + archive_read_support_format_tar(repo->ar); + + if (archive_read_open_filename(repo->ar, repofile, ARCHIVE_READ_BLOCKSIZE)) { + xbps_dbg_printf(xhp, "cannot open repository file %s: %s\n", + repofile, strerror(archive_errno(repo->ar))); + archive_read_free(repo->ar); + free(repo); + repo = NULL; + } + free(repofile); + return repo; +} + +prop_dictionary_t +xbps_repo_get_plist(struct xbps_repo *repo, const char *file) +{ + prop_dictionary_t d; + struct archive_entry *entry; + void *buf; + size_t buflen; + ssize_t nbytes = -1; + int rv; + + assert(repo); + assert(repo->ar); + assert(file); + + for (;;) { + rv = archive_read_next_header(repo->ar, &entry); + if (rv == ARCHIVE_EOF || rv == ARCHIVE_FATAL) + break; + else if (rv == ARCHIVE_RETRY) + continue; + if (strcmp(archive_entry_pathname(entry), file) == 0) { + buflen = (size_t)archive_entry_size(entry); + buf = malloc(buflen); + assert(buf); + nbytes = archive_read_data(repo->ar, buf, buflen); + if ((size_t)nbytes != buflen) { + free(buf); + return NULL; + } + d = prop_dictionary_internalize(buf); + free(buf); + return d; + } + archive_read_data_skip(repo->ar); + } + return NULL; +} + +void +xbps_repo_close(struct xbps_repo *repo) +{ + assert(repo); + + archive_read_free(repo->ar); + if (prop_object_type(repo->idx) == PROP_TYPE_DICTIONARY) + prop_object_release(repo->idx); + if (prop_object_type(repo->idxfiles) == PROP_TYPE_DICTIONARY) + prop_object_release(repo->idxfiles); + free(repo); +} + +prop_dictionary_t +xbps_repo_get_virtualpkg(struct xbps_repo *repo, const char *pkg) +{ + prop_dictionary_t pkgd; + + assert(repo); + assert(repo->ar); + assert(pkg); + + if (prop_object_type(repo->idx) != PROP_TYPE_DICTIONARY) { + repo->idx = xbps_repo_get_plist(repo, XBPS_PKGINDEX); + assert(repo->idx); + } + pkgd = xbps_find_virtualpkg_in_dict(repo->xhp, repo->idx, pkg); + if (pkgd) { + prop_dictionary_set_cstring_nocopy(pkgd, + "repository", repo->uri); + return pkgd; + } + return NULL; +} + +prop_dictionary_t +xbps_repo_get_pkg(struct xbps_repo *repo, const char *pkg) +{ + prop_dictionary_t pkgd; + + assert(repo); + assert(repo->ar); + assert(pkg); + + if (prop_object_type(repo->idx) != PROP_TYPE_DICTIONARY) { + repo->idx = xbps_repo_get_plist(repo, XBPS_PKGINDEX); + assert(repo->idx); + } + pkgd = xbps_find_pkg_in_dict(repo->idx, pkg); + if (pkgd) { + prop_dictionary_set_cstring_nocopy(pkgd, + "repository", repo->uri); + return pkgd; + } + + return NULL; +} diff --git a/lib/rindex_pkgdeps.c b/lib/repo_pkgdeps.c similarity index 100% rename from lib/rindex_pkgdeps.c rename to lib/repo_pkgdeps.c diff --git a/lib/rindex_sync.c b/lib/repo_sync.c similarity index 91% rename from lib/rindex_sync.c rename to lib/repo_sync.c index ba42404a..171d1aa7 100644 --- a/lib/rindex_sync.c +++ b/lib/repo_sync.c @@ -72,10 +72,10 @@ xbps_get_remote_repo_string(const char *uri) * size and/or mtime match) and 1 if downloaded successfully. */ int HIDDEN -xbps_rindex_sync(struct xbps_handle *xhp, const char *uri, const char *plistf) +xbps_repo_sync(struct xbps_handle *xhp, const char *uri) { const char *arch, *fetchstr = NULL; - char *rpidx, *lrepodir, *uri_fixedp; + char *repodata, *lrepodir, *uri_fixedp; int rv = 0; assert(uri != NULL); @@ -124,24 +124,24 @@ xbps_rindex_sync(struct xbps_handle *xhp, const char *uri, const char *plistf) /* * Remote repository plist index full URL. */ - rpidx = xbps_xasprintf("%s/%s-%s", uri, arch, plistf); + repodata = xbps_xasprintf("%s/%s-repodata", uri, arch); /* reposync start cb */ - xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC, 0, rpidx, NULL); + xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC, 0, repodata, NULL); /* * Download plist index file from repository. */ - if ((rv = xbps_fetch_file(xhp, rpidx, NULL)) == -1) { + if ((rv = xbps_fetch_file(xhp, repodata, NULL)) == -1) { /* reposync error cb */ fetchstr = xbps_fetch_error_string(); xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL, fetchLastErrCode != 0 ? fetchLastErrCode : errno, NULL, "[reposync] failed to fetch file `%s': %s", - rpidx, fetchstr ? fetchstr : strerror(errno)); + repodata, fetchstr ? fetchstr : strerror(errno)); } else if (rv == 1) rv = 0; - free(rpidx); + free(repodata); return rv; } diff --git a/lib/rindex_get.c b/lib/rindex_get.c deleted file mode 100644 index 53381364..00000000 --- a/lib/rindex_get.c +++ /dev/null @@ -1,66 +0,0 @@ -/*- - * Copyright (c) 2012-2013 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 "xbps_api_impl.h" - -/** - * @file lib/rindex_get.c - * @brief Repository index functions - * @defgroup rindex Repository index functions - */ -prop_dictionary_t -xbps_rindex_get_virtualpkg(struct xbps_rindex *rpi, const char *pkg) -{ - prop_dictionary_t pkgd; - - pkgd = xbps_find_virtualpkg_in_dict(rpi->xhp, rpi->repod, pkg); - if (pkgd) { - prop_dictionary_set_cstring_nocopy(pkgd, - "repository", rpi->uri); - return pkgd; - } - return NULL; -} - -prop_dictionary_t -xbps_rindex_get_pkg(struct xbps_rindex *rpi, const char *pkg) -{ - prop_dictionary_t pkgd; - - pkgd = xbps_find_pkg_in_dict(rpi->repod, pkg); - if (pkgd) { - prop_dictionary_set_cstring_nocopy(pkgd, - "repository", rpi->uri); - return pkgd; - } - - return NULL; -} diff --git a/lib/rpool.c b/lib/rpool.c index 4bbdecb4..153ed636 100644 --- a/lib/rpool.c +++ b/lib/rpool.c @@ -33,6 +33,14 @@ #include "xbps_api_impl.h" +struct rpool { + SIMPLEQ_ENTRY(rpool) entries; + struct xbps_repo *repo; +}; + +static SIMPLEQ_HEAD(rpool_head, rpool) rpool_queue = + SIMPLEQ_HEAD_INITIALIZER(rpool_queue); + /** * @file lib/rpool.c * @brief Repository pool routines @@ -42,81 +50,45 @@ int HIDDEN xbps_rpool_init(struct xbps_handle *xhp) { - prop_dictionary_t repod, d = NULL; - size_t i, ntotal = 0, nmissing = 0; + struct rpool *rp; const char *repouri; - char *plist; + unsigned int i; + bool foundrepo = false; int rv = 0; - if (xhp->repo_pool != NULL) + assert(xhp); + + if (xhp->rpool_initialized) return 0; else if (xhp->cfg == NULL) return ENOTSUP; - xhp->repo_pool = prop_array_create(); - if (xhp->repo_pool == NULL) - return ENOMEM; - for (i = 0; i < cfg_size(xhp->cfg, "repositories"); i++) { + rp = malloc(sizeof(struct rpool)); + assert(rp); repouri = cfg_getnstr(xhp->cfg, "repositories", i); - ntotal++; - /* - * If index file is not there, skip. - */ - plist = xbps_pkg_index_plist(xhp, repouri); - if (plist == NULL) { - rv = errno; - goto out; - } - if (access(plist, R_OK) == -1) { - xbps_dbg_printf(xhp, "[rpool] `%s' cannot be " - "internalized: %s\n", repouri, strerror(errno)); - nmissing++; + if ((rp->repo = xbps_repo_open(xhp, repouri)) == NULL) { + free(rp); continue; } - repod = prop_dictionary_internalize_from_zfile(plist); - free(plist); - if (prop_object_type(repod) != PROP_TYPE_DICTIONARY) { - xbps_dbg_printf(xhp, "[rpool] `%s' cannot be " - "internalized: %s\n", repouri, strerror(errno)); - nmissing++; + rp->repo->idx = xbps_repo_get_plist(rp->repo, XBPS_PKGINDEX); + if (rp->repo->idx == NULL) { + xbps_repo_close(rp->repo); + free(rp); continue; } - /* - * Register repository into the array. - */ - if ((d = prop_dictionary_create()) == NULL) { - rv = ENOMEM; - prop_object_release(repod); - goto out; - } - if (!prop_dictionary_set_cstring_nocopy(d, "uri", repouri)) { - rv = EINVAL; - prop_object_release(repod); - prop_object_release(d); - goto out; - } - if (!prop_dictionary_set(d, "index", repod)) { - rv = EINVAL; - prop_object_release(repod); - prop_object_release(d); - goto out; - } - prop_object_release(repod); - if (!prop_array_add(xhp->repo_pool, d)) { - rv = EINVAL; - prop_object_release(d); - goto out; - } + rp->repo->uri = repouri; + rp->repo->xhp = xhp; + SIMPLEQ_INSERT_TAIL(&rpool_queue, rp, entries); + foundrepo = true; xbps_dbg_printf(xhp, "[rpool] `%s' registered.\n", repouri); } - if (ntotal - nmissing == 0) { + if (!foundrepo) { /* no repositories available, error out */ rv = ENOTSUP; goto out; } - - prop_array_make_immutable(xhp->repo_pool); + xhp->rpool_initialized = true; xbps_dbg_printf(xhp, "[rpool] initialized ok.\n"); out: if (rv != 0) @@ -129,29 +101,22 @@ out: void HIDDEN xbps_rpool_release(struct xbps_handle *xhp) { - prop_dictionary_t d; - size_t i; - const char *uri; + struct rpool *rp; - if (xhp->repo_pool == NULL) + if (!xhp->rpool_initialized) return; - for (i = 0; i < prop_array_count(xhp->repo_pool); i++) { - d = prop_array_get(xhp->repo_pool, i); - if (xhp->flags & XBPS_FLAG_DEBUG) { - prop_dictionary_get_cstring_nocopy(d, "uri", &uri); - xbps_dbg_printf(xhp, "[rpool] unregistered " - "repository '%s'\n", uri); - } - prop_object_release(d); + while ((rp = SIMPLEQ_FIRST(&rpool_queue))) { + SIMPLEQ_REMOVE(&rpool_queue, rp, rpool, entries); + xbps_repo_close(rp->repo); + free(rp); } - prop_object_release(xhp->repo_pool); - xhp->repo_pool = NULL; + xhp->rpool_initialized = false; xbps_dbg_printf(xhp, "[rpool] released ok.\n"); } int -xbps_rpool_sync(struct xbps_handle *xhp, const char *file, const char *uri) +xbps_rpool_sync(struct xbps_handle *xhp, const char *uri) { const char *repouri; size_t i; @@ -165,11 +130,10 @@ xbps_rpool_sync(struct xbps_handle *xhp, const char *file, const char *uri) if (uri && strcmp(repouri, uri)) continue; - if (xbps_rindex_sync(xhp, repouri, file) == -1) { + if (xbps_repo_sync(xhp, repouri) == -1) { xbps_dbg_printf(xhp, - "[rpool] `%s' failed to fetch `%s': %s\n", - repouri, file, - fetchLastErrCode == 0 ? strerror(errno) : + "[rpool] `%s' failed to fetch repository data: %s\n", + repouri, fetchLastErrCode == 0 ? strerror(errno) : xbps_fetch_error_string()); continue; } @@ -179,12 +143,10 @@ xbps_rpool_sync(struct xbps_handle *xhp, const char *file, const char *uri) int xbps_rpool_foreach(struct xbps_handle *xhp, - int (*fn)(struct xbps_rindex *, void *, bool *), + int (*fn)(struct xbps_repo *, void *, bool *), void *arg) { - prop_dictionary_t d; - struct xbps_rindex rpi; - size_t i; + struct rpool *rp; int rv = 0; bool done = false; @@ -202,12 +164,8 @@ xbps_rpool_foreach(struct xbps_handle *xhp, return rv; } /* Iterate over repository pool */ - for (i = 0; i < prop_array_count(xhp->repo_pool); i++) { - d = prop_array_get(xhp->repo_pool, i); - prop_dictionary_get_cstring_nocopy(d, "uri", &rpi.uri); - rpi.repod = prop_dictionary_get(d, "index"); - rpi.xhp = xhp; - rv = (*fn)(&rpi, arg, &done); + SIMPLEQ_FOREACH(rp, &rpool_queue, entries) { + rv = (*fn)(rp->repo, arg, &done); if (rv != 0 || done) break; } diff --git a/lib/rpool_get.c b/lib/rpool_get.c index 755ba216..07658ab3 100644 --- a/lib/rpool_get.c +++ b/lib/rpool_get.c @@ -44,11 +44,11 @@ struct rpool_fpkg { }; static int -find_virtualpkg_cb(struct xbps_rindex *rpi, void *arg, bool *done) +find_virtualpkg_cb(struct xbps_repo *repo, void *arg, bool *done) { struct rpool_fpkg *rpf = arg; - rpf->pkgd = xbps_rindex_get_virtualpkg(rpi, rpf->pattern); + rpf->pkgd = xbps_repo_get_virtualpkg(repo, rpf->pattern); if (rpf->pkgd) { /* found */ *done = true; @@ -59,11 +59,11 @@ find_virtualpkg_cb(struct xbps_rindex *rpi, void *arg, bool *done) } static int -find_pkg_cb(struct xbps_rindex *rpi, void *arg, bool *done) +find_pkg_cb(struct xbps_repo *repo, void *arg, bool *done) { struct rpool_fpkg *rpf = arg; - rpf->pkgd = xbps_rindex_get_pkg(rpi, rpf->pattern); + rpf->pkgd = xbps_repo_get_pkg(repo, rpf->pattern); if (rpf->pkgd) { /* found */ *done = true; @@ -74,7 +74,7 @@ find_pkg_cb(struct xbps_rindex *rpi, void *arg, bool *done) } static int -find_best_pkg_cb(struct xbps_rindex *rpi, void *arg, bool *done) +find_best_pkg_cb(struct xbps_repo *repo, void *arg, bool *done) { struct rpool_fpkg *rpf = arg; prop_dictionary_t pkgd; @@ -82,25 +82,25 @@ find_best_pkg_cb(struct xbps_rindex *rpi, void *arg, bool *done) (void)done; - pkgd = xbps_rindex_get_pkg(rpi, rpf->pattern); + pkgd = xbps_repo_get_pkg(repo, rpf->pattern); if (pkgd == NULL) { if (errno && errno != ENOENT) return errno; - xbps_dbg_printf(rpi->xhp, + xbps_dbg_printf(repo->xhp, "[rpool] Package '%s' not found in repository " - "'%s'.\n", rpf->pattern, rpi->uri); + "'%s'.\n", rpf->pattern, repo->uri); return 0; } prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &repopkgver); if (rpf->bestpkgver == NULL) { - xbps_dbg_printf(rpi->xhp, + xbps_dbg_printf(repo->xhp, "[rpool] Found best match '%s' (%s).\n", - repopkgver, rpi->uri); + repopkgver, repo->uri); rpf->pkgd = pkgd; prop_dictionary_set_cstring_nocopy(rpf->pkgd, - "repository", rpi->uri); + "repository", repo->uri); rpf->bestpkgver = repopkgver; return 0; } @@ -109,12 +109,12 @@ find_best_pkg_cb(struct xbps_rindex *rpi, void *arg, bool *done) * version from current package in repository. */ if (xbps_cmpver(repopkgver, rpf->bestpkgver) == 1) { - xbps_dbg_printf(rpi->xhp, + xbps_dbg_printf(repo->xhp, "[rpool] Found best match '%s' (%s).\n", - repopkgver, rpi->uri); + repopkgver, repo->uri); rpf->pkgd = pkgd; prop_dictionary_set_cstring_nocopy(rpf->pkgd, - "repository", rpi->uri); + "repository", repo->uri); rpf->bestpkgver = repopkgver; } return 0; diff --git a/lib/transaction_commit.c b/lib/transaction_commit.c index e1edf7bd..09d41a66 100644 --- a/lib/transaction_commit.c +++ b/lib/transaction_commit.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include diff --git a/lib/util.c b/lib/util.c index c3da802e..88e3d7a8 100644 --- a/lib/util.c +++ b/lib/util.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2012 Juan Romero Pardines. + * Copyright (c) 2008-2013 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,6 +27,10 @@ # define _GNU_SOURCE /* for vasprintf(3) */ #endif +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -36,9 +40,6 @@ #include #include -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif #include "xbps_api_impl.h" #ifdef __clang__ @@ -170,69 +171,6 @@ xbps_pkgpattern_version(const char *pkg) return strpbrk(pkg, "><*?[]"); } -static char * -get_pkg_index_remote_plist(struct xbps_handle *xhp, - const char *uri, - const char *plistf) -{ - const char *arch; - char *uri_fixed, *repodir; - - assert(uri != NULL); - - uri_fixed = xbps_get_remote_repo_string(uri); - if (uri_fixed == NULL) - return NULL; - - if (xhp->target_arch) - arch = xhp->target_arch; - else - arch = xhp->native_arch; - - repodir = xbps_xasprintf("%s/%s/%s-%s", xhp->metadir, - uri_fixed, arch, plistf); - free(uri_fixed); - return repodir; -} - -char * -xbps_pkg_index_plist(struct xbps_handle *xhp, const char *uri) -{ - const char *arch; - - assert(xhp); - assert(uri != NULL); - - if (xbps_repository_is_remote(uri)) - return get_pkg_index_remote_plist(xhp, uri, XBPS_PKGINDEX); - - if (xhp->target_arch) - arch = xhp->target_arch; - else - arch = xhp->native_arch; - - return xbps_xasprintf("%s/%s-%s", uri, arch, XBPS_PKGINDEX); -} - -char * -xbps_pkg_index_files_plist(struct xbps_handle *xhp, const char *uri) -{ - const char *arch; - - assert(xhp); - assert(uri != NULL); - - if (xbps_repository_is_remote(uri)) - return get_pkg_index_remote_plist(xhp, uri, XBPS_PKGINDEX_FILES); - - if (xhp->target_arch) - arch = xhp->target_arch; - else - arch = xhp->native_arch; - - return xbps_xasprintf("%s/%s-%s", uri, arch, XBPS_PKGINDEX_FILES); -} - char HIDDEN * xbps_repository_pkg_path(struct xbps_handle *xhp, prop_dictionary_t pkg_repod) {