diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-11-11 15:45:43 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-11-11 15:45:43 +0000 |
commit | 9f9c495662cbba43fdb3bf577a48d40e30e1245e (patch) | |
tree | 3915204f95071cefce7f8928113f389004d43a98 /firmware | |
parent | 68640edf90c84c3d4494f0852f6236e1929a4603 (diff) | |
download | rockbox-9f9c495662cbba43fdb3bf577a48d40e30e1245e.tar.gz rockbox-9f9c495662cbba43fdb3bf577a48d40e30e1245e.zip |
Added support for O_CREAT, O_APPEND and O_TRUNC.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2828 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/common/file.c | 100 | ||||
-rw-r--r-- | firmware/common/file.h | 3 |
2 files changed, 63 insertions, 40 deletions
diff --git a/firmware/common/file.c b/firmware/common/file.c index cf8c46c5ab..82a33ada2d 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c | |||
@@ -44,14 +44,17 @@ struct filedesc { | |||
44 | bool busy; | 44 | bool busy; |
45 | bool write; | 45 | bool write; |
46 | bool dirty; | 46 | bool dirty; |
47 | bool trunc; | ||
47 | }; | 48 | }; |
48 | 49 | ||
49 | static struct filedesc openfiles[MAX_OPEN_FILES]; | 50 | static struct filedesc openfiles[MAX_OPEN_FILES]; |
50 | 51 | ||
52 | static int flush_cache(int fd); | ||
53 | |||
51 | int creat(const char *pathname, int mode) | 54 | int creat(const char *pathname, int mode) |
52 | { | 55 | { |
53 | (void)mode; | 56 | (void)mode; |
54 | return open(pathname, O_WRONLY); | 57 | return open(pathname, O_WRONLY|O_CREAT); |
55 | } | 58 | } |
56 | 59 | ||
57 | int open(const char* pathname, int flags) | 60 | int open(const char* pathname, int flags) |
@@ -81,20 +84,16 @@ int open(const char* pathname, int flags) | |||
81 | return -2; | 84 | return -2; |
82 | } | 85 | } |
83 | 86 | ||
84 | switch ( flags ) { | 87 | if (flags & O_RDONLY) { |
85 | case O_RDONLY: | 88 | openfiles[fd].write = false; |
86 | openfiles[fd].write = false; | 89 | } |
87 | break; | 90 | else { |
88 | 91 | if (flags & (O_RDWR | O_WRONLY)) { | |
89 | case O_RDWR: | ||
90 | case O_WRONLY: | ||
91 | openfiles[fd].write = true; | 92 | openfiles[fd].write = true; |
92 | break; | ||
93 | 93 | ||
94 | default: | 94 | if (flags & O_TRUNC) |
95 | DEBUGF("Only O_RDONLY and O_WRONLY is supported\n"); | 95 | openfiles[fd].trunc = true; |
96 | errno = EROFS; | 96 | } |
97 | return -3; | ||
98 | } | 97 | } |
99 | openfiles[fd].busy = true; | 98 | openfiles[fd].busy = true; |
100 | 99 | ||
@@ -130,7 +129,7 @@ int open(const char* pathname, int flags) | |||
130 | closedir(dir); | 129 | closedir(dir); |
131 | if ( !entry ) { | 130 | if ( !entry ) { |
132 | LDEBUGF("Didn't find file %s\n",name); | 131 | LDEBUGF("Didn't find file %s\n",name); |
133 | if ( openfiles[fd].write ) { | 132 | if ( openfiles[fd].write && (flags & O_CREAT) ) { |
134 | if (fat_create_file(name, | 133 | if (fat_create_file(name, |
135 | &(openfiles[fd].fatfile), | 134 | &(openfiles[fd].fatfile), |
136 | &(dir->fatdir)) < 0) { | 135 | &(dir->fatdir)) < 0) { |
@@ -151,6 +150,12 @@ int open(const char* pathname, int flags) | |||
151 | 150 | ||
152 | openfiles[fd].cacheoffset = -1; | 151 | openfiles[fd].cacheoffset = -1; |
153 | openfiles[fd].fileoffset = 0; | 152 | openfiles[fd].fileoffset = 0; |
153 | |||
154 | if (openfiles[fd].write && (flags & O_APPEND)) { | ||
155 | if (lseek(fd,0,SEEK_END) < 0 ) | ||
156 | return -7; | ||
157 | } | ||
158 | |||
154 | return fd; | 159 | return fd; |
155 | } | 160 | } |
156 | 161 | ||
@@ -169,18 +174,21 @@ int close(int fd) | |||
169 | return -2; | 174 | return -2; |
170 | } | 175 | } |
171 | if (openfiles[fd].write) { | 176 | if (openfiles[fd].write) { |
177 | /* truncate? */ | ||
178 | if (openfiles[fd].trunc) { | ||
179 | if (ftruncate(fd, openfiles[fd].fileoffset) < 0) | ||
180 | return -1; | ||
181 | } | ||
182 | |||
172 | /* flush sector cache */ | 183 | /* flush sector cache */ |
173 | if ( openfiles[fd].dirty ) { | 184 | if ( openfiles[fd].dirty ) { |
174 | if ( fat_readwrite(&(openfiles[fd].fatfile), 1, | 185 | if (flush_cache(fd) < 0) |
175 | &(openfiles[fd].cache),true) < 0 ) { | 186 | return -2; |
176 | DEBUGF("Failed flushing cache\n"); | ||
177 | errno = EIO; | ||
178 | rc = -1; | ||
179 | } | ||
180 | } | 187 | } |
181 | 188 | ||
182 | /* tie up all loose ends */ | 189 | /* tie up all loose ends */ |
183 | fat_closewrite(&(openfiles[fd].fatfile), openfiles[fd].size); | 190 | if (fat_closewrite(&(openfiles[fd].fatfile), openfiles[fd].size) < 0) |
191 | return -3; | ||
184 | } | 192 | } |
185 | openfiles[fd].busy = false; | 193 | openfiles[fd].busy = false; |
186 | return rc; | 194 | return rc; |
@@ -239,6 +247,28 @@ int ftruncate(int fd, unsigned int size) | |||
239 | return 0; | 247 | return 0; |
240 | } | 248 | } |
241 | 249 | ||
250 | static int flush_cache(int fd) | ||
251 | { | ||
252 | int rc; | ||
253 | int sector = openfiles[fd].fileoffset / SECTOR_SIZE; | ||
254 | |||
255 | DEBUGF("Flushing dirty sector cache %x\n", sector); | ||
256 | |||
257 | /* seek back one sector to get file position right */ | ||
258 | rc = fat_seek(&(openfiles[fd].fatfile), sector); | ||
259 | if ( rc < 0 ) | ||
260 | return -1; | ||
261 | |||
262 | rc = fat_readwrite(&(openfiles[fd].fatfile), 1, | ||
263 | openfiles[fd].cache, true ); | ||
264 | if ( rc < 0 ) | ||
265 | return -2; | ||
266 | |||
267 | openfiles[fd].dirty = false; | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
242 | static int readwrite(int fd, void* buf, int count, bool write) | 272 | static int readwrite(int fd, void* buf, int count, bool write) |
243 | { | 273 | { |
244 | int sectors; | 274 | int sectors; |
@@ -296,24 +326,8 @@ static int readwrite(int fd, void* buf, int count, bool write) | |||
296 | 326 | ||
297 | /* if buffer has been modified, write it back to disk */ | 327 | /* if buffer has been modified, write it back to disk */ |
298 | if (count && openfiles[fd].dirty) { | 328 | if (count && openfiles[fd].dirty) { |
299 | int rc; | 329 | if (flush_cache(fd) < 0) |
300 | DEBUGF("Flushing dirty sector cache\n"); | ||
301 | |||
302 | /* seek back one sector to get file position right */ | ||
303 | rc = fat_seek(&(openfiles[fd].fatfile), | ||
304 | openfiles[fd].fileoffset / SECTOR_SIZE); | ||
305 | if ( rc < 0 ) { | ||
306 | errno = EIO; | ||
307 | return -3; | 330 | return -3; |
308 | } | ||
309 | |||
310 | rc = fat_readwrite(&(openfiles[fd].fatfile), 1, | ||
311 | openfiles[fd].cache, true ); | ||
312 | if ( rc < 0 ) { | ||
313 | errno = EIO; | ||
314 | return -4; | ||
315 | } | ||
316 | openfiles[fd].dirty = false; | ||
317 | } | 331 | } |
318 | 332 | ||
319 | /* read whole sectors right into the supplied buffer */ | 333 | /* read whole sectors right into the supplied buffer */ |
@@ -454,7 +468,13 @@ int lseek(int fd, int offset, int whence) | |||
454 | 468 | ||
455 | if ( (newsector != oldsector) || | 469 | if ( (newsector != oldsector) || |
456 | ((openfiles[fd].cacheoffset==-1) && sectoroffset) ) { | 470 | ((openfiles[fd].cacheoffset==-1) && sectoroffset) ) { |
471 | |||
457 | if ( newsector != oldsector ) { | 472 | if ( newsector != oldsector ) { |
473 | if (openfiles[fd].dirty) { | ||
474 | if (flush_cache(fd) < 0) | ||
475 | return -5; | ||
476 | } | ||
477 | |||
458 | rc = fat_seek(&(openfiles[fd].fatfile), newsector); | 478 | rc = fat_seek(&(openfiles[fd].fatfile), newsector); |
459 | if ( rc < 0 ) { | 479 | if ( rc < 0 ) { |
460 | errno = EIO; | 480 | errno = EIO; |
@@ -466,7 +486,7 @@ int lseek(int fd, int offset, int whence) | |||
466 | &(openfiles[fd].cache),false); | 486 | &(openfiles[fd].cache),false); |
467 | if ( rc < 0 ) { | 487 | if ( rc < 0 ) { |
468 | errno = EIO; | 488 | errno = EIO; |
469 | return -5; | 489 | return -6; |
470 | } | 490 | } |
471 | openfiles[fd].cacheoffset = sectoroffset; | 491 | openfiles[fd].cacheoffset = sectoroffset; |
472 | } | 492 | } |
diff --git a/firmware/common/file.h b/firmware/common/file.h index 59ff717d1d..2effe31ac9 100644 --- a/firmware/common/file.h +++ b/firmware/common/file.h | |||
@@ -37,6 +37,9 @@ | |||
37 | #define O_RDONLY 0 | 37 | #define O_RDONLY 0 |
38 | #define O_WRONLY 1 | 38 | #define O_WRONLY 1 |
39 | #define O_RDWR 2 | 39 | #define O_RDWR 2 |
40 | #define O_CREAT 3 | ||
41 | #define O_APPEND 4 | ||
42 | #define O_TRUNC 5 | ||
40 | #endif | 43 | #endif |
41 | 44 | ||
42 | #if defined(__MINGW32__) && defined(SIMULATOR) | 45 | #if defined(__MINGW32__) && defined(SIMULATOR) |