Example #1
0
void
bug(const char* p_text)
{
  /* Rats. Try and write the reason to the network for diagnostics */
  vsf_sysutil_activate_noblock(VSFTP_COMMAND_FD);
  (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, FTP_500_STRING, FTP_500_SIZE);
  (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, p_text,
                                vsf_sysutil_strlen(p_text));
  (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, "\r\n", 2);
  vsf_sysutil_exit(2);
}
Example #2
0
void
vsf_exit(const char* p_text)
{
  (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, p_text,
                                vsf_sysutil_strlen(p_text));
  vsf_sysutil_exit(0);
}
Example #3
0
static struct vsf_transfer_ret
do_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;
    }
  }
}
Example #4
0
int
ftp_write_data(const struct vsf_session* p_sess, const char* p_buf,
               unsigned int len)
{
  if (p_sess->data_use_ssl)
  {
    return ssl_write(p_sess->p_data_ssl, p_buf, len);
  }
  else
  {
    return vsf_sysutil_write_loop(p_sess->data_fd, p_buf, len);
  }
}
Example #5
0
static struct vsf_transfer_ret
do_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();
    if (p_recvbuf == 0)
    {
        vsf_secbuf_alloc(&p_recvbuf, VSFTP_DATA_BUFSIZE);
    }
    while (1)
    {
        int retval = ftp_read_data(p_sess, p_recvbuf, chunk_size);
        if (vsf_sysutil_retval_is_error(retval))
        {
            vsf_cmdio_write(p_sess, FTP_BADSENDNET,
                            "Failure reading network stream.");
            ret_struct.retval = -1;
            return ret_struct;
        }
        else if (retval == 0)
        {
            /* Transfer done, nifty */
            vsf_cmdio_write(p_sess, FTP_TRANSFEROK, "File receive OK.");
            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.
             */
            num_to_write = vsf_ascii_ascii_to_bin(p_recvbuf, p_recvbuf,
                                                  num_to_write);
        }
        retval = vsf_sysutil_write_loop(file_fd, p_recvbuf, num_to_write);
        if (vsf_sysutil_retval_is_error(retval) ||
                (unsigned int) retval != num_to_write)
        {
            vsf_cmdio_write(p_sess, FTP_BADSENDFILE,
                            "Failure writing to local file.");
            ret_struct.retval = -1;
            return ret_struct;
        }
    }
}
Example #6
0
int
ftp_write_data(const struct vsf_session* p_sess, const 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_WRITE);
        priv_sock_send_buf(p_sess->ssl_consumer_fd, p_buf, len);
        ret = priv_sock_get_int(p_sess->ssl_consumer_fd);
        /* 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_write(p_sess->p_data_ssl, p_buf, len);
    }
    else
    {
        return vsf_sysutil_write_loop(p_sess->data_fd, p_buf, len);
    }
}
Example #7
0
int
str_write_loop(const struct mystr* p_str, const int fd)
{
  return vsf_sysutil_write_loop(fd, str_getbuf(p_str), str_getlen(p_str));
}
Example #8
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;
    }
  }
}