ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.11
Committed: 1999-11-08T16:43:06Z (25 years ago) by cebix
Branch: MAIN
Changes since 1.10: +10 -9 lines
Log Message:
- fixes to ExtFS from Lauri Pesonen

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