// File: /workspace/github_c_makefile_star2_O2/albertito[P]libjio/libjio/trans.c
// Function: jopen
struct jfs *jopen(const char *name, int flags, int mode, unsigned int jflags)
{
	int jfd, rv;
	unsigned int t;
	char jdir[PATH_MAX], jlockfile[PATH_MAX];
	struct stat sinfo;
	pthread_mutexattr_t attr;
	struct jfs *fs;

	fs = malloc(sizeof(struct jfs));
	if (fs == NULL)
		return NULL;

	fs->fd = -1;
	fs->jfd = -1;
	fs->jdir = NULL;
	fs->jdirfd = -1;
	fs->jmap = MAP_FAILED;
	fs->as_cfg = NULL;

	/* we provide either read-only or read-write access, because when we
	 * commit a transaction we read the current contents before applying,
	 * and write access is needed for locking with fcntl; the test is done
	 * this way because O_RDONLY is usually 0, so "if (flags & O_RDONLY)"
	 * will fail. */
	if ((flags & O_WRONLY) || (flags & O_RDWR)) {
		flags = flags & ~O_WRONLY;
		flags = flags & ~O_RDONLY;
		flags = flags | O_RDWR;
	} else {
		jflags = jflags | J_RDONLY;
	}

	fs->name = strdup(name);
	fs->flags = jflags;
	fs->open_flags = flags;
	fs->ltrans = NULL;
	fs->ltrans_len = 0;

	/* Note on fs->lock usage: this lock is used only to protect the file
	 * pointer. This means that it must only be held while performing
	 * operations that depend or alter the file pointer (jread, jreadv,
	 * jwrite, jwritev), but the others (jpread, jpwrite) are left
	 * unprotected because they can be performed in parallel as long as
	 * they don't affect the same portion of the file (this is protected
	 * by lockf). The lock doesn't slow things down tho: any threaded app
	 * MUST implement this kind of locking anyways if it wants to prevent
	 * data corruption, we only make it easier for them by taking care of
	 * it here. If performance is essential, the jpread/jpwrite functions
	 * should be used, just as real life.
	 * About fs->ltlock, it's used to protect the lingering transactions
	 * list, fs->ltrans. */
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
	pthread_mutex_init( &(fs->lock), &attr);
	pthread_mutex_init( &(fs->ltlock), &attr);
	pthread_mutexattr_destroy(&attr);

	fs->fd = open(name, flags, mode);
	if (fs->fd < 0)
		goto error_exit;

	/* nothing else to do for read-only access */
	if (jflags & J_RDONLY) {
		return fs;
	}

	if (!get_jdir(name, jdir))
		goto error_exit;
	mkdir(jdir, 0750);
	rv = lstat(jdir, &sinfo);
	if (rv < 0 || !S_ISDIR(sinfo.st_mode))
		goto error_exit;

	fs->jdir = malloc(strlen(jdir) + 1);
	if (fs->jdir == NULL)
		goto error_exit;
	strcpy(fs->jdir, jdir);

	/* open the directory, we will use it to flush transaction files'
	 * metadata in jtrans_commit() */
	fs->jdirfd = open(jdir, O_RDONLY);
	if (fs->jdirfd < 0)
		goto error_exit;

	snprintf(jlockfile, PATH_MAX, "%s/lock", jdir);
	jfd = open(jlockfile, O_RDWR | O_CREAT, 0600);
	if (jfd < 0)
		goto error_exit;

	fs->jfd = jfd;

	/* initialize the lock file by writing the first tid to it, but only
	 * if its empty, otherwise there is a race if two processes call
	 * jopen() simultaneously and both initialize the file */
	plockf(jfd, F_LOCKW, 0, 0);
	lstat(jlockfile, &sinfo);
	if (sinfo.st_size != sizeof(unsigned int)) {
		t = 0;
		rv = spwrite(jfd, &t, sizeof(t), 0);
		if (rv != sizeof(t)) {
			goto error_exit;
		}
	}
	plockf(jfd, F_UNLOCK, 0, 0);

	fs->jmap = (unsigned int *) mmap(NULL, sizeof(unsigned int),
			PROT_READ | PROT_WRITE, MAP_SHARED, jfd, 0);
	if (fs->jmap == MAP_FAILED)
		goto error_exit;

	return fs;

error_exit:
	/* if there was an error, clean up as much as possible so we don't
	 * leak anything, and return failure; jclose just does this cleaning
	 * for us */
	jclose(fs);
	return NULL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x20a8, %rsp           # imm = 0x20A8
movl %ecx, %ebp
movl %edx, %r15d
movl %esi, %r12d
movq %rdi, %r14
movl $0x98, %edi
callq 0x2390
testq %rax, %rax
je 0x3555
movq %rax, %rbx
orl $-0x1, (%rax)
andq $0x0, 0x10(%rax)
orq $-0x1, 0x18(%rax)
orq $-0x1, 0x20(%rax)
andq $0x0, 0x90(%rax)
movl %r15d, 0x4(%rsp)
movl %r12d, %r15d
andl $-0x4, %r15d
orl $0x2, %r15d
movl %ebp, %r13d
orl $0x200, %r13d           # imm = 0x200
testb $0x3, %r12b
cmovnel %ebp, %r13d
cmovel %r12d, %r15d
movq %r14, %rdi
callq 0x2570
movq %rax, 0x8(%rbx)
movl %r13d, 0x28(%rbx)
movl %r15d, 0x2c(%rbx)
xorps %xmm0, %xmm0
movups %xmm0, 0x30(%rbx)
leaq 0x8(%rsp), %r12
movq %r12, %rdi
callq 0x2550
movq %r12, %rdi
xorl %esi, %esi
callq 0x21c0
leaq 0x68(%rbx), %rdi
movq %r12, %rsi
callq 0x2580
movq %rbx, %rdi
addq $0x40, %rdi
movq %r12, %rsi
callq 0x2580
movq %r12, %rdi
callq 0x2590
movq %r14, %rdi
movl %r15d, %esi
movl 0x4(%rsp), %edx
xorl %eax, %eax
callq 0x24b0
movl %eax, (%rbx)
testl %eax, %eax
js 0x354d
btl $0x9, %r13d
jb 0x3557
leaq 0xa0(%rsp), %rsi
movq %r14, %rdi
callq 0x2450
testl %eax, %eax
je 0x354d
leaq 0xa0(%rsp), %r14
movq %r14, %rdi
movl $0x1e8, %esi            # imm = 0x1E8
callq 0x20b0
leaq 0x10(%rsp), %rsi
movq %r14, %rdi
callq 0x2260
testl %eax, %eax
js 0x354d
movl $0xf000, %eax           # imm = 0xF000
andl 0x28(%rsp), %eax
cmpl $0x4000, %eax           # imm = 0x4000
jne 0x354d
leaq 0xa0(%rsp), %rdi
callq 0x2140
leaq 0x1(%rax), %rdi
callq 0x2390
movq %rax, 0x10(%rbx)
testq %rax, %rax
je 0x354d
leaq 0xa0(%rsp), %r14
movq %rax, %rdi
movq %r14, %rsi
callq 0x20a0
movq %r14, %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x24b0
movl %eax, 0x18(%rbx)
testl %eax, %eax
js 0x354d
leaq 0x1f92(%rip), %rdx      # 0x5430
leaq 0x10a0(%rsp), %r14
leaq 0xa0(%rsp), %rcx
movl $0x1000, %esi           # imm = 0x1000
movq %r14, %rdi
xorl %eax, %eax
callq 0x21b0
pushq $0x42
popq %rsi
movq %r14, %rdi
movl $0x180, %edx            # imm = 0x180
xorl %eax, %eax
callq 0x24b0
testl %eax, %eax
js 0x354d
movl %eax, %ebp
movl %eax, 0x1c(%rbx)
movl %eax, %edi
movl $0x110, %esi            # imm = 0x110
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x2480
leaq 0x10a0(%rsp), %rdi
leaq 0x10(%rsp), %r14
movq %r14, %rsi
callq 0x2260
cmpq $0x4, 0x30(%r14)
je 0x351d
leaq 0xc(%rsp), %rsi
andl $0x0, (%rsi)
pushq $0x4
popq %rdx
movl %ebp, %edi
xorl %ecx, %ecx
callq 0x2440
cmpl $0x4, %eax
jne 0x354d
movl %ebp, %edi
movl $0x10000, %esi          # imm = 0x10000
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x2480
pushq $0x4
popq %rsi
pushq $0x3
popq %rdx
pushq $0x1
popq %rcx
xorl %edi, %edi
movl %ebp, %r8d
xorl %r9d, %r9d
callq 0x2160
movq %rax, 0x20(%rbx)
cmpq $-0x1, %rax
jne 0x3557
movq %rbx, %rdi
callq 0x2490
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x20a8, %rsp           # imm = 0x20A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq