xref: /minix3/external/bsd/fetch/dist/libfetch/file.c (revision 040ec64444222c3cf664253481b0af9434ab4a20)
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