author | Ryan C. Gordon <icculus@icculus.org> |
Wed, 31 Jul 2002 04:18:58 +0000 | |
changeset 446 | e1f7fe003b70 |
parent 393 | 468f75bf4d7d |
child 504 | 3420d82f9b01 |
permissions | -rw-r--r-- |
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 |
||
39 |
int __PHYSFS_platformInit(void) |
|
40 |
{ |
|
41 |
return(1); /* always succeed. */ |
|
42 |
} /* __PHYSFS_platformInit */ |
|
43 |
||
44 |
||
45 |
int __PHYSFS_platformDeinit(void) |
|
46 |
{ |
|
47 |
return(1); /* always succeed. */ |
|
48 |
} /* __PHYSFS_platformDeinit */ |
|
49 |
||
50 |
||
51 |
||
52 |
/* caller needs to malloc() mntpnt, and expect us to free() it. */ |
|
53 |
static void addDisc(char *mntpnt, char ***discs, int *disccount) |
|
54 |
{ |
|
55 |
char **tmp = (char **) realloc(*discs, sizeof (char *) * (*disccount + 1)); |
|
56 |
if (tmp) |
|
57 |
{ |
|
58 |
tmp[*disccount - 1] = mntpnt; |
|
59 |
*discs = tmp; |
|
60 |
(*disccount)++; |
|
61 |
} /* if */ |
|
62 |
} /* addDisc */ |
|
63 |
||
64 |
||
65 |
static char *getMountPoint(const char *devname) |
|
66 |
{ |
|
67 |
BVolumeRoster mounts; |
|
68 |
BVolume vol; |
|
69 |
||
70 |
mounts.Rewind(); |
|
71 |
while (mounts.GetNextVolume(&vol) == B_NO_ERROR) |
|
72 |
{ |
|
73 |
fs_info fsinfo; |
|
74 |
fs_stat_dev(vol.Device(), &fsinfo); |
|
75 |
if (strcmp(devname, fsinfo.device_name) == 0) |
|
76 |
{ |
|
77 |
//char buf[B_FILE_NAME_LENGTH]; |
|
78 |
BDirectory directory; |
|
79 |
BEntry entry; |
|
80 |
BPath path; |
|
81 |
status_t rc; |
|
82 |
rc = vol.GetRootDirectory(&directory); |
|
393 | 83 |
BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL); |
235 | 84 |
rc = directory.GetEntry(&entry); |
393 | 85 |
BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL); |
235 | 86 |
rc = entry.GetPath(&path); |
393 | 87 |
BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL); |
235 | 88 |
const char *str = path.Path(); |
89 |
BAIL_IF_MACRO(str == NULL, ERR_OS_ERROR, NULL); /* ?! */ |
|
90 |
char *retval = (char *) malloc(strlen(str) + 1); |
|
91 |
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); |
|
92 |
strcpy(retval, str); |
|
93 |
return(retval); |
|
94 |
} /* if */ |
|
95 |
} /* while */ |
|
96 |
||
97 |
return(NULL); |
|
98 |
} /* getMountPoint */ |
|
99 |
||
100 |
||
101 |
/* |
|
102 |
* This function is lifted from Simple Directmedia Layer (SDL): |
|
103 |
* http://www.libsdl.org/ |
|
104 |
*/ |
|
105 |
static void tryDir(const char *dirname, char ***discs, int *disccount) |
|
106 |
{ |
|
107 |
BDirectory dir; |
|
108 |
dir.SetTo(dirname); |
|
109 |
if (dir.InitCheck() != B_NO_ERROR) |
|
110 |
return; |
|
111 |
||
112 |
dir.Rewind(); |
|
113 |
BEntry entry; |
|
114 |
while (dir.GetNextEntry(&entry) >= 0) |
|
115 |
{ |
|
116 |
BPath path; |
|
117 |
const char *name; |
|
118 |
entry_ref e; |
|
119 |
||
120 |
if (entry.GetPath(&path) != B_NO_ERROR) |
|
121 |
continue; |
|
122 |
||
123 |
name = path.Path(); |
|
124 |
||
125 |
if (entry.GetRef(&e) != B_NO_ERROR) |
|
126 |
continue; |
|
127 |
||
128 |
if (entry.IsDirectory()) |
|
129 |
{ |
|
130 |
if (strcmp(e.name, "floppy") != 0) |
|
131 |
tryDir(name, discs, disccount); |
|
132 |
} /* if */ |
|
133 |
||
134 |
else |
|
135 |
{ |
|
136 |
bool add_it = false; |
|
137 |
int devfd; |
|
138 |
device_geometry g; |
|
139 |
||
140 |
if (strcmp(e.name, "raw") == 0) /* ignore partitions. */ |
|
141 |
{ |
|
142 |
int devfd = open(name, O_RDONLY); |
|
143 |
if (devfd >= 0) |
|
144 |
{ |
|
145 |
if (ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) |
|
146 |
{ |
|
147 |
if (g.device_type == B_CD) |
|
148 |
{ |
|
149 |
char *mntpnt = getMountPoint(name); |
|
150 |
if (mntpnt != NULL) |
|
151 |
addDisc(mntpnt, discs, disccount); |
|
152 |
} /* if */ |
|
153 |
} /* if */ |
|
154 |
} /* if */ |
|
155 |
} /* if */ |
|
156 |
||
157 |
close(devfd); |
|
158 |
} /* else */ |
|
159 |
} /* while */ |
|
160 |
} /* tryDir */ |
|
161 |
||
162 |
||
163 |
char **__PHYSFS_platformDetectAvailableCDs(void) |
|
164 |
{ |
|
165 |
char **retval = (char **) malloc(sizeof (char *)); |
|
166 |
int cd_count = 1; /* We count the NULL entry. */ |
|
167 |
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); |
|
168 |
tryDir("/dev/disk", &retval, &cd_count); |
|
169 |
retval[cd_count - 1] = NULL; |
|
170 |
return(retval); |
|
171 |
} /* __PHYSFS_platformDetectAvailableCDs */ |
|
172 |
||
173 |
||
174 |
static team_id getTeamID(void) |
|
175 |
{ |
|
176 |
thread_info info; |
|
177 |
thread_id tid = find_thread(NULL); |
|
178 |
get_thread_info(tid, &info); |
|
179 |
return(info.team); |
|
180 |
} /* getMyTeamID */ |
|
181 |
||
182 |
||
183 |
char *__PHYSFS_platformCalcBaseDir(const char *argv0) |
|
184 |
{ |
|
185 |
/* in case there isn't a BApplication yet, we'll construct a roster. */ |
|
186 |
BRoster roster; |
|
187 |
app_info info; |
|
188 |
status_t rc = roster.GetRunningAppInfo(getTeamID(), &info); |
|
393 | 189 |
BAIL_IF_MACRO(rc < B_OK, strerror(rc), NULL); |
235 | 190 |
BEntry entry(&(info.ref), true); |
191 |
BPath path; |
|
192 |
rc = entry.GetPath(&path); /* (path) now has binary's path. */ |
|
193 |
assert(rc == B_OK); |
|
194 |
rc = path.GetParent(&path); /* chop filename, keep directory. */ |
|
195 |
assert(rc == B_OK); |
|
196 |
const char *str = path.Path(); |
|
197 |
assert(str != NULL); |
|
198 |
char *retval = (char *) malloc(strlen(str) + 1); |
|
199 |
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); |
|
200 |
strcpy(retval, str); |
|
201 |
return(retval); |
|
202 |
} /* __PHYSFS_platformCalcBaseDir */ |
|
203 |
||
204 |
||
205 |
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void) |
|
206 |
{ |
|
207 |
return((PHYSFS_uint64) find_thread(NULL)); |
|
208 |
} /* __PHYSFS_platformGetThreadID */ |
|
209 |
||
210 |
||
211 |
/* Much like my college days, try to sleep for 10 milliseconds at a time... */ |
|
212 |
void __PHYSFS_platformTimeslice(void) |
|
213 |
{ |
|
214 |
snooze(10000); /* put thread to sleep for 10 milliseconds. */ |
|
215 |
} /* __PHYSFS_platformTimeslice */ |
|
216 |
||
217 |
||
218 |
char *__PHYSFS_platformRealPath(const char *path) |
|
219 |
{ |
|
220 |
char *str = (char *) alloca(strlen(path) + 1); |
|
221 |
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, NULL); |
|
222 |
strcpy(str, path); |
|
223 |
char *leaf = strrchr(str, '/'); |
|
224 |
if (leaf != NULL) |
|
225 |
*(leaf++) = '\0'; |
|
226 |
||
227 |
BPath normalized(str, leaf, true); /* force normalization of path. */ |
|
228 |
const char *resolved_path = normalized.Path(); |
|
362
ac8c846a0a66
Changed enumeration code to use __PHYSFS_addToLinkedStringList().
Ryan C. Gordon <icculus@icculus.org>
parents:
327
diff
changeset
|
229 |
BAIL_IF_MACRO(resolved_path == NULL, ERR_NO_SUCH_FILE, NULL); |
235 | 230 |
char *retval = (char *) malloc(strlen(resolved_path) + 1); |
231 |
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); |
|
232 |
strcpy(retval, resolved_path); |
|
233 |
return(retval); |
|
234 |
} /* __PHYSFS_platformRealPath */ |
|
235 |
||
236 |
||
237 |
void *__PHYSFS_platformCreateMutex(void) |
|
238 |
{ |
|
239 |
sem_id *retval = (sem_id *) malloc(sizeof (sem_id)); |
|
240 |
sem_id rc; |
|
241 |
||
242 |
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); |
|
243 |
rc = create_sem(1, "PhysicsFS semaphore"); |
|
244 |
if (rc < B_OK) |
|
245 |
{ |
|
246 |
free(retval); |
|
393 | 247 |
BAIL_MACRO(strerror(rc), NULL); |
235 | 248 |
} // if |
249 |
||
250 |
*retval = rc; |
|
251 |
return(retval); |
|
252 |
} /* __PHYSFS_platformCreateMutex */ |
|
253 |
||
254 |
||
255 |
void __PHYSFS_platformDestroyMutex(void *mutex) |
|
256 |
{ |
|
257 |
delete_sem( *((sem_id *) mutex) ); |
|
258 |
free(mutex); |
|
259 |
} /* __PHYSFS_platformDestroyMutex */ |
|
260 |
||
261 |
||
262 |
int __PHYSFS_platformGrabMutex(void *mutex) |
|
263 |
{ |
|
264 |
status_t rc = acquire_sem(*((sem_id *) mutex)); |
|
393 | 265 |
BAIL_IF_MACRO(rc < B_OK, strerror(rc), 0); |
235 | 266 |
return(1); |
267 |
} /* __PHYSFS_platformGrabMutex */ |
|
268 |
||
269 |
||
270 |
void __PHYSFS_platformReleaseMutex(void *mutex) |
|
271 |
{ |
|
272 |
release_sem(*((sem_id *) mutex)); |
|
273 |
} /* __PHYSFS_platformReleaseMutex */ |
|
274 |
||
275 |
#endif |
|
276 |
||
277 |
/* end of beos.cpp ... */ |
|
278 |