1/* $NetBSD: file.c,v 1.2 2011/06/25 20:27:01 christos 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 53static int fetch_stat_file(int, struct url_stat *); 54 55static ssize_t 56fetchFile_read(void *cookie, void *buf, size_t len) 57{ 58 return read(*(int *)cookie, buf, len); 59} 60 61static ssize_t 62fetchFile_write(void *cookie, const void *buf, size_t len) 63{ 64 return write(*(int *)cookie, buf, len); 65} 66 67static void 68fetchFile_close(void *cookie) 69{ 70 int fd = *(int *)cookie; 71 72 free(cookie); 73 74 close(fd); 75} 76 77fetchIO * 78fetchXGetFile(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 close(fd); 110 fetchLastErrCode = FETCH_UNCHANGED; 111 snprintf(fetchLastErrString, MAXERRSTRING, "Unchanged"); 112 return NULL; 113 } 114 115 if (u->offset && lseek(fd, u->offset, SEEK_SET) == -1) { 116 close(fd); 117 fetch_syserr(); 118 return NULL; 119 } 120 121 cookie = malloc(sizeof(int)); 122 if (cookie == NULL) { 123 close(fd); 124 fetch_syserr(); 125 return NULL; 126 } 127 128 *cookie = fd; 129 f = fetchIO_unopen(cookie, fetchFile_read, fetchFile_write, fetchFile_close); 130 if (f == NULL) { 131 close(fd); 132 free(cookie); 133 } 134 return f; 135} 136 137fetchIO * 138fetchGetFile(struct url *u, const char *flags) 139{ 140 return (fetchXGetFile(u, NULL, flags)); 141} 142 143fetchIO * 144fetchPutFile(struct url *u, const char *flags) 145{ 146 char *path; 147 fetchIO *f; 148 int fd, *cookie; 149 150 if ((path = fetchUnquotePath(u)) == NULL) { 151 fetch_syserr(); 152 return NULL; 153 } 154 155 if (CHECK_FLAG('a')) 156 fd = open(path, O_WRONLY | O_APPEND); 157 else 158 fd = open(path, O_WRONLY); 159 160 free(path); 161 162 if (fd == -1) { 163 fetch_syserr(); 164 return NULL; 165 } 166 167 if (u->offset && lseek(fd, u->offset, SEEK_SET) == -1) { 168 close(fd); 169 fetch_syserr(); 170 return NULL; 171 } 172 173 cookie = malloc(sizeof(int)); 174 if (cookie == NULL) { 175 close(fd); 176 fetch_syserr(); 177 return NULL; 178 } 179 180 *cookie = fd; 181 f = fetchIO_unopen(cookie, fetchFile_read, fetchFile_write, fetchFile_close); 182 if (f == NULL) { 183 close(fd); 184 free(cookie); 185 } 186 return f; 187} 188 189static int 190fetch_stat_file(int fd, struct url_stat *us) 191{ 192 struct stat sb; 193 194 us->size = -1; 195 us->atime = us->mtime = 0; 196 if (fstat(fd, &sb) == -1) { 197 fetch_syserr(); 198 return (-1); 199 } 200 us->size = sb.st_size; 201 us->atime = sb.st_atime; 202 us->mtime = sb.st_mtime; 203 return (0); 204} 205 206int 207/*ARGSUSED*/ 208fetchStatFile(struct url *u, struct url_stat *us, const char *flags __unused) 209{ 210 char *path; 211 int fd, rv; 212 213 if ((path = fetchUnquotePath(u)) == NULL) { 214 fetch_syserr(); 215 return -1; 216 } 217 218 fd = open(path, O_RDONLY); 219 free(path); 220 221 if (fd == -1) { 222 fetch_syserr(); 223 return -1; 224 } 225 226 rv = fetch_stat_file(fd, us); 227 close(fd); 228 229 return rv; 230} 231 232int 233/*ARGSUSED*/ 234fetchListFile(struct url_list *ue, struct url *u, const char *pattern, 235 const char *flags __unused) 236{ 237 char *path; 238 struct dirent *de; 239 DIR *dir; 240 int ret; 241 242 if ((path = fetchUnquotePath(u)) == NULL) { 243 fetch_syserr(); 244 return -1; 245 } 246 247 dir = opendir(path); 248 free(path); 249 250 if (dir == NULL) { 251 fetch_syserr(); 252 return -1; 253 } 254 255 ret = 0; 256 257 while ((de = readdir(dir)) != NULL) { 258 if (pattern && fnmatch(pattern, de->d_name, 0) != 0) 259 continue; 260 ret = fetch_add_entry(ue, u, de->d_name, 0); 261 if (ret) 262 break; 263 } 264 265 closedir(dir); 266 267 return ret; 268} 269