// File: /workspace/github_c_makefile_star2_O3/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 0xa276
movq %rcx, %r14
movl (%rcx), %eax
cmpq $0x6, %rax
ja 0xa276
movq %rdi, %rbx
leaq 0x5052(%rip), %rcx      # 0xf0a8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl 0x10(%r14), %edx
movl 0x18(%rbx), %ecx
cmpl %ecx, %edx
jbe 0xa1c9
leaq 0x539b(%rip), %rsi      # 0xf410
jmp 0xa268
movl 0x10(%r14), %eax
movl 0x18(%rbx), %edx
cmpl %edx, %eax
jae 0xa1bd
movl 0x14(%r14), %ecx
cmpl %edx, %ecx
jae 0xa1bd
movq 0x10(%rbx), %rdx
leaq (%rax,%rax,2), %rsi
movzwl 0x4(%rdx,%rsi,2), %edi
movw %di, 0xc(%rsp)
movl (%rdx,%rsi,2), %edi
movl %edi, 0x8(%rsp)
cmpl %eax, %ecx
jbe 0xa285
leaq (%rdx,%rsi,2), %rdi
leaq 0x6(%rdi), %rsi
subl %eax, %ecx
addq %rcx, %rcx
leaq (%rcx,%rcx,2), %rdx
jmp 0xa29e
movq 0x8(%r14), %rax
movl (%rax), %eax
cmpl $0x7, %eax
ja 0xa2c0
movl $0xe5, %ecx
btl %eax, %ecx
jae 0xa2c0
movl 0x10(%r14), %esi
movq %rbx, %rdi
callq 0xa6c1
movl 0x20(%rbx), %ecx
testl %eax, %eax
jns 0xa102
orl $0x2, %ecx
movl %ecx, 0x20(%rbx)
testb $0x2, %cl
je 0xa2c0
andl $-0x3, %ecx
movl %ecx, 0x20(%rbx)
cmpl $0x0, 0x18(%rbx)
je 0xa2c0
xorl %ebp, %ebp
movq %rbx, %rdi
movl %ebp, %esi
callq 0xa6c1
testl %eax, %eax
jns 0xa12f
orb $0x2, 0x20(%rbx)
incl %ebp
cmpl 0x18(%rbx), %ebp
jb 0xa11d
jmp 0xa2c0
movl 0x10(%r14), %esi
cmpl 0x18(%rbx), %esi
jae 0xa261
movq %rbx, %rdi
callq 0xb02d
movl 0x18(%rbx), %eax
decl %eax
movl %eax, 0x18(%rbx)
movl 0x10(%r14), %ecx
cmpl %ecx, %eax
jbe 0xa182
movq 0x10(%rbx), %rdx
leaq (%rcx,%rcx,2), %rsi
leaq (%rdx,%rsi,2), %rdi
leaq (%rdx,%rsi,2), %rsi
addq $0x6, %rsi
subl %ecx, %eax
addq %rax, %rax
leaq (%rax,%rax,2), %rdx
callq 0x5620
movl 0x20(%rbx), %eax
testb $0x2, %al
je 0xa2c0
andl $-0x3, %eax
movl %eax, 0x20(%rbx)
cmpl $0x0, 0x18(%rbx)
je 0xa2c0
xorl %ebp, %ebp
movq %rbx, %rdi
movl %ebp, %esi
callq 0xa6c1
testl %eax, %eax
jns 0xa1b1
orb $0x2, 0x20(%rbx)
incl %ebp
cmpl 0x18(%rbx), %ebp
jb 0xa19f
jmp 0xa2c0
leaq 0x52c3(%rip), %rsi      # 0xf487
jmp 0xa268
movq 0x10(%rbx), %rax
cmpl 0x1c(%rbx), %ecx
jne 0xa1f5
addl $0x90, %ecx
movl %ecx, 0x1c(%rbx)
addq %rcx, %rcx
leaq (%rcx,%rcx,2), %rsi
movq %rax, %rdi
callq 0x587c
movq %rax, 0x10(%rbx)
movl 0x10(%r14), %edx
movl 0x18(%rbx), %ecx
movl %ecx, %r8d
subl %edx, %r8d
jbe 0xa226
movl %edx, %ecx
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,2), %rsi
leaq (%rax,%rcx,2), %rdi
addq $0x6, %rdi
addq %r8, %r8
leaq (%r8,%r8,2), %rdx
callq 0x5620
movl 0x18(%rbx), %ecx
movq 0x10(%rbx), %rax
movl 0x10(%r14), %edx
incl %ecx
movl %ecx, 0x18(%rbx)
movl %edx, %ecx
leaq (%rcx,%rcx,2), %rcx
movw $0x0, 0x4(%rax,%rcx,2)
movl $0x0, (%rax,%rcx,2)
movq %rbx, %rdi
callq 0x9c0b
testl %eax, %eax
js 0xa27f
movl 0x10(%r14), %esi
movq %rbx, %rdi
callq 0xa6c1
testl %eax, %eax
jns 0xa2c0
orb $0x2, 0x20(%rbx)
jmp 0xa2c0
leaq 0x51e6(%rip), %rsi      # 0xf44e
movl $0x1, %edi
callq 0x591c
orb $0x8, 0x20(%rbx)
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
retq
orb $0x4, 0x20(%rbx)
jmp 0xa2c8
leaq (%rcx,%rcx,2), %rdi
leaq (%rdx,%rdi,2), %rsi
leaq (%rdx,%rdi,2), %rdi
addq $0x6, %rdi
subl %ecx, %eax
addq %rax, %rax
leaq (%rax,%rax,2), %rdx
callq 0x5620
movq 0x10(%rbx), %rax
movl 0x14(%r14), %ecx
leaq (%rcx,%rcx,2), %rcx
movzwl 0xc(%rsp), %edx
movw %dx, 0x4(%rax,%rcx,2)
movl 0x8(%rsp), %edx
movl %edx, (%rax,%rcx,2)
movq %rbx, %rdi
callq 0x9c0b
movq %rbx, %rdi
addq $0x10, %rsp
popq %rbx
popq %r14
popq %rbp
jmp 0x9eba