src/physfs_platform_qnx.c
changeset 1588 59a7ec36bd8c
equal deleted inserted replaced
1587:3396e6dd19fb 1588:59a7ec36bd8c
       
     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