XBPS Library API 20240111
The X Binary Package System
plist_fetch.c
1/*-
2 * Copyright (c) 2009-2014 Juan Romero Pardines.
3 * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg (at) NetBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *-
26 * From: $NetBSD: pkg_io.c,v 1.9 2009/08/16 21:10:15 joerg Exp $
27 */
28
29#include <errno.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include <archive.h>
35#include <archive_entry.h>
36
37#include "xbps_api_impl.h"
38#include "fetch.h"
39
40/**
41 * @file lib/plist_fetch.c
42 * @brief Package URL metadata files handling
43 * @defgroup plist_fetch Package URL metadata files handling
44 */
45
46struct fetch_archive {
47 struct url *url;
48 struct fetchIO *fetch;
49 char buffer[32768];
50};
51
52static int
53fetch_archive_open(struct archive *a UNUSED, void *client_data)
54{
55 struct fetch_archive *f = client_data;
56
57 f->fetch = fetchGet(f->url, NULL);
58
59 if (f->fetch == NULL)
60 return ENOENT;
61
62 return 0;
63}
64
65static ssize_t
66fetch_archive_read(struct archive *a UNUSED, void *client_data, const void **buf)
67{
68 struct fetch_archive *f = client_data;
69
70 *buf = f->buffer;
71 return fetchIO_read(f->fetch, f->buffer, sizeof(f->buffer));
72}
73
74static int
75fetch_archive_close(struct archive *a UNUSED, void *client_data)
76{
77 struct fetch_archive *f = client_data;
78
79 if (f->fetch != NULL)
80 fetchIO_close(f->fetch);
81 free(f);
82
83 return 0;
84}
85
86static struct archive *
87open_archive_by_url(struct url *url)
88{
89 struct fetch_archive *f;
90 struct archive *a;
91
92 f = malloc(sizeof(struct fetch_archive));
93 if (f == NULL)
94 return NULL;
95
96 f->url = url;
97
98 if ((a = archive_read_new()) == NULL) {
99 free(f);
100 return NULL;
101 }
102 archive_read_support_filter_gzip(a);
103 archive_read_support_filter_bzip2(a);
104 archive_read_support_filter_xz(a);
105 archive_read_support_filter_lz4(a);
106 archive_read_support_filter_zstd(a);
107 archive_read_support_format_tar(a);
108
109 if (archive_read_open(a, f, fetch_archive_open, fetch_archive_read,
110 fetch_archive_close) != ARCHIVE_OK) {
111 archive_read_free(a);
112 return NULL;
113 }
114
115 return a;
116}
117
118static struct archive *
119open_archive(const char *url)
120{
121 struct url *u;
122 struct archive *a;
123
124 if (!xbps_repository_is_remote(url)) {
125 if ((a = archive_read_new()) == NULL)
126 return NULL;
127
128 archive_read_support_filter_gzip(a);
129 archive_read_support_filter_bzip2(a);
130 archive_read_support_filter_xz(a);
131 archive_read_support_filter_lz4(a);
132 archive_read_support_filter_zstd(a);
133 archive_read_support_format_tar(a);
134
135 /* XXX: block size? */
136 if (archive_read_open_filename(a, url, 32768) != ARCHIVE_OK) {
137 archive_read_free(a);
138 return NULL;
139 }
140 return a;
141 }
142
143 if ((u = fetchParseURL(url)) == NULL)
144 return NULL;
145
146 a = open_archive_by_url(u);
147 fetchFreeURL(u);
148
149 return a;
150}
151
152char *
153xbps_archive_fetch_file(const char *url, const char *fname)
154{
155 struct archive *a;
156 struct archive_entry *entry;
157 char *buf = NULL;
158
159 assert(url);
160 assert(fname);
161
162 if ((a = open_archive(url)) == NULL)
163 return NULL;
164
165 while ((archive_read_next_header(a, &entry)) == ARCHIVE_OK) {
166 const char *bfile;
167
168 bfile = archive_entry_pathname(entry);
169 if (bfile[0] == '.')
170 bfile++; /* skip first dot */
171
172 if (strcmp(bfile, fname) == 0) {
173 buf = xbps_archive_get_file(a, entry);
174 break;
175 }
176 archive_read_data_skip(a);
177 }
178 archive_read_free(a);
179
180 return buf;
181}
182
183bool
184xbps_repo_fetch_remote(struct xbps_repo *repo, const char *url)
185{
186 struct archive *a;
187 struct archive_entry *entry;
188 uint8_t i = 0;
189
190 assert(url);
191 assert(repo);
192
193 if ((a = open_archive(url)) == NULL)
194 return false;
195
196 while ((archive_read_next_header(a, &entry)) == ARCHIVE_OK) {
197 const char *bfile;
198 char *buf;
199
200 bfile = archive_entry_pathname(entry);
201 if (bfile[0] == '.')
202 bfile++; /* skip first dot */
203
204 if (strcmp(bfile, XBPS_REPOIDX_META) == 0) {
205 buf = xbps_archive_get_file(a, entry);
206 repo->idxmeta = xbps_dictionary_internalize(buf);
207 free(buf);
208 i++;
209 } else if (strcmp(bfile, XBPS_REPOIDX) == 0) {
210 buf = xbps_archive_get_file(a, entry);
211 repo->idx = xbps_dictionary_internalize(buf);
212 free(buf);
213 i++;
214 } else {
215 archive_read_data_skip(a);
216 }
217 if (i == 2)
218 break;
219 }
220 archive_read_free(a);
221
222 if (xbps_object_type(repo->idxmeta) == XBPS_TYPE_DICTIONARY)
223 repo->is_signed = true;
224
225 if (xbps_object_type(repo->idx) == XBPS_TYPE_DICTIONARY)
226 return true;
227
228 return false;
229}
230
231int
232xbps_archive_fetch_file_into_fd(const char *url, const char *fname, int fd)
233{
234 struct archive *a;
235 struct archive_entry *entry;
236 int rv = 0;
237
238 assert(url);
239 assert(fname);
240 assert(fd != -1);
241
242 if ((a = open_archive(url)) == NULL)
243 return EINVAL;
244
245 for (;;) {
246 const char *bfile;
247 rv = archive_read_next_header(a, &entry);
248 if (rv == ARCHIVE_EOF) {
249 rv = 0;
250 break;
251 }
252 if (rv == ARCHIVE_FATAL) {
253 const char *error = archive_error_string(a);
254 if (error != NULL) {
255 xbps_error_printf(
256 "Reading archive entry from: %s: %s\n",
257 url, error);
258 } else {
259 xbps_error_printf(
260 "Reading archive entry from: %s: %s\n",
261 url, strerror(archive_errno(a)));
262 }
263 rv = archive_errno(a);
264 break;
265 }
266 bfile = archive_entry_pathname(entry);
267 if (bfile[0] == '.')
268 bfile++; /* skip first dot */
269
270 if (strcmp(bfile, fname) == 0) {
271 rv = archive_read_data_into_fd(a, fd);
272 if (rv != ARCHIVE_OK)
273 rv = archive_errno(a);
274 break;
275 }
276 archive_read_data_skip(a);
277 }
278 archive_read_free(a);
279
280 return rv;
281}
282
283xbps_dictionary_t
284xbps_archive_fetch_plist(const char *url, const char *plistf)
285{
286 xbps_dictionary_t d;
287 char *buf;
288
289 if ((buf = xbps_archive_fetch_file(url, plistf)) == NULL)
290 return NULL;
291
292 d = xbps_dictionary_internalize(buf);
293 free(buf);
294 return d;
295}
char * xbps_archive_fetch_file(const char *url, const char *fname)
xbps_dictionary_t xbps_archive_fetch_plist(const char *url, const char *plistf)
int xbps_archive_fetch_file_into_fd(const char *url, const char *fname, int fd)
bool xbps_repo_fetch_remote(struct xbps_repo *repo, const char *url)
bool is_signed
Definition xbps.h:1456
xbps_dictionary_t idxmeta
Definition xbps.h:1434
xbps_dictionary_t idx
Definition xbps.h:1428
Repository structure.
Definition xbps.h:1409
bool xbps_repository_is_remote(const char *uri)
Definition util.c:66