ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.24
Committed: 2001-02-02T20:52:57Z (23 years, 9 months ago) by cebix
Branch: MAIN
CVS Tags: snapshot-17022001
Changes since 1.23: +1 -1 lines
Log Message:
- bumped version number to 0.9
- updated copyright dates

File Contents

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