ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.6
Committed: 1999-10-22T15:08:10Z (24 years, 7 months ago) by cebix
Branch: MAIN
Changes since 1.5: +3 -1 lines
Log Message:
- added BlockMove() replacement
- extfs.cpp: get_path_for_fsitem(root parent) no longer crashes

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