235 lines
6.5 KiB
C
235 lines
6.5 KiB
C
/*
|
|
* 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
|