// File: /workspace/github_c_makefile_star2_O0/Tarsnap[P]kivaloo/lbs/storage.c
// Function: storage_init
struct storage_state *
storage_init(const char * storagedir, size_t blocklen, long latency,
    int nosync)
{
	struct storage_state * S;
	struct elasticqueue * files;
	struct storage_file * sf;
	struct file_state fs;
	char * s;
	int rc;
	off_t num_blocks;

	/* Sanity-check the block size. */
	assert(blocklen > 0);
#ifdef OFF_MAX
	assert(blocklen <= OFF_MAX);
#else
	assert(blocklen <= INT32_MAX);
#endif

	/* Allocate structure and fill in static data. */
	if ((S = malloc(sizeof(struct storage_state))) == NULL)
		goto err0;
	S->storagedir = storagedir;
	S->blocklen = blocklen;
	S->latency = latency;
	S->nosync = nosync;

	/*
	 * Figure out the maximum number of blocks a file can contain without
	 * having its length overflow either uint64_t or off_t.
	 */
#ifdef OFF_MAX
	S->maxnblks = UINT64_MAX;
	if (S->maxnblks > OFF_MAX)
		S->maxnblks = OFF_MAX;
#else
	/* Just treat off_t as an int32_t. */
	assert((int32_t)(off_t)(INT32_MAX) == INT32_MAX);
	S->maxnblks = INT32_MAX;
#endif
	S->maxnblks = S->maxnblks / S->blocklen;

	/* Create an elastic queue to hold block file state. */
	if ((S->files = elasticqueue_init(sizeof(struct file_state))) == NULL)
		goto err1;

	/* Get a sorted list of block files. */
	if ((files = storage_findfiles(S->storagedir)) == NULL)
		goto err2;

	/* If we have at least one file, its # is where the blocks start. */
	if (elasticqueue_getlen(files) > 0) {
		sf = elasticqueue_get(files, 0);
		S->minblk = sf->fileno;
	} else {
		/* Otherwise, we have nothing. */
		S->minblk = 0;
	}

	/* Look at files one by one. */
	S->nextblk = S->minblk;
	while (elasticqueue_getlen(files) > 0) {
		/* Grab a file. */
		sf = elasticqueue_get(files, 0);

		/* The first block is the file number. */
		fs.start = sf->fileno;

		/* Is the first block the one we expected? */
		if (fs.start != S->nextblk) {
			warn0("Start of block storage file does not match"
			    " end of previous file: %016" PRIx64, sf->fileno);
			goto err3;
		}

		/* Does it have a non-integer number of blocks? */
		if ((sf->len % (off_t)S->blocklen) != 0) {
			/* Not permitted for files in the middle. */
			if (elasticqueue_getlen(files) > 1) {
				warn0("Block storage file has non-integer"
				    " number of blocks: %016" PRIx64,
				    sf->fileno);
				goto err3;
			}

			/*
			 * The final file may have a non-integer number of
			 * blocks due to an interrupted write; just remove
			 * any partial block.
			 */
			if ((s = storage_util_mkpath(S, sf->fileno)) == NULL)
				goto err3;
			if (truncate(s, sf->len - (sf->len %
			    (off_t)S->blocklen)))
				goto err4;
			free(s);
		}

		/* Compute number of blocks. */
		num_blocks = sf->len / (off_t)S->blocklen;
#if UINTMAX_MAX > UINT64_MAX
		if ((uintmax_t)num_blocks > (uintmax_t)UINT64_MAX)
			goto err3;
#endif
		fs.len = (uint64_t)num_blocks;

		/* Add to the queue of block file state structures. */
		if (elasticqueue_add(S->files, &fs))
			goto err3;

		/* Adjust nextblk to account for this latest block file. */
		S->nextblk = fs.start + fs.len;

		/* Remove the file from the queue. */
		elasticqueue_delete(files);
	}

	/* Free the (now empty) queue of files. */
	elasticqueue_free(files);

	/* Create a lock on the dynamic data. */
	if ((rc = pthread_rwlock_init(&S->lck, NULL)) != 0) {
		warn0("pthread_rwlock_init: %s", strerror(rc));
		goto err2;
	}

	/* Success! */
	return (S);

err4:
	free(s);
err3:
	elasticqueue_free(files);
err2:
	elasticqueue_free(S->files);
err1:
	free(S);
err0:
	/* Failure! */
	return (NULL);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movl %ecx, -0x24(%rbp)
cmpq $0x0, -0x18(%rbp)
jbe 0x58f0
jmp 0x590f
leaq 0xd217(%rip), %rdi      # 0x12b0e
leaq 0xd21d(%rip), %rsi      # 0x12b1b
movl $0x2d, %edx
leaq 0xd21b(%rip), %rcx      # 0x12b25
callq 0x2240
cmpq $0x7fffffff, -0x18(%rbp) # imm = 0x7FFFFFFF
ja 0x591b
jmp 0x593a
leaq 0xd247(%rip), %rdi      # 0x12b69
leaq 0xd1f2(%rip), %rsi      # 0x12b1b
movl $0x31, %edx
leaq 0xd1f0(%rip), %rcx      # 0x12b25
callq 0x2240
movl $0x78, %edi
callq 0x23a0
movq %rax, -0x30(%rbp)
cmpq $0x0, %rax
jne 0x5953
jmp 0x5c0c
movq -0x10(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x20(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x18(%rax)
movl -0x24(%rbp), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x20(%rax)
movq -0x30(%rbp), %rax
movq $0x7fffffff, 0x10(%rax) # imm = 0x7FFFFFFF
movq -0x30(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x30(%rbp), %rcx
xorl %edx, %edx
divq 0x8(%rcx)
movq %rax, %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x10(%rax)
movl $0x10, %edi
callq 0x7070
movq -0x30(%rbp), %rcx
movq %rax, 0x60(%rcx)
cmpq $0x0, %rax
jne 0x59c6
jmp 0x5c03
movq -0x30(%rbp), %rax
movq (%rax), %rdi
callq 0x6360
movq %rax, -0x38(%rbp)
cmpq $0x0, %rax
jne 0x59e1
jmp 0x5bf6
movq -0x38(%rbp), %rdi
callq 0x7290
cmpq $0x0, %rax
jbe 0x5a12
movq -0x38(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x72b0
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq (%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x68(%rax)
jmp 0x5a1e
movq -0x30(%rbp), %rax
movq $0x0, 0x68(%rax)
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x70(%rax)
movq -0x38(%rbp), %rdi
callq 0x7290
cmpq $0x0, %rax
jbe 0x5b90
movq -0x38(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x72b0
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq -0x30(%rbp), %rcx
cmpq 0x70(%rcx), %rax
je 0x5a92
jmp 0x5a6d
movq -0x40(%rbp), %rax
movq (%rax), %rsi
leaq 0xd104(%rip), %rdi      # 0x12b7f
movb $0x0, %al
callq 0xf2c0
callq 0x20a0
movl $0x0, (%rax)
jmp 0x5bed
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x30(%rbp), %rcx
cqto
idivq 0x8(%rcx)
cmpq $0x0, %rdx
je 0x5b3c
movq -0x38(%rbp), %rdi
callq 0x7290
cmpq $0x1, %rax
jbe 0x5ae4
jmp 0x5abf
movq -0x40(%rbp), %rax
movq (%rax), %rsi
leaq 0xd0fa(%rip), %rdi      # 0x12bc7
movb $0x0, %al
callq 0xf2c0
callq 0x20a0
movl $0x0, (%rax)
jmp 0x5bed
movq -0x30(%rbp), %rdi
movq -0x40(%rbp), %rax
movq (%rax), %rsi
callq 0x69d0
movq %rax, -0x58(%rbp)
cmpq $0x0, %rax
jne 0x5b03
jmp 0x5bed
movq -0x58(%rbp), %rdi
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rsi
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x30(%rbp), %rcx
cqto
idivq 0x8(%rcx)
subq %rdx, %rsi
callq 0x2360
cmpl $0x0, %eax
je 0x5b33
jmp 0x5be4
movq -0x58(%rbp), %rdi
callq 0x2040
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x30(%rbp), %rcx
cqto
idivq 0x8(%rcx)
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x30(%rbp), %rax
movq 0x60(%rax), %rdi
leaq -0x50(%rbp), %rsi
callq 0x7130
cmpl $0x0, %eax
je 0x5b72
jmp 0x5bed
movq -0x50(%rbp), %rcx
addq -0x48(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x70(%rax)
movq -0x38(%rbp), %rdi
callq 0x7190
jmp 0x5a2e
movq -0x38(%rbp), %rdi
callq 0x7310
movq -0x30(%rbp), %rdi
addq $0x28, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x23e0
movl %eax, -0x5c(%rbp)
cmpl $0x0, %eax
je 0x5bda
jmp 0x5bb4
movl -0x5c(%rbp), %edi
callq 0x2530
movq %rax, %rsi
leaq 0xd03d(%rip), %rdi      # 0x12c03
movb $0x0, %al
callq 0xf2c0
callq 0x20a0
movl $0x0, (%rax)
jmp 0x5bf6
movq -0x30(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x5c14
movq -0x58(%rbp), %rdi
callq 0x2040
movq -0x38(%rbp), %rdi
callq 0x7310
movq -0x30(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x7310
movq -0x30(%rbp), %rdi
callq 0x2040
movq $0x0, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x70, %rsp
popq %rbp
retq
nop