1 /* $NetBSD: pkg_io.c,v 1.1.1.9 2010/04/23 20:54:11 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.1.1.9 2010/04/23 20:54:11 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
{
71 fetch_archive_open(struct archive
*a
, void *client_data
)
73 struct fetch_archive
*f
= client_data
;
76 f
->fetch
= fetchXGet(f
->url
, &us
, fetch_flags
);
86 fetch_archive_read(struct archive
*a
, void *client_data
,
89 struct fetch_archive
*f
= client_data
;
94 rv
= fetchIO_read(f
->fetch
, f
->buffer
, sizeof(f
->buffer
));
104 if (f
->url
->offset
== f
->size
)
109 char *url
= fetchStringifyURL(f
->url
);
110 fprintf(stderr
, "Trying to reconnect %s\n", url
);
113 fetchIO_close(f
->fetch
);
114 f
->fetch
= fetchXGet(f
->url
, &us
, fetch_flags
);
115 if (f
->fetch
== NULL
)
117 if (us
.size
!= f
->size
)
119 rv
= fetchIO_read(f
->fetch
, f
->buffer
, sizeof(f
->buffer
));
121 f
->url
->offset
+= rv
;
126 fetch_archive_close(struct archive
*a
, void *client_data
)
128 struct fetch_archive
*f
= client_data
;
130 if (f
->fetch
!= NULL
)
131 fetchIO_close(f
->fetch
);
132 fetchFreeURL(f
->url
);
137 static struct archive
*
138 open_archive_by_url(struct url
*url
, char **archive_name
)
140 struct fetch_archive
*f
;
143 f
= xmalloc(sizeof(*f
));
144 f
->url
= fetchCopyURL(url
);
146 *archive_name
= fetchStringifyURL(url
);
148 a
= archive_read_new();
149 archive_read_support_compression_all(a
);
150 archive_read_support_format_all(a
);
151 if (archive_read_open(a
, f
, fetch_archive_open
, fetch_archive_read
,
152 fetch_archive_close
)) {
154 *archive_name
= NULL
;
155 archive_read_finish(a
);
163 open_archive(const char *url
, char **archive_name
)
168 *archive_name
= NULL
;
171 a
= archive_read_new();
172 archive_read_support_compression_all(a
);
173 archive_read_support_format_all(a
);
174 if (archive_read_open_filename(a
, url
, 1024)) {
175 archive_read_close(a
);
178 *archive_name
= xstrdup(url
);
182 if ((u
= fetchParseURL(url
)) == NULL
)
185 a
= open_archive_by_url(u
, archive_name
);
192 strip_suffix(char *filename
)
196 len
= strlen(filename
);
199 if (strcmp(filename
+ len
- 4, ".tgz") == 0 ||
200 strcmp(filename
+ len
- 4, ".tbz") == 0) {
201 filename
[len
- 4] = '\0';
208 find_best_package_int(struct url
*url
, const char *pattern
,
209 struct url
**best_url
)
211 char *cur_match
, *url_pattern
, *best_match
= NULL
;
216 if ((best_match
= fetchUnquoteFilename(*best_url
)) == NULL
)
221 if (best_match
&& strip_suffix(best_match
) == 0) {
226 for (i
= 0; pattern
[i
] != '\0'; ++i
) {
227 if (!isalnum((unsigned char)(pattern
[i
])) &&
231 url_pattern
= xasprintf("%*.*s*", (int)i
, (int)i
, pattern
);
233 fetchInitURLList(&ue
);
234 if (fetchList(&ue
, url
, url_pattern
, fetch_flags
)) {
236 base_url
= fetchStringifyURL(url
);
237 warnx("Can't process %s/%s: %s", base_url
, url_pattern
,
241 fetchFreeURLList(&ue
);
246 for (i
= 0; i
< ue
.length
; ++i
) {
247 cur_match
= fetchUnquoteFilename(ue
.urls
+ i
);
249 if (cur_match
== NULL
) {
251 fetchFreeURLList(&ue
);
254 if (strip_suffix(cur_match
) == 0) {
258 if (pkg_order(pattern
, cur_match
, best_match
) == 1) {
260 fetchFreeURL(*best_url
);
261 *best_url
= fetchCopyURL(ue
.urls
+ i
);
263 best_match
= cur_match
;
265 if (*best_url
== NULL
) {
273 fetchFreeURLList(&ue
);
278 process_pkg_path(void)
283 const char *start
, *next
;
286 if (getcwd(cwd
, sizeof(cwd
)) == NULL
)
287 errx(EXIT_FAILURE
, "getcwd failed");
289 orig_cwd
= xstrdup(cwd
);
291 if (config_pkg_path
== NULL
)
294 for (start
= config_pkg_path
; *start
; start
= next
) {
295 len
= strcspn(start
, ";");
296 if (*(next
= start
+ len
) != '\0')
299 relative_path
= !IS_FULLPATH(start
) && !IS_URL(start
);
300 pl
= xmalloc(sizeof(*pl
));
301 pl
->pl_path
= xasprintf("%s%s%*.*s",
302 relative_path
? cwd
: "", len
&& relative_path
? "/" : "",
303 (int)len
, (int)len
, start
);
304 TAILQ_INSERT_TAIL(&pkg_path
, pl
, pl_link
);
309 find_best_package(const char *toplevel
, const char *pattern
, int do_path
)
311 struct url
*url
, *best_match
= NULL
;
315 url
= fetchParseURL(last_toplevel
);
317 find_best_package_int(url
, pattern
, &best_match
);
318 /* XXX Check return value and complain */
325 TAILQ_FOREACH(pl
, &pkg_path
, pl_link
) {
326 url
= fetchParseURL(pl
->pl_path
);
328 find_best_package_int(url
, pattern
, &best_match
);
329 /* XXX Check return value and complain */
338 find_archive(const char *fname
, int top_level
, char **archive_name
)
341 struct url
*best_match
;
342 char *full_fname
, *last_slash
;
346 if (IS_FULLPATH(fname
) || IS_URL(fname
)) {
347 full_fname
= xstrdup(fname
);
349 if (strchr(fname
, '/') == NULL
)
351 full_fname
= xasprintf("%s/%s", orig_cwd
, fname
);
354 last_slash
= strrchr(full_fname
, '/');
358 last_toplevel
= xstrdup(full_fname
);
362 a
= open_archive(full_fname
, archive_name
);
368 fname
= last_slash
+ 1;
371 best_match
= find_best_package(full_fname
, fname
, 0);
373 if (search_path
&& best_match
== NULL
)
374 best_match
= find_best_package(last_toplevel
, fname
, 1);
378 if (best_match
== NULL
)
380 a
= open_archive_by_url(best_match
, archive_name
);
381 fetchFreeURL(best_match
);