ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.36
Committed: 2008-06-20T00:39:47Z (16 years, 5 months ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.35: +1 -1 lines
Log Message:
[patch from Kelvin Delbarre] Fix file corruption experienced when doing random-access
file I/O to the external filesystem. The application-specified ioPosMode parameter must
be masked off appropriately in extfs.cpp:fs_set_fpos(), as is done elsewhere in the file.

File Contents

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