diff options
Diffstat (limited to 'src/gfile/gfile_fs_native.c')
-rw-r--r-- | src/gfile/gfile_fs_native.c | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/src/gfile/gfile_fs_native.c b/src/gfile/gfile_fs_native.c new file mode 100644 index 00000000..6a9fce94 --- /dev/null +++ b/src/gfile/gfile_fs_native.c @@ -0,0 +1,234 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/******************************************************** + * The native file-system + ********************************************************/ + +#include "gfx.h" + +#if GFX_USE_GFILE && GFILE_NEED_NATIVEFS + +#include "gfile_fs.h" + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +static bool_t NativeDel(const char *fname); +static bool_t NativeExists(const char *fname); +static long int NativeFilesize(const char *fname); +static bool_t NativeRen(const char *oldname, const char *newname); +static bool_t NativeOpen(GFILE *f, const char *fname); +static void NativeClose(GFILE *f); +static int NativeRead(GFILE *f, void *buf, int size); +static int NativeWrite(GFILE *f, const void *buf, int size); +static bool_t NativeSetpos(GFILE *f, long int pos); +static long int NativeGetsize(GFILE *f); +static bool_t NativeEof(GFILE *f); +#if GFILE_NEED_FILELISTS + static gfileList *NativeFlOpen(const char *path, bool_t dirs); + static const char *NativeFlRead(gfileList *pfl); + static void NativeFlClose(gfileList *pfl); +#endif + +const GFILEVMT FsNativeVMT = { + #if defined(WIN32) || GFX_USE_OS_WIN32 + GFSFLG_TEXTMODES| + #else + GFSFLG_CASESENSITIVE| + #endif + GFSFLG_WRITEABLE|GFSFLG_SEEKABLE|GFSFLG_FAST, // flags + 'N', // prefix + NativeDel, NativeExists, NativeFilesize, NativeRen, + NativeOpen, NativeClose, NativeRead, NativeWrite, + NativeSetpos, NativeGetsize, NativeEof, + 0, 0, 0, + #if GFILE_NEED_FILELISTS + NativeFlOpen, NativeFlRead, NativeFlClose + #endif +}; + +void _gfileNativeAssignStdio(void) { + static GFILE NativeStdIn; + static GFILE NativeStdOut; + static GFILE NativeStdErr; + + NativeStdIn.flags = GFILEFLG_OPEN|GFILEFLG_READ; + NativeStdIn.vmt = &FsNativeVMT; + NativeStdIn.obj = (void *)stdin; + NativeStdIn.pos = 0; + gfileStdIn = &NativeStdIn; + NativeStdOut.flags = GFILEFLG_OPEN|GFILEFLG_WRITE|GFILEFLG_APPEND; + NativeStdOut.vmt = &FsNativeVMT; + NativeStdOut.obj = (void *)stdout; + NativeStdOut.pos = 0; + gfileStdOut = &NativeStdOut; + NativeStdErr.flags = GFILEFLG_OPEN|GFILEFLG_WRITE|GFILEFLG_APPEND; + NativeStdErr.vmt = &FsNativeVMT; + NativeStdErr.obj = (void *)stderr; + NativeStdErr.pos = 0; + gfileStdErr = &NativeStdErr; +} + +static void Native_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 void NativeClose(GFILE *f) { fclose((FILE *)f->obj); } +static int NativeRead(GFILE *f, void *buf, int size) { return fread(buf, 1, size, (FILE *)f->obj); } +static int NativeWrite(GFILE *f, const void *buf, int size) { return fwrite(buf, 1, size, (FILE *)f->obj); } +static bool_t NativeSetpos(GFILE *f, long int pos) { return fseek((FILE *)f->obj, pos, SEEK_SET) ? FALSE : TRUE; } +static bool_t NativeEof(GFILE *f) { return feof((FILE *)f->obj) ? TRUE : FALSE; } +static bool_t NativeRen(const char *oldname, const char *newname) { return rename(oldname, newname) ? FALSE : TRUE; } +static bool_t NativeExists(const char *fname) { + // We define access this way so we don't have to include <unistd.h> which may + // (and does under windows) contain conflicting definitions for types such as uint16_t. + extern int access(const char *pathname, int mode); + return access(fname, 0) ? FALSE : TRUE; +} +static long int NativeFilesize(const char *fname) { + struct stat st; + if (stat(fname, &st)) return -1; + return st.st_size; +} +static bool_t NativeOpen(GFILE *f, const char *fname) { + FILE *fd; + char mode[5]; + + Native_flags2mode(mode, f->flags); + if (!(fd = fopen(fname, mode))) + return FALSE; + f->obj = (void *)fd; + return TRUE; +} +static long int NativeGetsize(GFILE *f) { + struct stat st; + if (fstat(fileno((FILE *)f->obj), &st)) return -1; + return st.st_size; +} + +#if GFILE_NEED_FILELISTS + #if defined(WIN32) || GFX_USE_OS_WIN32 + typedef struct NativeFileList { + gfileList fl; + HANDLE d; + WIN32_FIND_DATA f; + bool_t first; + } NativeFileList; + + static gfileList *NativeFlOpen(const char *path, bool_t dirs) { + NativeFileList *p; + (void) dirs; + + if (!(p = gfxAlloc(sizeof(NativeFileList)))) + return 0; + if ((p->d = FindFirstFile(path, &p->f)) == INVALID_HANDLE_VALUE) { + gfxFree(p); + return 0; + } + p->first = TRUE; + return &p->fl; + } + + static const char *NativeFlRead(gfileList *pfl) { + #define nfl ((NativeFileList *)pfl) + while(1) { + if (!nfl->first && !FindNextFile(nfl->d, &nfl->f)) + return 0; + nfl->first = FALSE; + if (nfl->f.cFileName[0] == '.') + continue; + if (nfl->fl.dirs) { + if ((nfl->f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + break; + } else { + if (!(nfl->f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + break; + } + } + return nfl->f.cFileName; + #undef nfl + } + + static void NativeFlClose(gfileList *pfl) { + CloseHandle(((NativeFileList *)pfl)->d); + gfxFree(pfl); + } + + #else + #include <dirent.h> + + typedef struct NativeFileList { + gfileList fl; + DIR * d; + struct dirent * f; + } NativeFileList; + + static gfileList *NativeFlOpen(const char *path, bool_t dirs) { + NativeFileList *p; + (void) dirs; + + if (!(p = gfxAlloc(sizeof(NativeFileList)))) + return 0; + if (!(p->d = opendir(path))) { + gfxFree(p); + return 0; + } + return &p->fl; + } + + static const char *NativeFlRead(gfileList *pfl) { + #define nfl ((NativeFileList *)pfl) + while(1) { + if (!(nfl->f = readdir(nfl->d))) + return 0; + if (nfl->f->d_name[0] == '.') + continue; + + #ifdef _DIRENT_HAVE_D_TYPE + if (nfl->fl.dirs) { + if (nfl->f->d_type == DT_DIR) + break; + } else { + if (nfl->f->d_type == DT_REG) + break; + } + #else + // Oops - no type field. We could use stat() here but that would mean + // concatting the supplied path to the found filename. + // That all just seems too hard. Instead we just don't + // distinguish between files and directories. + break; + #endif + } + return nfl->f->d_name; + #undef nfl + } + + static void NativeFlClose(gfileList *pfl) { + closedir(((NativeFileList *)pfl)->d); + gfxFree(pfl); + } + #endif +#endif + +#endif //GFX_USE_GFILE && GFILE_NEED_NATIVEFS |