aboutsummaryrefslogtreecommitdiffstats
path: root/src/gfile/gfile_fs_native.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gfile/gfile_fs_native.c')
-rw-r--r--src/gfile/gfile_fs_native.c234
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