// File: /workspace/github_c_makefile_star2_O0/albertito[P]libjio/libjio/trans.c
// Function: jtrans_rollback
ssize_t jtrans_rollback(struct jtrans *ts)
{
	ssize_t rv;
	struct jtrans *newts;
	struct operation *op, *curop, *lop;

	newts = jtrans_new(ts->fs, 0);
	if (newts == NULL)
		return -1;

	newts->flags = ts->flags;
	newts->numops_r = 0;
	newts->numops_w = 0;
	newts->len_w = 0;

	if (ts->op == NULL || ts->flags & J_NOROLLBACK) {
		rv = -1;
		goto exit;
	}

	/* find the last operation */
	for (op = ts->op; op->next != NULL; op = op->next)
		;

	/* and traverse the list backwards, skipping read operations */
	for ( ; op != NULL; op = op->prev) {
		if (op->direction == D_READ)
			continue;

		/* if we extended the data in the previous transaction, we
		 * should truncate it back */
		/* DANGEROUS: this is one of the main reasons why rollbacking
		 * is dangerous and should only be done with extreme caution:
		 * if for some reason, after the previous transacton, we have
		 * extended the file further, this will cut it back to what it
		 * was; read the docs for more detail */
		if (op->plen < op->len) {
			rv = ftruncate(ts->fs->fd, op->offset + op->plen);
			if (rv != 0)
				goto exit;
		}

		/* manually add the operation to the new transaction */
		curop = malloc(sizeof(struct operation));
		if (curop == NULL) {
			rv = -1;
			goto exit;
		}

		curop->offset = op->offset;
		curop->len = op->plen;
		curop->buf = op->pdata;
		curop->plen = op->plen;
		curop->pdata = op->pdata;
		curop->direction = op->direction;
		curop->locked = 0;

		newts->numops_w++;
		newts->len_w += curop->len;

		/* add the new transaction to the list */
		if (newts->op == NULL) {
			newts->op = curop;
			curop->prev = NULL;
			curop->next = NULL;
		} else {
			for (lop = newts->op; lop->next != NULL; lop = lop->next)
				;
			lop->next = curop;
			curop->prev = lop;
			curop->next = NULL;
		}
	}

	rv = jtrans_commit(newts);

exit:
	/* Free the transaction, taking care to set buf to NULL first since
	 * points to the same address as pdata, which would otherwise make
	 * jtrans_free() attempt to free it twice. We leave the data at
	 * curop->pdata since it is freed unconditionally, while the action
	 * on curop->buf depends on the direction of the transaction. */
	for (curop = newts->op; curop != NULL; curop = curop->next) {
		curop->buf = NULL;
	}
	jtrans_free(newts);

	return rv;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rdi
xorl %esi, %esi
callq 0x20d0
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
jne 0x3cf2
movq $-0x1, -0x8(%rbp)
jmp 0x3f55
movq -0x10(%rbp), %rax
movl 0xc(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0xc(%rax)
movq -0x20(%rbp), %rax
movl $0x0, 0x10(%rax)
movq -0x20(%rbp), %rax
movl $0x0, 0x14(%rax)
movq -0x20(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x48(%rax)
je 0x3d3c
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x3d49
movq $-0x1, -0x18(%rbp)
jmp 0x3f17
movq -0x10(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpq $0x0, 0x40(%rax)
je 0x3d70
jmp 0x3d62
movq -0x28(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x3d55
jmp 0x3d72
cmpq $0x0, -0x28(%rbp)
je 0x3f0a
movq -0x28(%rbp), %rax
cmpl $0x1, 0x20(%rax)
jne 0x3d8c
jmp 0x3ef9
movq -0x28(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x28(%rbp), %rcx
cmpq 0x10(%rcx), %rax
jae 0x3dd0
movq -0x10(%rbp), %rax
movq (%rax), %rax
movl (%rax), %edi
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x28(%rbp), %rax
addq 0x28(%rax), %rsi
callq 0x21e0
cltq
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x3dce
jmp 0x3f17
jmp 0x3dd0
movl $0x48, %edi
callq 0x23c0
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x3df2
movq $-0x1, -0x18(%rbp)
jmp 0x3f17
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x28(%rbp), %rax
movq 0x28(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x28(%rbp), %rax
movq 0x30(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x28(%rbp), %rax
movq 0x28(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x28(%rbp), %rax
movq 0x30(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x28(%rbp), %rax
movl 0x20(%rax), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x20(%rax)
movq -0x30(%rbp), %rax
movl $0x0, (%rax)
movq -0x20(%rbp), %rax
movl 0x14(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x14(%rax)
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x20(%rbp), %rax
addq 0x18(%rax), %rcx
movq %rcx, 0x18(%rax)
movq -0x20(%rbp), %rax
cmpq $0x0, 0x48(%rax)
jne 0x3eac
movq -0x30(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x48(%rax)
movq -0x30(%rbp), %rax
movq $0x0, 0x38(%rax)
movq -0x30(%rbp), %rax
movq $0x0, 0x40(%rax)
jmp 0x3ef7
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpq $0x0, 0x40(%rax)
je 0x3ed3
jmp 0x3ec5
movq -0x38(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x38(%rbp)
jmp 0x3eb8
movq -0x30(%rbp), %rcx
movq -0x38(%rbp), %rax
movq %rcx, 0x40(%rax)
movq -0x38(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x38(%rax)
movq -0x30(%rbp), %rax
movq $0x0, 0x40(%rax)
jmp 0x3ef9
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x28(%rbp)
jmp 0x3d72
movq -0x20(%rbp), %rdi
callq 0x2520
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rax
movq 0x48(%rax), %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x3f44
movq -0x30(%rbp), %rax
movq $0x0, 0x18(%rax)
movq -0x30(%rbp), %rax
movq 0x40(%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0x3f23
movq -0x20(%rbp), %rdi
callq 0x2170
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
nop