From c5ab2adbf0c14a6d0d4e2245a616d01de4b88214 Mon Sep 17 00:00:00 2001 From: inmarket Date: Fri, 24 Jan 2014 19:33:28 +1000 Subject: More code for GFile --- src/gfile/gfile.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++-- src/gfile/inc_nativefs.c | 23 ++++++++++-- src/gfile/inc_romfs.c | 14 ++------ 3 files changed, 113 insertions(+), 17 deletions(-) (limited to 'src/gfile') diff --git a/src/gfile/gfile.c b/src/gfile/gfile.c index bf76e8bc..83e487a1 100644 --- a/src/gfile/gfile.c +++ b/src/gfile/gfile.c @@ -147,7 +147,7 @@ long int gfileGetFilesize(const char *fname) { bool_t gfileRename(const char *oldname, const char *newname) { const GFILEVMT *p; - if ((oldname[0] && oldname[1] == '|') || (newname[0] && newname[1])) { + if ((oldname[0] && oldname[1] == '|') || (newname[0] && newname[1] == '|')) { char ch; if (oldname[0] && oldname[1] == '|') { @@ -155,6 +155,7 @@ bool_t gfileRename(const char *oldname, const char *newname) { oldname += 2; if (newname[0] && newname[1] == '|') { if (newname[0] != ch) + // Both oldname and newname are fs specific but different ones. return FALSE; newname += 2; } @@ -175,12 +176,100 @@ bool_t gfileRename(const char *oldname, const char *newname) { return FALSE; } +static uint16_t mode2flags(const char *mode) { + uint16_t flags; + + switch(mode[0]) { + case 'r': + flags = GFILEFLG_READ|GFILEFLG_MUSTEXIST; + while (*++mode) { + switch(mode[0]) { + case '+': flags |= GFILEFLG_WRITE; break; + case 'b': flags |= GFILEFLG_BINARY; break; + } + } + return flags; + case 'w': + flags = GFILEFLG_WRITE|GFILEFLG_TRUNC; + while (*++mode) { + switch(mode[0]) { + case '+': flags |= GFILEFLG_READ; break; + case 'b': flags |= GFILEFLG_BINARY; break; + case 'x': flags |= GFILEFLG_MUSTNOTEXIST; break; + } + } + return flags; + case 'a': + flags = GFILEFLG_WRITE|GFILEFLG_APPEND; + while (*++mode) { + switch(mode[0]) { + case '+': flags |= GFILEFLG_READ; break; + case 'b': flags |= GFILEFLG_BINARY; break; + case 'x': flags |= GFILEFLG_MUSTNOTEXIST; break; + } + } + return flags; + } + return 0; +} + +static bool_t testopen(const GFILEVMT *p, GFILE *f, const char *fname) { + // If we want write but the fs doesn't allow it then return + if ((f->flags & GFILEFLG_WRITE) && !(p->flags & GFSFLG_WRITEABLE)) + return FALSE; + + // Try to open + if (!p->open || !p->open(f, fname)) + return FALSE; + + // File is open - fill in all the details + f->vmt = p; + f->err = 0; + f->pos = 0; + f->flags |= GFILEFLG_OPEN; + if (p->flags & GFSFLG_SEEKABLE) + f->flags |= GFILEFLG_CANSEEK; + return TRUE; +} + GFILE *gfileOpen(const char *fname, const char *mode) { + GFILE *f; + const GFILEVMT *p; + + // First find an available GFILE slot. + for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) { + if (!(f->flags & GFILEFLG_OPEN)) { + + // Get the requested mode + if (!(f->flags = mode2flags(mode))) + return FALSE; + + // Try to open the file + if (fname[0] && fname[1] == '|') { + for(p = FsChain; p; p = p->next) { + if (p->prefix == fname[0]) + return testopen(p, f, fname+2); + } + } else { + for(p = FsChain; p; p = p->next) { + if (testopen(p, f, fname)) + return TRUE; + } + } + // File not found + return FALSE; + } + } + + // No available slot + return FALSE; } void gfileClose(GFILE *f) { - + // Make sure it is one of the system GFILE's + if (f < gfileArr || f >= &gfileArr[GFILE_MAX_GFILES]) + return; } size_t gfileRead(GFILE *f, char *buf, size_t len) { diff --git a/src/gfile/inc_nativefs.c b/src/gfile/inc_nativefs.c index 7828ff84..ccf1d40a 100644 --- a/src/gfile/inc_nativefs.c +++ b/src/gfile/inc_nativefs.c @@ -36,11 +36,11 @@ static bool_t NativeEof(GFILE *f); static const GFILEVMT FsNativeVMT = { GFILE_CHAINHEAD, // next - 'N', // prefix #if !defined(WIN32) && !GFX_USE_OS_WIN32 GFSFLG_CASESENSITIVE| #endif GFSFLG_WRITEABLE|GFSFLG_SEEKABLE|GFSFLG_FAST, // flags + 'N', // prefix NativeDel, NativeExists, NativeFilesize, NativeRen, NativeOpen, NativeClose, NativeRead, NativeWrite, NativeSetpos, NativeGetsize, NativeEof, @@ -48,6 +48,23 @@ static const GFILEVMT FsNativeVMT = { #undef GFILE_CHAINHEAD #define GFILE_CHAINHEAD &FsNativeVMT +static char *flags2mode(char *buf, uint16_t flags) { + if (flags & GFILEFLG_MUSTEXIST) + *buf = 'r'; + else if (flags & GFILEFLG_APPEND) + *buf = 'a'; + else + *buf = 'w'; + buf++; + if ((flags & (GFILEFLG_READ|GFILEFLG_WRITE)) == (GFILEFLG_READ|GFILEFLG_WRITE)) + *buf++ = '+'; + if (flags & GFILEFLG_BINARY) + *buf++ = 'b'; + if (flags & GFILEFLG_MUSTNOTEXIST) + *buf++ = 'x'; + *buf++ = 0; +} + static bool_t NativeDel(const char *fname) { return remove(fname) ? FALSE : TRUE; } static bool_t NativeExists(const char *fname) { return access(fname, 0) ? FALSE : TRUE; } static long int NativeFilesize(const char *fname) { @@ -56,12 +73,12 @@ static long int NativeFilesize(const char *fname) { return st.st_size; } static bool_t NativeRen(const char *oldname, const char *newname) { return rename(oldname, newname) ? FALSE : TRUE }; -static bool_t NativeOpen(GFILE *f, const char *fname, const char *mode) { +static bool_t NativeOpen(GFILE *f, const char *fname) { FILE *fd; + char mode[5]; if (!(fd = fopen(fname, mode))) return FALSE; - f->vmt = &FsNativeVMT; f->obj = (void *)fd; return TRUE; } diff --git a/src/gfile/inc_romfs.c b/src/gfile/inc_romfs.c index 321dc9b1..170b9a6c 100644 --- a/src/gfile/inc_romfs.c +++ b/src/gfile/inc_romfs.c @@ -39,8 +39,8 @@ static bool_t ROMEof(GFILE *f); static const GFILEVMT FsROMVMT = { GFILE_CHAINHEAD, // next - 'S', // prefix GFSFLG_CASESENSITIVE|GFSFLG_SEEKABLE|GFSFLG_FAST, // flags + 'S', // prefix 0, ROMExists, ROMFilesize, 0, ROMOpen, ROMClose, ROMRead, 0, ROMSetpos, ROMGetsize, ROMEof, @@ -64,20 +64,10 @@ static long int ROMFilesize(const char *fname) { if (!(p = ROMFindFile(fname))) return -1; return p->size; } -static bool_t ROMOpen(GFILE *f, const char *fname, const char *mode) { +static bool_t ROMOpen(GFILE *f, const char *fname) { const ROMFS_DIRENTRY *p; - // Check mode - if (mode[0] != 'r') return FALSE; - while(*++mode) { - switch(*mode) { - case '+': case 'w': case 'a': - return FALSE; - } - } - if (!(p = ROMFindFile(fname))) return FALSE; - f->vmt = &FsROMVMT; f->obj = (void *)p; return TRUE; } -- cgit v1.2.3