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