1 /* $NetBSD: file.c,v 1.1.1.4 2009/03/10 00:44:20 joerg Exp $ */ 2 /*- 3 * Copyright (c) 1998-2004 Dag-Erling Co�dan Sm�rgrav 4 * Copyright (c) 2008, 2009 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 struct url_stat local_us; 83 int if_modified_since, fd, *cookie; 84 85 if_modified_since = CHECK_FLAG('i'); 86 if (if_modified_since && us == NULL) 87 us = &local_us; 88 89 if ((path = fetchUnquotePath(u)) == NULL) { 90 fetch_syserr(); 91 return NULL; 92 } 93 94 fd = open(path, O_RDONLY); 95 free(path); 96 if (fd == -1) { 97 fetch_syserr(); 98 return NULL; 99 } 100 101 if (us && fetch_stat_file(fd, us) == -1) { 102 close(fd); 103 fetch_syserr(); 104 return NULL; 105 } 106 107 if (if_modified_since && u->last_modified > 0 && 108 u->last_modified >= us->mtime) { 109 fetchLastErrCode = FETCH_UNCHANGED; 110 snprintf(fetchLastErrString, MAXERRSTRING, "Unchanged"); 111 return NULL; 112 } 113 114 if (u->offset && lseek(fd, u->offset, SEEK_SET) == -1) { 115 close(fd); 116 fetch_syserr(); 117 return NULL; 118 } 119 120 cookie = malloc(sizeof(int)); 121 if (cookie == NULL) { 122 close(fd); 123 fetch_syserr(); 124 return NULL; 125 } 126 127 *cookie = fd; 128 f = fetchIO_unopen(cookie, fetchFile_read, fetchFile_write, fetchFile_close); 129 if (f == NULL) { 130 close(fd); 131 free(cookie); 132 } 133 return f; 134 } 135 136 fetchIO * 137 fetchGetFile(struct url *u, const char *flags) 138 { 139 return (fetchXGetFile(u, NULL, flags)); 140 } 141 142 fetchIO * 143 fetchPutFile(struct url *u, const char *flags) 144 { 145 char *path; 146 fetchIO *f; 147 int fd, *cookie; 148 149 if ((path = fetchUnquotePath(u)) == NULL) { 150 fetch_syserr(); 151 return NULL; 152 } 153 154 if (CHECK_FLAG('a')) 155 fd = open(path, O_WRONLY | O_APPEND); 156 else 157 fd = open(path, O_WRONLY); 158 159 free(path); 160 161 if (fd == -1) { 162 fetch_syserr(); 163 return NULL; 164 } 165 166 if (u->offset && lseek(fd, u->offset, SEEK_SET) == -1) { 167 close(fd); 168 fetch_syserr(); 169 return NULL; 170 } 171 172 cookie = malloc(sizeof(int)); 173 if (cookie == NULL) { 174 close(fd); 175 fetch_syserr(); 176 return NULL; 177 } 178 179 *cookie = fd; 180 f = fetchIO_unopen(cookie, fetchFile_read, fetchFile_write, fetchFile_close); 181 if (f == NULL) { 182 close(fd); 183 free(cookie); 184 } 185 return f; 186 } 187 188 static int 189 fetch_stat_file(int fd, struct url_stat *us) 190 { 191 struct stat sb; 192 193 us->size = -1; 194 us->atime = us->mtime = 0; 195 if (fstat(fd, &sb) == -1) { 196 fetch_syserr(); 197 return (-1); 198 } 199 us->size = sb.st_size; 200 us->atime = sb.st_atime; 201 us->mtime = sb.st_mtime; 202 return (0); 203 } 204 205 int 206 fetchStatFile(struct url *u, struct url_stat *us, const char *flags) 207 { 208 char *path; 209 int fd, rv; 210 211 if ((path = fetchUnquotePath(u)) == NULL) { 212 fetch_syserr(); 213 return -1; 214 } 215 216 fd = open(path, O_RDONLY); 217 free(path); 218 219 if (fd == -1) { 220 fetch_syserr(); 221 return -1; 222 } 223 224 rv = fetch_stat_file(fd, us); 225 close(fd); 226 227 return rv; 228 } 229 230 int 231 fetchListFile(struct url_list *ue, struct url *u, const char *pattern, const char *flags) 232 { 233 char *path; 234 struct dirent *de; 235 DIR *dir; 236 237 if ((path = fetchUnquotePath(u)) == NULL) { 238 fetch_syserr(); 239 return -1; 240 } 241 242 dir = opendir(path); 243 free(path); 244 245 if (dir == NULL) { 246 fetch_syserr(); 247 return -1; 248 } 249 250 while ((de = readdir(dir)) != NULL) { 251 if (pattern && fnmatch(pattern, de->d_name, 0) != 0) 252 continue; 253 fetch_add_entry(ue, u, de->d_name, 0); 254 } 255 256 return 0; 257 } 258