ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.16
Committed: 2000-04-10T18:52:22Z (24 years, 7 months ago) by cebix
Branch: MAIN
Changes since 1.15: +1 -1 lines
Log Message:
- updated copyright info: 1999->2000

File Contents

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