XBPS Library API 20240111
The X Binary Package System
rpool.c
1/*-
2 * Copyright (c) 2009-2015 Juan Romero Pardines.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <sys/utsname.h>
27#include <stdio.h>
28#include <stdbool.h>
29#include <stdlib.h>
30#include <libgen.h>
31#include <string.h>
32#include <errno.h>
33
34#include "xbps_api_impl.h"
35#include "fetch.h"
36
37struct rpool_fpkg {
38 xbps_array_t revdeps;
39 xbps_dictionary_t pkgd;
40 const char *pattern;
41 const char *bestpkgver;
42 bool best;
43};
44
45typedef enum {
46 BEST_PKG = 1,
47 VIRTUAL_PKG,
48 REAL_PKG,
49 REVDEPS_PKG
50} pkg_repo_type_t;
51
52static SIMPLEQ_HEAD(rpool_head, xbps_repo) rpool_queue =
53 SIMPLEQ_HEAD_INITIALIZER(rpool_queue);
54
55/**
56 * @file lib/rpool.c
57 * @brief Repository pool routines
58 * @defgroup repopool Repository pool functions
59 */
60
61int
62xbps_rpool_sync(struct xbps_handle *xhp, const char *uri)
63{
64 const char *repouri = NULL;
65
66 for (unsigned int i = 0; i < xbps_array_count(xhp->repositories); i++) {
67 xbps_array_get_cstring_nocopy(xhp->repositories, i, &repouri);
68 /* If argument was set just process that repository */
69 if (uri && strcmp(repouri, uri))
70 continue;
71
72 if (xbps_repo_sync(xhp, repouri) == -1) {
73 xbps_dbg_printf(
74 "[rpool] `%s' failed to fetch repository data: %s\n",
75 repouri, fetchLastErrCode == 0 ? strerror(errno) :
77 continue;
78 }
79 }
80 return 0;
81}
82
83struct xbps_repo HIDDEN *
84xbps_regget_repo(struct xbps_handle *xhp, const char *url)
85{
86 struct xbps_repo *repo;
87 const char *repouri = NULL;
88
89 if (SIMPLEQ_EMPTY(&rpool_queue)) {
90 /* iterate until we have a match */
91 for (unsigned int i = 0; i < xbps_array_count(xhp->repositories); i++) {
92 xbps_array_get_cstring_nocopy(xhp->repositories, i, &repouri);
93 if (strcmp(repouri, url))
94 continue;
95
96 repo = xbps_repo_open(xhp, repouri);
97 if (!repo)
98 return NULL;
99
100 SIMPLEQ_INSERT_TAIL(&rpool_queue, repo, entries);
101 xbps_dbg_printf("[rpool] `%s' registered.\n", repouri);
102 }
103 }
104 SIMPLEQ_FOREACH(repo, &rpool_queue, entries)
105 if (strcmp(url, repo->uri) == 0)
106 return repo;
107
108 return NULL;
109}
110
111struct xbps_repo *
112xbps_rpool_get_repo(const char *url)
113{
114 struct xbps_repo *repo;
115
116 SIMPLEQ_FOREACH(repo, &rpool_queue, entries)
117 if (strcmp(url, repo->uri) == 0)
118 return repo;
119
120 return NULL;
121}
122
123void
124xbps_rpool_release(struct xbps_handle *xhp)
125{
126 struct xbps_repo *repo;
127
128 while ((repo = SIMPLEQ_FIRST(&rpool_queue))) {
129 SIMPLEQ_REMOVE(&rpool_queue, repo, xbps_repo, entries);
130 xbps_repo_release(repo);
131 }
132 if (xhp && xhp->repositories) {
133 xbps_object_release(xhp->repositories);
134 xhp->repositories = NULL;
135 }
136}
137
138int
140 int (*fn)(struct xbps_repo *, void *, bool *),
141 void *arg)
142{
143 struct xbps_repo *repo = NULL;
144 const char *repouri = NULL;
145 int rv = 0;
146 bool foundrepo = false, done = false;
147 unsigned int n = 0;
148
149 assert(fn != NULL);
150
151again:
152 for (unsigned int i = n; i < xbps_array_count(xhp->repositories); i++, n++) {
153 xbps_array_get_cstring_nocopy(xhp->repositories, i, &repouri);
154 xbps_dbg_printf("[rpool] checking `%s' at index %u\n", repouri, n);
155 if ((repo = xbps_rpool_get_repo(repouri)) == NULL) {
156 repo = xbps_repo_open(xhp, repouri);
157 if (!repo) {
158 xbps_repo_remove(xhp, repouri);
159 goto again;
160 }
161 SIMPLEQ_INSERT_TAIL(&rpool_queue, repo, entries);
162 xbps_dbg_printf("[rpool] `%s' registered.\n", repouri);
163 }
164 foundrepo = true;
165 rv = (*fn)(repo, arg, &done);
166 if (rv != 0 || done)
167 break;
168 }
169 if (!foundrepo)
170 rv = ENOTSUP;
171
172 return rv;
173}
174
175static int
176find_virtualpkg_cb(struct xbps_repo *repo, void *arg, bool *done)
177{
178 struct rpool_fpkg *rpf = arg;
179
180 rpf->pkgd = xbps_repo_get_virtualpkg(repo, rpf->pattern);
181 if (rpf->pkgd) {
182 /* found */
183 *done = true;
184 return 0;
185 }
186 /* not found */
187 return 0;
188}
189
190static int
191find_pkg_cb(struct xbps_repo *repo, void *arg, bool *done)
192{
193 struct rpool_fpkg *rpf = arg;
194
195 rpf->pkgd = xbps_repo_get_pkg(repo, rpf->pattern);
196 if (rpf->pkgd) {
197 /* found */
198 *done = true;
199 return 0;
200 }
201 /* Not found */
202 return 0;
203}
204
205static int
206find_pkg_revdeps_cb(struct xbps_repo *repo, void *arg, bool *done UNUSED)
207{
208 struct rpool_fpkg *rpf = arg;
209 xbps_array_t revdeps = NULL;
210 const char *pkgver = NULL;
211
212 revdeps = xbps_repo_get_pkg_revdeps(repo, rpf->pattern);
213 if (xbps_array_count(revdeps)) {
214 /* found */
215 if (rpf->revdeps == NULL)
216 rpf->revdeps = xbps_array_create();
217 for (unsigned int i = 0; i < xbps_array_count(revdeps); i++) {
218 xbps_array_get_cstring_nocopy(revdeps, i, &pkgver);
219 xbps_array_add_cstring_nocopy(rpf->revdeps, pkgver);
220 }
221 xbps_object_release(revdeps);
222 }
223 return 0;
224}
225
226static int
227find_best_pkg_cb(struct xbps_repo *repo, void *arg, bool *done UNUSED)
228{
229 struct rpool_fpkg *rpf = arg;
230 xbps_dictionary_t pkgd;
231 const char *repopkgver = NULL;
232
233 pkgd = xbps_repo_get_pkg(repo, rpf->pattern);
234 if (pkgd == NULL) {
235 if (errno && errno != ENOENT)
236 return errno;
237
238 xbps_dbg_printf("[rpool] Package '%s' not found in repository"
239 " '%s'.\n", rpf->pattern, repo->uri);
240 return 0;
241 }
242 xbps_dictionary_get_cstring_nocopy(pkgd,
243 "pkgver", &repopkgver);
244 if (rpf->bestpkgver == NULL) {
245 xbps_dbg_printf("[rpool] Found match '%s' (%s).\n",
246 repopkgver, repo->uri);
247 rpf->pkgd = pkgd;
248 rpf->bestpkgver = repopkgver;
249 return 0;
250 }
251 /*
252 * Compare current stored version against new
253 * version from current package in repository.
254 */
255 if (xbps_cmpver(repopkgver, rpf->bestpkgver) == 1) {
256 xbps_dbg_printf("[rpool] Found best match '%s' (%s).\n",
257 repopkgver, repo->uri);
258 rpf->pkgd = pkgd;
259 rpf->bestpkgver = repopkgver;
260 }
261 return 0;
262}
263
264static xbps_object_t
265repo_find_pkg(struct xbps_handle *xhp,
266 const char *pkg,
267 pkg_repo_type_t type)
268{
269 struct rpool_fpkg rpf;
270 int rv = 0;
271
272 assert(xhp);
273 assert(pkg);
274
275 rpf.pattern = pkg;
276 rpf.pkgd = NULL;
277 rpf.revdeps = NULL;
278 rpf.bestpkgver = NULL;
279
280 switch (type) {
281 case BEST_PKG:
282 /*
283 * Find best pkg version.
284 */
285 rv = xbps_rpool_foreach(xhp, find_best_pkg_cb, &rpf);
286 break;
287 case VIRTUAL_PKG:
288 /*
289 * Find virtual pkg.
290 */
291 rv = xbps_rpool_foreach(xhp, find_virtualpkg_cb, &rpf);
292 break;
293 case REAL_PKG:
294 /*
295 * Find real pkg.
296 */
297 rv = xbps_rpool_foreach(xhp, find_pkg_cb, &rpf);
298 break;
299 case REVDEPS_PKG:
300 /*
301 * Find revdeps for pkg.
302 */
303 rv = xbps_rpool_foreach(xhp, find_pkg_revdeps_cb, &rpf);
304 break;
305 }
306 if (rv != 0) {
307 errno = rv;
308 return NULL;
309 }
310 if (type == REVDEPS_PKG) {
311 if (rpf.revdeps == NULL)
312 errno = ENOENT;
313
314 return rpf.revdeps;
315 } else {
316 if (rpf.pkgd == NULL)
317 errno = ENOENT;
318 }
319 return rpf.pkgd;
320}
321
322xbps_dictionary_t
323xbps_rpool_get_virtualpkg(struct xbps_handle *xhp, const char *pkg)
324{
325 return repo_find_pkg(xhp, pkg, VIRTUAL_PKG);
326}
327
328xbps_dictionary_t
329xbps_rpool_get_pkg(struct xbps_handle *xhp, const char *pkg)
330{
331 if (xhp->flags & XBPS_FLAG_BESTMATCH)
332 return repo_find_pkg(xhp, pkg, BEST_PKG);
333
334 return repo_find_pkg(xhp, pkg, REAL_PKG);
335}
336
337xbps_array_t
338xbps_rpool_get_pkg_revdeps(struct xbps_handle *xhp, const char *pkg)
339{
340 return repo_find_pkg(xhp, pkg, REVDEPS_PKG);
341}
342
343xbps_array_t
344xbps_rpool_get_pkg_fulldeptree(struct xbps_handle *xhp, const char *pkg)
345{
346 return xbps_get_pkg_fulldeptree(xhp, pkg, true);
347}
const char * xbps_fetch_error_string(void)
Definition download.c:89
xbps_array_t repositories
Definition xbps.h:563
int flags
Definition xbps.h:679
Generic XBPS structure handler for initialization.
Definition xbps.h:550
xbps_dictionary_t xbps_repo_get_pkg(struct xbps_repo *repo, const char *pkg)
Definition repo.c:441
struct xbps_repo * xbps_repo_open(struct xbps_handle *xhp, const char *uri)
Definition repo.c:340
void xbps_repo_release(struct xbps_repo *repo)
Definition repo.c:388
bool xbps_repo_remove(struct xbps_handle *xhp, const char *url)
Definition repo.c:306
xbps_dictionary_t xbps_repo_get_virtualpkg(struct xbps_repo *repo, const char *pkg)
Definition repo.c:407
xbps_array_t xbps_repo_get_pkg_revdeps(struct xbps_repo *repo, const char *pkg)
Definition repo.c:569
struct xbps_handle * xhp
Definition xbps.h:1422
const char * uri
Definition xbps.h:1440
Repository structure.
Definition xbps.h:1409
int xbps_rpool_foreach(struct xbps_handle *xhp, int(*fn)(struct xbps_repo *, void *, bool *), void *arg)
Definition rpool.c:139
struct xbps_repo * xbps_rpool_get_repo(const char *url)
Definition rpool.c:112
xbps_dictionary_t xbps_rpool_get_virtualpkg(struct xbps_handle *xhp, const char *pkg)
Definition rpool.c:323
xbps_dictionary_t xbps_rpool_get_pkg(struct xbps_handle *xhp, const char *pkg)
Definition rpool.c:329
xbps_array_t xbps_rpool_get_pkg_fulldeptree(struct xbps_handle *xhp, const char *pkg)
Definition rpool.c:344
xbps_array_t xbps_rpool_get_pkg_revdeps(struct xbps_handle *xhp, const char *pkg)
Definition rpool.c:338
int xbps_rpool_sync(struct xbps_handle *xhp, const char *uri)
int xbps_cmpver(const char *pkg1, const char *pkg2)
Definition dewey.c:273