|
1 /* |
|
2 * BeOS platform-dependent 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 #define __PHYSICSFS_INTERNAL__ |
|
10 #include "physfs_platforms.h" |
|
11 |
|
12 #ifdef PHYSFS_PLATFORM_BEOS |
|
13 |
|
14 #ifdef PHYSFS_PLATFORM_HAIKU |
|
15 #include <os/kernel/OS.h> |
|
16 #include <os/app/Roster.h> |
|
17 #include <os/storage/Volume.h> |
|
18 #include <os/storage/VolumeRoster.h> |
|
19 #include <os/storage/Directory.h> |
|
20 #include <os/storage/Entry.h> |
|
21 #include <os/storage/Path.h> |
|
22 #include <os/kernel/fs_info.h> |
|
23 #include <os/device/scsi.h> |
|
24 #include <os/support/Locker.h> |
|
25 #else |
|
26 #include <be/kernel/OS.h> |
|
27 #include <be/app/Roster.h> |
|
28 #include <be/storage/Volume.h> |
|
29 #include <be/storage/VolumeRoster.h> |
|
30 #include <be/storage/Directory.h> |
|
31 #include <be/storage/Entry.h> |
|
32 #include <be/storage/Path.h> |
|
33 #include <be/kernel/fs_info.h> |
|
34 #include <be/device/scsi.h> |
|
35 #include <be/support/Locker.h> |
|
36 #endif |
|
37 |
|
38 #include <errno.h> |
|
39 #include <unistd.h> |
|
40 |
|
41 #include "physfs_internal.h" |
|
42 |
|
43 int __PHYSFS_platformInit(void) |
|
44 { |
|
45 return 1; /* always succeed. */ |
|
46 } /* __PHYSFS_platformInit */ |
|
47 |
|
48 |
|
49 int __PHYSFS_platformDeinit(void) |
|
50 { |
|
51 return 1; /* always succeed. */ |
|
52 } /* __PHYSFS_platformDeinit */ |
|
53 |
|
54 |
|
55 static char *getMountPoint(const char *devname, char *buf, size_t bufsize) |
|
56 { |
|
57 BVolumeRoster mounts; |
|
58 BVolume vol; |
|
59 |
|
60 mounts.Rewind(); |
|
61 while (mounts.GetNextVolume(&vol) == B_NO_ERROR) |
|
62 { |
|
63 fs_info fsinfo; |
|
64 fs_stat_dev(vol.Device(), &fsinfo); |
|
65 if (strcmp(devname, fsinfo.device_name) == 0) |
|
66 { |
|
67 BDirectory directory; |
|
68 BEntry entry; |
|
69 BPath path; |
|
70 const char *str; |
|
71 |
|
72 if ( (vol.GetRootDirectory(&directory) < B_OK) || |
|
73 (directory.GetEntry(&entry) < B_OK) || |
|
74 (entry.GetPath(&path) < B_OK) || |
|
75 ( (str = path.Path()) == NULL) ) |
|
76 return NULL; |
|
77 |
|
78 strncpy(buf, str, bufsize-1); |
|
79 buf[bufsize-1] = '\0'; |
|
80 return buf; |
|
81 } /* if */ |
|
82 } /* while */ |
|
83 |
|
84 return NULL; |
|
85 } /* getMountPoint */ |
|
86 |
|
87 |
|
88 /* |
|
89 * This function is lifted from Simple Directmedia Layer (SDL): |
|
90 * http://www.libsdl.org/ ... this is zlib-licensed code, too. |
|
91 */ |
|
92 static void tryDir(const char *d, PHYSFS_StringCallback callback, void *data) |
|
93 { |
|
94 BDirectory dir; |
|
95 dir.SetTo(d); |
|
96 if (dir.InitCheck() != B_NO_ERROR) |
|
97 return; |
|
98 |
|
99 dir.Rewind(); |
|
100 BEntry entry; |
|
101 while (dir.GetNextEntry(&entry) >= 0) |
|
102 { |
|
103 BPath path; |
|
104 const char *name; |
|
105 entry_ref e; |
|
106 |
|
107 if (entry.GetPath(&path) != B_NO_ERROR) |
|
108 continue; |
|
109 |
|
110 name = path.Path(); |
|
111 |
|
112 if (entry.GetRef(&e) != B_NO_ERROR) |
|
113 continue; |
|
114 |
|
115 if (entry.IsDirectory()) |
|
116 { |
|
117 if (strcmp(e.name, "floppy") != 0) |
|
118 tryDir(name, callback, data); |
|
119 continue; |
|
120 } /* if */ |
|
121 |
|
122 if (strcmp(e.name, "raw") != 0) /* ignore partitions. */ |
|
123 continue; |
|
124 |
|
125 const int devfd = open(name, O_RDONLY); |
|
126 if (devfd < 0) |
|
127 continue; |
|
128 |
|
129 device_geometry g; |
|
130 const int rc = ioctl(devfd, B_GET_GEOMETRY, &g, sizeof (g)); |
|
131 close(devfd); |
|
132 if (rc < 0) |
|
133 continue; |
|
134 |
|
135 if (g.device_type != B_CD) |
|
136 continue; |
|
137 |
|
138 char mntpnt[B_FILE_NAME_LENGTH]; |
|
139 if (getMountPoint(name, mntpnt, sizeof (mntpnt))) |
|
140 callback(data, mntpnt); |
|
141 } /* while */ |
|
142 } /* tryDir */ |
|
143 |
|
144 |
|
145 void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data) |
|
146 { |
|
147 tryDir("/dev/disk", cb, data); |
|
148 } /* __PHYSFS_platformDetectAvailableCDs */ |
|
149 |
|
150 |
|
151 static team_id getTeamID(void) |
|
152 { |
|
153 thread_info info; |
|
154 thread_id tid = find_thread(NULL); |
|
155 get_thread_info(tid, &info); |
|
156 return info.team; |
|
157 } /* getTeamID */ |
|
158 |
|
159 |
|
160 char *__PHYSFS_platformCalcBaseDir(const char *argv0) |
|
161 { |
|
162 image_info info; |
|
163 int32 cookie = 0; |
|
164 |
|
165 while (get_next_image_info(0, &cookie, &info) == B_OK) |
|
166 { |
|
167 if (info.type == B_APP_IMAGE) |
|
168 break; |
|
169 } /* while */ |
|
170 |
|
171 BEntry entry(info.name, true); |
|
172 BPath path; |
|
173 status_t rc = entry.GetPath(&path); /* (path) now has binary's path. */ |
|
174 assert(rc == B_OK); |
|
175 rc = path.GetParent(&path); /* chop filename, keep directory. */ |
|
176 assert(rc == B_OK); |
|
177 const char *str = path.Path(); |
|
178 assert(str != NULL); |
|
179 const size_t len = strlen(str); |
|
180 char *retval = (char *) allocator.Malloc(len + 2); |
|
181 BAIL_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
182 strcpy(retval, str); |
|
183 retval[len] = '/'; |
|
184 retval[len+1] = '\0'; |
|
185 return retval; |
|
186 } /* __PHYSFS_platformCalcBaseDir */ |
|
187 |
|
188 |
|
189 char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app) |
|
190 { |
|
191 const char *userdir = __PHYSFS_getUserDir(); |
|
192 const char *append = "config/settings/"; |
|
193 const size_t len = strlen(userdir) + strlen(append) + strlen(app) + 2; |
|
194 char *retval = allocator.Malloc(len); |
|
195 BAIL_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
196 snprintf(retval, len, "%s%s%s/", userdir, append, app); |
|
197 return retval; |
|
198 } /* __PHYSFS_platformCalcPrefDir */ |
|
199 |
|
200 |
|
201 void *__PHYSFS_platformGetThreadID(void) |
|
202 { |
|
203 return (void *) find_thread(NULL); |
|
204 } /* __PHYSFS_platformGetThreadID */ |
|
205 |
|
206 |
|
207 void *__PHYSFS_platformCreateMutex(void) |
|
208 { |
|
209 return new BLocker("PhysicsFS lock", true); |
|
210 } /* __PHYSFS_platformCreateMutex */ |
|
211 |
|
212 |
|
213 void __PHYSFS_platformDestroyMutex(void *mutex) |
|
214 { |
|
215 delete ((BLocker *) mutex); |
|
216 } /* __PHYSFS_platformDestroyMutex */ |
|
217 |
|
218 |
|
219 int __PHYSFS_platformGrabMutex(void *mutex) |
|
220 { |
|
221 return ((BLocker *) mutex)->Lock() ? 1 : 0; |
|
222 } /* __PHYSFS_platformGrabMutex */ |
|
223 |
|
224 |
|
225 void __PHYSFS_platformReleaseMutex(void *mutex) |
|
226 { |
|
227 ((BLocker *) mutex)->Unlock(); |
|
228 } /* __PHYSFS_platformReleaseMutex */ |
|
229 |
|
230 |
|
231 int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a) |
|
232 { |
|
233 return 0; /* just use malloc() and friends. */ |
|
234 } /* __PHYSFS_platformSetDefaultAllocator */ |
|
235 |
|
236 #endif /* PHYSFS_PLATFORM_BEOS */ |
|
237 |
|
238 /* end of beos.cpp ... */ |
|
239 |