ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.33
Committed: 2007-01-24T02:37:06Z (17 years, 3 months ago) by asvitkine
Branch: MAIN
Changes since 1.32: +1 -1 lines
Log Message:
macroman_to_host_encoding - so it works the other way around too

File Contents

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