|
1 /* |
|
2 * Standard directory I/O support routines for PhysicsFS. |
|
3 * |
|
4 * Please see the file LICENSE.txt in the source's root directory. |
|
5 * |
|
6 * This file written by Ryan C. Gordon. |
|
7 */ |
|
8 |
|
9 #define __PHYSICSFS_INTERNAL__ |
|
10 #include "physfs_internal.h" |
|
11 |
|
12 /* There's no PHYSFS_Io interface here. Use __PHYSFS_createNativeIo(). */ |
|
13 |
|
14 |
|
15 |
|
16 static char *cvtToDependent(const char *prepend, const char *path, char *buf) |
|
17 { |
|
18 BAIL_IF_MACRO(buf == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
19 sprintf(buf, "%s%s", prepend ? prepend : "", path); |
|
20 |
|
21 if (__PHYSFS_platformDirSeparator != '/') |
|
22 { |
|
23 char *p; |
|
24 for (p = strchr(buf, '/'); p != NULL; p = strchr(p + 1, '/')) |
|
25 *p = __PHYSFS_platformDirSeparator; |
|
26 } /* if */ |
|
27 |
|
28 return buf; |
|
29 } /* cvtToDependent */ |
|
30 |
|
31 |
|
32 #define CVT_TO_DEPENDENT(buf, pre, dir) { \ |
|
33 const size_t len = ((pre) ? strlen((char *) pre) : 0) + strlen(dir) + 1; \ |
|
34 buf = cvtToDependent((char*)pre,dir,(char*)__PHYSFS_smallAlloc(len)); \ |
|
35 } |
|
36 |
|
37 |
|
38 |
|
39 static void *DIR_openArchive(PHYSFS_Io *io, const char *name, int forWriting) |
|
40 { |
|
41 PHYSFS_Stat st; |
|
42 const char dirsep = __PHYSFS_platformDirSeparator; |
|
43 char *retval = NULL; |
|
44 const size_t namelen = strlen(name); |
|
45 const size_t seplen = 1; |
|
46 int exists = 0; |
|
47 |
|
48 assert(io == NULL); /* shouldn't create an Io for these. */ |
|
49 BAIL_IF_MACRO(!__PHYSFS_platformStat(name, &exists, &st), ERRPASS, NULL); |
|
50 if (st.filetype != PHYSFS_FILETYPE_DIRECTORY) |
|
51 BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL); |
|
52 |
|
53 retval = allocator.Malloc(namelen + seplen + 1); |
|
54 BAIL_IF_MACRO(retval == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
55 |
|
56 strcpy(retval, name); |
|
57 |
|
58 /* make sure there's a dir separator at the end of the string */ |
|
59 if (retval[namelen - 1] != dirsep) |
|
60 { |
|
61 retval[namelen] = dirsep; |
|
62 retval[namelen + 1] = '\0'; |
|
63 } /* if */ |
|
64 |
|
65 return retval; |
|
66 } /* DIR_openArchive */ |
|
67 |
|
68 |
|
69 static void DIR_enumerateFiles(PHYSFS_Dir *opaque, const char *dname, |
|
70 int omitSymLinks, PHYSFS_EnumFilesCallback cb, |
|
71 const char *origdir, void *callbackdata) |
|
72 { |
|
73 char *d; |
|
74 |
|
75 CVT_TO_DEPENDENT(d, opaque, dname); |
|
76 if (d != NULL) |
|
77 { |
|
78 __PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb, |
|
79 origdir, callbackdata); |
|
80 __PHYSFS_smallFree(d); |
|
81 } /* if */ |
|
82 } /* DIR_enumerateFiles */ |
|
83 |
|
84 |
|
85 static PHYSFS_Io *doOpen(PHYSFS_Dir *opaque, const char *name, |
|
86 const int mode, int *fileExists) |
|
87 { |
|
88 char *f; |
|
89 PHYSFS_Io *io = NULL; |
|
90 int existtmp = 0; |
|
91 |
|
92 CVT_TO_DEPENDENT(f, opaque, name); |
|
93 BAIL_IF_MACRO(!f, ERRPASS, NULL); |
|
94 |
|
95 if (fileExists == NULL) |
|
96 fileExists = &existtmp; |
|
97 |
|
98 io = __PHYSFS_createNativeIo(f, mode); |
|
99 if (io == NULL) |
|
100 { |
|
101 const PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode(); |
|
102 PHYSFS_Stat statbuf; |
|
103 __PHYSFS_platformStat(f, fileExists, &statbuf); |
|
104 __PHYSFS_setError(err); |
|
105 } /* if */ |
|
106 else |
|
107 { |
|
108 *fileExists = 1; |
|
109 } /* else */ |
|
110 |
|
111 __PHYSFS_smallFree(f); |
|
112 |
|
113 return io; |
|
114 } /* doOpen */ |
|
115 |
|
116 |
|
117 static PHYSFS_Io *DIR_openRead(PHYSFS_Dir *opaque, const char *fnm, int *exist) |
|
118 { |
|
119 return doOpen(opaque, fnm, 'r', exist); |
|
120 } /* DIR_openRead */ |
|
121 |
|
122 |
|
123 static PHYSFS_Io *DIR_openWrite(PHYSFS_Dir *opaque, const char *filename) |
|
124 { |
|
125 return doOpen(opaque, filename, 'w', NULL); |
|
126 } /* DIR_openWrite */ |
|
127 |
|
128 |
|
129 static PHYSFS_Io *DIR_openAppend(PHYSFS_Dir *opaque, const char *filename) |
|
130 { |
|
131 return doOpen(opaque, filename, 'a', NULL); |
|
132 } /* DIR_openAppend */ |
|
133 |
|
134 |
|
135 static int DIR_remove(PHYSFS_Dir *opaque, const char *name) |
|
136 { |
|
137 int retval; |
|
138 char *f; |
|
139 |
|
140 CVT_TO_DEPENDENT(f, opaque, name); |
|
141 BAIL_IF_MACRO(!f, ERRPASS, 0); |
|
142 retval = __PHYSFS_platformDelete(f); |
|
143 __PHYSFS_smallFree(f); |
|
144 return retval; |
|
145 } /* DIR_remove */ |
|
146 |
|
147 |
|
148 static int DIR_mkdir(PHYSFS_Dir *opaque, const char *name) |
|
149 { |
|
150 int retval; |
|
151 char *f; |
|
152 |
|
153 CVT_TO_DEPENDENT(f, opaque, name); |
|
154 BAIL_IF_MACRO(!f, ERRPASS, 0); |
|
155 retval = __PHYSFS_platformMkDir(f); |
|
156 __PHYSFS_smallFree(f); |
|
157 return retval; |
|
158 } /* DIR_mkdir */ |
|
159 |
|
160 |
|
161 static void DIR_closeArchive(PHYSFS_Dir *opaque) |
|
162 { |
|
163 allocator.Free(opaque); |
|
164 } /* DIR_closeArchive */ |
|
165 |
|
166 |
|
167 static int DIR_stat(PHYSFS_Dir *opaque, const char *name, |
|
168 int *exists, PHYSFS_Stat *stat) |
|
169 { |
|
170 int retval = 0; |
|
171 char *d; |
|
172 |
|
173 CVT_TO_DEPENDENT(d, opaque, name); |
|
174 BAIL_IF_MACRO(!d, ERRPASS, 0); |
|
175 retval = __PHYSFS_platformStat(d, exists, stat); |
|
176 __PHYSFS_smallFree(d); |
|
177 return retval; |
|
178 } /* DIR_stat */ |
|
179 |
|
180 |
|
181 const PHYSFS_Archiver __PHYSFS_Archiver_DIR = |
|
182 { |
|
183 { |
|
184 "", |
|
185 "Non-archive, direct filesystem I/O", |
|
186 "Ryan C. Gordon <icculus@icculus.org>", |
|
187 "http://icculus.org/physfs/", |
|
188 }, |
|
189 DIR_openArchive, /* openArchive() method */ |
|
190 DIR_enumerateFiles, /* enumerateFiles() method */ |
|
191 DIR_openRead, /* openRead() method */ |
|
192 DIR_openWrite, /* openWrite() method */ |
|
193 DIR_openAppend, /* openAppend() method */ |
|
194 DIR_remove, /* remove() method */ |
|
195 DIR_mkdir, /* mkdir() method */ |
|
196 DIR_closeArchive, /* closeArchive() method */ |
|
197 DIR_stat /* stat() method */ |
|
198 }; |
|
199 |
|
200 /* end of dir.c ... */ |
|
201 |