ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.14
Committed: 1999-11-15T15:01:34Z (24 years, 6 months ago) by cebix
Branch: MAIN
Changes since 1.13: +16 -13 lines
Log Message:
- fixed more ExtFS bugs

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