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