ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.26
Committed: 2001-07-06T17:36:06Z (22 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.25: +8 -8 lines
Log Message:
replaced TIME_OFFSET constant by portable TimeToMacTime() function

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