示例#1
0
static struct vsf_transfer_ret
do_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;
  if (p_readbuf == 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);
    vsf_secbuf_alloc(&p_readbuf, VSFTP_DATA_BUFSIZE);
  }
  if (is_ascii)
  {
    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)
    {
      num_to_write = vsf_ascii_bin_to_ascii(p_readbuf, p_asciibuf,
                                            (unsigned int) retval);
    }
    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) ||
        (unsigned int) retval != num_to_write)
    {
      ret_struct.retval = -2;
      return ret_struct;
    }
    ret_struct.transferred += (unsigned int) retval;
  }
}
示例#2
0
int
ftp_read_data(const struct vsf_session* p_sess, char* p_buf, unsigned int len)
{
  if (p_sess->data_use_ssl)
  {
    return ssl_read(p_sess->p_data_ssl, p_buf, len);
  }
  else
  {
    return vsf_sysutil_read(p_sess->data_fd, p_buf, len);
  }
}
示例#3
0
int
ftp_read_data(struct vsf_session* p_sess, char* p_buf, unsigned int len)
{
    if (p_sess->data_use_ssl && p_sess->ssl_slave_active)
    {
        int ret;
        priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_READ);
        ret = priv_sock_get_int(p_sess->ssl_consumer_fd);
        priv_sock_recv_buf(p_sess->ssl_consumer_fd, p_buf, len);
        /* Need to do this here too because it is useless in the slave process. */
        vsf_sysutil_check_pending_actions(kVSFSysUtilIO, ret, p_sess->data_fd);
        return ret;
    }
    else if (p_sess->data_use_ssl)
    {
        return ssl_read(p_sess, p_sess->p_data_ssl, p_buf, len);
    }
    else
    {
        return vsf_sysutil_read(p_sess->data_fd, p_buf, len);
    }
}
示例#4
0
static int do_sendfile(const int out_fd, const int in_fd,
                       unsigned int num_send, filesize_t start_pos)
{
  /* Probably should one day be shared with instance in ftpdataio.c */
  static char* p_recvbuf;
  unsigned int total_written = 0;
  int retval;
  enum EVSFSysUtilError error;
  (void) start_pos;
  (void) error;
#if defined(VSF_SYSDEP_HAVE_LINUX_SENDFILE) || \
    defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE) || \
    defined(VSF_SYSDEP_HAVE_HPUX_SENDFILE) || \
    defined(VSF_SYSDEP_HAVE_AIX_SENDFILE) || \
    defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE)
  if (tunable_use_sendfile)
  {
    static int s_sendfile_checked;
    static int s_runtime_sendfile_works;
    if (!s_sendfile_checked || s_runtime_sendfile_works)
    {
      do
      {
  #ifdef VSF_SYSDEP_HAVE_LINUX_SENDFILE
        retval = sendfile(out_fd, in_fd, NULL, num_send);
  #elif defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE)
        {
          /* XXX - start_pos will truncate on 32-bit machines - can we
           * say "start from current pos"?
           */
          off_t written = 0;
          retval = sendfile(in_fd, out_fd, start_pos, num_send, NULL,
                            &written, 0);
          /* Translate to Linux-like retval */
          if (written > 0)
          {
            retval = (int) written;
          }
        }
  #elif defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE)
        {
          size_t written = 0;
          struct sendfilevec the_vec;
          vsf_sysutil_memclr(&the_vec, sizeof(the_vec));
          the_vec.sfv_fd = in_fd;
          the_vec.sfv_off = start_pos;
          the_vec.sfv_len = num_send;
          retval = sendfilev(out_fd, &the_vec, 1, &written);
          /* Translate to Linux-like retval */
          if (written > 0)
          {
            retval = (int) written;
          }
        }
  #elif defined(VSF_SYSDEP_HAVE_AIX_SENDFILE)
        {
          struct sf_parms sf_iobuf;
          vsf_sysutil_memclr(&sf_iobuf, sizeof(sf_iobuf));
          sf_iobuf.header_data = NULL;
          sf_iobuf.header_length = 0;
          sf_iobuf.trailer_data = NULL;
          sf_iobuf.trailer_length = 0;
          sf_iobuf.file_descriptor = in_fd;
          sf_iobuf.file_offset = start_pos;
          sf_iobuf.file_bytes = num_send;

          retval = send_file((int*)&out_fd, &sf_iobuf, 0);
          if (retval >= 0)
          {
            retval = sf_iobuf.bytes_sent;
          }
        }
  #else /* must be VSF_SYSDEP_HAVE_HPUX_SENDFILE */
        {
          retval = sendfile(out_fd, in_fd, start_pos, num_send, NULL, 0);
        }
  #endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE */
        error = vsf_sysutil_get_error();
        vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, out_fd);
      }
      while (vsf_sysutil_retval_is_error(retval) &&
             error == kVSFSysUtilErrINTR);
      if (!s_sendfile_checked)
      {
        s_sendfile_checked = 1;
        if (!vsf_sysutil_retval_is_error(retval) ||
            error != kVSFSysUtilErrNOSYS)
        {
          s_runtime_sendfile_works = 1;
        }
      }
      if (!vsf_sysutil_retval_is_error(retval))
      {
        return retval;
      }
      if (s_runtime_sendfile_works && error != kVSFSysUtilErrINVAL &&
          error != kVSFSysUtilErrOPNOTSUPP)
      {
        return retval;
      }
      /* Fall thru to normal implementation. We won't check again. NOTE -
       * also falls through if sendfile() is OK but it returns EINVAL. For
       * Linux this means the file was not page cache backed. Original
       * complaint was trying to serve files from an NTFS filesystem!
       */
    }
  }
#endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE || VSF_SYSDEP_HAVE_FREEBSD_SENDFILE */
  if (p_recvbuf == 0)
  {
    vsf_secbuf_alloc(&p_recvbuf, VSFTP_DATA_BUFSIZE);
  }
  while (1)
  {
    unsigned int num_read;
    unsigned int num_written;
    unsigned int num_read_this_time = VSFTP_DATA_BUFSIZE;
    if (num_read_this_time > num_send)
    {
      num_read_this_time = num_send;
    }
    retval = vsf_sysutil_read(in_fd, p_recvbuf, num_read_this_time);
    if (retval < 0)
    {
      return retval;
    }
    else if (retval == 0)
    {
      return -1;
    }
    num_read = (unsigned int) retval;
    retval = vsf_sysutil_write_loop(out_fd, p_recvbuf, num_read);
    if (retval < 0)
    {
      return retval;
    }
    num_written = (unsigned int) retval;
    total_written += num_written;
    if (num_written != num_read)
    {
      return num_written;
    }
    if (num_written > num_send)
    {
      bug("num_written bigger than num_send in do_sendfile");
    }
    num_send -= num_written;
    if (num_send == 0)
    {
      /* Bingo! */
      return total_written;
    }
  }
}