ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.28
Committed: 2002-01-15T14:58:32Z (22 years, 10 months ago) by cebix
Branch: MAIN
CVS Tags: nigel-build-12, nigel-build-13, snapshot-15012002
Changes since 1.27: +1 -1 lines
Log Message:
- documentation updates
- 2001 -> 2002
- version 0.9 -> 1.0

File Contents

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