1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Björn Stenberg 2002-11-11 15:45:43 +00:00
parent 68640edf90
commit 9f9c495662
2 changed files with 63 additions and 40 deletions

View file

@ -44,14 +44,17 @@ struct filedesc {
bool busy; bool busy;
bool write; bool write;
bool dirty; bool dirty;
bool trunc;
}; };
static struct filedesc openfiles[MAX_OPEN_FILES]; static struct filedesc openfiles[MAX_OPEN_FILES];
static int flush_cache(int fd);
int creat(const char *pathname, int mode) int creat(const char *pathname, int mode)
{ {
(void)mode; (void)mode;
return open(pathname, O_WRONLY); return open(pathname, O_WRONLY|O_CREAT);
} }
int open(const char* pathname, int flags) int open(const char* pathname, int flags)
@ -81,20 +84,16 @@ int open(const char* pathname, int flags)
return -2; return -2;
} }
switch ( flags ) { if (flags & O_RDONLY) {
case O_RDONLY: openfiles[fd].write = false;
openfiles[fd].write = false; }
break; else {
if (flags & (O_RDWR | O_WRONLY)) {
case O_RDWR:
case O_WRONLY:
openfiles[fd].write = true; openfiles[fd].write = true;
break;
default: if (flags & O_TRUNC)
DEBUGF("Only O_RDONLY and O_WRONLY is supported\n"); openfiles[fd].trunc = true;
errno = EROFS; }
return -3;
} }
openfiles[fd].busy = true; openfiles[fd].busy = true;
@ -130,7 +129,7 @@ int open(const char* pathname, int flags)
closedir(dir); closedir(dir);
if ( !entry ) { if ( !entry ) {
LDEBUGF("Didn't find file %s\n",name); LDEBUGF("Didn't find file %s\n",name);
if ( openfiles[fd].write ) { if ( openfiles[fd].write && (flags & O_CREAT) ) {
if (fat_create_file(name, if (fat_create_file(name,
&(openfiles[fd].fatfile), &(openfiles[fd].fatfile),
&(dir->fatdir)) < 0) { &(dir->fatdir)) < 0) {
@ -151,6 +150,12 @@ int open(const char* pathname, int flags)
openfiles[fd].cacheoffset = -1; openfiles[fd].cacheoffset = -1;
openfiles[fd].fileoffset = 0; openfiles[fd].fileoffset = 0;
if (openfiles[fd].write && (flags & O_APPEND)) {
if (lseek(fd,0,SEEK_END) < 0 )
return -7;
}
return fd; return fd;
} }
@ -169,18 +174,21 @@ int close(int fd)
return -2; return -2;
} }
if (openfiles[fd].write) { if (openfiles[fd].write) {
/* truncate? */
if (openfiles[fd].trunc) {
if (ftruncate(fd, openfiles[fd].fileoffset) < 0)
return -1;
}
/* flush sector cache */ /* flush sector cache */
if ( openfiles[fd].dirty ) { if ( openfiles[fd].dirty ) {
if ( fat_readwrite(&(openfiles[fd].fatfile), 1, if (flush_cache(fd) < 0)
&(openfiles[fd].cache),true) < 0 ) { return -2;
DEBUGF("Failed flushing cache\n");
errno = EIO;
rc = -1;
}
} }
/* tie up all loose ends */ /* tie up all loose ends */
fat_closewrite(&(openfiles[fd].fatfile), openfiles[fd].size); if (fat_closewrite(&(openfiles[fd].fatfile), openfiles[fd].size) < 0)
return -3;
} }
openfiles[fd].busy = false; openfiles[fd].busy = false;
return rc; return rc;
@ -239,6 +247,28 @@ int ftruncate(int fd, unsigned int size)
return 0; return 0;
} }
static int flush_cache(int fd)
{
int rc;
int sector = openfiles[fd].fileoffset / SECTOR_SIZE;
DEBUGF("Flushing dirty sector cache %x\n", sector);
/* seek back one sector to get file position right */
rc = fat_seek(&(openfiles[fd].fatfile), sector);
if ( rc < 0 )
return -1;
rc = fat_readwrite(&(openfiles[fd].fatfile), 1,
openfiles[fd].cache, true );
if ( rc < 0 )
return -2;
openfiles[fd].dirty = false;
return 0;
}
static int readwrite(int fd, void* buf, int count, bool write) static int readwrite(int fd, void* buf, int count, bool write)
{ {
int sectors; int sectors;
@ -296,24 +326,8 @@ static int readwrite(int fd, void* buf, int count, bool write)
/* if buffer has been modified, write it back to disk */ /* if buffer has been modified, write it back to disk */
if (count && openfiles[fd].dirty) { if (count && openfiles[fd].dirty) {
int rc; if (flush_cache(fd) < 0)
DEBUGF("Flushing dirty sector cache\n");
/* seek back one sector to get file position right */
rc = fat_seek(&(openfiles[fd].fatfile),
openfiles[fd].fileoffset / SECTOR_SIZE);
if ( rc < 0 ) {
errno = EIO;
return -3; return -3;
}
rc = fat_readwrite(&(openfiles[fd].fatfile), 1,
openfiles[fd].cache, true );
if ( rc < 0 ) {
errno = EIO;
return -4;
}
openfiles[fd].dirty = false;
} }
/* read whole sectors right into the supplied buffer */ /* read whole sectors right into the supplied buffer */
@ -454,7 +468,13 @@ int lseek(int fd, int offset, int whence)
if ( (newsector != oldsector) || if ( (newsector != oldsector) ||
((openfiles[fd].cacheoffset==-1) && sectoroffset) ) { ((openfiles[fd].cacheoffset==-1) && sectoroffset) ) {
if ( newsector != oldsector ) { if ( newsector != oldsector ) {
if (openfiles[fd].dirty) {
if (flush_cache(fd) < 0)
return -5;
}
rc = fat_seek(&(openfiles[fd].fatfile), newsector); rc = fat_seek(&(openfiles[fd].fatfile), newsector);
if ( rc < 0 ) { if ( rc < 0 ) {
errno = EIO; errno = EIO;
@ -466,7 +486,7 @@ int lseek(int fd, int offset, int whence)
&(openfiles[fd].cache),false); &(openfiles[fd].cache),false);
if ( rc < 0 ) { if ( rc < 0 ) {
errno = EIO; errno = EIO;
return -5; return -6;
} }
openfiles[fd].cacheoffset = sectoroffset; openfiles[fd].cacheoffset = sectoroffset;
} }

View file

@ -37,6 +37,9 @@
#define O_RDONLY 0 #define O_RDONLY 0
#define O_WRONLY 1 #define O_WRONLY 1
#define O_RDWR 2 #define O_RDWR 2
#define O_CREAT 3
#define O_APPEND 4
#define O_TRUNC 5
#endif #endif
#if defined(__MINGW32__) && defined(SIMULATOR) #if defined(__MINGW32__) && defined(SIMULATOR)