// File: jvanns[P]verbatim/sub/lmdb/libraries/liblmdb/mdb.c
// Function: mdb_env_copyfd0
static int ESECT
mdb_env_copyfd0(MDB_env *env, HANDLE fd)
{
	MDB_txn *txn = NULL;
	mdb_mutexref_t wmutex = NULL;
	int rc;
	size_t wsize;
	char *ptr;
#ifdef _WIN32
	DWORD len, w2;
#define DO_WRITE(rc, fd, ptr, w2, len)	rc = WriteFile(fd, ptr, w2, &len, NULL)
#else
	ssize_t len;
	size_t w2;
#define DO_WRITE(rc, fd, ptr, w2, len)	len = write(fd, ptr, w2); rc = (len >= 0)
#endif

	/* Do the lock/unlock of the reader mutex before starting the
	 * write txn.  Otherwise other read txns could block writers.
	 */
	rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
	if (rc)
		return rc;

	if (env->me_txns) {
		/* We must start the actual read txn after blocking writers */
		mdb_txn_end(txn, MDB_END_RESET_TMP);

		/* Temporarily block writers until we snapshot the meta pages */
		wmutex = env->me_wmutex;
		if (LOCK_MUTEX(rc, env, wmutex))
			goto leave;

		rc = mdb_txn_renew0(txn);
		if (rc) {
			UNLOCK_MUTEX(wmutex);
			goto leave;
		}
	}

	wsize = env->me_psize * NUM_METAS;
	ptr = env->me_map;
	w2 = wsize;
	while (w2 > 0) {
		DO_WRITE(rc, fd, ptr, w2, len);
		if (!rc) {
			rc = ErrCode();
			break;
		} else if (len > 0) {
			rc = MDB_SUCCESS;
			ptr += len;
			w2 -= len;
			continue;
		} else {
			/* Non-blocking or async handles are not supported */
			rc = EIO;
			break;
		}
	}
	if (wmutex)
		UNLOCK_MUTEX(wmutex);

	if (rc)
		goto leave;

	w2 = txn->mt_next_pgno * env->me_psize;
	{
		size_t fsize = 0;
		if ((rc = mdb_fsize(env->me_fd, &fsize)))
			goto leave;
		if (w2 > fsize)
			w2 = fsize;
	}
	wsize = w2 - wsize;
	while (wsize > 0) {
		if (wsize > MAX_WRITE)
			w2 = MAX_WRITE;
		else
			w2 = wsize;
		DO_WRITE(rc, fd, ptr, w2, len);
		if (!rc) {
			rc = ErrCode();
			break;
		} else if (len > 0) {
			rc = MDB_SUCCESS;
			ptr += len;
			wsize -= len;
			continue;
		} else {
			rc = EIO;
			break;
		}
	}

leave:
	mdb_txn_abort(txn);
	return rc;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x10(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
movl $0x20000, %edx          # imm = 0x20000
leaq -0x20(%rbp), %rcx
callq 0x3a60
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0x14c89
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x14ead
movq -0x10(%rbp), %rax
cmpq $0x0, 0x40(%rax)
je 0x14d02
movq -0x20(%rbp), %rdi
movl $0x4, %esi
callq 0x4030
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rax
addq $0x40, %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
callq 0x2400
movl %eax, -0x2c(%rbp)
cmpl $0x0, %eax
je 0x14ce0
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl -0x2c(%rbp), %edx
callq 0x158f0
movl %eax, -0x2c(%rbp)
cmpl $0x0, %eax
je 0x14ce0
jmp 0x14e9e
movq -0x20(%rbp), %rdi
callq 0x34c0
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0x14d00
movq -0x28(%rbp), %rdi
callq 0x2250
jmp 0x14e9e
jmp 0x14d02
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
shll %eax
movl %eax, %eax
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
jbe 0x14d94
movl -0x14(%rbp), %edi
movq -0x40(%rbp), %rsi
movq -0x50(%rbp), %rdx
callq 0x20c0
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
setge %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x14d62
callq 0x2050
movl (%rax), %eax
movl %eax, -0x2c(%rbp)
jmp 0x14d94
cmpq $0x0, -0x48(%rbp)
jle 0x14d8d
movl $0x0, -0x2c(%rbp)
movq -0x48(%rbp), %rax
addq -0x40(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x48(%rbp), %rcx
movq -0x50(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x50(%rbp)
jmp 0x14d25
movl $0x5, -0x2c(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0x14da4
movq -0x28(%rbp), %rdi
callq 0x2250
cmpl $0x0, -0x2c(%rbp)
je 0x14daf
jmp 0x14e9e
movq -0x20(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x10(%rbp), %rcx
movl 0x10(%rcx), %ecx
imulq %rcx, %rax
movq %rax, -0x50(%rbp)
movq $0x0, -0x58(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %edi
leaq -0x58(%rbp), %rsi
callq 0x16a70
movl %eax, -0x2c(%rbp)
cmpl $0x0, %eax
je 0x14dea
jmp 0x14e9e
movq -0x50(%rbp), %rax
cmpq -0x58(%rbp), %rax
jbe 0x14dfc
movq -0x58(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
subq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
jbe 0x14e9c
movl $0x80000000, %eax       # imm = 0x80000000
cmpq %rax, -0x38(%rbp)
jbe 0x14e29
movl $0x80000000, %eax       # imm = 0x80000000
movq %rax, -0x50(%rbp)
jmp 0x14e31
movq -0x38(%rbp), %rax
movq %rax, -0x50(%rbp)
movl -0x14(%rbp), %edi
movq -0x40(%rbp), %rsi
movq -0x50(%rbp), %rdx
callq 0x20c0
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
setge %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x14e67
callq 0x2050
movl (%rax), %eax
movl %eax, -0x2c(%rbp)
jmp 0x14e9c
cmpq $0x0, -0x48(%rbp)
jle 0x14e95
movl $0x0, -0x2c(%rbp)
movq -0x48(%rbp), %rax
addq -0x40(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x48(%rbp), %rcx
movq -0x38(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x38(%rbp)
jmp 0x14e08
movl $0x5, -0x2c(%rbp)
jmp 0x14e9e
movq -0x20(%rbp), %rdi
callq 0x4310
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)