// File: /workspace/github_cpp_makefile_star2_O1/davmac314[P]dinit/src/control.cc
// Function: control_conn_t::query_load_mech()
bool control_conn_t::query_load_mech()
{
    rbuf.consume(1);
    chklen = 0;

    if (services->get_set_type_id() == SSET_TYPE_DIRLOAD) {
        dirload_service_set *dss = static_cast<dirload_service_set *>(services);
        std::vector<char> reppkt;
        reppkt.resize(2 + sizeof(uint32_t) * 2);  // packet type, loader type, packet size, # dirs
        reppkt[0] = (char)cp_rply::LOADER_MECH;
        reppkt[1] = SSET_TYPE_DIRLOAD;

        // Number of directories in load path:
        uint32_t sdirs = dss->get_service_dir_count();
        std::memcpy(reppkt.data() + 2 + sizeof(uint32_t), &sdirs, sizeof(sdirs));

        // Our current working directory, which above are relative to:
        // leave sizeof(uint32_t) for size, which we'll fill in afterwards:
        std::size_t curpos = reppkt.size() + sizeof(uint32_t);
#ifdef PATH_MAX
        uint32_t try_path_size = PATH_MAX;
#else
        uint32_t try_path_size = 2048;
#endif
        char *wd;
        while (true) {
            std::size_t total_size = curpos + std::size_t(try_path_size);
            if (total_size < curpos) {
                // Overflow. In theory we could now limit to size_t max, but the size must already
                // be crazy long; let's abort.
                char ack_rep[] = { (char)cp_rply::NAK };
                if (! queue_packet(ack_rep, 1)) return false;
                return true;
            }
            reppkt.resize(total_size);
            wd = getcwd(reppkt.data() + curpos, try_path_size);
            if (wd != nullptr) break;

            // Keep doubling the path size we try until it's big enough, or we get numeric overflow
            uint32_t new_try_path_size = try_path_size * uint32_t(2u);
            if (new_try_path_size < try_path_size) {
                // Overflow.
                char ack_rep[] = { (char)cp_rply::NAK };
                return queue_packet(ack_rep, 1);
            }
            try_path_size = new_try_path_size;
        }

        uint32_t wd_len = std::strlen(reppkt.data() + curpos);
        reppkt.resize(curpos + std::size_t(wd_len));
        std::memcpy(reppkt.data() + curpos - sizeof(uint32_t), &wd_len, sizeof(wd_len));

        // Each directory in the load path:
        for (int i = 0; uint32_t(i) < sdirs; i++) {
            const char *sdir = dss->get_service_dir(i);
            uint32_t dlen = std::strlen(sdir);
            auto cursize = reppkt.size();
            reppkt.resize(cursize + sizeof(dlen) + dlen);
            std::memcpy(reppkt.data() + cursize, &dlen, sizeof(dlen));
            std::memcpy(reppkt.data() + cursize + sizeof(dlen), sdir, dlen);
        }

        // Total packet size:
        uint32_t fsize = reppkt.size();
        std::memcpy(reppkt.data() + 2, &fsize, sizeof(fsize));

        if (! queue_packet(std::move(reppkt))) return false;
        return true;
    }
    else {
        // If we don't know how to deal with the service set type, send a NAK reply:
        char ack_rep[] = { (char)cp_rply::NAK };
        return queue_packet(ack_rep, 1);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdi, %rbx
movl 0x480(%rdi), %eax
leal 0x1(%rax), %ecx
addl $0xfffffc01, %eax       # imm = 0xFFFFFC01
cmpl $0x400, %ecx            # imm = 0x400
cmovbl %ecx, %eax
movl %eax, 0x480(%rdi)
decl 0x484(%rdi)
movl $0x0, 0x7c(%rdi)
movq 0x70(%rdi), %rdi
movq (%rdi), %rax
callq *0x20(%rax)
cmpl $0x1, %eax
jne 0x29fc7
movq 0x70(%rbx), %r15
xorps %xmm0, %xmm0
leaq 0x10(%rsp), %rdi
movaps %xmm0, (%rdi)
movq $0x0, 0x10(%rdi)
movl $0xa, %esi
callq 0x1c132
leaq 0x10(%rsp), %r14
movq (%r14), %rax
movb $0x40, (%rax)
movq (%r14), %rax
movb $0x1, 0x1(%rax)
movq 0x50(%r15), %rcx
movq %r15, 0x40(%rsp)
subq 0x48(%r15), %rcx
shrq $0x4, %rcx
movq (%r14), %rax
movq %rcx, 0x38(%rsp)
movl %ecx, 0x6(%rax)
movq 0x8(%r14), %r13
subq (%r14), %r13
addq $0x4, %r13
movl $0x1000, %r15d          # imm = 0x1000
movl %r15d, %r12d
movq %r13, %rsi
addq %r12, %rsi
jae 0x29eb2
movb $0x33, 0xf(%rsp)
movl $0x1, %r12d
movq %rbx, %rdi
leaq 0xf(%rsp), %rsi
movl $0x1, %edx
callq 0x27fd2
movl %eax, %ebp
jmp 0x29ee0
movq %r14, %rdi
callq 0x1c132
movq 0x10(%rsp), %rdi
addq %r13, %rdi
movq %r12, %rsi
callq 0x8300
movl $0x3, %r12d
testq %rax, %rax
jne 0x29ee0
testl %r15d, %r15d
js 0x29e91
addl %r15d, %r15d
xorl %r12d, %r12d
testl %r12d, %r12d
je 0x29e86
cmpl $0x3, %r12d
jne 0x29fae
movq %rbx, 0x30(%rsp)
leaq 0x10(%rsp), %r15
movq (%r15), %rdi
addq %r13, %rdi
callq 0x8230
movq %rax, %r14
movl %r14d, %esi
addq %r13, %rsi
movq %r15, %rdi
callq 0x1c132
movq 0x10(%rsp), %rax
movl %r14d, -0x4(%rax,%r13)
movq 0x38(%rsp), %rax
testl %eax, %eax
je 0x29f92
movl %eax, %ebp
shlq $0x4, %rbp
xorl %r14d, %r14d
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
movq (%rax,%r14), %r15
movq %r15, %rdi
callq 0x8230
movq %rax, %r13
movq 0x18(%rsp), %rbx
subq 0x10(%rsp), %rbx
movl %r13d, %r12d
leaq (%r12,%rbx), %rsi
addq $0x4, %rsi
leaq 0x10(%rsp), %rdi
callq 0x1c132
movq 0x10(%rsp), %rax
movl %r13d, (%rax,%rbx)
movq 0x10(%rsp), %rax
leaq (%rax,%rbx), %rdi
addq $0x4, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x84d0
addq $0x10, %r14
cmpq %r14, %rbp
jne 0x29f31
leaq 0x10(%rsp), %rsi
movl 0x8(%rsi), %eax
movq (%rsi), %rcx
subl %ecx, %eax
movl %eax, 0x2(%rcx)
movq 0x30(%rsp), %rdi
callq 0x2ada4
movl %eax, %ebp
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x29fde
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x8620
jmp 0x29fde
leaq 0x10(%rsp), %rsi
movb $0x33, (%rsi)
movq %rbx, %rdi
movl $0x1, %edx
callq 0x27fd2
movl %eax, %ebp
andb $0x1, %bpl
movl %ebp, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x29ff9
jmp 0x29ff9
jmp 0x29ff9
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x2a013
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x8620
movq %rbx, %rdi
callq 0x8ab0
nop