Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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