// File: /workspace/github_c_makefile_star2_O2/excess-c64[P]lib1541img/src/lib/1541img/cbmdosfs.c
// Function: vfsChanged
static void vfsChanged(void *receiver, int id, const void *sender,
	const void *args)
{
    (void)id;
    (void)sender;

    CbmdosFs *self = receiver;
    if (self->status & CFS_BROKEN) return;
    const CbmdosVfsEventArgs *ea = args;
    switch (ea->what)
    {
	DirEntry tmpEntry;

	case CVE_DOSVERCHANGED:
	case CVE_NAMECHANGED:
	case CVE_IDCHANGED:
	    updateBam(self);
	    break;

	case CVE_FILEADDED:
	    if (ea->filepos > self->dir.size)
	    {
		logmsg(L_ERROR, "CbmdosFs: inconsistent state, file added at "
			"invalid position.");
		self->status |= CFS_BROKEN;
		break;
	    }
	    if (self->dir.size == self->dir.capa)
	    {
		self->dir.capa += DIRCHUNK;
		self->dir.entries = xrealloc(self->dir.entries,
			self->dir.capa * sizeof *self->dir.entries);
	    }
	    if (ea->filepos < self->dir.size)
	    {
		memmove(self->dir.entries + ea->filepos + 1,
			self->dir.entries + ea->filepos,
			(self->dir.size - ea->filepos)
			* sizeof *self->dir.entries);
	    }
	    ++self->dir.size;
            memset(self->dir.entries + ea->filepos, 0,
                    sizeof *self->dir.entries);
	    if (updateDir(self) < 0)
	    {
		self->status |= CFS_DIRFULL;
		updateBam(self);
		break;
	    }
	    if (updateFile(self, ea->filepos) < 0)
	    {
		self->status |= CFS_DISKFULL;
	    }
	    updateDir(self);
	    updateBam(self);
	    break;

	case CVE_FILEDELETED:
	    if (ea->filepos >= self->dir.size)
	    {
		logmsg(L_ERROR, "CbmdosFs: inconsistent state, non-existent "
			"file removed.");
		self->status |= CFS_BROKEN;
		break;
	    }
	    scratchFile(self, ea->filepos);
	    --self->dir.size;
	    if (ea->filepos < self->dir.size)
	    {
		memmove(self->dir.entries + ea->filepos,
			self->dir.entries + ea->filepos + 1,
			(self->dir.size - ea->filepos)
			* sizeof *self->dir.entries);
	    }
	    if (self->status & CFS_DISKFULL)
	    {
		self->status &= ~CFS_DISKFULL;
		for (unsigned pos = 0; pos < self->dir.size; ++pos)
		{
		    if (updateFile(self, pos) < 0)
		    {
			self->status |= CFS_DISKFULL;
		    }
		}
	    }
	    updateDir(self);
	    updateBam(self);
	    break;

	case CVE_FILEMOVED:
	    if (ea->filepos >= self->dir.size
		    || ea->targetpos >= self->dir.size)
	    {
		logmsg(L_ERROR, "CbmdosFs: inconsistent state, file moved to "
			"or from invalid position.");
		self->status |= CFS_BROKEN;
		break;
	    }
	    memcpy(&tmpEntry, self->dir.entries + ea->filepos,
		    sizeof tmpEntry);
	    if (ea->targetpos > ea->filepos)
	    {
		memmove(self->dir.entries + ea->filepos,
			self->dir.entries + ea->filepos + 1,
			(ea->targetpos - ea->filepos)
			* sizeof *self->dir.entries);
	    }
	    else
	    {
		memmove(self->dir.entries + ea->targetpos + 1,
			self->dir.entries + ea->targetpos,
			(ea->filepos - ea->targetpos)
			* sizeof *self->dir.entries);
	    }
	    memcpy(self->dir.entries + ea->targetpos, &tmpEntry,
		    sizeof *self->dir.entries);
	    updateDir(self);
	    updateBam(self);
	    break;

	case CVE_FILECHANGED:
	    if (ea->fileEventArgs->what == CFE_DATACHANGED
                    || ea->fileEventArgs->what == CFE_TYPECHANGED
                    || ea->fileEventArgs->what == CFE_RECORDLENGTHCHANGED
		    || ea->fileEventArgs->what == CFE_FORCEDBLOCKSCHANGED
		    || ea->fileEventArgs->what == CFE_OPTOVERRIDESCHANGED)
	    {
		if (updateFile(self, ea->filepos) < 0)
		{
		    self->status |= CFS_DISKFULL;
		}
		if (self->status & CFS_DISKFULL)
		{
		    self->status &= ~CFS_DISKFULL;
		    for (unsigned pos = 0; pos < self->dir.size; ++pos)
		    {
			if (updateFile(self, pos) < 0)
			{
			    self->status |= CFS_DISKFULL;
			}
		    }
		}
	    }
	    updateDir(self);
	    updateBam(self);
	    break;
    }
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0x10, %rsp
testb $0x8, 0x20(%rdi)
jne 0x9ef8
movq %rcx, %r14
movl (%rcx), %eax
cmpq $0x6, %rax
ja 0x9ef8
movq %rdi, %rbx
leaq 0x43aa(%rip), %rcx      # 0xe0a8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl 0x10(%r14), %edx
movl 0x18(%rbx), %ecx
cmpl %ecx, %edx
jbe 0x9e57
leaq 0x46f3(%rip), %rsi      # 0xe410
jmp 0x9eec
movl 0x10(%r14), %eax
movl 0x18(%rbx), %edx
cmpl %edx, %eax
jae 0x9e4b
movl 0x14(%r14), %ecx
cmpl %edx, %ecx
jae 0x9e4b
movq 0x10(%rbx), %rdi
imulq $0x6, %rax, %rdx
movzwl 0x4(%rdi,%rdx), %esi
movw %si, 0xc(%rsp)
movl (%rdi,%rdx), %esi
movl %esi, 0x8(%rsp)
cmpl %eax, %ecx
jbe 0x9f07
addq %rdx, %rdi
leaq 0x6(%rdi), %rsi
subl %eax, %ecx
imulq $0x6, %rcx, %rdx
jmp 0x9f1c
movq 0x8(%r14), %rax
movl (%rax), %eax
cmpl $0x7, %eax
ja 0x9f3e
movl $0xe5, %ecx
btl %eax, %ecx
jae 0x9f3e
movl 0x10(%r14), %esi
movq %rbx, %rdi
callq 0xa314
movl 0x20(%rbx), %ecx
testl %eax, %eax
jns 0x9da6
orl $0x2, %ecx
movl %ecx, 0x20(%rbx)
testb $0x2, %cl
je 0x9f3e
andl $-0x3, %ecx
movl %ecx, 0x20(%rbx)
xorl %ebp, %ebp
cmpl 0x18(%rbx), %ebp
jae 0x9f3e
movq %rbx, %rdi
movl %ebp, %esi
callq 0xa314
testl %eax, %eax
jns 0x9dd2
orb $0x2, 0x20(%rbx)
incl %ebp
jmp 0x9db7
movl 0x10(%r14), %esi
cmpl 0x18(%rbx), %esi
jae 0x9ee5
movq %rbx, %rdi
callq 0xabef
movl 0x18(%rbx), %eax
decl %eax
movl %eax, 0x18(%rbx)
movl 0x10(%r14), %ecx
cmpl %ecx, %eax
jbe 0x9e19
movq 0x10(%rbx), %rdx
imulq $0x6, %rcx, %rsi
leaq (%rdx,%rsi), %rdi
addq %rdx, %rsi
addq $0x6, %rsi
subl %ecx, %eax
imulq $0x6, %rax, %rdx
callq 0x5660
movl 0x20(%rbx), %eax
testb $0x2, %al
je 0x9f3e
andl $-0x3, %eax
movl %eax, 0x20(%rbx)
xorl %ebp, %ebp
cmpl 0x18(%rbx), %ebp
jae 0x9f3e
movq %rbx, %rdi
movl %ebp, %esi
callq 0xa314
testl %eax, %eax
jns 0x9e47
orb $0x2, 0x20(%rbx)
incl %ebp
jmp 0x9e2c
leaq 0x4635(%rip), %rsi      # 0xe487
jmp 0x9eec
movq 0x10(%rbx), %rax
cmpl 0x1c(%rbx), %ecx
jne 0x9e80
addl $0x90, %ecx
movl %ecx, 0x1c(%rbx)
imulq $0x6, %rcx, %rsi
movq %rax, %rdi
callq 0x58bc
movq %rax, 0x10(%rbx)
movl 0x10(%r14), %edx
movl 0x18(%rbx), %ecx
movl %ecx, %r8d
subl %edx, %r8d
jbe 0x9eae
movl %edx, %ecx
imulq $0x6, %rcx, %rcx
leaq (%rax,%rcx), %rsi
leaq (%rax,%rcx), %rdi
addq $0x6, %rdi
imulq $0x6, %r8, %rdx
callq 0x5660
movl 0x18(%rbx), %ecx
movq 0x10(%rbx), %rax
movl 0x10(%r14), %edx
incl %ecx
movl %ecx, 0x18(%rbx)
movl %edx, %ecx
imulq $0x6, %rcx, %rcx
andw $0x0, 0x4(%rax,%rcx)
andl $0x0, (%rax,%rcx)
movq %rbx, %rdi
callq 0x98d6
testl %eax, %eax
js 0x9f01
movl 0x10(%r14), %esi
movq %rbx, %rdi
callq 0xa314
testl %eax, %eax
jns 0x9f3e
orb $0x2, 0x20(%rbx)
jmp 0x9f3e
leaq 0x4562(%rip), %rsi      # 0xe44e
pushq $0x1
popq %rdi
callq 0x5960
orb $0x8, 0x20(%rbx)
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
retq
orb $0x4, 0x20(%rbx)
jmp 0x9f46
imulq $0x6, %rcx, %rdx
leaq (%rdi,%rdx), %rsi
addq %rdx, %rdi
addq $0x6, %rdi
subl %ecx, %eax
imulq $0x6, %rax, %rdx
callq 0x5660
movq 0x10(%rbx), %rax
movl 0x14(%r14), %ecx
imulq $0x6, %rcx, %rcx
movzwl 0xc(%rsp), %edx
movw %dx, 0x4(%rax,%rcx)
movl 0x8(%rsp), %edx
movl %edx, (%rax,%rcx)
movq %rbx, %rdi
callq 0x98d6
movq %rbx, %rdi
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
jmp 0x9b77