Ejemplo n.º 1
0
int ftp_putfile(SESSION handle, const char *lname, const char *rname,
                uint8_t how, uint8_t xfrmode)
{
  FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
  FAR char *abslpath;
  struct stat statbuf;
  FILE *finstream;
  int ret;

  /* Don't call this with a NULL local file name */

  DEBUGASSERT(lname);

  /* If the remote name is not specified, then it is assumed to the same as
   * the local file name.
   */

  if (!rname)
    {
      rname = lname;
    }

  /* Get the full path to the local file */

  abslpath = ftpc_abslpath(session, lname);
  if (!abslpath)
    {
      ndbg("ftpc_abslpath(%s) failed: %d\n", errno);
      goto errout;
    }

  /* Make sure that the local file exists */

  ret = stat(abslpath, &statbuf);
  if (ret != OK)
    {
      ndbg("stat(%s) failed: %d\n", errno);
      goto errout_with_abspath;
    }

  /* Make sure that the local name does not refer to a directory */

  if (S_ISDIR(statbuf.st_mode))
    {
      ndbg("%s is a directory\n", abslpath);
      goto errout_with_abspath;
    }

  /* Open the local file for reading */

  finstream = fopen(abslpath, "r");
  if (!finstream)
    {
      ndbg("fopen() failed: %d\n", errno);
      goto errout_with_abspath;
    }

  /* Are we resuming a transfer? */

  session->offset = 0;
  if (how == FTPC_PUT_RESUME)
    {
      /* Yes... Get the size of the file.  This will only work if the
       * server supports the SIZE command.
       */

      session->offset = ftpc_filesize(session, rname);
      if (session->offset == (off_t)ERROR)
        {
          ndbg("Failed to get size of remote file: %s\n", rname);
          goto errout_with_instream;
        }
      else
        {
          /* Seek to the offset in the file corresponding to the size
           * that we have already sent.
           */

          ret = fseek(finstream, session->offset, SEEK_SET);
          if (ret != OK)
            {
              ndbg("fseek failed: %d\n", errno);
              goto errout_with_instream;
            }
        }
    }

  /* Send the file */

  ret = ftpc_sendfile(session, rname, finstream, how, xfrmode);
  if (ret == OK)
    {
      fclose(finstream);
      free(abslpath);
      return OK;
    }

  /* Various error exits */

errout_with_instream:
  fclose(finstream);
errout_with_abspath:
  free(abslpath);
errout:
  return ERROR;
}
int ftpc_getfile(SESSION handle, FAR const char *rname, FAR const char *lname,
                 uint8_t how, uint8_t xfrmode)
{
  FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
  struct stat statbuf;
  FILE *loutstream;
  FAR char *abslpath;
  off_t offset;
  int ret;

  /* Don't call this with a NULL remote file name */

  DEBUGASSERT(rname);

  /* If the local name is not specified, then it is assumed to the same as
   * the remote file name.
   */

  if (!lname)
    {
      lname = rname;
    }

  /* Get the full path to the local file */

  abslpath = ftpc_abslpath(session, lname);
  if (!abslpath)
    {
      ndbg("ftpc_abslpath(%s) failed: %d\n", errno);
      goto errout;
    }

  /* Get information about the local file */

  ret = stat(abslpath, &statbuf);
  if (ret == 0)
    {
      /* It already exists.  Is it a directory? */

      if (S_ISDIR(statbuf.st_mode))
        {
          ndbg("'%s' is a directory\n", abslpath);
          goto errout_with_abspath;
        }
    }

  /* Is it write-able? */

#ifdef S_IWRITE
  if (!(statbuf.st_mode & S_IWRITE))
    {
      ndbg("'%s' permission denied\n", abslpath);
      goto errout_with_abspath;
    }
#endif

  /* Are we resuming the transfers?  Is so then the starting offset is the
   * size of the existing, partial file.
   */

  if (how == FTPC_GET_RESUME)
    {
      offset = statbuf.st_size;
    }
  else
    {
      offset = 0;
    }

  /* Setup to receive the file */

  ret = ftpc_recvinit(session, rname, xfrmode, offset);
  if (ret != OK)
    {
      ndbg("ftpc_recvinit failed\n");
      goto errout_with_abspath;
    }

  loutstream = fopen(abslpath, (offset > 0 || (how == FTPC_GET_APPEND)) ? "a" : "w");
  if (!loutstream)
    {
      ndbg("fopen failed: %d\n", errno);
      goto errout_with_abspath;
    }

  /* If the offset is non-zero, then seek to that offset in the file */

  if (offset > 0)
    {
      ret = fseek(loutstream, offset, SEEK_SET);
      if (ret != OK)
        {
          ndbg("fseek failed: %d\n", errno);
          goto errout_with_outstream;
        }
    }

  /* And receive the new file data */

  if (xfrmode == FTPC_XFRMODE_ASCII)
    {
      ret = ftpc_recvtext(session, session->data.instream, loutstream);
    }
  else
    {
      ret = ftpc_recvbinary(session, session->data.instream, loutstream);
    }

  ftpc_sockclose(&session->data);

  if (ret == 0)
    {
      fptc_getreply(session);
    }

  /* Check for success */

  if (ret == OK && !FTPC_INTERRUPTED(session))
    {
      fclose(loutstream);
      free(abslpath);
      return OK;
    }

  /* Various error exits */

errout_with_outstream:
  fclose(loutstream);
errout_with_abspath:
  free(abslpath);
  session->offset = 0;
errout:
  return ERROR;
}