ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.19
Committed: 2000-07-14T21:42:05Z (24 years, 4 months ago) by cebix
Branch: MAIN
Changes since 1.18: +2 -2 lines
Log Message:
- fixed compilation problems

File Contents

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