ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.20
Committed: 2000-07-21T18:01:05Z (23 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.19: +15 -37 lines
Log Message:
- extfs: replaced get/set_finder_*() functions by get/set_finfo(), helper
  files now store complete FInfo/FXInfo

File Contents

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