ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.18
Committed: 2000-07-14T21:29:08Z (23 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.17: +65 -38 lines
Log Message:
- AmigaOS bug fixes by J.Lachmann (floppy, 2060scsi.device, "Add Volume" in
  prefs editor)
- imported some changes from the Windows source (1Hz interrupt, FPU fixes)

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