ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.1
Committed: 1999-10-19T17:41:14Z (25 years, 1 month ago) by cebix
Branch: MAIN
Log Message:
- added external file system
- moved most init/deinit code to InitAll()/ExitAll() in main.cpp

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