µGFX  2.9
version 2.9
gfile_fs_native.c
1 /*
2  * This file is subject to the terms of the GFX License. If a copy of
3  * the license was not distributed with this file, you can obtain one at:
4  *
5  * http://ugfx.io/license.html
6  */
7 
8 /********************************************************
9  * The native file-system
10  ********************************************************/
11 
12 // We need to include stdio.h below. Turn off GFILE_NEED_STDIO just for this file to prevent conflicts
13 #define GFILE_NEED_STDIO_MUST_BE_OFF
14 
15 #include "../../gfx.h"
16 
17 #if GFX_USE_GFILE && GFILE_NEED_NATIVEFS
18 
19 #include "gfile_fs.h"
20 
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 
25 static gBool NativeDel(const char *fname);
26 static gBool NativeExists(const char *fname);
27 static gFileSize NativeFilesize(const char *fname);
28 static gBool NativeRen(const char *oldname, const char *newname);
29 static gBool NativeOpen(GFILE *f, const char *fname);
30 static void NativeClose(GFILE *f);
31 static int NativeRead(GFILE *f, void *buf, int size);
32 static int NativeWrite(GFILE *f, const void *buf, int size);
33 static gBool NativeSetpos(GFILE *f, gFileSize pos);
34 static gFileSize NativeGetsize(GFILE *f);
35 static gBool NativeEof(GFILE *f);
36 #if GFILE_NEED_FILELISTS
37  static gfileList *NativeFlOpen(const char *path, gBool dirs);
38  static const char *NativeFlRead(gfileList *pfl);
39  static void NativeFlClose(gfileList *pfl);
40 #endif
41 
42 const GFILEVMT FsNativeVMT = {
43  #if defined(WIN32) || GFX_USE_OS_WIN32
44  GFSFLG_TEXTMODES|
45  #else
46  GFSFLG_CASESENSITIVE|
47  #endif
48  GFSFLG_WRITEABLE|GFSFLG_SEEKABLE|GFSFLG_FAST, // flags
49  'N', // prefix
50  NativeDel, NativeExists, NativeFilesize, NativeRen,
51  NativeOpen, NativeClose, NativeRead, NativeWrite,
52  NativeSetpos, NativeGetsize, NativeEof,
53  0, 0, 0,
54  #if GFILE_NEED_FILELISTS
55  NativeFlOpen, NativeFlRead, NativeFlClose
56  #endif
57 };
58 
59 void _gfileNativeAssignStdio(void) {
60  static GFILE NativeStdIn;
61  static GFILE NativeStdOut;
62  static GFILE NativeStdErr;
63 
64  NativeStdIn.flags = GFILEFLG_OPEN|GFILEFLG_READ;
65  NativeStdIn.vmt = &FsNativeVMT;
66  NativeStdIn.obj = (void *)stdin;
67  NativeStdIn.pos = 0;
68  gfileStdIn = &NativeStdIn;
69  NativeStdOut.flags = GFILEFLG_OPEN|GFILEFLG_WRITE|GFILEFLG_APPEND;
70  NativeStdOut.vmt = &FsNativeVMT;
71  NativeStdOut.obj = (void *)stdout;
72  NativeStdOut.pos = 0;
73  gfileStdOut = &NativeStdOut;
74  NativeStdErr.flags = GFILEFLG_OPEN|GFILEFLG_WRITE|GFILEFLG_APPEND;
75  NativeStdErr.vmt = &FsNativeVMT;
76  NativeStdErr.obj = (void *)stderr;
77  NativeStdErr.pos = 0;
78  gfileStdErr = &NativeStdErr;
79 }
80 
81 static void Native_flags2mode(char *buf, gU16 flags) {
82  if (flags & GFILEFLG_MUSTEXIST)
83  *buf = 'r';
84  else if (flags & GFILEFLG_APPEND)
85  *buf = 'a';
86  else
87  *buf = 'w';
88  buf++;
89  if ((flags & (GFILEFLG_READ|GFILEFLG_WRITE)) == (GFILEFLG_READ|GFILEFLG_WRITE))
90  *buf++ = '+';
91  if (flags & GFILEFLG_BINARY)
92  *buf++ = 'b';
93  if (flags & GFILEFLG_MUSTNOTEXIST)
94  *buf++ = 'x';
95  *buf++ = 0;
96 }
97 
98 static gBool NativeDel(const char *fname) { return remove(fname) ? gFalse : gTrue; }
99 static void NativeClose(GFILE *f) { fclose((FILE *)f->obj); }
100 static int NativeRead(GFILE *f, void *buf, int size) { return fread(buf, 1, size, (FILE *)f->obj); }
101 static int NativeWrite(GFILE *f, const void *buf, int size) { return fwrite(buf, 1, size, (FILE *)f->obj); }
102 static gBool NativeSetpos(GFILE *f, gFileSize pos) { return fseek((FILE *)f->obj, pos, SEEK_SET) ? gFalse : gTrue; }
103 static gBool NativeEof(GFILE *f) { return feof((FILE *)f->obj) ? gTrue : gFalse; }
104 static gBool NativeRen(const char *oldname, const char *newname) { return rename(oldname, newname) ? gFalse : gTrue; }
105 static gBool NativeExists(const char *fname) {
106  // We define access this way so we don't have to include <unistd.h> which may
107  // (and does under windows) contain conflicting definitions for types such as gU16.
108  extern int access(const char *pathname, int mode);
109  return access(fname, 0) ? gFalse : gTrue;
110 }
111 static gFileSize NativeFilesize(const char *fname) {
112  struct stat st;
113  if (stat(fname, &st)) return (gFileSize)-1;
114  return (gFileSize)st.st_size;
115 }
116 static gBool NativeOpen(GFILE *f, const char *fname) {
117  FILE *fd;
118  char mode[5];
119 
120  Native_flags2mode(mode, f->flags);
121  if (!(fd = fopen(fname, mode)))
122  return gFalse;
123  f->obj = (void *)fd;
124  return gTrue;
125 }
126 static gFileSize NativeGetsize(GFILE *f) {
127  struct stat st;
128  if (fstat(fileno((FILE *)f->obj), &st)) return (gFileSize)-1;
129  return (gFileSize)st.st_size;
130 }
131 
132 #if GFILE_NEED_FILELISTS
133  #if defined(WIN32) || GFX_USE_OS_WIN32
134  typedef struct NativeFileList {
135  gfileList fl;
136  HANDLE d;
137  WIN32_FIND_DATA f;
138  gBool first;
139  } NativeFileList;
140 
141  static gfileList *NativeFlOpen(const char *path, gBool dirs) {
142  NativeFileList *p;
143  (void) dirs;
144 
145  if (!(p = gfxAlloc(sizeof(NativeFileList))))
146  return 0;
147  if ((p->d = FindFirstFile(path, &p->f)) == INVALID_HANDLE_VALUE) {
148  gfxFree(p);
149  return 0;
150  }
151  p->first = gTrue;
152  return &p->fl;
153  }
154 
155  static const char *NativeFlRead(gfileList *pfl) {
156  #define nfl ((NativeFileList *)pfl)
157  while(1) {
158  if (!nfl->first && !FindNextFile(nfl->d, &nfl->f))
159  return 0;
160  nfl->first = gFalse;
161  if (nfl->f.cFileName[0] == '.')
162  continue;
163  if (nfl->fl.dirs) {
164  if ((nfl->f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
165  break;
166  } else {
167  if (!(nfl->f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
168  break;
169  }
170  }
171  return nfl->f.cFileName;
172  #undef nfl
173  }
174 
175  static void NativeFlClose(gfileList *pfl) {
176  CloseHandle(((NativeFileList *)pfl)->d);
177  gfxFree(pfl);
178  }
179 
180  #else
181  #include <dirent.h>
182 
183  typedef struct NativeFileList {
184  gfileList fl;
185  DIR * d;
186  struct dirent * f;
187  } NativeFileList;
188 
189  static gfileList *NativeFlOpen(const char *path, gBool dirs) {
190  NativeFileList *p;
191  (void) dirs;
192 
193  if (!(p = gfxAlloc(sizeof(NativeFileList))))
194  return 0;
195  if (!(p->d = opendir(path))) {
196  gfxFree(p);
197  return 0;
198  }
199  return &p->fl;
200  }
201 
202  static const char *NativeFlRead(gfileList *pfl) {
203  #define nfl ((NativeFileList *)pfl)
204  while(1) {
205  if (!(nfl->f = readdir(nfl->d)))
206  return 0;
207  if (nfl->f->d_name[0] == '.')
208  continue;
209 
210  #ifdef _DIRENT_HAVE_D_TYPE
211  if (nfl->fl.dirs) {
212  if (nfl->f->d_type == DT_DIR)
213  break;
214  } else {
215  if (nfl->f->d_type == DT_REG)
216  break;
217  }
218  #else
219  // Oops - no type field. We could use stat() here but that would mean
220  // concatting the supplied path to the found filename.
221  // That all just seems too hard. Instead we just don't
222  // distinguish between files and directories.
223  break;
224  #endif
225  }
226  return nfl->f->d_name;
227  #undef nfl
228  }
229 
230  static void NativeFlClose(gfileList *pfl) {
231  closedir(((NativeFileList *)pfl)->d);
232  gfxFree(pfl);
233  }
234  #endif
235 #endif
236 
237 #endif //GFX_USE_GFILE && GFILE_NEED_NATIVEFS
GFILE file system header.
struct GFILE GFILE
A file pointer.
Definition: gfile.h:34
void * gfxAlloc(gMemSize sz)
Allocate memory.
void gfxFree(void *ptr)
Free memory.