ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.21
Committed: 2000-07-22T16:07:16Z (24 years, 4 months ago) by cebix
Branch: MAIN
Changes since 1.20: +9 -24 lines
Log Message:
- new FOURCC() macro in macos_util.h

File Contents

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