1*040ec644SDavid van Moolenbroek /* $NetBSD: file.c,v 1.2 2011/06/25 20:27:01 christos Exp $ */
2*040ec644SDavid van Moolenbroek /*-
3*040ec644SDavid van Moolenbroek * Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav
4*040ec644SDavid van Moolenbroek * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>
5*040ec644SDavid van Moolenbroek * All rights reserved.
6*040ec644SDavid van Moolenbroek *
7*040ec644SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
8*040ec644SDavid van Moolenbroek * modification, are permitted provided that the following conditions
9*040ec644SDavid van Moolenbroek * are met:
10*040ec644SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
11*040ec644SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer
12*040ec644SDavid van Moolenbroek * in this position and unchanged.
13*040ec644SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
14*040ec644SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
15*040ec644SDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
16*040ec644SDavid van Moolenbroek * 3. The name of the author may not be used to endorse or promote products
17*040ec644SDavid van Moolenbroek * derived from this software without specific prior written permission
18*040ec644SDavid van Moolenbroek *
19*040ec644SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20*040ec644SDavid van Moolenbroek * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21*040ec644SDavid van Moolenbroek * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22*040ec644SDavid van Moolenbroek * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23*040ec644SDavid van Moolenbroek * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24*040ec644SDavid van Moolenbroek * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25*040ec644SDavid van Moolenbroek * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26*040ec644SDavid van Moolenbroek * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27*040ec644SDavid van Moolenbroek * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28*040ec644SDavid van Moolenbroek * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*040ec644SDavid van Moolenbroek *
30*040ec644SDavid van Moolenbroek * $FreeBSD: file.c,v 1.18 2007/12/14 10:26:58 des Exp $
31*040ec644SDavid van Moolenbroek */
32*040ec644SDavid van Moolenbroek
33*040ec644SDavid van Moolenbroek #if HAVE_CONFIG_H
34*040ec644SDavid van Moolenbroek #include "config.h"
35*040ec644SDavid van Moolenbroek #endif
36*040ec644SDavid van Moolenbroek #ifndef NETBSD
37*040ec644SDavid van Moolenbroek #include <nbcompat.h>
38*040ec644SDavid van Moolenbroek #endif
39*040ec644SDavid van Moolenbroek
40*040ec644SDavid van Moolenbroek #include <sys/stat.h>
41*040ec644SDavid van Moolenbroek
42*040ec644SDavid van Moolenbroek #include <dirent.h>
43*040ec644SDavid van Moolenbroek #include <fcntl.h>
44*040ec644SDavid van Moolenbroek #include <fnmatch.h>
45*040ec644SDavid van Moolenbroek #include <stdio.h>
46*040ec644SDavid van Moolenbroek #include <stdlib.h>
47*040ec644SDavid van Moolenbroek #include <string.h>
48*040ec644SDavid van Moolenbroek #include <unistd.h>
49*040ec644SDavid van Moolenbroek
50*040ec644SDavid van Moolenbroek #include "fetch.h"
51*040ec644SDavid van Moolenbroek #include "common.h"
52*040ec644SDavid van Moolenbroek
53*040ec644SDavid van Moolenbroek static int fetch_stat_file(int, struct url_stat *);
54*040ec644SDavid van Moolenbroek
55*040ec644SDavid van Moolenbroek static ssize_t
fetchFile_read(void * cookie,void * buf,size_t len)56*040ec644SDavid van Moolenbroek fetchFile_read(void *cookie, void *buf, size_t len)
57*040ec644SDavid van Moolenbroek {
58*040ec644SDavid van Moolenbroek return read(*(int *)cookie, buf, len);
59*040ec644SDavid van Moolenbroek }
60*040ec644SDavid van Moolenbroek
61*040ec644SDavid van Moolenbroek static ssize_t
fetchFile_write(void * cookie,const void * buf,size_t len)62*040ec644SDavid van Moolenbroek fetchFile_write(void *cookie, const void *buf, size_t len)
63*040ec644SDavid van Moolenbroek {
64*040ec644SDavid van Moolenbroek return write(*(int *)cookie, buf, len);
65*040ec644SDavid van Moolenbroek }
66*040ec644SDavid van Moolenbroek
67*040ec644SDavid van Moolenbroek static void
fetchFile_close(void * cookie)68*040ec644SDavid van Moolenbroek fetchFile_close(void *cookie)
69*040ec644SDavid van Moolenbroek {
70*040ec644SDavid van Moolenbroek int fd = *(int *)cookie;
71*040ec644SDavid van Moolenbroek
72*040ec644SDavid van Moolenbroek free(cookie);
73*040ec644SDavid van Moolenbroek
74*040ec644SDavid van Moolenbroek close(fd);
75*040ec644SDavid van Moolenbroek }
76*040ec644SDavid van Moolenbroek
77*040ec644SDavid van Moolenbroek fetchIO *
fetchXGetFile(struct url * u,struct url_stat * us,const char * flags)78*040ec644SDavid van Moolenbroek fetchXGetFile(struct url *u, struct url_stat *us, const char *flags)
79*040ec644SDavid van Moolenbroek {
80*040ec644SDavid van Moolenbroek char *path;
81*040ec644SDavid van Moolenbroek fetchIO *f;
82*040ec644SDavid van Moolenbroek struct url_stat local_us;
83*040ec644SDavid van Moolenbroek int if_modified_since, fd, *cookie;
84*040ec644SDavid van Moolenbroek
85*040ec644SDavid van Moolenbroek if_modified_since = CHECK_FLAG('i');
86*040ec644SDavid van Moolenbroek if (if_modified_since && us == NULL)
87*040ec644SDavid van Moolenbroek us = &local_us;
88*040ec644SDavid van Moolenbroek
89*040ec644SDavid van Moolenbroek if ((path = fetchUnquotePath(u)) == NULL) {
90*040ec644SDavid van Moolenbroek fetch_syserr();
91*040ec644SDavid van Moolenbroek return NULL;
92*040ec644SDavid van Moolenbroek }
93*040ec644SDavid van Moolenbroek
94*040ec644SDavid van Moolenbroek fd = open(path, O_RDONLY);
95*040ec644SDavid van Moolenbroek free(path);
96*040ec644SDavid van Moolenbroek if (fd == -1) {
97*040ec644SDavid van Moolenbroek fetch_syserr();
98*040ec644SDavid van Moolenbroek return NULL;
99*040ec644SDavid van Moolenbroek }
100*040ec644SDavid van Moolenbroek
101*040ec644SDavid van Moolenbroek if (us && fetch_stat_file(fd, us) == -1) {
102*040ec644SDavid van Moolenbroek close(fd);
103*040ec644SDavid van Moolenbroek fetch_syserr();
104*040ec644SDavid van Moolenbroek return NULL;
105*040ec644SDavid van Moolenbroek }
106*040ec644SDavid van Moolenbroek
107*040ec644SDavid van Moolenbroek if (if_modified_since && u->last_modified > 0 &&
108*040ec644SDavid van Moolenbroek u->last_modified >= us->mtime) {
109*040ec644SDavid van Moolenbroek close(fd);
110*040ec644SDavid van Moolenbroek fetchLastErrCode = FETCH_UNCHANGED;
111*040ec644SDavid van Moolenbroek snprintf(fetchLastErrString, MAXERRSTRING, "Unchanged");
112*040ec644SDavid van Moolenbroek return NULL;
113*040ec644SDavid van Moolenbroek }
114*040ec644SDavid van Moolenbroek
115*040ec644SDavid van Moolenbroek if (u->offset && lseek(fd, u->offset, SEEK_SET) == -1) {
116*040ec644SDavid van Moolenbroek close(fd);
117*040ec644SDavid van Moolenbroek fetch_syserr();
118*040ec644SDavid van Moolenbroek return NULL;
119*040ec644SDavid van Moolenbroek }
120*040ec644SDavid van Moolenbroek
121*040ec644SDavid van Moolenbroek cookie = malloc(sizeof(int));
122*040ec644SDavid van Moolenbroek if (cookie == NULL) {
123*040ec644SDavid van Moolenbroek close(fd);
124*040ec644SDavid van Moolenbroek fetch_syserr();
125*040ec644SDavid van Moolenbroek return NULL;
126*040ec644SDavid van Moolenbroek }
127*040ec644SDavid van Moolenbroek
128*040ec644SDavid van Moolenbroek *cookie = fd;
129*040ec644SDavid van Moolenbroek f = fetchIO_unopen(cookie, fetchFile_read, fetchFile_write, fetchFile_close);
130*040ec644SDavid van Moolenbroek if (f == NULL) {
131*040ec644SDavid van Moolenbroek close(fd);
132*040ec644SDavid van Moolenbroek free(cookie);
133*040ec644SDavid van Moolenbroek }
134*040ec644SDavid van Moolenbroek return f;
135*040ec644SDavid van Moolenbroek }
136*040ec644SDavid van Moolenbroek
137*040ec644SDavid van Moolenbroek fetchIO *
fetchGetFile(struct url * u,const char * flags)138*040ec644SDavid van Moolenbroek fetchGetFile(struct url *u, const char *flags)
139*040ec644SDavid van Moolenbroek {
140*040ec644SDavid van Moolenbroek return (fetchXGetFile(u, NULL, flags));
141*040ec644SDavid van Moolenbroek }
142*040ec644SDavid van Moolenbroek
143*040ec644SDavid van Moolenbroek fetchIO *
fetchPutFile(struct url * u,const char * flags)144*040ec644SDavid van Moolenbroek fetchPutFile(struct url *u, const char *flags)
145*040ec644SDavid van Moolenbroek {
146*040ec644SDavid van Moolenbroek char *path;
147*040ec644SDavid van Moolenbroek fetchIO *f;
148*040ec644SDavid van Moolenbroek int fd, *cookie;
149*040ec644SDavid van Moolenbroek
150*040ec644SDavid van Moolenbroek if ((path = fetchUnquotePath(u)) == NULL) {
151*040ec644SDavid van Moolenbroek fetch_syserr();
152*040ec644SDavid van Moolenbroek return NULL;
153*040ec644SDavid van Moolenbroek }
154*040ec644SDavid van Moolenbroek
155*040ec644SDavid van Moolenbroek if (CHECK_FLAG('a'))
156*040ec644SDavid van Moolenbroek fd = open(path, O_WRONLY | O_APPEND);
157*040ec644SDavid van Moolenbroek else
158*040ec644SDavid van Moolenbroek fd = open(path, O_WRONLY);
159*040ec644SDavid van Moolenbroek
160*040ec644SDavid van Moolenbroek free(path);
161*040ec644SDavid van Moolenbroek
162*040ec644SDavid van Moolenbroek if (fd == -1) {
163*040ec644SDavid van Moolenbroek fetch_syserr();
164*040ec644SDavid van Moolenbroek return NULL;
165*040ec644SDavid van Moolenbroek }
166*040ec644SDavid van Moolenbroek
167*040ec644SDavid van Moolenbroek if (u->offset && lseek(fd, u->offset, SEEK_SET) == -1) {
168*040ec644SDavid van Moolenbroek close(fd);
169*040ec644SDavid van Moolenbroek fetch_syserr();
170*040ec644SDavid van Moolenbroek return NULL;
171*040ec644SDavid van Moolenbroek }
172*040ec644SDavid van Moolenbroek
173*040ec644SDavid van Moolenbroek cookie = malloc(sizeof(int));
174*040ec644SDavid van Moolenbroek if (cookie == NULL) {
175*040ec644SDavid van Moolenbroek close(fd);
176*040ec644SDavid van Moolenbroek fetch_syserr();
177*040ec644SDavid van Moolenbroek return NULL;
178*040ec644SDavid van Moolenbroek }
179*040ec644SDavid van Moolenbroek
180*040ec644SDavid van Moolenbroek *cookie = fd;
181*040ec644SDavid van Moolenbroek f = fetchIO_unopen(cookie, fetchFile_read, fetchFile_write, fetchFile_close);
182*040ec644SDavid van Moolenbroek if (f == NULL) {
183*040ec644SDavid van Moolenbroek close(fd);
184*040ec644SDavid van Moolenbroek free(cookie);
185*040ec644SDavid van Moolenbroek }
186*040ec644SDavid van Moolenbroek return f;
187*040ec644SDavid van Moolenbroek }
188*040ec644SDavid van Moolenbroek
189*040ec644SDavid van Moolenbroek static int
fetch_stat_file(int fd,struct url_stat * us)190*040ec644SDavid van Moolenbroek fetch_stat_file(int fd, struct url_stat *us)
191*040ec644SDavid van Moolenbroek {
192*040ec644SDavid van Moolenbroek struct stat sb;
193*040ec644SDavid van Moolenbroek
194*040ec644SDavid van Moolenbroek us->size = -1;
195*040ec644SDavid van Moolenbroek us->atime = us->mtime = 0;
196*040ec644SDavid van Moolenbroek if (fstat(fd, &sb) == -1) {
197*040ec644SDavid van Moolenbroek fetch_syserr();
198*040ec644SDavid van Moolenbroek return (-1);
199*040ec644SDavid van Moolenbroek }
200*040ec644SDavid van Moolenbroek us->size = sb.st_size;
201*040ec644SDavid van Moolenbroek us->atime = sb.st_atime;
202*040ec644SDavid van Moolenbroek us->mtime = sb.st_mtime;
203*040ec644SDavid van Moolenbroek return (0);
204*040ec644SDavid van Moolenbroek }
205*040ec644SDavid van Moolenbroek
206*040ec644SDavid van Moolenbroek int
207*040ec644SDavid van Moolenbroek /*ARGSUSED*/
fetchStatFile(struct url * u,struct url_stat * us,const char * flags __unused)208*040ec644SDavid van Moolenbroek fetchStatFile(struct url *u, struct url_stat *us, const char *flags __unused)
209*040ec644SDavid van Moolenbroek {
210*040ec644SDavid van Moolenbroek char *path;
211*040ec644SDavid van Moolenbroek int fd, rv;
212*040ec644SDavid van Moolenbroek
213*040ec644SDavid van Moolenbroek if ((path = fetchUnquotePath(u)) == NULL) {
214*040ec644SDavid van Moolenbroek fetch_syserr();
215*040ec644SDavid van Moolenbroek return -1;
216*040ec644SDavid van Moolenbroek }
217*040ec644SDavid van Moolenbroek
218*040ec644SDavid van Moolenbroek fd = open(path, O_RDONLY);
219*040ec644SDavid van Moolenbroek free(path);
220*040ec644SDavid van Moolenbroek
221*040ec644SDavid van Moolenbroek if (fd == -1) {
222*040ec644SDavid van Moolenbroek fetch_syserr();
223*040ec644SDavid van Moolenbroek return -1;
224*040ec644SDavid van Moolenbroek }
225*040ec644SDavid van Moolenbroek
226*040ec644SDavid van Moolenbroek rv = fetch_stat_file(fd, us);
227*040ec644SDavid van Moolenbroek close(fd);
228*040ec644SDavid van Moolenbroek
229*040ec644SDavid van Moolenbroek return rv;
230*040ec644SDavid van Moolenbroek }
231*040ec644SDavid van Moolenbroek
232*040ec644SDavid van Moolenbroek int
233*040ec644SDavid van Moolenbroek /*ARGSUSED*/
fetchListFile(struct url_list * ue,struct url * u,const char * pattern,const char * flags __unused)234*040ec644SDavid van Moolenbroek fetchListFile(struct url_list *ue, struct url *u, const char *pattern,
235*040ec644SDavid van Moolenbroek const char *flags __unused)
236*040ec644SDavid van Moolenbroek {
237*040ec644SDavid van Moolenbroek char *path;
238*040ec644SDavid van Moolenbroek struct dirent *de;
239*040ec644SDavid van Moolenbroek DIR *dir;
240*040ec644SDavid van Moolenbroek int ret;
241*040ec644SDavid van Moolenbroek
242*040ec644SDavid van Moolenbroek if ((path = fetchUnquotePath(u)) == NULL) {
243*040ec644SDavid van Moolenbroek fetch_syserr();
244*040ec644SDavid van Moolenbroek return -1;
245*040ec644SDavid van Moolenbroek }
246*040ec644SDavid van Moolenbroek
247*040ec644SDavid van Moolenbroek dir = opendir(path);
248*040ec644SDavid van Moolenbroek free(path);
249*040ec644SDavid van Moolenbroek
250*040ec644SDavid van Moolenbroek if (dir == NULL) {
251*040ec644SDavid van Moolenbroek fetch_syserr();
252*040ec644SDavid van Moolenbroek return -1;
253*040ec644SDavid van Moolenbroek }
254*040ec644SDavid van Moolenbroek
255*040ec644SDavid van Moolenbroek ret = 0;
256*040ec644SDavid van Moolenbroek
257*040ec644SDavid van Moolenbroek while ((de = readdir(dir)) != NULL) {
258*040ec644SDavid van Moolenbroek if (pattern && fnmatch(pattern, de->d_name, 0) != 0)
259*040ec644SDavid van Moolenbroek continue;
260*040ec644SDavid van Moolenbroek ret = fetch_add_entry(ue, u, de->d_name, 0);
261*040ec644SDavid van Moolenbroek if (ret)
262*040ec644SDavid van Moolenbroek break;
263*040ec644SDavid van Moolenbroek }
264*040ec644SDavid van Moolenbroek
265*040ec644SDavid van Moolenbroek closedir(dir);
266*040ec644SDavid van Moolenbroek
267*040ec644SDavid van Moolenbroek return ret;
268*040ec644SDavid van Moolenbroek }
269