ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/extfs.cpp
Revision: 1.31
Committed: 2006-04-30T15:46:55Z (18 years ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-19
Changes since 1.30: +50 -0 lines
Log Message:
handle creation time on MacOS X

File Contents

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