// File: davmac314[P]dinit/src/dinit.cc
// Function: open_control_socket(bool)
static bool open_control_socket(bool report_ro_failure) noexcept
{
    if (control_socket_open) {
        struct stat stat_buf;
        if (stat(control_socket_path, &stat_buf) != 0 && errno == ENOENT) {
            // Looks like our control socket has disappeared from the filesystem. Close our control
            // socket and re-create it:
            control_socket_io.deregister(event_loop);
            close(control_socket_io.get_watched_fd());
            control_socket_open = false; // now re-open below
        }
    }

    if (!control_socket_open) {
        const char * saddrname = control_socket_path;
        size_t saddrname_len = strlen(saddrname);
        uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
        
        struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
        if (name == nullptr) {
            log(loglevel_t::ERROR, "Opening control socket: out of memory");
            return false;
        }

        name->sun_family = AF_UNIX;
        memcpy(name->sun_path, saddrname, saddrname_len + 1);

        int sockfd = dinit_socket(AF_UNIX, SOCK_STREAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
        if (sockfd == -1) {
            log(loglevel_t::ERROR, "Error creating control socket: ", strerror(errno));
            free(name);
            return false;
        }

        // Check if there is already an active control socket (from another instance).
        // Unfortunately, there's no way to check atomically if a socket file is stale. Still, we
        // will try to check, since the consequences of running a system dinit instance twice are
        // potentially severe.
        int connr = connect(sockfd, (struct sockaddr *) name, sockaddr_size);
        if (connr != -1 || errno == EAGAIN) {
            log(loglevel_t::ERROR, "Control socket is already active"
                    " (another instance already running?)");

            close(connr);
            close(sockfd);
            free(name);

            return false;
        }

        // Unlink any stale control socket file.
        //
        // In the worst case, this potentially removes a socket which was not active at the time
        // we checked (just above) but has since become active; there's just no good API to avoid
        // this (we'd have to use a file lock, on yet another file). Since that's unlikely to
        // occur in practice, and because a stale socket will prevent communication with dinit (or
        // prevent it starting), then we'll take the chance on unlinking here.
        unlink(saddrname);

        if (bind(sockfd, (struct sockaddr *) name, sockaddr_size) == -1) {
            bool have_error = (errno != EROFS || report_ro_failure);
            if (have_error) {
                log(loglevel_t::ERROR, "Error binding control socket: ", strerror(errno));
            }
            close(sockfd);
            free(name);
            return !have_error;
        }
        
        free(name);

        // No connections can be made until we listen, so it is fine to change the permissions now
        // (and anyway there is no way to atomically create the socket and set permissions):
        if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
            log(loglevel_t::ERROR, "Error setting control socket permissions: ", strerror(errno));
            close(sockfd);
            return false;
        }

        if (listen(sockfd, 10) == -1) {
            log(loglevel_t::ERROR, "Error listening on control socket: ", strerror(errno));
            close(sockfd);
            return false;
        }

        try {
            control_socket_io.add_watch(event_loop, sockfd, dasynq::IN_EVENTS);
            control_socket_open = true;
        }
        catch (std::exception &e)
        {
            log(loglevel_t::ERROR, "Could not setup I/O on control socket: ", e.what());
            close(sockfd);
        }
    }

    return control_socket_open;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movb %dil, %al
andb $0x1, %al
movb %al, -0x2(%rbp)
testb $0x1, 0x9bc09(%rip)     # 0xa8e53
je 0xd2b2
movq 0x9b4bd(%rip), %rdi     # 0xa8710
leaq -0x98(%rbp), %rsi
callq 0xa640
cmpl $0x0, %eax
je 0xd2b0
callq 0xa060
cmpl $0x2, (%rax)
jne 0xd2b0
leaq 0x9bb23(%rip), %rdi     # 0xa8d98
movq %rdi, -0x118(%rbp)
leaq 0x9b8dd(%rip), %rsi     # 0xa8b60
callq 0x17d20
movq -0x118(%rbp), %rdi
callq 0x17d50
movl %eax, -0x10c(%rbp)
jmp 0xd29c
movl -0x10c(%rbp), %edi
callq 0xad80
jmp 0xd2a9
movb $0x0, 0x9bba3(%rip)     # 0xa8e53
jmp 0xd2b2
testb $0x1, 0x9bb9a(%rip)     # 0xa8e53
jne 0xd668
movq 0x9b44a(%rip), %rax     # 0xa8710
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rdi
callq 0xa280
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
addq $0x2, %rax
addq $0x1, %rax
movl %eax, -0xac(%rbp)
movl -0xac(%rbp), %eax
movl %eax, %edi
callq 0xa9e0
movq %rax, -0xb8(%rbp)
cmpq $0x0, -0xb8(%rbp)
jne 0xd32d
movl $0x3, %edi
leaq 0x699b9(%rip), %rsi     # 0x76cd8
callq 0x6b540
movb $0x0, -0x1(%rbp)
jmp 0xd673
movq -0xb8(%rbp), %rax
movw $0x1, (%rax)
movq -0xb8(%rbp), %rdi
addq $0x2, %rdi
movq -0xa0(%rbp), %rsi
movq -0xa8(%rbp), %rdx
incq %rdx
callq 0xa5b0
movl $0x1, %esi
xorl %edx, %edx
movl $0x80800, %ecx          # imm = 0x80800
movl %esi, %edi
callq 0xdf80
movl %eax, -0x11c(%rbp)
jmp 0xd375
movl -0x11c(%rbp), %eax
movl %eax, -0xbc(%rbp)
cmpl $-0x1, -0xbc(%rbp)
jne 0xd3ca
callq 0xa060
movl (%rax), %edi
callq 0xa1f0
movq %rax, -0xc8(%rbp)
movl $0x3, %edi
leaq 0x69955(%rip), %rsi     # 0x76cfe
leaq -0xc8(%rbp), %rdx
callq 0xf090
movq -0xb8(%rbp), %rdi
callq 0xa890
movb $0x0, -0x1(%rbp)
jmp 0xd673
movl -0xbc(%rbp), %edi
movq -0xb8(%rbp), %rsi
movl -0xac(%rbp), %edx
callq 0xa5d0
movl %eax, -0x120(%rbp)
jmp 0xd3ea
movl -0x120(%rbp), %eax
movl %eax, -0xcc(%rbp)
cmpl $-0x1, -0xcc(%rbp)
jne 0xd409
callq 0xa060
cmpl $0xb, (%rax)
jne 0xd449
leaq 0x6990e(%rip), %rsi     # 0x76d1e
movl $0x3, %edi
callq 0x6b540
movl -0xcc(%rbp), %edi
callq 0xad80
jmp 0xd427
movl -0xbc(%rbp), %edi
callq 0xad80
jmp 0xd434
movq -0xb8(%rbp), %rdi
callq 0xa890
movb $0x0, -0x1(%rbp)
jmp 0xd673
movq -0xa0(%rbp), %rdi
callq 0xa2c0
movl -0xbc(%rbp), %edi
movq -0xb8(%rbp), %rsi
movl -0xac(%rbp), %edx
callq 0xa0b0
cmpl $-0x1, %eax
jne 0xd501
callq 0xa060
movq %rax, %rcx
movb $0x1, %al
cmpl $0x1e, (%rcx)
movb %al, -0x121(%rbp)
jne 0xd494
movb -0x2(%rbp), %al
movb %al, -0x121(%rbp)
movb -0x121(%rbp), %al
andb $0x1, %al
movb %al, -0xcd(%rbp)
testb $0x1, -0xcd(%rbp)
je 0xd4d6
callq 0xa060
movl (%rax), %edi
callq 0xa1f0
movq %rax, -0xd8(%rbp)
movl $0x3, %edi
leaq 0x69899(%rip), %rsi     # 0x76d63
leaq -0xd8(%rbp), %rdx
callq 0xf0c0
movl -0xbc(%rbp), %edi
callq 0xad80
jmp 0xd4e3
movq -0xb8(%rbp), %rdi
callq 0xa890
movb -0xcd(%rbp), %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0xd673
movq -0xb8(%rbp), %rdi
callq 0xa890
movq -0xa0(%rbp), %rdi
movl $0x180, %esi            # imm = 0x180
callq 0xa680
cmpl $-0x1, %eax
jne 0xd564
callq 0xa060
movl (%rax), %edi
callq 0xa1f0
movq %rax, -0xe0(%rbp)
leaq 0x69845(%rip), %rsi     # 0x76d82
movl $0x3, %edi
leaq -0xe0(%rbp), %rdx
callq 0xf0f0
movl -0xbc(%rbp), %edi
callq 0xad80
jmp 0xd55b
movb $0x0, -0x1(%rbp)
jmp 0xd673
movl -0xbc(%rbp), %edi
movl $0xa, %esi
callq 0xa810
cmpl $-0x1, %eax
jne 0xd5ba
callq 0xa060
movl (%rax), %edi
callq 0xa1f0
movq %rax, -0xe8(%rbp)
leaq 0x6981a(%rip), %rsi     # 0x76dad
movl $0x3, %edi
leaq -0xe8(%rbp), %rdx
callq 0xf120
movl -0xbc(%rbp), %edi
callq 0xad80
jmp 0xd5b1
movb $0x0, -0x1(%rbp)
jmp 0xd673
movl -0xbc(%rbp), %edx
leaq 0x9b7d1(%rip), %rdi     # 0xa8d98
leaq 0x9b592(%rip), %rsi     # 0xa8b60
movl $0x1, %r8d
movl $0x32, %r9d
movl %r8d, %ecx
callq 0xf690
jmp 0xd5e4
movb $0x1, 0x9b868(%rip)     # 0xa8e53
jmp 0xd666
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf0(%rbp)
movl %eax, -0xf4(%rbp)
movl -0xf4(%rbp), %eax
movl $0x2, %ecx
cmpl %ecx, %eax
jne 0xd689
movq -0xf0(%rbp), %rdi
callq 0xa240
movq %rax, -0x100(%rbp)
movq -0x100(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq %rax, -0x108(%rbp)
leaq 0x69792(%rip), %rsi     # 0x76dd1
movl $0x3, %edi
leaq -0x108(%rbp), %rdx
callq 0xf150
movl -0xbc(%rbp), %edi
callq 0xad80
jmp 0xd65d
callq 0xac30
jmp 0xd664
jmp 0xd666
jmp 0xd668
movb 0x9b7e5(%rip), %al      # 0xa8e53
andb $0x1, %al
movb %al, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
movq %rax, %rdi
callq 0xfa30
movq -0xf0(%rbp), %rdi
callq 0xfa30
nopw %cs:(%rax,%rax)