Skip to content

Latest commit

 

History

History
326 lines (251 loc) · 8.95 KB

platform_macosx.c

File metadata and controls

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