Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
Nicolas Pennequin | 357ffb3 | 2008-05-05 10:32:46 +0000 | [diff] [blame] | 10 | * Copyright (C) 2002 by Björn Stenberg |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame^] | 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
| 21 | #include <string.h> |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 22 | #include <errno.h> |
Björn Stenberg | 2382044 | 2002-05-13 12:29:34 +0000 | [diff] [blame] | 23 | #include <stdbool.h> |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 24 | #include "file.h" |
| 25 | #include "fat.h" |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 26 | #include "dir_uncached.h" |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 27 | #include "debug.h" |
Miika Pekkarinen | ab78b04 | 2005-10-07 17:38:05 +0000 | [diff] [blame] | 28 | #include "dircache.h" |
Jens Arnold | a601fb8 | 2005-12-17 12:17:11 +0000 | [diff] [blame] | 29 | #include "system.h" |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 30 | |
Björn Stenberg | 412917e | 2002-05-08 15:27:21 +0000 | [diff] [blame] | 31 | /* |
| 32 | These functions provide a roughly POSIX-compatible file IO API. |
| 33 | |
| 34 | Since the fat32 driver only manages sectors, we maintain a one-sector |
| 35 | cache for each open file. This way we can provide byte access without |
| 36 | having to re-read the sector each time. |
| 37 | The penalty is the RAM used for the cache and slightly more complex code. |
| 38 | */ |
| 39 | |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 40 | struct filedesc { |
Jens Arnold | ef3e129 | 2006-12-04 21:37:22 +0000 | [diff] [blame] | 41 | unsigned char cache[SECTOR_SIZE]; |
Jean-Philippe Bernardy | cea551d | 2005-01-23 23:29:35 +0000 | [diff] [blame] | 42 | int cacheoffset; /* invariant: 0 <= cacheoffset <= SECTOR_SIZE */ |
| 43 | long fileoffset; |
| 44 | long size; |
Björn Stenberg | 184fd55 | 2003-01-27 09:32:17 +0000 | [diff] [blame] | 45 | int attr; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 46 | struct fat_file fatfile; |
| 47 | bool busy; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 48 | bool write; |
Björn Stenberg | 228605d | 2002-11-11 13:57:58 +0000 | [diff] [blame] | 49 | bool dirty; |
Björn Stenberg | 9f9c495 | 2002-11-11 15:45:43 +0000 | [diff] [blame] | 50 | bool trunc; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 51 | }; |
| 52 | |
| 53 | static struct filedesc openfiles[MAX_OPEN_FILES]; |
| 54 | |
Björn Stenberg | 9f9c495 | 2002-11-11 15:45:43 +0000 | [diff] [blame] | 55 | static int flush_cache(int fd); |
| 56 | |
Jens Arnold | 67eb154 | 2007-02-01 23:08:15 +0000 | [diff] [blame] | 57 | int creat(const char *pathname) |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 58 | { |
Björn Stenberg | 7d8bbe7 | 2002-11-13 23:25:46 +0000 | [diff] [blame] | 59 | return open(pathname, O_WRONLY|O_CREAT|O_TRUNC); |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 60 | } |
| 61 | |
Miika Pekkarinen | d489377 | 2006-04-13 21:14:13 +0000 | [diff] [blame] | 62 | static int open_internal(const char* pathname, int flags, bool use_cache) |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 63 | { |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 64 | DIR_UNCACHED* dir; |
| 65 | struct dirent_uncached* entry; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 66 | int fd; |
Jens Arnold | f68e13c | 2004-07-19 21:08:44 +0000 | [diff] [blame] | 67 | char pathnamecopy[MAX_PATH]; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 68 | char* name; |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 69 | struct filedesc* file = NULL; |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 70 | int rc; |
Miika Pekkarinen | d489377 | 2006-04-13 21:14:13 +0000 | [diff] [blame] | 71 | #ifndef HAVE_DIRCACHE |
| 72 | (void)use_cache; |
| 73 | #endif |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 74 | |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 75 | LDEBUGF("open(\"%s\",%d)\n",pathname,flags); |
Linus Nielsen Feltzing | 7fbdc36 | 2002-06-07 15:15:10 +0000 | [diff] [blame] | 76 | |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 77 | if ( pathname[0] != '/' ) { |
| 78 | DEBUGF("'%s' is not an absolute path.\n",pathname); |
| 79 | DEBUGF("Only absolute pathnames supported at the moment\n"); |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 80 | errno = EINVAL; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 81 | return -1; |
| 82 | } |
| 83 | |
| 84 | /* find a free file descriptor */ |
| 85 | for ( fd=0; fd<MAX_OPEN_FILES; fd++ ) |
| 86 | if ( !openfiles[fd].busy ) |
| 87 | break; |
| 88 | |
| 89 | if ( fd == MAX_OPEN_FILES ) { |
| 90 | DEBUGF("Too many files open\n"); |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 91 | errno = EMFILE; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 92 | return -2; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 93 | } |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 94 | |
| 95 | file = &openfiles[fd]; |
| 96 | memset(file, 0, sizeof(struct filedesc)); |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 97 | |
Björn Stenberg | 4059ea6 | 2002-11-11 16:08:28 +0000 | [diff] [blame] | 98 | if (flags & (O_RDWR | O_WRONLY)) { |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 99 | file->write = true; |
Jens Arnold | f68e13c | 2004-07-19 21:08:44 +0000 | [diff] [blame] | 100 | |
Björn Stenberg | 4059ea6 | 2002-11-11 16:08:28 +0000 | [diff] [blame] | 101 | if (flags & O_TRUNC) |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 102 | file->trunc = true; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 103 | } |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 104 | file->busy = true; |
Björn Stenberg | 881cd23 | 2002-05-27 09:13:56 +0000 | [diff] [blame] | 105 | |
Miika Pekkarinen | 2d93495 | 2006-03-28 11:51:12 +0000 | [diff] [blame] | 106 | #ifdef HAVE_DIRCACHE |
Miika Pekkarinen | d489377 | 2006-04-13 21:14:13 +0000 | [diff] [blame] | 107 | if (dircache_is_enabled() && !file->write && use_cache) |
Miika Pekkarinen | 2d93495 | 2006-03-28 11:51:12 +0000 | [diff] [blame] | 108 | { |
| 109 | const struct dircache_entry *ce; |
Miika Pekkarinen | d80246f | 2008-03-11 19:52:07 +0000 | [diff] [blame] | 110 | # ifdef HAVE_MULTIVOLUME |
| 111 | int volume = strip_volume(pathname, pathnamecopy); |
| 112 | # endif |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 113 | |
Miika Pekkarinen | 2d93495 | 2006-03-28 11:51:12 +0000 | [diff] [blame] | 114 | ce = dircache_get_entry_ptr(pathname); |
| 115 | if (!ce) |
| 116 | { |
| 117 | errno = ENOENT; |
| 118 | file->busy = false; |
| 119 | return -7; |
| 120 | } |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 121 | |
Miika Pekkarinen | d80246f | 2008-03-11 19:52:07 +0000 | [diff] [blame] | 122 | fat_open(IF_MV2(volume,) |
Miika Pekkarinen | 2d93495 | 2006-03-28 11:51:12 +0000 | [diff] [blame] | 123 | ce->startcluster, |
| 124 | &(file->fatfile), |
| 125 | NULL); |
| 126 | file->size = ce->size; |
| 127 | file->attr = ce->attribute; |
| 128 | file->cacheoffset = -1; |
| 129 | file->fileoffset = 0; |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 130 | |
Miika Pekkarinen | 2d93495 | 2006-03-28 11:51:12 +0000 | [diff] [blame] | 131 | return fd; |
| 132 | } |
| 133 | #endif |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 134 | |
Jens Arnold | f68e13c | 2004-07-19 21:08:44 +0000 | [diff] [blame] | 135 | strncpy(pathnamecopy,pathname,sizeof(pathnamecopy)); |
| 136 | pathnamecopy[sizeof(pathnamecopy)-1] = 0; |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 137 | |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 138 | /* locate filename */ |
Jens Arnold | f68e13c | 2004-07-19 21:08:44 +0000 | [diff] [blame] | 139 | name=strrchr(pathnamecopy+1,'/'); |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 140 | if ( name ) { |
Jens Arnold | f68e13c | 2004-07-19 21:08:44 +0000 | [diff] [blame] | 141 | *name = 0; |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 142 | dir = opendir_uncached(pathnamecopy); |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 143 | *name = '/'; |
| 144 | name++; |
| 145 | } |
| 146 | else { |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 147 | dir = opendir_uncached("/"); |
Jens Arnold | f68e13c | 2004-07-19 21:08:44 +0000 | [diff] [blame] | 148 | name = pathnamecopy+1; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 149 | } |
| 150 | if (!dir) { |
| 151 | DEBUGF("Failed opening dir\n"); |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 152 | errno = EIO; |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 153 | file->busy = false; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 154 | return -4; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 155 | } |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 156 | |
Linus Nielsen Feltzing | 05f1fc4 | 2004-02-11 14:37:16 +0000 | [diff] [blame] | 157 | if(name[0] == 0) { |
| 158 | DEBUGF("Empty file name\n"); |
| 159 | errno = EINVAL; |
| 160 | file->busy = false; |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 161 | closedir_uncached(dir); |
Linus Nielsen Feltzing | 05f1fc4 | 2004-02-11 14:37:16 +0000 | [diff] [blame] | 162 | return -5; |
| 163 | } |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 164 | |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 165 | /* scan dir for name */ |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 166 | while ((entry = readdir_uncached(dir))) { |
Daniel Stenberg | e666ce9 | 2002-08-22 20:13:21 +0000 | [diff] [blame] | 167 | if ( !strcasecmp(name, entry->d_name) ) { |
Jörg Hohensohn | da84857 | 2004-12-28 22:16:07 +0000 | [diff] [blame] | 168 | fat_open(IF_MV2(dir->fatdir.file.volume,) |
| 169 | entry->startcluster, |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 170 | &(file->fatfile), |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 171 | &(dir->fatdir)); |
Jens Arnold | 8537e2d | 2004-09-06 23:33:21 +0000 | [diff] [blame] | 172 | file->size = file->trunc ? 0 : entry->size; |
Björn Stenberg | 184fd55 | 2003-01-27 09:32:17 +0000 | [diff] [blame] | 173 | file->attr = entry->attribute; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 174 | break; |
| 175 | } |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 176 | } |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 177 | |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 178 | if ( !entry ) { |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 179 | LDEBUGF("Didn't find file %s\n",name); |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 180 | if ( file->write && (flags & O_CREAT) ) { |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 181 | rc = fat_create_file(name, |
| 182 | &(file->fatfile), |
| 183 | &(dir->fatdir)); |
| 184 | if (rc < 0) { |
Jens Arnold | f68e13c | 2004-07-19 21:08:44 +0000 | [diff] [blame] | 185 | DEBUGF("Couldn't create %s in %s\n",name,pathnamecopy); |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 186 | errno = EIO; |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 187 | file->busy = false; |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 188 | closedir_uncached(dir); |
Linus Nielsen Feltzing | 05f1fc4 | 2004-02-11 14:37:16 +0000 | [diff] [blame] | 189 | return rc * 10 - 6; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 190 | } |
Miika Pekkarinen | ab78b04 | 2005-10-07 17:38:05 +0000 | [diff] [blame] | 191 | #ifdef HAVE_DIRCACHE |
Miika Pekkarinen | 2d93495 | 2006-03-28 11:51:12 +0000 | [diff] [blame] | 192 | dircache_add_file(pathname, file->fatfile.firstcluster); |
Miika Pekkarinen | ab78b04 | 2005-10-07 17:38:05 +0000 | [diff] [blame] | 193 | #endif |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 194 | file->size = 0; |
Björn Stenberg | 184fd55 | 2003-01-27 09:32:17 +0000 | [diff] [blame] | 195 | file->attr = 0; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 196 | } |
| 197 | else { |
Jens Arnold | f68e13c | 2004-07-19 21:08:44 +0000 | [diff] [blame] | 198 | DEBUGF("Couldn't find %s in %s\n",name,pathnamecopy); |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 199 | errno = ENOENT; |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 200 | file->busy = false; |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 201 | closedir_uncached(dir); |
Linus Nielsen Feltzing | 05f1fc4 | 2004-02-11 14:37:16 +0000 | [diff] [blame] | 202 | return -7; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 203 | } |
Linus Nielsen Feltzing | 5c8e82e | 2004-03-10 19:47:59 +0000 | [diff] [blame] | 204 | } else { |
| 205 | if(file->write && (file->attr & FAT_ATTR_DIRECTORY)) { |
| 206 | errno = EISDIR; |
| 207 | file->busy = false; |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 208 | closedir_uncached(dir); |
Linus Nielsen Feltzing | 5c8e82e | 2004-03-10 19:47:59 +0000 | [diff] [blame] | 209 | return -8; |
| 210 | } |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 211 | } |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 212 | closedir_uncached(dir); |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 213 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 214 | file->cacheoffset = -1; |
| 215 | file->fileoffset = 0; |
Björn Stenberg | 9f9c495 | 2002-11-11 15:45:43 +0000 | [diff] [blame] | 216 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 217 | if (file->write && (flags & O_APPEND)) { |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 218 | rc = lseek(fd,0,SEEK_END); |
| 219 | if (rc < 0 ) |
Linus Nielsen Feltzing | 5c8e82e | 2004-03-10 19:47:59 +0000 | [diff] [blame] | 220 | return rc * 10 - 9; |
Björn Stenberg | 9f9c495 | 2002-11-11 15:45:43 +0000 | [diff] [blame] | 221 | } |
| 222 | |
Miika Pekkarinen | ab78b04 | 2005-10-07 17:38:05 +0000 | [diff] [blame] | 223 | #ifdef HAVE_DIRCACHE |
| 224 | if (file->write) |
| 225 | dircache_bind(fd, pathname); |
| 226 | #endif |
| 227 | |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 228 | return fd; |
| 229 | } |
| 230 | |
Miika Pekkarinen | d489377 | 2006-04-13 21:14:13 +0000 | [diff] [blame] | 231 | int open(const char* pathname, int flags) |
| 232 | { |
| 233 | /* By default, use the dircache if available. */ |
| 234 | return open_internal(pathname, flags, true); |
| 235 | } |
| 236 | |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 237 | int close(int fd) |
| 238 | { |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 239 | struct filedesc* file = &openfiles[fd]; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 240 | int rc = 0; |
| 241 | |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 242 | LDEBUGF("close(%d)\n", fd); |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 243 | |
Heikki Hannikainen | adbe4ed | 2002-08-24 09:47:54 +0000 | [diff] [blame] | 244 | if (fd < 0 || fd > MAX_OPEN_FILES-1) { |
| 245 | errno = EINVAL; |
| 246 | return -1; |
| 247 | } |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 248 | if (!file->busy) { |
Heikki Hannikainen | adbe4ed | 2002-08-24 09:47:54 +0000 | [diff] [blame] | 249 | errno = EBADF; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 250 | return -2; |
| 251 | } |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 252 | if (file->write) { |
Björn Stenberg | a4baacd | 2003-06-29 13:17:19 +0000 | [diff] [blame] | 253 | rc = fsync(fd); |
Linus Nielsen Feltzing | 44e5183 | 2003-03-10 17:10:46 +0000 | [diff] [blame] | 254 | if (rc < 0) |
| 255 | return rc * 10 - 3; |
Hardeep Sidhu | 2436dba | 2006-05-16 06:53:41 +0000 | [diff] [blame] | 256 | #ifdef HAVE_DIRCACHE |
| 257 | dircache_update_filesize(fd, file->size, file->fatfile.firstcluster); |
Jonathan Gordon | e73f287 | 2007-09-02 13:24:51 +0000 | [diff] [blame] | 258 | dircache_update_filetime(fd); |
Hardeep Sidhu | 2436dba | 2006-05-16 06:53:41 +0000 | [diff] [blame] | 259 | #endif |
Linus Nielsen Feltzing | 44e5183 | 2003-03-10 17:10:46 +0000 | [diff] [blame] | 260 | } |
| 261 | |
| 262 | file->busy = false; |
| 263 | return 0; |
| 264 | } |
| 265 | |
Björn Stenberg | a4baacd | 2003-06-29 13:17:19 +0000 | [diff] [blame] | 266 | int fsync(int fd) |
Linus Nielsen Feltzing | 44e5183 | 2003-03-10 17:10:46 +0000 | [diff] [blame] | 267 | { |
| 268 | struct filedesc* file = &openfiles[fd]; |
| 269 | int rc = 0; |
| 270 | |
Björn Stenberg | a4baacd | 2003-06-29 13:17:19 +0000 | [diff] [blame] | 271 | LDEBUGF("fsync(%d)\n", fd); |
Linus Nielsen Feltzing | 44e5183 | 2003-03-10 17:10:46 +0000 | [diff] [blame] | 272 | |
| 273 | if (fd < 0 || fd > MAX_OPEN_FILES-1) { |
| 274 | errno = EINVAL; |
| 275 | return -1; |
| 276 | } |
| 277 | if (!file->busy) { |
| 278 | errno = EBADF; |
| 279 | return -2; |
| 280 | } |
| 281 | if (file->write) { |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 282 | /* flush sector cache */ |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 283 | if ( file->dirty ) { |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 284 | rc = flush_cache(fd); |
| 285 | if (rc < 0) |
Peter D'Hoye | 85058f5 | 2007-10-10 23:26:17 +0000 | [diff] [blame] | 286 | { |
| 287 | /* when failing, try to close the file anyway */ |
| 288 | fat_closewrite(&(file->fatfile), file->size, file->attr); |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 289 | return rc * 10 - 3; |
Peter D'Hoye | 85058f5 | 2007-10-10 23:26:17 +0000 | [diff] [blame] | 290 | } |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 291 | } |
Björn Stenberg | 9f9c495 | 2002-11-11 15:45:43 +0000 | [diff] [blame] | 292 | |
Björn Stenberg | 4cde17d | 2002-11-14 15:50:07 +0000 | [diff] [blame] | 293 | /* truncate? */ |
| 294 | if (file->trunc) { |
Jens Arnold | 8537e2d | 2004-09-06 23:33:21 +0000 | [diff] [blame] | 295 | rc = ftruncate(fd, file->size); |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 296 | if (rc < 0) |
Peter D'Hoye | 85058f5 | 2007-10-10 23:26:17 +0000 | [diff] [blame] | 297 | { |
| 298 | /* when failing, try to close the file anyway */ |
| 299 | fat_closewrite(&(file->fatfile), file->size, file->attr); |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 300 | return rc * 10 - 4; |
Peter D'Hoye | 85058f5 | 2007-10-10 23:26:17 +0000 | [diff] [blame] | 301 | } |
Björn Stenberg | 4cde17d | 2002-11-14 15:50:07 +0000 | [diff] [blame] | 302 | } |
| 303 | |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 304 | /* tie up all loose ends */ |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 305 | rc = fat_closewrite(&(file->fatfile), file->size, file->attr); |
| 306 | if (rc < 0) |
| 307 | return rc * 10 - 5; |
Heikki Hannikainen | adbe4ed | 2002-08-24 09:47:54 +0000 | [diff] [blame] | 308 | } |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 309 | return 0; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 310 | } |
| 311 | |
Björn Stenberg | 307f5d8 | 2002-11-01 15:26:06 +0000 | [diff] [blame] | 312 | int remove(const char* name) |
| 313 | { |
| 314 | int rc; |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 315 | struct filedesc* file; |
Miika Pekkarinen | d489377 | 2006-04-13 21:14:13 +0000 | [diff] [blame] | 316 | /* Can't use dircache now, because we need to access the fat structures. */ |
| 317 | int fd = open_internal(name, O_WRONLY, false); |
Björn Stenberg | 307f5d8 | 2002-11-01 15:26:06 +0000 | [diff] [blame] | 318 | if ( fd < 0 ) |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 319 | return fd * 10 - 1; |
Björn Stenberg | 307f5d8 | 2002-11-01 15:26:06 +0000 | [diff] [blame] | 320 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 321 | file = &openfiles[fd]; |
Miika Pekkarinen | 82f32e3 | 2006-03-30 10:20:44 +0000 | [diff] [blame] | 322 | #ifdef HAVE_DIRCACHE |
| 323 | dircache_remove(name); |
| 324 | #endif |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 325 | rc = fat_remove(&(file->fatfile)); |
Björn Stenberg | 11a09e6 | 2002-11-11 10:21:51 +0000 | [diff] [blame] | 326 | if ( rc < 0 ) { |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 327 | DEBUGF("Failed removing file: %d\n", rc); |
Björn Stenberg | 11a09e6 | 2002-11-11 10:21:51 +0000 | [diff] [blame] | 328 | errno = EIO; |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 329 | return rc * 10 - 3; |
Björn Stenberg | 11a09e6 | 2002-11-11 10:21:51 +0000 | [diff] [blame] | 330 | } |
| 331 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 332 | file->size = 0; |
Björn Stenberg | 307f5d8 | 2002-11-01 15:26:06 +0000 | [diff] [blame] | 333 | |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 334 | rc = close(fd); |
| 335 | if (rc<0) |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 336 | return rc * 10 - 4; |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 337 | |
| 338 | return 0; |
| 339 | } |
| 340 | |
| 341 | int rename(const char* path, const char* newpath) |
| 342 | { |
| 343 | int rc, fd; |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 344 | DIR_UNCACHED* dir; |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 345 | char* nameptr; |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 346 | char* dirptr; |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 347 | struct filedesc* file; |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 348 | char newpath2[MAX_PATH]; |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 349 | |
| 350 | /* verify new path does not already exist */ |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 351 | /* If it is a directory, errno == EISDIR if the name exists */ |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 352 | fd = open(newpath, O_RDONLY); |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 353 | if ( fd >= 0 || errno == EISDIR) { |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 354 | close(fd); |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 355 | errno = EBUSY; |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 356 | return -1; |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 357 | } |
Björn Stenberg | 307f5d8 | 2002-11-01 15:26:06 +0000 | [diff] [blame] | 358 | close(fd); |
| 359 | |
Miika Pekkarinen | d489377 | 2006-04-13 21:14:13 +0000 | [diff] [blame] | 360 | fd = open_internal(path, O_RDONLY, false); |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 361 | if ( fd < 0 ) { |
| 362 | errno = EIO; |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 363 | return fd * 10 - 2; |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 364 | } |
| 365 | |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 366 | /* extract new file name */ |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 367 | nameptr = strrchr(newpath,'/'); |
| 368 | if (nameptr) |
| 369 | nameptr++; |
| 370 | else |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 371 | return - 3; |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 372 | |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 373 | /* Extract new path */ |
| 374 | strcpy(newpath2, newpath); |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 375 | |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 376 | dirptr = strrchr(newpath2,'/'); |
| 377 | if(dirptr) |
| 378 | *dirptr = 0; |
| 379 | else |
| 380 | return - 4; |
| 381 | |
| 382 | dirptr = newpath2; |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 383 | |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 384 | if(strlen(dirptr) == 0) { |
| 385 | dirptr = "/"; |
| 386 | } |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 387 | |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 388 | dir = opendir_uncached(dirptr); |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 389 | if(!dir) |
| 390 | return - 5; |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 391 | |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 392 | file = &openfiles[fd]; |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 393 | |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 394 | rc = fat_rename(&file->fatfile, &dir->fatdir, nameptr, |
| 395 | file->size, file->attr); |
Dan Everton | ccd0e74 | 2006-03-02 11:03:34 +0000 | [diff] [blame] | 396 | #ifdef HAVE_MULTIVOLUME |
| 397 | if ( rc == -1) { |
Jens Arnold | 7a0110e | 2006-03-02 22:29:53 +0000 | [diff] [blame] | 398 | DEBUGF("Failed renaming file across volumnes: %d\n", rc); |
| 399 | errno = EXDEV; |
| 400 | return -6; |
Dan Everton | ccd0e74 | 2006-03-02 11:03:34 +0000 | [diff] [blame] | 401 | } |
| 402 | #endif |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 403 | if ( rc < 0 ) { |
| 404 | DEBUGF("Failed renaming file: %d\n", rc); |
| 405 | errno = EIO; |
Dan Everton | ccd0e74 | 2006-03-02 11:03:34 +0000 | [diff] [blame] | 406 | return rc * 10 - 7; |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 407 | } |
| 408 | |
Peter D'Hoye | c04f4976 | 2008-02-07 22:15:13 +0000 | [diff] [blame] | 409 | #ifdef HAVE_DIRCACHE |
| 410 | dircache_rename(path, newpath); |
| 411 | #endif |
| 412 | |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 413 | rc = close(fd); |
| 414 | if (rc<0) { |
| 415 | errno = EIO; |
Dan Everton | ccd0e74 | 2006-03-02 11:03:34 +0000 | [diff] [blame] | 416 | return rc * 10 - 8; |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 417 | } |
| 418 | |
Kevin Ferrare | 011a325 | 2007-07-20 17:06:55 +0000 | [diff] [blame] | 419 | rc = closedir_uncached(dir); |
Linus Nielsen Feltzing | e0e0140 | 2004-08-22 11:28:24 +0000 | [diff] [blame] | 420 | if (rc<0) { |
| 421 | errno = EIO; |
Dan Everton | ccd0e74 | 2006-03-02 11:03:34 +0000 | [diff] [blame] | 422 | return rc * 10 - 9; |
Björn Stenberg | c5f5be5 | 2002-11-19 12:48:50 +0000 | [diff] [blame] | 423 | } |
| 424 | |
| 425 | return 0; |
Björn Stenberg | 307f5d8 | 2002-11-01 15:26:06 +0000 | [diff] [blame] | 426 | } |
| 427 | |
Daniel Stenberg | ae960a9 | 2003-12-08 21:58:38 +0000 | [diff] [blame] | 428 | int ftruncate(int fd, off_t size) |
Björn Stenberg | 68640ed | 2002-11-11 14:40:18 +0000 | [diff] [blame] | 429 | { |
| 430 | int rc, sector; |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 431 | struct filedesc* file = &openfiles[fd]; |
Björn Stenberg | 68640ed | 2002-11-11 14:40:18 +0000 | [diff] [blame] | 432 | |
Jens Arnold | ef3e129 | 2006-12-04 21:37:22 +0000 | [diff] [blame] | 433 | sector = size / SECTOR_SIZE; |
| 434 | if (size % SECTOR_SIZE) |
Björn Stenberg | 68640ed | 2002-11-11 14:40:18 +0000 | [diff] [blame] | 435 | sector++; |
| 436 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 437 | rc = fat_seek(&(file->fatfile), sector); |
Björn Stenberg | 68640ed | 2002-11-11 14:40:18 +0000 | [diff] [blame] | 438 | if (rc < 0) { |
| 439 | errno = EIO; |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 440 | return rc * 10 - 1; |
Björn Stenberg | 68640ed | 2002-11-11 14:40:18 +0000 | [diff] [blame] | 441 | } |
| 442 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 443 | rc = fat_truncate(&(file->fatfile)); |
Björn Stenberg | 68640ed | 2002-11-11 14:40:18 +0000 | [diff] [blame] | 444 | if (rc < 0) { |
| 445 | errno = EIO; |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 446 | return rc * 10 - 2; |
Björn Stenberg | 68640ed | 2002-11-11 14:40:18 +0000 | [diff] [blame] | 447 | } |
| 448 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 449 | file->size = size; |
Miika Pekkarinen | 2d93495 | 2006-03-28 11:51:12 +0000 | [diff] [blame] | 450 | #ifdef HAVE_DIRCACHE |
| 451 | dircache_update_filesize(fd, size, file->fatfile.firstcluster); |
| 452 | #endif |
Björn Stenberg | 68640ed | 2002-11-11 14:40:18 +0000 | [diff] [blame] | 453 | |
| 454 | return 0; |
| 455 | } |
| 456 | |
Björn Stenberg | 9f9c495 | 2002-11-11 15:45:43 +0000 | [diff] [blame] | 457 | static int flush_cache(int fd) |
| 458 | { |
| 459 | int rc; |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 460 | struct filedesc* file = &openfiles[fd]; |
Jens Arnold | ef3e129 | 2006-12-04 21:37:22 +0000 | [diff] [blame] | 461 | long sector = file->fileoffset / SECTOR_SIZE; |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 462 | |
Linus Nielsen Feltzing | 5f12c8f | 2003-03-10 21:55:59 +0000 | [diff] [blame] | 463 | DEBUGF("Flushing dirty sector cache\n"); |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 464 | |
Hardeep Sidhu | e5e9bc3 | 2003-03-15 21:13:35 +0000 | [diff] [blame] | 465 | /* make sure we are on correct sector */ |
| 466 | rc = fat_seek(&(file->fatfile), sector); |
| 467 | if ( rc < 0 ) |
| 468 | return rc * 10 - 3; |
| 469 | |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 470 | rc = fat_readwrite(&(file->fatfile), 1, file->cache, true ); |
Linus Nielsen Feltzing | c6db787 | 2003-06-19 12:08:22 +0000 | [diff] [blame] | 471 | |
| 472 | if ( rc < 0 ) { |
| 473 | if(file->fatfile.eof) |
| 474 | errno = ENOSPC; |
| 475 | |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 476 | return rc * 10 - 2; |
Linus Nielsen Feltzing | c6db787 | 2003-06-19 12:08:22 +0000 | [diff] [blame] | 477 | } |
Björn Stenberg | 9f9c495 | 2002-11-11 15:45:43 +0000 | [diff] [blame] | 478 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 479 | file->dirty = false; |
Björn Stenberg | 9f9c495 | 2002-11-11 15:45:43 +0000 | [diff] [blame] | 480 | |
| 481 | return 0; |
| 482 | } |
| 483 | |
Jean-Philippe Bernardy | cea551d | 2005-01-23 23:29:35 +0000 | [diff] [blame] | 484 | static int readwrite(int fd, void* buf, long count, bool write) |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 485 | { |
Jean-Philippe Bernardy | cea551d | 2005-01-23 23:29:35 +0000 | [diff] [blame] | 486 | long sectors; |
| 487 | long nread=0; |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 488 | struct filedesc* file = &openfiles[fd]; |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 489 | int rc; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 490 | |
Peter D'Hoye | 85058f5 | 2007-10-10 23:26:17 +0000 | [diff] [blame] | 491 | if (fd < 0 || fd > MAX_OPEN_FILES-1) { |
| 492 | errno = EINVAL; |
| 493 | return -1; |
| 494 | } |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 495 | if ( !file->busy ) { |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 496 | errno = EBADF; |
| 497 | return -1; |
| 498 | } |
| 499 | |
Jean-Philippe Bernardy | cea551d | 2005-01-23 23:29:35 +0000 | [diff] [blame] | 500 | LDEBUGF( "readwrite(%d,%lx,%ld,%s)\n", |
| 501 | fd,(long)buf,count,write?"write":"read"); |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 502 | |
Björn Stenberg | 08356fb | 2002-10-31 19:05:25 +0000 | [diff] [blame] | 503 | /* attempt to read past EOF? */ |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 504 | if (!write && count > file->size - file->fileoffset) |
| 505 | count = file->size - file->fileoffset; |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 506 | |
| 507 | /* any head bytes? */ |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 508 | if ( file->cacheoffset != -1 ) { |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 509 | int offs = file->cacheoffset; |
Jens Arnold | ef3e129 | 2006-12-04 21:37:22 +0000 | [diff] [blame] | 510 | int headbytes = MIN(count, SECTOR_SIZE - offs); |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 511 | |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 512 | if (write) { |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 513 | memcpy( file->cache + offs, buf, headbytes ); |
Jens Arnold | a601fb8 | 2005-12-17 12:17:11 +0000 | [diff] [blame] | 514 | file->dirty = true; |
| 515 | } |
| 516 | else { |
| 517 | memcpy( buf, file->cache + offs, headbytes ); |
| 518 | } |
| 519 | |
Jens Arnold | ef3e129 | 2006-12-04 21:37:22 +0000 | [diff] [blame] | 520 | if (offs + headbytes == SECTOR_SIZE) { |
Jens Arnold | a601fb8 | 2005-12-17 12:17:11 +0000 | [diff] [blame] | 521 | if (file->dirty) { |
Daniel Stenberg | 5079812 | 2007-04-26 10:29:41 +0000 | [diff] [blame] | 522 | rc = flush_cache(fd); |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 523 | if ( rc < 0 ) { |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 524 | errno = EIO; |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 525 | return rc * 10 - 2; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 526 | } |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 527 | } |
Jens Arnold | a601fb8 | 2005-12-17 12:17:11 +0000 | [diff] [blame] | 528 | file->cacheoffset = -1; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 529 | } |
| 530 | else { |
Jens Arnold | a601fb8 | 2005-12-17 12:17:11 +0000 | [diff] [blame] | 531 | file->cacheoffset += headbytes; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 532 | } |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 533 | |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 534 | nread = headbytes; |
| 535 | count -= headbytes; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 536 | } |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 537 | |
Jens Arnold | f78524b | 2004-11-17 02:34:17 +0000 | [diff] [blame] | 538 | /* If the buffer has been modified, either it has been flushed already |
| 539 | * (if (offs+headbytes == SECTOR_SIZE)...) or does not need to be (no |
| 540 | * more data to follow in this call). Do NOT flush here. */ |
Björn Stenberg | 228605d | 2002-11-11 13:57:58 +0000 | [diff] [blame] | 541 | |
Linus Nielsen Feltzing | c6db787 | 2003-06-19 12:08:22 +0000 | [diff] [blame] | 542 | /* read/write whole sectors right into/from the supplied buffer */ |
Jens Arnold | ef3e129 | 2006-12-04 21:37:22 +0000 | [diff] [blame] | 543 | sectors = count / SECTOR_SIZE; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 544 | if ( sectors ) { |
Daniel Stenberg | 5079812 | 2007-04-26 10:29:41 +0000 | [diff] [blame] | 545 | rc = fat_readwrite(&(file->fatfile), sectors, |
Jörg Hohensohn | 85c91a3 | 2004-10-01 19:45:51 +0000 | [diff] [blame] | 546 | (unsigned char*)buf+nread, write ); |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 547 | if ( rc < 0 ) { |
Jean-Philippe Bernardy | cea551d | 2005-01-23 23:29:35 +0000 | [diff] [blame] | 548 | DEBUGF("Failed read/writing %ld sectors\n",sectors); |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 549 | errno = EIO; |
Linus Nielsen Feltzing | c6db787 | 2003-06-19 12:08:22 +0000 | [diff] [blame] | 550 | if(write && file->fatfile.eof) { |
| 551 | DEBUGF("No space left on device\n"); |
| 552 | errno = ENOSPC; |
| 553 | } else { |
| 554 | file->fileoffset += nread; |
| 555 | } |
Björn Stenberg | 631b8d3 | 2003-04-15 08:07:50 +0000 | [diff] [blame] | 556 | file->cacheoffset = -1; |
Peter D'Hoye | eb947cd | 2007-12-13 23:36:22 +0000 | [diff] [blame] | 557 | /* adjust file size to length written */ |
| 558 | if ( write && file->fileoffset > file->size ) |
| 559 | { |
| 560 | file->size = file->fileoffset; |
| 561 | #ifdef HAVE_DIRCACHE |
| 562 | dircache_update_filesize(fd, file->size, file->fatfile.firstcluster); |
| 563 | #endif |
| 564 | } |
Björn Stenberg | 188be8e | 2003-03-12 15:06:57 +0000 | [diff] [blame] | 565 | return nread ? nread : rc * 10 - 4; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 566 | } |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 567 | else { |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 568 | if ( rc > 0 ) { |
Jens Arnold | ef3e129 | 2006-12-04 21:37:22 +0000 | [diff] [blame] | 569 | nread += rc * SECTOR_SIZE; |
| 570 | count -= sectors * SECTOR_SIZE; |
Björn Stenberg | 08356fb | 2002-10-31 19:05:25 +0000 | [diff] [blame] | 571 | |
| 572 | /* if eof, skip tail bytes */ |
| 573 | if ( rc < sectors ) |
| 574 | count = 0; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 575 | } |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 576 | else { |
| 577 | /* eof */ |
| 578 | count=0; |
| 579 | } |
| 580 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 581 | file->cacheoffset = -1; |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 582 | } |
| 583 | } |
| 584 | |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 585 | /* any tail bytes? */ |
| 586 | if ( count ) { |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 587 | if (write) { |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 588 | if ( file->fileoffset + nread < file->size ) { |
Björn Stenberg | 6dc77d8 | 2002-11-11 11:16:49 +0000 | [diff] [blame] | 589 | /* sector is only partially filled. copy-back from disk */ |
Björn Stenberg | 6dc77d8 | 2002-11-11 11:16:49 +0000 | [diff] [blame] | 590 | LDEBUGF("Copy-back tail cache\n"); |
Björn Stenberg | 631b8d3 | 2003-04-15 08:07:50 +0000 | [diff] [blame] | 591 | rc = fat_readwrite(&(file->fatfile), 1, file->cache, false ); |
Björn Stenberg | 6dc77d8 | 2002-11-11 11:16:49 +0000 | [diff] [blame] | 592 | if ( rc < 0 ) { |
Linus Nielsen Feltzing | 490085a | 2003-02-22 01:54:03 +0000 | [diff] [blame] | 593 | DEBUGF("Failed writing\n"); |
Björn Stenberg | 6dc77d8 | 2002-11-11 11:16:49 +0000 | [diff] [blame] | 594 | errno = EIO; |
Björn Stenberg | 631b8d3 | 2003-04-15 08:07:50 +0000 | [diff] [blame] | 595 | file->fileoffset += nread; |
| 596 | file->cacheoffset = -1; |
Peter D'Hoye | eb947cd | 2007-12-13 23:36:22 +0000 | [diff] [blame] | 597 | /* adjust file size to length written */ |
| 598 | if ( file->fileoffset > file->size ) |
| 599 | { |
| 600 | file->size = file->fileoffset; |
| 601 | #ifdef HAVE_DIRCACHE |
| 602 | dircache_update_filesize(fd, file->size, file->fatfile.firstcluster); |
| 603 | #endif |
| 604 | } |
Björn Stenberg | 188be8e | 2003-03-12 15:06:57 +0000 | [diff] [blame] | 605 | return nread ? nread : rc * 10 - 5; |
Björn Stenberg | 6dc77d8 | 2002-11-11 11:16:49 +0000 | [diff] [blame] | 606 | } |
| 607 | /* seek back one sector to put file position right */ |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 608 | rc = fat_seek(&(file->fatfile), |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 609 | (file->fileoffset + nread) / |
Jens Arnold | ef3e129 | 2006-12-04 21:37:22 +0000 | [diff] [blame] | 610 | SECTOR_SIZE); |
Björn Stenberg | 6dc77d8 | 2002-11-11 11:16:49 +0000 | [diff] [blame] | 611 | if ( rc < 0 ) { |
| 612 | DEBUGF("fat_seek() failed\n"); |
| 613 | errno = EIO; |
Björn Stenberg | 631b8d3 | 2003-04-15 08:07:50 +0000 | [diff] [blame] | 614 | file->fileoffset += nread; |
| 615 | file->cacheoffset = -1; |
Peter D'Hoye | eb947cd | 2007-12-13 23:36:22 +0000 | [diff] [blame] | 616 | /* adjust file size to length written */ |
| 617 | if ( file->fileoffset > file->size ) |
| 618 | { |
| 619 | file->size = file->fileoffset; |
| 620 | #ifdef HAVE_DIRCACHE |
| 621 | dircache_update_filesize(fd, file->size, file->fatfile.firstcluster); |
| 622 | #endif |
| 623 | } |
Björn Stenberg | 188be8e | 2003-03-12 15:06:57 +0000 | [diff] [blame] | 624 | return nread ? nread : rc * 10 - 6; |
Björn Stenberg | 6dc77d8 | 2002-11-11 11:16:49 +0000 | [diff] [blame] | 625 | } |
Björn Stenberg | 11a09e6 | 2002-11-11 10:21:51 +0000 | [diff] [blame] | 626 | } |
Jörg Hohensohn | 85c91a3 | 2004-10-01 19:45:51 +0000 | [diff] [blame] | 627 | memcpy( file->cache, (unsigned char*)buf + nread, count ); |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 628 | file->dirty = true; |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 629 | } |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 630 | else { |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 631 | rc = fat_readwrite(&(file->fatfile), 1, &(file->cache),false); |
| 632 | if (rc < 1 ) { |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 633 | DEBUGF("Failed caching sector\n"); |
| 634 | errno = EIO; |
Björn Stenberg | 631b8d3 | 2003-04-15 08:07:50 +0000 | [diff] [blame] | 635 | file->fileoffset += nread; |
| 636 | file->cacheoffset = -1; |
Björn Stenberg | 188be8e | 2003-03-12 15:06:57 +0000 | [diff] [blame] | 637 | return nread ? nread : rc * 10 - 7; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 638 | } |
Jörg Hohensohn | 85c91a3 | 2004-10-01 19:45:51 +0000 | [diff] [blame] | 639 | memcpy( (unsigned char*)buf + nread, file->cache, count ); |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 640 | } |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 641 | |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 642 | nread += count; |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 643 | file->cacheoffset = count; |
Björn Stenberg | 073ce1a | 2002-05-08 12:10:30 +0000 | [diff] [blame] | 644 | } |
| 645 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 646 | file->fileoffset += nread; |
Jean-Philippe Bernardy | cea551d | 2005-01-23 23:29:35 +0000 | [diff] [blame] | 647 | LDEBUGF("fileoffset: %ld\n", file->fileoffset); |
Björn Stenberg | 08356fb | 2002-10-31 19:05:25 +0000 | [diff] [blame] | 648 | |
| 649 | /* adjust file size to length written */ |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 650 | if ( write && file->fileoffset > file->size ) |
Miika Pekkarinen | ab78b04 | 2005-10-07 17:38:05 +0000 | [diff] [blame] | 651 | { |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 652 | file->size = file->fileoffset; |
Miika Pekkarinen | ab78b04 | 2005-10-07 17:38:05 +0000 | [diff] [blame] | 653 | #ifdef HAVE_DIRCACHE |
Miika Pekkarinen | 2d93495 | 2006-03-28 11:51:12 +0000 | [diff] [blame] | 654 | dircache_update_filesize(fd, file->size, file->fatfile.firstcluster); |
Miika Pekkarinen | ab78b04 | 2005-10-07 17:38:05 +0000 | [diff] [blame] | 655 | #endif |
| 656 | } |
Björn Stenberg | 08356fb | 2002-10-31 19:05:25 +0000 | [diff] [blame] | 657 | |
Björn Stenberg | 4bd8703 | 2002-05-07 16:01:53 +0000 | [diff] [blame] | 658 | return nread; |
| 659 | } |
| 660 | |
Daniel Stenberg | ae960a9 | 2003-12-08 21:58:38 +0000 | [diff] [blame] | 661 | ssize_t write(int fd, const void* buf, size_t count) |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 662 | { |
Björn Stenberg | 228605d | 2002-11-11 13:57:58 +0000 | [diff] [blame] | 663 | if (!openfiles[fd].write) { |
| 664 | errno = EACCES; |
| 665 | return -1; |
| 666 | } |
Daniel Stenberg | ae960a9 | 2003-12-08 21:58:38 +0000 | [diff] [blame] | 667 | return readwrite(fd, (void *)buf, count, true); |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 668 | } |
| 669 | |
Daniel Stenberg | ae960a9 | 2003-12-08 21:58:38 +0000 | [diff] [blame] | 670 | ssize_t read(int fd, void* buf, size_t count) |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 671 | { |
| 672 | return readwrite(fd, buf, count, false); |
| 673 | } |
| 674 | |
| 675 | |
Daniel Stenberg | ae960a9 | 2003-12-08 21:58:38 +0000 | [diff] [blame] | 676 | off_t lseek(int fd, off_t offset, int whence) |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 677 | { |
Jean-Philippe Bernardy | cea551d | 2005-01-23 23:29:35 +0000 | [diff] [blame] | 678 | off_t pos; |
| 679 | long newsector; |
| 680 | long oldsector; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 681 | int sectoroffset; |
| 682 | int rc; |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 683 | struct filedesc* file = &openfiles[fd]; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 684 | |
Jean-Philippe Bernardy | cea551d | 2005-01-23 23:29:35 +0000 | [diff] [blame] | 685 | LDEBUGF("lseek(%d,%ld,%d)\n",fd,offset,whence); |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 686 | |
Peter D'Hoye | 85058f5 | 2007-10-10 23:26:17 +0000 | [diff] [blame] | 687 | if (fd < 0 || fd > MAX_OPEN_FILES-1) { |
| 688 | errno = EINVAL; |
| 689 | return -1; |
| 690 | } |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 691 | if ( !file->busy ) { |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 692 | errno = EBADF; |
| 693 | return -1; |
| 694 | } |
| 695 | |
| 696 | switch ( whence ) { |
| 697 | case SEEK_SET: |
| 698 | pos = offset; |
| 699 | break; |
| 700 | |
| 701 | case SEEK_CUR: |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 702 | pos = file->fileoffset + offset; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 703 | break; |
| 704 | |
| 705 | case SEEK_END: |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 706 | pos = file->size + offset; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 707 | break; |
| 708 | |
| 709 | default: |
| 710 | errno = EINVAL; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 711 | return -2; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 712 | } |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 713 | if ((pos < 0) || (pos > file->size)) { |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 714 | errno = EINVAL; |
Björn Stenberg | b7b48fe | 2002-10-20 22:50:58 +0000 | [diff] [blame] | 715 | return -3; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 716 | } |
| 717 | |
| 718 | /* new sector? */ |
Jens Arnold | ef3e129 | 2006-12-04 21:37:22 +0000 | [diff] [blame] | 719 | newsector = pos / SECTOR_SIZE; |
| 720 | oldsector = file->fileoffset / SECTOR_SIZE; |
| 721 | sectoroffset = pos % SECTOR_SIZE; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 722 | |
| 723 | if ( (newsector != oldsector) || |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 724 | ((file->cacheoffset==-1) && sectoroffset) ) { |
Björn Stenberg | 9f9c495 | 2002-11-11 15:45:43 +0000 | [diff] [blame] | 725 | |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 726 | if ( newsector != oldsector ) { |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 727 | if (file->dirty) { |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 728 | rc = flush_cache(fd); |
| 729 | if (rc < 0) |
| 730 | return rc * 10 - 5; |
Björn Stenberg | 9f9c495 | 2002-11-11 15:45:43 +0000 | [diff] [blame] | 731 | } |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 732 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 733 | rc = fat_seek(&(file->fatfile), newsector); |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 734 | if ( rc < 0 ) { |
| 735 | errno = EIO; |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 736 | return rc * 10 - 4; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 737 | } |
| 738 | } |
Björn Stenberg | 675d258 | 2002-10-31 20:41:36 +0000 | [diff] [blame] | 739 | if ( sectoroffset ) { |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 740 | rc = fat_readwrite(&(file->fatfile), 1, |
| 741 | &(file->cache),false); |
Björn Stenberg | 675d258 | 2002-10-31 20:41:36 +0000 | [diff] [blame] | 742 | if ( rc < 0 ) { |
| 743 | errno = EIO; |
Linus Nielsen Feltzing | a077e27 | 2003-02-26 02:08:52 +0000 | [diff] [blame] | 744 | return rc * 10 - 6; |
Björn Stenberg | 675d258 | 2002-10-31 20:41:36 +0000 | [diff] [blame] | 745 | } |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 746 | file->cacheoffset = sectoroffset; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 747 | } |
Björn Stenberg | c9fb098 | 2002-11-04 14:59:46 +0000 | [diff] [blame] | 748 | else |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 749 | file->cacheoffset = -1; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 750 | } |
Björn Stenberg | 88c861e | 2002-06-26 14:21:25 +0000 | [diff] [blame] | 751 | else |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 752 | if ( file->cacheoffset != -1 ) |
| 753 | file->cacheoffset = sectoroffset; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 754 | |
Björn Stenberg | 94fb95f | 2002-11-11 16:13:45 +0000 | [diff] [blame] | 755 | file->fileoffset = pos; |
Björn Stenberg | 1c32179 | 2002-05-08 15:16:02 +0000 | [diff] [blame] | 756 | |
| 757 | return pos; |
| 758 | } |
Linus Nielsen Feltzing | e98bad5 | 2003-03-18 00:39:57 +0000 | [diff] [blame] | 759 | |
Jean-Philippe Bernardy | cea551d | 2005-01-23 23:29:35 +0000 | [diff] [blame] | 760 | off_t filesize(int fd) |
Linus Nielsen Feltzing | e98bad5 | 2003-03-18 00:39:57 +0000 | [diff] [blame] | 761 | { |
| 762 | struct filedesc* file = &openfiles[fd]; |
| 763 | |
Peter D'Hoye | 85058f5 | 2007-10-10 23:26:17 +0000 | [diff] [blame] | 764 | if (fd < 0 || fd > MAX_OPEN_FILES-1) { |
| 765 | errno = EINVAL; |
| 766 | return -1; |
| 767 | } |
Linus Nielsen Feltzing | e98bad5 | 2003-03-18 00:39:57 +0000 | [diff] [blame] | 768 | if ( !file->busy ) { |
| 769 | errno = EBADF; |
| 770 | return -1; |
| 771 | } |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 772 | |
Linus Nielsen Feltzing | e98bad5 | 2003-03-18 00:39:57 +0000 | [diff] [blame] | 773 | return file->size; |
| 774 | } |
Jörg Hohensohn | dc7534b | 2005-01-28 21:32:16 +0000 | [diff] [blame] | 775 | |
| 776 | |
| 777 | #ifdef HAVE_HOTSWAP |
Peter D'Hoye | bae8f4c | 2007-10-29 00:04:35 +0000 | [diff] [blame] | 778 | /* release all file handles on a given volume "by force", to avoid leaks */ |
Jörg Hohensohn | dc7534b | 2005-01-28 21:32:16 +0000 | [diff] [blame] | 779 | int release_files(int volume) |
| 780 | { |
| 781 | struct filedesc* pfile = openfiles; |
| 782 | int fd; |
| 783 | int closed = 0; |
| 784 | for ( fd=0; fd<MAX_OPEN_FILES; fd++, pfile++) |
| 785 | { |
| 786 | if (pfile->fatfile.volume == volume) |
| 787 | { |
| 788 | pfile->busy = false; /* mark as available, no further action */ |
| 789 | closed++; |
| 790 | } |
| 791 | } |
| 792 | return closed; /* return how many we did */ |
| 793 | } |
| 794 | #endif /* #ifdef HAVE_HOTSWAP */ |
Peter D'Hoye | 85058f5 | 2007-10-10 23:26:17 +0000 | [diff] [blame] | 795 | |