3a475ecc48fd520997f8491a4ad53dad5e6a3e06
[btb/d2x.git] / include / physfsx.h
1 /* $Id: physfsx.h,v 1.9 2005-02-25 04:25:58 chris Exp $ */
2
3 /*
4  *
5  * Some simple physfs extensions
6  *
7  */
8
9 #ifndef PHYSFSX_H
10 #define PHYSFSX_H
11
12 #if !defined(macintosh) && !defined(_MSC_VER)
13 #include <sys/param.h>
14 #endif
15 #if defined(__linux__)
16 #include <sys/vfs.h>
17 #elif defined(__MACH__) && defined(__APPLE__)
18 #include <sys/mount.h>
19 #endif
20 #include <string.h>
21
22 #include <physfs.h>
23
24 #include "pstypes.h"
25 #include "error.h"
26
27 static inline int PHYSFSX_readString(PHYSFS_file *file, char *s)
28 {
29         char *ptr = s;
30
31         if (PHYSFS_eof(file))
32                 *ptr = 0;
33         else
34                 do
35                         PHYSFS_read(file, ptr, 1, 1);
36                 while (!PHYSFS_eof(file) && *ptr++ != 0);
37
38         return strlen(s);
39 }
40
41 static inline int PHYSFSX_gets(PHYSFS_file *file, char *s)
42 {
43         char *ptr = s;
44
45         if (PHYSFS_eof(file))
46                 *ptr = 0;
47         else
48                 do
49                         PHYSFS_read(file, ptr, 1, 1);
50                 while (!PHYSFS_eof(file) && *ptr++ != '\n');
51
52         return strlen(s);
53 }
54
55 static inline int PHYSFSX_writeU8(PHYSFS_file *file, PHYSFS_uint8 val)
56 {
57         return PHYSFS_write(file, &val, 1, 1);
58 }
59
60 static inline int PHYSFSX_writeString(PHYSFS_file *file, char *s)
61 {
62         return PHYSFS_write(file, s, 1, strlen(s) + 1);
63 }
64
65 static inline int PHYSFSX_puts(PHYSFS_file *file, char *s)
66 {
67         return PHYSFS_write(file, s, 1, strlen(s));
68 }
69
70 static inline int PHYSFSX_putc(PHYSFS_file *file, int c)
71 {
72         unsigned char ch = (unsigned char)c;
73
74         if (PHYSFS_write(file, &ch, 1, 1) < 1)
75                 return -1;
76         else
77                 return (int)c;
78 }
79
80 static inline int PHYSFSX_getRealPath(const char *stdPath, char *realPath)
81 {
82         const char *realDir = PHYSFS_getRealDir(stdPath);
83         const char *sep = PHYSFS_getDirSeparator();
84         char *p;
85
86         if (!realDir)
87         {
88                 realDir = PHYSFS_getWriteDir();
89                 if (!realDir)
90                         return 0;
91         }
92
93         strncpy(realPath, realDir, PATH_MAX - 1);
94         if (strlen(realPath) >= strlen(sep))
95         {
96                 p = realPath + strlen(realPath) - strlen(sep);
97                 if (strcmp(p, sep)) // no sep at end of realPath
98                         strncat(realPath, sep, PATH_MAX - 1 - strlen(realPath));
99         }
100
101         if (strlen(stdPath) >= 1)
102                 if (*stdPath == '/')
103                         stdPath++;
104
105         while (*stdPath)
106         {
107                 if (*stdPath == '/')
108                         strncat(realPath, sep, PATH_MAX - 1 - strlen(realPath));
109                 else
110                 {
111                         if (strlen(realPath) < PATH_MAX - 2)
112                         {
113                                 p = realPath + strlen(realPath);
114                                 p[0] = *stdPath;
115                                 p[1] = '\0';
116                         }
117                 }
118                 stdPath++;
119         }
120
121         return 1;
122 }
123
124 static inline int PHYSFSX_rename(char *oldpath, char *newpath)
125 {
126         char old[PATH_MAX], new[PATH_MAX];
127
128         PHYSFSX_getRealPath(oldpath, old);
129         PHYSFSX_getRealPath(newpath, new);
130         return (rename(old, new) == 0);
131 }
132
133
134 // returns -1 if error
135 // Gets bytes free in current write dir
136 static inline PHYSFS_sint64 PHYSFSX_getFreeDiskSpace()
137 {
138 #if defined(__linux__) || (defined(__MACH__) && defined(__APPLE__))
139         struct statfs sfs;
140
141         if (!statfs(PHYSFS_getWriteDir(), &sfs))
142                 return (PHYSFS_sint64)(sfs.f_bavail * sfs.f_bsize);
143
144         return -1;
145 #else
146         return 0x7FFFFFFF;
147 #endif
148 }
149
150 //Open a file for reading, set up a buffer
151 static inline PHYSFS_file *PHYSFSX_openReadBuffered(char *filename)
152 {
153         PHYSFS_file *fp;
154         PHYSFS_uint64 bufSize;
155
156         if (filename[0] == '\x01')
157         {
158                 //FIXME: don't look in dir, only in hogfile
159                 filename++;
160         }
161
162         fp = PHYSFS_openRead(filename);
163         if (!fp)
164                 return NULL;
165
166         bufSize = PHYSFS_fileLength(fp);
167         while (!PHYSFS_setBuffer(fp, bufSize) && bufSize)
168                 bufSize /= 2;   // even if the error isn't memory full, for a 20MB file it'll only do this 8 times
169
170         return fp;
171 }
172
173 //Open a file for writing, set up a buffer
174 static inline PHYSFS_file *PHYSFSX_openWriteBuffered(char *filename)
175 {
176         PHYSFS_file *fp;
177         PHYSFS_uint64 bufSize = 1024*1024;      // hmm, seems like an OK size.
178
179         fp = PHYSFS_openWrite(filename);
180         if (!fp)
181                 return NULL;
182
183         while (!PHYSFS_setBuffer(fp, bufSize) && bufSize)
184                 bufSize /= 2;
185
186         return fp;
187 }
188
189 #endif /* PHYSFSX_H */