ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.17
Committed: 2000-05-16T17:11:35Z (24 years, 6 months ago) by cebix
Branch: MAIN
CVS Tags: snapshot-13072000
Changes since 1.16: +1 -1 lines
Log Message:
- added "noclipconversion" prefs item

File Contents

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