// File: /workspace/github_cpp_makefile_star2_O2/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 $0x48, %rsp
movl %edx, %r12d
movq %rsi, %r13
movq %rdi, %rbx
xorps %xmm0, %xmm0
leaq 0x10(%rsp), %rax
movaps %xmm0, (%rax)
andq $0x0, 0x10(%rax)
movl $0xad, %edi
callq 0x4220
movq %rax, %r15
incq %r15
movl $0x0, 0x4(%rsp)
movq %rax, 0x8(%rsp)
cmpb $0x0, (%rbx)
leaq 0x6f7b(%rip), %rbp      # 0x12cde
je 0xbd68
movq %rbx, %rbp
movl %r12d, %edi
movq %rbp, %rsi
movl $0x210000, %edx         # imm = 0x210000
xorl %eax, %eax
callq 0x4540
movl %eax, %ebx
testb $0x1, 0x4(%rsp)
je 0xbd8b
movl %r12d, %edi
callq 0x4590
cmpl $-0x1, %ebx
je 0xbe9c
movl %ebx, %edi
movq %r13, %rsi
movl $0x20000, %edx          # imm = 0x20000
xorl %eax, %eax
callq 0x4540
cmpl $-0x1, %eax
jne 0xbeab
callq 0x4040
movq %rax, %r14
cmpl $0x28, (%rax)
jne 0xbeb2
decq %r15
je 0xbec3
leaq 0x28(%rsp), %rdi
movl %ebx, %esi
movq %r13, %rdx
callq 0xc537
cmpb $0x0, 0x28(%rsp)
je 0xbe34
leaq 0x10(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0xc982
movq 0x10(%rsp), %rbp
movq %rbp, %rdi
callq 0xc6b9
movq %rax, %r13
movb $0x1, %r14b
movq %rax, %rsi
subq %rbp, %rsi
je 0xbe48
cmpb $0x0, (%r13)
je 0xbe5a
movq %rbp, %rdi
callq 0xc0a2
testq %rdx, %rdx
je 0xbe48
cmpq $0x1, %rdx
jne 0xbe6e
movb $0x1, %al
movl %eax, 0x4(%rsp)
movl %ebx, %r12d
leaq 0x6e3d(%rip), %rbp      # 0x12c6f
jmp 0xbe7c
movl %ebx, %edi
callq 0x4590
movl (%r14), %eax
movq %rax, 0x8(%rsp)
xorl %r14d, %r14d
jmp 0xbe7c
movb $0x1, %al
movl %eax, 0x4(%rsp)
movl %ebx, %r12d
leaq 0x6c99(%rip), %rbp      # 0x12af1
jmp 0xbe7c
movl %ebx, %edi
callq 0x4590
xorl %r14d, %r14d
pushq $0x2
popq %rax
movq %rax, 0x8(%rsp)
jmp 0xbe7c
movb $0x0, (%rbp,%rdx)
movb $0x1, %al
movl %eax, 0x4(%rsp)
movl %ebx, %r12d
leaq 0x30(%rsp), %rdi
callq 0xc7a0
movq %rbp, %rbx
testb %r14b, %r14b
jne 0xbd59
pushq $-0x1
popq %rbx
movq 0x8(%rsp), %r14
jmp 0xbeae
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
callq 0x4040
movl (%rax), %r14d
jmp 0xbed3
movl %eax, %r14d
movl %ebx, %ebx
jmp 0xbed3
movl %ebx, %edi
callq 0x4590
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movl (%r14), %r14d
jmp 0xbed3
movl %ebx, %edi
callq 0x4590
pushq $0x28
popq %r14
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
leaq 0x10(%rsp), %rdi
callq 0xc7a0
shlq $0x20, %r14
orq %rbx, %r14
movq %r14, %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xbef8
movq %rax, %rdi
callq 0xac53