ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.3
Committed: 1999-10-20T15:13:53Z (24 years, 6 months ago) by cebix
Branch: MAIN
Changes since 1.2: +19 -12 lines
Log Message:
- renamed main_volume to speaker_volume and dac_volume to main_volume
  (same for mute)
- added defines for headphone volume/mute

File Contents

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