platform/beos.cpp
author Ryan C. Gordon <icculus@icculus.org>
Mon, 25 Jul 2005 01:38:07 +0000
changeset 745 df04959950eb
parent 657 dad3b5c307a9
child 788 3df4f1b61339
permissions -rw-r--r--
Patched to compile again on BeOS.
icculus@235
     1
/*
icculus@235
     2
 * BeOS platform-dependent support routines for PhysicsFS.
icculus@235
     3
 *
icculus@235
     4
 * Please see the file LICENSE in the source's root directory.
icculus@235
     5
 *
icculus@235
     6
 *  This file written by Ryan C. Gordon.
icculus@235
     7
 */
icculus@235
     8
icculus@235
     9
#if HAVE_CONFIG_H
icculus@235
    10
#  include <config.h>
icculus@235
    11
#endif
icculus@235
    12
icculus@235
    13
#ifdef __BEOS__
icculus@235
    14
icculus@235
    15
#include <be/kernel/OS.h>
icculus@235
    16
#include <be/app/Roster.h>
icculus@235
    17
#include <be/storage/Volume.h>
icculus@235
    18
#include <be/storage/VolumeRoster.h>
icculus@235
    19
#include <be/storage/Directory.h>
icculus@235
    20
#include <be/storage/Entry.h>
icculus@235
    21
#include <be/storage/Path.h>
icculus@235
    22
#include <be/kernel/fs_info.h>
icculus@235
    23
#include <be/device/scsi.h>
icculus@235
    24
icculus@235
    25
#include <stdio.h>
icculus@235
    26
#include <stdlib.h>
icculus@235
    27
#include <string.h>
icculus@235
    28
#include <errno.h>
icculus@235
    29
#include <unistd.h>
icculus@235
    30
icculus@235
    31
#define __PHYSICSFS_INTERNAL__
icculus@235
    32
#include "physfs_internal.h"
icculus@235
    33
icculus@235
    34
icculus@235
    35
const char *__PHYSFS_platformDirSeparator = "/";
icculus@235
    36
icculus@235
    37
icculus@235
    38
int __PHYSFS_platformInit(void)
icculus@235
    39
{
icculus@235
    40
    return(1);  /* always succeed. */
icculus@235
    41
} /* __PHYSFS_platformInit */
icculus@235
    42
icculus@235
    43
icculus@235
    44
int __PHYSFS_platformDeinit(void)
icculus@235
    45
{
icculus@235
    46
    return(1);  /* always succeed. */
icculus@235
    47
} /* __PHYSFS_platformDeinit */
icculus@235
    48
icculus@235
    49
icculus@235
    50
static char *getMountPoint(const char *devname)
icculus@235
    51
{
icculus@235
    52
    BVolumeRoster mounts;
icculus@235
    53
    BVolume vol;
icculus@235
    54
icculus@235
    55
    mounts.Rewind();
icculus@235
    56
    while (mounts.GetNextVolume(&vol) == B_NO_ERROR)
icculus@235
    57
    {
icculus@235
    58
        fs_info fsinfo;
icculus@235
    59
        fs_stat_dev(vol.Device(), &fsinfo);
icculus@235
    60
        if (strcmp(devname, fsinfo.device_name) == 0)
icculus@235
    61
        {
icculus@235
    62
            //char buf[B_FILE_NAME_LENGTH];
icculus@235
    63
            BDirectory directory;
icculus@235
    64
            BEntry entry;
icculus@235
    65
            BPath path;
icculus@235
    66
            status_t rc;
icculus@235
    67
            rc = vol.GetRootDirectory(&directory);
icculus@393
    68
            BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL);
icculus@235
    69
            rc = directory.GetEntry(&entry);
icculus@393
    70
            BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL);
icculus@235
    71
            rc = entry.GetPath(&path);
icculus@393
    72
            BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL);
icculus@235
    73
            const char *str = path.Path();
icculus@235
    74
            BAIL_IF_MACRO(str == NULL, ERR_OS_ERROR, NULL);  /* ?! */
icculus@745
    75
            char *retval = (char *) allocator.Malloc(strlen(str) + 1);
icculus@235
    76
            BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
icculus@235
    77
            strcpy(retval, str);
icculus@235
    78
            return(retval);
icculus@235
    79
        } /* if */
icculus@235
    80
    } /* while */
icculus@235
    81
icculus@235
    82
    return(NULL);
icculus@235
    83
} /* getMountPoint */
icculus@235
    84
icculus@235
    85
icculus@235
    86
    /*
icculus@235
    87
     * This function is lifted from Simple Directmedia Layer (SDL):
icculus@235
    88
     *  http://www.libsdl.org/
icculus@235
    89
     */
icculus@657
    90
static void tryDir(const char *d, PHYSFS_StringCallback callback, void *data)
icculus@235
    91
{
icculus@235
    92
    BDirectory dir;
icculus@657
    93
    dir.SetTo(d);
icculus@235
    94
    if (dir.InitCheck() != B_NO_ERROR)
icculus@235
    95
        return;
icculus@235
    96
icculus@235
    97
    dir.Rewind();
icculus@235
    98
    BEntry entry;
icculus@235
    99
    while (dir.GetNextEntry(&entry) >= 0)
icculus@235
   100
    {
icculus@235
   101
        BPath path;
icculus@235
   102
        const char *name;
icculus@235
   103
        entry_ref e;
icculus@235
   104
icculus@235
   105
        if (entry.GetPath(&path) != B_NO_ERROR)
icculus@235
   106
            continue;
icculus@235
   107
icculus@235
   108
        name = path.Path();
icculus@235
   109
icculus@235
   110
        if (entry.GetRef(&e) != B_NO_ERROR)
icculus@235
   111
            continue;
icculus@235
   112
icculus@235
   113
        if (entry.IsDirectory())
icculus@235
   114
        {
icculus@235
   115
            if (strcmp(e.name, "floppy") != 0)
icculus@657
   116
                tryDir(name, callback, data);
icculus@235
   117
        } /* if */
icculus@235
   118
icculus@235
   119
        else
icculus@235
   120
        {
icculus@235
   121
            bool add_it = false;
icculus@235
   122
            int devfd;
icculus@235
   123
            device_geometry g;
icculus@235
   124
icculus@235
   125
            if (strcmp(e.name, "raw") == 0)  /* ignore partitions. */
icculus@235
   126
            {
icculus@235
   127
                int devfd = open(name, O_RDONLY);
icculus@235
   128
                if (devfd >= 0)
icculus@235
   129
                {
icculus@235
   130
                    if (ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0)
icculus@235
   131
                    {
icculus@235
   132
                        if (g.device_type == B_CD)
icculus@235
   133
                        {
icculus@235
   134
                            char *mntpnt = getMountPoint(name);
icculus@235
   135
                            if (mntpnt != NULL)
icculus@657
   136
                            {
icculus@657
   137
                                callback(data, mntpnt);
icculus@745
   138
                                allocator.Free(mntpnt);  /* !!! FIXME: lose this malloc! */
icculus@657
   139
                            } /* if */
icculus@235
   140
                        } /* if */
icculus@235
   141
                    } /* if */
icculus@235
   142
                } /* if */
icculus@235
   143
            } /* if */
icculus@235
   144
icculus@235
   145
            close(devfd);
icculus@235
   146
        } /* else */
icculus@235
   147
    } /* while */
icculus@235
   148
} /* tryDir */
icculus@235
   149
icculus@235
   150
icculus@657
   151
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
icculus@235
   152
{
icculus@657
   153
    tryDir("/dev/disk", cb, data);
icculus@235
   154
} /* __PHYSFS_platformDetectAvailableCDs */
icculus@235
   155
icculus@235
   156
icculus@235
   157
static team_id getTeamID(void)
icculus@235
   158
{
icculus@235
   159
    thread_info info;
icculus@235
   160
    thread_id tid = find_thread(NULL);
icculus@235
   161
    get_thread_info(tid, &info);
icculus@235
   162
    return(info.team);
icculus@235
   163
} /* getMyTeamID */
icculus@235
   164
icculus@235
   165
icculus@235
   166
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
icculus@235
   167
{
icculus@235
   168
    /* in case there isn't a BApplication yet, we'll construct a roster. */
icculus@235
   169
    BRoster roster; 
icculus@235
   170
    app_info info;
icculus@235
   171
    status_t rc = roster.GetRunningAppInfo(getTeamID(), &info);
icculus@393
   172
    BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL);
icculus@235
   173
    BEntry entry(&(info.ref), true);
icculus@235
   174
    BPath path;
icculus@235
   175
    rc = entry.GetPath(&path);  /* (path) now has binary's path. */
icculus@235
   176
    assert(rc == B_OK);
icculus@235
   177
    rc = path.GetParent(&path); /* chop filename, keep directory. */
icculus@235
   178
    assert(rc == B_OK);
icculus@235
   179
    const char *str = path.Path();
icculus@235
   180
    assert(str != NULL);
icculus@745
   181
    char *retval = (char *) allocator.Malloc(strlen(str) + 1);
icculus@235
   182
    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
icculus@235
   183
    strcpy(retval, str);
icculus@235
   184
    return(retval);
icculus@235
   185
} /* __PHYSFS_platformCalcBaseDir */
icculus@235
   186
icculus@235
   187
icculus@235
   188
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
icculus@235
   189
{
icculus@235
   190
    return((PHYSFS_uint64) find_thread(NULL));
icculus@235
   191
} /* __PHYSFS_platformGetThreadID */
icculus@235
   192
icculus@235
   193
icculus@235
   194
/* Much like my college days, try to sleep for 10 milliseconds at a time... */
icculus@235
   195
void __PHYSFS_platformTimeslice(void)
icculus@235
   196
{
icculus@235
   197
    snooze(10000);  /* put thread to sleep for 10 milliseconds. */
icculus@235
   198
} /* __PHYSFS_platformTimeslice */
icculus@235
   199
icculus@235
   200
icculus@235
   201
char *__PHYSFS_platformRealPath(const char *path)
icculus@235
   202
{
icculus@235
   203
    char *str = (char *) alloca(strlen(path) + 1);
icculus@235
   204
    BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, NULL);
icculus@235
   205
    strcpy(str, path);
icculus@235
   206
    char *leaf = strrchr(str, '/');
icculus@235
   207
    if (leaf != NULL)
icculus@235
   208
        *(leaf++) = '\0';
icculus@235
   209
icculus@235
   210
    BPath normalized(str, leaf, true);  /* force normalization of path. */
icculus@235
   211
    const char *resolved_path = normalized.Path();
icculus@362
   212
    BAIL_IF_MACRO(resolved_path == NULL, ERR_NO_SUCH_FILE, NULL);
icculus@745
   213
    char *retval = (char *) allocator.Malloc(strlen(resolved_path) + 1);
icculus@235
   214
    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
icculus@235
   215
    strcpy(retval, resolved_path);
icculus@235
   216
    return(retval);
icculus@235
   217
} /* __PHYSFS_platformRealPath */
icculus@235
   218
icculus@235
   219
icculus@235
   220
void *__PHYSFS_platformCreateMutex(void)
icculus@235
   221
{
icculus@745
   222
    sem_id *retval = (sem_id *) allocator.Malloc(sizeof (sem_id));
icculus@235
   223
    sem_id rc;
icculus@235
   224
icculus@235
   225
    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
icculus@235
   226
    rc = create_sem(1, "PhysicsFS semaphore");
icculus@235
   227
    if (rc < B_OK)
icculus@235
   228
    {
icculus@745
   229
        allocator.Free(retval);
icculus@393
   230
        BAIL_MACRO(strerror(rc), NULL);
icculus@235
   231
    } // if
icculus@235
   232
icculus@235
   233
    *retval = rc;
icculus@235
   234
    return(retval);
icculus@235
   235
} /* __PHYSFS_platformCreateMutex */
icculus@235
   236
icculus@235
   237
icculus@235
   238
void __PHYSFS_platformDestroyMutex(void *mutex)
icculus@235
   239
{
icculus@235
   240
    delete_sem( *((sem_id *) mutex) );
icculus@745
   241
    allocator.Free(mutex);
icculus@235
   242
} /* __PHYSFS_platformDestroyMutex */
icculus@235
   243
icculus@235
   244
icculus@235
   245
int __PHYSFS_platformGrabMutex(void *mutex)
icculus@235
   246
{
icculus@235
   247
    status_t rc = acquire_sem(*((sem_id *) mutex));
icculus@393
   248
    BAIL_IF_MACRO(rc < B_OK, strerror(rc), 0);
icculus@235
   249
    return(1);
icculus@235
   250
} /* __PHYSFS_platformGrabMutex */
icculus@235
   251
icculus@235
   252
icculus@235
   253
void __PHYSFS_platformReleaseMutex(void *mutex)
icculus@235
   254
{
icculus@235
   255
    release_sem(*((sem_id *) mutex));
icculus@235
   256
} /* __PHYSFS_platformReleaseMutex */
icculus@235
   257
icculus@235
   258
#endif
icculus@235
   259
icculus@235
   260
/* end of beos.cpp ... */
icculus@235
   261