ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.9
Committed: 1999-11-03T10:56:14Z (24 years, 6 months ago) by cebix
Branch: MAIN
Changes since 1.8: +20 -22 lines
Log Message:
- imported UAE CPU 0.8.10 changes
- new utility functions Mac_memset, Mac2Host_memcpy, Host2Mac_memcpu and
  Mac2Mac_memcpy
- extfs.cpp: fixed bug in fs_rename() and fs_cat_move() (auxiliary IOParam
  block was not in Mac address space)
- some provisions for using UAE CPU compiler (doesn't work yet)

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 name 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 name 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);
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 count++;
1378 }
1379 closedir(d);
1380 }
1381 fs_item->cache_dircount = count;
1382 }
1383 WriteMacInt16(pb + ioDrNmFls, count);
1384 } else {
1385 Mac_memset(pb + ioFlFndrInfo, 0, SIZEOF_FInfo);
1386 Mac_memset(pb + ioFlXFndrInfo, 0, SIZEOF_FXInfo);
1387 uint32 type, creator; // pb may point to kernel space, but stack is switched
1388 get_finder_type(full_path, type, creator);
1389 WriteMacInt32(pb + ioFlFndrInfo + fdType, type);
1390 WriteMacInt32(pb + ioFlFndrInfo + fdCreator, creator);
1391 uint16 fflags;
1392 get_finder_flags(full_path, fflags);
1393 WriteMacInt16(pb + ioFlFndrInfo + fdFlags, fflags);
1394 WriteMacInt16(pb + ioFlStBlk, 0);
1395 WriteMacInt32(pb + ioFlLgLen, st.st_size);
1396 WriteMacInt32(pb + ioFlPyLen, (st.st_size + 1023) & ~1023);
1397 WriteMacInt16(pb + ioFlRStBlk, 0);
1398 uint32 rf_size = get_rfork_size(full_path);
1399 WriteMacInt32(pb + ioFlRLgLen, rf_size);
1400 WriteMacInt32(pb + ioFlRPyLen, (rf_size + 1023) & ~1023);
1401 WriteMacInt32(pb + ioFlClpSiz, 0);
1402 }
1403 return noErr;
1404 }
1405
1406 // Set file/directory attributes
1407 static int16 fs_set_cat_info(uint32 pb)
1408 {
1409 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)));
1410
1411 // Find FSItem for given file/dir
1412 FSItem *fs_item;
1413 int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1414 if (result != noErr)
1415 return result;
1416
1417 // Get stats
1418 struct stat st;
1419 if (stat(full_path, &st) < 0)
1420 return errno2oserr();
1421
1422 // Set attributes
1423 if (S_ISDIR(st.st_mode))
1424 set_finder_flags(full_path, ReadMacInt16(pb + ioDrUsrWds + frFlags));
1425 else {
1426 set_finder_type(full_path, ReadMacInt32(pb + ioFlFndrInfo + fdType), ReadMacInt32(pb + ioFlFndrInfo + fdCreator));
1427 set_finder_flags(full_path, ReadMacInt16(pb + ioFlFndrInfo + fdFlags));
1428 }
1429 //!! times
1430 return noErr;
1431 }
1432
1433 // Open file
1434 static int16 fs_open(uint32 pb, uint32 dirID, uint32 vcb, bool resource_fork)
1435 {
1436 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)));
1437 M68kRegisters r;
1438
1439 // Find FSItem for given file
1440 FSItem *fs_item;
1441 int16 result = get_item_and_path(pb, dirID, fs_item);
1442 if (result != noErr)
1443 return result;
1444
1445 // Convert ioPermssn to open() flag
1446 int flag = 0;
1447 bool write_ok = (access(full_path, W_OK) == 0);
1448 switch (ReadMacInt8(pb + ioPermssn)) {
1449 case fsCurPerm: // Whatever is currently allowed
1450 if (write_ok)
1451 flag = O_RDWR;
1452 else
1453 flag = O_RDONLY;
1454 break;
1455 case fsRdPerm: // Exclusive read
1456 flag = O_RDONLY;
1457 break;
1458 case fsWrPerm: // Exclusive write
1459 flag = O_WRONLY;
1460 break;
1461 case fsRdWrPerm: // Exclusive read/write
1462 case fsRdWrShPerm: // Shared read/write
1463 default:
1464 flag = O_RDWR;
1465 break;
1466 }
1467
1468 // Try to open and stat the file
1469 int fd = -1;
1470 struct stat st;
1471 if (resource_fork) {
1472 if (access(full_path, F_OK))
1473 return fnfErr;
1474 fd = open_rfork(full_path, flag);
1475 if (fd > 0) {
1476 if (fstat(fd, &st) < 0)
1477 return errno2oserr();
1478 } else { // Resource fork not supported, silently ignore it ("pseudo" resource fork)
1479 st.st_size = 0;
1480 st.st_mode = 0;
1481 }
1482 } else {
1483 fd = open(full_path, flag);
1484 if (fd < 0)
1485 return errno2oserr();
1486 if (fstat(fd, &st) < 0)
1487 return errno2oserr();
1488 }
1489
1490 // File open, allocate FCB
1491 D(bug(" allocating FCB\n"));
1492 r.a[0] = pb + ioRefNum;
1493 r.a[1] = fs_data + fsReturn;
1494 Execute68k(fs_data + fsAllocateFCB, &r);
1495 uint32 fcb = ReadMacInt32(fs_data + fsReturn);
1496 D(bug(" UTAllocateFCB() returned %d, fRefNum %d, fcb %08lx\n", r.d[0], ReadMacInt16(pb + ioRefNum), fcb));
1497 if (r.d[0] & 0xffff) {
1498 close(fd);
1499 return r.d[0];
1500 }
1501
1502 // Initialize FCB, fd is stored in fcbCatPos
1503 WriteMacInt32(fcb + fcbFlNm, fs_item->id);
1504 WriteMacInt8(fcb + fcbFlags, ((flag == O_WRONLY || flag == O_RDWR) ? fcbWriteMask : 0) | (resource_fork ? fcbResourceMask : 0) | (write_ok ? 0 : fcbFileLockedMask));
1505 WriteMacInt32(fcb + fcbEOF, st.st_size);
1506 WriteMacInt32(fcb + fcbPLen, (st.st_size + 1023) & ~1023);
1507 WriteMacInt32(fcb + fcbCrPs, 0);
1508 WriteMacInt32(fcb + fcbVPtr, vcb);
1509 WriteMacInt32(fcb + fcbClmpSize, 1024);
1510 uint32 type, creator; // fcb may point to kernel space, but stack is switched
1511 get_finder_type(full_path, type, creator);
1512 WriteMacInt32(fcb + fcbFType, type);
1513 WriteMacInt32(fcb + fcbCatPos, fd);
1514 WriteMacInt32(fcb + fcbDirID, fs_item->parent_id);
1515 cstr2pstr((char *)Mac2HostAddr(fcb + fcbCName), fs_item->name);
1516 return noErr;
1517 }
1518
1519 // Close file
1520 static int16 fs_close(uint32 pb)
1521 {
1522 D(bug(" fs_close(%08lx), refNum %d\n", pb, ReadMacInt16(pb + ioRefNum)));
1523 M68kRegisters r;
1524
1525 // Find FCB and fd for file
1526 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1527 if (fcb == 0)
1528 return rfNumErr;
1529 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1530 return fnOpnErr;
1531 int fd = ReadMacInt32(fcb + fcbCatPos);
1532
1533 // Close file
1534 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) {
1535 FSItem *item = find_fsitem_by_id(ReadMacInt32(fcb + fcbFlNm));
1536 if (item) {
1537 get_path_for_fsitem(item);
1538 close_rfork(full_path, fd);
1539 }
1540 } else
1541 close(fd);
1542 WriteMacInt32(fcb + fcbCatPos, (uint32)-1);
1543
1544 // Release FCB
1545 D(bug(" releasing FCB\n"));
1546 r.d[0] = ReadMacInt16(pb + ioRefNum);
1547 Execute68k(fs_data + fsReleaseFCB, &r);
1548 D(bug(" UTReleaseFCB() returned %d\n", r.d[0]));
1549 return r.d[0];
1550 }
1551
1552 // Query information about FCB (FCBPBRec)
1553 static int16 fs_get_fcb_info(uint32 pb, uint32 vcb)
1554 {
1555 D(bug(" fs_get_fcb_info(%08lx), vRefNum %d, refNum %d, idx %d\n", pb, ReadMacInt16(pb + ioVRefNum), ReadMacInt16(pb + ioRefNum), ReadMacInt16(pb + ioFCBIndx)));
1556 M68kRegisters r;
1557
1558 uint32 fcb = 0;
1559 if (ReadMacInt16(pb + ioFCBIndx) == 0) { // Get information about single file
1560
1561 // Find FCB for file
1562 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1563
1564 } else { // Get information about file specified by index
1565
1566 // Find FCB by index
1567 WriteMacInt16(pb + ioRefNum, 0);
1568 for (int i=0; i<ReadMacInt16(pb + ioFCBIndx); i++) {
1569 D(bug(" indexing FCBs\n"));
1570 r.a[0] = vcb;
1571 r.a[1] = pb + ioRefNum;
1572 r.a[2] = fs_data + fsReturn;
1573 Execute68k(fs_data + fsIndexFCB, &r);
1574 fcb = ReadMacInt32(fs_data + fsReturn);
1575 D(bug(" UTIndexFCB() returned %d, fcb %p\n", r.d[0], fcb));
1576 if (r.d[0] & 0xffff)
1577 return r.d[0];
1578 }
1579 }
1580 if (fcb == 0)
1581 return rfNumErr;
1582
1583 // Copy information from FCB
1584 if (ReadMacInt32(pb + ioNamePtr))
1585 pstrcpy((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), (char *)Mac2HostAddr(fcb + fcbCName));
1586 WriteMacInt32(pb + ioFCBFlNm, ReadMacInt32(fcb + fcbFlNm));
1587 WriteMacInt8(pb + ioFCBFlags, ReadMacInt8(fcb + fcbFlags));
1588 WriteMacInt16(pb + ioFCBStBlk, ReadMacInt16(fcb + fcbSBlk));
1589 WriteMacInt32(pb + ioFCBEOF, ReadMacInt32(fcb + fcbEOF));
1590 WriteMacInt32(pb + ioFCBPLen, ReadMacInt32(fcb + fcbPLen));
1591 WriteMacInt32(pb + ioFCBCrPs, ReadMacInt32(fcb + fcbCrPs));
1592 WriteMacInt16(pb + ioFCBVRefNum, ReadMacInt16(ReadMacInt32(fcb + fcbVPtr) + vcbVRefNum));
1593 WriteMacInt32(pb + ioFCBClpSiz, ReadMacInt32(fcb + fcbClmpSize));
1594 WriteMacInt32(pb + ioFCBParID, ReadMacInt32(fcb + fcbDirID));
1595 return noErr;
1596 }
1597
1598 // Obtain logical size of an open file
1599 static int16 fs_get_eof(uint32 pb)
1600 {
1601 D(bug(" fs_get_eof(%08lx), refNum %d\n", pb, ReadMacInt16(pb + ioRefNum)));
1602 M68kRegisters r;
1603
1604 // Find FCB and fd for file
1605 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1606 if (fcb == 0)
1607 return rfNumErr;
1608 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1609 return fnOpnErr;
1610 int fd = ReadMacInt32(fcb + fcbCatPos);
1611 if (fd < 0)
1612 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1613 WriteMacInt32(pb + ioMisc, 0);
1614 return noErr;
1615 } else
1616 return fnOpnErr;
1617
1618 // Get file size
1619 struct stat st;
1620 if (fstat(fd, &st) < 0)
1621 return errno2oserr();
1622
1623 // Adjust FCBs
1624 WriteMacInt32(fcb + fcbEOF, st.st_size);
1625 WriteMacInt32(fcb + fcbPLen, (st.st_size + 1023) & ~1023);
1626 WriteMacInt32(pb + ioMisc, st.st_size);
1627 D(bug(" adjusting FCBs\n"));
1628 r.d[0] = ReadMacInt16(pb + ioRefNum);
1629 Execute68k(fs_data + fsAdjustEOF, &r);
1630 D(bug(" UTAdjustEOF() returned %d\n", r.d[0]));
1631 return noErr;
1632 }
1633
1634 // Truncate file
1635 static int16 fs_set_eof(uint32 pb)
1636 {
1637 D(bug(" fs_set_eof(%08lx), refNum %d, size %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt32(pb + ioMisc)));
1638 M68kRegisters r;
1639
1640 // Find FCB and fd for file
1641 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1642 if (fcb == 0)
1643 return rfNumErr;
1644 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1645 return fnOpnErr;
1646 int fd = ReadMacInt32(fcb + fcbCatPos);
1647 if (fd < 0)
1648 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) // "pseudo" resource fork
1649 return noErr;
1650 else
1651 return fnOpnErr;
1652
1653 // Truncate file
1654 uint32 size = ReadMacInt32(pb + ioMisc);
1655 if (ftruncate(fd, size) < 0)
1656 return errno2oserr();
1657
1658 // Adjust FCBs
1659 WriteMacInt32(fcb + fcbEOF, size);
1660 WriteMacInt32(fcb + fcbPLen, (size + 1023) & ~1023);
1661 D(bug(" adjusting FCBs\n"));
1662 r.d[0] = ReadMacInt16(pb + ioRefNum);
1663 Execute68k(fs_data + fsAdjustEOF, &r);
1664 D(bug(" UTAdjustEOF() returned %d\n", r.d[0]));
1665 return noErr;
1666 }
1667
1668 // Query current file position
1669 static int16 fs_get_fpos(uint32 pb)
1670 {
1671 D(bug(" fs_get_fpos(%08lx), refNum %d\n", pb, ReadMacInt16(pb + ioRefNum)));
1672
1673 WriteMacInt32(pb + ioReqCount, 0);
1674 WriteMacInt32(pb + ioActCount, 0);
1675 WriteMacInt16(pb + ioPosMode, 0);
1676
1677 // Find FCB and fd for file
1678 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1679 if (fcb == 0)
1680 return rfNumErr;
1681 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1682 return fnOpnErr;
1683 int fd = ReadMacInt32(fcb + fcbCatPos);
1684 if (fd < 0)
1685 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1686 WriteMacInt32(pb + ioPosOffset, 0);
1687 return noErr;
1688 } else
1689 return fnOpnErr;
1690
1691 // Get file position
1692 uint32 pos = lseek(fd, 0, SEEK_CUR);
1693 WriteMacInt32(fcb + fcbCrPs, pos);
1694 WriteMacInt32(pb + ioPosOffset, pos);
1695 return noErr;
1696 }
1697
1698 // Set current file position
1699 static int16 fs_set_fpos(uint32 pb)
1700 {
1701 D(bug(" fs_set_fpos(%08lx), refNum %d, posMode %d, offset %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt16(pb + ioPosMode), ReadMacInt32(pb + ioPosOffset)));
1702
1703 // Find FCB and fd for file
1704 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1705 if (fcb == 0)
1706 return rfNumErr;
1707 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1708 return fnOpnErr;
1709 int fd = ReadMacInt32(fcb + fcbCatPos);
1710 if (fd < 0)
1711 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1712 WriteMacInt32(pb + ioPosOffset, 0);
1713 return noErr;
1714 } else
1715 return fnOpnErr;
1716
1717 // Set file position
1718 switch (ReadMacInt16(pb + ioPosMode)) {
1719 case fsFromStart:
1720 if (lseek(fd, ReadMacInt32(pb + ioPosOffset), SEEK_SET) < 0)
1721 return posErr;
1722 break;
1723 case fsFromLEOF:
1724 if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_END) < 0)
1725 return posErr;
1726 break;
1727 case fsFromMark:
1728 if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_CUR) < 0)
1729 return posErr;
1730 break;
1731 default:
1732 break;
1733 }
1734 uint32 pos = lseek(fd, 0, SEEK_CUR);
1735 WriteMacInt32(fcb + fcbCrPs, pos);
1736 WriteMacInt32(pb + ioPosOffset, pos);
1737 return noErr;
1738 }
1739
1740 // Read from file
1741 static int16 fs_read(uint32 pb)
1742 {
1743 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)));
1744
1745 // Find FCB and fd for file
1746 uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1747 if (fcb == 0)
1748 return rfNumErr;
1749 if (ReadMacInt32(fcb + fcbFlNm) == 0)
1750 return fnOpnErr;
1751 int fd = ReadMacInt32(fcb + fcbCatPos);
1752 if (fd < 0)
1753 if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1754 WriteMacInt32(pb + ioActCount, 0);
1755 return eofErr;
1756 } else
1757 return fnOpnErr;
1758
1759 // Seek
1760 switch (ReadMacInt16(pb + ioPosMode) & 3) {
1761 case fsFromStart:
1762 if (lseek(fd, ReadMacInt32(pb + ioPosOffset), SEEK_SET) < 0)
1763 return posErr;
1764 break;
1765 case fsFromLEOF:
1766 if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_END) < 0)
1767 return posErr;
1768 break;
1769 case fsFromMark:
1770 if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_CUR) < 0)
1771 return posErr;
1772 break;
1773 }
1774
1775 // Read
1776 size_t actual = extfs_read(fd, Mac2HostAddr(ReadMacInt32(pb + ioBuffer)), ReadMacInt32(pb + ioReqCount));
1777 D(bug(" actual %d\n", actual));
1778 WriteMacInt32(pb + ioActCount, actual);
1779 uint32 pos = lseek(fd, 0, SEEK_CUR);
1780 WriteMacInt32(fcb + fcbCrPs, pos);
1781 WriteMacInt32(pb + ioPosOffset, pos);
1782 if (actual != ReadMacInt32(pb + ioReqCount))
1783 if (errno)
1784 return errno2oserr();
1785 else
1786 return 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 D(bug(" actual %d\n", actual));
1829 WriteMacInt32(pb + ioActCount, actual);
1830 uint32 pos = lseek(fd, 0, SEEK_CUR);
1831 WriteMacInt32(fcb + fcbCrPs, pos);
1832 WriteMacInt32(pb + ioPosOffset, pos);
1833 if (actual != ReadMacInt32(pb + ioReqCount))
1834 return errno2oserr();
1835 else
1836 return noErr;
1837 }
1838
1839 // Create file
1840 static int16 fs_create(uint32 pb, uint32 dirID)
1841 {
1842 D(bug(" fs_create(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), dirID));
1843
1844 // Find FSItem for given file
1845 FSItem *fs_item;
1846 int16 result = get_item_and_path(pb, dirID, fs_item);
1847 if (result != noErr)
1848 return result;
1849
1850 // Does the file already exist?
1851 if (access(full_path, F_OK) == 0)
1852 return dupFNErr;
1853
1854 // Create file
1855 int fd = creat(full_path, 0666);
1856 if (fd < 0)
1857 return errno2oserr();
1858 else {
1859 close(fd);
1860 return noErr;
1861 }
1862 }
1863
1864 // Create directory
1865 static int16 fs_dir_create(uint32 pb)
1866 {
1867 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)));
1868
1869 // Find FSItem for given directory
1870 FSItem *fs_item;
1871 int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1872 if (result != noErr)
1873 return result;
1874
1875 // Does the directory already exist?
1876 if (access(full_path, F_OK) == 0)
1877 return dupFNErr;
1878
1879 // Create directory
1880 if (mkdir(full_path, 0777) < 0)
1881 return errno2oserr();
1882 else {
1883 WriteMacInt32(pb + ioDirID, fs_item->id);
1884 return noErr;
1885 }
1886 }
1887
1888 // Delete file/directory
1889 static int16 fs_delete(uint32 pb, uint32 dirID)
1890 {
1891 D(bug(" fs_delete(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), dirID));
1892
1893 // Find FSItem for given file/dir
1894 FSItem *fs_item;
1895 int16 result = get_item_and_path(pb, dirID, fs_item);
1896 if (result != noErr)
1897 return result;
1898
1899 // Delete file
1900 if (remove(full_path) < 0) {
1901 int16 err = errno2oserr();
1902 if (errno == EISDIR) { // Workaround for BeOS bug
1903 if (rmdir(full_path) < 0)
1904 return errno2oserr();
1905 else
1906 return noErr;
1907 } else
1908 return err;
1909 } else
1910 return noErr;
1911 }
1912
1913 // Rename file/directory
1914 static int16 fs_rename(uint32 pb, uint32 dirID)
1915 {
1916 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)));
1917
1918 // Find path of given file/dir
1919 FSItem *fs_item;
1920 int16 result = get_item_and_path(pb, dirID, fs_item);
1921 if (result != noErr)
1922 return result;
1923
1924 // Save path of existing item
1925 char old_path[MAX_PATH_LENGTH];
1926 strcpy(old_path, full_path);
1927
1928 // Find path for new name
1929 Mac2Mac_memcpy(fs_data + fsPB, pb, SIZEOF_IOParam);
1930 WriteMacInt32(fs_data + fsPB + ioNamePtr, ReadMacInt32(pb + ioMisc));
1931 FSItem *new_item;
1932 result = get_item_and_path(fs_data + fsPB, dirID, new_item);
1933 if (result != noErr)
1934 return result;
1935
1936 // Does the new name already exist?
1937 if (access(full_path, F_OK) == 0)
1938 return dupFNErr;
1939
1940 // Rename item
1941 D(bug(" renaming %s -> %s\n", old_path, full_path));
1942 if (rename(old_path, full_path) < 0)
1943 return errno2oserr();
1944 else {
1945 // The ID of the old file/dir has to stay the same, so we swap the IDs of the FSItems
1946 uint32 t = fs_item->id;
1947 fs_item->id = new_item->id;
1948 new_item->id = t;
1949 return noErr;
1950 }
1951 }
1952
1953 // Move file/directory (CMovePBRec)
1954 static int16 fs_cat_move(uint32 pb)
1955 {
1956 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)));
1957
1958 // Find path of given file/dir
1959 FSItem *fs_item;
1960 int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1961 if (result != noErr)
1962 return result;
1963
1964 // Save path of existing item
1965 char old_path[MAX_PATH_LENGTH];
1966 strcpy(old_path, full_path);
1967
1968 // Find path for new directory
1969 Mac2Host_memcpy(fs_data + fsPB, pb, SIZEOF_IOParam);
1970 WriteMacInt32(fs_data + fsPB + ioNamePtr, ReadMacInt32(pb + ioNewName));
1971 FSItem *new_dir_item;
1972 result = get_item_and_path(fs_data + fsPB, ReadMacInt32(pb + ioNewDirID), new_dir_item);
1973 if (result != noErr)
1974 return result;
1975
1976 // Append old file/dir name
1977 add_path_comp(fs_item->name);
1978
1979 // Does the new name already exist?
1980 if (access(full_path, F_OK) == 0)
1981 return dupFNErr;
1982
1983 // Move item
1984 D(bug(" moving %s -> %s\n", old_path, full_path));
1985 if (rename(old_path, full_path) < 0)
1986 return errno2oserr();
1987 else {
1988 // The ID of the old file/dir has to stay the same, so we swap the IDs of the FSItems
1989 FSItem *new_item = find_fsitem(fs_item->name, new_dir_item);
1990 if (new_item) {
1991 uint32 t = fs_item->id;
1992 fs_item->id = new_item->id;
1993 new_item->id = t;
1994 }
1995 return noErr;
1996 }
1997 }
1998
1999 // Open working directory (WDParam)
2000 static int16 fs_open_wd(uint32 pb)
2001 {
2002 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)));
2003 M68kRegisters r;
2004
2005 // Allocate WDCB
2006 D(bug(" allocating WDCB\n"));
2007 r.a[0] = pb;
2008 Execute68k(fs_data + fsAllocateWDCB, &r);
2009 D(bug(" UTAllocateWDCB returned %d, refNum is %d\n", r.d[0], ReadMacInt16(pb + ioVRefNum)));
2010 return r.d[0];
2011 }
2012
2013 // Close working directory (WDParam)
2014 static int16 fs_close_wd(uint32 pb)
2015 {
2016 D(bug(" fs_close_wd(%08lx), vRefNum %d\n", pb, ReadMacInt16(pb + ioVRefNum)));
2017 M68kRegisters r;
2018
2019 // Release WDCB
2020 D(bug(" releasing WDCB\n"));
2021 r.d[0] = ReadMacInt16(pb + ioVRefNum);
2022 Execute68k(fs_data + fsReleaseWDCB, &r);
2023 D(bug(" UTReleaseWDCB returned %d\n", r.d[0]));
2024 return r.d[0];
2025 }
2026
2027 // Query information about working directory (WDParam)
2028 static int16 fs_get_wd_info(uint32 pb, uint32 vcb)
2029 {
2030 D(bug(" fs_get_wd_info(%08lx), vRefNum %d, idx %d, procID %d\n", pb, ReadMacInt16(pb + ioVRefNum), ReadMacInt16(pb + ioWDIndex), ReadMacInt32(pb + ioWDProcID)));
2031 M68kRegisters r;
2032
2033 // Querying volume?
2034 if (ReadMacInt16(pb + ioWDIndex) == 0 && ReadMacInt16(pb + ioVRefNum) == ReadMacInt16(vcb + vcbVRefNum)) {
2035 WriteMacInt32(pb + ioWDProcID, 0);
2036 WriteMacInt16(pb + ioWDVRefNum, ReadMacInt16(vcb + vcbVRefNum));
2037 if (ReadMacInt32(pb + ioNamePtr))
2038 Mac2Mac_memcpy(ReadMacInt32(pb + ioNamePtr), vcb + vcbVN, 28);
2039 WriteMacInt32(pb + ioWDDirID, ROOT_ID);
2040 return noErr;
2041 }
2042
2043 // Resolve WDCB
2044 D(bug(" resolving WDCB\n"));
2045 r.d[0] = ReadMacInt32(pb + ioWDProcID);
2046 r.d[1] = ReadMacInt16(pb + ioWDIndex);
2047 r.d[2] = ReadMacInt16(pb + ioVRefNum);
2048 r.a[0] = fs_data + fsReturn;
2049 Execute68k(fs_data + fsResolveWDCB, &r);
2050 uint32 wdcb = ReadMacInt32(fs_data + fsReturn);
2051 D(bug(" UTResolveWDCB() returned %d, dirID %d\n", r.d[0], ReadMacInt32(wdcb + wdDirID)));
2052 if (r.d[0] & 0xffff)
2053 return r.d[0];
2054
2055 // Return information
2056 WriteMacInt16(pb + ioWDProcID, ReadMacInt32(wdcb + wdProcID));
2057 WriteMacInt16(pb + ioWDVRefNum, ReadMacInt16(ReadMacInt32(wdcb + wdVCBPtr) + vcbVRefNum));
2058 if (ReadMacInt32(pb + ioNamePtr))
2059 Mac2Mac_memcpy(ReadMacInt32(pb + ioNamePtr), ReadMacInt32(wdcb + wdVCBPtr) + vcbVN, 28);
2060 WriteMacInt32(pb + ioWDDirID, ReadMacInt32(wdcb + wdDirID));
2061 return noErr;
2062 }
2063
2064 // Main dispatch routine
2065 int16 ExtFSHFS(uint32 vcb, uint16 selectCode, uint32 paramBlock, uint32 globalsPtr, int16 fsid)
2066 {
2067 uint16 trapWord = selectCode & 0xf0ff;
2068 bool hfs = selectCode & kHFSMask;
2069 switch (trapWord) {
2070 case kFSMOpen:
2071 return fs_open(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0, vcb, false);
2072
2073 case kFSMClose:
2074 return fs_close(paramBlock);
2075
2076 case kFSMRead:
2077 return fs_read(paramBlock);
2078
2079 case kFSMWrite:
2080 return fs_write(paramBlock);
2081
2082 case kFSMGetVolInfo:
2083 return fs_get_vol_info(paramBlock, hfs);
2084
2085 case kFSMCreate:
2086 return fs_create(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2087
2088 case kFSMDelete:
2089 return fs_delete(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2090
2091 case kFSMOpenRF:
2092 return fs_open(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0, vcb, true);
2093
2094 case kFSMRename:
2095 return fs_rename(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2096
2097 case kFSMGetFileInfo:
2098 return fs_get_file_info(paramBlock, hfs, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2099
2100 case kFSMSetFileInfo:
2101 return fs_set_file_info(paramBlock, hfs, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2102
2103 case kFSMUnmountVol:
2104 return fs_unmount_vol(vcb);
2105
2106 case kFSMMountVol:
2107 return fs_mount_vol(paramBlock);
2108
2109 case kFSMAllocate:
2110 D(bug(" allocate\n"));
2111 WriteMacInt32(paramBlock + ioActCount, ReadMacInt32(paramBlock + ioReqCount));
2112 return noErr;
2113
2114 case kFSMGetEOF:
2115 return fs_get_eof(paramBlock);
2116
2117 case kFSMSetEOF:
2118 return fs_set_eof(paramBlock);
2119
2120 case kFSMGetVol:
2121 return fs_get_vol(paramBlock);
2122
2123 case kFSMSetVol:
2124 return fs_set_vol(paramBlock, hfs, vcb);
2125
2126 case kFSMEject:
2127 D(bug(" eject\n"));
2128 return noErr;
2129
2130 case kFSMGetFPos:
2131 return fs_get_fpos(paramBlock);
2132
2133 case kFSMOffline:
2134 D(bug(" offline\n"));
2135 return noErr;
2136
2137 case kFSMSetFilLock:
2138 return noErr; //!!
2139
2140 case kFSMRstFilLock:
2141 return noErr; //!!
2142
2143 case kFSMSetFPos:
2144 return fs_set_fpos(paramBlock);
2145
2146 case kFSMOpenWD:
2147 return fs_open_wd(paramBlock);
2148
2149 case kFSMCloseWD:
2150 return fs_close_wd(paramBlock);
2151
2152 case kFSMCatMove:
2153 return fs_cat_move(paramBlock);
2154
2155 case kFSMDirCreate:
2156 return fs_dir_create(paramBlock);
2157
2158 case kFSMGetWDInfo:
2159 return fs_get_wd_info(paramBlock, vcb);
2160
2161 case kFSMGetFCBInfo:
2162 return fs_get_fcb_info(paramBlock, vcb);
2163
2164 case kFSMGetCatInfo:
2165 return fs_get_cat_info(paramBlock);
2166
2167 case kFSMSetCatInfo:
2168 return fs_set_cat_info(paramBlock);
2169
2170 case kFSMSetVolInfo:
2171 return fs_set_vol_info(paramBlock);
2172
2173 case kFSMGetVolParms:
2174 return fs_get_vol_parms(paramBlock);
2175
2176 case kFSMVolumeMount:
2177 return fs_volume_mount(paramBlock);
2178
2179 case kFSMFlushVol:
2180 case kFSMFlushFile:
2181 D(bug(" flush_vol/flush_file\n"));
2182 return noErr;
2183
2184 default:
2185 D(bug("ExtFSHFS(%08lx, %04x, %08lx, %08lx, %d)\n", vcb, selectCode, paramBlock, globalsPtr, fsid));
2186 return paramErr;
2187 }
2188 }