ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.4
Committed: 1999-10-20T17:23:53Z (25 years, 1 month ago) by cebix
Branch: MAIN
CVS Tags: snapshot-21101999
Changes since 1.3: +39 -23 lines
Log Message:
- fixed bugs in extfs.cpp:
   - root's parent now has an FSItem, so finding the volume by name with
     parent dirID 1 now works
   - fs_get_file_info() and fs_get_cat_info() handle all negative values of
     dir_index correctly
   - fs_set_fpos() handles fsFromLEOF positioning mode
   - replaced "%#s" format codes in debug output
- fixed some file extensions in extfs_unix.cpp
- "speaker" means "main volume", as before

File Contents

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