XBPS Library API  0.19
The X Binary Package System
rpool_get.c
1 /*-
2  * Copyright (c) 2009-2012 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 <stdio.h>
27 #include <stdbool.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 
32 #include "xbps_api_impl.h"
33 
34 /**
35  * @file lib/rpool_get.c
36  * @brief Repository pool functions
37  * @defgroup repopool Repository pool functions
38  */
39 struct rpool_fpkg {
40  prop_dictionary_t pkgd;
41  const char *pattern;
42  const char *bestpkgver;
43  bool best;
44 };
45 
46 static int
47 find_virtualpkg_cb(struct xbps_rindex *rpi, void *arg, bool *done)
48 {
49  struct rpool_fpkg *rpf = arg;
50 
51  rpf->pkgd = xbps_rindex_get_virtualpkg(rpi, rpf->pattern);
52  if (rpf->pkgd) {
53  /* found */
54  *done = true;
55  return 0;
56  }
57  /* not found */
58  return 0;
59 }
60 
61 static int
62 find_pkg_cb(struct xbps_rindex *rpi, void *arg, bool *done)
63 {
64  struct rpool_fpkg *rpf = arg;
65 
66  rpf->pkgd = xbps_rindex_get_pkg(rpi, rpf->pattern);
67  if (rpf->pkgd) {
68  /* found */
69  *done = true;
70  return 0;
71  }
72  /* Not found */
73  return 0;
74 }
75 
76 static int
77 find_best_pkg_cb(struct xbps_rindex *rpi, void *arg, bool *done)
78 {
79  struct rpool_fpkg *rpf = arg;
80  prop_dictionary_t pkgd;
81  const char *repopkgver;
82 
83  (void)done;
84 
85  pkgd = xbps_rindex_get_pkg(rpi, rpf->pattern);
86  if (pkgd == NULL) {
87  if (errno && errno != ENOENT)
88  return errno;
89 
90  xbps_dbg_printf(rpi->xhp,
91  "[rpool] Package '%s' not found in repository "
92  "'%s'.\n", rpf->pattern, rpi->uri);
93  return 0;
94  }
95  prop_dictionary_get_cstring_nocopy(pkgd,
96  "pkgver", &repopkgver);
97  if (rpf->bestpkgver == NULL) {
98  xbps_dbg_printf(rpi->xhp,
99  "[rpool] Found best match '%s' (%s).\n",
100  repopkgver, rpi->uri);
101  rpf->pkgd = pkgd;
102  prop_dictionary_set_cstring_nocopy(rpf->pkgd,
103  "repository", rpi->uri);
104  rpf->bestpkgver = repopkgver;
105  return 0;
106  }
107  /*
108  * Compare current stored version against new
109  * version from current package in repository.
110  */
111  if (xbps_cmpver(repopkgver, rpf->bestpkgver) == 1) {
112  xbps_dbg_printf(rpi->xhp,
113  "[rpool] Found best match '%s' (%s).\n",
114  repopkgver, rpi->uri);
115  rpf->pkgd = pkgd;
116  prop_dictionary_set_cstring_nocopy(rpf->pkgd,
117  "repository", rpi->uri);
118  rpf->bestpkgver = repopkgver;
119  }
120  return 0;
121 }
122 
123 typedef enum {
124  BEST_PKG = 1,
125  VIRTUAL_PKG,
126  REAL_PKG
127 } pkg_repo_type_t;
128 
129 static prop_dictionary_t
130 repo_find_pkg(struct xbps_handle *xhp,
131  const char *pkg,
132  pkg_repo_type_t type)
133 {
134  struct rpool_fpkg rpf;
135  int rv = 0;
136 
137  rpf.pattern = pkg;
138  rpf.pkgd = NULL;
139  rpf.bestpkgver = NULL;
140 
141  switch (type) {
142  case BEST_PKG:
143  /*
144  * Find best pkg version.
145  */
146  rv = xbps_rpool_foreach(xhp, find_best_pkg_cb, &rpf);
147  break;
148  case VIRTUAL_PKG:
149  /*
150  * Find virtual pkg.
151  */
152  rv = xbps_rpool_foreach(xhp, find_virtualpkg_cb, &rpf);
153  break;
154  case REAL_PKG:
155  /*
156  * Find real pkg.
157  */
158  rv = xbps_rpool_foreach(xhp, find_pkg_cb, &rpf);
159  break;
160  }
161  if (rv != 0) {
162  errno = rv;
163  return NULL;
164  }
165 
166  return rpf.pkgd;
167 }
168 
169 prop_dictionary_t
170 xbps_rpool_get_virtualpkg(struct xbps_handle *xhp, const char *pkg)
171 {
172  assert(xhp);
173  assert(pkg);
174 
175  return repo_find_pkg(xhp, pkg, VIRTUAL_PKG);
176 }
177 
178 prop_dictionary_t
179 xbps_rpool_get_pkg(struct xbps_handle *xhp, const char *pkg)
180 {
181  assert(xhp);
182  assert(pkg);
183 
184  if (!xbps_pkgpattern_version(pkg) && !xbps_pkg_version(pkg))
185  return repo_find_pkg(xhp, pkg, BEST_PKG);
186 
187  return repo_find_pkg(xhp, pkg, REAL_PKG);
188 }
189 
190 prop_dictionary_t
192  const char *pkg,
193  const char *plistf)
194 {
195  prop_dictionary_t pkgd = NULL, plistd = NULL;
196  char *url;
197 
198  assert(pkg != NULL);
199  assert(plistf != NULL);
200  /*
201  * Iterate over the the repository pool and search for a plist file
202  * in the binary package matching `pattern'. The plist file will be
203  * internalized to a proplib dictionary.
204  *
205  * The first repository that has it wins and the loop is stopped.
206  * This will work locally and remotely, thanks to libarchive and
207  * libfetch!
208  */
209  pkgd = xbps_rpool_get_pkg(xhp, pkg);
210  if (pkgd == NULL)
211  goto out;
212 
213  url = xbps_repository_pkg_path(xhp, pkgd);
214  if (url == NULL) {
215  errno = EINVAL;
216  goto out;
217  }
218  plistd = xbps_get_pkg_plist_from_binpkg(url, plistf);
219  free(url);
220 
221 out:
222  if (plistd == NULL)
223  errno = ENOENT;
224 
225  return plistd;
226 }