Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

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