physfs_platform_qnx.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * QNX 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. /* This is tested against QNX 7 at the moment. */
  9. #define __PHYSICSFS_INTERNAL__
  10. #include "physfs_platforms.h"
  11. #ifdef PHYSFS_PLATFORM_QNX
  12. #include <fcntl.h>
  13. #include <unistd.h>
  14. #include <sys/types.h>
  15. #include <limits.h>
  16. #include "physfs_internal.h"
  17. int __PHYSFS_platformInit(void)
  18. {
  19. return 1; /* always succeed. */
  20. } /* __PHYSFS_platformInit */
  21. void __PHYSFS_platformDeinit(void)
  22. {
  23. /* no-op */
  24. } /* __PHYSFS_platformDeinit */
  25. char *__PHYSFS_platformCalcBaseDir(const char *argv0)
  26. {
  27. char *retval = (char *) allocator.Malloc(PATH_MAX+1);
  28. if (retval == NULL)
  29. BAIL(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
  30. else
  31. {
  32. const int fd = open("/proc/self/exefile", O_RDONLY);
  33. const ssize_t br = (fd == -1) ? -1 : read(fd, retval, PATH_MAX);
  34. char *ptr;
  35. if (fd != -1)
  36. close(fd);
  37. if ((br < 0) || (br > PATH_MAX))
  38. {
  39. allocator.Free(retval);
  40. BAIL(PHYSFS_ERR_OS_ERROR, NULL);
  41. } /* if */
  42. retval[br] = '\0';
  43. ptr = strrchr(retval, '/');
  44. if (ptr == NULL) /* uhoh! */
  45. {
  46. allocator.Free(retval);
  47. BAIL(PHYSFS_ERR_OS_ERROR, NULL);
  48. } /* if */
  49. ptr[1] = '\0'; /* chop off filename, leave dirs and '/' */
  50. ptr = (char *) allocator.Realloc(retval, (ptr - retval) + 2);
  51. if (ptr != NULL) /* just shrinking buffer; don't care if it failed. */
  52. retval = ptr;
  53. } /* else */
  54. return retval;
  55. } /* __PHYSFS_platformCalcBaseDir */
  56. char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app)
  57. {
  58. /* !!! FIXME: this might be wrong; I don't know if there's a better method
  59. on QNX, or if it follows XDG specs, etc. */
  60. char *retval = NULL;
  61. const char *home = __PHYSFS_getUserDir();
  62. if (home)
  63. {
  64. const size_t len = strlen(home) + strlen(app) + 3;
  65. retval = (char *) allocator.Malloc(len);
  66. BAIL_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
  67. snprintf(retval, len, "%s.%s/", home, app);
  68. } /* if */
  69. return retval;
  70. } /* __PHYSFS_platformCalcPrefDir */
  71. #if !PHYSFS_NO_CDROM_SUPPORT
  72. #include <devctl.h>
  73. #include <sys/dcmd_blk.h>
  74. #include <dirent.h>
  75. #include <sys/stat.h>
  76. #include <sys/statvfs.h>
  77. static void checkPathForCD(const char *path, PHYSFS_StringCallback cb, void *d)
  78. {
  79. struct stat statbuf;
  80. int fd;
  81. /* The devctl() thing is QNX-specific. In this case, we query what is
  82. probably the mountpoint for the device. statvfs() on that mountpoint
  83. will tell use its filesystem type. */
  84. if ( (stat(path, &statbuf) == 0) &&
  85. (S_ISBLK(statbuf.st_mode)) &&
  86. ((fd = open(path, O_RDONLY | O_NONBLOCK)) != -1) )
  87. {
  88. char mnt[256] = { 0 };
  89. const int rc = devctl(fd, DCMD_FSYS_MOUNTED_BY, mnt, sizeof (mnt), 0);
  90. close(fd);
  91. if ( (rc == EOK) && (mnt[0]) )
  92. {
  93. struct statvfs statvfsbuf;
  94. if (statvfs(mnt, &statvfsbuf) == 0)
  95. {
  96. /* I don't know if this is a complete or accurate list. */
  97. const char *fstype = statvfsbuf.f_basetype;
  98. const int iscd = ( (strcmp(fstype, "cd") == 0) ||
  99. (strcmp(fstype, "udf") == 0) );
  100. if (iscd)
  101. cb(d, mnt);
  102. } /* if */
  103. } /* if */
  104. } /* if */
  105. } /* checkPathForCD */
  106. static void checkDevForCD(const char *dev, PHYSFS_StringCallback cb, void *d)
  107. {
  108. size_t len;
  109. char *path;
  110. if (dev[0] == '.') /* ignore "." and ".." */
  111. {
  112. if ((dev[1] == '\0') || ((dev[1] == '.') && (dev[2] == '\0')))
  113. return;
  114. } /* if */
  115. len = strlen(dev) + 6;
  116. path = (char *) __PHYSFS_smallAlloc(len);
  117. if (!path)
  118. return; /* oh well. */
  119. snprintf(path, len, "/dev/%s", dev);
  120. checkPathForCD(path, cb, d);
  121. __PHYSFS_smallFree(path);
  122. } /* checkDevForCD */
  123. #endif /* !PHYSFS_NO_CDROM_SUPPORT */
  124. void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
  125. {
  126. #if !PHYSFS_NO_CDROM_SUPPORT
  127. DIR *dirp = opendir("/dev");
  128. if (dirp)
  129. {
  130. struct dirent *dent;
  131. while ((dent = readdir(dirp)) != NULL)
  132. checkDevForCD(dent->d_name, cb, data);
  133. closedir(dirp);
  134. } /* if */
  135. #endif
  136. } /* __PHYSFS_platformDetectAvailableCDs */
  137. #endif /* PHYSFS_PLATFORM_QNX */
  138. /* end of physfs_platform_qnx.c ... */