ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.2
Committed: 1999-10-19T21:33:56Z (25 years, 1 month ago) by cebix
Branch: MAIN
Changes since 1.1: +4 -1 lines
Log Message:
- fixed compilation problems on BeOS

File Contents

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