ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.5
Committed: 1999-10-21T22:39:51Z (25 years, 1 month ago) by cebix
Branch: MAIN
Changes since 1.4: +23 -28 lines
Log Message:
- ExtFS works under AmigaOS
- fixed erroneous __regargs attributes in prefs_editor_amiga.cpp
  and audio_amiga.cpp for GCC

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