ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.21
Committed: 2000-07-22T16:07:16Z (23 years, 9 months ago) by cebix
Branch: MAIN
Changes since 1.20: +9 -24 lines
Log Message:
- new FOURCC() macro in macos_util.h

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