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