1 
2 #pragma once
3 
4 #ifndef vfs_h_
5 #define vfs_h_
6 
7 #include "compat.h"
8 
9 #ifdef USE_PHYSFS
10 
11 #include "physfs.h"
12 
13 using buildvfs_FILE = PHYSFS_File *;
14 #define buildvfs_EOF (-1)
15 #define buildvfs_fread(p, s, n, fp) PHYSFS_readBytes((fp), (p), (s)*(n))
16 #define buildvfs_fwrite(p, s, n, fp) PHYSFS_writeBytes((fp), (p), (s)*(n))
17 #define buildvfs_fopen_read(fn) PHYSFS_openRead(fn)
18 #define buildvfs_fopen_write(fn) PHYSFS_openWrite(fn)
19 #define buildvfs_fopen_write_text(fn) PHYSFS_openWrite(fn)
20 #define buildvfs_fopen_append(fn) PHYSFS_openAppend(fn)
buildvfs_fgetc(buildvfs_FILE fp)21 static inline int buildvfs_fgetc(buildvfs_FILE fp)
22 {
23   unsigned char c;
24   return buildvfs_fread(&c, 1, 1, fp) != 1 ? buildvfs_EOF : c;
25 }
buildvfs_fputc(char c,buildvfs_FILE fp)26 static inline int buildvfs_fputc(char c, buildvfs_FILE fp)
27 {
28     return PHYSFS_writeBytes(fp, &c, 1) != 1 ? buildvfs_EOF : c;
29 }
30 #define buildvfs_fclose(fp) PHYSFS_close(fp)
31 #define buildvfs_feof(fp) PHYSFS_eof(fp)
32 #define buildvfs_ftell(fp) PHYSFS_tell(fp)
33 #define buildvfs_fseek_abs(fp, o) PHYSFS_seek((fp), (o))
34 #define buildvfs_fseek_rel(fp, o) PHYSFS_seek((fp), PHYSFS_tell(fp) + (o))
35 #define buildvfs_rewind(fp) PHYSFS_seek((fp), 0)
36 
37 #define buildvfs_flength(fp) PHYSFS_fileLength(fp)
38 
39 #define buildvfs_chdir(dir) (-1)
40 #define buildvfs_mkdir(dir, x) (!PHYSFS_mkdir(dir))
buildvfs_getcwd(char * buf,size_t size)41 static inline char *buildvfs_getcwd(char *buf, size_t size)
42 {
43     if (buf == nullptr || size == 0)
44         return nullptr;
45 
46     buf[0] = '\0';
47     return buf;
48 }
49 
50 using buildvfs_fd = PHYSFS_File *;
51 #define buildvfs_fd_invalid (nullptr)
52 #define buildvfs_read(fd, p, s) PHYSFS_readBytes((fd), (p), (s))
53 #define buildvfs_write(fd, p, s) PHYSFS_writeBytes((fd), (p), (s))
54 #define buildvfs_open_read(fn) PHYSFS_openRead(fn)
55 #define buildvfs_open_write(fn) PHYSFS_openWrite(fn)
56 #define buildvfs_open_append(fn) PHYSFS_openAppend(fn)
57 #define buildvfs_close(fd) PHYSFS_close(fd)
58 #define buildvfs_tell(fd) PHYSFS_tell(fd)
buildvfs_lseek_abs(buildvfs_fd fd,int64_t o)59 static inline int64_t buildvfs_lseek_abs(buildvfs_fd fd, int64_t o)
60 {
61     PHYSFS_seek(fd, o);
62     return PHYSFS_tell(fd);
63 }
buildvfs_lseek_rel(buildvfs_fd fd,int64_t o)64 static inline int64_t buildvfs_lseek_rel(buildvfs_fd fd, int64_t o)
65 {
66     PHYSFS_seek(fd, PHYSFS_tell(fd) + o);
67     return PHYSFS_tell(fd);
68 }
69 
70 #define buildvfs_length(fd) PHYSFS_fileLength(fd)
71 #define buildvfs_exists(fn) PHYSFS_exists(fn)
72 #define buildvfs_isdir(path) PHYSFS_isDirectory(path)
73 #define buildvfs_unlink(path) PHYSFS_delete(path)
74 
75 #else
76 
77 #include <stdio.h>
78 #include <fcntl.h>
79 #include <sys/stat.h>
80 #ifdef _WIN32
81 # include <io.h>
82 #endif
83 
84 using buildvfs_FILE = FILE *;
85 #define buildvfs_EOF EOF
86 #define buildvfs_fread(p, s, n, fp) fread((p), (s), (n), (fp))
87 #define buildvfs_fwrite(p, s, n, fp) fwrite((p), (s), (n), (fp))
88 #define buildvfs_fopen_read(fn) fopen((fn), "rb")
89 #define buildvfs_fopen_write(fn) fopen((fn), "wb")
90 #define buildvfs_fopen_write_text(fn) fopen((fn), "w")
91 #define buildvfs_fopen_append(fn) fopen((fn), "ab")
92 #define buildvfs_fgetc(fp) fgetc(fp)
93 #define buildvfs_fputc(c, fp) fputc((c), (fp))
94 #define buildvfs_fgets(str, size, fp) fgets((str), (size), (fp))
95 #define buildvfs_fclose(fp) fclose(fp)
96 #define buildvfs_feof(fp) feof(fp)
97 #define buildvfs_ftell(fp) ftell(fp)
98 #define buildvfs_fseek_abs(fp, o) fseek((fp), (o), SEEK_SET)
99 #define buildvfs_fseek_rel(fp, o) fseek((fp), (o), SEEK_CUR)
100 #define buildvfs_rewind(fp) rewind(fp)
101 
buildvfs_length(int fd)102 static inline int64_t buildvfs_length(int fd)
103 {
104 #ifdef _WIN32
105     return filelength(fd);
106 #else
107     struct stat st;
108     return fstat(fd, &st) < 0 ? -1 : st.st_size;
109 #endif
110 }
111 
112 #define buildvfs_chdir(dir) chdir(dir)
113 #define buildvfs_mkdir(dir, x) Bmkdir(dir, x)
114 #define buildvfs_getcwd(buf, size) getcwd((buf), (size))
115 
116 using buildvfs_fd = int;
117 #define buildvfs_fd_invalid (-1)
118 #define buildvfs_read(fd, p, s) read((fd), (p), (s))
119 #define buildvfs_write(fd, p, s) write((fd), (p), (s))
120 #define buildvfs_open_read(fn) open((fn), O_RDONLY|O_BINARY)
121 #define buildvfs_open_write(fn) open((fn), O_BINARY|O_TRUNC|O_CREAT|O_WRONLY, S_IREAD|S_IWRITE)
122 // #define buildvfs_open_append(fn) todo(fn)
123 #define buildvfs_close(fd) close(fd)
124 #define buildvfs_tell(fd) lseek((fd), 0, SEEK_CUR)
125 #define buildvfs_lseek_abs(fd, o) lseek((fd), (o), SEEK_SET)
126 #define buildvfs_lseek_rel(fd, o) lseek((fd), (o), SEEK_CUR)
127 
buildvfs_flength(FILE * f)128 static inline int64_t buildvfs_flength(FILE * f)
129 {
130 #ifdef _WIN32
131     return filelength(_fileno(f));
132 #else
133     return buildvfs_length(fileno(f));
134 #endif
135 }
136 #define buildvfs_exists(fn) (access((fn), F_OK) == 0)
buildvfs_isdir(char const * path)137 static inline int buildvfs_isdir(char const *path)
138 {
139     struct Bstat st;
140     return (Bstat(path, &st) ? 0 : (st.st_mode & S_IFDIR) == S_IFDIR);
141 }
142 #define buildvfs_unlink(path) unlink(path)
143 
144 #endif
145 
146 #define MAYBE_FCLOSE_AND_NULL(fileptr) do { \
147     if (fileptr) { buildvfs_fclose(fileptr); fileptr = buildvfs_FILE{}; } \
148 } while (0)
149 
buildvfs_fputstrptr(buildvfs_FILE fp,char const * str)150 static inline void buildvfs_fputstrptr(buildvfs_FILE fp, char const * str)
151 {
152     buildvfs_fwrite(str, 1, strlen(str), fp);
153 }
154 
buildvfs_fputs(char const * str,buildvfs_FILE fp)155 static inline void buildvfs_fputs(char const * str, buildvfs_FILE fp)
156 {
157     buildvfs_fwrite(str, 1, strlen(str), fp);
158 }
159 
160 template <size_t N>
buildvfs_fputstr(buildvfs_FILE fp,char const (& str)[N])161 static inline void buildvfs_fputstr(buildvfs_FILE fp, char const (&str)[N])
162 {
163     buildvfs_fwrite(&str, 1, N-1, fp);
164 }
165 
166 
167 #ifdef __cplusplus
168 extern "C" {
169 #endif
170 
171 extern char toupperlookup[256];
172 
173 extern char *kpzbuf;
174 extern int32_t kpzbufsiz;
175 extern int32_t kpzbufload(const char *);
176 
177 #ifdef USE_PHYSFS
178 using buildvfs_kfd = PHYSFS_File *;
179 #define buildvfs_kfd_invalid (nullptr)
180 
181 extern int32_t pathsearchmode;	// 0 = gamefs mode (default), 1 = localfs mode (editor's mode)
182 
183 #define addsearchpath(a) addsearchpath_user(a, 0)
addsearchpath_user(const char * p,int32_t)184 static inline int32_t addsearchpath_user(const char *p, int32_t)
185 {
186     return PHYSFS_mount(p, NULL, 1) == 0 ? -1 : 0;
187 }
188 
removesearchpath(const char * p)189 static inline int32_t removesearchpath(const char *p)
190 {
191     return PHYSFS_unmount(p);
192 }
removesearchpaths_withuser(int32_t)193 static inline void removesearchpaths_withuser(int32_t)
194 {
195     // TODO
196 }
197 
198 
199 int32_t findfrompath(const char *fn, char **where);
200 buildvfs_kfd openfrompath(const char *fn, int32_t flags, int32_t mode);
201 buildvfs_FILE fopenfrompath(const char *fn, const char *mode);
202 
203 
204 extern int32_t numgroupfiles;
205 void uninitgroupfile(void);
206 
207 
initgroupfile(const char * filename)208 static inline int initgroupfile(const char *filename)
209 {
210     return PHYSFS_mount(filename, NULL, 1) == 0 ? -1 : 0;
211 }
212 
213 
214 #define kread(fd, p, s) PHYSFS_readBytes((fd), (p), (s))
215 #define kwrite(fd, p, s) PHYSFS_writeBytes((fd), (p), (s))
216 #define kopen4load(fn, searchfirst) PHYSFS_openRead(fn)
217 #define ktell(fd) PHYSFS_tell(fd)
218 #define kfilelength(fd) PHYSFS_fileLength(fd)
219 
220 
kclose(buildvfs_kfd handle)221 static inline void kclose(buildvfs_kfd handle)
222 {
223     PHYSFS_close(handle);
224 }
225 
226 #define kread_and_test(handle, buffer, leng) EDUKE32_PREDICT_FALSE(kread((handle), (buffer), (leng)) != (leng))
227 extern int32_t klseek(buildvfs_kfd handle, int32_t offset, int32_t whence);
228 #define klseek_and_test(handle, offset, whence) EDUKE32_PREDICT_FALSE(klseek((handle), (offset), (whence)) < 0)
229 
krename(int32_t,int32_t,const char *)230 static inline void krename(int32_t, int32_t, const char *)
231 {
232 }
233 
234 #else
235 using buildvfs_kfd = int32_t;
236 #define buildvfs_kfd_invalid (-1)
237 
238 extern int32_t pathsearchmode;	// 0 = gamefs mode (default), 1 = localfs mode (editor's mode)
239 char *listsearchpath(int32_t initp);
240 int32_t     addsearchpath_user(const char *p, int32_t user);
241 #define addsearchpath(a) addsearchpath_user(a, 0)
242 int32_t     removesearchpath(const char *p);
243 void     removesearchpaths_withuser(int32_t usermask);
244 int32_t		findfrompath(const char *fn, char **where);
245 buildvfs_kfd     openfrompath(const char *fn, int32_t flags, int32_t mode);
246 buildvfs_FILE fopenfrompath(const char *fn, const char *mode);
247 
248 extern char g_modDir[BMAX_PATH];
249 extern int32_t numgroupfiles;
250 int initgroupfile(const char *filename);
251 void	uninitgroupfile(void);
252 buildvfs_kfd	kopen4load(const char *filename, char searchfirst);	// searchfirst: 0 = anywhere, 1 = first group, 2 = any group
253 buildvfs_kfd	kopen4loadfrommod(const char* filename, char searchfirst);
254 int32_t	kread(buildvfs_kfd handle, void *buffer, int32_t leng);
255 #define kread_and_test(handle, buffer, leng) EDUKE32_PREDICT_FALSE(kread((handle), (buffer), (leng)) != (int32_t)(leng))
256 int32_t	klseek(buildvfs_kfd handle, int32_t offset, int32_t whence);
257 #define klseek_and_test(handle, offset, whence) EDUKE32_PREDICT_FALSE(klseek((handle), (offset), (whence)) < 0)
258 int32_t	kfilelength(buildvfs_kfd handle);
259 int32_t	ktell(buildvfs_kfd handle);
260 void	kclose(buildvfs_kfd handle);
261 
262 void krename(int32_t crcval, int32_t filenum, const char *newname);
263 char const * kfileparent(int32_t handle);
264 #endif
265 
266 extern int32_t kpzbufloadfil(buildvfs_kfd);
267 
268 #ifdef WITHKPLIB
269 int32_t cache1d_file_fromzip(buildvfs_kfd fil);
270 #endif
271 
272 enum {
273     BUILDVFS_FIND_FILE     = 1,
274     BUILDVFS_FIND_DIR      = 2,
275     BUILDVFS_FIND_DRIVE    = 4,
276     BUILDVFS_FIND_NOCURDIR = 8,
277 
278     BUILDVFS_OPT_NOSTACK = 0x100,
279 
280     // the lower the number, the higher the priority
281     BUILDVFS_SOURCE_DRIVE  = 0,
282     BUILDVFS_SOURCE_CURDIR = 1,
283     BUILDVFS_SOURCE_PATH   = 2,  // + path stack depth
284     BUILDVFS_SOURCE_ZIP    = 0x7ffffffe,
285     BUILDVFS_SOURCE_GRP    = 0x7fffffff,
286 };
287 
288 typedef struct _BUILDVFS_FIND_REC {
289     char *name;
290     int32_t type, source;
291     struct _BUILDVFS_FIND_REC *next, *prev, *usera, *userb;
292 } BUILDVFS_FIND_REC;
293 int32_t klistaddentry(BUILDVFS_FIND_REC **rec, const char *name, int32_t type, int32_t source);
294 void klistfree(BUILDVFS_FIND_REC *rec);
295 BUILDVFS_FIND_REC *klistpath(const char *path, const char *mask, int type);
296 
297 extern int32_t lz4CompressionLevel;
298 int32_t     kdfread(void *buffer, int dasizeof, int count, buildvfs_kfd fil);
299 int32_t kdfread_LZ4(void *buffer, int dasizeof, int count, buildvfs_kfd fil);
300 void     dfwrite(const void *buffer, int dasizeof, int count, buildvfs_FILE fil);
301 void dfwrite_LZ4(const void *buffer, int dasizeof, int count, buildvfs_FILE fil);
302 
303 #ifdef __cplusplus
304 }
305 #endif
306 
307 #endif // vfs_h_
308