ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.8
Committed: 1999-11-01T16:24:06Z (25 years ago) by cebix
Branch: MAIN
CVS Tags: snapshot-02111999
Changes since 1.7: +2 -2 lines
Log Message:
- AmigaOS: removed support for SAS/C
- AmigaOS: sys_amiga.cpp: supports 64-bit device access and respects
  device block size on writes
- AmigaOS: added support for resource forks and Finder info for ExtFS
- AmigaOS: added "ExtFS" gadget to prefs editor
- protection mask for all open()/creat()/mkdir() calls is now 0666 or
  0777

File Contents

# Content
1 /*
2 * extfs.cpp - MacOS file system for access native file system access
3 *
4 * Basilisk II (C) 1997-1999 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 * SEE ALSO
23 * Guide to the File System Manager (from FSM 1.2 SDK)
24 *
25 * TODO
26 * LockRng
27 * UnlockRng
28 * (CatSearch)
29 * (MakeFSSpec)
30 * (GetVolMountInfoSize)
31 * (GetVolMountInfo)
32 * (GetForeignPrivs)
33 * (SetForeignPrivs)
34 */
35
36 #include "sysdeps.h"
37
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <string.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <fcntl.h>
45 #include <dirent.h>
46 #include <errno.h>
47
48 #include "cpu_emulation.h"
49 #include "macos_util.h"
50 #include "emul_op.h"
51 #include "main.h"
52 #include "disk.h"
53 #include "prefs.h"
54 #include "user_strings.h"
55 #include "extfs.h"
56 #include "extfs_defs.h"
57
58 #define DEBUG 0
59 #include "debug.h"
60
61
62 // File system global data and 68k routines
63 enum {
64 fsCommProcStub = 0,
65 fsHFSProcStub = 6,
66 fsDrvStatus = 12, // Drive Status record
67 fsFSD = 42, // File system descriptor
68 fsPB = 238, // IOParam (for mounting)
69 fsVMI = 288, // VoumeMountInfoHeader (for mounting)
70 fsParseRec = 296, // ParsePathRec struct
71 fsReturn = 306, // Area for return data of 68k routines
72 fsAllocateVCB = 562, // UTAllocateVCB(uint16 *sysVCBLength{a0}, uint32 *vcb{a1})
73 fsAddNewVCB = 578, // UTAddNewVCB(int drive_number{d0}, int16 *vRefNum{a1}, uint32 vcb{a1})
74 fsDetermineVol = 594, // UTDetermineVol(uint32 pb{a0}, int16 *status{a1}, int16 *more_matches{a2}, int16 *vRefNum{a3}, uint32 *vcb{a4})
75 fsResolveWDCB = 614, // UTResolveWDCB(uint32 procID{d0}, int16 index{d1}, int16 vRefNum{d0}, uint32 *wdcb{a0})
76 fsGetDefaultVol = 632, // UTGetDefaultVol(uint32 wdpb{a0})
77 fsGetPathComponentName = 644, // UTGetPathComponentName(uint32 rec{a0})
78 fsParsePathname = 656, // UTParsePathname(uint32 *start{a0}, uint32 name{a1})
79 fsDisposeVCB = 670, // UTDisposeVCB(uint32 vcb{a0})
80 fsCheckWDRefNum = 682, // UTCheckWDRefNum(int16 refNum{d0})
81 fsSetDefaultVol = 694, // UTSetDefaultVol(uint32 dummy{d0}, int32 dirID{d1}, int16 refNum{d2})
82 fsAllocateFCB = 710, // UTAllocateFCB(int16 *refNum{a0}, uint32 *fcb{a1})
83 fsReleaseFCB = 724, // UTReleaseFCB(int16 refNum{d0})
84 fsIndexFCB = 736, // UTIndexFCB(uint32 vcb{a0}, int16 *refNum{a1}, uint32 *fcb{a2})
85 fsResolveFCB = 752, // UTResolveFCB(int16 refNum{d0}, uint32 *fcb{a0})
86 fsAdjustEOF = 766, // UTAdjustEOF(int16 refNum{d0})
87 fsAllocateWDCB = 778, // UTAllocateWDCB(uint32 pb{a0})
88 fsReleaseWDCB = 790, // UTReleaseWDCB(int16 vRefNum{d0})
89 SIZEOF_fsdat = 802
90 };
91
92 static uint32 fs_data = 0; // Mac address of global data
93
94
95 // File system and volume name
96 static char FS_NAME[32], VOLUME_NAME[32];
97
98 // This directory is our root (read from prefs)
99 static const char *RootPath;
100 static bool ready = false;
101 static struct stat root_stat;
102
103 // File system ID/media type
104 const int16 MY_FSID = 'ba';
105 const uint32 MY_MEDIA_TYPE = 'basi';
106
107 // CNID of root and root's parent
108 const uint32 ROOT_ID = 2;
109 const uint32 ROOT_PARENT_ID = 1;
110
111 // File system stack size
112 const int STACK_SIZE = 0x10000;
113
114 // Drive number of our pseudo-drive
115 static int drive_number;
116
117
118 // Disk/drive icon
119 const uint8 ExtFSIcon[256] = {
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe,
125 0x80, 0x00, 0x00, 0x91, 0x80, 0x00, 0x00, 0x91, 0x80, 0x00, 0x01, 0x21, 0x80, 0x00, 0x01, 0x21,
126 0x80, 0x00, 0x02, 0x41, 0x8c, 0x00, 0x02, 0x41, 0x80, 0x00, 0x04, 0x81, 0x80, 0x00, 0x04, 0x81,
127 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe,
134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
136 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
137 };
138
139
140 // These objects are used to map CNIDs to path names
141 struct FSItem {
142 FSItem *next; // Pointer to next FSItem in list
143 uint32 id; // CNID of this file/dir
144 uint32 parent_id; // CNID of parent file/dir
145 FSItem *parent; // Pointer to parent
146 char name[32]; // Object name (C string)
147 time_t mtime; // Modification time for get_cat_info caching
148 int cache_dircount; // Cached number of files in directory
149 };
150
151 static FSItem *first_fs_item, *last_fs_item;
152
153 static uint32 next_cnid = fsUsrCNID; // Next available CNID
154
155
156 /*
157 * Find FSItem for given CNID
158 */
159
160 static FSItem *find_fsitem_by_id(uint32 cnid)
161 {
162 FSItem *p = first_fs_item;
163 while (p) {
164 if (p->id == cnid)
165 return p;
166 p = p->next;
167 }
168 return NULL;
169 }
170
171
172 /*
173 * Find FSItem for given name and parent, construct new FSItem if not found
174 */
175
176 static FSItem *find_fsitem(const char *name, FSItem *parent)
177 {
178 FSItem *p = first_fs_item;
179 while (p) {
180 if (p->parent == parent && !strcmp(p->name, name))
181 return p;
182 p = p->next;
183 }
184
185 // Not found, construct new FSItem
186 p = new FSItem;
187 last_fs_item->next = p;
188 p->next = NULL;
189 last_fs_item = p;
190 p->id = next_cnid++;
191 p->parent_id = parent->id;
192 p->parent = parent;
193 strncpy(p->name, name, 31);
194 p->name[31] = 0;
195 p->mtime = 0;
196 return p;
197 }
198
199
200 /*
201 * Get full path (->full_path) for given FSItem
202 */
203
204 static char full_path[MAX_PATH_LENGTH];
205
206 static void add_path_comp(const char *s)
207 {
208 add_path_component(full_path, s);
209 }
210
211 static void get_path_for_fsitem(FSItem *p)
212 {
213 if (p->id == ROOT_PARENT_ID) {
214 full_path[0] = 0;
215 } else if (p->id == ROOT_ID) {
216 strncpy(full_path, RootPath, MAX_PATH_LENGTH-1);
217 full_path[MAX_PATH_LENGTH-1] = 0;
218 } else {
219 get_path_for_fsitem(p->parent);
220 add_path_comp(p->name);
221 }
222 }
223
224
225 /*
226 * String handling functions
227 */
228
229 // Copy pascal string
230 static void pstrcpy(char *dst, const char *src)
231 {
232 int size = *dst++ = *src++;
233 while (size--)
234 *dst++ = *src++;
235 }
236
237 // Convert C string to pascal string
238 static void cstr2pstr(char *dst, const char *src)
239 {
240 *dst++ = strlen(src);
241 char c;
242 while ((c = *src++) != 0) {
243 if (c == ':')
244 c = '/';
245 *dst++ = c;
246 }
247 }
248
249 // Convert pascal string to C string
250 static void pstr2cstr(char *dst, const char *src)
251 {
252 int size = *src++;
253 while (size--) {
254 char c = *src++;
255 if (c == '/')
256 c = ':';
257 *dst++ = c;
258 }
259 *dst = 0;
260 }
261
262 // Convert string (no length byte) to C string, length given separately
263 static void strn2cstr(char *dst, const char *src, int size)
264 {
265 while (size--) {
266 char c = *src++;
267 if (c == '/')
268 c = ':';
269 *dst++ = c;
270 }
271 *dst = 0;
272 }
273
274
275 /*
276 * Convert errno to MacOS error code
277 */
278
279 static int16 errno2oserr(void)
280 {
281 D(bug(" errno %08x\n", errno));
282 switch (errno) {
283 case 0:
284 return noErr;
285 case ENOENT:
286 case EISDIR:
287 return fnfErr;
288 case EACCES:
289 case EPERM:
290 return permErr;
291 case EEXIST:
292 return dupFNErr;
293 case EBUSY:
294 case ENOTEMPTY:
295 return fBsyErr;
296 case ENOSPC:
297 return dskFulErr;
298 case EROFS:
299 return wPrErr;
300 case EMFILE:
301 return tmfoErr;
302 case ENOMEM:
303 return -108;
304 case EIO:
305 default:
306 return ioErr;
307 }
308 }
309
310
311 /*
312 * Initialization
313 */
314
315 void ExtFSInit(void)
316 {
317 // System specific initialization
318 extfs_init();
319
320 // Get file system and volume name
321 cstr2pstr(FS_NAME, GetString(STR_EXTFS_NAME));
322 cstr2pstr(VOLUME_NAME, GetString(STR_EXTFS_VOLUME_NAME));
323
324 // Create root's parent FSItem
325 FSItem *p = new FSItem;
326 first_fs_item = last_fs_item = p;
327 p->next = NULL;
328 p->id = ROOT_PARENT_ID;
329 p->parent_id = 0;
330 p->parent = NULL;
331 p->name[0] = 0;
332
333 // Create root FSItem
334 p = new FSItem;
335 last_fs_item->next = p;
336 p->next = NULL;
337 last_fs_item = p;
338 p->id = ROOT_ID;
339 p->parent_id = ROOT_PARENT_ID;
340 p->parent = first_fs_item;
341 strncpy(p->name, GetString(STR_EXTFS_VOLUME_NAME), 32);
342
343 // Find path for root
344 if ((RootPath = PrefsFindString("extfs")) != NULL) {
345 if (stat(RootPath, &root_stat))
346 return;
347 if (!S_ISDIR(root_stat.st_mode))
348 return;
349 ready = true;
350 }
351 }
352
353
354 /*
355 * Deinitialization
356 */
357
358 void ExtFSExit(void)
359 {
360 // Delete all FSItems
361 FSItem *p = first_fs_item, *next;
362 while (p) {
363 next = p->next;
364 delete p;
365 p = next;
366 }
367 first_fs_item = last_fs_item = NULL;
368
369 // System specific deinitialization
370 extfs_exit();
371 }
372
373
374 /*
375 * Install file system
376 */
377
378 void InstallExtFS(void)
379 {
380 int num_blocks = 0xffff; // Fake number of blocks of our drive
381 M68kRegisters r;
382
383 D(bug("InstallExtFS\n"));
384 if (!ready)
385 return;
386
387 // FSM present?
388 r.d[0] = gestaltFSAttr;
389 Execute68kTrap(0xa1ad, &r); // Gestalt()
390 D(bug("FSAttr %ld, %08lx\n", r.d[0], r.a[0]));
391 if ((r.d[0] & 0xffff) || !(r.a[0] & (1 << gestaltHasFileSystemManager))) {
392 printf("WARNING: No FSM present, disabling ExtFS\n");
393 return;
394 }
395
396 // Yes, version >=1.2?
397 r.d[0] = gestaltFSMVersion;
398 Execute68kTrap(0xa1ad, &r); // Gestalt()
399 D(bug("FSMVersion %ld, %08lx\n", r.d[0], r.a[0]));
400 if ((r.d[0] & 0xffff) || (r.a[0] < 0x0120)) {
401 printf("WARNING: FSM <1.2 found, disabling ExtFS\n");
402 return;
403 }
404
405 D(bug("FSM present\n"));
406
407 // Yes, allocate file system stack
408 r.d[0] = STACK_SIZE;
409 Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
410 if (r.a[0] == 0)
411 return;
412 uint32 fs_stack = r.a[0];
413
414 // Allocate memory for our data structures and 68k code
415 r.d[0] = SIZEOF_fsdat;
416 Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
417 if (r.a[0] == 0)
418 return;
419 fs_data = r.a[0];
420
421 // Set up 68k code fragments
422 int p = fs_data + fsCommProcStub;
423 WriteMacInt16(p, M68K_EMUL_OP_EXTFS_COMM); p += 2;
424 WriteMacInt16(p, M68K_RTD); p += 2;
425 WriteMacInt16(p, 10); p += 2;
426 if (p - fs_data != fsHFSProcStub)
427 goto fsdat_error;
428 WriteMacInt16(p, M68K_EMUL_OP_EXTFS_HFS); p += 2;
429 WriteMacInt16(p, M68K_RTD); p += 2;
430 WriteMacInt16(p, 16);
431 p = fs_data + fsAllocateVCB;
432 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
433 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
434 WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(sp)
435 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
436 WriteMacInt16(p, 0x7006); p+= 2; // UTAllocateVCB
437 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
438 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
439 WriteMacInt16(p, M68K_RTS); p+= 2;
440 if (p - fs_data != fsAddNewVCB)
441 goto fsdat_error;
442 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
443 WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
444 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(a7)
445 WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(a7)
446 WriteMacInt16(p, 0x7007); p+= 2; // UTAddNewVCB
447 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
448 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
449 WriteMacInt16(p, M68K_RTS); p+= 2;
450 if (p - fs_data != fsDetermineVol)
451 goto fsdat_error;
452 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
453 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
454 WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(sp)
455 WriteMacInt16(p, 0x2f0a); p+= 2; // move.l a2,-(sp)
456 WriteMacInt16(p, 0x2f0b); p+= 2; // move.l a3,-(sp)
457 WriteMacInt16(p, 0x2f0c); p+= 2; // move.l a4,-(sp)
458 WriteMacInt16(p, 0x701d); p+= 2; // UTDetermineVol
459 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
460 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
461 WriteMacInt16(p, M68K_RTS); p+= 2;
462 if (p - fs_data != fsResolveWDCB)
463 goto fsdat_error;
464 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
465 WriteMacInt16(p, 0x2f00); p+= 2; // move.l d0,-(sp)
466 WriteMacInt16(p, 0x3f01); p+= 2; // move.w d1,-(sp)
467 WriteMacInt16(p, 0x3f02); p+= 2; // move.w d2,-(sp)
468 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
469 WriteMacInt16(p, 0x700e); p+= 2; // UTResolveWDCB
470 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
471 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
472 WriteMacInt16(p, M68K_RTS); p+= 2;
473 if (p - fs_data != fsGetDefaultVol)
474 goto fsdat_error;
475 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
476 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
477 WriteMacInt16(p, 0x7012); p+= 2; // UTGetDefaultVol
478 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
479 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
480 WriteMacInt16(p, M68K_RTS); p+= 2;
481 if (p - fs_data != fsGetPathComponentName)
482 goto fsdat_error;
483 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
484 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
485 WriteMacInt16(p, 0x701c); p+= 2; // UTGetPathComponentName
486 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
487 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
488 WriteMacInt16(p, M68K_RTS); p+= 2;
489 if (p - fs_data != fsParsePathname)
490 goto fsdat_error;
491 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
492 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
493 WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(sp)
494 WriteMacInt16(p, 0x701b); p+= 2; // UTParsePathname
495 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
496 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
497 WriteMacInt16(p, M68K_RTS); p+= 2;
498 if (p - fs_data != fsDisposeVCB)
499 goto fsdat_error;
500 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
501 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
502 WriteMacInt16(p, 0x7008); p+= 2; // UTDisposeVCB
503 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
504 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
505 WriteMacInt16(p, M68K_RTS); p+= 2;
506 if (p - fs_data != fsCheckWDRefNum)
507 goto fsdat_error;
508 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
509 WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
510 WriteMacInt16(p, 0x7013); p+= 2; // UTCheckWDRefNum
511 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
512 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
513 WriteMacInt16(p, M68K_RTS); p+= 2;
514 if (p - fs_data != fsSetDefaultVol)
515 goto fsdat_error;
516 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
517 WriteMacInt16(p, 0x2f00); p+= 2; // move.l d0,-(sp)
518 WriteMacInt16(p, 0x2f01); p+= 2; // move.l d1,-(sp)
519 WriteMacInt16(p, 0x3f02); p+= 2; // move.w d2,-(sp)
520 WriteMacInt16(p, 0x7011); p+= 2; // UTSetDefaultVol
521 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
522 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
523 WriteMacInt16(p, M68K_RTS); p+= 2;
524 if (p - fs_data != fsAllocateFCB)
525 goto fsdat_error;
526 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
527 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
528 WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(sp)
529 WriteMacInt16(p, 0x7000); p+= 2; // UTAllocateFCB
530 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
531 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
532 WriteMacInt16(p, M68K_RTS); p+= 2;
533 if (p - fs_data != fsReleaseFCB)
534 goto fsdat_error;
535 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
536 WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
537 WriteMacInt16(p, 0x7001); p+= 2; // UTReleaseFCB
538 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
539 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
540 WriteMacInt16(p, M68K_RTS); p+= 2;
541 if (p - fs_data != fsIndexFCB)
542 goto fsdat_error;
543 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
544 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
545 WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(sp)
546 WriteMacInt16(p, 0x2f0a); p+= 2; // move.l a2,-(sp)
547 WriteMacInt16(p, 0x7004); p+= 2; // UTIndexFCB
548 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
549 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
550 WriteMacInt16(p, M68K_RTS); p+= 2;
551 if (p - fs_data != fsResolveFCB)
552 goto fsdat_error;
553 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
554 WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
555 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
556 WriteMacInt16(p, 0x7005); p+= 2; // UTResolveFCB
557 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
558 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
559 WriteMacInt16(p, M68K_RTS); p+= 2;
560 if (p - fs_data != fsAdjustEOF)
561 goto fsdat_error;
562 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
563 WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
564 WriteMacInt16(p, 0x7010); p+= 2; // UTAdjustEOF
565 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
566 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
567 WriteMacInt16(p, M68K_RTS); p+= 2;
568 if (p - fs_data != fsAllocateWDCB)
569 goto fsdat_error;
570 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
571 WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
572 WriteMacInt16(p, 0x700c); p+= 2; // UTAllocateWDCB
573 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
574 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
575 WriteMacInt16(p, M68K_RTS); p+= 2;
576 if (p - fs_data != fsReleaseWDCB)
577 goto fsdat_error;
578 WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
579 WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
580 WriteMacInt16(p, 0x700d); p+= 2; // UTReleaseWDCB
581 WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
582 WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
583 WriteMacInt16(p, M68K_RTS); p+= 2;
584 if (p - fs_data != SIZEOF_fsdat)
585 goto fsdat_error;
586
587 // Set up drive status
588 WriteMacInt8(fs_data + fsDrvStatus + dsDiskInPlace, 8); // Fixed disk
589 WriteMacInt8(fs_data + fsDrvStatus + dsInstalled, 1);
590 WriteMacInt16(fs_data + fsDrvStatus + dsQType, hard20);
591 WriteMacInt16(fs_data + fsDrvStatus + dsDriveSize, num_blocks & 0xffff);
592 WriteMacInt16(fs_data + fsDrvStatus + dsDriveS1, num_blocks >> 16);
593 WriteMacInt16(fs_data + fsDrvStatus + dsQFSID, MY_FSID);
594
595 // Add drive to drive queue
596 drive_number = FindFreeDriveNumber(1);
597 D(bug(" adding drive %d\n", drive_number));
598 r.d[0] = (drive_number << 16) | (DiskRefNum & 0xffff);
599 r.a[0] = fs_data + fsDrvStatus + dsQLink;
600 Execute68kTrap(0xa04e, &r); // AddDrive()
601
602 // Init FSDRec and install file system
603 D(bug(" installing file system\n"));
604 WriteMacInt16(fs_data + fsFSD + fsdLength, SIZEOF_FSDRec);
605 WriteMacInt16(fs_data + fsFSD + fsdVersion, fsdVersion1);
606 WriteMacInt16(fs_data + fsFSD + fileSystemFSID, MY_FSID);
607 memcpy(Mac2HostAddr(fs_data + fsFSD + fileSystemName), FS_NAME, 32);
608 WriteMacInt32(fs_data + fsFSD + fileSystemCommProc, fs_data + fsCommProcStub);
609 WriteMacInt32(fs_data + fsFSD + fsdHFSCI + compInterfProc, fs_data + fsHFSProcStub);
610 WriteMacInt32(fs_data + fsFSD + fsdHFSCI + stackTop, fs_stack + STACK_SIZE);
611 WriteMacInt32(fs_data + fsFSD + fsdHFSCI + stackSize, STACK_SIZE);
612 WriteMacInt32(fs_data + fsFSD + fsdHFSCI + idSector, (uint32)-1);
613 r.a[0] = fs_data + fsFSD;
614 r.d[0] = 0; // InstallFS
615 Execute68kTrap(0xa0ac, &r); // FSMDispatch()
616 D(bug(" InstallFS() returned %d\n", r.d[0]));
617
618 // Enable HFS component
619 D(bug(" enabling HFS component\n"));
620 WriteMacInt32(fs_data + fsFSD + fsdHFSCI + compInterfMask, ReadMacInt32(fs_data + fsFSD + fsdHFSCI + compInterfMask) | (fsmComponentEnableMask | hfsCIResourceLoadedMask | hfsCIDoesHFSMask));
621 r.a[0] = fs_data + fsFSD;
622 r.d[3] = SIZEOF_FSDRec;
623 r.d[4] = MY_FSID;
624 r.d[0] = 5; // SetFSInfo
625 Execute68kTrap(0xa0ac, &r); // FSMDispatch()
626 D(bug(" SetFSInfo() returned %d\n", r.d[0]));
627
628 // Mount volume
629 D(bug(" mounting volume\n"));
630 WriteMacInt32(fs_data + fsPB + ioBuffer, fs_data + fsVMI);
631 WriteMacInt16(fs_data + fsVMI + vmiLength, SIZEOF_VolumeMountInfoHeader);
632 WriteMacInt32(fs_data + fsVMI + vmiMedia, MY_MEDIA_TYPE);
633 r.a[0] = fs_data + fsPB;
634 r.d[0] = 0x41; // PBVolumeMount
635 Execute68kTrap(0xa260, &r); // HFSDispatch()
636 D(bug(" PBVolumeMount() returned %d\n", r.d[0]));
637 return;
638
639 fsdat_error:
640 printf("FATAL: ExtFS data block initialization error\n");
641 QuitEmulator();
642 }
643
644
645 /*
646 * FS communications function
647 */
648
649 int16 ExtFSComm(uint16 message, uint32 paramBlock, uint32 globalsPtr)
650 {
651 D(bug("ExtFSComm(%d, %08lx, %08lx)\n", message, paramBlock, globalsPtr));
652
653 switch (message) {
654 case ffsNopMessage:
655 case ffsLoadMessage:
656 case ffsUnloadMessage:
657 return noErr;
658
659 case ffsGetIconMessage: { // Get disk/drive icon
660 if (ReadMacInt8(paramBlock + iconType) == kLargeIcon && ReadMacInt32(paramBlock + requestSize) >= sizeof(ExtFSIcon)) {
661 memcpy(Mac2HostAddr(ReadMacInt32(paramBlock + iconBufferPtr)), ExtFSIcon, sizeof(ExtFSIcon));
662 WriteMacInt32(paramBlock + actualSize, sizeof(ExtFSIcon));
663 return noErr;
664 } else
665 return -5012; // afpItemNotFound
666 }
667
668 case ffsIDDiskMessage: { // Check if volume is handled by our FS
669 if (ReadMacInt16(paramBlock + ioVRefNum) == drive_number)
670 return noErr;
671 else
672 return extFSErr;
673 }
674
675 case ffsIDVolMountMessage: { // Check if volume can be mounted by our FS
676 if (ReadMacInt32(ReadMacInt32(paramBlock + ioBuffer) + vmiMedia) == MY_MEDIA_TYPE)
677 return noErr;
678 else
679 return extFSErr;
680 }
681
682 default:
683 return fsmUnknownFSMMessageErr;
684 }
685 }
686
687
688 /*
689 * Get current directory specified by given ParamBlock/dirID
690 */
691
692 static int16 get_current_dir(uint32 pb, uint32 dirID, uint32 &current_dir, bool no_vol_name = false)
693 {
694 M68kRegisters r;
695 int16 result;
696
697 // Determine volume
698 D(bug(" determining volume, dirID %d\n", dirID));
699 r.a[0] = pb;
700 r.a[1] = fs_data + fsReturn;
701 r.a[2] = fs_data + fsReturn + 2;
702 r.a[3] = fs_data + fsReturn + 4;
703 r.a[4] = fs_data + fsReturn + 6;
704 uint32 name_ptr = 0;
705 if (no_vol_name) {
706 name_ptr = ReadMacInt32(pb + ioNamePtr);
707 WriteMacInt32(pb + ioNamePtr, 0);
708 }
709 Execute68k(fs_data + fsDetermineVol, &r);
710 if (no_vol_name)
711 WriteMacInt32(pb + ioNamePtr, name_ptr);
712 int16 status = ReadMacInt16(fs_data + fsReturn);
713 int16 more_matches = ReadMacInt16(fs_data + fsReturn + 2);
714 int16 vRefNum = ReadMacInt16(fs_data + fsReturn + 4);
715 uint32 vcb = ReadMacInt32(fs_data + fsReturn + 6);
716 D(bug(" UTDetermineVol() returned %d, status %d\n", r.d[0], status));
717 result = r.d[0] & 0xffff;
718
719 if (result == noErr) {
720 switch (status) {
721 case dtmvFullPathname: // Determined by full pathname
722 current_dir = ROOT_ID;
723 break;
724
725 case dtmvVRefNum: // Determined by refNum or by drive number
726 case dtmvDriveNum:
727 current_dir = dirID ? dirID : ROOT_ID;
728 break;
729
730 case dtmvWDRefNum: // Determined by working directory refNum
731 if (dirID)
732 current_dir = dirID;
733 else {
734 D(bug(" resolving WDCB\n"));
735 r.d[0] = 0;
736 r.d[1] = 0;
737 r.d[2] = ReadMacInt16(pb + ioVRefNum);
738 r.a[0] = fs_data + fsReturn;
739 Execute68k(fs_data + fsResolveWDCB, &r);
740 uint32 wdcb = ReadMacInt32(fs_data + fsReturn);
741 D(bug(" UTResolveWDCB() returned %d, dirID %d\n", r.d[0], ReadMacInt32(wdcb + wdDirID)));
742 result = r.d[0] & 0xffff;
743 if (result == noErr)
744 current_dir = ReadMacInt32(wdcb + wdDirID);
745 }
746 break;
747
748 case dtmvDefault: // Determined by default volume
749 if (dirID)
750 current_dir = dirID;
751 else {
752 uint32 wdpb = fs_data + fsReturn;
753 WriteMacInt32(wdpb + ioNamePtr, 0);
754 D(bug(" getting default volume\n"));
755 r.a[0] = wdpb;
756 Execute68k(fs_data + fsGetDefaultVol, &r);
757 D(bug(" UTGetDefaultVol() returned %d, dirID %d\n", r.d[0], ReadMacInt32(wdpb + ioWDDirID)));
758 result = r.d[0] & 0xffff;
759 if (result == noErr)
760 current_dir = ReadMacInt32(wdpb + ioWDDirID);
761 }
762 break;
763
764 default:
765 result = paramErr;
766 break;
767 }
768 }
769 return result;
770 }
771
772
773 /*
774 * Get path component name
775 */
776
777 static int16 get_path_component_name(uint32 rec)
778 {
779 // D(bug(" getting path component\n"));
780 M68kRegisters r;
781 r.a[0] = rec;
782 Execute68k(fs_data + fsGetPathComponentName, &r);
783 // D(bug(" UTGetPathComponentName returned %d\n", r.d[0]));
784 return r.d[0] & 0xffff;
785 }
786
787
788 /*
789 * Get FSItem and full path (->full_path) for file/dir specified in ParamBlock
790 */
791
792 static int16 get_item_and_path(uint32 pb, uint32 dirID, FSItem *&item, bool no_vol_name = false)
793 {
794 M68kRegisters r;
795
796 // Find FSItem for parent directory
797 int16 result;
798 uint32 current_dir;
799 if ((result = get_current_dir(pb, dirID, current_dir, no_vol_name)) != noErr)
800 return result;
801 D(bug(" current dir %08x\n", current_dir));
802 FSItem *p = find_fsitem_by_id(current_dir);
803 if (p == NULL)
804 return dirNFErr;
805
806 // Start parsing
807 uint32 parseRec = fs_data + fsParseRec;
808 WriteMacInt32(parseRec + ppNamePtr, ReadMacInt32(pb + ioNamePtr));
809 WriteMacInt16(parseRec + ppStartOffset, 0);
810 WriteMacInt16(parseRec + ppComponentLength, 0);
811 WriteMacInt8(parseRec + ppMoreName, false);
812 WriteMacInt8(parseRec + ppFoundDelimiter, false);
813
814 // Get length of volume name
815 D(bug(" parsing pathname\n"));
816 r.a[0] = parseRec + ppStartOffset;
817 r.a[1] = ReadMacInt32(parseRec + ppNamePtr);
818 Execute68k(fs_data + fsParsePathname, &r);
819 D(bug(" UTParsePathname() returned %d, startOffset %d\n", r.d[0], ReadMacInt16(parseRec + ppStartOffset)));
820 result = r.d[0] & 0xffff;
821 if (result == noErr) {
822
823 // Check for leading delimiter of the partial pathname
824 result = get_path_component_name(parseRec);
825 if (result == noErr) {
826 if (ReadMacInt16(parseRec + ppComponentLength) == 0 && ReadMacInt8(parseRec + ppFoundDelimiter)) {
827 // Get past initial delimiter
828 WriteMacInt16(parseRec + ppStartOffset, ReadMacInt16(parseRec + ppStartOffset) + 1);
829 }
830
831 // Parse until there is no more pathname to parse
832 while ((result == noErr) && ReadMacInt8(parseRec + ppMoreName)) {
833
834 // Search for the next delimiter from startOffset
835 result = get_path_component_name(parseRec);
836 if (result == noErr) {
837 if (ReadMacInt16(parseRec + ppComponentLength) == 0) {
838
839 // Delimiter immediately following another delimiter, get parent
840 if (current_dir != ROOT_ID) {
841 p = p->parent;
842 current_dir = p->id;
843 } else
844 result = bdNamErr;
845
846 // startOffset = start of next component
847 WriteMacInt16(parseRec + ppStartOffset, ReadMacInt16(parseRec + ppStartOffset) + 1);
848
849 } else if (ReadMacInt8(parseRec + ppMoreName)) {
850
851 // Component found and isn't the last, so it must be a directory, enter it
852 char name[32];
853 strn2cstr(name, (char *)Mac2HostAddr(ReadMacInt32(parseRec + ppNamePtr)) + ReadMacInt16(parseRec + ppStartOffset) + 1, ReadMacInt16(parseRec + ppComponentLength));
854 D(bug(" entering %s\n", name));
855 p = find_fsitem(name, p);
856 current_dir = p->id;
857
858 // startOffset = start of next component
859 WriteMacInt16(parseRec + ppStartOffset, ReadMacInt16(parseRec + ppStartOffset) + ReadMacInt16(parseRec + ppComponentLength) + 1);
860 }
861 }
862 }
863
864 if (result == noErr) {
865
866 // There is no more pathname to parse
867 if (ReadMacInt16(parseRec + ppComponentLength) == 0) {
868
869 // Pathname ended with '::' or was simply a volume name, so current directory is the object
870 item = p;
871
872 } else {
873
874 // Pathname ended with 'name:' or 'name', so name is the object
875 char name[32];
876 strn2cstr(name, (char *)Mac2HostAddr(ReadMacInt32(parseRec + ppNamePtr)) + ReadMacInt16(parseRec + ppStartOffset) + 1, ReadMacInt16(parseRec + ppComponentLength));
877 D(bug(" object is %s\n", name));
878 item = find_fsitem(name, p);
879 }
880 }
881 }
882
883 } else {
884
885 // Default to bad name
886 result = bdNamErr;
887
888 if (ReadMacInt32(pb + ioNamePtr) == 0 || ReadMacInt8(ReadMacInt32(pb + ioNamePtr)) == 0) {
889
890 // Pathname was NULL or a zero length string, so we found a directory at the end of the string
891 item = p;
892 result = noErr;
893 }
894 }
895
896 // Eat the path
897 if (result == noErr) {
898 get_path_for_fsitem(item);
899 D(bug(" path %s\n", full_path));
900 }
901 return result;
902 }
903
904
905 /*
906 * Find FCB for given file RefNum
907 */
908
909 static uint32 find_fcb(int16 refNum)
910 {
911 D(bug(" finding FCB\n"));
912 M68kRegisters r;
913 r.d[0] = refNum;
914 r.a[0] = fs_data + fsReturn;
915 Execute68k(fs_data + fsResolveFCB, &r);
916 uint32 fcb = ReadMacInt32(fs_data + fsReturn);
917 D(bug(" UTResolveFCB() returned %d, fcb %08lx\n", r.d[0], fcb));
918 if (r.d[0] & 0xffff)
919 return 0;
920 else
921 return fcb;
922 }
923
924
925 /*
926 * HFS interface functions
927 */
928
929 // Check if volume belongs to our FS
930 static int16 fs_mount_vol(uint32 pb)
931 {
932 D(bug(" fs_mount_vol(%08lx), vRefNum %d\n", pb, ReadMacInt16(pb + ioVRefNum)));
933 if (ReadMacInt16(pb + ioVRefNum) == drive_number)
934 return noErr;
935 else
936 return extFSErr;
937 }
938
939 // Mount volume
940 static int16 fs_volume_mount(uint32 pb)
941 {
942 D(bug(" fs_volume_mount(%08lx)\n", pb));
943 M68kRegisters r;
944
945 // Create new VCB
946 D(bug(" creating VCB\n"));
947 r.a[0] = fs_data + fsReturn;
948 r.a[1] = fs_data + fsReturn + 2;
949 Execute68k(fs_data + fsAllocateVCB, &r);
950 uint16 sysVCBLength = ReadMacInt16(fs_data + fsReturn);
951 uint32 vcb = ReadMacInt32(fs_data + fsReturn + 2);
952 D(bug(" UTAllocateVCB() returned %d, vcb %08lx, size %d\n", r.d[0], vcb, sysVCBLength));
953 if (r.d[0] & 0xffff)
954 return r.d[0];
955
956 // Init VCB
957 WriteMacInt16(vcb + vcbSigWord, 0x4244);
958 #ifdef __BEOS__
959 WriteMacInt32(vcb + vcbCrDate, root_stat.st_crtime + TIME_OFFSET);
960 #else
961 WriteMacInt32(vcb + vcbCrDate, 0);
962 #endif
963 WriteMacInt32(vcb + vcbLsMod, root_stat.st_mtime + TIME_OFFSET);
964 WriteMacInt32(vcb + vcbVolBkUp, 0);
965 WriteMacInt16(vcb + vcbNmFls, 1); //!!
966 WriteMacInt16(vcb + vcbNmRtDirs, 1); //!!
967 WriteMacInt16(vcb + vcbNmAlBlks, 0xffff); //!!
968 WriteMacInt32(vcb + vcbAlBlkSiz, 1024);
969 WriteMacInt32(vcb + vcbClpSiz, 1024);
970 WriteMacInt32(vcb + vcbNxtCNID, next_cnid);
971 WriteMacInt16(vcb + vcbFreeBks, 0xffff); //!!
972 memcpy(Mac2HostAddr(vcb + vcbVN), VOLUME_NAME, 28);
973 WriteMacInt16(vcb + vcbFSID, MY_FSID);
974 WriteMacInt32(vcb + vcbFilCnt, 1); //!!
975 WriteMacInt32(vcb + vcbDirCnt, 1); //!!
976
977 // Add VCB to VCB queue
978 D(bug(" adding VCB to queue\n"));
979 r.d[0] = drive_number;
980 r.a[0] = fs_data + fsReturn;
981 r.a[1] = vcb;
982 Execute68k(fs_data + fsAddNewVCB, &r);
983 int16 vRefNum = ReadMacInt32(fs_data + fsReturn);
984 D(bug(" UTAddNewVCB() returned %d, vRefNum %d\n", r.d[0], vRefNum));
985 if (r.d[0] & 0xffff)
986 return r.d[0];
987
988 // Post diskInsertEvent
989 D(bug(" posting diskInsertEvent\n"));
990 r.d[0] = drive_number;
991 r.a[0] = 7; // diskEvent
992 Execute68kTrap(0xa02f, &r); // PostEvent()
993
994 // Return volume RefNum
995 WriteMacInt16(pb + ioVRefNum, vRefNum);
996 return noErr;
997 }
998
999 // Unmount volume
1000 static int16 fs_unmount_vol(uint32 vcb)
1001 {
1002 D(bug(" fs_unmount_vol(%08lx), vRefNum %d\n", vcb, ReadMacInt16(vcb + vcbVRefNum)));
1003 M68kRegisters r;
1004
1005 // Remove and free VCB
1006 D(bug(" freeing VCB\n"));
1007 r.a[0] = vcb;
1008 Execute68k(fs_data + fsDisposeVCB, &r);
1009 D(bug(" UTDisposeVCB() returned %d\n", r.d[0]));
1010 return r.d[0];
1011 }
1012
1013 // Get information about a volume (HVolumeParam)
1014 static int16 fs_get_vol_info(uint32 pb, bool hfs)
1015 {
1016 // D(bug(" fs_get_vol_info(%08lx)\n", pb));
1017
1018 // Fill in struct
1019 if (ReadMacInt32(pb + ioNamePtr))
1020 pstrcpy((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), VOLUME_NAME);
1021 #ifdef __BEOS__
1022 WriteMacInt32(pb + ioVCrDate, root_stat.st_crtime + TIME_OFFSET);
1023 #else
1024 WriteMacInt32(pb + ioVCrDate, 0);
1025 #endif
1026 WriteMacInt32(pb + ioVLsMod, root_stat.st_mtime + TIME_OFFSET);
1027 WriteMacInt16(pb + ioVAtrb, 0);
1028 WriteMacInt16(pb + ioVNmFls, 1); //!!
1029 WriteMacInt16(pb + ioVBitMap, 0);
1030 WriteMacInt16(pb + ioAllocPtr, 0);
1031 WriteMacInt16(pb + ioVNmAlBlks, 0xffff); //!!
1032 WriteMacInt32(pb + ioVAlBlkSiz, 1024);
1033 WriteMacInt32(pb + ioVClpSiz, 1024);
1034 WriteMacInt16(pb + ioAlBlSt, 0);
1035 WriteMacInt32(pb + ioVNxtCNID, next_cnid);
1036 WriteMacInt16(pb + ioVFrBlk, 0xffff); //!!
1037 if (hfs) {
1038 WriteMacInt16(pb + ioVDrvInfo, drive_number);
1039 WriteMacInt16(pb + ioVDRefNum, ReadMacInt16(fs_data + fsDrvStatus + dsQRefNum));
1040 WriteMacInt16(pb + ioVFSID, MY_FSID);
1041 WriteMacInt32(pb + ioVBkUp, 0);
1042 WriteMacInt16(pb + ioVSeqNum, 0);
1043 WriteMacInt32(pb + ioVWrCnt, 0);
1044 WriteMacInt32(pb + ioVFilCnt, 1); //!!
1045 WriteMacInt32(pb + ioVDirCnt, 1); //!!
1046 memset(Mac2HostAddr(pb + ioVFndrInfo), 0, 32);
1047 }
1048 return noErr;
1049 }
1050
1051 // Change volume information (HVolumeParam)
1052 static int16 fs_set_vol_info(uint32 pb)
1053 {
1054 D(bug(" fs_set_vol_info(%08lx)\n", pb));
1055
1056 //!! times
1057 return noErr;
1058 }
1059
1060 // Get volume parameter block
1061 static int16 fs_get_vol_parms(uint32 pb)
1062 {
1063 // D(bug(" fs_get_vol_parms(%08lx)\n", pb));
1064
1065 // Return parameter block
1066 uint8 vol[SIZEOF_GetVolParmsInfoBuffer];
1067 WriteMacInt16((uint32)vol + vMVersion, 2);
1068 WriteMacInt32((uint32)vol + vMAttrib, kNoMiniFndr | kNoVNEdit | kNoLclSync | kTrshOffLine | kNoSwitchTo | kNoBootBlks | kNoSysDir | kHasExtFSVol);
1069 WriteMacInt32((uint32)vol + vMLocalHand, 0);
1070 WriteMacInt32((uint32)vol + vMServerAdr, 0);
1071 WriteMacInt32((uint32)vol + vMVolumeGrade, 0);
1072 WriteMacInt16((uint32)vol + vMForeignPrivID, 0);
1073 uint32 actual = ReadMacInt32(pb + ioReqCount);
1074 if (actual > sizeof(vol))
1075 actual = sizeof(vol);
1076 memcpy(Mac2HostAddr(ReadMacInt32(pb + ioBuffer)), vol, actual);
1077 WriteMacInt32(pb + ioActCount, actual);
1078 return noErr;
1079 }
1080
1081 // Get default volume (WDParam)
1082 static int16 fs_get_vol(uint32 pb)
1083 {
1084 D(bug(" fs_get_vol(%08lx)\n", pb));
1085 M68kRegisters r;
1086
1087 // Getting default volume
1088 D(bug(" getting default volume\n"));
1089 r.a[0] = pb;
1090 Execute68k(fs_data + fsGetDefaultVol, &r);
1091 D(bug(" UTGetDefaultVol() returned %d\n", r.d[0]));
1092 return r.d[0];
1093 }
1094
1095 // Set default volume (WDParam)
1096 static int16 fs_set_vol(uint32 pb, bool hfs, uint32 vcb)
1097 {
1098 D(bug(" fs_set_vol(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt32(pb + ioWDDirID)));
1099 M68kRegisters r;
1100
1101 // Determine parameters
1102 uint32 dirID;
1103 int16 refNum;
1104 if (hfs) {
1105
1106 // Find FSItem for given dir
1107 FSItem *fs_item;
1108 int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioWDDirID), fs_item);
1109 if (result != noErr)
1110 return result;
1111
1112 // Is it a directory?
1113 struct stat st;
1114 if (stat(full_path, &st))
1115 return dirNFErr;
1116 if (!S_ISDIR(st.st_mode))
1117 return dirNFErr;
1118
1119 // Get dirID and refNum
1120 dirID = fs_item->id;
1121 refNum = ReadMacInt16(vcb + vcbVRefNum);
1122
1123 } else {
1124
1125 // Is the given vRefNum a working directory number?
1126 D(bug(" checking for WDRefNum\n"));
1127 r.d[0] = ReadMacInt16(pb + ioVRefNum);
1128 Execute68k(fs_data + fsCheckWDRefNum, &r);
1129 D(bug(" UTCheckWDRefNum() returned %d\n", r.d[0]));
1130 if (r.d[0] & 0xffff) {
1131 // Volume refNum
1132 dirID = ROOT_ID;
1133 refNum = ReadMacInt16(vcb + vcbVRefNum);
1134 } else {
1135 // WD refNum
1136 dirID = 0;
1137 refNum = ReadMacInt16(pb + ioVRefNum);
1138 }
1139 }
1140
1141 // Setting default volume
1142 D(bug(" setting default volume\n"));
1143 r.d[0] = 0;
1144 r.d[1] = dirID;
1145 r.d[2] = refNum;
1146 Execute68k(fs_data + fsSetDefaultVol, &r);
1147 D(bug(" UTSetDefaultVol() returned %d\n", r.d[0]));
1148 return r.d[0];
1149 }
1150
1151 // Query file attributes (HFileParam)
1152 static int16 fs_get_file_info(uint32 pb, bool hfs, uint32 dirID)
1153 {
1154 D(bug(" fs_get_file_info(%08lx), vRefNum %d, name %.31s, idx %d, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt16(pb + ioFDirIndex), dirID));
1155
1156 FSItem *fs_item;
1157 int16 dir_index = ReadMacInt16(pb + ioFDirIndex);
1158 if (dir_index <= 0) { // Query item specified by ioDirID and ioNamePtr
1159
1160 // Find FSItem for given file
1161 int16 result = get_item_and_path(pb, dirID, fs_item);
1162 if (result != noErr)
1163 return result;
1164
1165 } else { // Query item in directory specified by ioDirID by index
1166
1167 // Find FSItem for parent directory
1168 int16 result;
1169 uint32 current_dir;
1170 if ((result = get_current_dir(pb, dirID, current_dir, true)) != noErr)
1171 return result;
1172 FSItem *p = find_fsitem_by_id(current_dir);
1173 if (p == NULL)
1174 return dirNFErr;
1175 get_path_for_fsitem(p);
1176
1177 // Look for nth item in directory and add name to path
1178 DIR *d = opendir(full_path);
1179 if (d == NULL)
1180 return dirNFErr;
1181 struct dirent *de = NULL;
1182 for (int i=0; i<dir_index; i++) {
1183 read_next_de:
1184 de = readdir(d);
1185 if (de == NULL) {
1186 closedir(d);
1187 return fnfErr;
1188 }
1189 if (de->d_name[0] == '.')
1190 goto read_next_de; // Suppress name beginning with '.' (MacOS could interpret these as driver names)
1191 //!! suppress directories
1192 }
1193 add_path_comp(de->d_name);
1194
1195 // Get FSItem for queried item
1196 fs_item = find_fsitem(de->d_name, p);
1197 closedir(d);
1198 }
1199
1200 // Get stats
1201 struct stat st;
1202 if (stat(full_path, &st))
1203 return fnfErr;
1204 if (S_ISDIR(st.st_mode))
1205 return fnfErr;
1206
1207 // Fill in struct from fs_item and stats
1208 if (ReadMacInt32(pb + ioNamePtr))
1209 cstr2pstr((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), fs_item->name);
1210 WriteMacInt16(pb + ioFRefNum, 0);
1211 WriteMacInt8(pb + ioFlAttrib, access(full_path, W_OK) == 0 ? 0 : faLocked);
1212 WriteMacInt32(pb + ioDirID, fs_item->id);
1213
1214 #ifdef __BEOS__
1215 WriteMacInt32(pb + ioFlCrDat, st.st_crtime + TIME_OFFSET);
1216 #else
1217 WriteMacInt32(pb + ioFlCrDat, 0);
1218 #endif
1219 WriteMacInt32(pb + ioFlMdDat, st.st_mtime + TIME_OFFSET);
1220
1221 memset(Mac2HostAddr(pb + ioFlFndrInfo), 0, SIZEOF_FInfo);
1222 uint32 type, creator; // pb may point to kernel space, but stack is switched
1223 get_finder_type(full_path, type, creator);
1224 WriteMacInt32(pb + ioFlFndrInfo + fdType, type);
1225 WriteMacInt32(pb + ioFlFndrInfo + fdCreator, creator);
1226 uint16 fflags;
1227 get_finder_flags(full_path, fflags);
1228 WriteMacInt16(pb + ioFlFndrInfo + fdFlags, fflags);
1229
1230 WriteMacInt16(pb + ioFlStBlk, 0);
1231 WriteMacInt32(pb + ioFlLgLen, st.st_size);
1232 WriteMacInt32(pb + ioFlPyLen, (st.st_size + 1023) & ~1023);
1233 WriteMacInt16(pb + ioFlRStBlk, 0);
1234 uint32 rf_size = get_rfork_size(full_path);
1235 WriteMacInt32(pb + ioFlRLgLen, rf_size);
1236 WriteMacInt32(pb + ioFlRPyLen, (rf_size + 1023) & ~1023);
1237
1238 if (hfs) {
1239 WriteMacInt32(pb + ioFlBkDat, 0);
1240 memset(Mac2HostAddr(pb + ioFlXFndrInfo), 0, SIZEOF_FXInfo);
1241 WriteMacInt32(pb + ioFlParID, fs_item->parent_id);
1242 WriteMacInt32(pb + ioFlClpSiz, 0);
1243 }
1244 return noErr;
1245 }
1246
1247 // Set file attributes (HFileParam)
1248 static int16 fs_set_file_info(uint32 pb, bool hfs, uint32 dirID)
1249 {
1250 D(bug(" fs_set_file_info(%08lx), vRefNum %d, name %.31s, idx %d, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt16(pb + ioFDirIndex), dirID));
1251
1252 // Find FSItem for given file/dir
1253 FSItem *fs_item;
1254 int16 result = get_item_and_path(pb, dirID, fs_item);
1255 if (result != noErr)
1256 return result;
1257
1258 // Get stats
1259 struct stat st;
1260 if (stat(full_path, &st) < 0)
1261 return errno2oserr();
1262 if (S_ISDIR(st.st_mode))
1263 return fnfErr;
1264
1265 // Set attributes
1266 set_finder_type(full_path, ReadMacInt32(pb + ioFlFndrInfo + fdType), ReadMacInt32(pb + ioFlFndrInfo + fdCreator));
1267 set_finder_flags(full_path, ReadMacInt16(pb + ioFlFndrInfo + fdFlags));
1268 //!! times
1269 return noErr;
1270 }
1271
1272 // Query file/directory attributes
1273 static int16 fs_get_cat_info(uint32 pb)
1274 {
1275 D(bug(" fs_get_cat_info(%08lx), vRefNum %d, name %.31s, idx %d, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt16(pb + ioFDirIndex), ReadMacInt32(pb + ioDirID)));
1276
1277 FSItem *fs_item;
1278 int16 dir_index = ReadMacInt16(pb + ioFDirIndex);
1279 if (dir_index < 0) { // Query directory specified by ioDirID
1280
1281 // Find FSItem for directory
1282 fs_item = find_fsitem_by_id(ReadMacInt32(pb + ioDrDirID));
1283 if (fs_item == NULL)
1284 return dirNFErr;
1285 get_path_for_fsitem(fs_item);
1286
1287 } else if (dir_index == 0) { // Query item specified by ioDirID and ioNamePtr
1288
1289 // Find FSItem for given file/dir
1290 int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1291 if (result != noErr)
1292 return result;
1293
1294 } else { // Query item in directory specified by ioDirID by index
1295
1296 // Find FSItem for parent directory
1297 int16 result;
1298 uint32 current_dir;
1299 if ((result = get_current_dir(pb, ReadMacInt32(pb + ioDirID), current_dir, true)) != noErr)
1300 return result;
1301 FSItem *p = find_fsitem_by_id(current_dir);
1302 if (p == NULL)
1303 return dirNFErr;
1304 get_path_for_fsitem(p);
1305
1306 // Look for nth item in directory and add name to path
1307 DIR *d = opendir(full_path);
1308 if (d == NULL)
1309 return dirNFErr;
1310 struct dirent *de = NULL;
1311 for (int i=0; i<dir_index; i++) {
1312 read_next_de:
1313 de = readdir(d);
1314 if (de == NULL) {
1315 closedir(d);
1316 return fnfErr;
1317 }
1318 if (de->d_name[0] == '.')
1319 goto read_next_de; // Suppress name beginning with '.' (MacOS could interpret these as driver names)
1320 }
1321 add_path_comp(de->d_name);
1322
1323 // Get FSItem for queried item
1324 fs_item = find_fsitem(de->d_name, p);
1325 closedir(d);
1326 }
1327 D(bug(" path %s\n", full_path));
1328
1329 // Get stats
1330 struct stat st;
1331 if (stat(full_path, &st) < 0)
1332 return errno2oserr();
1333 if (dir_index == -1 && !S_ISDIR(st.st_mode))
1334 return dirNFErr;
1335
1336 // Fill in struct from fs_item and stats
1337 if (ReadMacInt32(pb + ioNamePtr))
1338 cstr2pstr((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), fs_item->name);
1339 WriteMacInt16(pb + ioFRefNum, 0);
1340 WriteMacInt8(pb + ioFlAttrib, (S_ISDIR(st.st_mode) ? faIsDir : 0) | (access(full_path, W_OK) == 0 ? 0 : faLocked));
1341 WriteMacInt8(pb + ioACUser, 0);
1342 WriteMacInt32(pb + ioDirID, fs_item->id);
1343 WriteMacInt32(pb + ioFlParID, fs_item->parent_id);
1344 #ifdef __BEOS__
1345 WriteMacInt32(pb + ioFlCrDat, st.st_crtime + TIME_OFFSET);
1346 #else
1347 WriteMacInt32(pb + ioFlCrDat, 0);
1348 #endif
1349 time_t mtime = st.st_mtime;
1350 bool cached = true;
1351 if (mtime > fs_item->mtime) {
1352 fs_item->mtime = mtime;
1353 cached = false;
1354 }
1355 WriteMacInt32(pb + ioFlMdDat, mtime);
1356 WriteMacInt32(pb + ioFlBkDat, 0);
1357 if (S_ISDIR(st.st_mode)) {
1358 memset(Mac2HostAddr(pb + ioDrUsrWds), 0, SIZEOF_DInfo);
1359 memset(Mac2HostAddr(pb + ioDrFndrInfo), 0, SIZEOF_DXInfo);
1360 uint16 fflags; // pb may point to kernel space, but stack is switched
1361 get_finder_flags(full_path, fflags);
1362 WriteMacInt16(pb + ioDrUsrWds + frFlags, fflags);
1363
1364 // Determine number of files in directory (cached)
1365 int count;
1366 if (cached)
1367 count = fs_item->cache_dircount;
1368 else {
1369 count = 0;
1370 DIR *d = opendir(full_path);
1371 if (d) {
1372 struct dirent *de;
1373 for (;;) {
1374 de = readdir(d);
1375 if (de == NULL)
1376 break;
1377 count++;
1378 }
1379 closedir(d);
1380 }
1381 fs_item->cache_dircount = count;
1382 }
1383 WriteMacInt16(pb + ioDrNmFls, count);
1384 } else {
1385 memset(Mac2HostAddr(pb + ioFlFndrInfo), 0, SIZEOF_FInfo);
1386 memset(Mac2HostAddr(pb + ioFlXFndrInfo), 0, SIZEOF_FXInfo);
1387 uint32 type, creator; // pb may point to kernel space, but stack is switched
1388 get_finder_type(full_path, type, creator);
1389 WriteMacInt32(pb + ioFlFndrInfo + fdType, type);
1390 WriteMacInt32(pb + ioFlFndrInfo + fdCreator, creator);
1391 uint16 fflags;
1392 get_finder_flags(full_path, fflags);
1393 WriteMacInt16(pb + ioFlFndrInfo + fdFlags, fflags);
1394 WriteMacInt16(pb + ioFlStBlk, 0);
1395 WriteMacInt32(pb + ioFlLgLen, st.st_size);
1396 WriteMacInt32(pb + ioFlPyLen, (st.st_size + 1023) & ~1023);
1397 WriteMacInt16(pb + ioFlRStBlk, 0);
1398 uint32 rf_size = get_rfork_size(full_path);
1399 WriteMacInt32(pb + ioFlRLgLen, rf_size);
1400 WriteMacInt32(pb + ioFlRPyLen, (rf_size + 1023) & ~1023);
1401 WriteMacInt32(pb + ioFlClpSiz, 0);
1402 }
1403 return noErr;
1404 }
1405
1406 // Set file/directory attributes
1407 static int16 fs_set_cat_info(uint32 pb)
1408 {
1409 D(bug(" fs_set_cat_info(%08lx), vRefNum %d, name %.31s, idx %d, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt16(pb + ioFDirIndex), ReadMacInt32(pb + ioDirID)));
1410
1411 // Find FSItem for given file/dir
1412 FSItem *fs_item;
1413 int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1414 if (result != noErr)
1415 return result;
1416
1417 // Get stats
1418 struct stat st;
1419 if (stat(full_path, &st) < 0)
1420 return errno2oserr();
1421
1422 // Set attributes
1423 if (S_ISDIR(st.st_mode))
1424 set_finder_flags(full_path, ReadMacInt16(pb + ioDrUsrWds + frFlags));
1425 else {
1426 set_finder_type(full_path, ReadMacInt32(pb + ioFlFndrInfo + fdType), ReadMacInt32(pb + ioFlFndrInfo + fdCreator));
1427 set_finder_flags(full_path, ReadMacInt16(pb + ioFlFndrInfo + fdFlags));
1428 }
1429 //!! times
1430 return noErr;
1431 }
1432
1433 // Open file
1434 static int16 fs_open(uint32 pb, uint32 dirID, uint32 vcb, bool resource_fork)
1435 {
1436 D(bug(" fs_open(%08lx), %s, vRefNum %d, name %.31s, dirID %d, perm %d\n", pb, resource_fork ? "rsrc" : "data", ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), dirID, ReadMacInt8(pb + ioPermssn)));
1437 M68kRegisters r;
1438
1439 // Find FSItem for given file
1440 FSItem *fs_item;
1441 int16 result = get_item_and_path(pb, dirID, fs_item);
1442 if (result != noErr)
1443 return result;
1444
1445 // Convert ioPermssn to open() flag
1446 int flag = 0;
1447 bool write_ok = (access(full_path, W_OK) == 0);
1448 switch (ReadMacInt8(pb + ioPermssn)) {
1449 case fsCurPerm: // Whatever is currently allowed
1450 if (write_ok)
1451 flag = O_RDWR;
1452 else
1453 flag = O_RDONLY;
1454 break;
1455 case fsRdPerm: // Exclusive read
1456 flag = O_RDONLY;
1457 break;
1458 case fsWrPerm: // Exclusive write
1459 flag = O_WRONLY;
1460 break;
1461 case fsRdWrPerm: // Exclusive read/write
1462 case fsRdWrShPerm: // Shared read/write
1463 default:
1464 flag = O_RDWR;
1465 break;
1466 }
1467
1468 // Try to open and stat the file
1469 int fd = -1;
1470 struct stat st;
1471 if (resource_fork) {
1472 if (access(full_path, F_OK))
1473 return fnfErr;
1474 fd = open_rfork(full_path, flag);
1475 if (fd > 0) {
1476 if (fstat(fd, &st) < 0)
1477 return errno2oserr();
1478 } else { // Resource fork not supported, silently ignore it ("pseudo" resource fork)
1479 st.st_size = 0;
1480 st.st_mode = 0;
1481 }
1482 } else {
1483 fd = open(full_path, flag);
1484 if (fd < 0)
1485 return errno2oserr();
1486 if (fstat(fd, &st) < 0)
1487 return errno2oserr();
1488 }
1489
1490 // File open, allocate FCB
1491 D(bug(" allocating FCB\n"));
1492 r.a[0] = pb + ioRefNum;
1493 r.a[1] = fs_data + fsReturn;
1494 Execute68k(fs_data + fsAllocateFCB, &r);
1495 uint32 fcb = ReadMacInt32(fs_data + fsReturn);
1496 D(bug(" UTAllocateFCB() returned %d, fRefNum %d, fcb %08lx\n", r.d[0], ReadMacInt16(pb + ioRefNum), fcb));
1497 if (r.d[0] & 0xffff) {
1498 close(fd);
1499 return r.d[0];
1500 }
1501
1502 // Initialize FCB, fd is stored in fcbCatPos
1503 WriteMacInt32(fcb + fcbFlNm, fs_item->id);
1504 WriteMacInt8(fcb + fcbFlags, ((flag == O_WRONLY || flag == O_RDWR) ? fcbWriteMask : 0) | (resource_fork ? fcbResourceMask : 0) | (write_ok ? 0 : fcbFileLockedMask));
1505 WriteMacInt32(fcb + fcbEOF, st.st_size);
1506 WriteMacInt32(fcb + fcbPLen, (st.st_size + 1023) & ~1023);
1507 WriteMacInt32(fcb + fcbCrPs, 0);
1508 WriteMacInt32(fcb + fcbVPtr, vcb);
1509 WriteMacInt32(fcb + fcbClmpSize, 1024);
1510 uint32 type, creator; // fcb may point to kernel space, but stack is switched
1511 get_finder_type(full_path, type, creator);
1512 WriteMacInt32(fcb + fcbFType, type);
1513 WriteMacInt32(fcb + fcbCatPos, fd);
1514 WriteMacInt32(fcb + fcbDirID, fs_item->parent_id);
1515 cstr2pstr((char *)Mac2HostAddr(fcb + fcbCName), fs_item->name);
1516 return noErr;
1517 }
1518
1519 // Close file
1520 static int16 fs_close(uint32 pb)
1521 {
1522 D(bug(" fs_close(%08lx), refNum %d\n", pb, ReadMacInt16(pb + ioRefNum)));
1523 M68kRegisters r;
1524
1525 // Find FCB and fd for file
1526 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1527 if (fcb == 0)
1528 return rfNumErr;
1529 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1530 return fnOpnErr;
1531 int fd = ReadMacInt32(fcb + fcbCatPos);
1532
1533 // Close file
1534 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) {
1535 FSItem *item = find_fsitem_by_id(ReadMacInt32(fcb + fcbFlNm));
1536 if (item) {
1537 get_path_for_fsitem(item);
1538 close_rfork(full_path, fd);
1539 }
1540 } else
1541 close(fd);
1542 WriteMacInt32(fcb + fcbCatPos, (uint32)-1);
1543
1544 // Release FCB
1545 D(bug(" releasing FCB\n"));
1546 r.d[0] = ReadMacInt16(pb + ioRefNum);
1547 Execute68k(fs_data + fsReleaseFCB, &r);
1548 D(bug(" UTReleaseFCB() returned %d\n", r.d[0]));
1549 return r.d[0];
1550 }
1551
1552 // Query information about FCB (FCBPBRec)
1553 static int16 fs_get_fcb_info(uint32 pb, uint32 vcb)
1554 {
1555 D(bug(" fs_get_fcb_info(%08lx), vRefNum %d, refNum %d, idx %d\n", pb, ReadMacInt16(pb + ioVRefNum), ReadMacInt16(pb + ioRefNum), ReadMacInt16(pb + ioFCBIndx)));
1556 M68kRegisters r;
1557
1558 uint32 fcb = 0;
1559 if (ReadMacInt16(pb + ioFCBIndx) == 0) { // Get information about single file
1560
1561 // Find FCB for file
1562 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1563
1564 } else { // Get information about file specified by index
1565
1566 // Find FCB by index
1567 WriteMacInt16(pb + ioRefNum, 0);
1568 for (int i=0; i<ReadMacInt16(pb + ioFCBIndx); i++) {
1569 D(bug(" indexing FCBs\n"));
1570 r.a[0] = vcb;
1571 r.a[1] = pb + ioRefNum;
1572 r.a[2] = fs_data + fsReturn;
1573 Execute68k(fs_data + fsIndexFCB, &r);
1574 fcb = ReadMacInt32(fs_data + fsReturn);
1575 D(bug(" UTIndexFCB() returned %d, fcb %p\n", r.d[0], fcb));
1576 if (r.d[0] & 0xffff)
1577 return r.d[0];
1578 }
1579 }
1580 if (fcb == 0)
1581 return rfNumErr;
1582
1583 // Copy information from FCB
1584 if (ReadMacInt32(pb + ioNamePtr))
1585 pstrcpy((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), (char *)Mac2HostAddr(fcb + fcbCName));
1586 WriteMacInt32(pb + ioFCBFlNm, ReadMacInt32(fcb + fcbFlNm));
1587 WriteMacInt8(pb + ioFCBFlags, ReadMacInt8(fcb + fcbFlags));
1588 WriteMacInt16(pb + ioFCBStBlk, ReadMacInt16(fcb + fcbSBlk));
1589 WriteMacInt32(pb + ioFCBEOF, ReadMacInt32(fcb + fcbEOF));
1590 WriteMacInt32(pb + ioFCBPLen, ReadMacInt32(fcb + fcbPLen));
1591 WriteMacInt32(pb + ioFCBCrPs, ReadMacInt32(fcb + fcbCrPs));
1592 WriteMacInt16(pb + ioFCBVRefNum, ReadMacInt16(ReadMacInt32(fcb + fcbVPtr) + vcbVRefNum));
1593 WriteMacInt32(pb + ioFCBClpSiz, ReadMacInt32(fcb + fcbClmpSize));
1594 WriteMacInt32(pb + ioFCBParID, ReadMacInt32(fcb + fcbDirID));
1595 return noErr;
1596 }
1597
1598 // Obtain logical size of an open file
1599 static int16 fs_get_eof(uint32 pb)
1600 {
1601 D(bug(" fs_get_eof(%08lx), refNum %d\n", pb, ReadMacInt16(pb + ioRefNum)));
1602 M68kRegisters r;
1603
1604 // Find FCB and fd for file
1605 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1606 if (fcb == 0)
1607 return rfNumErr;
1608 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1609 return fnOpnErr;
1610 int fd = ReadMacInt32(fcb + fcbCatPos);
1611 if (fd < 0)
1612 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1613 WriteMacInt32(pb + ioMisc, 0);
1614 return noErr;
1615 } else
1616 return fnOpnErr;
1617
1618 // Get file size
1619 struct stat st;
1620 if (fstat(fd, &st) < 0)
1621 return errno2oserr();
1622
1623 // Adjust FCBs
1624 WriteMacInt32(fcb + fcbEOF, st.st_size);
1625 WriteMacInt32(fcb + fcbPLen, (st.st_size + 1023) & ~1023);
1626 WriteMacInt32(pb + ioMisc, st.st_size);
1627 D(bug(" adjusting FCBs\n"));
1628 r.d[0] = ReadMacInt16(pb + ioRefNum);
1629 Execute68k(fs_data + fsAdjustEOF, &r);
1630 D(bug(" UTAdjustEOF() returned %d\n", r.d[0]));
1631 return noErr;
1632 }
1633
1634 // Truncate file
1635 static int16 fs_set_eof(uint32 pb)
1636 {
1637 D(bug(" fs_set_eof(%08lx), refNum %d, size %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt32(pb + ioMisc)));
1638 M68kRegisters r;
1639
1640 // Find FCB and fd for file
1641 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1642 if (fcb == 0)
1643 return rfNumErr;
1644 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1645 return fnOpnErr;
1646 int fd = ReadMacInt32(fcb + fcbCatPos);
1647 if (fd < 0)
1648 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) // "pseudo" resource fork
1649 return noErr;
1650 else
1651 return fnOpnErr;
1652
1653 // Truncate file
1654 uint32 size = ReadMacInt32(pb + ioMisc);
1655 if (ftruncate(fd, size) < 0)
1656 return errno2oserr();
1657
1658 // Adjust FCBs
1659 WriteMacInt32(fcb + fcbEOF, size);
1660 WriteMacInt32(fcb + fcbPLen, (size + 1023) & ~1023);
1661 D(bug(" adjusting FCBs\n"));
1662 r.d[0] = ReadMacInt16(pb + ioRefNum);
1663 Execute68k(fs_data + fsAdjustEOF, &r);
1664 D(bug(" UTAdjustEOF() returned %d\n", r.d[0]));
1665 return noErr;
1666 }
1667
1668 // Query current file position
1669 static int16 fs_get_fpos(uint32 pb)
1670 {
1671 D(bug(" fs_get_fpos(%08lx), refNum %d\n", pb, ReadMacInt16(pb + ioRefNum)));
1672
1673 WriteMacInt32(pb + ioReqCount, 0);
1674 WriteMacInt32(pb + ioActCount, 0);
1675 WriteMacInt16(pb + ioPosMode, 0);
1676
1677 // Find FCB and fd for file
1678 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1679 if (fcb == 0)
1680 return rfNumErr;
1681 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1682 return fnOpnErr;
1683 int fd = ReadMacInt32(fcb + fcbCatPos);
1684 if (fd < 0)
1685 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1686 WriteMacInt32(pb + ioPosOffset, 0);
1687 return noErr;
1688 } else
1689 return fnOpnErr;
1690
1691 // Get file position
1692 uint32 pos = lseek(fd, 0, SEEK_CUR);
1693 WriteMacInt32(fcb + fcbCrPs, pos);
1694 WriteMacInt32(pb + ioPosOffset, pos);
1695 return noErr;
1696 }
1697
1698 // Set current file position
1699 static int16 fs_set_fpos(uint32 pb)
1700 {
1701 D(bug(" fs_set_fpos(%08lx), refNum %d, posMode %d, offset %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt16(pb + ioPosMode), ReadMacInt32(pb + ioPosOffset)));
1702
1703 // Find FCB and fd for file
1704 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1705 if (fcb == 0)
1706 return rfNumErr;
1707 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1708 return fnOpnErr;
1709 int fd = ReadMacInt32(fcb + fcbCatPos);
1710 if (fd < 0)
1711 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1712 WriteMacInt32(pb + ioPosOffset, 0);
1713 return noErr;
1714 } else
1715 return fnOpnErr;
1716
1717 // Set file position
1718 switch (ReadMacInt16(pb + ioPosMode)) {
1719 case fsFromStart:
1720 if (lseek(fd, ReadMacInt32(pb + ioPosOffset), SEEK_SET) < 0)
1721 return posErr;
1722 break;
1723 case fsFromLEOF:
1724 if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_END) < 0)
1725 return posErr;
1726 break;
1727 case fsFromMark:
1728 if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_CUR) < 0)
1729 return posErr;
1730 break;
1731 default:
1732 break;
1733 }
1734 uint32 pos = lseek(fd, 0, SEEK_CUR);
1735 WriteMacInt32(fcb + fcbCrPs, pos);
1736 WriteMacInt32(pb + ioPosOffset, pos);
1737 return noErr;
1738 }
1739
1740 // Read from file
1741 static int16 fs_read(uint32 pb)
1742 {
1743 D(bug(" fs_read(%08lx), refNum %d, buffer %p, count %d, posMode %d, posOffset %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt32(pb + ioBuffer), ReadMacInt32(pb + ioReqCount), ReadMacInt16(pb + ioPosMode), ReadMacInt32(pb + ioPosOffset)));
1744
1745 // Find FCB and fd for file
1746 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1747 if (fcb == 0)
1748 return rfNumErr;
1749 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1750 return fnOpnErr;
1751 int fd = ReadMacInt32(fcb + fcbCatPos);
1752 if (fd < 0)
1753 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1754 WriteMacInt32(pb + ioActCount, 0);
1755 return eofErr;
1756 } else
1757 return fnOpnErr;
1758
1759 // Seek
1760 switch (ReadMacInt16(pb + ioPosMode) & 3) {
1761 case fsFromStart:
1762 if (lseek(fd, ReadMacInt32(pb + ioPosOffset), SEEK_SET) < 0)
1763 return posErr;
1764 break;
1765 case fsFromLEOF:
1766 if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_END) < 0)
1767 return posErr;
1768 break;
1769 case fsFromMark:
1770 if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_CUR) < 0)
1771 return posErr;
1772 break;
1773 }
1774
1775 // Read
1776 size_t actual = extfs_read(fd, Mac2HostAddr(ReadMacInt32(pb + ioBuffer)), ReadMacInt32(pb + ioReqCount));
1777 D(bug(" actual %d\n", actual));
1778 WriteMacInt32(pb + ioActCount, actual);
1779 uint32 pos = lseek(fd, 0, SEEK_CUR);
1780 WriteMacInt32(fcb + fcbCrPs, pos);
1781 WriteMacInt32(pb + ioPosOffset, pos);
1782 if (actual != ReadMacInt32(pb + ioReqCount))
1783 if (errno)
1784 return errno2oserr();
1785 else
1786 return eofErr;
1787 else
1788 return noErr;
1789 }
1790
1791 // Write to file
1792 static int16 fs_write(uint32 pb)
1793 {
1794 D(bug(" fs_write(%08lx), refNum %d, buffer %p, count %d, posMode %d, posOffset %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt32(pb + ioBuffer), ReadMacInt32(pb + ioReqCount), ReadMacInt16(pb + ioPosMode), ReadMacInt32(pb + ioPosOffset)));
1795
1796 // Find FCB and fd for file
1797 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1798 if (fcb == 0)
1799 return rfNumErr;
1800 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1801 return fnOpnErr;
1802 int fd = ReadMacInt32(fcb + fcbCatPos);
1803 if (fd < 0)
1804 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1805 WriteMacInt32(pb + ioActCount, ReadMacInt32(pb + ioReqCount));
1806 return noErr;
1807 } else
1808 return fnOpnErr;
1809
1810 // Seek
1811 switch (ReadMacInt16(pb + ioPosMode) & 3) {
1812 case fsFromStart:
1813 if (lseek(fd, ReadMacInt32(pb + ioPosOffset), SEEK_SET) < 0)
1814 return posErr;
1815 break;
1816 case fsFromLEOF:
1817 if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_END) < 0)
1818 return posErr;
1819 break;
1820 case fsFromMark:
1821 if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_CUR) < 0)
1822 return posErr;
1823 break;
1824 }
1825
1826 // Write
1827 size_t actual = extfs_write(fd, Mac2HostAddr(ReadMacInt32(pb + ioBuffer)), ReadMacInt32(pb + ioReqCount));
1828 D(bug(" actual %d\n", actual));
1829 WriteMacInt32(pb + ioActCount, actual);
1830 uint32 pos = lseek(fd, 0, SEEK_CUR);
1831 WriteMacInt32(fcb + fcbCrPs, pos);
1832 WriteMacInt32(pb + ioPosOffset, pos);
1833 if (actual != ReadMacInt32(pb + ioReqCount))
1834 return errno2oserr();
1835 else
1836 return noErr;
1837 }
1838
1839 // Create file
1840 static int16 fs_create(uint32 pb, uint32 dirID)
1841 {
1842 D(bug(" fs_create(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), dirID));
1843
1844 // Find FSItem for given file
1845 FSItem *fs_item;
1846 int16 result = get_item_and_path(pb, dirID, fs_item);
1847 if (result != noErr)
1848 return result;
1849
1850 // Does the file already exist?
1851 if (access(full_path, F_OK) == 0)
1852 return dupFNErr;
1853
1854 // Create file
1855 int fd = creat(full_path, 0666);
1856 if (fd < 0)
1857 return errno2oserr();
1858 else {
1859 close(fd);
1860 return noErr;
1861 }
1862 }
1863
1864 // Create directory
1865 static int16 fs_dir_create(uint32 pb)
1866 {
1867 D(bug(" fs_dir_create(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt32(pb + ioDirID)));
1868
1869 // Find FSItem for given directory
1870 FSItem *fs_item;
1871 int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1872 if (result != noErr)
1873 return result;
1874
1875 // Does the directory already exist?
1876 if (access(full_path, F_OK) == 0)
1877 return dupFNErr;
1878
1879 // Create directory
1880 if (mkdir(full_path, 0777) < 0)
1881 return errno2oserr();
1882 else {
1883 WriteMacInt32(pb + ioDirID, fs_item->id);
1884 return noErr;
1885 }
1886 }
1887
1888 // Delete file/directory
1889 static int16 fs_delete(uint32 pb, uint32 dirID)
1890 {
1891 D(bug(" fs_delete(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), dirID));
1892
1893 // Find FSItem for given file/dir
1894 FSItem *fs_item;
1895 int16 result = get_item_and_path(pb, dirID, fs_item);
1896 if (result != noErr)
1897 return result;
1898
1899 // Delete file
1900 if (remove(full_path) < 0) {
1901 int16 err = errno2oserr();
1902 if (errno == EISDIR) { // Workaround for BeOS bug
1903 if (rmdir(full_path) < 0)
1904 return errno2oserr();
1905 else
1906 return noErr;
1907 } else
1908 return err;
1909 } else
1910 return noErr;
1911 }
1912
1913 // Rename file/directory
1914 static int16 fs_rename(uint32 pb, uint32 dirID)
1915 {
1916 D(bug(" fs_rename(%08lx), vRefNum %d, name %.31s, dirID %d, new name %.31s\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), dirID, Mac2HostAddr(ReadMacInt32(pb + ioMisc) + 1)));
1917
1918 // Find path of given file/dir
1919 FSItem *fs_item;
1920 int16 result = get_item_and_path(pb, dirID, fs_item);
1921 if (result != noErr)
1922 return result;
1923
1924 // Save path of existing item
1925 char old_path[MAX_PATH_LENGTH];
1926 strcpy(old_path, full_path);
1927
1928 // Find path for new name
1929 uint8 new_pb[SIZEOF_IOParam];
1930 memcpy(new_pb, Mac2HostAddr(pb), SIZEOF_IOParam);
1931 WriteMacInt32((uint32)new_pb + ioNamePtr, ReadMacInt32(pb + ioMisc));
1932 FSItem *new_item;
1933 result = get_item_and_path((uint32)new_pb, dirID, new_item);
1934 if (result != noErr)
1935 return result;
1936
1937 // Does the new name already exist?
1938 if (access(full_path, F_OK) == 0)
1939 return dupFNErr;
1940
1941 // Rename item
1942 D(bug(" renaming %s -> %s\n", old_path, full_path));
1943 if (rename(old_path, full_path) < 0)
1944 return errno2oserr();
1945 else {
1946 // The ID of the old file/dir has to stay the same, so we swap the IDs of the FSItems
1947 uint32 t = fs_item->id;
1948 fs_item->id = new_item->id;
1949 new_item->id = t;
1950 return noErr;
1951 }
1952 }
1953
1954 // Move file/directory (CMovePBRec)
1955 static int16 fs_cat_move(uint32 pb)
1956 {
1957 D(bug(" fs_cat_move(%08lx), vRefNum %d, name %.31s, dirID %d, new name %.31s, new dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt32(pb + ioDirID), Mac2HostAddr(ReadMacInt32(pb + ioNewName) + 1), ReadMacInt32(pb + ioNewDirID)));
1958
1959 // Find path of given file/dir
1960 FSItem *fs_item;
1961 int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1962 if (result != noErr)
1963 return result;
1964
1965 // Save path of existing item
1966 char old_path[MAX_PATH_LENGTH];
1967 strcpy(old_path, full_path);
1968
1969 // Find path for new directory
1970 uint8 new_pb[SIZEOF_IOParam];
1971 memcpy(new_pb, Mac2HostAddr(pb), SIZEOF_IOParam);
1972 WriteMacInt32((uint32)new_pb + ioNamePtr, ReadMacInt32(pb + ioNewName));
1973 FSItem *new_dir_item;
1974 result = get_item_and_path((uint32)new_pb, ReadMacInt32(pb + ioNewDirID), new_dir_item);
1975 if (result != noErr)
1976 return result;
1977
1978 // Append old file/dir name
1979 add_path_comp(fs_item->name);
1980
1981 // Does the new name already exist?
1982 if (access(full_path, F_OK) == 0)
1983 return dupFNErr;
1984
1985 // Move item
1986 D(bug(" moving %s -> %s\n", old_path, full_path));
1987 if (rename(old_path, full_path) < 0)
1988 return errno2oserr();
1989 else {
1990 // The ID of the old file/dir has to stay the same, so we swap the IDs of the FSItems
1991 FSItem *new_item = find_fsitem(fs_item->name, new_dir_item);
1992 if (new_item) {
1993 uint32 t = fs_item->id;
1994 fs_item->id = new_item->id;
1995 new_item->id = t;
1996 }
1997 return noErr;
1998 }
1999 }
2000
2001 // Open working directory (WDParam)
2002 static int16 fs_open_wd(uint32 pb)
2003 {
2004 D(bug(" fs_open_wd(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt32(pb + ioWDDirID)));
2005 M68kRegisters r;
2006
2007 // Allocate WDCB
2008 D(bug(" allocating WDCB\n"));
2009 r.a[0] = pb;
2010 Execute68k(fs_data + fsAllocateWDCB, &r);
2011 D(bug(" UTAllocateWDCB returned %d, refNum is %d\n", r.d[0], ReadMacInt16(pb + ioVRefNum)));
2012 return r.d[0];
2013 }
2014
2015 // Close working directory (WDParam)
2016 static int16 fs_close_wd(uint32 pb)
2017 {
2018 D(bug(" fs_close_wd(%08lx), vRefNum %d\n", pb, ReadMacInt16(pb + ioVRefNum)));
2019 M68kRegisters r;
2020
2021 // Release WDCB
2022 D(bug(" releasing WDCB\n"));
2023 r.d[0] = ReadMacInt16(pb + ioVRefNum);
2024 Execute68k(fs_data + fsReleaseWDCB, &r);
2025 D(bug(" UTReleaseWDCB returned %d\n", r.d[0]));
2026 return r.d[0];
2027 }
2028
2029 // Query information about working directory (WDParam)
2030 static int16 fs_get_wd_info(uint32 pb, uint32 vcb)
2031 {
2032 D(bug(" fs_get_wd_info(%08lx), vRefNum %d, idx %d, procID %d\n", pb, ReadMacInt16(pb + ioVRefNum), ReadMacInt16(pb + ioWDIndex), ReadMacInt32(pb + ioWDProcID)));
2033 M68kRegisters r;
2034
2035 // Querying volume?
2036 if (ReadMacInt16(pb + ioWDIndex) == 0 && ReadMacInt16(pb + ioVRefNum) == ReadMacInt16(vcb + vcbVRefNum)) {
2037 WriteMacInt32(pb + ioWDProcID, 0);
2038 WriteMacInt16(pb + ioWDVRefNum, ReadMacInt16(vcb + vcbVRefNum));
2039 if (ReadMacInt32(pb + ioNamePtr))
2040 memcpy(Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), Mac2HostAddr(vcb + vcbVN), 28);
2041 WriteMacInt32(pb + ioWDDirID, ROOT_ID);
2042 return noErr;
2043 }
2044
2045 // Resolve WDCB
2046 D(bug(" resolving WDCB\n"));
2047 r.d[0] = ReadMacInt32(pb + ioWDProcID);
2048 r.d[1] = ReadMacInt16(pb + ioWDIndex);
2049 r.d[2] = ReadMacInt16(pb + ioVRefNum);
2050 r.a[0] = fs_data + fsReturn;
2051 Execute68k(fs_data + fsResolveWDCB, &r);
2052 uint32 wdcb = ReadMacInt32(fs_data + fsReturn);
2053 D(bug(" UTResolveWDCB() returned %d, dirID %d\n", r.d[0], ReadMacInt32(wdcb + wdDirID)));
2054 if (r.d[0] & 0xffff)
2055 return r.d[0];
2056
2057 // Return information
2058 WriteMacInt16(pb + ioWDProcID, ReadMacInt32(wdcb + wdProcID));
2059 WriteMacInt16(pb + ioWDVRefNum, ReadMacInt16(ReadMacInt32(wdcb + wdVCBPtr) + vcbVRefNum));
2060 if (ReadMacInt32(pb + ioNamePtr))
2061 memcpy(Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), Mac2HostAddr(ReadMacInt32(wdcb + wdVCBPtr) + vcbVN), 28);
2062 WriteMacInt32(pb + ioWDDirID, ReadMacInt32(wdcb + wdDirID));
2063 return noErr;
2064 }
2065
2066 // Main dispatch routine
2067 int16 ExtFSHFS(uint32 vcb, uint16 selectCode, uint32 paramBlock, uint32 globalsPtr, int16 fsid)
2068 {
2069 uint16 trapWord = selectCode & 0xf0ff;
2070 bool hfs = selectCode & kHFSMask;
2071 switch (trapWord) {
2072 case kFSMOpen:
2073 return fs_open(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0, vcb, false);
2074
2075 case kFSMClose:
2076 return fs_close(paramBlock);
2077
2078 case kFSMRead:
2079 return fs_read(paramBlock);
2080
2081 case kFSMWrite:
2082 return fs_write(paramBlock);
2083
2084 case kFSMGetVolInfo:
2085 return fs_get_vol_info(paramBlock, hfs);
2086
2087 case kFSMCreate:
2088 return fs_create(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2089
2090 case kFSMDelete:
2091 return fs_delete(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2092
2093 case kFSMOpenRF:
2094 return fs_open(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0, vcb, true);
2095
2096 case kFSMRename:
2097 return fs_rename(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2098
2099 case kFSMGetFileInfo:
2100 return fs_get_file_info(paramBlock, hfs, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2101
2102 case kFSMSetFileInfo:
2103 return fs_set_file_info(paramBlock, hfs, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2104
2105 case kFSMUnmountVol:
2106 return fs_unmount_vol(vcb);
2107
2108 case kFSMMountVol:
2109 return fs_mount_vol(paramBlock);
2110
2111 case kFSMAllocate:
2112 D(bug(" allocate\n"));
2113 WriteMacInt32(paramBlock + ioActCount, ReadMacInt32(paramBlock + ioReqCount));
2114 return noErr;
2115
2116 case kFSMGetEOF:
2117 return fs_get_eof(paramBlock);
2118
2119 case kFSMSetEOF:
2120 return fs_set_eof(paramBlock);
2121
2122 case kFSMGetVol:
2123 return fs_get_vol(paramBlock);
2124
2125 case kFSMSetVol:
2126 return fs_set_vol(paramBlock, hfs, vcb);
2127
2128 case kFSMEject:
2129 D(bug(" eject\n"));
2130 return noErr;
2131
2132 case kFSMGetFPos:
2133 return fs_get_fpos(paramBlock);
2134
2135 case kFSMOffline:
2136 D(bug(" offline\n"));
2137 return noErr;
2138
2139 case kFSMSetFilLock:
2140 return noErr; //!!
2141
2142 case kFSMRstFilLock:
2143 return noErr; //!!
2144
2145 case kFSMSetFPos:
2146 return fs_set_fpos(paramBlock);
2147
2148 case kFSMOpenWD:
2149 return fs_open_wd(paramBlock);
2150
2151 case kFSMCloseWD:
2152 return fs_close_wd(paramBlock);
2153
2154 case kFSMCatMove:
2155 return fs_cat_move(paramBlock);
2156
2157 case kFSMDirCreate:
2158 return fs_dir_create(paramBlock);
2159
2160 case kFSMGetWDInfo:
2161 return fs_get_wd_info(paramBlock, vcb);
2162
2163 case kFSMGetFCBInfo:
2164 return fs_get_fcb_info(paramBlock, vcb);
2165
2166 case kFSMGetCatInfo:
2167 return fs_get_cat_info(paramBlock);
2168
2169 case kFSMSetCatInfo:
2170 return fs_set_cat_info(paramBlock);
2171
2172 case kFSMSetVolInfo:
2173 return fs_set_vol_info(paramBlock);
2174
2175 case kFSMGetVolParms:
2176 return fs_get_vol_parms(paramBlock);
2177
2178 case kFSMVolumeMount:
2179 return fs_volume_mount(paramBlock);
2180
2181 case kFSMFlushVol:
2182 case kFSMFlushFile:
2183 D(bug(" flush_vol/flush_file\n"));
2184 return noErr;
2185
2186 default:
2187 D(bug("ExtFSHFS(%08lx, %04x, %08lx, %08lx, %d)\n", vcb, selectCode, paramBlock, globalsPtr, fsid));
2188 return paramErr;
2189 }
2190 }