// File: 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
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0xa0(%rbp)
addq $0x80, %rdi
movl $0x1, %esi
callq 0x5e1a0
movq -0xa0(%rbp), %rax
movl $0x0, 0x7c(%rax)
movq 0x70(%rax), %rdi
movq (%rdi), %rax
callq *0x20(%rax)
cmpl $0x1, %eax
jne 0x5ac96
movq -0xa0(%rbp), %rax
movq 0x70(%rax), %rax
movq %rax, -0x18(%rbp)
leaq -0x30(%rbp), %rdi
movq %rdi, -0xa8(%rbp)
callq 0x30d60
movq -0xa8(%rbp), %rdi
movl $0xa, %esi
callq 0x31490
jmp 0x5a9ee
leaq -0x30(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5e950
movb $0x40, (%rax)
leaq -0x30(%rbp), %rdi
movl $0x1, %esi
callq 0x5e950
movb $0x1, (%rax)
movq -0x18(%rbp), %rdi
callq 0x5f830
movl %eax, -0x40(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x31180
movl -0x40(%rbp), %ecx
movl %ecx, 0x6(%rax)
leaq -0x30(%rbp), %rdi
callq 0x31650
addq $0x4, %rax
movq %rax, -0x48(%rbp)
movl $0x1000, -0x4c(%rbp)    # imm = 0x1000
jmp 0x5aa44
movq -0x48(%rbp), %rax
movl -0x4c(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
cmpq -0x48(%rbp), %rax
jae 0x5aab8
movq -0xa0(%rbp), %rdi
movb 0x1e9fb(%rip), %al      # 0x79464
movb %al, -0x61(%rbp)
leaq -0x61(%rbp), %rsi
movl $0x1, %edx
callq 0x58340
testb $0x1, %al
jne 0x5aaa8
movb $0x0, -0x1(%rbp)
movl $0x1, -0x68(%rbp)
jmp 0x5ac8b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x13f20
jmp 0x5accd
movb $0x1, -0x1(%rbp)
movl $0x1, -0x68(%rbp)
jmp 0x5ac8b
movq -0x60(%rbp), %rsi
leaq -0x30(%rbp), %rdi
callq 0x31490
jmp 0x5aac7
leaq -0x30(%rbp), %rdi
callq 0x31180
movq %rax, %rdi
addq -0x48(%rbp), %rdi
movl -0x4c(%rbp), %eax
movl %eax, %esi
callq 0xa360
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x58(%rbp)
je 0x5aaee
jmp 0x5ab38
movl -0x4c(%rbp), %eax
shll %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jae 0x5ab2d
movq -0xa0(%rbp), %rdi
movb 0x1e95a(%rip), %al      # 0x79465
movb %al, -0x6d(%rbp)
leaq -0x6d(%rbp), %rsi
movl $0x1, %edx
callq 0x58340
andb $0x1, %al
movb %al, -0x1(%rbp)
movl $0x1, -0x68(%rbp)
jmp 0x5ac8b
movl -0x6c(%rbp), %eax
movl %eax, -0x4c(%rbp)
jmp 0x5aa42
leaq -0x30(%rbp), %rdi
movq %rdi, -0xb0(%rbp)
callq 0x31180
movq %rax, %rdi
movq -0x48(%rbp), %rax
addq %rax, %rdi
callq 0xa280
movq -0xb0(%rbp), %rdi
movl %eax, -0x74(%rbp)
movq -0x48(%rbp), %rsi
movl -0x74(%rbp), %eax
addq %rax, %rsi
callq 0x31490
jmp 0x5ab72
leaq -0x30(%rbp), %rdi
callq 0x31180
movq -0x48(%rbp), %rcx
movl -0x74(%rbp), %edx
movl %edx, -0x4(%rax,%rcx)
movl $0x0, -0x78(%rbp)
movl -0x78(%rbp), %eax
cmpl -0x40(%rbp), %eax
jae 0x5ac3e
movq -0x18(%rbp), %rdi
movl -0x78(%rbp), %esi
callq 0x5f850
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rdi
callq 0xa280
movl %eax, -0x84(%rbp)
leaq -0x30(%rbp), %rdi
movq %rdi, -0xb8(%rbp)
callq 0x31650
movq -0xb8(%rbp), %rdi
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
movl -0x84(%rbp), %ecx
leaq 0x4(%rax,%rcx), %rsi
callq 0x31490
jmp 0x5abef
leaq -0x30(%rbp), %rdi
callq 0x31180
movq -0x90(%rbp), %rcx
movl -0x84(%rbp), %edx
movl %edx, (%rax,%rcx)
leaq -0x30(%rbp), %rdi
callq 0x31180
movq %rax, %rdi
addq -0x90(%rbp), %rdi
addq $0x4, %rdi
movq -0x80(%rbp), %rsi
movl -0x84(%rbp), %eax
movl %eax, %edx
callq 0xa5b0
movl -0x78(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x78(%rbp)
jmp 0x5ab8d
leaq -0x30(%rbp), %rdi
callq 0x31650
movl %eax, -0x94(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x31180
movq -0xa0(%rbp), %rdi
movl -0x94(%rbp), %ecx
movl %ecx, 0x2(%rax)
leaq -0x30(%rbp), %rsi
callq 0x5bc70
testb $0x1, %al
jne 0x5ac80
movb $0x0, -0x1(%rbp)
movl $0x1, -0x68(%rbp)
jmp 0x5ac8b
movb $0x1, -0x1(%rbp)
movl $0x1, -0x68(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x13f20
jmp 0x5acbf
movq -0xa0(%rbp), %rdi
movb 0x1e7c3(%rip), %al      # 0x79466
movb %al, -0x95(%rbp)
leaq -0x95(%rbp), %rsi
movl $0x1, %edx
callq 0x58340
andb $0x1, %al
movb %al, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xc0, %rsp
popq %rbp
retq
movq -0x38(%rbp), %rdi
callq 0xacc0
nopw %cs:(%rax,%rax)