Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * Apple platform (macOS, iOS, watchOS, etc) 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_APPLE
13
 
14
#include <Foundation/Foundation.h>
15
 
16
#include "physfs_internal.h"
17
 
18
int __PHYSFS_platformInit(void)
19
{
20
    return 1;  /* success. */
21
} /* __PHYSFS_platformInit */
22
 
23
 
24
void __PHYSFS_platformDeinit(void)
25
{
26
    /* no-op */
27
} /* __PHYSFS_platformDeinit */
28
 
29
 
30
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
31
{
32
    @autoreleasepool
33
    {
34
        NSString *path = [[NSBundle mainBundle] bundlePath];
35
        BAIL_IF(!path, PHYSFS_ERR_OS_ERROR, NULL);
36
        size_t len = [path lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
37
        char *retval = (char *) allocator.Malloc(len + 2);
38
        BAIL_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
39
        [path getCString:retval maxLength:len+1 encoding:NSUTF8StringEncoding];
40
        retval[len] = '/';
41
        retval[len+1] = '\0';
42
        return retval;  /* whew. */
43
    } /* @autoreleasepool */
44
} /* __PHYSFS_platformCalcBaseDir */
45
 
46
 
47
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app)
48
{
49
    @autoreleasepool
50
    {
51
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, TRUE);
52
        BAIL_IF(!paths, PHYSFS_ERR_OS_ERROR, NULL);
53
        NSString *path = (NSString *) [paths objectAtIndex:0];
54
        BAIL_IF(!path, PHYSFS_ERR_OS_ERROR, NULL);
55
        size_t len = [path lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
56
        const size_t applen = strlen(app);
57
        char *retval = (char *) allocator.Malloc(len + applen + 3);
58
        BAIL_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
59
        [path getCString:retval maxLength:len+1 encoding:NSUTF8StringEncoding];
60
        snprintf(retval + len, applen + 3, "/%s/", app);
61
        return retval;  /* whew. */
62
    } /* @autoreleasepool */
63
} /* __PHYSFS_platformCalcPrefDir */
64
 
65
 
66
/* CD-ROM detection code... */
67
 
68
/*
69
 * Code based on sample from Apple Developer Connection:
70
 *  https://developer.apple.com/samplecode/Sample_Code/Devices_and_Hardware/Disks/VolumeToBSDNode/VolumeToBSDNode.c.htm
71
 */
72
 
73
#if !defined(PHYSFS_NO_CDROM_SUPPORT)
74
 
75
#include <IOKit/IOKitLib.h>
76
#include <IOKit/storage/IOMedia.h>
77
#include <IOKit/storage/IOCDMedia.h>
78
#include <IOKit/storage/IODVDMedia.h>
79
#include <sys/mount.h>
80
 
81
static int darwinIsWholeMedia(io_service_t service)
82
{
83
    int retval = 0;
84
    CFTypeRef wholeMedia;
85
 
86
    if (!IOObjectConformsTo(service, kIOMediaClass))
87
        return 0;
88
 
89
    wholeMedia = IORegistryEntryCreateCFProperty(service,
90
                                                 CFSTR(kIOMediaWholeKey),
91
                                                 NULL, 0);
92
    if (wholeMedia == NULL)
93
        return 0;
94
 
95
    retval = CFBooleanGetValue(wholeMedia);
96
    CFRelease(wholeMedia);
97
 
98
    return retval;
99
} /* darwinIsWholeMedia */
100
 
101
 
102
static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
103
{
104
    int retval = 0;
105
    CFMutableDictionaryRef matchingDict;
106
    kern_return_t rc;
107
    io_iterator_t iter;
108
    io_service_t service;
109
 
110
    if ((matchingDict = IOBSDNameMatching(masterPort, 0, bsdName)) == NULL)
111
        return 0;
112
 
113
    rc = IOServiceGetMatchingServices(masterPort, matchingDict, &iter);
114
    if ((rc != KERN_SUCCESS) || (!iter))
115
        return 0;
116
 
117
    service = IOIteratorNext(iter);
118
    IOObjectRelease(iter);
119
    if (!service)
120
        return 0;
121
 
122
    rc = IORegistryEntryCreateIterator(service, kIOServicePlane,
123
             kIORegistryIterateRecursively | kIORegistryIterateParents, &iter);
124
 
125
    if (!iter)
126
        return 0;
127
 
128
    if (rc != KERN_SUCCESS)
129
    {
130
        IOObjectRelease(iter);
131
        return 0;
132
    } /* if */
133
 
134
    IOObjectRetain(service);  /* add an extra object reference... */
135
 
136
    do
137
    {
138
        if (darwinIsWholeMedia(service))
139
        {
140
            if ( (IOObjectConformsTo(service, kIOCDMediaClass)) ||
141
                 (IOObjectConformsTo(service, kIODVDMediaClass)) )
142
            {
143
                retval = 1;
144
            } /* if */
145
        } /* if */
146
        IOObjectRelease(service);
147
    } while ((service = IOIteratorNext(iter)) && (!retval));
148
 
149
    IOObjectRelease(iter);
150
    IOObjectRelease(service);
151
 
152
    return retval;
153
} /* darwinIsMountedDisc */
154
 
155
#endif /* !defined(PHYSFS_NO_CDROM_SUPPORT) */
156
 
157
 
158
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
159
{
160
#if !defined(PHYSFS_NO_CDROM_SUPPORT)
161
    const char *devPrefix = "/dev/";
162
    const int prefixLen = strlen(devPrefix);
163
    mach_port_t masterPort = 0;
164
    struct statfs *mntbufp;
165
    int i, mounts;
166
 
167
    if (IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS)
168
        BAIL(PHYSFS_ERR_OS_ERROR, ) /*return void*/;
169
 
170
    mounts = getmntinfo(&mntbufp, MNT_WAIT);  /* NOT THREAD SAFE! */
171
    for (i = 0; i < mounts; i++)
172
    {
173
        char *dev = mntbufp[i].f_mntfromname;
174
        char *mnt = mntbufp[i].f_mntonname;
175
        if (strncmp(dev, devPrefix, prefixLen) != 0)  /* a virtual device? */
176
            continue;
177
 
178
        dev += prefixLen;
179
        if (darwinIsMountedDisc(dev, masterPort))
180
            cb(data, mnt);
181
    } /* for */
182
#endif /* !defined(PHYSFS_NO_CDROM_SUPPORT) */
183
} /* __PHYSFS_platformDetectAvailableCDs */
184
 
185
#endif /* PHYSFS_PLATFORM_APPLE */
186
 
187
/* end of physfs_platform_apple.m ... */
188