forked from xuos/xiuos
Add nuttx to the system framework, which is 10.1.0
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config NETUTILS_FTPC
|
||||
bool "FTP client"
|
||||
default n
|
||||
---help---
|
||||
Enable support for the FTP client.
|
||||
|
||||
if NETUTILS_FTPC
|
||||
|
||||
config DEBUG_FTPC
|
||||
bool "Debug FTP client"
|
||||
default n
|
||||
depends on DEBUG_FEATURES
|
||||
---help---
|
||||
Enable debug support for the FTP client. This option simple forces
|
||||
CONFIG_DEBUG_NET to be on, but only for the files within this directory.
|
||||
|
||||
config FTP_TMPDIR
|
||||
string "TMP directory path for FTP"
|
||||
default "/tmp"
|
||||
---help---
|
||||
The path to use for storing temporary files used in the transfer process
|
||||
by the FTP client.
|
||||
|
||||
config FTP_SIZE_CMD_MODE_BINARY
|
||||
bool "Use binary mode for size command"
|
||||
default n
|
||||
---help---
|
||||
Use binary transfer mode for FTP size command.
|
||||
|
||||
config FTPC_DISABLE_EPRT
|
||||
bool "Disable EPRT and use PORT instead"
|
||||
default n
|
||||
---help---
|
||||
FTP uses PORT and EPRT when in active mode. EPRT replaced PORT to allow
|
||||
for IPv6 support. EPRT is supported in most FTP implementations now. However,
|
||||
if you need to use PORT instead, use this option to disable EPRT and
|
||||
fallback to using PORT.
|
||||
|
||||
config FTPC_DISABLE_EPSV
|
||||
bool "Disable EPSV and use PASV instead"
|
||||
default n
|
||||
---help---
|
||||
FTP uses EPSV or PASV when in passive mode. EPSV replaced PASV to allow
|
||||
for IPv6 support. EPSV is supported in most FTP implementations now. However,
|
||||
if you need to use PASV instead, use this option to disable EPSV and
|
||||
fallback to using PASV.
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,38 @@
|
||||
# apps/netutils/ftpc/Make.defs
|
||||
# Adds selected applications to apps/ build
|
||||
#
|
||||
# Copyright (C) 2016 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifeq ($(CONFIG_NETUTILS_FTPC),y)
|
||||
CONFIGURED_APPS += $(APPDIR)/netutils/ftpc
|
||||
endif
|
||||
@@ -0,0 +1,58 @@
|
||||
############################################################################
|
||||
# apps/netutils/ftpc/Makefile
|
||||
#
|
||||
# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
ifeq ($(CONFIG_NET_TCP),y)
|
||||
# FTP connection management
|
||||
CSRCS += ftpc_connect.c ftpc_disconnect.c
|
||||
|
||||
# FTP commands
|
||||
CSRCS += ftpc_cdup.c ftpc_chdir.c ftpc_chmod.c ftpc_filesize.c ftpc_filetime.c
|
||||
CSRCS += ftpc_help.c ftpc_idle.c ftpc_listdir.c ftpc_login.c ftpc_mkdir.c
|
||||
CSRCS += ftpc_noop.c ftpc_rpwd.c ftpc_quit.c ftpc_rename.c ftpc_rmdir.c ftpc_unlink.c
|
||||
CSRCS += ftpc_cmd.c
|
||||
|
||||
# FTP transfers
|
||||
CSRCS += ftpc_getfile.c ftpc_putfile.c ftpc_transfer.c
|
||||
|
||||
# FTP responses
|
||||
CSRCS += ftpc_response.c ftpc_getreply.c
|
||||
|
||||
# FTP helpers
|
||||
CSRCS += ftpc_utils.c ftpc_socket.c
|
||||
endif
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
@@ -0,0 +1,81 @@
|
||||
# Network Utilities / `ftpc` FTP Client
|
||||
|
||||
## FTP Commands
|
||||
|
||||
- `ABOR` – abort a file transfer
|
||||
- `ACCT` – send account information
|
||||
- `APPE` – append to a remote file
|
||||
- `CDUP` – CWD to the parent of the current directory
|
||||
- `CWD` – change working directory
|
||||
- `DELE` – delete a remote file
|
||||
- `HELP` – return help on using the server
|
||||
- `LIST` – list remote files
|
||||
- `MDTM` – return the modification time of a file
|
||||
- `MKD` – make a remote directory
|
||||
- `MLSD` – Standardized directory listing (instead of `LIST`)
|
||||
- `MLST` – Standardized object listing (instead of `LIST`)
|
||||
- `MODE` – set transfer mode
|
||||
- `NLST` – name list of remote directory
|
||||
- `NOOP` – do nothing
|
||||
- `PASS` – send password
|
||||
- `PASV` – enter passive mode
|
||||
- `PORT` – open a data port
|
||||
- `PWD` – print working directory
|
||||
- `QUIT` – terminate the connection
|
||||
- `REIN` – reinitialize the connection
|
||||
- `RETR` – retrieve a remote file
|
||||
- `REST` – Sets the point at which a file transfer should start
|
||||
- `RMD` – remove a remote directory
|
||||
- `RNFR` – rename from
|
||||
- `RNTO` – rename to
|
||||
- `SITE` – site-specific commands
|
||||
- `SIZE` – return the size of a file
|
||||
- `STOR` – store a file on the remote host
|
||||
- `STOU` – store a file uniquely
|
||||
- `STRU` – set file transfer structure
|
||||
- `STAT` – return server status
|
||||
- `SYST` – return system type
|
||||
- `TYPE` – set transfer type
|
||||
- `USER` – send username
|
||||
|
||||
## FTP Replies
|
||||
|
||||
- `110` – Restart marker reply.
|
||||
- `120` – Service ready in nnn minutes.
|
||||
- `125` – Data connection already open; transfer starting.
|
||||
- `150` – File status okay; about to open data connection.
|
||||
- `200` – Command okay.
|
||||
- `202` – Command not implemented, superfluous at this site.
|
||||
- `211` – System status, or system help reply.
|
||||
- `212` – Directory status.
|
||||
- `213` – File status.
|
||||
- `214` – Help message.
|
||||
- `215` – NAME system type.
|
||||
- `220` – Service ready for new user.
|
||||
- `221` – Service closing control connection.
|
||||
- `225` – Data connection open; no transfer in progress.
|
||||
- `226` – Closing data connection.
|
||||
- `227` – Entering Passive Mode (`h1`, `h2`, `h3`, `h4`, `p1`, `p2`).
|
||||
- `230` – User logged in, proceed.
|
||||
- `250` – Requested file action okay, completed.
|
||||
- `257` – `PATHNAME` created.
|
||||
- `331` – User name okay, need password.
|
||||
- `332` – Need account for login.
|
||||
- `350` – Requested file action pending further information.
|
||||
- `421` – Service not available, closing control connection.
|
||||
- `425` – Can't open data connection.
|
||||
- `426` – Connection closed; transfer aborted.
|
||||
- `450` – Requested file action not taken.
|
||||
- `451` – Requested action aborted: local error in processing.
|
||||
- `452` – Requested action not taken.
|
||||
- `500` – Syntax error, command unrecognized.
|
||||
- `501` – Syntax error in parameters or arguments.
|
||||
- `502` – Command not implemented.
|
||||
- `503` – Bad sequence of commands.
|
||||
- `504` – Command not implemented for that parameter.
|
||||
- `530` – Not logged in.
|
||||
- `532` – Need account for storing files.
|
||||
- `550` – Requested action not taken.
|
||||
- `551` – Requested action aborted: page type unknown.
|
||||
- `552` – Requested file action aborted.
|
||||
- `553` – Requested action not taken.
|
||||
@@ -0,0 +1,86 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_cdup.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_cdup
|
||||
*
|
||||
* Description:
|
||||
* Make the parent of the current directory be the new current directory.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_cdup(SESSION handle)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
int ret;
|
||||
|
||||
ret = ftpc_cmd(session, "CDUP");
|
||||
session->currdir = ftpc_rpwd(handle);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_chdir.c
|
||||
*
|
||||
* Copyright (C) 2011, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_chdir
|
||||
*
|
||||
* Description:
|
||||
* Change the current working directory.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_chdir(SESSION handle, FAR const char *path)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
int ret;
|
||||
|
||||
ret = ftpc_cmd(session, "CWD %s", path);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Free any previous setting and set the new working directory */
|
||||
|
||||
if (session->currdir != NULL)
|
||||
{
|
||||
free(session->currdir);
|
||||
}
|
||||
|
||||
session->currdir = ftpc_rpwd(handle);
|
||||
return OK;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_chmod.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <debug.h>
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_chmod
|
||||
*
|
||||
* Description:
|
||||
* Change the protections on the remote file.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_chmod(SESSION handle, FAR const char *path, FAR const char *mode)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
|
||||
/* Does the server support the size CHMOD command? */
|
||||
|
||||
if (FTPC_HAS_CHMOD(session))
|
||||
{
|
||||
ftpc_cmd(session, "SITE CHMOD %s %s", path, mode);
|
||||
|
||||
/* Check for "502 Command not implemented" */
|
||||
|
||||
if (session->code == 502)
|
||||
{
|
||||
/* No.. the server does not support the SITE CHMOD command */
|
||||
|
||||
FTPC_CLR_CHMOD(session);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
nwarn("WARNING: Server does not support SITE CHMOD\n");
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_cmd.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_restore
|
||||
*
|
||||
* Description:
|
||||
* Restore the connection to the server and log in again.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FTP_AUTORECONNECT
|
||||
static int ftpc_restore(struct ftpc_session_s *session)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (session)
|
||||
{
|
||||
/* Set the initial directory to the last valid current directory */
|
||||
|
||||
free(session->initrdir);
|
||||
session->initrdir = ftpc_dequote(session->currdir);
|
||||
|
||||
/* Reconnect to the server */
|
||||
|
||||
ret = ftpc_reconnect(session);
|
||||
if (ret == 0)
|
||||
{
|
||||
/* Log into the server */
|
||||
|
||||
ret = ftpc_relogin(session);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Failed to reconnect to the server */
|
||||
|
||||
ftpc_reset(session);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_cmd
|
||||
*
|
||||
* Description:
|
||||
* Send the specified command to the server.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_cmd(struct ftpc_session_s *session, const char *cmd, ...)
|
||||
{
|
||||
va_list ap;
|
||||
#ifdef CONFIG_FTP_AUTORECONNECT
|
||||
bool reconnect = false;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
/* Verify that we are still connected to the server */
|
||||
|
||||
if (!ftpc_sockconnected(&session->cmd))
|
||||
{
|
||||
nwarn("WARNING: Cmd channel is not connected\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Loop, reconnecting as necessary until the command is sent */
|
||||
|
||||
#ifdef CONFIG_FTP_AUTORECONNECT
|
||||
for (; ; )
|
||||
#endif
|
||||
{
|
||||
/* Send the command */
|
||||
|
||||
va_start(ap, cmd);
|
||||
ret = ftpc_sockvprintf(&session->cmd, cmd, ap);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = ftpc_sockprintf(&session->cmd, "\r\n");
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = ftpc_sockflush(&session->cmd);
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
/* Check for an error in sending the data */
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Error sending cmd %s: %d\n", cmd, errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get the response to the command */
|
||||
|
||||
ret = fptc_getreply(session);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Error getting reply: %d\n", errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Check for "421 Service not available, closing control connection" */
|
||||
|
||||
if (session->code == 421)
|
||||
{
|
||||
/* Server is closing the control connection. */
|
||||
|
||||
nwarn("WARNING: Server closed control connection\n");
|
||||
|
||||
/* If we were previously logged in and this is not a QUIT command
|
||||
* then attempt to automatically reconnect to the server.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FTP_AUTORECONNECT
|
||||
if (ftpc_loggedin(session) && strcasecmp(cmd, "QUIT") != 0)
|
||||
{
|
||||
/* Don't try re-connecting more than once */
|
||||
|
||||
if (reconnect)
|
||||
{
|
||||
nwarn("WARNING: Reconnect failed\n");
|
||||
goto errout;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to restore the connection and, if successful,
|
||||
* continue the loop and try to send the command again.
|
||||
*/
|
||||
|
||||
ninfo("Reconnecting...\n");
|
||||
reconnect = true;
|
||||
ret = ftpc_restore();
|
||||
if (ret < 0)
|
||||
{
|
||||
nwarn("WARNING: Failed to restore the connection");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Don't try to connect, just return an error (retaining
|
||||
* the session response code (421)
|
||||
*/
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Error codes 5xx are Permanent Negative Completion. These can be
|
||||
* handled generically for all commands. An example is error code 530
|
||||
* which means 'not logged in'. The reply should include a string to
|
||||
* display to the user
|
||||
*/
|
||||
|
||||
else if (session->code > 500 && session->code < 600)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* The command was successfully sent */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
errout:
|
||||
session->code = -1;
|
||||
return ERROR;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_config.h
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_NETUTILS_FTPC_FTPC_CONFIG_H
|
||||
#define __APPS_NETUTILS_FTPC_FTPC_CONFIG_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* This is a mindless little wrapper around include/nuttx/config.h. Every
|
||||
* file in the ftpc directory includes this file at the very beginning of
|
||||
* of the file (instead of include/nuttx/config.h). The only purpose of
|
||||
* this file is to muck with some of the settings to support some debug
|
||||
* features.
|
||||
*
|
||||
* The FPT client uses common networking debug macros (ndbg and ninfo).
|
||||
* This can be overwhelming if there is a lot of networking debug output
|
||||
* as well. But by defining CONFIG_DEBUG_FTPC, this file will force
|
||||
* networking debug ON only for the files within this directory.
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_DEBUG_NET) && defined(CONFIG_DEBUG_FTPC)
|
||||
# undef CONFIG_DEBUG_NET
|
||||
# define CONFIG_DEBUG_NET 1
|
||||
# undef CONFIG_DEBUG_NET_ERROR
|
||||
# define CONFIG_DEBUG_NET_ERROR 1
|
||||
# undef CONFIG_DEBUG_NET_WARN
|
||||
# define CONFIG_DEBUG_NET_WARN 1
|
||||
# undef CONFIG_DEBUG_NET_INFO
|
||||
# define CONFIG_DEBUG_NET_INFO 1
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
#endif /* __APPS_NETUTILS_FTPC_FTPC_CONFIG_H */
|
||||
@@ -0,0 +1,276 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_connect.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_connect
|
||||
*
|
||||
* Description:
|
||||
* Create a session handle and connect to the server.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
SESSION ftpc_connect(FAR union ftpc_sockaddr_u *server)
|
||||
{
|
||||
FAR struct ftpc_session_s *session;
|
||||
int ret;
|
||||
|
||||
/* Allocate a session structure */
|
||||
|
||||
session = (struct ftpc_session_s *)zalloc(sizeof(struct ftpc_session_s));
|
||||
if (!session)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate a session\n");
|
||||
errno = ENOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Initialize the session structure with all non-zero and variable values */
|
||||
|
||||
memcpy(&session->server, server, sizeof(union ftpc_sockaddr_u));
|
||||
|
||||
session->flags &= ~FTPC_FLAGS_CLEAR;
|
||||
session->flags |= FTPC_FLAGS_SET;
|
||||
session->replytimeo = CONFIG_FTP_DEFTIMEO * CLOCKS_PER_SEC;
|
||||
session->conntimeo = CONFIG_FTP_DEFTIMEO * CLOCKS_PER_SEC;
|
||||
session->pid = getpid();
|
||||
|
||||
/* Use the default port if the user specified port number zero */
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (session->server.sa.sa_family == AF_INET6)
|
||||
{
|
||||
if (!session->server.in6.sin6_port)
|
||||
{
|
||||
session->server.in6.sin6_port = HTONS(CONFIG_FTP_DEFPORT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (session->server.sa.sa_family == AF_INET)
|
||||
{
|
||||
if (!session->server.in4.sin_port)
|
||||
{
|
||||
session->server.in4.sin_port = HTONS(CONFIG_FTP_DEFPORT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the local home directory, i.e., the value of the PWD environment
|
||||
* variable at the time of the connection. We keep a local copy so that
|
||||
* we can change the current working directory without effecting any other
|
||||
* logic that may be in same context.
|
||||
*/
|
||||
|
||||
session->homeldir = strdup(ftpc_lpwd());
|
||||
|
||||
/* And (Re-)connect to the server */
|
||||
|
||||
ret = ftpc_reconnect(session);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: ftpc_reconnect() failed: %d\n", errno);
|
||||
goto errout_with_alloc;
|
||||
}
|
||||
|
||||
return (SESSION)session;
|
||||
|
||||
errout_with_alloc:
|
||||
if (session->homeldir != NULL)
|
||||
{
|
||||
free(session->homeldir);
|
||||
}
|
||||
|
||||
free(session);
|
||||
errout:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_reconnect
|
||||
*
|
||||
* Description:
|
||||
* re-connect to the server either initially, or after loss of connection.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_reconnect(FAR struct ftpc_session_s *session)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_NET_ERROR
|
||||
char buffer[48];
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
/* Re-initialize the session structure */
|
||||
|
||||
session->replytimeo = CONFIG_FTP_DEFTIMEO * CLOCKS_PER_SEC;
|
||||
session->conntimeo = CONFIG_FTP_DEFTIMEO * CLOCKS_PER_SEC;
|
||||
session->xfrmode = FTPC_XFRMODE_UNKNOWN;
|
||||
|
||||
/* Set up a timer to prevent hangs */
|
||||
|
||||
ret = wd_start(&session->wdog, session->conntimeo,
|
||||
ftpc_timeout, (wdparm_t)session);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: wd_start() failed\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Initialize a socket */
|
||||
|
||||
ret = ftpc_sockinit(&session->cmd, session->server.sa.sa_family);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: ftpc_sockinit() failed: %d\n", errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Connect the socket to the server */
|
||||
|
||||
#ifdef CONFIG_DEBUG_NET_ERROR
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (session->server.sa.sa_family == AF_INET6)
|
||||
{
|
||||
if (inet_ntop(AF_INET6, &session->server.in6.sin6_addr, buffer, 48))
|
||||
{
|
||||
ninfo("Connecting to server address %s:%d\n", buffer,
|
||||
ntohs(session->server.in6.sin6_port));
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (session->server.sa.sa_family == AF_INET)
|
||||
{
|
||||
if (inet_ntop(AF_INET, &session->server.in4.sin_addr, buffer, 48))
|
||||
{
|
||||
ninfo("Connecting to server address %s:%d\n", buffer,
|
||||
ntohs(session->server.in4.sin_port));
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
#endif /* CONFIG_DEBUG_NET_ERROR */
|
||||
|
||||
ret = ftpc_sockconnect(&session->cmd,
|
||||
(FAR struct sockaddr *)&session->server);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: ftpc_sockconnect() failed: %d\n", errno);
|
||||
goto errout_with_socket;
|
||||
}
|
||||
|
||||
/* Read startup message from server */
|
||||
|
||||
fptc_getreply(session);
|
||||
|
||||
/* Check for "120 Service ready in nnn minutes" */
|
||||
|
||||
if (session->code == 120)
|
||||
{
|
||||
fptc_getreply(session);
|
||||
}
|
||||
|
||||
wd_cancel(&session->wdog);
|
||||
|
||||
if (!ftpc_sockconnected(&session->cmd))
|
||||
{
|
||||
ftpc_reset(session);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Check for "220 Service ready for new user" */
|
||||
|
||||
if (session->code == 220)
|
||||
{
|
||||
FTPC_SET_CONNECTED(session);
|
||||
}
|
||||
|
||||
if (!FTPC_IS_CONNECTED(session))
|
||||
{
|
||||
goto errout_with_socket;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_NET_ERROR
|
||||
ninfo("Connected\n");
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (session->server.sa.sa_family == AF_INET6)
|
||||
{
|
||||
if (inet_ntop(AF_INET6, &session->server.in6.sin6_addr, buffer, 48))
|
||||
{
|
||||
ninfo(" Remote address: %s:%d\n", buffer,
|
||||
ntohs(session->server.in6.sin6_port));
|
||||
}
|
||||
|
||||
if (inet_ntop(AF_INET6, &session->cmd.laddr.in6.sin6_addr, buffer, 48))
|
||||
{
|
||||
ninfo(" Local address: %s:%d\n", buffer,
|
||||
ntohs(session->cmd.laddr.in6.sin6_port));
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (session->server.sa.sa_family == AF_INET)
|
||||
{
|
||||
if (inet_ntop(AF_INET, &session->server.in4.sin_addr, buffer, 48))
|
||||
{
|
||||
ninfo(" Remote address: %s:%d\n", buffer,
|
||||
ntohs(session->server.in4.sin_port));
|
||||
}
|
||||
|
||||
if (inet_ntop(AF_INET, &session->cmd.laddr.in4.sin_addr, buffer, 48))
|
||||
{
|
||||
ninfo(" Local address: %s:%d\n", buffer,
|
||||
ntohs(session->cmd.laddr.in4.sin_port));
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
#endif /* CONFIG_DEBUG_NET_ERROR */
|
||||
|
||||
return OK;
|
||||
|
||||
errout_with_socket:
|
||||
ftpc_sockclose(&session->cmd);
|
||||
errout:
|
||||
return ERROR;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_disconnect.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_disconnect
|
||||
*
|
||||
* Description:
|
||||
* Disconnect from the server and destroy the session handle..
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ftpc_disconnect(SESSION handle)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
if (session)
|
||||
{
|
||||
/* Release sockets */
|
||||
|
||||
ftpc_sockclose(&session->data);
|
||||
ftpc_sockclose(&session->dacceptor);
|
||||
ftpc_sockclose(&session->cmd);
|
||||
|
||||
/* Free strings */
|
||||
|
||||
free(session->uname);
|
||||
free(session->pwd);
|
||||
free(session->initrdir);
|
||||
free(session->homerdir);
|
||||
free(session->homeldir);
|
||||
free(session->currdir);
|
||||
|
||||
/* Then destroy the session */
|
||||
|
||||
free(session);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_filesize.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_filesize
|
||||
*
|
||||
* Description:
|
||||
* Return the size of the given file on the remote server.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
off_t ftpc_filesize(SESSION handle, FAR const char *path)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
unsigned long ret;
|
||||
uint8_t mode = FTPC_XFRMODE_ASCII;
|
||||
|
||||
/* Check if the host supports the SIZE command */
|
||||
|
||||
if (!FTPC_HAS_SIZE(session))
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FTP_SIZE_CMD_MODE_BINARY
|
||||
mode = FTPC_XFRMODE_BINARY;
|
||||
#endif
|
||||
|
||||
if (ftpc_xfrmode(session, mode) != 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = ftpc_cmd(session, "SIZE %s", path);
|
||||
|
||||
/* Check for "502 Command not implemented" */
|
||||
|
||||
if (session->code == 502)
|
||||
{
|
||||
/* No.. the host does not support the SIZE command */
|
||||
|
||||
FTPC_CLR_SIZE(session);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
sscanf(session->reply, "%*s %lu", &ret);
|
||||
return (off_t)ret;
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_filetime.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_filetime
|
||||
*
|
||||
* Description:
|
||||
* Return the timestamp on the remote file. Returned time is UTC
|
||||
* (Universal Coordinated Time).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
time_t ftpc_filetime(SESSION handle, FAR const char *filename)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
struct tm timestamp;
|
||||
int ret;
|
||||
|
||||
/* Make sure that the server is still connected */
|
||||
|
||||
if (!ftpc_connected(session))
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Does the server support the MDTM command? */
|
||||
|
||||
if (!FTPC_HAS_MDTM(session))
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Get the file time in UTC */
|
||||
|
||||
memset(×tamp, 0, sizeof(timestamp));
|
||||
ret = ftpc_cmd(session, "MDTM %s", filename);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Check for "202 Command not implemented, superfluous at this site" */
|
||||
|
||||
if (session->code == 202)
|
||||
{
|
||||
FTPC_CLR_MDTM(session);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Check for "213 File status" */
|
||||
|
||||
if (session->code != 213)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Time is Universal Coordinated Time */
|
||||
|
||||
sscanf(session->reply, "%*s %04d%02d%02d%02d%02d%02d",
|
||||
×tamp.tm_year, ×tamp.tm_mon, ×tamp.tm_mday,
|
||||
×tamp.tm_hour, ×tamp.tm_min, ×tamp.tm_sec);
|
||||
timestamp.tm_year -= 1900;
|
||||
timestamp.tm_mon--;
|
||||
return mktime(×tamp);
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_getfile.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_recvinit
|
||||
*
|
||||
* Description:
|
||||
* Initialize to receive a file
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ftpc_recvinit(struct ftpc_session_s *session,
|
||||
FAR const char *path,
|
||||
uint8_t xfrmode, off_t offset)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Reset transfer related variables */
|
||||
|
||||
ftpc_xfrreset(session);
|
||||
|
||||
ret = ftpc_xfrinit(session);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Configure the transfer: Initial file offset and transfer mode */
|
||||
|
||||
session->offset = 0;
|
||||
ftpc_xfrmode(session, xfrmode);
|
||||
|
||||
/* Handle the resume offset (caller is responsible for fseeking in the
|
||||
* file)
|
||||
*/
|
||||
|
||||
if (offset > 0)
|
||||
{
|
||||
/* Send the REST command. This command sets the offset where the
|
||||
* transfer should start. This must come after PORT or PASV commands.
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "REST %ld", offset);
|
||||
if (ret < 0)
|
||||
{
|
||||
nwarn("WARNING: REST command failed: %d\n", errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
session->size = offset;
|
||||
}
|
||||
|
||||
/* Send the RETR (Retrieve a remote file) command. Normally the server
|
||||
* responds with a mark using code 150:
|
||||
*
|
||||
* - "150 File status okay; about to open data connection"
|
||||
*
|
||||
* It then stops accepting new connections, attempts to send the contents
|
||||
* of the file over the data connection, and closes the data connection.
|
||||
* Finally it either accepts the RETR request with:
|
||||
*
|
||||
* - "226 Closing data connection" if the entire file was successfully
|
||||
* written to the server's TCP buffers
|
||||
*
|
||||
* Or rejects the RETR request with:
|
||||
*
|
||||
* - "425 Can't open data connection" if no TCP connection was established
|
||||
* - "426 Connection closed; transfer aborted" if the TCP connection was
|
||||
* established but then broken by the client or by network failure
|
||||
* - "451 Requested action aborted: local error in processing" or
|
||||
* "551 Requested action aborted: page type unknown" if the server had
|
||||
* trouble reading the file from disk.
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "RETR %s", path);
|
||||
if (ret < 0)
|
||||
{
|
||||
nwarn("WARNING: RETR command failed: %d\n", errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* In active mode, we need to accept a connection on the data socket
|
||||
* (in passive mode, we have already connected the data channel to
|
||||
* the FTP server).
|
||||
*/
|
||||
|
||||
if (!FTPC_IS_PASSIVE(session))
|
||||
{
|
||||
ret = ftpc_sockaccept(&session->dacceptor, &session->data);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: Data connection not accepted\n");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_recvbinary
|
||||
*
|
||||
* Description:
|
||||
* Receive a binary file.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ftpc_recvbinary(FAR struct ftpc_session_s *session,
|
||||
FAR FILE *rinstream, FAR FILE *loutstream)
|
||||
{
|
||||
ssize_t nread;
|
||||
ssize_t nwritten;
|
||||
|
||||
/* Loop until the entire file is received */
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* Read the data from the socket */
|
||||
|
||||
nread = fread(session->buffer, sizeof(char), CONFIG_FTP_BUFSIZE,
|
||||
rinstream);
|
||||
if (nread <= 0)
|
||||
{
|
||||
/* nread < 0 is an error */
|
||||
|
||||
if (nread < 0)
|
||||
{
|
||||
/* errno should already be set by fread */
|
||||
|
||||
ftpc_xfrabort(session, rinstream);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* nread == 0 means end of file. Return success */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Write the data to the file */
|
||||
|
||||
nwritten = fwrite(session->buffer, sizeof(char), nread, loutstream);
|
||||
if (nwritten != nread)
|
||||
{
|
||||
ftpc_xfrabort(session, loutstream);
|
||||
|
||||
/* If nwritten < 0 errno should already be set by fwrite.
|
||||
* What would a short write mean?
|
||||
*/
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Increment the size of the file written */
|
||||
|
||||
session->size += nwritten;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_getfile
|
||||
*
|
||||
* Description:
|
||||
* Get a file from the remote host.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
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)
|
||||
{
|
||||
nwarn("WARNING: ftpc_abslpath(%s) failed: %d\n", lname, 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))
|
||||
{
|
||||
nwarn("WARNING: '%s' is a directory\n", abslpath);
|
||||
goto errout_with_abspath;
|
||||
}
|
||||
}
|
||||
|
||||
/* Is it write-able? */
|
||||
|
||||
#ifdef S_IWRITE
|
||||
if (!(statbuf.st_mode & S_IWRITE))
|
||||
{
|
||||
nwarn("WARNING: '%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)
|
||||
{
|
||||
nerr("ERROR: ftpc_recvinit failed\n");
|
||||
goto errout_with_abspath;
|
||||
}
|
||||
|
||||
loutstream = fopen(abslpath,
|
||||
(offset > 0 || (how == FTPC_GET_APPEND)) ? "a" : "w");
|
||||
if (!loutstream)
|
||||
{
|
||||
nerr("ERROR: 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)
|
||||
{
|
||||
nerr("ERROR: 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;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_recvtext
|
||||
*
|
||||
* Description:
|
||||
* Receive a text file.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_recvtext(FAR struct ftpc_session_s *session,
|
||||
FAR FILE *rinstream, FAR FILE *loutstream)
|
||||
{
|
||||
int ch;
|
||||
|
||||
/* Read the next character from the incoming data stream */
|
||||
|
||||
while ((ch = fgetc(rinstream)) != EOF)
|
||||
{
|
||||
/* Is it a carriage return? Compress \r\n to \n */
|
||||
|
||||
if (ch == '\r')
|
||||
{
|
||||
/* Get the next character */
|
||||
|
||||
ch = fgetc(rinstream);
|
||||
if (ch == EOF)
|
||||
{
|
||||
/* Ooops... */
|
||||
|
||||
ftpc_xfrabort(session, rinstream);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* If its not a newline, then keep the carriage return */
|
||||
|
||||
if (ch != '\n')
|
||||
{
|
||||
ungetc(ch, rinstream);
|
||||
ch = '\r';
|
||||
}
|
||||
}
|
||||
|
||||
/* Then write the character to the output file */
|
||||
|
||||
if (fputc(ch, loutstream) == EOF)
|
||||
{
|
||||
ftpc_xfrabort(session, loutstream);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Increase the actual size of the file by one */
|
||||
|
||||
session->size++;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_getreply.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_gets
|
||||
****************************************************************************/
|
||||
|
||||
static int ftpc_gets(struct ftpc_session_s *session)
|
||||
{
|
||||
int ch;
|
||||
int ndx = 0;
|
||||
|
||||
/* Start with an empty response string */
|
||||
|
||||
session->reply[0] = '\0';
|
||||
|
||||
/* Verify that the command channel is still connected */
|
||||
|
||||
if (!ftpc_sockconnected(&session->cmd))
|
||||
{
|
||||
nwarn("WARNING: Cmd channel disconnected\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Loop until the full line is obtained */
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* Get the next character from incoming command stream */
|
||||
|
||||
ch = ftpc_sockgetc(&session->cmd);
|
||||
|
||||
/* Check if the command stream was closed */
|
||||
|
||||
if (ch == EOF)
|
||||
{
|
||||
nwarn("WARNING: EOF: Server closed command stream\n");
|
||||
ftpc_reset(session);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Handle embedded Telnet stuff */
|
||||
|
||||
else if (ch == TELNET_IAC)
|
||||
{
|
||||
/* Handle TELNET commands */
|
||||
|
||||
switch (ch = ftpc_sockgetc(&session->cmd))
|
||||
{
|
||||
case TELNET_WILL:
|
||||
case TELNET_WONT:
|
||||
ch = ftpc_sockgetc(&session->cmd);
|
||||
ftpc_sockprintf(&session->cmd, "%c%c%c",
|
||||
TELNET_IAC, TELNET_DONT, ch);
|
||||
ftpc_sockflush(&session->cmd);
|
||||
break;
|
||||
|
||||
case TELNET_DO:
|
||||
case TELNET_DONT:
|
||||
ch = ftpc_sockgetc(&session->cmd);
|
||||
ftpc_sockprintf(&session->cmd, "%c%c%c",
|
||||
TELNET_IAC, TELNET_WONT, ch);
|
||||
ftpc_sockflush(&session->cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Deal with carriage returns */
|
||||
|
||||
else if (ch == ISO_CR)
|
||||
{
|
||||
/* What follows the carriage return? */
|
||||
|
||||
ch = ftpc_sockgetc(&session->cmd);
|
||||
if (ch == '\0')
|
||||
{
|
||||
/* If it is followed by a NUL then keep it */
|
||||
|
||||
ch = ISO_CR;
|
||||
}
|
||||
|
||||
/* If it is followed by a newline then break out of the loop. */
|
||||
|
||||
else if (ch == ISO_NL)
|
||||
{
|
||||
/* Newline terminates the reply */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we did not lose the connection, then push the character
|
||||
* following the carriage back on the "stack" and continue to
|
||||
* examine it from scratch (if could be part of the Telnet
|
||||
* protocol).
|
||||
*/
|
||||
|
||||
else if (ch != EOF)
|
||||
{
|
||||
ungetc(ch, session->cmd.instream);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
else if (ch == ISO_NL)
|
||||
{
|
||||
/* The ISO newline character terminates the string. Just break
|
||||
* out of the loop.
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Put the character into the response buffer. Is there space for
|
||||
* another character in the reply buffer?
|
||||
*/
|
||||
|
||||
if (ndx < CONFIG_FTP_MAXREPLY)
|
||||
{
|
||||
/* Yes.. put the character in the reply buffer */
|
||||
|
||||
session->reply[ndx++] = (char)ch;
|
||||
}
|
||||
else
|
||||
{
|
||||
nwarn("WARNING: Reply truncated\n");
|
||||
}
|
||||
}
|
||||
|
||||
session->reply[ndx] = '\0';
|
||||
session->code = atoi(session->reply);
|
||||
return session->code;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_getreply
|
||||
****************************************************************************/
|
||||
|
||||
int fptc_getreply(struct ftpc_session_s *session)
|
||||
{
|
||||
char tmp[5] = "xxx ";
|
||||
int ret;
|
||||
|
||||
/* Set up a timeout */
|
||||
|
||||
if (session->replytimeo)
|
||||
{
|
||||
ret = wd_start(&session->wdog, session->replytimeo,
|
||||
ftpc_timeout, (wdparm_t)session);
|
||||
}
|
||||
|
||||
/* Get the next line from the server */
|
||||
|
||||
ret = ftpc_gets(session);
|
||||
|
||||
/* Do we still have a connection? */
|
||||
|
||||
if (!ftpc_sockconnected(&session->cmd))
|
||||
{
|
||||
/* No.. cancel the timer and return an error */
|
||||
|
||||
wd_cancel(&session->wdog);
|
||||
ninfo("Lost connection\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Did an error occur? */
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
/* No.. cancel the timer and return an error */
|
||||
|
||||
wd_cancel(&session->wdog);
|
||||
ninfo("ftpc_gets failed\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ninfo("Reply: %s\n", session->reply);
|
||||
|
||||
if (session->reply[3] == '-')
|
||||
{
|
||||
/* Multi-line response */
|
||||
|
||||
strncpy(tmp, session->reply, 3);
|
||||
do
|
||||
{
|
||||
if (ftpc_gets(session) == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ninfo("Reply: %s\n", session->reply);
|
||||
}
|
||||
while (strncmp(tmp, session->reply, 4) != 0);
|
||||
}
|
||||
|
||||
wd_cancel(&session->wdog);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_help.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_help
|
||||
*
|
||||
* Description:
|
||||
* Request a list of available help commands. This implementation is
|
||||
* fragementary and no ready for any real use at this time.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_help(SESSION handle, FAR const char *arg)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
int ret;
|
||||
|
||||
/* Send the HELP command with or without an argument */
|
||||
|
||||
if (arg)
|
||||
{
|
||||
ret = ftpc_cmd(session, "HELP %s", arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ftpc_cmd(session, "HELP");
|
||||
}
|
||||
|
||||
/* Logic is missing here to return the help string to the caller. The caller
|
||||
* needs to call ftpc_getreply.
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_idle.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <debug.h>
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_idle
|
||||
*
|
||||
* Description:
|
||||
* This command will change the FTP server's idle time limit with the site
|
||||
* idle ftp command. This is useful if the default time limit is too short
|
||||
* for the transmission of files).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_idle(SESSION handle, unsigned int idletime)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
int ret = OK;
|
||||
|
||||
/* Check if the server supports the SITE IDLE command */
|
||||
|
||||
if (!FTPC_HAS_IDLE(session))
|
||||
{
|
||||
nwarn("WARNING: Server does not support SITE IDLE\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Did the caller provide an IDLE time? Or is this just a query for the
|
||||
* current IDLE time setting?
|
||||
*/
|
||||
|
||||
if (idletime)
|
||||
{
|
||||
ret = ftpc_cmd(session, "SITE IDLE %u", idletime);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ftpc_cmd(session, "SITE IDLE");
|
||||
}
|
||||
|
||||
/* Check for "502 Command not implemented" or 500 "Unknown SITE command" */
|
||||
|
||||
if (session->code == 500 || session->code == 502)
|
||||
{
|
||||
/* Server does not support SITE IDLE */
|
||||
|
||||
nwarn("WARNING: Server does not support SITE IDLE\n");
|
||||
FTPC_CLR_IDLE(session);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_internal.h
|
||||
*
|
||||
* Copyright (C) 2011, 2014 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_NETUTILS_FTPC_FTPC_INTERNAL_H
|
||||
#define __APPS_NETUTILS_FTPC_FTPC_INTERNAL_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <nuttx/wdog.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* MISC definitions *********************************************************/
|
||||
|
||||
#define ISO_NL 0x0a
|
||||
#define ISO_CR 0x0d
|
||||
|
||||
/* Telnet-related definitions */
|
||||
|
||||
#define TELNET_DM 242
|
||||
#define TELNET_IP 244
|
||||
#define TELNET_IAC 255
|
||||
#define TELNET_WILL 251
|
||||
#define TELNET_WONT 252
|
||||
#define TELNET_DO 253
|
||||
#define TELNET_DONT 254
|
||||
|
||||
/* Session flag bits ********************************************************/
|
||||
|
||||
#define FTPC_FLAG_PASSIVE (1 << 0) /* Passive mode requested */
|
||||
#define FTPC_SESSION_FLAGS (0x0001) /* Persist throughout the session */
|
||||
|
||||
#define FTPC_FLAG_CONNECTED (1 << 1) /* Connected to host */
|
||||
#define FTPC_FLAG_LOGGEDIN (1 << 2) /* Logged in to host */
|
||||
#define FTPC_STATE_FLAGS (0x0006) /* State of connection */
|
||||
|
||||
#define FTPC_FLAG_MDTM (1 << 3) /* Host supports MDTM command */
|
||||
#define FTPC_FLAG_SIZE (1 << 4) /* Host supports SIZE command */
|
||||
#define FTPC_FLAG_PASV (1 << 5) /* Host supports PASV command */
|
||||
#define FTPC_FLAG_STOU (1 << 6) /* Host supports STOU command */
|
||||
#define FTPC_FLAG_CHMOD (1 << 7) /* Host supports SITE CHMOD command */
|
||||
#define FTPC_FLAG_IDLE (1 << 8) /* Host supports SITE IDLE command */
|
||||
#define FTPC_HOSTCAP_FLAGS (0x01f8) /* Host capabilities */
|
||||
|
||||
#define FTPC_FLAG_INTERRUPT (1 << 9) /* Transfer interrupted */
|
||||
#define FTPC_FLAG_PUT (1 << 10) /* Transfer is a PUT operation (upload) */
|
||||
#define FTPC_XFER_FLAGS (0x0600) /* Transfer related */
|
||||
|
||||
/* These are the bits to be set/cleared when the flags are reset */
|
||||
|
||||
#define FTPC_FLAGS_CLEAR (FTPC_STATE_FLAGS | FTPC_XFER_FLAGS)
|
||||
#define FTPC_FLAGS_SET FTPC_HOSTCAP_FLAGS
|
||||
|
||||
/* Macros to set bits */
|
||||
|
||||
#define FTPC_SET_CONNECTED(s) do { (s)->flags |= FTPC_FLAG_CONNECTED; } while (0)
|
||||
#define FTPC_SET_LOGGEDIN(s) do { (s)->flags |= FTPC_FLAG_LOGGEDIN; } while (0)
|
||||
#define FTPC_SET_MDTM(s) do { (s)->flags |= FTPC_FLAG_MDTM; } while (0)
|
||||
#define FTPC_SET_SIZE(s) do { (s)->flags |= FTPC_FLAG_SIZE; } while (0)
|
||||
#define FTPC_SET_PASV(s) do { (s)->flags |= FTPC_FLAG_PASV; } while (0)
|
||||
#define FTPC_SET_STOU(s) do { (s)->flags |= FTPC_FLAG_STOU; } while (0)
|
||||
#define FTPC_SET_CHMOD(s) do { (s)->flags |= FTPC_FLAG_CHMOD; } while (0)
|
||||
#define FTPC_SET_IDLE(s) do { (s)->flags |= FTPC_FLAG_IDLE; } while (0)
|
||||
#define FTPC_SET_INTERRUPT(s) do { (s)->flags |= FTPC_FLAG_INTERRUPT; } while (0)
|
||||
#define FTPC_SET_PUT(s) do { (s)->flags |= FTPC_FLAG_PUT; } while (0)
|
||||
#define FTPC_SET_PASSIVE(s) do { (s)->flags |= FTPC_FLAG_PASSIVE; } while (0)
|
||||
|
||||
/* Macros to clear bits */
|
||||
|
||||
#define FTPC_CLR_CONNECTED(s) do { (s)->flags &= ~FTPC_FLAG_CONNECTED; } while (0)
|
||||
#define FTPC_CLR_LOGGEDIN(s) do { (s)->flags &= ~FTPC_FLAG_LOGGEDIN; } while (0)
|
||||
#define FTPC_CLR_MDTM(s) do { (s)->flags &= ~FTPC_FLAG_MDTM; } while (0)
|
||||
#define FTPC_CLR_SIZE(s) do { (s)->flags &= ~FTPC_FLAG_SIZE; } while (0)
|
||||
#define FTPC_CLR_PASV(s) do { (s)->flags &= ~FTPC_FLAG_PASV; } while (0)
|
||||
#define FTPC_CLR_STOU(s) do { (s)->flags &= ~FTPC_FLAG_STOU; } while (0)
|
||||
#define FTPC_CLR_CHMOD(s) do { (s)->flags &= ~FTPC_FLAG_CHMOD; } while (0)
|
||||
#define FTPC_CLR_IDLE(s) do { (s)->flags &= ~FTPC_FLAG_IDLE; } while (0)
|
||||
#define FTPC_CLR_INTERRUPT(s) do { (s)->flags &= ~FTPC_FLAG_INTERRUPT; } while (0)
|
||||
#define FTPC_CLR_PUT(s) do { (s)->flags &= ~FTPC_FLAG_PUT; } while (0)
|
||||
#define FTPC_CLR_PASSIVE(s) do { (s)->flags &= ~FTPC_FLAG_PASSIVE; } while (0)
|
||||
|
||||
/* Macros to test bits */
|
||||
|
||||
#define FTPC_IS_CONNECTED(s) (((s)->flags & FTPC_FLAG_CONNECTED) != 0)
|
||||
#define FTPC_IS_LOGGEDIN(s) (((s)->flags & FTPC_FLAG_LOGGEDIN) != 0)
|
||||
#define FTPC_HAS_MDTM(s) (((s)->flags & FTPC_FLAG_MDTM) != 0)
|
||||
#define FTPC_HAS_SIZE(s) (((s)->flags & FTPC_FLAG_SIZE) != 0)
|
||||
#define FTPC_HAS_PASV(s) (((s)->flags & FTPC_FLAG_PASV) != 0)
|
||||
#define FTPC_HAS_STOU(s) (((s)->flags & FTPC_FLAG_STOU) != 0)
|
||||
#define FTPC_HAS_CHMOD(s) (((s)->flags & FTPC_FLAG_CHMOD) != 0)
|
||||
#define FTPC_HAS_IDLE(s) (((s)->flags & FTPC_FLAG_IDLE) != 0)
|
||||
#define FTPC_INTERRUPTED(s) (((s)->flags & FTPC_FLAG_INTERRUPT) != 0)
|
||||
#define FTPC_IS_PUT(s) (((s)->flags & FTPC_FLAG_PUT) != 0)
|
||||
#define FTPC_IS_PASSIVE(s) (((s)->flags & FTPC_FLAG_PASSIVE) != 0)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure represents the state of one socket connection */
|
||||
|
||||
struct ftpc_socket_s
|
||||
{
|
||||
int sd; /* Socket descriptor */
|
||||
FILE *instream; /* Incoming stream */
|
||||
FILE *outstream; /* Outgoing stream */
|
||||
union ftpc_sockaddr_u laddr; /* Local Address */
|
||||
bool connected; /* True: socket is connected */
|
||||
};
|
||||
|
||||
/* This structure represents the state of an FTP connection */
|
||||
|
||||
struct ftpc_session_s
|
||||
{
|
||||
union ftpc_sockaddr_u server; /* Server/proxy socket address */
|
||||
struct ftpc_socket_s cmd; /* FTP command channel */
|
||||
struct ftpc_socket_s data; /* FTP data channel */
|
||||
struct ftpc_socket_s dacceptor; /* FTP data listener (accepts data connection in active mode) */
|
||||
struct wdog_s wdog; /* Timer */
|
||||
FAR char *uname; /* Login uname */
|
||||
FAR char *pwd; /* Login pwd */
|
||||
FAR char *initrdir; /* Initial remote directory */
|
||||
FAR char *homerdir; /* Remote home directory (currdir on startup) */
|
||||
FAR char *currdir; /* Remote current directory */
|
||||
FAR char *homeldir; /* Local home directory (PWD on startup) */
|
||||
pid_t pid; /* Task ID of FTP client */
|
||||
uint8_t xfrmode; /* Previous data transfer type (See FTPC_XFRMODE_* defines) */
|
||||
uint16_t flags; /* Connection flags (see FTPC_FLAGS_* defines) */
|
||||
uint16_t code; /* Last 3-digit reply code */
|
||||
uint32_t replytimeo; /* Server reply timeout (ticks) */
|
||||
uint32_t conntimeo; /* Connection timeout (ticks) */
|
||||
off_t offset; /* Transfer file offset */
|
||||
off_t size; /* Number of bytes transferred */
|
||||
|
||||
char reply[CONFIG_FTP_MAXREPLY + 1]; /* Last reply string from server */
|
||||
char buffer[CONFIG_FTP_BUFSIZE]; /* Used to buffer file data during transfers */
|
||||
};
|
||||
|
||||
/* There is not yet any want to change the local working directly (an lcd
|
||||
* command), but the following definition is provided to reserve the name
|
||||
* for the storage location for the local current working directory.
|
||||
*/
|
||||
|
||||
#define curldir homeldir
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions/Function-like Macros
|
||||
****************************************************************************/
|
||||
|
||||
#define ftpc_sockconnected(s) \
|
||||
((s) && (s)->connected)
|
||||
#define ftpc_connected(s) \
|
||||
(FTPC_IS_CONNECTED(session) && ftpc_sockconnected(&session->cmd))
|
||||
#define ftpc_loggedin(s) \
|
||||
(ftpc_connected(s) && FTPC_IS_LOGGEDIN(s))
|
||||
|
||||
#define ftpc_sockgetc(s) \
|
||||
fgetc((s)->instream)
|
||||
#define ftpc_sockflush(s) \
|
||||
fflush((s)->outstream)
|
||||
#define ftpc_sockvprintf(s,f,ap) \
|
||||
vfprintf((s)->outstream,f,ap)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Low-level string management */
|
||||
|
||||
EXTERN void ftpc_stripcrlf(FAR char *str);
|
||||
EXTERN void ftpc_stripslash(FAR char *str);
|
||||
EXTERN FAR char *ftpc_dequote(FAR const char *hostname);
|
||||
|
||||
/* Connection helpers */
|
||||
|
||||
EXTERN int ftpc_reconnect(FAR struct ftpc_session_s *session);
|
||||
EXTERN int ftpc_relogin(FAR struct ftpc_session_s *session);
|
||||
|
||||
/* FTP helpers */
|
||||
|
||||
EXTERN void ftpc_reset(struct ftpc_session_s *session);
|
||||
EXTERN int ftpc_cmd(struct ftpc_session_s *session, const char *cmd, ...);
|
||||
EXTERN int fptc_getreply(struct ftpc_session_s *session);
|
||||
EXTERN FAR const char *ftpc_lpwd(void);
|
||||
EXTERN int ftpc_xfrmode(struct ftpc_session_s *session, uint8_t xfrmode);
|
||||
EXTERN FAR char *ftpc_absrpath(FAR struct ftpc_session_s *session,
|
||||
FAR const char *relpath);
|
||||
EXTERN FAR char *ftpc_abslpath(FAR struct ftpc_session_s *session,
|
||||
FAR const char *relpath);
|
||||
|
||||
/* Socket helpers */
|
||||
|
||||
EXTERN int ftpc_sockinit(FAR struct ftpc_socket_s *sock, sa_family_t family);
|
||||
EXTERN void ftpc_sockclose(FAR struct ftpc_socket_s *sock);
|
||||
EXTERN int ftpc_sockconnect(FAR struct ftpc_socket_s *sock,
|
||||
FAR struct sockaddr *addr);
|
||||
EXTERN int ftpc_sockgetsockname(FAR struct ftpc_socket_s *sock,
|
||||
FAR union ftpc_sockaddr_u *addr);
|
||||
EXTERN int ftpc_sockaccept(FAR struct ftpc_socket_s *acceptor,
|
||||
FAR struct ftpc_socket_s *sock);
|
||||
EXTERN int ftpc_socklisten(FAR struct ftpc_socket_s *sock);
|
||||
EXTERN void ftpc_sockcopy(FAR struct ftpc_socket_s *dest,
|
||||
FAR const struct ftpc_socket_s *src);
|
||||
|
||||
/* Socket I/O helpers */
|
||||
|
||||
EXTERN int ftpc_sockprintf(FAR struct ftpc_socket_s *sock,
|
||||
const char *fmt, ...);
|
||||
EXTERN void ftpc_timeout(wdparm_t arg);
|
||||
|
||||
/* Transfer helpers */
|
||||
|
||||
EXTERN int ftpc_xfrinit(FAR struct ftpc_session_s *session);
|
||||
EXTERN int ftpc_recvtext(FAR struct ftpc_session_s *session,
|
||||
FAR FILE *rinstream, FAR FILE *loutstream);
|
||||
EXTERN int ftpc_waitdata(FAR struct ftpc_session_s *session,
|
||||
FAR FILE *stream, bool rdwait);
|
||||
|
||||
EXTERN void ftpc_xfrreset(struct ftpc_session_s *session);
|
||||
EXTERN int ftpc_xfrabort(FAR struct ftpc_session_s *session,
|
||||
FAR FILE *stream);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __APPS_NETUTILS_FTPC_FTPC_INTERNAL_H */
|
||||
@@ -0,0 +1,420 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_listdir.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef void (*callback_t)(FAR const char *name, FAR void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_dircount
|
||||
*
|
||||
* Description:
|
||||
* This callback simply counts the number of names in the directory.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void ftpc_dircount(FAR const char *name, FAR void *arg)
|
||||
{
|
||||
FAR unsigned int *dircount = (FAR unsigned int *)arg;
|
||||
(*dircount)++;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_addname
|
||||
*
|
||||
* Description:
|
||||
* This callback adds a name to the directory listing.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void ftpc_addname(FAR const char *name, FAR void *arg)
|
||||
{
|
||||
FAR struct ftpc_dirlist_s *dirlist = (FAR struct ftpc_dirlist_s *)arg;
|
||||
unsigned int nnames = dirlist->nnames;
|
||||
dirlist->name[nnames] = strdup(name);
|
||||
dirlist->nnames = nnames + 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_nlstparse
|
||||
*
|
||||
* Description:
|
||||
* Parse the NLST directory response. The NLST response consists of a
|
||||
* sequence of pathnames. Each pathname is terminated by \r\n.
|
||||
*
|
||||
* If a pathname starts with a slash, it represents the pathname. If a
|
||||
* pathname does not start with a slash, it represents the pathname
|
||||
* obtained by concatenating the pathname of the directory and the
|
||||
* pathname.
|
||||
*
|
||||
* IF NLST of directory /pub produces foo\r\nbar\r\n, it refers to the
|
||||
* pathnames /pub/foo and /pub/bar.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void ftpc_nlstparse(FAR FILE *instream, callback_t callback,
|
||||
FAR void *arg)
|
||||
{
|
||||
char buffer[CONFIG_FTP_MAXPATH + 1];
|
||||
|
||||
/* Read every filename from the temporary file */
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* Read the next line from the file */
|
||||
|
||||
if (!fgets(buffer, CONFIG_FTP_MAXPATH, instream))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Remove any trailing CR-LF from the line */
|
||||
|
||||
ftpc_stripcrlf(buffer);
|
||||
|
||||
/* Check for empty file names */
|
||||
|
||||
if (buffer[0] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ninfo("File: %s\n", buffer);
|
||||
|
||||
/* Perform the callback operation */
|
||||
|
||||
callback(buffer, arg);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_recvdir
|
||||
*
|
||||
* Description:
|
||||
* Get the directory listing.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ftpc_recvdir(FAR struct ftpc_session_s *session,
|
||||
FAR FILE *outstream)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Verify that we are still connected to the server */
|
||||
|
||||
if (!ftpc_connected(session))
|
||||
{
|
||||
nerr("ERROR: Not connected to server\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Setup for the transfer */
|
||||
|
||||
ftpc_xfrreset(session);
|
||||
ret = ftpc_xfrinit(session);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Send the "NLST" command. Normally the server responds with a mark
|
||||
* using code 150:
|
||||
*
|
||||
* - "150 File status okay; about to open data connection"
|
||||
*
|
||||
* It then stops accepting new connections, attempts to
|
||||
* send the contents of the directory over the data connection, and
|
||||
* closes the data connection.
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "NLST");
|
||||
if (ret != OK)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* In active mode, we need to accept a connection on the data socket
|
||||
* (in passive mode, we have already connected the data channel to
|
||||
* the FTP server).
|
||||
*/
|
||||
|
||||
if (!FTPC_IS_PASSIVE(session))
|
||||
{
|
||||
ret = ftpc_sockaccept(&session->dacceptor, &session->data);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: ftpc_sockaccept() failed: %d\n", errno);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Receive the NLST directory list */
|
||||
|
||||
ret = ftpc_recvtext(session, session->data.instream, outstream);
|
||||
ftpc_sockclose(&session->data);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Get the server reply. After closing the data connection, the should
|
||||
* accept the request with:
|
||||
*
|
||||
* - "226 Closing data connection" if the entire directory was
|
||||
* successfully transmitted;
|
||||
*
|
||||
* Or reject it with:
|
||||
*
|
||||
* - "425 Can't open data connection" if no TCP connection was established
|
||||
* - "426 - Connection closed; transfer aborted" if the TCP connection was
|
||||
* established but then broken by the client or by network failure
|
||||
* - "451 - Requested action aborted: local error in processing" if the
|
||||
* server had trouble reading the directory from disk.
|
||||
*
|
||||
* The server may reject the LIST or NLST request (with code 450 or 550)
|
||||
* without first responding with a mark. In this case the server does not
|
||||
* touch the data connection.
|
||||
*/
|
||||
|
||||
fptc_getreply(session);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_listdir
|
||||
*
|
||||
* Description:
|
||||
* Get a simple directory listing using NLST:
|
||||
*
|
||||
* NLST [<SP> <pathname>] <CRLF>
|
||||
*
|
||||
* We could do much, much more here using the LIST or MLST/MLSD commands,
|
||||
* but the parsing is a bitch. See http://cr.yp.to/ftpparse.html
|
||||
*
|
||||
* NOTE: We expect to receive only well structured directory paths. Tilde
|
||||
* expansion "~/xyz" and relative paths (abc/def) because we do have
|
||||
* special knowledge about the home and current directories. But otherwise
|
||||
* the paths are expected to be pre-sanitized: No . or .. in paths,
|
||||
* no multiple consecutive '/' in paths, etc.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct ftpc_dirlist_s *ftpc_listdir(SESSION handle,
|
||||
FAR const char *dirpath)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
struct ftpc_dirlist_s *dirlist;
|
||||
FILE *filestream;
|
||||
FAR char *absrpath;
|
||||
FAR char *tmpfname;
|
||||
bool iscurrdir;
|
||||
unsigned int nnames;
|
||||
int allocsize;
|
||||
int ret;
|
||||
|
||||
/* If no remote current directory, we are not logged in. */
|
||||
|
||||
if (!session->currdir)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the absolute path to the directory */
|
||||
|
||||
absrpath = ftpc_absrpath(session, dirpath);
|
||||
if (!absrpath)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ftpc_stripslash(absrpath);
|
||||
|
||||
/* Is the directory also the remote current working directory? */
|
||||
|
||||
iscurrdir = (strcmp(absrpath, session->currdir) == 0);
|
||||
|
||||
/* Create a temporary file to hold the directory listing */
|
||||
|
||||
ret = asprintf(&tmpfname, "%s/TMP%d.dat", CONFIG_FTP_TMPDIR, getpid());
|
||||
if (ret < 0)
|
||||
{
|
||||
free(absrpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
filestream = fopen(tmpfname, "w+");
|
||||
if (!filestream)
|
||||
{
|
||||
nerr("ERROR: Failed to create %s: %d\n", tmpfname, errno);
|
||||
free(absrpath);
|
||||
free(tmpfname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* "CWD" first so that we get the directory contents, not the
|
||||
* directory itself.
|
||||
*/
|
||||
|
||||
if (!iscurrdir)
|
||||
{
|
||||
ret = ftpc_cmd(session, "CWD %s", absrpath);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: CWD to %s failed\n", absrpath);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send the NLST command with no arguments to get the entire contents of
|
||||
* the directory.
|
||||
*/
|
||||
|
||||
ret = ftpc_recvdir(session, filestream);
|
||||
|
||||
/* Go back to the correct current working directory */
|
||||
|
||||
if (!iscurrdir)
|
||||
{
|
||||
int tmpret = ftpc_cmd(session, "CWD %s", session->currdir);
|
||||
if (tmpret != OK)
|
||||
{
|
||||
nerr("ERROR: CWD back to %s failed\n", session->currdir);
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we successfully receive the directory listing? */
|
||||
|
||||
dirlist = NULL;
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Count the number of names in the temporary file */
|
||||
|
||||
rewind(filestream);
|
||||
nnames = 0;
|
||||
|
||||
ftpc_nlstparse(filestream, ftpc_dircount, &nnames);
|
||||
if (!nnames)
|
||||
{
|
||||
nwarn("WARNING: Nothing found in directory\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ninfo("nnames: %d\n", nnames);
|
||||
|
||||
/* Allocate and initialize a directory container */
|
||||
|
||||
allocsize = SIZEOF_FTPC_DIRLIST(nnames);
|
||||
dirlist = (struct ftpc_dirlist_s *)malloc(allocsize);
|
||||
if (!dirlist)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate dirlist\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Then copy all of the directory strings into the container */
|
||||
|
||||
rewind(filestream);
|
||||
dirlist->nnames = 0;
|
||||
|
||||
ftpc_nlstparse(filestream, ftpc_addname, dirlist);
|
||||
DEBUGASSERT(nnames == dirlist->nnames);
|
||||
}
|
||||
|
||||
errout:
|
||||
fclose(filestream);
|
||||
free(absrpath);
|
||||
unlink(tmpfname);
|
||||
free(tmpfname);
|
||||
return dirlist;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_dirfree
|
||||
*
|
||||
* Description:
|
||||
* Release the allocated directory listing.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ftpc_dirfree(FAR struct ftpc_dirlist_s *dirlist)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dirlist)
|
||||
{
|
||||
/* Free each directory name in the directory container */
|
||||
|
||||
for (i = 0; i < dirlist->nnames; i++)
|
||||
{
|
||||
/* NULL means that the caller stole the string */
|
||||
|
||||
if (dirlist->name[i])
|
||||
{
|
||||
free(dirlist->name[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Then free the container itself */
|
||||
|
||||
free(dirlist);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_login.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_login
|
||||
*
|
||||
* Description:
|
||||
* Log into the server
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_login(SESSION handle, FAR struct ftpc_login_s *login)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
int errcode;
|
||||
int ret;
|
||||
|
||||
/* Verify that we are connected to a server */
|
||||
|
||||
if (!ftpc_connected(session))
|
||||
{
|
||||
nerr("ERROR: Not connected\n");
|
||||
errcode = ENOTCONN;
|
||||
goto errout_with_err;
|
||||
}
|
||||
|
||||
/* Verify that we are not already logged in to the server */
|
||||
|
||||
if (ftpc_loggedin(session))
|
||||
{
|
||||
nerr("ERROR: Already logged in\n");
|
||||
errcode = EINVAL;
|
||||
goto errout_with_err;
|
||||
}
|
||||
|
||||
/* Save the login parameter */
|
||||
|
||||
session->uname = ftpc_dequote(login->uname);
|
||||
session->pwd = ftpc_dequote(login->pwd);
|
||||
session->initrdir = ftpc_dequote(login->rdir);
|
||||
|
||||
/* Is passive mode requested? */
|
||||
|
||||
FTPC_CLR_PASSIVE(session);
|
||||
if (login->pasv)
|
||||
{
|
||||
ninfo("Setting passive mode\n");
|
||||
FTPC_SET_PASSIVE(session);
|
||||
}
|
||||
|
||||
/* The (Re-)login to the server */
|
||||
|
||||
ret = ftpc_relogin(session);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: login failed: %d\n", errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
errout_with_err:
|
||||
errno = errcode;
|
||||
errout:
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_relogin
|
||||
*
|
||||
* Description:
|
||||
* Log in again after a loss of connection
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_relogin(FAR struct ftpc_session_s *session)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Log into the server. First send the USER command. The server may
|
||||
* accept USER with:
|
||||
*
|
||||
* - "230 User logged in, proceed" meaning that the client has permission
|
||||
* access files under that username
|
||||
* - "331 "User name okay, need password" or "332 Need account for login"
|
||||
* meaning that permission might be granted after a PASS request.
|
||||
*
|
||||
* Or the server may reject USER with:
|
||||
*
|
||||
* - "530 Not logged in" meaning that the username is unacceptable.
|
||||
*/
|
||||
|
||||
FTPC_CLR_LOGGEDIN(session);
|
||||
ret = ftpc_cmd(session, "USER %s", session->uname);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: USER %s cmd failed: %d\n", session->uname, errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (session->code == 331)
|
||||
{
|
||||
/* Send the PASS command with the passed. The server may accept PASS
|
||||
* with:
|
||||
*
|
||||
* - "230 User logged in, proceed" meaning that the client has
|
||||
* permission to access files under that username
|
||||
* - "202 Command not implemented, superfluous at this site" meaning
|
||||
* that permission was already granted in response to USER
|
||||
* - "332 Need account for login" meaning that permission might be
|
||||
* granted after an ACCT request.
|
||||
*
|
||||
* The server may reject PASS with:
|
||||
*
|
||||
* - "503 Bad sequence of commands" if the previous request was not
|
||||
* USER.
|
||||
* - "530 - Not logged in" if this username and password are
|
||||
* unacceptable.
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "PASS %s", session->pwd);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: PASS %s cmd failed: %d\n", session->pwd, errno);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are logged in.. the current working directory on login is our "home"
|
||||
* directory.
|
||||
*/
|
||||
|
||||
FTPC_SET_LOGGEDIN(session);
|
||||
session->homerdir = ftpc_rpwd((SESSION)session);
|
||||
if (session->homerdir != NULL)
|
||||
{
|
||||
session->currdir = strdup(session->homerdir);
|
||||
}
|
||||
|
||||
/* If the user has requested a special start up directory, then change to
|
||||
* that directory now.
|
||||
*/
|
||||
|
||||
if (session->initrdir)
|
||||
{
|
||||
ftpc_chdir((SESSION)session, session->initrdir);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_mkdir.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_mkdir
|
||||
*
|
||||
* Description:
|
||||
* Creates the named directory on the remote server.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_mkdir(SESSION handle, FAR const char *path)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
char *ptr;
|
||||
int ret;
|
||||
|
||||
ptr = strdup(path);
|
||||
if (!ptr)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ftpc_stripslash(ptr);
|
||||
|
||||
/* Send the MKD request. The MKD request asks the server to create a new
|
||||
* directory. The server accepts the MKD with either:
|
||||
*
|
||||
* - "257 PATHNAME created" that includes the pathname of the directory
|
||||
* - "250 - Requested file action okay, completed" if the directory was
|
||||
* successfully created.
|
||||
*
|
||||
* The server reject MKD with:
|
||||
*
|
||||
* - "550 Requested action not taken" if the creation failed.
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "MKD %s", ptr);
|
||||
free(ptr);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_noop.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_noop
|
||||
*
|
||||
* Description:
|
||||
* No operation command. Using NOOP allows us to make sure that commands
|
||||
* are passed over the control connection without changing the status of
|
||||
* any data transaction or server status. This is useful for (1)
|
||||
* maintaining connections during long IDLE times and (2) It can also be
|
||||
* used as a harmless way of detecting timeouts.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_noop(SESSION handle)
|
||||
{
|
||||
return ftpc_cmd((FAR struct ftpc_session_s *)handle, "NOOP");
|
||||
}
|
||||
@@ -0,0 +1,483 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_putfile.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_sendbinary
|
||||
*
|
||||
* Description:
|
||||
* Send a binary file to the remote host.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ftpc_sendbinary(FAR struct ftpc_session_s *session,
|
||||
FAR FILE *linstream, FILE *routstream)
|
||||
{
|
||||
ssize_t nread;
|
||||
ssize_t nwritten;
|
||||
|
||||
/* Loop until the entire file is sent */
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* Read data from the file */
|
||||
|
||||
nread = fread(session->buffer, sizeof(char), CONFIG_FTP_BUFSIZE,
|
||||
linstream);
|
||||
if (nread <= 0)
|
||||
{
|
||||
/* nread == 0 is just EOF */
|
||||
|
||||
if (nread < 0)
|
||||
{
|
||||
ftpc_xfrabort(session, linstream);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Send the data */
|
||||
|
||||
nwritten = fwrite(session->buffer, sizeof(char), nread, routstream);
|
||||
if (nwritten != nread)
|
||||
{
|
||||
ftpc_xfrabort(session, routstream);
|
||||
|
||||
/* Return failure */
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Increment the size of the file sent */
|
||||
|
||||
session->size += nread;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_sendtext
|
||||
*
|
||||
* Description:
|
||||
* Send a text file to the remote host.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ftpc_sendtext(FAR struct ftpc_session_s *session,
|
||||
FAR FILE *linstream, FAR FILE *routstream)
|
||||
{
|
||||
int ch;
|
||||
int ret = OK;
|
||||
|
||||
/* Write characters one at a time. */
|
||||
|
||||
while ((ch = fgetc(linstream)) != EOF)
|
||||
{
|
||||
/* If it is a newline, send a carriage return too */
|
||||
|
||||
if (ch == '\n')
|
||||
{
|
||||
if (fputc('\r', routstream) == EOF)
|
||||
{
|
||||
ftpc_xfrabort(session, routstream);
|
||||
ret = ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Increment the size of the file sent */
|
||||
|
||||
session->size++;
|
||||
}
|
||||
|
||||
/* Send the character */
|
||||
|
||||
if (fputc(ch, routstream) == EOF)
|
||||
{
|
||||
ftpc_xfrabort(session, routstream);
|
||||
ret = ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Increment the size of the file sent */
|
||||
|
||||
session->size++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_sendfile
|
||||
*
|
||||
* Description:
|
||||
* Send the file to the remote host.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int ftpc_sendfile(struct ftpc_session_s *session, const char *path,
|
||||
FILE *stream, uint8_t how, uint8_t xfrmode)
|
||||
{
|
||||
long offset = session->offset;
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
FAR char *rname;
|
||||
FAR char *str;
|
||||
int len;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
session->offset = 0;
|
||||
|
||||
/* Were we asked to store a file uniquely? Does the host support the STOU
|
||||
* command?
|
||||
*/
|
||||
|
||||
if (how == FTPC_PUT_UNIQUE && !FTPC_HAS_STOU(session))
|
||||
{
|
||||
/* We cannot store a file uniquely */
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ftpc_xfrreset(session);
|
||||
FTPC_SET_PUT(session);
|
||||
|
||||
/* Initialize for the transfer */
|
||||
|
||||
ret = ftpc_xfrinit(session);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ftpc_xfrmode(session, xfrmode);
|
||||
|
||||
/* The REST command sets the start position in the file. Some servers
|
||||
* allow REST immediately before STOR for binary files.
|
||||
*/
|
||||
|
||||
if (offset > 0)
|
||||
{
|
||||
ret = ftpc_cmd(session, "REST %ld", offset);
|
||||
session->size = offset;
|
||||
}
|
||||
|
||||
/* Send the file using STOR, STOU, or APPE:
|
||||
*
|
||||
* - STOR request asks the server to receive the contents of a file from
|
||||
* the data connection already established by the client.
|
||||
* - APPE is just like STOR except that, if the file already exists, the
|
||||
* server appends the client's data to the file.
|
||||
* - STOU is just like STOR except that it asks the server to create a
|
||||
* file under a new pathname selected by the server. If the server
|
||||
* accepts STOU, it provides the pathname in a human-readable format in
|
||||
* the text of its response.
|
||||
*/
|
||||
|
||||
switch (how)
|
||||
{
|
||||
case FTPC_PUT_UNIQUE:
|
||||
{
|
||||
ret = ftpc_cmd(session, "STOU %s", path);
|
||||
|
||||
/* Check for "502 Command not implemented" */
|
||||
|
||||
if (session->code == 502)
|
||||
{
|
||||
/* The host does not support the STOU command */
|
||||
|
||||
FTPC_CLR_STOU(session);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Get the remote filename from the response */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
str = strstr(session->reply, " for ");
|
||||
if (str)
|
||||
{
|
||||
str += 5;
|
||||
len = strlen(str);
|
||||
if (len)
|
||||
{
|
||||
if (*str == '\'')
|
||||
{
|
||||
rname = strndup(str + 1, len - 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
rname = strndup(str, len - 1);
|
||||
ninfo("Unique filename is: %s\n", rname);
|
||||
}
|
||||
|
||||
free(rname);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case FTPC_PUT_APPEND:
|
||||
ret = ftpc_cmd(session, "APPE %s", path);
|
||||
break;
|
||||
|
||||
case FTPC_PUT_NORMAL:
|
||||
default:
|
||||
ret = ftpc_cmd(session, "STOR %s", path);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the server is willing to create a new file under that name, or
|
||||
* replace an existing file under that name, it responds with a mark
|
||||
* using code 150:
|
||||
*
|
||||
* - "150 File status okay; about to open data connection"
|
||||
*
|
||||
* It then attempts to read the contents of the file from the data
|
||||
* connection, and closes the data connection. Finally it accepts the STOR
|
||||
* with:
|
||||
*
|
||||
* - "226 Closing data connection" if the entire file was successfully
|
||||
* received and stored
|
||||
*
|
||||
* Or rejects the STOR with:
|
||||
*
|
||||
* - "425 Can't open data connection" if no TCP connection was established
|
||||
* - "426 Connection closed; transfer aborted" if the TCP connection was
|
||||
* established but then broken by the client or by network failure
|
||||
* - "451 Requested action aborted: local error in processing",
|
||||
* "452 - Requested action not taken", or "552 Requested file action
|
||||
* aborted" if the server had trouble saving the file to disk.
|
||||
*
|
||||
* The server may reject the STOR request with:
|
||||
*
|
||||
* - "450 Requested file action not taken", "452 - Requested action not
|
||||
* taken" or "553 Requested action not taken" without first responding
|
||||
* with a mark.
|
||||
*/
|
||||
|
||||
/* In active mode, we need to accept a connection on the data socket
|
||||
* (in passive mode, we have already connected the data channel to
|
||||
* the FTP server).
|
||||
*/
|
||||
|
||||
if (!FTPC_IS_PASSIVE(session))
|
||||
{
|
||||
ret = ftpc_sockaccept(&session->dacceptor, &session->data);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: Data connection not accepted\n");
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then perform the data transfer */
|
||||
|
||||
if (xfrmode == FTPC_XFRMODE_ASCII)
|
||||
{
|
||||
ret = ftpc_sendtext(session, stream, session->data.outstream);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ftpc_sendbinary(session, stream, session->data.outstream);
|
||||
}
|
||||
|
||||
ftpc_sockflush(&session->data);
|
||||
ftpc_sockclose(&session->data);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
fptc_getreply(session);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_putfile
|
||||
*
|
||||
* Description:
|
||||
* Put a file on the remote host.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
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)
|
||||
{
|
||||
nwarn("WARNING: ftpc_abslpath(%s) failed: %d\n", lname, errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Make sure that the local file exists */
|
||||
|
||||
ret = stat(abslpath, &statbuf);
|
||||
if (ret != OK)
|
||||
{
|
||||
nwarn("WARNING: stat(%s) failed: %d\n", abslpath, errno);
|
||||
goto errout_with_abspath;
|
||||
}
|
||||
|
||||
/* Make sure that the local name does not refer to a directory */
|
||||
|
||||
if (S_ISDIR(statbuf.st_mode))
|
||||
{
|
||||
nwarn("WARNING: %s is a directory\n", abslpath);
|
||||
goto errout_with_abspath;
|
||||
}
|
||||
|
||||
/* Open the local file for reading */
|
||||
|
||||
finstream = fopen(abslpath, "r");
|
||||
if (!finstream)
|
||||
{
|
||||
nwarn("WARNING: 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)
|
||||
{
|
||||
nwarn("WARNING: 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)
|
||||
{
|
||||
nerr("ERROR: 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;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_quit.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <time.h>
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_quit
|
||||
*
|
||||
* Description:
|
||||
* Ends the FTP session with the remote computer and exits ftp
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_quit(SESSION handle)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
int ret = OK;
|
||||
|
||||
if (ftpc_connected(session))
|
||||
{
|
||||
session->replytimeo = 10 * CLOCKS_PER_SEC;
|
||||
ret = ftpc_cmd(session, "QUIT");
|
||||
}
|
||||
|
||||
ftpc_disconnect(handle);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_rename.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_rename
|
||||
*
|
||||
* Description:
|
||||
* Rename a file on the remote server.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_rename(SESSION handle, FAR const char *oldname,
|
||||
FAR const char *newname)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
char *oldcopy;
|
||||
char *newcopy;
|
||||
int ret;
|
||||
|
||||
oldcopy = strdup(oldname);
|
||||
if (!oldcopy)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ftpc_stripslash(oldcopy);
|
||||
|
||||
/* A RNFR request asks the server to begin renaming a file. A typical
|
||||
* server accepts RNFR with:
|
||||
*
|
||||
* - "350 Requested file action pending further information" if the file
|
||||
* exists
|
||||
*
|
||||
* Or rejects RNFR with:
|
||||
*
|
||||
* - "450 Requested file action not taken"
|
||||
* - "550 Requested action not taken"
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "RNFR %s", oldcopy);
|
||||
if (ret != OK)
|
||||
{
|
||||
free(oldcopy);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
free(oldcopy);
|
||||
newcopy = strdup(newname);
|
||||
if (!newcopy)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ftpc_stripslash(newcopy);
|
||||
|
||||
/* A RNTO request asks the server to finish renaming a file. RNTO must
|
||||
* come immediately after RNFR; otherwise the server may reject RNTO with:
|
||||
*
|
||||
* - "503 Bad sequence of commands"
|
||||
*
|
||||
* A typical server accepts RNTO with:
|
||||
*
|
||||
* - "250 Requested file action okay, completed" if the file was renamed
|
||||
* successfully
|
||||
*
|
||||
* Or rejects RMD with:
|
||||
*
|
||||
* - "550 Requested action not taken"
|
||||
* - "553 Requested action not taken"
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "RNTO %s", newcopy);
|
||||
|
||||
free(newcopy);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_response.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_response
|
||||
*
|
||||
* Description:
|
||||
* Return the response string from the last command. This is allocated
|
||||
* memory that must be freed using free() when it is no longer needed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR char *ftpc_response(SESSION handle)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
return strndup(session->reply, CONFIG_FTP_MAXREPLY);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_rmdir.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_rmdir
|
||||
*
|
||||
* Description:
|
||||
* Deletes the named directory on the remote server.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_rmdir(SESSION handle, FAR const char *path)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
char *ptr;
|
||||
int ret;
|
||||
|
||||
ptr = strdup(path);
|
||||
if (!ptr)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ftpc_stripslash(ptr);
|
||||
|
||||
/* An RMD request asks the server to remove a directory. A typical server
|
||||
* accepts RMD with:
|
||||
*
|
||||
* - "250 Requested file action okay, completed" if the directory was
|
||||
* successfully removed
|
||||
*
|
||||
* Or rejects RMD with:
|
||||
*
|
||||
* - "550 Requested action not taken" if the removal failed.
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "RMD %s", ptr);
|
||||
free(ptr);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_rpwd.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_rpwd
|
||||
*
|
||||
* Description:
|
||||
* Returns the current working directory on the remote server.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR char *ftpc_rpwd(SESSION handle)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
FAR char *start;
|
||||
FAR char *end;
|
||||
FAR char *pwd;
|
||||
FAR char *ptr;
|
||||
int len;
|
||||
|
||||
/* Send the PWD command */
|
||||
|
||||
ftpc_cmd(session, "PWD");
|
||||
|
||||
/* Response is like: 257 "/home/gnutt" (from vsftpd).
|
||||
*
|
||||
* Extract the quoted path name into allocated memory.
|
||||
*/
|
||||
|
||||
start = strchr(session->reply, '\"');
|
||||
if (!start)
|
||||
{
|
||||
nwarn("WARNING: Opening quote not found\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
start++;
|
||||
|
||||
end = strchr(start, '\"');
|
||||
if (!end)
|
||||
{
|
||||
nwarn("WARNING: Closing quote not found\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate memory for the path name:
|
||||
*
|
||||
* Reply: 257 "/home/gnutt"
|
||||
* ^start ^end
|
||||
*
|
||||
* len = end - start + 1 = 11 (+ NUL terminator)
|
||||
*/
|
||||
|
||||
len = end - start + 1;
|
||||
pwd = (char *)malloc(len + 1);
|
||||
if (!pwd)
|
||||
{
|
||||
nerr("ERROR: Failed to allocate string\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy the string into the allocated memory */
|
||||
|
||||
memcpy(pwd, start, len);
|
||||
pwd[len] = '\0';
|
||||
|
||||
/* Remove any trailing slash that the server may have added */
|
||||
|
||||
ftpc_stripslash(pwd);
|
||||
|
||||
/* Change DOS style directory separator ('\') to UNIX style ('/') */
|
||||
|
||||
for (ptr = pwd; *ptr; ptr++)
|
||||
{
|
||||
if (*ptr == '\\')
|
||||
{
|
||||
*ptr = '/';
|
||||
}
|
||||
}
|
||||
|
||||
return pwd;
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_socket.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_sockinit
|
||||
*
|
||||
* Description:
|
||||
* Initialize a socket. Create the socket and "wrap" it as C standard
|
||||
* incoming and outgoing streams.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_sockinit(FAR struct ftpc_socket_s *sock, sa_family_t family)
|
||||
{
|
||||
/* Initialize the socket structure */
|
||||
|
||||
memset(sock, 0, sizeof(struct ftpc_socket_s));
|
||||
|
||||
DEBUGASSERT(family == AF_INET || family == AF_INET6);
|
||||
|
||||
sock->laddr.sa.sa_family = family;
|
||||
|
||||
/* Create a socket descriptor */
|
||||
|
||||
sock->sd = socket(family, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sock->sd < 0)
|
||||
{
|
||||
nerr("ERROR: socket() failed: %d\n", errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Call fdopen to "wrap" the socket descriptor as an input stream using C
|
||||
* buffered I/O.
|
||||
*/
|
||||
|
||||
sock->instream = fdopen(sock->sd, "r");
|
||||
if (!sock->instream)
|
||||
{
|
||||
nerr("ERROR: fdopen() failed: %d\n", errno);
|
||||
goto errout_with_sd;
|
||||
}
|
||||
|
||||
/* Call fdopen to "wrap" the socket descriptor as an output stream using C
|
||||
* buffered I/O.
|
||||
*/
|
||||
|
||||
sock->outstream = fdopen(sock->sd, "w");
|
||||
if (!sock->outstream)
|
||||
{
|
||||
nerr("ERROR: fdopen() failed: %d\n", errno);
|
||||
goto errout_with_instream;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
/* Close the instream. NOTE: Since the underlying socket descriptor is
|
||||
* *not* dup'ed, the following close should fail harmlessly.
|
||||
*/
|
||||
|
||||
errout_with_instream:
|
||||
fclose(sock->instream);
|
||||
sock->instream = NULL;
|
||||
errout_with_sd:
|
||||
close(sock->sd);
|
||||
sock->sd = -1;
|
||||
errout:
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_sockclose
|
||||
*
|
||||
* Description:
|
||||
* Close a socket
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ftpc_sockclose(FAR struct ftpc_socket_s *sock)
|
||||
{
|
||||
/* Note that the same underlying socket descriptor is used for both streams.
|
||||
* There should be harmless failures on the second fclose and the close.
|
||||
*/
|
||||
|
||||
fclose(sock->instream);
|
||||
fclose(sock->outstream);
|
||||
close(sock->sd);
|
||||
memset(sock, 0, sizeof(struct ftpc_socket_s));
|
||||
sock->sd = -1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_sockconnect
|
||||
*
|
||||
* Description:
|
||||
* Connect the socket to the host. On a failure, the caller should call.
|
||||
* ftpc_sockclose() to clean up.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_sockconnect(FAR struct ftpc_socket_s *sock, FAR struct sockaddr *addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Connect to the server */
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (addr->sa_family == AF_INET6)
|
||||
{
|
||||
ret = connect(sock->sd, (struct sockaddr *)addr, sizeof(struct sockaddr_in6));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (addr->sa_family == AF_INET)
|
||||
{
|
||||
ret = connect(sock->sd, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nerr("ERROR: Unsupported address family\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: connect() failed: %d\n", errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Get the local address of the socket */
|
||||
|
||||
ret = ftpc_sockgetsockname(sock, &sock->laddr);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: ftpc_sockgetsockname() failed: %d\n", errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
sock->connected = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_sockcopy
|
||||
*
|
||||
* Description:
|
||||
* Copy the socket state from one location to another.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ftpc_sockcopy(FAR struct ftpc_socket_s *dest,
|
||||
FAR const struct ftpc_socket_s *src)
|
||||
{
|
||||
memcpy(&dest->laddr, &src->laddr, sizeof(dest->laddr));
|
||||
dest->connected = ftpc_sockconnected(src);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_sockaccept
|
||||
*
|
||||
* Description:
|
||||
* Accept a connection on the data socket. This function is only used
|
||||
* in active mode.
|
||||
*
|
||||
* In active mode FTP the client connects from a random port (N>1023) to the
|
||||
* FTP server's command port, port 21. Then, the client starts listening to
|
||||
* port N+1 and sends the FTP command PORT N+1 to the FTP server. The server
|
||||
* will then connect back to the client's specified data port from its local
|
||||
* data port, which is port 20. In passive mode FTP the client initiates
|
||||
* both connections to the server, solving the problem of firewalls filtering
|
||||
* the incoming data port connection to the client from the server. When
|
||||
* opening an FTP connection, the client opens two random ports locally
|
||||
* (N>1023 and N+1). The first port contacts the server on port 21, but
|
||||
* instead of then issuing a PORT command and allowing the server to connect
|
||||
* back to its data port, the client will issue the PASV command. The result
|
||||
* of this is that the server then opens a random unprivileged port (P >
|
||||
* 1023) and sends the PORT P command back to the client. The client then
|
||||
* initiates the connection from port N+1 to port P on the server to transfer
|
||||
* data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_sockaccept(FAR struct ftpc_socket_s *acceptor,
|
||||
FAR struct ftpc_socket_s *sock)
|
||||
{
|
||||
union ftpc_sockaddr_u addr;
|
||||
socklen_t addrlen;
|
||||
|
||||
/* Any previous socket should have been uninitialized (0) or explicitly
|
||||
* closed (-1). But the path to this function may include a call to
|
||||
* ftpc_sockinit(). If so... close that socket and call accept to
|
||||
* get a new one.
|
||||
*/
|
||||
|
||||
if (sock->sd > 0)
|
||||
{
|
||||
ftpc_sockclose(sock);
|
||||
}
|
||||
|
||||
addrlen = sizeof(addr);
|
||||
sock->sd = accept(acceptor->sd, (struct sockaddr *)&addr, &addrlen);
|
||||
if (sock->sd == -1)
|
||||
{
|
||||
nerr("ERROR: accept() failed: %d\n", errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
memcpy(&sock->laddr, &addr, sizeof(union ftpc_sockaddr_u));
|
||||
|
||||
/* Create in/out C buffer I/O streams on the data channel. First,
|
||||
* create the incoming buffered stream.
|
||||
*/
|
||||
|
||||
sock->instream = fdopen(sock->sd, "r");
|
||||
if (!sock->instream)
|
||||
{
|
||||
nerr("ERROR: fdopen() failed: %d\n", errno);
|
||||
goto errout_with_sd;
|
||||
}
|
||||
|
||||
/* Create the outgoing stream */
|
||||
|
||||
sock->outstream = fdopen(sock->sd, "w");
|
||||
if (!sock->outstream)
|
||||
{
|
||||
nerr("ERROR: fdopen() failed: %d\n", errno);
|
||||
goto errout_with_instream;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
/* Close the instream. NOTE: Since the underlying socket descriptor is
|
||||
* *not* dup'ed, the following close should fail harmlessly.
|
||||
*/
|
||||
|
||||
errout_with_instream:
|
||||
fclose(sock->instream);
|
||||
sock->instream = NULL;
|
||||
errout_with_sd:
|
||||
close(sock->sd);
|
||||
sock->sd = -1;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_socklisten
|
||||
*
|
||||
* Description:
|
||||
* Bind the socket to local address and wait for connection from the server.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_socklisten(FAR struct ftpc_socket_s *sock)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Bind the local socket to the local address */
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (sock->laddr.sa.sa_family == AF_INET6)
|
||||
{
|
||||
sock->laddr.in6.sin6_port = 0;
|
||||
ret = bind(sock->sd, (struct sockaddr *)&sock->laddr,
|
||||
sizeof(struct sockaddr_in6));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (sock->laddr.sa.sa_family == AF_INET)
|
||||
{
|
||||
sock->laddr.in4.sin_port = 0;
|
||||
ret = bind(sock->sd, (struct sockaddr *)&sock->laddr,
|
||||
sizeof(struct sockaddr_in));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nerr("ERROR: unsupported family\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: bind() failed: %d\n", errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Wait for the connection to the server */
|
||||
|
||||
if (listen(sock->sd, 1) == -1)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Then get the local address selected by NuttX */
|
||||
|
||||
ret = ftpc_sockgetsockname(sock, &sock->laddr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_sockprintf
|
||||
*
|
||||
* Description:
|
||||
* printf to a socket stream
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_sockprintf(FAR struct ftpc_socket_s *sock, FAR const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
va_start(ap, fmt);
|
||||
r = vfprintf(sock->outstream, fmt, ap);
|
||||
va_end(ap);
|
||||
return r;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_sockgetsockname
|
||||
*
|
||||
* Description:
|
||||
* Get the address of the local socket
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_sockgetsockname(FAR struct ftpc_socket_s *sock,
|
||||
FAR union ftpc_sockaddr_u *addr)
|
||||
{
|
||||
socklen_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(union ftpc_sockaddr_u);
|
||||
|
||||
ret = getsockname(sock->sd, (FAR struct sockaddr *)addr, &len);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: getsockname failed: %d\n", errno);
|
||||
return ERROR;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
@@ -0,0 +1,691 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_transfer.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <poll.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
#include "netutils/netlib.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftp_cmd_epsv
|
||||
*
|
||||
* Description:
|
||||
* Enter passive mode using EPSV command.
|
||||
*
|
||||
* In active mode FTP the client connects from a random port (N>1023) to
|
||||
* the FTP server's command port, port 21. Then the client starts listening
|
||||
* to port N+1 and sends the FTP command PORT N+1 to the FTP server. The
|
||||
* server will then connect back to the client's specified data port from
|
||||
* its local data port, which is port 20. In passive mode FTP the client
|
||||
* initiates both connections to the server, solving the problem of
|
||||
* firewalls filtering the incoming data port connection to the client from
|
||||
* the server. When opening an FTP connection, the client opens two random
|
||||
* ports locally (N>1023 and N+1). The first port contacts the server on
|
||||
* port 21, but instead of then issuing a PORT command and allowing the
|
||||
* server to connect back to its data port, the client will issue the PASV
|
||||
* command. The result of this is that the server then opens a random
|
||||
* unprivileged port (P > 1023) and sends the PORT P command back to the
|
||||
* client. The client then initiates the connection from port N+1 to port
|
||||
* P on the server to transfer data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_FTPC_DISABLE_EPSV
|
||||
static int ftp_cmd_epsv(FAR struct ftpc_session_s *session,
|
||||
FAR union ftpc_sockaddr_u *addr)
|
||||
{
|
||||
char *ptr;
|
||||
int nscan;
|
||||
int ret;
|
||||
uint16_t tmp;
|
||||
|
||||
/* Request passive mode. The server normally accepts EPSV with code 227.
|
||||
* Its response is a single line showing the IP address of the server and
|
||||
* the TCP port number where the server is accepting connections.
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "EPSV");
|
||||
if (ret < 0 || !ftpc_connected(session))
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Skip over any leading stuff before important data begins */
|
||||
|
||||
ptr = session->reply + 4;
|
||||
while (*ptr != '(')
|
||||
{
|
||||
ptr++;
|
||||
|
||||
if (ptr > (session->reply + sizeof(session->reply) - 1))
|
||||
{
|
||||
nwarn("WARNING: Error parsing EPSV reply: '%s'\n", session->reply);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ptr++;
|
||||
|
||||
/* The response is then just the port number. None of the other fields
|
||||
* are supplied.
|
||||
*/
|
||||
|
||||
nscan = sscanf(ptr, "|||%hu|", &tmp);
|
||||
if (nscan != 1)
|
||||
{
|
||||
nwarn("WARNING: Error parsing EPSV reply: '%s'\n", session->reply);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (addr->sa.sa_family == AF_INET)
|
||||
{
|
||||
addr->in4.sin_port = HTONS(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (addr->sa.sa_family == AF_INET6)
|
||||
{
|
||||
addr->in6.sin6_port = HTONS(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftp_cmd_pasv
|
||||
*
|
||||
* Description:
|
||||
* Enter passive mode using PASV command.
|
||||
*
|
||||
* In active mode FTP the client connects from a random port (N>1023) to
|
||||
* the FTP server's command port, port 21. Then the client starts listening
|
||||
* to port N+1 and sends the FTP command PORT N+1 to the FTP server. The
|
||||
* server will then connect back to the client's specified data port from
|
||||
* its local data port, which is port 20. In passive mode FTP the client
|
||||
* initiates both connections to the server, solving the problem of
|
||||
* firewalls filtering the incoming data port connection to the client from
|
||||
* the server. When opening an FTP connection, the client opens two random
|
||||
* ports locally (N>1023 and N+1). The first port contacts the server on
|
||||
* port 21, but instead of then issuing a PORT command and allowing the
|
||||
* server to connect back to its data port, the client will issue the PASV
|
||||
* of this is that the server then opens a random unprivileged port (P >
|
||||
* command. The result 1023) and sends the PORT P command back to the
|
||||
* client. The client then initiates the connection from port N+1 to port P
|
||||
* on the server to transfer data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FTPC_DISABLE_EPSV
|
||||
static int ftp_cmd_pasv(FAR struct ftpc_session_s *session,
|
||||
FAR union ftpc_sockaddr_u *addr)
|
||||
{
|
||||
int tmpap[6];
|
||||
char *ptr;
|
||||
int nscan;
|
||||
int ret;
|
||||
|
||||
/* Request passive mode. The server normally accepts PASV with code 227.
|
||||
* Its response is a single line showing the IP address of the server and
|
||||
* the TCP port number where the server is accepting connections.
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "PASV");
|
||||
if (ret < 0 || !ftpc_connected(session))
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Skip over any leading stuff before important data begins */
|
||||
|
||||
ptr = session->reply + 4;
|
||||
while (*ptr != '\0' && !isdigit((int)*ptr))
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* The response is then 6 integer values: four representing the
|
||||
* IP address and two representing the port number.
|
||||
*/
|
||||
|
||||
nscan = sscanf(ptr, "%d,%d,%d,%d,%d,%d",
|
||||
&tmpap[0], &tmpap[1], &tmpap[2],
|
||||
&tmpap[3], &tmpap[4], &tmpap[5]);
|
||||
if (nscan != 6)
|
||||
{
|
||||
nwarn("WARNING: Error parsing PASV reply: '%s'\n", session->reply);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Then copy the sscanf'ed values as bytes */
|
||||
|
||||
memcpy(&addr->in4.sin_addr, tmpap, sizeof(addr->in4.sin_addr));
|
||||
memcpy(&addr->in4.sin_port, &tmpap[4], sizeof(addr->in4.sin_port));
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_abspath
|
||||
*
|
||||
* Description:
|
||||
* Get the absolute path to a file, handling tilde expansion.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR char *ftpc_abspath(FAR struct ftpc_session_s *session,
|
||||
FAR const char *relpath,
|
||||
FAR const char *homedir,
|
||||
FAR const char *curdir)
|
||||
{
|
||||
FAR char *ptr = NULL;
|
||||
|
||||
/* If no relative path was provide,
|
||||
* then use the current working directory
|
||||
*/
|
||||
|
||||
if (!relpath)
|
||||
{
|
||||
return strdup(curdir);
|
||||
}
|
||||
|
||||
/* Handle tilde expansion */
|
||||
|
||||
if (relpath[0] == '~')
|
||||
{
|
||||
/* Is the relative path only '~' */
|
||||
|
||||
if (relpath[1] == '\0')
|
||||
{
|
||||
return strdup(homedir);
|
||||
}
|
||||
|
||||
/* No... then a '/' better follow the tilde */
|
||||
|
||||
else if (relpath[1] == '/')
|
||||
{
|
||||
asprintf(&ptr, "%s%s", homedir, &relpath[1]);
|
||||
}
|
||||
|
||||
/* Hmmm... this pretty much guaranteed to fail */
|
||||
|
||||
else
|
||||
{
|
||||
ptr = strdup(relpath);
|
||||
}
|
||||
}
|
||||
|
||||
/* No tilde expansion. Check for a path relative to the current
|
||||
* directory.
|
||||
*/
|
||||
|
||||
else if (strncmp(relpath, "./", 2) == 0)
|
||||
{
|
||||
asprintf(&ptr, "%s%s", curdir, relpath + 1);
|
||||
}
|
||||
|
||||
/* Check for an absolute path */
|
||||
|
||||
else if (relpath[0] == '/')
|
||||
{
|
||||
ptr = strdup(relpath);
|
||||
}
|
||||
|
||||
/* Assume it a relative path */
|
||||
|
||||
else
|
||||
{
|
||||
asprintf(&ptr, "%s/%s", curdir, relpath);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_xfrinit
|
||||
*
|
||||
* Description:
|
||||
* Perform common transfer setup logic.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_xfrinit(FAR struct ftpc_session_s *session)
|
||||
{
|
||||
union ftpc_sockaddr_u addr;
|
||||
int ret;
|
||||
#ifdef CONFIG_FTPC_DISABLE_EPRT
|
||||
uint8_t *paddr;
|
||||
uint8_t *pport;
|
||||
#else
|
||||
char ipstr[48];
|
||||
#endif
|
||||
|
||||
/* We must be connected to initiate a transfer */
|
||||
|
||||
if (!ftpc_connected(session))
|
||||
{
|
||||
nerr("ERROR: Not connected\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Should we enter passive mode? */
|
||||
|
||||
if (FTPC_IS_PASSIVE(session))
|
||||
{
|
||||
/* Initialize the data channel */
|
||||
|
||||
ret = ftpc_sockinit(&session->data, session->server.sa.sa_family);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: ftpc_sockinit() failed: %d\n", errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Does this host support the PASV command */
|
||||
|
||||
if (!FTPC_HAS_PASV(session))
|
||||
{
|
||||
nerr("ERROR: Host doesn't support passive mode\n");
|
||||
goto errout_with_data;
|
||||
}
|
||||
|
||||
/* Configure the address to be the server address. If EPSV is used, the
|
||||
* port will be populated by parsing the reply of the EPSV command. If
|
||||
* the PASV command is used, the address and port will be overwritten.
|
||||
*/
|
||||
|
||||
memcpy(&addr, &session->server, sizeof(union ftpc_sockaddr_u));
|
||||
|
||||
/* Yes.. going passive. */
|
||||
|
||||
#ifdef CONFIG_FTPC_DISABLE_EPSV
|
||||
ret = ftp_cmd_pasv(session, &addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: ftp_cmd_pasv() failed: %d\n", errno);
|
||||
goto errout_with_data;
|
||||
}
|
||||
#else
|
||||
ret = ftp_cmd_epsv(session, &addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: ftp_cmd_epsv() failed: %d\n", errno);
|
||||
goto errout_with_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Connect the data socket */
|
||||
|
||||
ret = ftpc_sockconnect(&session->data, (FAR struct sockaddr *)&addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: ftpc_sockconnect() failed: %d\n", errno);
|
||||
goto errout_with_data;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialize the data listener socket that allows us to accept new
|
||||
* data connections from the server
|
||||
*/
|
||||
|
||||
ret = ftpc_sockinit(&session->dacceptor, session->server.sa.sa_family);
|
||||
if (ret != OK)
|
||||
{
|
||||
nerr("ERROR: ftpc_sockinit() failed: %d\n", errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Use the server IP address to find the network interface, and
|
||||
* subsequent local IP address used to establish the active
|
||||
* connection. We must send the IP and port to the server so that
|
||||
* it knows how to connect.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (session->server.sa.sa_family == AF_INET6)
|
||||
{
|
||||
ret = netlib_ipv6adaptor(&session->server.in6.sin6_addr,
|
||||
&session->dacceptor.laddr.in6.sin6_addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: netlib_ipv6adaptor() failed: %d\n", ret);
|
||||
goto errout_with_data;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (session->server.sa.sa_family == AF_INET)
|
||||
{
|
||||
ret = netlib_ipv4adaptor(session->server.in4.sin_addr.s_addr,
|
||||
&session->dacceptor.laddr.in4.sin_addr.s_addr);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: netlib_ipv4adaptor() failed: %d\n", ret);
|
||||
goto errout_with_data;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nerr("ERROR: unsupported address family\n");
|
||||
goto errout_with_data;
|
||||
}
|
||||
|
||||
/* Wait for the connection to be established */
|
||||
|
||||
ftpc_socklisten(&session->dacceptor);
|
||||
|
||||
#ifdef CONFIG_FTPC_DISABLE_EPRT
|
||||
/* Then send our local data channel address to the server */
|
||||
|
||||
paddr = (uint8_t *)&session->dacceptor.laddr.in4.sin_addr;
|
||||
pport = (uint8_t *)&session->dacceptor.laddr.in4.sin_port;
|
||||
|
||||
ret = ftpc_cmd(session, "PORT %d,%d,%d,%d,%d,%d",
|
||||
paddr[0], paddr[1], paddr[2],
|
||||
paddr[3], pport[0], pport[1]);
|
||||
#else
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (session->dacceptor.laddr.sa.sa_family == AF_INET6)
|
||||
{
|
||||
if (!inet_ntop(AF_INET6, &session->dacceptor.laddr.in6.sin6_addr,
|
||||
ipstr, 48))
|
||||
{
|
||||
nerr("ERROR: inet_ntop failed: %d\n", errno);
|
||||
goto errout_with_data;
|
||||
}
|
||||
|
||||
ret = ftpc_cmd(session, "EPRT |2|%s|%d|", ipstr,
|
||||
session->dacceptor.laddr.in6.sin6_port);
|
||||
}
|
||||
else
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (session->dacceptor.laddr.sa.sa_family == AF_INET)
|
||||
{
|
||||
if (!inet_ntop(AF_INET, &session->dacceptor.laddr.in4.sin_addr,
|
||||
ipstr, 48))
|
||||
{
|
||||
nerr("ERROR: inet_ntop failed: %d\n", errno);
|
||||
goto errout_with_data;
|
||||
}
|
||||
|
||||
ret = ftpc_cmd(session, "EPRT |1|%s|%d|", ipstr,
|
||||
session->dacceptor.laddr.in4.sin_port);
|
||||
}
|
||||
else
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
#endif /* CONFIG_FTPC_DISABLE_EPRT */
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: ftpc_cmd() failed: %d\n", errno);
|
||||
goto errout_with_data;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
errout_with_data:
|
||||
ftpc_sockclose(&session->data);
|
||||
ftpc_sockclose(&session->dacceptor);
|
||||
errout:
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_xfrreset
|
||||
*
|
||||
* Description:
|
||||
* Reset transfer variables
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ftpc_xfrreset(struct ftpc_session_s *session)
|
||||
{
|
||||
session->size = 0;
|
||||
session->flags &= ~FTPC_XFER_FLAGS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_xfrmode
|
||||
*
|
||||
* Description:
|
||||
* Select ASCII or Binary transfer mode
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_xfrmode(struct ftpc_session_s *session, uint8_t xfrmode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Check if we have already selected the requested mode */
|
||||
|
||||
DEBUGASSERT(xfrmode != FTPC_XFRMODE_UNKNOWN);
|
||||
if (session->xfrmode != xfrmode)
|
||||
{
|
||||
/* Send the TYPE request to control the binary flag.
|
||||
* Parameters for the TYPE request include:
|
||||
*
|
||||
* A: Turn the binary flag off.
|
||||
* A N: Turn the binary flag off.
|
||||
* I: Turn the binary flag on.
|
||||
* L 8: Turn the binary flag on.
|
||||
*
|
||||
* The server accepts the TYPE request with code 200.
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "TYPE %c",
|
||||
xfrmode == FTPC_XFRMODE_ASCII ? 'A' : 'I');
|
||||
if (ret < 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
session->xfrmode = xfrmode;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_xfrabort
|
||||
*
|
||||
* Description:
|
||||
* Abort a transfer in progress
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_xfrabort(FAR struct ftpc_session_s *session, FAR FILE *stream)
|
||||
{
|
||||
FAR struct pollfd fds;
|
||||
int ret;
|
||||
|
||||
/* Make sure that we are still connected */
|
||||
|
||||
if (!ftpc_connected(session))
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Check if there is data waiting to be read from the cmd channel */
|
||||
|
||||
fds.fd = session->cmd.sd;
|
||||
fds.events = POLLIN;
|
||||
ret = poll(&fds, 1, 0);
|
||||
if (ret > 0)
|
||||
{
|
||||
/* Read data from command channel */
|
||||
|
||||
ninfo("Flush cmd channel data\n");
|
||||
while (stream &&
|
||||
fread(session->buffer, 1, CONFIG_FTP_BUFSIZE, stream) > 0);
|
||||
return OK;
|
||||
}
|
||||
|
||||
FTPC_SET_INTERRUPT(session);
|
||||
|
||||
/* Send the Telnet interrupt sequence to abort the transfer:
|
||||
* <IAC IP><IAC DM>ABORT<CR><LF>
|
||||
*/
|
||||
|
||||
ninfo("Telnet ABORt sequence\n");
|
||||
ftpc_sockprintf(&session->cmd, "%c%c", TELNET_IAC, TELNET_IP); /* Interrupt process */
|
||||
ftpc_sockprintf(&session->cmd, "%c%c", TELNET_IAC, TELNET_DM); /* Telnet synch signal */
|
||||
ftpc_sockprintf(&session->cmd, "ABOR\r\n"); /* Abort */
|
||||
ftpc_sockflush(&session->cmd);
|
||||
|
||||
/* Read remaining bytes from connection */
|
||||
|
||||
while (stream &&
|
||||
fread(session->buffer, 1, CONFIG_FTP_BUFSIZE, stream) > 0);
|
||||
|
||||
/* Get the ABORt reply */
|
||||
|
||||
fptc_getreply(session);
|
||||
|
||||
/* Expected replies are: "226 Closing data connection" or
|
||||
* "426 Connection closed; transfer aborted"
|
||||
*/
|
||||
|
||||
if (session->code != 226 && session->code != 426)
|
||||
{
|
||||
ninfo("Expected 226 or 426 reply\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the next reply */
|
||||
|
||||
fptc_getreply(session);
|
||||
|
||||
/* Expected replies are: "226 Closing data connection" or
|
||||
* "225 Data connection open; no transfer in progress"
|
||||
*/
|
||||
|
||||
if (session->code != 226 && session->code != 225)
|
||||
{
|
||||
ninfo("Expected 225 or 226 reply\n");
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_timeout
|
||||
*
|
||||
* Description:
|
||||
* A timeout occurred -- either on a specific command or while waiting
|
||||
* for a reply.
|
||||
*
|
||||
* NOTE:
|
||||
* This function executes in the context of a timer interrupt handler.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ftpc_timeout(wdparm_t arg)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)arg;
|
||||
|
||||
nerr("ERROR: Timeout!\n");
|
||||
DEBUGASSERT(session);
|
||||
kill(session->pid, CONFIG_FTP_SIGNAL);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_absrpath
|
||||
*
|
||||
* Description:
|
||||
* Get the absolute path to a remote file, handling tilde expansion.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR char *ftpc_absrpath(FAR struct ftpc_session_s *session,
|
||||
FAR const char *relpath)
|
||||
{
|
||||
FAR char *absrpath = ftpc_abspath(session, relpath,
|
||||
session->homerdir, session->currdir);
|
||||
ninfo("%s -> %s\n", relpath, absrpath);
|
||||
return absrpath;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_abslpath
|
||||
*
|
||||
* Description:
|
||||
* Get the absolute path to a local file, handling tilde expansion.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR char *ftpc_abslpath(FAR struct ftpc_session_s *session,
|
||||
FAR const char *relpath)
|
||||
{
|
||||
FAR char *abslpath = ftpc_abspath(session, relpath,
|
||||
session->homeldir, session->curldir);
|
||||
ninfo("%s -> %s\n", relpath, abslpath);
|
||||
return abslpath;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_unlink.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include "netutils/ftpc.h"
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_unlink
|
||||
*
|
||||
* Description:
|
||||
* Delete the given file from the remote server.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_unlink(SESSION handle, FAR const char *path)
|
||||
{
|
||||
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
|
||||
int ret;
|
||||
|
||||
/* A DELE request asks the server to remove a regular file. A typical server
|
||||
* accepts DELE with:
|
||||
*
|
||||
* - "250 Requested file action okay, completed" if the file was
|
||||
* successfully removed
|
||||
*
|
||||
* Or rejects RMD with:
|
||||
*
|
||||
* - "550 Requested action not taken" f the removal failed.
|
||||
*/
|
||||
|
||||
ret = ftpc_cmd(session, "DELE %s", path);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
/****************************************************************************
|
||||
* apps/netutils/ftpc/ftpc_utils.c
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "ftpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ftpc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_nibble
|
||||
*
|
||||
* Description:
|
||||
* Convert a ASCII hex 'digit' to binary
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ftpc_nibble(char ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
{
|
||||
return (unsigned int)ch - '0';
|
||||
}
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
{
|
||||
return (unsigned int)ch - 'A' + 10;
|
||||
}
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
{
|
||||
return (unsigned int)ch - 'a' + 10;
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_reset
|
||||
*
|
||||
* Description:
|
||||
* Reset the FTP session.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ftpc_reset(struct ftpc_session_s *session)
|
||||
{
|
||||
ftpc_sockclose(&session->data);
|
||||
ftpc_sockclose(&session->cmd);
|
||||
free(session->uname);
|
||||
session->uname = NULL;
|
||||
free(session->pwd);
|
||||
session->pwd = NULL;
|
||||
free(session->initrdir);
|
||||
session->initrdir = NULL;
|
||||
session->flags &= ~FTPC_FLAGS_CLEAR;
|
||||
session->flags |= FTPC_FLAGS_SET;
|
||||
session->xfrmode = FTPC_XFRMODE_UNKNOWN;
|
||||
session->code = 0;
|
||||
session->replytimeo = CONFIG_FTP_DEFTIMEO * CLOCKS_PER_SEC;
|
||||
session->conntimeo = CONFIG_FTP_DEFTIMEO * CLOCKS_PER_SEC;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_lpwd
|
||||
*
|
||||
* Description:
|
||||
* Return the local current working directory. NOTE: This is a peek at
|
||||
* a global copy. The caller should call strdup if it wants to keep it.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR const char *ftpc_lpwd(void)
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
FAR const char *val;
|
||||
|
||||
val = getenv("PWD");
|
||||
if (!val)
|
||||
{
|
||||
val = CONFIG_FTP_TMPDIR;
|
||||
}
|
||||
|
||||
return val;
|
||||
#else
|
||||
return CONFIG_FTP_TMPDIR;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_stripcrlf
|
||||
*
|
||||
* Description:
|
||||
* Strip any trailing carriage returns or line feeds from a string (by
|
||||
* overwriting them with NUL characters).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ftpc_stripcrlf(FAR char *str)
|
||||
{
|
||||
FAR char *ptr;
|
||||
int len;
|
||||
|
||||
if (str)
|
||||
{
|
||||
len = strlen(str);
|
||||
if (len > 0)
|
||||
{
|
||||
for (ptr = str + len - 1;
|
||||
len > 0 && (*ptr == '\r' || *ptr == '\n');
|
||||
ptr--, len--)
|
||||
{
|
||||
*ptr = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_stripslash
|
||||
*
|
||||
* Description:
|
||||
* Strip single trailing slash from a string (by overwriting it with NUL
|
||||
* character).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void ftpc_stripslash(FAR char *str)
|
||||
{
|
||||
FAR char *ptr;
|
||||
int len;
|
||||
|
||||
if (str)
|
||||
{
|
||||
len = strlen(str);
|
||||
if (len > 1)
|
||||
{
|
||||
ptr = str + len - 1;
|
||||
if (*ptr == '/')
|
||||
{
|
||||
*ptr = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ftpc_dequote
|
||||
*
|
||||
* Description:
|
||||
* Convert quoted hexadecimal constants to binary values.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR char *ftpc_dequote(FAR const char *str)
|
||||
{
|
||||
FAR char *allocstr = NULL;
|
||||
FAR char *ptr;
|
||||
int ms;
|
||||
int ls;
|
||||
int len;
|
||||
|
||||
if (str)
|
||||
{
|
||||
/* Allocate space for a modifiable copy of the string */
|
||||
|
||||
len = strlen(str);
|
||||
allocstr = (FAR char *)malloc(len + 1);
|
||||
if (allocstr)
|
||||
{
|
||||
/* Search the string */
|
||||
|
||||
ptr = allocstr;
|
||||
while (*str != '\0')
|
||||
{
|
||||
/* Check for a quoted hex value (make sure that there are
|
||||
* least 3 characters remaining in the string.
|
||||
*/
|
||||
|
||||
if (len > 2 && str[0] == '%')
|
||||
{
|
||||
/* Extract the hex value */
|
||||
|
||||
ms = ftpc_nibble(str[1]);
|
||||
if (ms >= 0)
|
||||
{
|
||||
ls = ftpc_nibble(str[2]);
|
||||
if (ls >= 0)
|
||||
{
|
||||
/* Save the binary value and skip ahead by 3 */
|
||||
|
||||
*ptr++ = (char)(ms << 4 | ls);
|
||||
str += 3;
|
||||
len -= 3;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Just transfer the character */
|
||||
|
||||
*ptr++ = *str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
/* NUL terminate */
|
||||
|
||||
*ptr = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return allocstr;
|
||||
}
|
||||
Reference in New Issue
Block a user