2
* extfs.cpp - MacOS file system for native file system access
4
* Basilisk II (C) 1997-2002 Christian Bauer
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.
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.
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
23
* Guide to the File System Manager (from FSM 1.2 SDK)
30
* (GetVolMountInfoSize)
38
#include <sys/types.h>
51
#include "cpu_emulation.h"
56
#include "user_strings.h"
58
#include "extfs_defs.h"
61
# include "posix_emu.h"
68
// File system global data and 68k routines
72
fsDrvStatus = 12, // Drive Status record
73
fsFSD = 42, // File system descriptor
74
fsPB = 238, // IOParam (for mounting and renaming), also used for temporary storage
75
fsVMI = 288, // VoumeMountInfoHeader (for mounting)
76
fsParseRec = 296, // ParsePathRec struct
77
fsReturn = 306, // Area for return data of 68k routines
78
fsAllocateVCB = 562, // UTAllocateVCB(uint16 *sysVCBLength{a0}, uint32 *vcb{a1})
79
fsAddNewVCB = 578, // UTAddNewVCB(int drive_number{d0}, int16 *vRefNum{a1}, uint32 vcb{a1})
80
fsDetermineVol = 594, // UTDetermineVol(uint32 pb{a0}, int16 *status{a1}, int16 *more_matches{a2}, int16 *vRefNum{a3}, uint32 *vcb{a4})
81
fsResolveWDCB = 614, // UTResolveWDCB(uint32 procID{d0}, int16 index{d1}, int16 vRefNum{d0}, uint32 *wdcb{a0})
82
fsGetDefaultVol = 632, // UTGetDefaultVol(uint32 wdpb{a0})
83
fsGetPathComponentName = 644, // UTGetPathComponentName(uint32 rec{a0})
84
fsParsePathname = 656, // UTParsePathname(uint32 *start{a0}, uint32 name{a1})
85
fsDisposeVCB = 670, // UTDisposeVCB(uint32 vcb{a0})
86
fsCheckWDRefNum = 682, // UTCheckWDRefNum(int16 refNum{d0})
87
fsSetDefaultVol = 694, // UTSetDefaultVol(uint32 dummy{d0}, int32 dirID{d1}, int16 refNum{d2})
88
fsAllocateFCB = 710, // UTAllocateFCB(int16 *refNum{a0}, uint32 *fcb{a1})
89
fsReleaseFCB = 724, // UTReleaseFCB(int16 refNum{d0})
90
fsIndexFCB = 736, // UTIndexFCB(uint32 vcb{a0}, int16 *refNum{a1}, uint32 *fcb{a2})
91
fsResolveFCB = 752, // UTResolveFCB(int16 refNum{d0}, uint32 *fcb{a0})
92
fsAdjustEOF = 766, // UTAdjustEOF(int16 refNum{d0})
93
fsAllocateWDCB = 778, // UTAllocateWDCB(uint32 pb{a0})
94
fsReleaseWDCB = 790, // UTReleaseWDCB(int16 vRefNum{d0})
98
static uint32 fs_data = 0; // Mac address of global data
101
// File system and volume name
102
static char FS_NAME[32], VOLUME_NAME[32];
104
// This directory is our root (read from prefs)
105
static const char *RootPath;
106
static bool ready = false;
107
static struct stat root_stat;
109
// File system ID/media type
110
const int16 MY_FSID = EMULATOR_ID_2;
111
const uint32 MY_MEDIA_TYPE = EMULATOR_ID_4;
113
// CNID of root and root's parent
114
const uint32 ROOT_ID = 2;
115
const uint32 ROOT_PARENT_ID = 1;
117
// File system stack size
118
const int STACK_SIZE = 0x10000;
120
// Allocation block and clump size as reported to MacOS (these are of course
121
// not the real values and have no meaning on the host OS)
122
const int AL_BLK_SIZE = 0x4000;
123
const int CLUMP_SIZE = 0x4000;
125
// Drive number of our pseudo-drive
126
static int drive_number;
130
const uint8 ExtFSIcon[256] = {
131
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe,
136
0x80, 0x00, 0x00, 0x91, 0x80, 0x00, 0x00, 0x91, 0x80, 0x00, 0x01, 0x21, 0x80, 0x00, 0x01, 0x21,
137
0x80, 0x00, 0x02, 0x41, 0x8c, 0x00, 0x02, 0x41, 0x80, 0x00, 0x04, 0x81, 0x80, 0x00, 0x04, 0x81,
138
0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe,
145
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
146
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
147
0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
151
// These objects are used to map CNIDs to path names
153
FSItem *next; // Pointer to next FSItem in list
154
uint32 id; // CNID of this file/dir
155
uint32 parent_id; // CNID of parent file/dir
156
FSItem *parent; // Pointer to parent
157
char name[32]; // Object name (C string)
158
time_t mtime; // Modification time for get_cat_info caching
159
int cache_dircount; // Cached number of files in directory
162
static FSItem *first_fs_item, *last_fs_item;
164
static uint32 next_cnid = fsUsrCNID; // Next available CNID
168
* Find FSItem for given CNID
171
static FSItem *find_fsitem_by_id(uint32 cnid)
173
FSItem *p = first_fs_item;
184
* Find FSItem for given name and parent, construct new FSItem if not found
187
static FSItem *find_fsitem(const char *name, FSItem *parent)
189
FSItem *p = first_fs_item;
191
if (p->parent == parent && !strcmp(p->name, name))
196
// Not found, construct new FSItem
198
last_fs_item->next = p;
202
p->parent_id = parent->id;
204
strncpy(p->name, name, 31);
212
* Get full path (->full_path) for given FSItem
215
static char full_path[MAX_PATH_LENGTH];
217
static void add_path_comp(const char *s)
219
add_path_component(full_path, s);
222
static void get_path_for_fsitem(FSItem *p)
224
if (p->id == ROOT_PARENT_ID) {
226
} else if (p->id == ROOT_ID) {
227
strncpy(full_path, RootPath, MAX_PATH_LENGTH-1);
228
full_path[MAX_PATH_LENGTH-1] = 0;
230
get_path_for_fsitem(p->parent);
231
add_path_comp(p->name);
237
* Exchange parent CNIDs in all FSItems
240
static void swap_parent_ids(uint32 parent1, uint32 parent2)
242
FSItem *p = first_fs_item;
244
if (p->parent_id == parent1)
245
p->parent_id = parent2;
246
else if (p->parent_id == parent2)
247
p->parent_id = parent1;
254
* String handling functions
257
// Copy pascal string
258
static void pstrcpy(char *dst, const char *src)
260
int size = *dst++ = *src++;
265
// Convert C string to pascal string
266
static void cstr2pstr(char *dst, const char *src)
268
*dst++ = strlen(src);
270
while ((c = *src++) != 0) {
271
// Note: we are converting host ':' characters to Mac '/' characters here
272
// '/' is not a path separator as this function is only used on object names
279
// Convert string (no length byte) to C string, length given separately
280
static void strn2cstr(char *dst, const char *src, int size)
284
// Note: we are converting Mac '/' characters to host ':' characters here
285
// '/' is not a path separator as this function is only used on object names
295
* Convert errno to MacOS error code
298
static int16 errno2oserr(void)
300
D(bug(" errno %08x\n", errno));
336
// System specific initialization
339
// Get file system and volume name
340
cstr2pstr(FS_NAME, GetString(STR_EXTFS_NAME));
341
cstr2pstr(VOLUME_NAME, GetString(STR_EXTFS_VOLUME_NAME));
343
// Create root's parent FSItem
344
FSItem *p = new FSItem;
345
first_fs_item = last_fs_item = p;
347
p->id = ROOT_PARENT_ID;
352
// Create root FSItem
354
last_fs_item->next = p;
358
p->parent_id = ROOT_PARENT_ID;
359
p->parent = first_fs_item;
360
strncpy(p->name, GetString(STR_EXTFS_VOLUME_NAME), 32);
363
// Find path for root
364
if ((RootPath = PrefsFindString("extfs")) != NULL) {
365
if (stat(RootPath, &root_stat))
367
if (!S_ISDIR(root_stat.st_mode))
380
// Delete all FSItems
381
FSItem *p = first_fs_item, *next;
387
first_fs_item = last_fs_item = NULL;
389
// System specific deinitialization
395
* Install file system
398
void InstallExtFS(void)
400
int num_blocks = 0xffff; // Fake number of blocks of our drive
403
D(bug("InstallExtFS\n"));
408
r.d[0] = gestaltFSAttr;
409
Execute68kTrap(0xa1ad, &r); // Gestalt()
410
D(bug("FSAttr %d, %08x\n", r.d[0], r.a[0]));
411
if ((r.d[0] & 0xffff) || !(r.a[0] & (1 << gestaltHasFileSystemManager))) {
412
printf("WARNING: No FSM present, disabling ExtFS\n");
416
// Yes, version >=1.2?
417
r.d[0] = gestaltFSMVersion;
418
Execute68kTrap(0xa1ad, &r); // Gestalt()
419
D(bug("FSMVersion %d, %08x\n", r.d[0], r.a[0]));
420
if ((r.d[0] & 0xffff) || (r.a[0] < 0x0120)) {
421
printf("WARNING: FSM <1.2 found, disabling ExtFS\n");
425
D(bug("FSM present\n"));
427
// Yes, allocate file system stack
429
Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
432
uint32 fs_stack = r.a[0];
434
// Allocate memory for our data structures and 68k code
435
r.d[0] = SIZEOF_fsdat;
436
Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
441
// Set up 68k code fragments
442
int p = fs_data + fsCommProcStub;
443
WriteMacInt16(p, M68K_EMUL_OP_EXTFS_COMM); p += 2;
444
WriteMacInt16(p, M68K_RTD); p += 2;
445
WriteMacInt16(p, 10); p += 2;
446
if (p - fs_data != fsHFSProcStub)
448
WriteMacInt16(p, M68K_EMUL_OP_EXTFS_HFS); p += 2;
449
WriteMacInt16(p, M68K_RTD); p += 2;
450
WriteMacInt16(p, 16);
451
p = fs_data + fsAllocateVCB;
452
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
453
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
454
WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(sp)
455
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
456
WriteMacInt16(p, 0x7006); p+= 2; // UTAllocateVCB
457
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
458
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
459
WriteMacInt16(p, M68K_RTS); p+= 2;
460
if (p - fs_data != fsAddNewVCB)
462
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
463
WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
464
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(a7)
465
WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(a7)
466
WriteMacInt16(p, 0x7007); p+= 2; // UTAddNewVCB
467
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
468
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
469
WriteMacInt16(p, M68K_RTS); p+= 2;
470
if (p - fs_data != fsDetermineVol)
472
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
473
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
474
WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(sp)
475
WriteMacInt16(p, 0x2f0a); p+= 2; // move.l a2,-(sp)
476
WriteMacInt16(p, 0x2f0b); p+= 2; // move.l a3,-(sp)
477
WriteMacInt16(p, 0x2f0c); p+= 2; // move.l a4,-(sp)
478
WriteMacInt16(p, 0x701d); p+= 2; // UTDetermineVol
479
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
480
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
481
WriteMacInt16(p, M68K_RTS); p+= 2;
482
if (p - fs_data != fsResolveWDCB)
484
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
485
WriteMacInt16(p, 0x2f00); p+= 2; // move.l d0,-(sp)
486
WriteMacInt16(p, 0x3f01); p+= 2; // move.w d1,-(sp)
487
WriteMacInt16(p, 0x3f02); p+= 2; // move.w d2,-(sp)
488
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
489
WriteMacInt16(p, 0x700e); p+= 2; // UTResolveWDCB
490
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
491
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
492
WriteMacInt16(p, M68K_RTS); p+= 2;
493
if (p - fs_data != fsGetDefaultVol)
495
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
496
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
497
WriteMacInt16(p, 0x7012); p+= 2; // UTGetDefaultVol
498
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
499
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
500
WriteMacInt16(p, M68K_RTS); p+= 2;
501
if (p - fs_data != fsGetPathComponentName)
503
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
504
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
505
WriteMacInt16(p, 0x701c); p+= 2; // UTGetPathComponentName
506
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
507
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
508
WriteMacInt16(p, M68K_RTS); p+= 2;
509
if (p - fs_data != fsParsePathname)
511
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
512
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
513
WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(sp)
514
WriteMacInt16(p, 0x701b); p+= 2; // UTParsePathname
515
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
516
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
517
WriteMacInt16(p, M68K_RTS); p+= 2;
518
if (p - fs_data != fsDisposeVCB)
520
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
521
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
522
WriteMacInt16(p, 0x7008); p+= 2; // UTDisposeVCB
523
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
524
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
525
WriteMacInt16(p, M68K_RTS); p+= 2;
526
if (p - fs_data != fsCheckWDRefNum)
528
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
529
WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
530
WriteMacInt16(p, 0x7013); p+= 2; // UTCheckWDRefNum
531
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
532
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
533
WriteMacInt16(p, M68K_RTS); p+= 2;
534
if (p - fs_data != fsSetDefaultVol)
536
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
537
WriteMacInt16(p, 0x2f00); p+= 2; // move.l d0,-(sp)
538
WriteMacInt16(p, 0x2f01); p+= 2; // move.l d1,-(sp)
539
WriteMacInt16(p, 0x3f02); p+= 2; // move.w d2,-(sp)
540
WriteMacInt16(p, 0x7011); p+= 2; // UTSetDefaultVol
541
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
542
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
543
WriteMacInt16(p, M68K_RTS); p+= 2;
544
if (p - fs_data != fsAllocateFCB)
546
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
547
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
548
WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(sp)
549
WriteMacInt16(p, 0x7000); p+= 2; // UTAllocateFCB
550
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
551
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
552
WriteMacInt16(p, M68K_RTS); p+= 2;
553
if (p - fs_data != fsReleaseFCB)
555
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
556
WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
557
WriteMacInt16(p, 0x7001); p+= 2; // UTReleaseFCB
558
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
559
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
560
WriteMacInt16(p, M68K_RTS); p+= 2;
561
if (p - fs_data != fsIndexFCB)
563
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
564
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
565
WriteMacInt16(p, 0x2f09); p+= 2; // move.l a1,-(sp)
566
WriteMacInt16(p, 0x2f0a); p+= 2; // move.l a2,-(sp)
567
WriteMacInt16(p, 0x7004); p+= 2; // UTIndexFCB
568
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
569
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
570
WriteMacInt16(p, M68K_RTS); p+= 2;
571
if (p - fs_data != fsResolveFCB)
573
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
574
WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
575
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
576
WriteMacInt16(p, 0x7005); p+= 2; // UTResolveFCB
577
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
578
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
579
WriteMacInt16(p, M68K_RTS); p+= 2;
580
if (p - fs_data != fsAdjustEOF)
582
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
583
WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
584
WriteMacInt16(p, 0x7010); p+= 2; // UTAdjustEOF
585
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
586
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
587
WriteMacInt16(p, M68K_RTS); p+= 2;
588
if (p - fs_data != fsAllocateWDCB)
590
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
591
WriteMacInt16(p, 0x2f08); p+= 2; // move.l a0,-(sp)
592
WriteMacInt16(p, 0x700c); p+= 2; // UTAllocateWDCB
593
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
594
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
595
WriteMacInt16(p, M68K_RTS); p+= 2;
596
if (p - fs_data != fsReleaseWDCB)
598
WriteMacInt16(p, 0x4267); p+= 2; // clr.w -(sp)
599
WriteMacInt16(p, 0x3f00); p+= 2; // move.w d0,-(sp)
600
WriteMacInt16(p, 0x700d); p+= 2; // UTReleaseWDCB
601
WriteMacInt16(p, 0xa824); p+= 2; // FSMgr
602
WriteMacInt16(p, 0x301f); p+= 2; // move.w (sp)+,d0
603
WriteMacInt16(p, M68K_RTS); p+= 2;
604
if (p - fs_data != SIZEOF_fsdat)
607
// Set up drive status
608
WriteMacInt8(fs_data + fsDrvStatus + dsDiskInPlace, 8); // Fixed disk
609
WriteMacInt8(fs_data + fsDrvStatus + dsInstalled, 1);
610
WriteMacInt16(fs_data + fsDrvStatus + dsQType, hard20);
611
WriteMacInt16(fs_data + fsDrvStatus + dsDriveSize, num_blocks & 0xffff);
612
WriteMacInt16(fs_data + fsDrvStatus + dsDriveS1, num_blocks >> 16);
613
WriteMacInt16(fs_data + fsDrvStatus + dsQFSID, MY_FSID);
615
// Add drive to drive queue
616
drive_number = FindFreeDriveNumber(1);
617
D(bug(" adding drive %d\n", drive_number));
618
r.d[0] = (drive_number << 16) | (DiskRefNum & 0xffff);
619
r.a[0] = fs_data + fsDrvStatus + dsQLink;
620
Execute68kTrap(0xa04e, &r); // AddDrive()
622
// Init FSDRec and install file system
623
D(bug(" installing file system\n"));
624
WriteMacInt16(fs_data + fsFSD + fsdLength, SIZEOF_FSDRec);
625
WriteMacInt16(fs_data + fsFSD + fsdVersion, fsdVersion1);
626
WriteMacInt16(fs_data + fsFSD + fileSystemFSID, MY_FSID);
627
Host2Mac_memcpy(fs_data + fsFSD + fileSystemName, FS_NAME, 32);
628
WriteMacInt32(fs_data + fsFSD + fileSystemCommProc, fs_data + fsCommProcStub);
629
WriteMacInt32(fs_data + fsFSD + fsdHFSCI + compInterfProc, fs_data + fsHFSProcStub);
630
WriteMacInt32(fs_data + fsFSD + fsdHFSCI + stackTop, fs_stack + STACK_SIZE);
631
WriteMacInt32(fs_data + fsFSD + fsdHFSCI + stackSize, STACK_SIZE);
632
WriteMacInt32(fs_data + fsFSD + fsdHFSCI + idSector, (uint32)-1);
633
r.a[0] = fs_data + fsFSD;
634
r.d[0] = 0; // InstallFS
635
Execute68kTrap(0xa0ac, &r); // FSMDispatch()
636
D(bug(" InstallFS() returned %d\n", r.d[0]));
638
// Enable HFS component
639
D(bug(" enabling HFS component\n"));
640
WriteMacInt32(fs_data + fsFSD + fsdHFSCI + compInterfMask, ReadMacInt32(fs_data + fsFSD + fsdHFSCI + compInterfMask) | (fsmComponentEnableMask | hfsCIResourceLoadedMask | hfsCIDoesHFSMask));
641
r.a[0] = fs_data + fsFSD;
642
r.d[3] = SIZEOF_FSDRec;
644
r.d[0] = 5; // SetFSInfo
645
Execute68kTrap(0xa0ac, &r); // FSMDispatch()
646
D(bug(" SetFSInfo() returned %d\n", r.d[0]));
649
D(bug(" mounting volume\n"));
650
WriteMacInt32(fs_data + fsPB + ioBuffer, fs_data + fsVMI);
651
WriteMacInt16(fs_data + fsVMI + vmiLength, SIZEOF_VolumeMountInfoHeader);
652
WriteMacInt32(fs_data + fsVMI + vmiMedia, MY_MEDIA_TYPE);
653
r.a[0] = fs_data + fsPB;
654
r.d[0] = 0x41; // PBVolumeMount
655
Execute68kTrap(0xa260, &r); // HFSDispatch()
656
D(bug(" PBVolumeMount() returned %d\n", r.d[0]));
660
printf("FATAL: ExtFS data block initialization error\n");
666
* FS communications function
669
int16 ExtFSComm(uint16 message, uint32 paramBlock, uint32 globalsPtr)
671
D(bug("ExtFSComm(%d, %08lx, %08lx)\n", message, paramBlock, globalsPtr));
676
case ffsUnloadMessage:
679
case ffsGetIconMessage: { // Get disk/drive icon
680
if (ReadMacInt8(paramBlock + iconType) == kLargeIcon && ReadMacInt32(paramBlock + requestSize) >= sizeof(ExtFSIcon)) {
681
Host2Mac_memcpy(ReadMacInt32(paramBlock + iconBufferPtr), ExtFSIcon, sizeof(ExtFSIcon));
682
WriteMacInt32(paramBlock + actualSize, sizeof(ExtFSIcon));
685
return -5012; // afpItemNotFound
688
case ffsIDDiskMessage: { // Check if volume is handled by our FS
689
if ((int16)ReadMacInt16(paramBlock + ioVRefNum) == drive_number)
695
case ffsIDVolMountMessage: { // Check if volume can be mounted by our FS
696
if (ReadMacInt32(ReadMacInt32(paramBlock + ioBuffer) + vmiMedia) == MY_MEDIA_TYPE)
703
return fsmUnknownFSMMessageErr;
709
* Get current directory specified by given ParamBlock/dirID
712
static int16 get_current_dir(uint32 pb, uint32 dirID, uint32 ¤t_dir, bool no_vol_name = false)
718
D(bug(" determining volume, dirID %d\n", dirID));
720
r.a[1] = fs_data + fsReturn;
721
r.a[2] = fs_data + fsReturn + 2;
722
r.a[3] = fs_data + fsReturn + 4;
723
r.a[4] = fs_data + fsReturn + 6;
726
name_ptr = ReadMacInt32(pb + ioNamePtr);
727
WriteMacInt32(pb + ioNamePtr, 0);
729
Execute68k(fs_data + fsDetermineVol, &r);
731
WriteMacInt32(pb + ioNamePtr, name_ptr);
732
int16 status = ReadMacInt16(fs_data + fsReturn);
733
D(bug(" UTDetermineVol() returned %d, status %d\n", r.d[0], status));
734
result = (int16)(r.d[0] & 0xffff);
736
if (result == noErr) {
738
case dtmvFullPathname: // Determined by full pathname
739
current_dir = ROOT_ID;
742
case dtmvVRefNum: // Determined by refNum or by drive number
744
current_dir = dirID ? dirID : ROOT_ID;
747
case dtmvWDRefNum: // Determined by working directory refNum
751
D(bug(" resolving WDCB\n"));
754
r.d[2] = ReadMacInt16(pb + ioVRefNum);
755
r.a[0] = fs_data + fsReturn;
756
Execute68k(fs_data + fsResolveWDCB, &r);
757
uint32 wdcb = ReadMacInt32(fs_data + fsReturn);
758
D(bug(" UTResolveWDCB() returned %d, dirID %d\n", r.d[0], ReadMacInt32(wdcb + wdDirID)));
759
result = (int16)(r.d[0] & 0xffff);
761
current_dir = ReadMacInt32(wdcb + wdDirID);
765
case dtmvDefault: // Determined by default volume
769
uint32 wdpb = fs_data + fsReturn;
770
WriteMacInt32(wdpb + ioNamePtr, 0);
771
D(bug(" getting default volume\n"));
773
Execute68k(fs_data + fsGetDefaultVol, &r);
774
D(bug(" UTGetDefaultVol() returned %d, dirID %d\n", r.d[0], ReadMacInt32(wdpb + ioWDDirID)));
775
result = (int16)(r.d[0] & 0xffff);
777
current_dir = ReadMacInt32(wdpb + ioWDDirID);
791
* Get path component name
794
static int16 get_path_component_name(uint32 rec)
796
// D(bug(" getting path component\n"));
799
Execute68k(fs_data + fsGetPathComponentName, &r);
800
// D(bug(" UTGetPathComponentName returned %d\n", r.d[0]));
801
return (int16)(r.d[0] & 0xffff);
806
* Get FSItem and full path (->full_path) for file/dir specified in ParamBlock
809
static int16 get_item_and_path(uint32 pb, uint32 dirID, FSItem *&item, bool no_vol_name = false)
813
// Find FSItem for parent directory
816
if ((result = get_current_dir(pb, dirID, current_dir, no_vol_name)) != noErr)
818
D(bug(" current dir %08x\n", current_dir));
819
FSItem *p = find_fsitem_by_id(current_dir);
824
uint32 parseRec = fs_data + fsParseRec;
825
WriteMacInt32(parseRec + ppNamePtr, ReadMacInt32(pb + ioNamePtr));
826
WriteMacInt16(parseRec + ppStartOffset, 0);
827
WriteMacInt16(parseRec + ppComponentLength, 0);
828
WriteMacInt8(parseRec + ppMoreName, false);
829
WriteMacInt8(parseRec + ppFoundDelimiter, false);
831
// Get length of volume name
832
D(bug(" parsing pathname\n"));
833
r.a[0] = parseRec + ppStartOffset;
834
r.a[1] = ReadMacInt32(parseRec + ppNamePtr);
835
Execute68k(fs_data + fsParsePathname, &r);
836
D(bug(" UTParsePathname() returned %d, startOffset %d\n", r.d[0], ReadMacInt16(parseRec + ppStartOffset)));
837
result = (int16)(r.d[0] & 0xffff);
838
if (result == noErr) {
840
// Check for leading delimiter of the partial pathname
841
result = get_path_component_name(parseRec);
842
if (result == noErr) {
843
if (ReadMacInt16(parseRec + ppComponentLength) == 0 && ReadMacInt8(parseRec + ppFoundDelimiter)) {
844
// Get past initial delimiter
845
WriteMacInt16(parseRec + ppStartOffset, ReadMacInt16(parseRec + ppStartOffset) + 1);
848
// Parse until there is no more pathname to parse
849
while ((result == noErr) && ReadMacInt8(parseRec + ppMoreName)) {
851
// Search for the next delimiter from startOffset
852
result = get_path_component_name(parseRec);
853
if (result == noErr) {
854
if (ReadMacInt16(parseRec + ppComponentLength) == 0) {
856
// Delimiter immediately following another delimiter, get parent
857
if (current_dir != ROOT_ID) {
863
// startOffset = start of next component
864
WriteMacInt16(parseRec + ppStartOffset, ReadMacInt16(parseRec + ppStartOffset) + 1);
866
} else if (ReadMacInt8(parseRec + ppMoreName)) {
868
// Component found and isn't the last, so it must be a directory, enter it
870
strn2cstr(name, (char *)Mac2HostAddr(ReadMacInt32(parseRec + ppNamePtr)) + ReadMacInt16(parseRec + ppStartOffset) + 1, ReadMacInt16(parseRec + ppComponentLength));
871
D(bug(" entering %s\n", name));
872
p = find_fsitem(name, p);
875
// startOffset = start of next component
876
WriteMacInt16(parseRec + ppStartOffset, ReadMacInt16(parseRec + ppStartOffset) + ReadMacInt16(parseRec + ppComponentLength) + 1);
881
if (result == noErr) {
883
// There is no more pathname to parse
884
if (ReadMacInt16(parseRec + ppComponentLength) == 0) {
886
// Pathname ended with '::' or was simply a volume name, so current directory is the object
891
// Pathname ended with 'name:' or 'name', so name is the object
893
strn2cstr(name, (char *)Mac2HostAddr(ReadMacInt32(parseRec + ppNamePtr)) + ReadMacInt16(parseRec + ppStartOffset) + 1, ReadMacInt16(parseRec + ppComponentLength));
894
D(bug(" object is %s\n", name));
895
item = find_fsitem(name, p);
902
// Default to bad name
905
if (ReadMacInt32(pb + ioNamePtr) == 0 || ReadMacInt8(ReadMacInt32(pb + ioNamePtr)) == 0) {
907
// Pathname was NULL or a zero length string, so we found a directory at the end of the string
914
if (result == noErr) {
915
get_path_for_fsitem(item);
916
D(bug(" path %s\n", full_path));
923
* Find FCB for given file RefNum
926
static uint32 find_fcb(int16 refNum)
928
D(bug(" finding FCB\n"));
931
r.a[0] = fs_data + fsReturn;
932
Execute68k(fs_data + fsResolveFCB, &r);
933
uint32 fcb = ReadMacInt32(fs_data + fsReturn);
934
D(bug(" UTResolveFCB() returned %d, fcb %08lx\n", r.d[0], fcb));
943
* HFS interface functions
946
// Check if volume belongs to our FS
947
static int16 fs_mount_vol(uint32 pb)
949
D(bug(" fs_mount_vol(%08lx), vRefNum %d\n", pb, ReadMacInt16(pb + ioVRefNum)));
950
if ((int16)ReadMacInt16(pb + ioVRefNum) == drive_number)
957
static int16 fs_volume_mount(uint32 pb)
959
D(bug(" fs_volume_mount(%08lx)\n", pb));
963
D(bug(" creating VCB\n"));
964
r.a[0] = fs_data + fsReturn;
965
r.a[1] = fs_data + fsReturn + 2;
966
Execute68k(fs_data + fsAllocateVCB, &r);
968
uint16 sysVCBLength = ReadMacInt16(fs_data + fsReturn);
970
uint32 vcb = ReadMacInt32(fs_data + fsReturn + 2);
971
D(bug(" UTAllocateVCB() returned %d, vcb %08lx, size %d\n", r.d[0], vcb, sysVCBLength));
973
return (int16)r.d[0];
976
WriteMacInt16(vcb + vcbSigWord, 0x4244);
977
#if defined(__BEOS__) || defined(WIN32)
978
WriteMacInt32(vcb + vcbCrDate, TimeToMacTime(root_stat.st_crtime));
980
WriteMacInt32(vcb + vcbCrDate, 0);
982
WriteMacInt32(vcb + vcbLsMod, TimeToMacTime(root_stat.st_mtime));
983
WriteMacInt32(vcb + vcbVolBkUp, 0);
984
WriteMacInt16(vcb + vcbNmFls, 1); //!!
985
WriteMacInt16(vcb + vcbNmRtDirs, 1); //!!
986
WriteMacInt16(vcb + vcbNmAlBlks, 0xffff); //!!
987
WriteMacInt32(vcb + vcbAlBlkSiz, AL_BLK_SIZE);
988
WriteMacInt32(vcb + vcbClpSiz, CLUMP_SIZE);
989
WriteMacInt32(vcb + vcbNxtCNID, next_cnid);
990
WriteMacInt16(vcb + vcbFreeBks, 0xffff); //!!
991
Host2Mac_memcpy(vcb + vcbVN, VOLUME_NAME, 28);
992
WriteMacInt16(vcb + vcbFSID, MY_FSID);
993
WriteMacInt32(vcb + vcbFilCnt, 1); //!!
994
WriteMacInt32(vcb + vcbDirCnt, 1); //!!
996
// Add VCB to VCB queue
997
D(bug(" adding VCB to queue\n"));
998
r.d[0] = drive_number;
999
r.a[0] = fs_data + fsReturn;
1001
Execute68k(fs_data + fsAddNewVCB, &r);
1002
int16 vRefNum = (int16)ReadMacInt32(fs_data + fsReturn);
1003
D(bug(" UTAddNewVCB() returned %d, vRefNum %d\n", r.d[0], vRefNum));
1004
if (r.d[0] & 0xffff)
1005
return (int16)r.d[0];
1007
// Post diskInsertEvent
1008
D(bug(" posting diskInsertEvent\n"));
1009
r.d[0] = drive_number;
1010
r.a[0] = 7; // diskEvent
1011
Execute68kTrap(0xa02f, &r); // PostEvent()
1013
// Return volume RefNum
1014
WriteMacInt16(pb + ioVRefNum, vRefNum);
1019
static int16 fs_unmount_vol(uint32 vcb)
1021
D(bug(" fs_unmount_vol(%08lx), vRefNum %d\n", vcb, ReadMacInt16(vcb + vcbVRefNum)));
1024
// Remove and free VCB
1025
D(bug(" freeing VCB\n"));
1027
Execute68k(fs_data + fsDisposeVCB, &r);
1028
D(bug(" UTDisposeVCB() returned %d\n", r.d[0]));
1029
return (int16)r.d[0];
1032
// Get information about a volume (HVolumeParam)
1033
static int16 fs_get_vol_info(uint32 pb, bool hfs)
1035
// D(bug(" fs_get_vol_info(%08lx)\n", pb));
1038
if (ReadMacInt32(pb + ioNamePtr))
1039
pstrcpy((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), VOLUME_NAME);
1040
#if defined(__BEOS__) || defined(WIN32)
1041
WriteMacInt32(pb + ioVCrDate, TimeToMacTime(root_stat.st_crtime));
1043
WriteMacInt32(pb + ioVCrDate, 0);
1045
WriteMacInt32(pb + ioVLsMod, TimeToMacTime(root_stat.st_mtime));
1046
WriteMacInt16(pb + ioVAtrb, 0);
1047
WriteMacInt16(pb + ioVNmFls, 1); //!!
1048
WriteMacInt16(pb + ioVBitMap, 0);
1049
WriteMacInt16(pb + ioAllocPtr, 0);
1050
WriteMacInt16(pb + ioVNmAlBlks, 0xffff); //!!
1051
WriteMacInt32(pb + ioVAlBlkSiz, AL_BLK_SIZE);
1052
WriteMacInt32(pb + ioVClpSiz, CLUMP_SIZE);
1053
WriteMacInt16(pb + ioAlBlSt, 0);
1054
WriteMacInt32(pb + ioVNxtCNID, next_cnid);
1055
WriteMacInt16(pb + ioVFrBlk, 0xffff); //!!
1057
WriteMacInt16(pb + ioVDrvInfo, drive_number);
1058
WriteMacInt16(pb + ioVDRefNum, ReadMacInt16(fs_data + fsDrvStatus + dsQRefNum));
1059
WriteMacInt16(pb + ioVFSID, MY_FSID);
1060
WriteMacInt32(pb + ioVBkUp, 0);
1061
WriteMacInt16(pb + ioVSeqNum, 0);
1062
WriteMacInt32(pb + ioVWrCnt, 0);
1063
WriteMacInt32(pb + ioVFilCnt, 1); //!!
1064
WriteMacInt32(pb + ioVDirCnt, 1); //!!
1065
Mac_memset(pb + ioVFndrInfo, 0, 32);
1070
// Change volume information (HVolumeParam)
1071
static int16 fs_set_vol_info(uint32 pb)
1073
D(bug(" fs_set_vol_info(%08lx)\n", pb));
1079
// Get volume parameter block
1080
static int16 fs_get_vol_parms(uint32 pb)
1082
// D(bug(" fs_get_vol_parms(%08lx)\n", pb));
1084
// Return parameter block
1085
uint32 actual = ReadMacInt32(pb + ioReqCount);
1086
if (actual > SIZEOF_GetVolParmsInfoBuffer)
1087
actual = SIZEOF_GetVolParmsInfoBuffer;
1088
WriteMacInt32(pb + ioActCount, actual);
1089
uint32 p = ReadMacInt32(pb + ioBuffer);
1090
if (actual > vMVersion) WriteMacInt16(p + vMVersion, 2);
1091
if (actual > vMAttrib) WriteMacInt32(p + vMAttrib, kNoMiniFndr | kNoVNEdit | kNoLclSync | kTrshOffLine | kNoSwitchTo | kNoBootBlks | kNoSysDir | kHasExtFSVol);
1092
if (actual > vMLocalHand) WriteMacInt32(p + vMLocalHand, 0);
1093
if (actual > vMServerAdr) WriteMacInt32(p + vMServerAdr, 0);
1094
if (actual > vMVolumeGrade) WriteMacInt32(p + vMVolumeGrade, 0);
1095
if (actual > vMForeignPrivID) WriteMacInt16(p + vMForeignPrivID, 0);
1099
// Get default volume (WDParam)
1100
static int16 fs_get_vol(uint32 pb)
1102
D(bug(" fs_get_vol(%08lx)\n", pb));
1105
// Getting default volume
1106
D(bug(" getting default volume\n"));
1108
Execute68k(fs_data + fsGetDefaultVol, &r);
1109
D(bug(" UTGetDefaultVol() returned %d\n", r.d[0]));
1110
return (int16)r.d[0];
1113
// Set default volume (WDParam)
1114
static int16 fs_set_vol(uint32 pb, bool hfs, uint32 vcb)
1116
D(bug(" fs_set_vol(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt32(pb + ioWDDirID)));
1119
// Determine parameters
1124
// Find FSItem for given dir
1126
int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioWDDirID), fs_item);
1127
if (result != noErr)
1130
// Is it a directory?
1132
if (stat(full_path, &st))
1134
if (!S_ISDIR(st.st_mode))
1137
// Get dirID and refNum
1138
dirID = fs_item->id;
1139
refNum = ReadMacInt16(vcb + vcbVRefNum);
1143
// Is the given vRefNum a working directory number?
1144
D(bug(" checking for WDRefNum\n"));
1145
r.d[0] = ReadMacInt16(pb + ioVRefNum);
1146
Execute68k(fs_data + fsCheckWDRefNum, &r);
1147
D(bug(" UTCheckWDRefNum() returned %d\n", r.d[0]));
1148
if (r.d[0] & 0xffff) {
1151
refNum = ReadMacInt16(vcb + vcbVRefNum);
1155
refNum = ReadMacInt16(pb + ioVRefNum);
1159
// Setting default volume
1160
D(bug(" setting default volume\n"));
1164
Execute68k(fs_data + fsSetDefaultVol, &r);
1165
D(bug(" UTSetDefaultVol() returned %d\n", r.d[0]));
1166
return (int16)r.d[0];
1169
// Query file attributes (HFileParam)
1170
static int16 fs_get_file_info(uint32 pb, bool hfs, uint32 dirID)
1172
D(bug(" fs_get_file_info(%08lx), vRefNum %d, name %.31s, idx %d, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt16(pb + ioFDirIndex), dirID));
1175
int16 dir_index = ReadMacInt16(pb + ioFDirIndex);
1176
if (dir_index <= 0) { // Query item specified by ioDirID and ioNamePtr
1178
// Find FSItem for given file
1179
int16 result = get_item_and_path(pb, dirID, fs_item);
1180
if (result != noErr)
1183
} else { // Query item in directory specified by ioDirID by index
1185
// Find FSItem for parent directory
1188
if ((result = get_current_dir(pb, dirID, current_dir, true)) != noErr)
1190
FSItem *p = find_fsitem_by_id(current_dir);
1193
get_path_for_fsitem(p);
1195
// Look for nth item in directory and add name to path
1196
DIR *d = opendir(full_path);
1199
struct dirent *de = NULL;
1200
for (int i=0; i<dir_index; i++) {
1207
if (de->d_name[0] == '.')
1208
goto read_next_de; // Suppress names beginning with '.' (MacOS could interpret these as driver names)
1209
//!! suppress directories
1211
add_path_comp(de->d_name);
1213
// Get FSItem for queried item
1214
fs_item = find_fsitem(de->d_name, p);
1220
if (stat(full_path, &st))
1222
if (S_ISDIR(st.st_mode))
1225
// Fill in struct from fs_item and stats
1226
if (ReadMacInt32(pb + ioNamePtr))
1227
cstr2pstr((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), fs_item->name);
1228
WriteMacInt16(pb + ioFRefNum, 0);
1229
WriteMacInt8(pb + ioFlAttrib, access(full_path, W_OK) == 0 ? 0 : faLocked);
1230
WriteMacInt32(pb + ioDirID, fs_item->id);
1232
#if defined(__BEOS__) || defined(WIN32)
1233
WriteMacInt32(pb + ioFlCrDat, TimeToMacTime(st.st_crtime));
1235
WriteMacInt32(pb + ioFlCrDat, 0);
1237
WriteMacInt32(pb + ioFlMdDat, TimeToMacTime(st.st_mtime));
1239
get_finfo(full_path, pb + ioFlFndrInfo, hfs ? pb + ioFlXFndrInfo : 0, false);
1241
WriteMacInt16(pb + ioFlStBlk, 0);
1242
WriteMacInt32(pb + ioFlLgLen, st.st_size);
1243
WriteMacInt32(pb + ioFlPyLen, (st.st_size | (AL_BLK_SIZE - 1)) + 1);
1244
WriteMacInt16(pb + ioFlRStBlk, 0);
1245
uint32 rf_size = get_rfork_size(full_path);
1246
WriteMacInt32(pb + ioFlRLgLen, rf_size);
1247
WriteMacInt32(pb + ioFlRPyLen, (rf_size | (AL_BLK_SIZE - 1)) + 1);
1250
WriteMacInt32(pb + ioFlBkDat, 0);
1251
WriteMacInt32(pb + ioFlParID, fs_item->parent_id);
1252
WriteMacInt32(pb + ioFlClpSiz, 0);
1257
// Set file attributes (HFileParam)
1258
static int16 fs_set_file_info(uint32 pb, bool hfs, uint32 dirID)
1260
D(bug(" fs_set_file_info(%08lx), vRefNum %d, name %.31s, idx %d, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt16(pb + ioFDirIndex), dirID));
1262
// Find FSItem for given file/dir
1264
int16 result = get_item_and_path(pb, dirID, fs_item);
1265
if (result != noErr)
1270
if (stat(full_path, &st) < 0)
1271
return errno2oserr();
1272
if (S_ISDIR(st.st_mode))
1276
set_finfo(full_path, pb + ioFlFndrInfo, hfs ? pb + ioFlXFndrInfo : 0, false);
1282
// Query file/directory attributes
1283
static int16 fs_get_cat_info(uint32 pb)
1285
D(bug(" fs_get_cat_info(%08lx), vRefNum %d, name %.31s, idx %d, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt16(pb + ioFDirIndex), ReadMacInt32(pb + ioDirID)));
1288
int16 dir_index = ReadMacInt16(pb + ioFDirIndex);
1289
if (dir_index < 0) { // Query directory specified by ioDirID
1291
// Find FSItem for directory
1292
fs_item = find_fsitem_by_id(ReadMacInt32(pb + ioDrDirID));
1293
if (fs_item == NULL)
1295
get_path_for_fsitem(fs_item);
1297
} else if (dir_index == 0) { // Query item specified by ioDirID and ioNamePtr
1299
// Find FSItem for given file/dir
1300
int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1301
if (result != noErr)
1304
} else { // Query item in directory specified by ioDirID by index
1306
// Find FSItem for parent directory
1309
if ((result = get_current_dir(pb, ReadMacInt32(pb + ioDirID), current_dir, true)) != noErr)
1311
FSItem *p = find_fsitem_by_id(current_dir);
1314
get_path_for_fsitem(p);
1316
// Look for nth item in directory and add name to path
1317
DIR *d = opendir(full_path);
1320
struct dirent *de = NULL;
1321
for (int i=0; i<dir_index; i++) {
1328
if (de->d_name[0] == '.')
1329
goto read_next_de; // Suppress names beginning with '.' (MacOS could interpret these as driver names)
1331
add_path_comp(de->d_name);
1333
// Get FSItem for queried item
1334
fs_item = find_fsitem(de->d_name, p);
1337
D(bug(" path %s\n", full_path));
1341
if (stat(full_path, &st) < 0)
1342
return errno2oserr();
1343
if (dir_index == -1 && !S_ISDIR(st.st_mode))
1346
// Fill in struct from fs_item and stats
1347
if (ReadMacInt32(pb + ioNamePtr))
1348
cstr2pstr((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), fs_item->name);
1349
WriteMacInt16(pb + ioFRefNum, 0);
1350
WriteMacInt8(pb + ioFlAttrib, (S_ISDIR(st.st_mode) ? faIsDir : 0) | (access(full_path, W_OK) == 0 ? 0 : faLocked));
1351
WriteMacInt8(pb + ioACUser, 0);
1352
WriteMacInt32(pb + ioDirID, fs_item->id);
1353
WriteMacInt32(pb + ioFlParID, fs_item->parent_id);
1354
#if defined(__BEOS__) || defined(WIN32)
1355
WriteMacInt32(pb + ioFlCrDat, TimeToMacTime(st.st_crtime));
1357
WriteMacInt32(pb + ioFlCrDat, 0);
1359
time_t mtime = st.st_mtime;
1361
if (mtime > fs_item->mtime) {
1362
fs_item->mtime = mtime;
1365
WriteMacInt32(pb + ioFlMdDat, TimeToMacTime(mtime));
1366
WriteMacInt32(pb + ioFlBkDat, 0);
1368
get_finfo(full_path, pb + ioFlFndrInfo, pb + ioFlXFndrInfo, S_ISDIR(st.st_mode));
1370
if (S_ISDIR(st.st_mode)) {
1372
// Determine number of files in directory (cached)
1375
count = fs_item->cache_dircount;
1378
DIR *d = opendir(full_path);
1385
if (de->d_name[0] == '.')
1386
continue; // Suppress names beginning with '.'
1391
fs_item->cache_dircount = count;
1393
WriteMacInt16(pb + ioDrNmFls, count);
1395
WriteMacInt16(pb + ioFlStBlk, 0);
1396
WriteMacInt32(pb + ioFlLgLen, st.st_size);
1397
WriteMacInt32(pb + ioFlPyLen, (st.st_size | (AL_BLK_SIZE - 1)) + 1);
1398
WriteMacInt16(pb + ioFlRStBlk, 0);
1399
uint32 rf_size = get_rfork_size(full_path);
1400
WriteMacInt32(pb + ioFlRLgLen, rf_size);
1401
WriteMacInt32(pb + ioFlRPyLen, (rf_size | (AL_BLK_SIZE - 1)) + 1);
1402
WriteMacInt32(pb + ioFlClpSiz, 0);
1407
// Set file/directory attributes
1408
static int16 fs_set_cat_info(uint32 pb)
1410
D(bug(" fs_set_cat_info(%08lx), vRefNum %d, name %.31s, idx %d, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt16(pb + ioFDirIndex), ReadMacInt32(pb + ioDirID)));
1412
// Find FSItem for given file/dir
1414
int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1415
if (result != noErr)
1420
if (stat(full_path, &st) < 0)
1421
return errno2oserr();
1424
set_finfo(full_path, pb + ioFlFndrInfo, pb + ioFlXFndrInfo, S_ISDIR(st.st_mode));
1431
static int16 fs_open(uint32 pb, uint32 dirID, uint32 vcb, bool resource_fork)
1433
D(bug(" fs_open(%08lx), %s, vRefNum %d, name %.31s, dirID %d, perm %d\n", pb, resource_fork ? "rsrc" : "data", ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), dirID, ReadMacInt8(pb + ioPermssn)));
1436
// Find FSItem for given file
1438
int16 result = get_item_and_path(pb, dirID, fs_item);
1439
if (result != noErr)
1442
// Convert ioPermssn to open() flag
1444
bool write_ok = (access(full_path, W_OK) == 0);
1445
switch (ReadMacInt8(pb + ioPermssn)) {
1446
case fsCurPerm: // Whatever is currently allowed
1452
case fsRdPerm: // Exclusive read
1455
case fsWrPerm: // Exclusive write
1458
case fsRdWrPerm: // Exclusive read/write
1459
case fsRdWrShPerm: // Shared read/write
1465
// Try to open and stat the file
1468
if (resource_fork) {
1469
if (access(full_path, F_OK))
1471
fd = open_rfork(full_path, flag);
1473
if (fstat(fd, &st) < 0) {
1475
return errno2oserr();
1477
} else { // Resource fork not supported, silently ignore it ("pseudo" resource fork)
1482
fd = open(full_path, flag);
1484
return errno2oserr();
1485
if (fstat(fd, &st) < 0) {
1487
return errno2oserr();
1491
// File open, allocate FCB
1492
D(bug(" allocating FCB\n"));
1493
r.a[0] = pb + ioRefNum;
1494
r.a[1] = fs_data + fsReturn;
1495
Execute68k(fs_data + fsAllocateFCB, &r);
1496
uint32 fcb = ReadMacInt32(fs_data + fsReturn);
1497
D(bug(" UTAllocateFCB() returned %d, fRefNum %d, fcb %08lx\n", r.d[0], ReadMacInt16(pb + ioRefNum), fcb));
1498
if (r.d[0] & 0xffff) {
1500
return (int16)r.d[0];
1503
// Initialize FCB, fd is stored in fcbCatPos
1504
WriteMacInt32(fcb + fcbFlNm, fs_item->id);
1505
WriteMacInt8(fcb + fcbFlags, ((flag == O_WRONLY || flag == O_RDWR) ? fcbWriteMask : 0) | (resource_fork ? fcbResourceMask : 0) | (write_ok ? 0 : fcbFileLockedMask));
1506
WriteMacInt32(fcb + fcbEOF, st.st_size);
1507
WriteMacInt32(fcb + fcbPLen, (st.st_size | (AL_BLK_SIZE - 1)) + 1);
1508
WriteMacInt32(fcb + fcbCrPs, 0);
1509
WriteMacInt32(fcb + fcbVPtr, vcb);
1510
WriteMacInt32(fcb + fcbClmpSize, CLUMP_SIZE);
1512
get_finfo(full_path, fs_data + fsPB, 0, false);
1513
WriteMacInt32(fcb + fcbFType, ReadMacInt32(fs_data + fsPB + fdType));
1515
WriteMacInt32(fcb + fcbCatPos, fd);
1516
WriteMacInt32(fcb + fcbDirID, fs_item->parent_id);
1517
cstr2pstr((char *)Mac2HostAddr(fcb + fcbCName), fs_item->name);
1522
static int16 fs_close(uint32 pb)
1524
D(bug(" fs_close(%08lx), refNum %d\n", pb, ReadMacInt16(pb + ioRefNum)));
1527
// Find FCB and fd for file
1528
uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1531
if (ReadMacInt32(fcb + fcbFlNm) == 0)
1533
int fd = ReadMacInt32(fcb + fcbCatPos);
1536
if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) {
1537
FSItem *item = find_fsitem_by_id(ReadMacInt32(fcb + fcbFlNm));
1539
get_path_for_fsitem(item);
1540
close_rfork(full_path, fd);
1544
WriteMacInt32(fcb + fcbCatPos, (uint32)-1);
1547
D(bug(" releasing FCB\n"));
1548
r.d[0] = ReadMacInt16(pb + ioRefNum);
1549
Execute68k(fs_data + fsReleaseFCB, &r);
1550
D(bug(" UTReleaseFCB() returned %d\n", r.d[0]));
1551
return (int16)r.d[0];
1554
// Query information about FCB (FCBPBRec)
1555
static int16 fs_get_fcb_info(uint32 pb, uint32 vcb)
1557
D(bug(" fs_get_fcb_info(%08lx), vRefNum %d, refNum %d, idx %d\n", pb, ReadMacInt16(pb + ioVRefNum), ReadMacInt16(pb + ioRefNum), ReadMacInt16(pb + ioFCBIndx)));
1561
if (ReadMacInt16(pb + ioFCBIndx) == 0) { // Get information about single file
1563
// Find FCB for file
1564
fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1566
} else { // Get information about file specified by index
1568
// Find FCB by index
1569
WriteMacInt16(pb + ioRefNum, 0);
1570
for (int i=0; i<(int)ReadMacInt16(pb + ioFCBIndx); i++) {
1571
D(bug(" indexing FCBs\n"));
1573
r.a[1] = pb + ioRefNum;
1574
r.a[2] = fs_data + fsReturn;
1575
Execute68k(fs_data + fsIndexFCB, &r);
1576
fcb = ReadMacInt32(fs_data + fsReturn);
1577
D(bug(" UTIndexFCB() returned %d, fcb %p\n", r.d[0], fcb));
1578
if (r.d[0] & 0xffff)
1579
return (int16)r.d[0];
1585
// Copy information from FCB
1586
if (ReadMacInt32(pb + ioNamePtr))
1587
pstrcpy((char *)Mac2HostAddr(ReadMacInt32(pb + ioNamePtr)), (char *)Mac2HostAddr(fcb + fcbCName));
1588
WriteMacInt32(pb + ioFCBFlNm, ReadMacInt32(fcb + fcbFlNm));
1589
WriteMacInt8(pb + ioFCBFlags, ReadMacInt8(fcb + fcbFlags));
1590
WriteMacInt16(pb + ioFCBStBlk, ReadMacInt16(fcb + fcbSBlk));
1591
WriteMacInt32(pb + ioFCBEOF, ReadMacInt32(fcb + fcbEOF));
1592
WriteMacInt32(pb + ioFCBPLen, ReadMacInt32(fcb + fcbPLen));
1593
WriteMacInt32(pb + ioFCBCrPs, ReadMacInt32(fcb + fcbCrPs));
1594
WriteMacInt16(pb + ioFCBVRefNum, ReadMacInt16(ReadMacInt32(fcb + fcbVPtr) + vcbVRefNum));
1595
WriteMacInt32(pb + ioFCBClpSiz, ReadMacInt32(fcb + fcbClmpSize));
1596
WriteMacInt32(pb + ioFCBParID, ReadMacInt32(fcb + fcbDirID));
1600
// Obtain logical size of an open file
1601
static int16 fs_get_eof(uint32 pb)
1603
D(bug(" fs_get_eof(%08lx), refNum %d\n", pb, ReadMacInt16(pb + ioRefNum)));
1606
// Find FCB and fd for file
1607
uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1610
if (ReadMacInt32(fcb + fcbFlNm) == 0)
1612
int fd = ReadMacInt32(fcb + fcbCatPos);
1614
if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1615
WriteMacInt32(pb + ioMisc, 0);
1622
if (fstat(fd, &st) < 0)
1623
return errno2oserr();
1626
WriteMacInt32(fcb + fcbEOF, st.st_size);
1627
WriteMacInt32(fcb + fcbPLen, (st.st_size | (AL_BLK_SIZE - 1)) + 1);
1628
WriteMacInt32(pb + ioMisc, st.st_size);
1629
D(bug(" adjusting FCBs\n"));
1630
r.d[0] = ReadMacInt16(pb + ioRefNum);
1631
Execute68k(fs_data + fsAdjustEOF, &r);
1632
D(bug(" UTAdjustEOF() returned %d\n", r.d[0]));
1637
static int16 fs_set_eof(uint32 pb)
1639
D(bug(" fs_set_eof(%08lx), refNum %d, size %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt32(pb + ioMisc)));
1642
// Find FCB and fd for file
1643
uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1646
if (ReadMacInt32(fcb + fcbFlNm) == 0)
1648
int fd = ReadMacInt32(fcb + fcbCatPos);
1650
if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) // "pseudo" resource fork
1656
uint32 size = ReadMacInt32(pb + ioMisc);
1657
if (ftruncate(fd, size) < 0)
1658
return errno2oserr();
1661
WriteMacInt32(fcb + fcbEOF, size);
1662
WriteMacInt32(fcb + fcbPLen, (size | (AL_BLK_SIZE - 1)) + 1);
1663
D(bug(" adjusting FCBs\n"));
1664
r.d[0] = ReadMacInt16(pb + ioRefNum);
1665
Execute68k(fs_data + fsAdjustEOF, &r);
1666
D(bug(" UTAdjustEOF() returned %d\n", r.d[0]));
1670
// Query current file position
1671
static int16 fs_get_fpos(uint32 pb)
1673
D(bug(" fs_get_fpos(%08lx), refNum %d\n", pb, ReadMacInt16(pb + ioRefNum)));
1675
WriteMacInt32(pb + ioReqCount, 0);
1676
WriteMacInt32(pb + ioActCount, 0);
1677
WriteMacInt16(pb + ioPosMode, 0);
1679
// Find FCB and fd for file
1680
uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1683
if (ReadMacInt32(fcb + fcbFlNm) == 0)
1685
int fd = ReadMacInt32(fcb + fcbCatPos);
1687
if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1688
WriteMacInt32(pb + ioPosOffset, 0);
1693
// Get file position
1694
uint32 pos = lseek(fd, 0, SEEK_CUR);
1695
WriteMacInt32(fcb + fcbCrPs, pos);
1696
WriteMacInt32(pb + ioPosOffset, pos);
1700
// Set current file position
1701
static int16 fs_set_fpos(uint32 pb)
1703
D(bug(" fs_set_fpos(%08lx), refNum %d, posMode %d, offset %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt16(pb + ioPosMode), ReadMacInt32(pb + ioPosOffset)));
1705
// Find FCB and fd for file
1706
uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1709
if (ReadMacInt32(fcb + fcbFlNm) == 0)
1711
int fd = ReadMacInt32(fcb + fcbCatPos);
1713
if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1714
WriteMacInt32(pb + ioPosOffset, 0);
1719
// Set file position
1720
switch (ReadMacInt16(pb + ioPosMode)) {
1722
if (lseek(fd, ReadMacInt32(pb + ioPosOffset), SEEK_SET) < 0)
1726
if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_END) < 0)
1730
if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_CUR) < 0)
1736
uint32 pos = lseek(fd, 0, SEEK_CUR);
1737
WriteMacInt32(fcb + fcbCrPs, pos);
1738
WriteMacInt32(pb + ioPosOffset, pos);
1743
static int16 fs_read(uint32 pb)
1745
D(bug(" fs_read(%08lx), refNum %d, buffer %p, count %d, posMode %d, posOffset %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt32(pb + ioBuffer), ReadMacInt32(pb + ioReqCount), ReadMacInt16(pb + ioPosMode), ReadMacInt32(pb + ioPosOffset)));
1748
if ((int32)ReadMacInt32(pb + ioReqCount) < 0)
1751
// Find FCB and fd for file
1752
uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1755
if (ReadMacInt32(fcb + fcbFlNm) == 0)
1757
int fd = ReadMacInt32(fcb + fcbCatPos);
1759
if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1760
WriteMacInt32(pb + ioActCount, 0);
1766
switch (ReadMacInt16(pb + ioPosMode) & 3) {
1768
if (lseek(fd, ReadMacInt32(pb + ioPosOffset), SEEK_SET) < 0)
1772
if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_END) < 0)
1776
if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_CUR) < 0)
1782
ssize_t actual = extfs_read(fd, Mac2HostAddr(ReadMacInt32(pb + ioBuffer)), ReadMacInt32(pb + ioReqCount));
1783
int16 read_err = errno2oserr();
1784
D(bug(" actual %d\n", actual));
1785
WriteMacInt32(pb + ioActCount, actual >= 0 ? actual : 0);
1786
uint32 pos = lseek(fd, 0, SEEK_CUR);
1787
WriteMacInt32(fcb + fcbCrPs, pos);
1788
WriteMacInt32(pb + ioPosOffset, pos);
1789
if (actual != (ssize_t)ReadMacInt32(pb + ioReqCount))
1790
return actual < 0 ? read_err : eofErr;
1796
static int16 fs_write(uint32 pb)
1798
D(bug(" fs_write(%08lx), refNum %d, buffer %p, count %d, posMode %d, posOffset %d\n", pb, ReadMacInt16(pb + ioRefNum), ReadMacInt32(pb + ioBuffer), ReadMacInt32(pb + ioReqCount), ReadMacInt16(pb + ioPosMode), ReadMacInt32(pb + ioPosOffset)));
1801
if ((int32)ReadMacInt32(pb + ioReqCount) < 0)
1804
// Find FCB and fd for file
1805
uint32 fcb = find_fcb(ReadMacInt16(pb + ioRefNum));
1808
if (ReadMacInt32(fcb + fcbFlNm) == 0)
1810
int fd = ReadMacInt32(fcb + fcbCatPos);
1812
if (ReadMacInt8(fcb + fcbFlags) & fcbResourceMask) { // "pseudo" resource fork
1813
WriteMacInt32(pb + ioActCount, ReadMacInt32(pb + ioReqCount));
1819
switch (ReadMacInt16(pb + ioPosMode) & 3) {
1821
if (lseek(fd, ReadMacInt32(pb + ioPosOffset), SEEK_SET) < 0)
1825
if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_END) < 0)
1829
if (lseek(fd, (int32)ReadMacInt32(pb + ioPosOffset), SEEK_CUR) < 0)
1835
ssize_t actual = extfs_write(fd, Mac2HostAddr(ReadMacInt32(pb + ioBuffer)), ReadMacInt32(pb + ioReqCount));
1836
int16 write_err = errno2oserr();
1837
D(bug(" actual %d\n", actual));
1838
WriteMacInt32(pb + ioActCount, actual >= 0 ? actual : 0);
1839
uint32 pos = lseek(fd, 0, SEEK_CUR);
1840
WriteMacInt32(fcb + fcbCrPs, pos);
1841
WriteMacInt32(pb + ioPosOffset, pos);
1842
if (actual != (ssize_t)ReadMacInt32(pb + ioReqCount))
1849
static int16 fs_create(uint32 pb, uint32 dirID)
1851
D(bug(" fs_create(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), dirID));
1853
// Find FSItem for given file
1855
int16 result = get_item_and_path(pb, dirID, fs_item);
1856
if (result != noErr)
1859
// Does the file already exist?
1860
if (access(full_path, F_OK) == 0)
1864
int fd = creat(full_path, 0666);
1866
return errno2oserr();
1874
static int16 fs_dir_create(uint32 pb)
1876
D(bug(" fs_dir_create(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt32(pb + ioDirID)));
1878
// Find FSItem for given directory
1880
int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1881
if (result != noErr)
1884
// Does the directory already exist?
1885
if (access(full_path, F_OK) == 0)
1889
if (mkdir(full_path, 0777) < 0)
1890
return errno2oserr();
1892
WriteMacInt32(pb + ioDirID, fs_item->id);
1897
// Delete file/directory
1898
static int16 fs_delete(uint32 pb, uint32 dirID)
1900
D(bug(" fs_delete(%08lx), vRefNum %d, name %.31s, dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), dirID));
1902
// Find FSItem for given file/dir
1904
int16 result = get_item_and_path(pb, dirID, fs_item);
1905
if (result != noErr)
1909
if (!extfs_remove(full_path))
1910
return errno2oserr();
1915
// Rename file/directory
1916
static int16 fs_rename(uint32 pb, uint32 dirID)
1918
D(bug(" fs_rename(%08lx), vRefNum %d, name %.31s, dirID %d, new name %.31s\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), dirID, Mac2HostAddr(ReadMacInt32(pb + ioMisc) + 1)));
1920
// Find path of given file/dir
1922
int16 result = get_item_and_path(pb, dirID, fs_item);
1923
if (result != noErr)
1926
// Save path of existing item
1927
char old_path[MAX_PATH_LENGTH];
1928
strcpy(old_path, full_path);
1930
// Find path for new name
1931
Mac2Mac_memcpy(fs_data + fsPB, pb, SIZEOF_IOParam);
1932
WriteMacInt32(fs_data + fsPB + ioNamePtr, ReadMacInt32(pb + ioMisc));
1934
result = get_item_and_path(fs_data + fsPB, dirID, new_item);
1935
if (result != noErr)
1938
// Does the new name already exist?
1939
if (access(full_path, F_OK) == 0)
1943
D(bug(" renaming %s -> %s\n", old_path, full_path));
1944
if (!extfs_rename(old_path, full_path))
1945
return errno2oserr();
1947
// The ID of the old file/dir has to stay the same, so we swap the IDs of the FSItems
1948
swap_parent_ids(fs_item->id, new_item->id);
1949
uint32 t = fs_item->id;
1950
fs_item->id = new_item->id;
1956
// Move file/directory (CMovePBRec)
1957
static int16 fs_cat_move(uint32 pb)
1959
D(bug(" fs_cat_move(%08lx), vRefNum %d, name %.31s, dirID %d, new name %.31s, new dirID %d\n", pb, ReadMacInt16(pb + ioVRefNum), Mac2HostAddr(ReadMacInt32(pb + ioNamePtr) + 1), ReadMacInt32(pb + ioDirID), Mac2HostAddr(ReadMacInt32(pb + ioNewName) + 1), ReadMacInt32(pb + ioNewDirID)));
1961
// Find path of given file/dir
1963
int16 result = get_item_and_path(pb, ReadMacInt32(pb + ioDirID), fs_item);
1964
if (result != noErr)
1967
// Save path of existing item
1968
char old_path[MAX_PATH_LENGTH];
1969
strcpy(old_path, full_path);
1971
// Find path for new directory
1972
Mac2Mac_memcpy(fs_data + fsPB, pb, SIZEOF_IOParam);
1973
WriteMacInt32(fs_data + fsPB + ioNamePtr, ReadMacInt32(pb + ioNewName));
1974
FSItem *new_dir_item;
1975
result = get_item_and_path(fs_data + fsPB, ReadMacInt32(pb + ioNewDirID), new_dir_item);
1976
if (result != noErr)
1979
// Append old file/dir name
1980
add_path_comp(fs_item->name);
1982
// Does the new name already exist?
1983
if (access(full_path, F_OK) == 0)
1987
D(bug(" moving %s -> %s\n", old_path, full_path));
1988
if (!extfs_rename(old_path, full_path))
1989
return errno2oserr();
1991
// The ID of the old file/dir has to stay the same, so we swap the IDs of the FSItems
1992
FSItem *new_item = find_fsitem(fs_item->name, new_dir_item);
1994
swap_parent_ids(fs_item->id, new_item->id);
1995
uint32 t = fs_item->id;
1996
fs_item->id = new_item->id;
2003
// Open working directory (WDParam)
2004
static int16 fs_open_wd(uint32 pb)
2006
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)));
2010
D(bug(" allocating WDCB\n"));
2012
Execute68k(fs_data + fsAllocateWDCB, &r);
2013
D(bug(" UTAllocateWDCB returned %d, refNum is %d\n", r.d[0], ReadMacInt16(pb + ioVRefNum)));
2014
return (int16)r.d[0];
2017
// Close working directory (WDParam)
2018
static int16 fs_close_wd(uint32 pb)
2020
D(bug(" fs_close_wd(%08lx), vRefNum %d\n", pb, ReadMacInt16(pb + ioVRefNum)));
2024
D(bug(" releasing WDCB\n"));
2025
r.d[0] = ReadMacInt16(pb + ioVRefNum);
2026
Execute68k(fs_data + fsReleaseWDCB, &r);
2027
D(bug(" UTReleaseWDCB returned %d\n", r.d[0]));
2028
return (int16)r.d[0];
2031
// Query information about working directory (WDParam)
2032
static int16 fs_get_wd_info(uint32 pb, uint32 vcb)
2034
D(bug(" fs_get_wd_info(%08lx), vRefNum %d, idx %d, procID %d\n", pb, ReadMacInt16(pb + ioVRefNum), ReadMacInt16(pb + ioWDIndex), ReadMacInt32(pb + ioWDProcID)));
2038
if (ReadMacInt16(pb + ioWDIndex) == 0 && ReadMacInt16(pb + ioVRefNum) == ReadMacInt16(vcb + vcbVRefNum)) {
2039
WriteMacInt32(pb + ioWDProcID, 0);
2040
WriteMacInt16(pb + ioWDVRefNum, ReadMacInt16(vcb + vcbVRefNum));
2041
if (ReadMacInt32(pb + ioNamePtr))
2042
Mac2Mac_memcpy(ReadMacInt32(pb + ioNamePtr), vcb + vcbVN, 28);
2043
WriteMacInt32(pb + ioWDDirID, ROOT_ID);
2048
D(bug(" resolving WDCB\n"));
2049
r.d[0] = ReadMacInt32(pb + ioWDProcID);
2050
r.d[1] = ReadMacInt16(pb + ioWDIndex);
2051
r.d[2] = ReadMacInt16(pb + ioVRefNum);
2052
r.a[0] = fs_data + fsReturn;
2053
Execute68k(fs_data + fsResolveWDCB, &r);
2054
uint32 wdcb = ReadMacInt32(fs_data + fsReturn);
2055
D(bug(" UTResolveWDCB() returned %d, dirID %d\n", r.d[0], ReadMacInt32(wdcb + wdDirID)));
2056
if (r.d[0] & 0xffff)
2057
return (int16)r.d[0];
2059
// Return information
2060
WriteMacInt32(pb + ioWDProcID, ReadMacInt32(wdcb + wdProcID));
2061
WriteMacInt16(pb + ioWDVRefNum, ReadMacInt16(ReadMacInt32(wdcb + wdVCBPtr) + vcbVRefNum));
2062
if (ReadMacInt32(pb + ioNamePtr))
2063
Mac2Mac_memcpy(ReadMacInt32(pb + ioNamePtr), ReadMacInt32(wdcb + wdVCBPtr) + vcbVN, 28);
2064
WriteMacInt32(pb + ioWDDirID, ReadMacInt32(wdcb + wdDirID));
2068
// Main dispatch routine
2069
int16 ExtFSHFS(uint32 vcb, uint16 selectCode, uint32 paramBlock, uint32 globalsPtr, int16 fsid)
2071
uint16 trapWord = selectCode & 0xf0ff;
2072
bool hfs = selectCode & kHFSMask;
2075
return fs_open(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0, vcb, false);
2078
return fs_close(paramBlock);
2081
return fs_read(paramBlock);
2084
return fs_write(paramBlock);
2086
case kFSMGetVolInfo:
2087
return fs_get_vol_info(paramBlock, hfs);
2090
return fs_create(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2093
return fs_delete(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2096
return fs_open(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0, vcb, true);
2099
return fs_rename(paramBlock, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2101
case kFSMGetFileInfo:
2102
return fs_get_file_info(paramBlock, hfs, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2104
case kFSMSetFileInfo:
2105
return fs_set_file_info(paramBlock, hfs, hfs ? ReadMacInt32(paramBlock + ioDirID) : 0);
2107
case kFSMUnmountVol:
2108
return fs_unmount_vol(vcb);
2111
return fs_mount_vol(paramBlock);
2114
D(bug(" allocate\n"));
2115
WriteMacInt32(paramBlock + ioActCount, ReadMacInt32(paramBlock + ioReqCount));
2119
return fs_get_eof(paramBlock);
2122
return fs_set_eof(paramBlock);
2125
return fs_get_vol(paramBlock);
2128
return fs_set_vol(paramBlock, hfs, vcb);
2135
return fs_get_fpos(paramBlock);
2138
D(bug(" offline\n"));
2141
case kFSMSetFilLock:
2144
case kFSMRstFilLock:
2148
return fs_set_fpos(paramBlock);
2151
return fs_open_wd(paramBlock);
2154
return fs_close_wd(paramBlock);
2157
return fs_cat_move(paramBlock);
2160
return fs_dir_create(paramBlock);
2163
return fs_get_wd_info(paramBlock, vcb);
2165
case kFSMGetFCBInfo:
2166
return fs_get_fcb_info(paramBlock, vcb);
2168
case kFSMGetCatInfo:
2169
return fs_get_cat_info(paramBlock);
2171
case kFSMSetCatInfo:
2172
return fs_set_cat_info(paramBlock);
2174
case kFSMSetVolInfo:
2175
return fs_set_vol_info(paramBlock);
2177
case kFSMGetVolParms:
2178
return fs_get_vol_parms(paramBlock);
2180
case kFSMVolumeMount:
2181
return fs_volume_mount(paramBlock);
2185
D(bug(" flush_vol/flush_file\n"));
2189
D(bug("ExtFSHFS(%08lx, %04x, %08lx, %08lx, %d)\n", vcb, selectCode, paramBlock, globalsPtr, fsid));