⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpdataio.c

📁 文件传输协议linux 下vsftpd2.1.0.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
  }  if (loc_result.found && tunable_ls_recurse_enable)  {    p_subdir_list = &subdir_list;  }  vsf_ls_populate_dir_list(&dir_list, p_subdir_list, p_dir, p_base_dir_str,                           p_option_str, p_filter_str, is_verbose);  if (p_subdir_list)  {    int retval;    str_copy(&dir_prefix_str, p_base_dir_str);    str_append_text(&dir_prefix_str, ":\r\n");    retval = ftp_write_str(p_sess, &dir_prefix_str, target);    if (retval != 0)    {      failed = 1;    }  }  if (!failed)  {    failed = write_dir_list(p_sess, &dir_list, target);  }  /* Recurse into the subdirectories if required... */  if (!failed)  {    struct mystr sub_str = INIT_MYSTR;    unsigned int num_subdirs = str_list_get_length(&subdir_list);    unsigned int subdir_index;    for (subdir_index = 0; subdir_index < num_subdirs; subdir_index++)    {      int retval;      struct vsf_sysutil_dir* p_subdir;      const struct mystr* p_subdir_str =         str_list_get_pstr(&subdir_list, subdir_index);      if (str_equal_text(p_subdir_str, ".") ||          str_equal_text(p_subdir_str, ".."))      {        continue;      }      str_copy(&sub_str, p_base_dir_str);      str_append_char(&sub_str, '/');      str_append_str(&sub_str, p_subdir_str);      p_subdir = str_opendir(&sub_str);      if (p_subdir == 0)      {        /* Unreadable, gone missing, etc. - no matter */        continue;      }      str_alloc_text(&dir_prefix_str, "\r\n");      retval = ftp_write_str(p_sess, &dir_prefix_str, target);      if (retval != 0)      {        failed = 1;        break;      }      retval = transfer_dir_internal(p_sess, is_control, p_subdir, &sub_str,                                     p_option_str, p_filter_str, is_verbose);      vsf_sysutil_closedir(p_subdir);      if (retval != 0)      {        failed = 1;        break;      }    }    str_free(&sub_str);  }  str_list_free(&dir_list);  str_list_free(&subdir_list);  str_free(&dir_prefix_str);  if (!failed)  {    return 0;  }  else  {    return -1;  }}/* XXX - really, this should be refactored into a "buffered writer" object */static intwrite_dir_list(struct vsf_session* p_sess, struct mystr_list* p_dir_list,               enum EVSFRWTarget target){  /* This function writes out a list of strings to the client, over the   * data socket. We now coalesce the strings into fewer write() syscalls,   * which saved 33% CPU time writing a large directory.   */  int retval = 0;  unsigned int dir_index_max = str_list_get_length(p_dir_list);  unsigned int dir_index;  struct mystr buf_str = INIT_MYSTR;  str_reserve(&buf_str, VSFTP_DIR_BUFSIZE);  for (dir_index = 0; dir_index < dir_index_max; dir_index++)  {    str_append_str(&buf_str, str_list_get_pstr(p_dir_list, dir_index));    if (dir_index == dir_index_max - 1 ||        str_getlen(&buf_str) +          str_getlen(str_list_get_pstr(p_dir_list, dir_index + 1)) >            VSFTP_DIR_BUFSIZE)    {      /* Writeout needed - we're either at the end, or we filled the buffer */      int writeret = ftp_write_str(p_sess, &buf_str, target);      if (writeret != 0)      {        retval = 1;        break;      }      str_empty(&buf_str);    }  }  str_free(&buf_str);  return retval;}struct vsf_transfer_retvsf_ftpdataio_transfer_file(struct vsf_session* p_sess, int remote_fd,                            int file_fd, int is_recv, int is_ascii){  if (!is_recv)  {    if (is_ascii || p_sess->data_use_ssl)    {      return do_file_send_rwloop(p_sess, file_fd, is_ascii);    }    else    {      filesize_t curr_offset = vsf_sysutil_get_file_offset(file_fd);      filesize_t num_send = calc_num_send(file_fd, curr_offset);      return do_file_send_sendfile(        p_sess, remote_fd, file_fd, curr_offset, num_send);    }  }  else  {    return do_file_recv(p_sess, file_fd, is_ascii);  }}static struct vsf_transfer_retdo_file_send_rwloop(struct vsf_session* p_sess, int file_fd, int is_ascii){  static char* p_readbuf;  static char* p_asciibuf;  struct vsf_transfer_ret ret_struct = { 0, 0 };  unsigned int chunk_size = get_chunk_size();  char* p_writefrom_buf;  int prev_cr = 0;  if (p_readbuf == 0)  {    vsf_secbuf_alloc(&p_readbuf, VSFTP_DATA_BUFSIZE);  }  if (is_ascii)  {    if (p_asciibuf == 0)    {      /* NOTE!! * 2 factor because we can double the data by doing our ASCII       * linefeed mangling       */      vsf_secbuf_alloc(&p_asciibuf, VSFTP_DATA_BUFSIZE * 2);    }    p_writefrom_buf = p_asciibuf;  }  else  {    p_writefrom_buf = p_readbuf;  }  while (1)  {    unsigned int num_to_write;    int retval = vsf_sysutil_read(file_fd, p_readbuf, chunk_size);    if (vsf_sysutil_retval_is_error(retval))    {      ret_struct.retval = -1;      return ret_struct;    }    else if (retval == 0)    {      /* Success - cool */      return ret_struct;    }    if (is_ascii)    {      struct bin_to_ascii_ret ret =          vsf_ascii_bin_to_ascii(p_readbuf,                                 p_asciibuf,                                 (unsigned int) retval,                                 prev_cr);      num_to_write = ret.stored;      prev_cr = ret.last_was_cr;    }    else    {      num_to_write = (unsigned int) retval;    }    retval = ftp_write_data(p_sess, p_writefrom_buf, num_to_write);    if (!vsf_sysutil_retval_is_error(retval))    {      ret_struct.transferred += (unsigned int) retval;    }    if (vsf_sysutil_retval_is_error(retval) ||        (unsigned int) retval != num_to_write)    {      ret_struct.retval = -2;      return ret_struct;    }  }}static struct vsf_transfer_retdo_file_send_sendfile(struct vsf_session* p_sess, int net_fd, int file_fd,                      filesize_t curr_file_offset, filesize_t bytes_to_send){  int retval;  unsigned int chunk_size = 0;  struct vsf_transfer_ret ret_struct = { 0, 0 };  filesize_t init_file_offset = curr_file_offset;  filesize_t bytes_sent;  if (p_sess->bw_rate_max)  {    chunk_size = get_chunk_size();  }  /* Just because I can ;-) */  retval = vsf_sysutil_sendfile(net_fd, file_fd, &curr_file_offset,                                bytes_to_send, chunk_size);  bytes_sent = curr_file_offset - init_file_offset;  ret_struct.transferred = bytes_sent;  if (vsf_sysutil_retval_is_error(retval))  {    ret_struct.retval = -2;    return ret_struct;  }  else if (bytes_sent != bytes_to_send)  {    ret_struct.retval = -2;    return ret_struct;  }  return ret_struct; }static filesize_tcalc_num_send(int file_fd, filesize_t init_offset){  static struct vsf_sysutil_statbuf* s_p_statbuf;  filesize_t bytes_to_send;  /* Work out how many bytes to send based on file size minus current offset */  vsf_sysutil_fstat(file_fd, &s_p_statbuf);  bytes_to_send = vsf_sysutil_statbuf_get_size(s_p_statbuf);  if (init_offset < 0 || bytes_to_send < 0)  {    die("calc_num_send: negative file offset or send count");  }  /* Don't underflow if some bonehead sets a REST greater than the file size */  if (init_offset > bytes_to_send)  {    bytes_to_send = 0;  }  else  {    bytes_to_send -= init_offset;  }  return bytes_to_send;}static struct vsf_transfer_retdo_file_recv(struct vsf_session* p_sess, int file_fd, int is_ascii){  static char* p_recvbuf;  unsigned int num_to_write;  struct vsf_transfer_ret ret_struct = { 0, 0 };  unsigned int chunk_size = get_chunk_size();  int prev_cr = 0;  if (p_recvbuf == 0)  {    /* Now that we do ASCII conversion properly, the plus one is to cater for     * the fact we may need to stick a '\r' at the front of the buffer if the     * last buffer fragment eneded in a '\r' and the current buffer fragment     * does not start with a '\n'.     */    vsf_secbuf_alloc(&p_recvbuf, VSFTP_DATA_BUFSIZE + 1);  }  while (1)  {    const char* p_writebuf = p_recvbuf + 1;    int retval = ftp_read_data(p_sess, p_recvbuf + 1, chunk_size);    if (vsf_sysutil_retval_is_error(retval))    {      ret_struct.retval = -2;      return ret_struct;    }    else if (retval == 0 && !prev_cr)    {      /* Transfer done, nifty */      return ret_struct;    }    num_to_write = (unsigned int) retval;    ret_struct.transferred += num_to_write;    if (is_ascii)    {      /* Handle ASCII conversion if we have to. Note that using the same       * buffer for source and destination is safe, because the ASCII ->       * binary transform only ever results in a smaller file.       */      struct ascii_to_bin_ret ret =        vsf_ascii_ascii_to_bin(p_recvbuf, num_to_write, prev_cr);      num_to_write = ret.stored;      prev_cr = ret.last_was_cr;      p_writebuf = ret.p_buf;    }    retval = vsf_sysutil_write_loop(file_fd, p_writebuf, num_to_write);    if (vsf_sysutil_retval_is_error(retval) ||        (unsigned int) retval != num_to_write)    {      ret_struct.retval = -1;      return ret_struct;    }  }}static unsigned intget_chunk_size(){  unsigned int ret = VSFTP_DATA_BUFSIZE;  if (tunable_trans_chunk_size < VSFTP_DATA_BUFSIZE &&      tunable_trans_chunk_size > 0)  {    ret = tunable_trans_chunk_size;    if (ret < 4096)    {      ret = 4096;    }  }  return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -