1 /* $NetBSD: pkg_io.c,v 1.9 2009/08/16 21:10:15 joerg Exp $ */
3 * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/cdefs.h>
39 __RCSID("$NetBSD: pkg_io.c,v 1.9 2009/08/16 21:10:15 joerg Exp $");
42 #include <archive_entry.h>
55 TAILQ_ENTRY(pkg_path
) pl_link
;
59 static char *orig_cwd
, *last_toplevel
;
60 static TAILQ_HEAD(, pkg_path
) pkg_path
= TAILQ_HEAD_INITIALIZER(pkg_path
);
62 struct fetch_archive
{
69 fetch_archive_open(struct archive
*a
, void *client_data
)
71 struct fetch_archive
*f
= client_data
;
73 f
->fetch
= fetchGet(f
->url
, fetch_flags
);
80 fetch_archive_read(struct archive
*a
, void *client_data
,
83 struct fetch_archive
*f
= client_data
;
86 return fetchIO_read(f
->fetch
, f
->buffer
, sizeof(f
->buffer
));
90 fetch_archive_close(struct archive
*a
, void *client_data
)
92 struct fetch_archive
*f
= client_data
;
95 fetchIO_close(f
->fetch
);
100 static struct archive
*
101 open_archive_by_url(struct url
*url
)
103 struct fetch_archive
*f
;
106 f
= xmalloc(sizeof(*f
));
109 a
= archive_read_new();
110 archive_read_support_compression_all(a
);
111 archive_read_support_format_all(a
);
112 if (archive_read_open(a
, f
, fetch_archive_open
, fetch_archive_read
,
113 fetch_archive_close
)) {
114 archive_read_finish(a
);
122 open_archive(const char *url
)
128 a
= archive_read_new();
129 archive_read_support_compression_all(a
);
130 archive_read_support_format_all(a
);
131 if (archive_read_open_filename(a
, url
, 1024)) {
132 archive_read_close(a
);
138 if ((u
= fetchParseURL(url
)) == NULL
)
141 a
= open_archive_by_url(u
);
148 strip_suffix(char *filename
)
152 len
= strlen(filename
);
155 if (strcmp(filename
+ len
- 4, ".tgz") == 0 ||
156 strcmp(filename
+ len
- 4, ".tbz") == 0) {
157 filename
[len
- 4] = '\0';
164 find_best_package_int(struct url
*url
, const char *pattern
,
165 struct url
**best_url
)
167 char *cur_match
, *url_pattern
, *best_match
= NULL
;
172 if ((best_match
= fetchUnquoteFilename(*best_url
)) == NULL
)
177 if (best_match
&& strip_suffix(best_match
) == 0) {
182 for (i
= 0; pattern
[i
] != '\0'; ++i
) {
183 if (!isalnum((unsigned char)(pattern
[i
])) &&
187 url_pattern
= xasprintf("%*.*s*", (int)i
, (int)i
, pattern
);
189 fetchInitURLList(&ue
);
190 if (fetchList(&ue
, url
, url_pattern
, fetch_flags
)) {
192 base_url
= fetchStringifyURL(url
);
193 warnx("Can't process %s/%s: %s", base_url
, url_pattern
,
197 fetchFreeURLList(&ue
);
202 for (i
= 0; i
< ue
.length
; ++i
) {
203 cur_match
= fetchUnquoteFilename(ue
.urls
+ i
);
205 if (cur_match
== NULL
) {
207 fetchFreeURLList(&ue
);
210 if (strip_suffix(cur_match
) == 0) {
214 if (pkg_order(pattern
, cur_match
, best_match
) == 1) {
216 fetchFreeURL(*best_url
);
217 *best_url
= fetchCopyURL(ue
.urls
+ i
);
219 best_match
= cur_match
;
221 if (*best_url
== NULL
) {
229 fetchFreeURLList(&ue
);
234 process_pkg_path(void)
239 const char *start
, *next
;
242 if (getcwd(cwd
, sizeof(cwd
)) == NULL
)
243 errx(EXIT_FAILURE
, "getcwd failed");
245 orig_cwd
= xstrdup(cwd
);
247 if (config_pkg_path
== NULL
)
250 for (start
= config_pkg_path
; *start
; start
= next
) {
251 len
= strcspn(start
, ";");
252 if (*(next
= start
+ len
) != '\0')
255 relative_path
= !IS_FULLPATH(start
) && !IS_URL(start
);
256 pl
= xmalloc(sizeof(*pl
));
257 pl
->pl_path
= xasprintf("%s%s%*.*s",
258 relative_path
? cwd
: "", len
&& relative_path
? "/" : "",
259 (int)len
, (int)len
, start
);
260 TAILQ_INSERT_TAIL(&pkg_path
, pl
, pl_link
);
265 find_best_package(const char *toplevel
, const char *pattern
, int do_path
)
267 struct url
*url
, *best_match
= NULL
;
271 url
= fetchParseURL(last_toplevel
);
273 find_best_package_int(url
, pattern
, &best_match
);
274 /* XXX Check return value and complain */
281 TAILQ_FOREACH(pl
, &pkg_path
, pl_link
) {
282 url
= fetchParseURL(pl
->pl_path
);
284 find_best_package_int(url
, pattern
, &best_match
);
285 /* XXX Check return value and complain */
294 find_archive(const char *fname
, int top_level
)
297 struct url
*best_match
;
298 char *full_fname
, *last_slash
;
302 if (IS_FULLPATH(fname
) || IS_URL(fname
)) {
303 full_fname
= xstrdup(fname
);
305 if (strchr(fname
, '/') == NULL
)
307 full_fname
= xasprintf("%s/%s", orig_cwd
, fname
);
310 last_slash
= strrchr(full_fname
, '/');
314 last_toplevel
= xstrdup(full_fname
);
318 a
= open_archive(full_fname
);
324 fname
= last_slash
+ 1;
327 best_match
= find_best_package(full_fname
, fname
, 0);
329 if (search_path
&& best_match
== NULL
)
330 best_match
= find_best_package(last_toplevel
, fname
, 1);
334 if (best_match
== NULL
)
336 a
= open_archive_by_url(best_match
);
337 fetchFreeURL(best_match
);