🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
5.3 KiB

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