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

File Contents

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