author | nemo |
Mon, 10 Apr 2017 12:06:43 -0400 | |
changeset 12213 | bb5522e88ab2 |
parent 10017 | de822cd3df3a |
permissions | -rw-r--r-- |
7768 | 1 |
/* |
2 |
* Mac OS X 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_platforms.h" |
|
11 |
||
12 |
#ifdef PHYSFS_PLATFORM_MACOSX |
|
13 |
||
14 |
#include <CoreFoundation/CoreFoundation.h> |
|
15 |
||
16 |
#if !defined(PHYSFS_NO_CDROM_SUPPORT) |
|
17 |
#include <Carbon/Carbon.h> /* !!! FIXME */ |
|
18 |
#include <IOKit/storage/IOMedia.h> |
|
19 |
#include <IOKit/storage/IOCDMedia.h> |
|
20 |
#include <IOKit/storage/IODVDMedia.h> |
|
21 |
#include <sys/mount.h> |
|
22 |
#endif |
|
23 |
||
24 |
/* Seems to get defined in some system header... */ |
|
25 |
#ifdef Free |
|
26 |
#undef Free |
|
27 |
#endif |
|
28 |
||
29 |
#include "physfs_internal.h" |
|
30 |
||
31 |
||
32 |
/* Wrap PHYSFS_Allocator in a CFAllocator... */ |
|
33 |
static CFAllocatorRef cfallocator = NULL; |
|
34 |
||
12213
bb5522e88ab2
bulk copy of latest physfs to our misc/libphysfs since this seems to fix an off-by-1 error reliably hit in readln read of 1 byte probably introduced in the addition of the buffered read. Whether this is excessive or whether libphysfs should even be maintained by us is another matter. But at least we shouldn't crash
nemo
parents:
10017
diff
changeset
|
35 |
static CFStringRef cfallocCopyDesc(const void *info) |
7768 | 36 |
{ |
37 |
return CFStringCreateWithCString(cfallocator, "PhysicsFS", |
|
38 |
kCFStringEncodingASCII); |
|
12213
bb5522e88ab2
bulk copy of latest physfs to our misc/libphysfs since this seems to fix an off-by-1 error reliably hit in readln read of 1 byte probably introduced in the addition of the buffered read. Whether this is excessive or whether libphysfs should even be maintained by us is another matter. But at least we shouldn't crash
nemo
parents:
10017
diff
changeset
|
39 |
} /* cfallocCopyDesc */ |
7768 | 40 |
|
41 |
||
42 |
static void *cfallocMalloc(CFIndex allocSize, CFOptionFlags hint, void *info) |
|
43 |
{ |
|
44 |
return allocator.Malloc(allocSize); |
|
45 |
} /* cfallocMalloc */ |
|
46 |
||
47 |
||
48 |
static void cfallocFree(void *ptr, void *info) |
|
49 |
{ |
|
50 |
allocator.Free(ptr); |
|
51 |
} /* cfallocFree */ |
|
52 |
||
53 |
||
54 |
static void *cfallocRealloc(void *ptr, CFIndex newsize, |
|
55 |
CFOptionFlags hint, void *info) |
|
56 |
{ |
|
57 |
if ((ptr == NULL) || (newsize <= 0)) |
|
58 |
return NULL; /* ADC docs say you should always return NULL here. */ |
|
59 |
return allocator.Realloc(ptr, newsize); |
|
60 |
} /* cfallocRealloc */ |
|
61 |
||
62 |
||
63 |
int __PHYSFS_platformInit(void) |
|
64 |
{ |
|
65 |
/* set up a CFAllocator, so Carbon can use the physfs allocator, too. */ |
|
66 |
CFAllocatorContext ctx; |
|
67 |
memset(&ctx, '\0', sizeof (ctx)); |
|
12213
bb5522e88ab2
bulk copy of latest physfs to our misc/libphysfs since this seems to fix an off-by-1 error reliably hit in readln read of 1 byte probably introduced in the addition of the buffered read. Whether this is excessive or whether libphysfs should even be maintained by us is another matter. But at least we shouldn't crash
nemo
parents:
10017
diff
changeset
|
68 |
ctx.copyDescription = cfallocCopyDesc; |
7768 | 69 |
ctx.allocate = cfallocMalloc; |
70 |
ctx.reallocate = cfallocRealloc; |
|
71 |
ctx.deallocate = cfallocFree; |
|
72 |
cfallocator = CFAllocatorCreate(kCFAllocatorUseContext, &ctx); |
|
73 |
BAIL_IF_MACRO(!cfallocator, PHYSFS_ERR_OUT_OF_MEMORY, 0); |
|
74 |
return 1; /* success. */ |
|
75 |
} /* __PHYSFS_platformInit */ |
|
76 |
||
77 |
||
78 |
int __PHYSFS_platformDeinit(void) |
|
79 |
{ |
|
80 |
CFRelease(cfallocator); |
|
81 |
cfallocator = NULL; |
|
82 |
return 1; /* always succeed. */ |
|
83 |
} /* __PHYSFS_platformDeinit */ |
|
84 |
||
85 |
||
86 |
||
87 |
/* CD-ROM detection code... */ |
|
88 |
||
89 |
/* |
|
90 |
* Code based on sample from Apple Developer Connection: |
|
12213
bb5522e88ab2
bulk copy of latest physfs to our misc/libphysfs since this seems to fix an off-by-1 error reliably hit in readln read of 1 byte probably introduced in the addition of the buffered read. Whether this is excessive or whether libphysfs should even be maintained by us is another matter. But at least we shouldn't crash
nemo
parents:
10017
diff
changeset
|
91 |
* https://developer.apple.com/samplecode/Sample_Code/Devices_and_Hardware/Disks/VolumeToBSDNode/VolumeToBSDNode.c.htm |
7768 | 92 |
*/ |
93 |
||
94 |
#if !defined(PHYSFS_NO_CDROM_SUPPORT) |
|
95 |
||
96 |
static int darwinIsWholeMedia(io_service_t service) |
|
97 |
{ |
|
98 |
int retval = 0; |
|
99 |
CFTypeRef wholeMedia; |
|
100 |
||
101 |
if (!IOObjectConformsTo(service, kIOMediaClass)) |
|
102 |
return 0; |
|
12213
bb5522e88ab2
bulk copy of latest physfs to our misc/libphysfs since this seems to fix an off-by-1 error reliably hit in readln read of 1 byte probably introduced in the addition of the buffered read. Whether this is excessive or whether libphysfs should even be maintained by us is another matter. But at least we shouldn't crash
nemo
parents:
10017
diff
changeset
|
103 |
|
7768 | 104 |
wholeMedia = IORegistryEntryCreateCFProperty(service, |
105 |
CFSTR(kIOMediaWholeKey), |
|
106 |
cfallocator, 0); |
|
107 |
if (wholeMedia == NULL) |
|
108 |
return 0; |
|
109 |
||
110 |
retval = CFBooleanGetValue(wholeMedia); |
|
111 |
CFRelease(wholeMedia); |
|
112 |
||
113 |
return retval; |
|
114 |
} /* darwinIsWholeMedia */ |
|
115 |
||
116 |
||
117 |
static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort) |
|
118 |
{ |
|
119 |
int retval = 0; |
|
120 |
CFMutableDictionaryRef matchingDict; |
|
121 |
kern_return_t rc; |
|
122 |
io_iterator_t iter; |
|
123 |
io_service_t service; |
|
124 |
||
125 |
if ((matchingDict = IOBSDNameMatching(masterPort, 0, bsdName)) == NULL) |
|
126 |
return 0; |
|
127 |
||
128 |
rc = IOServiceGetMatchingServices(masterPort, matchingDict, &iter); |
|
129 |
if ((rc != KERN_SUCCESS) || (!iter)) |
|
130 |
return 0; |
|
131 |
||
132 |
service = IOIteratorNext(iter); |
|
133 |
IOObjectRelease(iter); |
|
134 |
if (!service) |
|
135 |
return 0; |
|
136 |
||
137 |
rc = IORegistryEntryCreateIterator(service, kIOServicePlane, |
|
138 |
kIORegistryIterateRecursively | kIORegistryIterateParents, &iter); |
|
12213
bb5522e88ab2
bulk copy of latest physfs to our misc/libphysfs since this seems to fix an off-by-1 error reliably hit in readln read of 1 byte probably introduced in the addition of the buffered read. Whether this is excessive or whether libphysfs should even be maintained by us is another matter. But at least we shouldn't crash
nemo
parents:
10017
diff
changeset
|
139 |
|
7768 | 140 |
if (!iter) |
141 |
return 0; |
|
142 |
||
143 |
if (rc != KERN_SUCCESS) |
|
144 |
{ |
|
145 |
IOObjectRelease(iter); |
|
146 |
return 0; |
|
147 |
} /* if */ |
|
148 |
||
149 |
IOObjectRetain(service); /* add an extra object reference... */ |
|
150 |
||
151 |
do |
|
152 |
{ |
|
153 |
if (darwinIsWholeMedia(service)) |
|
154 |
{ |
|
155 |
if ( (IOObjectConformsTo(service, kIOCDMediaClass)) || |
|
156 |
(IOObjectConformsTo(service, kIODVDMediaClass)) ) |
|
157 |
{ |
|
158 |
retval = 1; |
|
159 |
} /* if */ |
|
160 |
} /* if */ |
|
161 |
IOObjectRelease(service); |
|
162 |
} while ((service = IOIteratorNext(iter)) && (!retval)); |
|
12213
bb5522e88ab2
bulk copy of latest physfs to our misc/libphysfs since this seems to fix an off-by-1 error reliably hit in readln read of 1 byte probably introduced in the addition of the buffered read. Whether this is excessive or whether libphysfs should even be maintained by us is another matter. But at least we shouldn't crash
nemo
parents:
10017
diff
changeset
|
163 |
|
7768 | 164 |
IOObjectRelease(iter); |
165 |
IOObjectRelease(service); |
|
166 |
||
167 |
return retval; |
|
168 |
} /* darwinIsMountedDisc */ |
|
169 |
||
170 |
#endif /* !defined(PHYSFS_NO_CDROM_SUPPORT) */ |
|
171 |
||
172 |
||
173 |
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data) |
|
174 |
{ |
|
175 |
#if !defined(PHYSFS_NO_CDROM_SUPPORT) |
|
176 |
const char *devPrefix = "/dev/"; |
|
177 |
const int prefixLen = strlen(devPrefix); |
|
178 |
mach_port_t masterPort = 0; |
|
179 |
struct statfs *mntbufp; |
|
180 |
int i, mounts; |
|
181 |
||
182 |
if (IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS) |
|
183 |
BAIL_MACRO(PHYSFS_ERR_OS_ERROR, ) /*return void*/; |
|
184 |
||
185 |
mounts = getmntinfo(&mntbufp, MNT_WAIT); /* NOT THREAD SAFE! */ |
|
186 |
for (i = 0; i < mounts; i++) |
|
187 |
{ |
|
188 |
char *dev = mntbufp[i].f_mntfromname; |
|
189 |
char *mnt = mntbufp[i].f_mntonname; |
|
190 |
if (strncmp(dev, devPrefix, prefixLen) != 0) /* a virtual device? */ |
|
191 |
continue; |
|
192 |
||
193 |
dev += prefixLen; |
|
194 |
if (darwinIsMountedDisc(dev, masterPort)) |
|
195 |
cb(data, mnt); |
|
196 |
} /* for */ |
|
197 |
#endif /* !defined(PHYSFS_NO_CDROM_SUPPORT) */ |
|
198 |
} /* __PHYSFS_platformDetectAvailableCDs */ |
|
199 |
||
200 |
||
201 |
static char *convertCFString(CFStringRef cfstr) |
|
202 |
{ |
|
203 |
CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr), |
|
204 |
kCFStringEncodingUTF8) + 1; |
|
205 |
char *retval = (char *) allocator.Malloc(len); |
|
206 |
BAIL_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
207 |
||
208 |
if (CFStringGetCString(cfstr, retval, len, kCFStringEncodingUTF8)) |
|
209 |
{ |
|
210 |
/* shrink overallocated buffer if possible... */ |
|
211 |
CFIndex newlen = strlen(retval) + 1; |
|
212 |
if (newlen < len) |
|
213 |
{ |
|
214 |
void *ptr = allocator.Realloc(retval, newlen); |
|
215 |
if (ptr != NULL) |
|
216 |
retval = (char *) ptr; |
|
217 |
} /* if */ |
|
218 |
} /* if */ |
|
219 |
||
220 |
else /* probably shouldn't fail, but just in case... */ |
|
221 |
{ |
|
222 |
allocator.Free(retval); |
|
223 |
BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
224 |
} /* else */ |
|
225 |
||
226 |
return retval; |
|
227 |
} /* convertCFString */ |
|
228 |
||
229 |
||
230 |
char *__PHYSFS_platformCalcBaseDir(const char *argv0) |
|
231 |
{ |
|
232 |
CFURLRef cfurl = NULL; |
|
233 |
CFStringRef cfstr = NULL; |
|
234 |
CFMutableStringRef cfmutstr = NULL; |
|
235 |
char *retval = NULL; |
|
236 |
||
237 |
cfurl = CFBundleCopyBundleURL(CFBundleGetMainBundle()); |
|
238 |
BAIL_IF_MACRO(cfurl == NULL, PHYSFS_ERR_OS_ERROR, NULL); |
|
239 |
cfstr = CFURLCopyFileSystemPath(cfurl, kCFURLPOSIXPathStyle); |
|
240 |
CFRelease(cfurl); |
|
241 |
BAIL_IF_MACRO(!cfstr, PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
242 |
cfmutstr = CFStringCreateMutableCopy(cfallocator, 0, cfstr); |
|
243 |
CFRelease(cfstr); |
|
244 |
BAIL_IF_MACRO(!cfmutstr, PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
245 |
CFStringAppendCString(cfmutstr, "/", kCFStringEncodingUTF8); |
|
246 |
retval = convertCFString(cfmutstr); |
|
247 |
CFRelease(cfmutstr); |
|
248 |
||
249 |
return retval; /* whew. */ |
|
250 |
} /* __PHYSFS_platformCalcBaseDir */ |
|
251 |
||
252 |
||
253 |
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app) |
|
254 |
{ |
|
255 |
/* !!! FIXME: there's a real API to determine this */ |
|
256 |
const char *userdir = __PHYSFS_getUserDir(); |
|
257 |
const char *append = "Library/Application Support/"; |
|
258 |
const size_t len = strlen(userdir) + strlen(append) + strlen(app) + 2; |
|
259 |
char *retval = allocator.Malloc(len); |
|
260 |
BAIL_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
261 |
snprintf(retval, len, "%s%s%s/", userdir, append, app); |
|
262 |
return retval; |
|
263 |
} /* __PHYSFS_platformCalcPrefDir */ |
|
264 |
||
265 |
||
266 |
/* Platform allocator uses default CFAllocator at PHYSFS_init() time. */ |
|
267 |
||
268 |
static CFAllocatorRef cfallocdef = NULL; |
|
269 |
||
270 |
static int macosxAllocatorInit(void) |
|
271 |
{ |
|
272 |
int retval = 0; |
|
273 |
cfallocdef = CFAllocatorGetDefault(); |
|
274 |
retval = (cfallocdef != NULL); |
|
275 |
if (retval) |
|
276 |
CFRetain(cfallocdef); |
|
277 |
return retval; |
|
278 |
} /* macosxAllocatorInit */ |
|
279 |
||
280 |
||
281 |
static void macosxAllocatorDeinit(void) |
|
282 |
{ |
|
283 |
if (cfallocdef != NULL) |
|
284 |
{ |
|
285 |
CFRelease(cfallocdef); |
|
286 |
cfallocdef = NULL; |
|
287 |
} /* if */ |
|
288 |
} /* macosxAllocatorDeinit */ |
|
289 |
||
290 |
||
291 |
static void *macosxAllocatorMalloc(PHYSFS_uint64 s) |
|
292 |
{ |
|
293 |
if (!__PHYSFS_ui64FitsAddressSpace(s)) |
|
294 |
BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
295 |
return CFAllocatorAllocate(cfallocdef, (CFIndex) s, 0); |
|
296 |
} /* macosxAllocatorMalloc */ |
|
297 |
||
298 |
||
299 |
static void *macosxAllocatorRealloc(void *ptr, PHYSFS_uint64 s) |
|
300 |
{ |
|
301 |
if (!__PHYSFS_ui64FitsAddressSpace(s)) |
|
302 |
BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
303 |
return CFAllocatorReallocate(cfallocdef, ptr, (CFIndex) s, 0); |
|
304 |
} /* macosxAllocatorRealloc */ |
|
305 |
||
306 |
||
307 |
static void macosxAllocatorFree(void *ptr) |
|
308 |
{ |
|
309 |
CFAllocatorDeallocate(cfallocdef, ptr); |
|
310 |
} /* macosxAllocatorFree */ |
|
311 |
||
312 |
||
313 |
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a) |
|
314 |
{ |
|
315 |
allocator.Init = macosxAllocatorInit; |
|
316 |
allocator.Deinit = macosxAllocatorDeinit; |
|
317 |
allocator.Malloc = macosxAllocatorMalloc; |
|
318 |
allocator.Realloc = macosxAllocatorRealloc; |
|
319 |
allocator.Free = macosxAllocatorFree; |
|
320 |
return 1; /* return non-zero: we're supplying custom allocator. */ |
|
321 |
} /* __PHYSFS_platformSetDefaultAllocator */ |
|
322 |
||
323 |
#endif /* PHYSFS_PLATFORM_MACOSX */ |
|
324 |
||
325 |
/* end of macosx.c ... */ |
|
326 |