// File: /workspace/github_c_makefile_star2_O0/icysunlight[P]miniftpd/ftpproto.c
// Function: do_retr
void do_retr(session_t *sess)
{
    //打开数据连接
    int data_fd = get_datafd(sess);
    sess->datafd = data_fd;
    if ( -1 == data_fd )
    {
        ftp_reply(sess,FTP_BADSENDCONN,"Use port or pasv first");
        return;
    }

    //打开文件并加锁
    if ( is_dir(sess->arg) )
    {
        ftp_reply(sess,FTP_BADSENDFILE,"Read local file fail.");
        return;
    }
    int filefd = open(sess->arg,O_RDONLY);
    if ( -1 == filefd )
    {
        ftp_reply(sess,FTP_BADSENDFILE,"Read local file fail.");
        return;
    }
    if ( -1 == file_rdlock(filefd)) 
    {
        ftp_reply(sess,FTP_BADSENDFILE,"Read local file fail.");
        close(filefd);
        return;
    }

    //读取文件大小
    off_t filesize = lseek(filefd,0,SEEK_END);
    lseek(filefd,sess->rest_pos,SEEK_SET);
    
    //发送开始信息
    char buf[2048] = {0};
    sprintf(buf,"Openning BINARY mode data connect for %s (%lld bytes)",sess->arg,(long long)filesize);
    ftp_reply(sess,FTP_DATACONN,buf);

    int flag = 0;
    //发送文件
    if ( 0 == sess->bASCII)
    {
        off_t sizetosend = filesize - sess->rest_pos;
        while ( 0 != sizetosend )
        {
            ratelim_init(sess);
            data_disconn_start();
            ssize_t sizecur = sizetosend > 2048 ? 2048 : sizetosend;
            ssize_t ret = sendfile(data_fd,filefd,NULL,sizecur);
            if ( -1 == ret )
            {
                flag = 1;
                break; 
            } 
            sizetosend -= ret;
            ratelim_do(sess,tunable_download_max_rate,ret);
            b_dataconn = 1; 
        }
    }

    switch (flag)
    {
        case 0:
            ftp_reply(sess,FTP_TRANSFEROK,"Transfer complete.");
            break;
        case 1:
            ftp_reply(sess,FTP_BADSENDNET,"Send file failure.");
            break;
    }

    is_urg(sess);
    file_unlock(filefd);
    close(data_fd);
    close(filefd);
    clear_transfer(sess);
    sess->rest_pos = 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x850, %rsp            # imm = 0x850
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
callq 0x6400
movl %eax, -0xc(%rbp)
movl -0xc(%rbp), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0xc(%rax)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl -0xc(%rbp), %eax
jne 0x6a49
movq -0x8(%rbp), %rdi
movl $0x1a9, %esi            # imm = 0x1A9
leaq 0x2b84(%rip), %rdx      # 0x95c3
callq 0x5600
jmp 0x6ce2
movq -0x8(%rbp), %rdi
addq $0x818, %rdi            # imm = 0x818
callq 0x5de0
cmpl $0x0, %eax
je 0x6a78
movq -0x8(%rbp), %rdi
movl $0x1c3, %esi            # imm = 0x1C3
leaq 0x2b6c(%rip), %rdx      # 0x95da
callq 0x5600
jmp 0x6ce2
movq -0x8(%rbp), %rdi
addq $0x818, %rdi            # imm = 0x818
xorl %esi, %esi
movb $0x0, %al
callq 0x3450
movl %eax, -0x10(%rbp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl -0x10(%rbp), %eax
jne 0x6ab3
movq -0x8(%rbp), %rdi
movl $0x1c3, %esi            # imm = 0x1C3
leaq 0x2b31(%rip), %rdx      # 0x95da
callq 0x5600
jmp 0x6ce2
movl -0x10(%rbp), %edi
callq 0x3a60
movl %eax, %ecx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl %ecx, %eax
jne 0x6ae8
movq -0x8(%rbp), %rdi
movl $0x1c3, %esi            # imm = 0x1C3
leaq 0x2b04(%rip), %rdx      # 0x95da
callq 0x5600
movl -0x10(%rbp), %edi
callq 0x3260
jmp 0x6ce2
movl -0x10(%rbp), %edi
xorl %eax, %eax
movl %eax, %esi
movl $0x2, %edx
callq 0x31e0
movq %rax, -0x18(%rbp)
movl -0x10(%rbp), %edi
movq -0x8(%rbp), %rax
movq 0xc30(%rax), %rsi
xorl %edx, %edx
callq 0x31e0
leaq -0x820(%rbp), %rdi
xorl %esi, %esi
movl $0x800, %edx            # imm = 0x800
callq 0x3220
leaq -0x820(%rbp), %rdi
movq -0x8(%rbp), %rdx
addq $0x818, %rdx            # imm = 0x818
movq -0x18(%rbp), %rcx
leaq 0x2aae(%rip), %rsi      # 0x95f0
movb $0x0, %al
callq 0x34d0
movq -0x8(%rbp), %rdi
leaq -0x820(%rbp), %rdx
movl $0x96, %esi
callq 0x5600
movl $0x0, -0x824(%rbp)
movq -0x8(%rbp), %rcx
xorl %eax, %eax
cmpl 0x10(%rcx), %eax
jne 0x6c5e
movq -0x18(%rbp), %rax
movq -0x8(%rbp), %rcx
subq 0xc30(%rcx), %rax
movq %rax, -0x830(%rbp)
xorl %eax, %eax
cmpq -0x830(%rbp), %rax
je 0x6c5c
movq -0x8(%rbp), %rdi
callq 0x4dc0
callq 0x5ed0
cmpq $0x800, -0x830(%rbp) # imm = 0x800
jle 0x6bc5
movl $0x800, %eax            # imm = 0x800
movq %rax, -0x848(%rbp)
jmp 0x6bd3
movq -0x830(%rbp), %rax
movq %rax, -0x848(%rbp)
movq -0x848(%rbp), %rax
movq %rax, -0x838(%rbp)
movl -0xc(%rbp), %edi
movl -0x10(%rbp), %esi
movq -0x838(%rbp), %rcx
xorl %eax, %eax
movl %eax, %edx
callq 0x33d0
movq %rax, -0x840(%rbp)
movq $-0x1, %rax
cmpq -0x840(%rbp), %rax
jne 0x6c1a
movl $0x1, -0x824(%rbp)
jmp 0x6c5c
movq -0x840(%rbp), %rcx
movq -0x830(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x830(%rbp)
movq -0x8(%rbp), %rdi
leaq 0x66ab(%rip), %rax      # 0xd2e8
movl (%rax), %esi
movq -0x840(%rbp), %rax
movl %eax, %edx
callq 0x4e20
movl $0x1, 0x6a49(%rip)      # 0xd6a0
jmp 0x6b8d
jmp 0x6c5e
movl -0x824(%rbp), %eax
movl %eax, -0x84c(%rbp)
testl %eax, %eax
je 0x6c7d
jmp 0x6c70
movl -0x84c(%rbp), %eax
subl $0x1, %eax
je 0x6c94
jmp 0x6ca9
movq -0x8(%rbp), %rdi
movl $0xe2, %esi
leaq 0x2999(%rip), %rdx      # 0x9626
callq 0x5600
jmp 0x6ca9
movq -0x8(%rbp), %rdi
movl $0x1aa, %esi            # imm = 0x1AA
leaq 0x2995(%rip), %rdx      # 0x9639
callq 0x5600
movq -0x8(%rbp), %rdi
callq 0x6110
movl -0x10(%rbp), %edi
callq 0x3ae0
movl -0xc(%rbp), %edi
callq 0x3260
movl -0x10(%rbp), %edi
callq 0x3260
movq -0x8(%rbp), %rdi
callq 0x4cc0
movq -0x8(%rbp), %rax
movq $0x0, 0xc30(%rax)
addq $0x850, %rsp            # imm = 0x850
popq %rbp
retq
nopl (%rax,%rax)