// File: /workspace/github_cpp_makefile_star2_O1/davmac314[P]dinit/src/includes/dinit-util.h
// Function: open_with_dir(char const*, char const*, int)
inline std::pair<int,int> open_with_dir(const char *dirname, const char *basename,
        int resolve_fd = AT_FDCWD) noexcept
{
    // For a file /x/y/z, if the final component 'z' is a link to /a/b/c, then the real parent
    // directory is /a/b (not /x/y).

    // This vector is used as backing for the next path if we need to "recurse" (i.e. if we need
    // to manually follow a symlink).
    std::vector<char> path_vec;

    // Whether to close resolve_fd after use (initially false because it is supplied by caller,
    // and we don't want to close the caller's fd):
    bool close_resolve_fd = false;

    long link_resolve_times = sysconf(_SC_SYMLOOP_MAX);

    // strip the basename and open as a directory
    #ifdef O_SEARCH
        constexpr int dir_search_flag = O_SEARCH;
    #else
        // O_SEARCH is not available on Linux
        constexpr int dir_search_flag = O_PATH;
    #endif

    begin:

    if (*dirname == '\0') {
        dirname = ".";
    }

    int parent_dir_fd = bp_sys::openat(resolve_fd, dirname, dir_search_flag | O_DIRECTORY);
    if (close_resolve_fd) bp_sys::close(resolve_fd);
    if (parent_dir_fd == -1) {
        return {-1, errno};
    }

    // open the final file (basename) without following symlinks
    int file_fd = bp_sys::openat(parent_dir_fd, basename, O_RDONLY | O_NOFOLLOW);
    if (file_fd == -1) {
        if (errno == ELOOP) {
            // It's a symlink
            if (link_resolve_times == 0) {
                // We've tried to resolve as many as the system normally would, so give up.
                bp_sys::close(parent_dir_fd);
                return {-1, ELOOP};
            }

            link_resolve_times--;

            // read the next path
            auto link_path_r = readlink_at_str(parent_dir_fd, basename);
            if (!link_path_r.first) {
                // If EINVAL, it's supposedly not a symbolic link. Maybe it changed out from
                // underneath us. The risk of handling this by looping back and trying as a file
                // again seems greater than the risk that this will actually happen, so let's not
                // worry about it, and just error out now:
                bp_sys::close(parent_dir_fd);
                return {-1, errno};
            }

            // Ok, we successfully read the link target. We need to extract the parent directory
            // name and base name, and then we'll jump back to 'begin' to iterate:
            path_vec = std::move(link_path_r.second);
            char *path = path_vec.data();
            dirname = path;
            basename = base_name(dirname);
            if (basename == dirname) {
                dirname = "";
            }
            else if (*basename == '\0') {
                bp_sys::close(parent_dir_fd);
                return {-1, ENOENT};
            }
            else {
                string_view path_ish {path, (size_t)(basename - path)};
                string_view parent_path_v = parent_path(path_ish);
                if (parent_path_v.length() == 1) {
                    // Parent path must be '/'. Inserting nul might overwrite base name string,
                    // so we need a separate string:
                    dirname = "/";
                }
                else if (parent_path_v.empty()) {
                    dirname = "";
                }
                else {
                    path[parent_path_v.length()] = '\0';
                }
            }

            resolve_fd = parent_dir_fd;
            close_resolve_fd = true;
            goto begin;
        }

        // Other errors: bail out
        bp_sys::close(parent_dir_fd);
        return {-1, errno};
    }

    return {parent_dir_fd, file_fd};
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movl %edx, %r15d
movq %rsi, %r13
movq %rdi, %r12
movl $0xad, %edi
callq 0x4210
movq %rax, 0x30(%rsp)
movq $0x0, 0x10(%rsp)
movq $0x0, 0x20(%rsp)
movq $0x0, 0x8(%rsp)
movq %rax, 0x18(%rsp)
xorl %ebx, %ebx
cmpb $0x0, (%r12)
leaq 0x6e5c(%rip), %rax      # 0x16d03
cmoveq %rax, %r12
movl %r15d, %edi
movq %r12, %rsi
movl $0x210000, %edx         # imm = 0x210000
xorl %eax, %eax
callq 0x4530
movl %eax, %ebp
testb $0x1, %bl
je 0xfecc
movl %r15d, %edi
callq 0x4560
cmpl $-0x1, %ebp
je 0xfef8
movl %ebp, %edi
movq %r13, %rsi
movl $0x20000, %edx          # imm = 0x20000
xorl %eax, %eax
callq 0x4530
cmpl $-0x1, %eax
je 0xff04
xorl %r14d, %r14d
movl %ebp, 0x4(%rsp)
movq %rax, 0x18(%rsp)
jmp 0x10024
callq 0x4040
movl (%rax), %eax
jmp 0x10014
callq 0x4040
movq %rax, %r14
cmpl $0x28, (%rax)
jne 0x1000a
cmpq $0x0, 0x30(%rsp)
je 0x10032
leaq 0x38(%rsp), %rdi
movl %ebp, %esi
movq %r13, %rdx
callq 0x108e5
cmpb $0x0, 0x38(%rsp)
je 0x10056
movq 0x40(%rsp), %r12
movq 0x48(%rsp), %r14
movq 0x50(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x8(%rsp), %rdi
movq %rdi, 0x40(%rsp)
movq 0x20(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x10(%rsp), %rsi
movq %rsi, 0x50(%rsp)
leaq 0x40(%rsp), %rax
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movq $0x0, 0x10(%rax)
testq %rdi, %rdi
je 0xff8d
subq %rdi, %rsi
callq 0x42f0
leaq 0x1(%r12), %rax
movq %r12, %r13
jmp 0xff9d
movq %rax, %r13
incq %rax
movzbl -0x1(%rax), %ecx
cmpl $0x2f, %ecx
je 0xff97
testl %ecx, %ecx
jne 0xff9a
movq %r13, %rax
subq %r12, %rax
je 0x100f4
cmpb $0x0, (%r13)
je 0x10075
movq %r12, 0x58(%rsp)
movq %rax, 0x60(%rsp)
leaq 0x58(%rsp), %rdi
movl $0x2f, %esi
callq 0x11f9e
cmpq $-0x1, %rax
je 0x100b4
testq %rax, %rax
je 0x10000
movq 0x58(%rsp), %rcx
leal -0x1(%rax), %edx
cmpb $0x2f, (%rcx,%rdx)
jne 0x100b8
decq %rax
jne 0xffee
movl $0x1, %eax
jmp 0x100c4
movl %ebp, %edi
callq 0x4560
movl (%r14), %eax
movq %rax, 0x18(%rsp)
movl $0xffffffff, 0x4(%rsp)  # imm = 0xFFFFFFFF
xorl %r14d, %r14d
testb %r14b, %r14b
jne 0xfe9b
jmp 0x1015b
movl %ebp, %edi
callq 0x4560
movl $0x28, %eax
movq %rax, 0x18(%rsp)
movl $0xffffffff, 0x4(%rsp)  # imm = 0xFFFFFFFF
movq $0x0, 0x30(%rsp)
jmp 0x10021
movl %ebp, %edi
callq 0x4560
movl (%r14), %eax
movq %rax, 0x18(%rsp)
movl $0xffffffff, 0x4(%rsp)  # imm = 0xFFFFFFFF
xorl %r14d, %r14d
jmp 0x1013a
movq %r14, 0x8(%rsp)
movl %ebp, %edi
callq 0x4560
movl $0x2, %eax
movq %rax, 0x18(%rsp)
movl $0xffffffff, 0x4(%rsp)  # imm = 0xFFFFFFFF
xorl %r14d, %r14d
movq 0x28(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x8(%rsp), %rax
movq %rax, 0x20(%rsp)
movq %r12, 0x8(%rsp)
jmp 0x1013a
xorl %eax, %eax
jmp 0x100c4
movq 0x60(%rsp), %rcx
cmpq %rax, %rcx
cmovbq %rcx, %rax
testq %rax, %rax
je 0x100f4
movb $0x1, %bl
cmpq $0x1, %rax
jne 0x10119
movq 0x28(%rsp), %rax
movq %rax, 0x10(%rsp)
movq %r14, 0x20(%rsp)
movq %r12, 0x8(%rsp)
movb $0x1, %r14b
movl %ebp, %r15d
leaq 0x6ba2(%rip), %r12      # 0x16c94
jmp 0x1013a
movb $0x1, %bl
movq 0x28(%rsp), %rax
movq %rax, 0x10(%rsp)
movq %r14, 0x20(%rsp)
movq %r12, 0x8(%rsp)
movb $0x1, %r14b
movl %ebp, %r15d
leaq 0x69ff(%rip), %r12      # 0x16b16
jmp 0x1013a
movb $0x0, (%r12,%rax)
movb $0x1, %bl
movq 0x28(%rsp), %rax
movq %rax, 0x10(%rsp)
movq %r14, 0x20(%rsp)
movq %r12, 0x8(%rsp)
movb $0x1, %r14b
movl %ebp, %r15d
movq 0x40(%rsp), %rdi
testq %rdi, %rdi
je 0x10151
movq 0x50(%rsp), %rsi
subq %rdi, %rsi
callq 0x42f0
decq 0x30(%rsp)
jmp 0x10024
movq 0x8(%rsp), %rdi
testq %rdi, %rdi
je 0x10172
movq 0x10(%rsp), %rsi
subq %rdi, %rsi
callq 0x42f0
movq 0x18(%rsp), %rcx
shlq $0x20, %rcx
movl 0x4(%rsp), %eax
orq %rcx, %rax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rdi
callq 0xe564
nop