// File: /workspace/github_c_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
testq %rsi, %rsi
je 0x47a6
movq %rsi, %r15
movq %rsi, %rax
shrq $0x1f, %rax
jne 0x47bf
movl %ecx, %ebp
movq %rdx, %r12
movq %rdi, %r14
pushq $0x78
popq %rdi
callq 0x2380
testq %rax, %rax
je 0x4792
movq %rax, %rbx
movq %r14, (%rax)
movq %r15, 0x8(%rax)
movq %r12, 0x18(%rax)
movl %ebp, 0x20(%rax)
movl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
xorl %edx, %edx
divl %r15d
movq %rax, 0x10(%rbx)
pushq $0x10
popq %rdi
callq 0x54e8
movq %rax, 0x60(%rbx)
testq %rax, %rax
je 0x478a
movq %r14, %rdi
callq 0x4cac
testq %rax, %rax
je 0x4781
movq %rax, %r14
movq %rax, %rdi
callq 0x55fe
testq %rax, %rax
je 0x4634
movq %r14, %rdi
xorl %esi, %esi
callq 0x5603
movq (%rax), %rax
jmp 0x4636
xorl %eax, %eax
movq %rax, 0x68(%rbx)
movq %rax, 0x70(%rbx)
leaq 0x8(%rsp), %r15
movq %r14, %rdi
callq 0x55fe
testq %rax, %rax
je 0x471e
movq %r14, %rdi
xorl %esi, %esi
callq 0x5603
movq (%rax), %rsi
movq %rsi, 0x8(%rsp)
cmpq 0x70(%rbx), %rsi
jne 0x475a
movq %rax, %r12
movq 0x8(%rax), %rcx
movq 0x8(%rbx), %rsi
movq %rcx, %rax
cqto
idivq %rsi
testq %rdx, %rdx
je 0x46e6
movq %r14, %rdi
callq 0x55fe
movq (%r12), %rsi
cmpq $0x2, %rax
jae 0x4763
movq %rbx, %rdi
callq 0x503d
testq %rax, %rax
je 0x4779
movq %rax, %r13
movq 0x8(%r12), %rsi
movq %rsi, %rax
cqto
idivq 0x8(%rbx)
subq %rdx, %rsi
movq %r13, %rdi
callq 0x2340
movl %eax, %ebp
movq %r13, %rdi
callq 0x2040
testl %ebp, %ebp
jne 0x4779
movq 0x8(%r12), %rcx
movq 0x8(%rbx), %rsi
movq %rcx, %rax
cqto
idivq %rsi
movq %rax, 0x10(%rsp)
movq 0x60(%rbx), %rdi
movq %r15, %rsi
callq 0x5555
testl %eax, %eax
jne 0x4779
movq 0x10(%rsp), %rax
addq 0x8(%rsp), %rax
movq %rax, 0x70(%rbx)
movq %r14, %rdi
callq 0x5579
jmp 0x4643
movq %r14, %rdi
callq 0x561f
movq %rbx, %rdi
addq $0x28, %rdi
xorl %esi, %esi
callq 0x23d0
testl %eax, %eax
je 0x4794
movl %eax, %edi
callq 0x2520
leaq 0x82d9(%rip), %rdi      # 0xca1f
movq %rax, %rsi
xorl %eax, %eax
callq 0x9ec8
callq 0x20a0
andl $0x0, (%rax)
jmp 0x4781
leaq 0x823a(%rip), %rdi      # 0xc99b
jmp 0x476a
leaq 0x8279(%rip), %rdi      # 0xc9e3
xorl %eax, %eax
callq 0x9ec8
callq 0x20a0
andl $0x0, (%rax)
movq %r14, %rdi
callq 0x561f
movq 0x60(%rbx), %rdi
callq 0x561f
movq %rbx, %rdi
callq 0x2040
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x817d(%rip), %rdi      # 0xc92a
leaq 0x8183(%rip), %rsi      # 0xc937
leaq 0x8186(%rip), %rcx      # 0xc941
pushq $0x2d
jmp 0x47d6
leaq 0x81bf(%rip), %rdi      # 0xc985
leaq 0x816a(%rip), %rsi      # 0xc937
leaq 0x816d(%rip), %rcx      # 0xc941
pushq $0x31
popq %rdx
callq 0x2220