More FTP bugfixes

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3665 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-06-03 20:27:30 +00:00
parent a94c011b4e
commit da50c819f9
23 changed files with 350 additions and 209 deletions

View File

@ -56,9 +56,13 @@ examples/ftpc
to that it will only work as a "built-in" program that can be run from
NSH when CONFIG_NSH_BUILTIN_APPS is defined.
From NSH, the startup command line is then:
From NSH, the startup command sequence is as follows. This is only
an example, your configration could have different mass storage devices,
mount paths, and FTP directories:
ftpc xx.xx.xx.xx[:pp]
mount -t vfat /dev/mmcsd0 /tmp # Mount the SD card at /tmp
cd /tmp # cd into the /tmp directory
ftpc xx.xx.xx.xx[:pp] # Start the FTP client
where xx.xx.xx.xx is the IP address of the FTP server and pp is an
optional port number.

View File

@ -108,7 +108,7 @@ int cmd_rchdir(SESSION handle, int argc, char **argv)
int cmd_rpwd(SESSION handle, int argc, char **argv)
{
FAR char *pwd = ftpc_pwd(handle);
FAR char *pwd = ftpc_rpwd(handle);
if (pwd)
{
printf("PWD: %s\n", pwd);
@ -178,8 +178,8 @@ int cmd_rrename(SESSION handle, int argc, char **argv)
int cmd_rsize(SESSION handle, int argc, char **argv)
{
uint64_t size = ftpc_filesize(handle, argv[1]);
printf("SIZE: %ull\n", size);
off_t size = ftpc_filesize(handle, argv[1]);
printf("SIZE: %lu\n", size);
return OK;
}
@ -190,7 +190,7 @@ int cmd_rsize(SESSION handle, int argc, char **argv)
int cmd_rtime(SESSION handle, int argc, char **argv)
{
time_t filetime = ftpc_filetime(handle, argv[1]);
printf("TIME: %ul\n", (long)filetime);
printf("TIME: %lu\n", (long)filetime);
return OK;
}
@ -264,6 +264,7 @@ int cmd_rls(SESSION handle, int argc, char **argv)
{
printf(" %s\n", dirlist->name[i]);
}
FFLUSH();
ftpc_dirfree(dirlist);
return OK;

View File

@ -42,6 +42,7 @@
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdbool.h>
#include <signal.h>
#include <time.h>
@ -184,7 +185,7 @@ EXTERN int ftpc_login(SESSION handle, FAR struct ftpc_login_s *login);
EXTERN int ftpc_quit(SESSION handle);
EXTERN int ftpc_chdir(SESSION handle, FAR const char *path);
EXTERN FAR char *ftpc_pwd(SESSION handle);
EXTERN FAR char *ftpc_rpwd(SESSION handle);
EXTERN int ftpc_cdup(SESSION handle);
EXTERN int ftpc_mkdir(SESSION handle, FAR const char *path);
EXTERN int ftpc_rmdir(SESSION handle, FAR const char *path);
@ -192,7 +193,7 @@ EXTERN int ftpc_rmdir(SESSION handle, FAR const char *path);
EXTERN int ftpc_unlink(SESSION handle, FAR const char *path);
EXTERN int ftpc_chmod(SESSION handle, FAR const char *path, FAR const char *mode);
EXTERN int ftpc_rename(SESSION handle, FAR const char *oldname, FAR const char *newname);
EXTERN uint64_t ftpc_filesize(SESSION handle, FAR const char *path);
EXTERN off_t ftpc_filesize(SESSION handle, FAR const char *path);
EXTERN time_t ftpc_filetime(SESSION handle, FAR const char *filename);
EXTERN int ftpc_idle(SESSION handle, unsigned int idletime);

View File

@ -49,7 +49,7 @@ 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_pwd.c ftpc_quit.c ftpc_rename.c ftpc_rmdir.c ftpc_unlink.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

View File

@ -75,13 +75,13 @@
*
****************************************************************************/
int ftpc_cdup(SESSION handle)
int ftpc_cdup(SESSION handle)
{
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
int ret;
ret = ftpc_cmd(session, "CDUP");
ftpc_curdir(session);
ftpc_currdir(session);
return ret;
}

View File

@ -86,6 +86,6 @@ int ftpc_chdir(SESSION handle, FAR const char *path)
return ret;
}
ftpc_curdir(session);
ftpc_currdir(session);
return OK;
}

View File

@ -85,7 +85,7 @@ int ftpc_chmod(SESSION handle, FAR const char *path, FAR const char *mode)
if (FTPC_HAS_CHMOD(session))
{
ret = ftpc_cmd(session, "SITE CHMOD %s %s", mode, path);
ret = ftpc_cmd(session, "SITE CHMOD %s %s", path, mode);
/* Check for "502 Command not implemented" */

View File

@ -87,8 +87,8 @@ static int ftpc_restore(struct ftpc_session_s *session)
{
/* Set the initial directory to the last valid current directory */
free(session->initdir);
session->initdir = ftpc_dequote(session->curdir);
free(session->initrdir);
session->initrdir = ftpc_dequote(session->currdir);
/* Reconnect to the server */

View File

@ -41,6 +41,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
@ -114,6 +115,15 @@ SESSION ftpc_connect(FAR struct ftpc_connect_s *server)
session->port = htons(server->port);
}
/* 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());
/* session->curldir = strdup(sssion->homeldir); */
/* Create up a timer to prevent hangs */
session->wdog = wd_create();

View File

@ -91,10 +91,10 @@ void ftpc_disconnect(SESSION handle)
free(session->uname);
free(session->pwd);
free(session->initdir);
free(session->homedir);
free(session->curdir);
free(session->prevdir);
free(session->initrdir);
free(session->homerdir);
free(session->currdir);
free(session->prevrdir);
free(session->rname);
free(session->lname);

View File

@ -78,10 +78,10 @@
*
****************************************************************************/
uint64_t ftpc_filesize(SESSION handle, FAR const char *path)
off_t ftpc_filesize(SESSION handle, FAR const char *path)
{
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
uint64_t ret;
unsigned long ret;
/* Check if the host supports the SIZE command */
@ -107,6 +107,6 @@
return ERROR;
}
sscanf(session->reply, "%*s %llu", &ret);
return ret;
sscanf(session->reply, "%*s %lu", &ret);
return (off_t)ret;
}

View File

@ -270,20 +270,30 @@ int ftpc_getfile(SESSION handle, FAR const char *rname, FAR const char *lname,
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;
/* Get the full path to the local file */
abslpath = ftpc_abslpath(session, lname);
if (!abslpath)
{
ndbg("ftpc_abslpath(%s) failed: %d\n", errno);
goto errout;
}
/* Get information about the local file */
ret = stat(lname, &statbuf);
ret = stat(abslpath, &statbuf);
if (ret == 0)
{
/* It already exists. Is it a directory? */
if (S_ISDIR(statbuf.st_mode))
{
ndbg("'%s' is a directory\n", lname);
return ERROR;
ndbg("'%s' is a directory\n", abslpath);
goto errout_with_abspath;
}
}
@ -292,8 +302,8 @@ int ftpc_getfile(SESSION handle, FAR const char *rname, FAR const char *lname,
#ifdef S_IWRITE
if (!(statbuf.st_mode & S_IWRITE))
{
ndbg("'%s' permission denied\n", lname);
return ERROR;
ndbg("'%s' permission denied\n", abslpath);
goto errout_with_abspath;
}
#endif
@ -316,27 +326,14 @@ int ftpc_getfile(SESSION handle, FAR const char *rname, FAR const char *lname,
if (ret != OK)
{
ndbg("ftpc_recvinit failed\n");
return ERROR;
goto errout_with_abspath;
}
loutstream = fopen(lname, (offset > 0 || (how == FTPC_GET_APPEND)) ? "a" : "w");
loutstream = fopen(abslpath, (offset > 0 || (how == FTPC_GET_APPEND)) ? "a" : "w");
if (!loutstream)
{
ndbg("fopen failed: %d\n", errno);
session->offset = 0;
return ERROR;
}
if (offset > 0)
{
ret = fseek(loutstream, offset, SEEK_SET);
if (ret != OK)
{
ndbg("fseek failed: %d\n", errno);
fclose(loutstream);
session->offset = 0;
return ERROR;
}
goto errout_with_abspath;
}
/* Save the new local and remote file names */
@ -344,7 +341,17 @@ int ftpc_getfile(SESSION handle, FAR const char *rname, FAR const char *lname,
free(session->rname);
free(session->lname);
session->rname = strdup(rname);
session->lname = strdup(lname);
session->lname = abslpath;
if (offset > 0)
{
ret = fseek(loutstream, offset, SEEK_SET);
if (ret != OK)
{
ndbg("fseek failed: %d\n", errno);
goto errout_with_outstream;
}
}
/* And receive the new file data */
@ -364,8 +371,26 @@ int ftpc_getfile(SESSION handle, FAR const char *rname, FAR const char *lname,
fptc_getreply(session);
}
/* On success, the last rname and lname are retained for debug purpose */
if (ret == OK && !FTPC_INTERRUPTED(session))
{
fclose(loutstream);
return OK;
}
/* Various error exits */
errout_with_outstream:
fclose(loutstream);
return (ret == OK && !FTPC_INTERRUPTED(session)) ? OK : ERROR;
free(session->rname);
session->rname = NULL;
session->lname = NULL;
errout_with_abspath:
free(abslpath);
session->offset = 0;
errout:
return ERROR;
}
/****************************************************************************

View File

@ -91,7 +91,7 @@ int ftpc_idle(SESSION handle, unsigned int idletime)
if (!FTPC_HAS_IDLE(session))
{
ndbg("Server doesn't support SITE IDLE\n");
ndbg("Server does not support SITE IDLE\n");
return ERROR;
}
@ -108,12 +108,13 @@ int ftpc_idle(SESSION handle, unsigned int idletime)
ret = ftpc_cmd(session, "SITE IDLE");
}
/* Check for "502 Command not implemented" */
/* Check for "502 Command not implemented" or 500 "Unknown SITE command" */
if (session->code == 502)
if (session->code == 500 || session->code == 502)
{
/* Server does not support SITE IDLE */
ndbg("Server does not support SITE IDLE\n");
FTPC_CLR_IDLE(session);
}

View File

@ -153,11 +153,12 @@ struct ftpc_session_s
WDOG_ID wdog; /* Timer */
FAR char *uname; /* Login uname */
FAR char *pwd; /* Login pwd */
FAR char *initdir; /* Initial remote directory */
FAR char *homedir; /* Home directory (curdir on startup) */
FAR char *curdir; /* Current directory */
FAR char *prevdir; /* Previous directory */
FAR char *initrdir; /* Initial remote directory */
FAR char *homerdir; /* Remote home directory (currdir on startup) */
FAR char *currdir; /* Remote current directory */
FAR char *prevrdir; /* Previous remote directory */
FAR char *rname; /* Remote file name */
FAR char *homeldir; /* Local home directory (PWD on startup) */
FAR char *lname; /* Local file name */
pid_t pid; /* Task ID of FTP client */
uint8_t xfrmode; /* Previous data transfer type (See FTPC_XFRMODE_* defines) */
@ -174,6 +175,13 @@ struct ftpc_session_s
char reply[CONFIG_FTP_MAXREPLY+1]; /* Last reply string from server */
};
/* 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
****************************************************************************/
@ -212,16 +220,23 @@ 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 void ftpc_curdir(struct ftpc_session_s *session);
EXTERN void ftpc_currdir(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 int ftpc_reconnect(FAR struct ftpc_session_s *session);
EXTERN int ftpc_relogin(FAR struct ftpc_session_s *session);
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 */

View File

@ -73,79 +73,6 @@ typedef void (*callback_t)(FAR const char *name, FAR void *arg);
* Private Functions
****************************************************************************/
/****************************************************************************
* 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 char *ptr = NULL;
int ret = OK;
/* If no relative path was provide, then use the current working directory */
if (!relpath)
{
return strdup(session->curdir);
}
/* Handle tilde expansion */
if (relpath[0] == '~')
{
/* Is the relative path only '~' */
if (relpath[1] == '\0')
{
return strdup(session->homedir);
}
/* No... then a '/' better follow the tilde */
else if (relpath[1] == '/')
{
ret = asprintf(&ptr, "%s%s", session->homedir, &relpath[1]);
}
/* Hmmm... this prety 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)
{
ret = asprintf(&ptr, "%s%s", session->curdir, relpath+1);
}
/* Check for an absolute path */
else if (relpath[0] == '/' && relpath[1] == ':' && relpath[2] == '\\')
{
ptr = strdup(relpath);
}
/* Take a wild guess */
else
{
ret = asprintf(&ptr, "%s/%s", session->curdir, relpath);
}
return ptr;
}
/****************************************************************************
* Name: ftpc_dircount
*
@ -342,30 +269,30 @@ FAR struct ftpc_dirlist_s *ftpc_listdir(SESSION handle,
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
struct ftpc_dirlist_s *dirlist;
FILE *filestream;
FAR char *abspath;
FAR char *absrpath;
FAR char *tmpfname;
bool iscurdir;
bool iscurrdir;
unsigned int nnames;
int allocsize;
int ret;
/* Get the absolute path to the directory */
abspath = ftpc_abspath(session, dirpath);
ftpc_stripslash(abspath);
absrpath = ftpc_absrpath(session, dirpath);
ftpc_stripslash(absrpath);
/* Is the directory also the remote current working directory? */
iscurdir = (strcmp(abspath, session->curdir) == 0);
iscurrdir = (strcmp(absrpath, session->currdir) == 0);
/* Create a temporary file to hold the directory listing */
asprintf(&tmpfname, "%s/TMP%s.dat", CONFIG_FTP_TMPDIR, getpid());
asprintf(&tmpfname, "%s/TMP%d.dat", CONFIG_FTP_TMPDIR, getpid());
filestream = fopen(tmpfname, "w+");
if (!filestream)
{
ndbg("Failed to create %s: %d\n", tmpfname, errno);
free(abspath);
free(absrpath);
free(tmpfname);
return NULL;
}
@ -374,12 +301,12 @@ FAR struct ftpc_dirlist_s *ftpc_listdir(SESSION handle,
* directory itself.
*/
if (!iscurdir)
if (!iscurrdir)
{
ret = ftpc_cmd(session, "CWD %s", abspath);
ret = ftpc_cmd(session, "CWD %s", absrpath);
if (ret != OK)
{
ndbg("CWD to %s failed\n", abspath);
ndbg("CWD to %s failed\n", absrpath);
}
}
@ -391,12 +318,12 @@ FAR struct ftpc_dirlist_s *ftpc_listdir(SESSION handle,
/* Go back to the correct current working directory */
if (!iscurdir)
if (!iscurrdir)
{
int tmpret = ftpc_cmd(session, "CWD %s", session->curdir);
int tmpret = ftpc_cmd(session, "CWD %s", session->currdir);
if (tmpret != OK)
{
ndbg("CWD back to to %s failed\n", session->curdir);
ndbg("CWD back to to %s failed\n", session->currdir);
}
}
@ -435,7 +362,7 @@ FAR struct ftpc_dirlist_s *ftpc_listdir(SESSION handle,
errout:
fclose(filestream);
free(abspath);
free(absrpath);
unlink(tmpfname);
free(tmpfname);
return dirlist;

View File

@ -105,9 +105,9 @@ int ftpc_login(SESSION handle, FAR struct ftpc_login_s *login)
/* Save the login parameter */
session->uname = ftpc_dequote(login->uname);
session->pwd = ftpc_dequote(login->pwd);
session->initdir = ftpc_dequote(login->rdir);
session->uname = ftpc_dequote(login->uname);
session->pwd = ftpc_dequote(login->pwd);
session->initrdir = ftpc_dequote(login->rdir);
/* Is passive mode requested? */
@ -198,17 +198,17 @@ int ftpc_relogin(FAR struct ftpc_session_s *session)
*/
FTPC_SET_LOGGEDIN(session);
session->homedir = ftpc_pwd((SESSION)session);
session->curdir = strdup(session->homedir);
session->prevdir = strdup(session->homedir);
session->homerdir = ftpc_rpwd((SESSION)session);
session->currdir = strdup(session->homerdir);
session->prevrdir = strdup(session->homerdir);
/* If the user has requested a special start up directory, then change to
* that directory now.
*/
if (session->initdir)
if (session->initrdir)
{
ftpc_chdir((SESSION)session, session->initdir);
ftpc_chdir((SESSION)session, session->initrdir);
}
return OK;

View File

@ -286,15 +286,15 @@ static int ftpc_sendfile(struct ftpc_session_s *session, const char *path,
len = strlen(str);
if (len)
{
free(session->lname);
free(session->rname);
if (*str == '\'')
{
session->lname = strndup(str+1, len-3);
session->rname = strndup(str+1, len-3);
}
else
{
session->lname = strndup(str, len-1);
nvdbg("Unique filename is: %s\n", session->lname);
session->rname = strndup(str, len-1);
nvdbg("Unique filename is: %s\n", session->rname);
}
}
}
@ -383,34 +383,45 @@ 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;
/* Get the full path to the local file */
abslpath = ftpc_abslpath(session, lname);
if (!abslpath)
{
ndbg("ftpc_abslpath(%s) failed: %d\n", errno);
goto errout;
}
/* Make sure that the local file exists */
ret = stat(lname, &statbuf);
ret = stat(abslpath, &statbuf);
if (ret != OK)
{
ndbg("stat() failed: %d\n", errno);
return ERROR;
ndbg("stat(%s) failed: %d\n", errno);
free(abslpath);
goto errout;
}
/* Make sure that the local name does not refer to a directory */
if (S_ISDIR(statbuf.st_mode))
{
ndbg("%s is a directory\n", lname);
return ERROR;
ndbg("%s is a directory\n", abslpath);
goto errout_with_abspath;
}
/* Open the local file for reading */
finstream = fopen(lname, "r");
finstream = fopen(abslpath, "r");
if (!finstream == 0)
{
ndbg("fopen() failed: %d\n", errno);
return ERROR;
goto errout_with_abspath;
}
/* Configure for the transfer */
@ -418,8 +429,8 @@ int ftp_putfile(SESSION handle, const char *lname, const char *rname,
session->filesize = statbuf.st_size;
free(session->rname);
free(session->lname);
session->rname = strdup(lname);
session->lname = strdup(rname);
session->rname = strdup(rname);
session->lname = abslpath;
/* Are we resuming a transfer? */
@ -434,6 +445,7 @@ int ftp_putfile(SESSION handle, const char *lname, const char *rname,
if (session->offset == (off_t)ERROR)
{
ndbg("Failed to get size of remote file: %s\n", rname);
goto errout_with_instream;
}
else
{
@ -445,13 +457,29 @@ int ftp_putfile(SESSION handle, const char *lname, const char *rname,
if (ret != OK)
{
ndbg("fseek failed: %d\n", errno);
fclose(finstream);
return ERROR;
goto errout_with_instream;
}
}
}
/* On success, the last rname and lname are retained for debug purpose */
ret = ftpc_sendfile(session, rname, finstream, how, xfrmode);
if (ret == OK)
{
fclose(finstream);
return OK;
}
/* Various error exits */
errout_with_instream:
fclose(finstream);
return ret;
free(session->rname);
session->rname = NULL;
session->lname = NULL;
errout_with_abspath:
free(abslpath);
errout:
return ERROR;
}

View File

@ -1,5 +1,5 @@
/****************************************************************************
* apps/netutils/ftpc/ftpc_pwd.c
* apps/netutils/ftpc/ftpc_rpwd.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
@ -72,14 +72,14 @@
****************************************************************************/
/****************************************************************************
* Name: ftpc_pwd
* Name: ftpc_rpwd
*
* Descripton:
* Returns the current working directory on the remote server.
*
****************************************************************************/
FAR char *ftpc_pwd(SESSION handle)
FAR char *ftpc_rpwd(SESSION handle)
{
FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
FAR char *start;

View File

@ -216,7 +216,6 @@ int ftpc_sockaccept(struct ftpc_socket_s *sock, const char *mode, bool passive)
{
struct sockaddr addr;
socklen_t addrlen;
int sd;
/* Any previous socket should have been uninitialized (0) or explicitly
* closed (-1).
@ -245,7 +244,7 @@ int ftpc_sockaccept(struct ftpc_socket_s *sock, const char *mode, bool passive)
{
addrlen = sizeof(addr);
sock->sd = accept(sock->sd, &addr, &addrlen);
if (sd == -1)
if (sock->sd == -1)
{
ndbg("accept() failed: %d\n", errno);
return ERROR;

View File

@ -158,6 +158,80 @@ static int ftp_pasvmode(struct ftpc_session_s *session,
return OK;
}
/****************************************************************************
* 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;
int ret = OK;
/* 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] == '/')
{
ret = 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)
{
ret = asprintf(&ptr, "%s%s", curdir, relpath+1);
}
/* Check for an absolute path */
else if (relpath[0] == '/' && relpath[1] == ':' && relpath[2] == '\\')
{
ptr = strdup(relpath);
}
/* Assume it a relative path */
else
{
ret = asprintf(&ptr, "%s/%s", curdir, relpath);
}
return ptr;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -182,6 +256,7 @@ int ftpc_xfrinit(FAR struct ftpc_session_s *session)
if (!ftpc_connected(session))
{
ndbg("Not connected\n");
goto errout;
}
@ -207,6 +282,7 @@ int ftpc_xfrinit(FAR struct ftpc_session_s *session)
ret = ftp_pasvmode(session, addrport);
if (ret != OK)
{
ndbg("ftp_pasvmode() failed: %d\n", errno);
goto errout_with_data;
}
}
@ -343,7 +419,7 @@ int ftpc_xfrabort(FAR struct ftpc_session_s *session, FAR FILE *stream)
* <IAC IP><IAC DM>ABORT<CR><LF>
*/
ndbg("Telnet ABORt sequence\n");
nvdbg("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 */
@ -435,3 +511,39 @@ void ftpc_timeout(int argc, uint32_t arg1, ...)
DEBUGASSERT(argc == 1 && 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);
nvdbg("%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);
nvdbg("%s -> %s\n", relpath, abslpath);
return abslpath;
}

View File

@ -109,8 +109,8 @@ void ftpc_reset(struct ftpc_session_s *session)
session->uname = NULL;
free(session->pwd);
session->pwd = NULL;
free(session->initdir);
session->initdir = NULL;
free(session->initrdir);
session->initrdir = NULL;
session->flags = FTPC_FLAGS_INIT;
session->xfrmode = FTPC_XFRMODE_UNKNOWN;
session->code = 0;
@ -119,18 +119,43 @@ void ftpc_reset(struct ftpc_session_s *session)
}
/****************************************************************************
* Name: ftpc_curdir
* Name: ftpc_currdir
*
* Description:
* Update the current working directory
* Update the remote current working directory
*
****************************************************************************/
void ftpc_curdir(struct ftpc_session_s *session)
void ftpc_currdir(struct ftpc_session_s *session)
{
free(session->prevdir);
session->prevdir = session->curdir;
session->curdir = ftpc_pwd((SESSION)session);
free(session->prevrdir);
session->prevrdir = session->currdir;
session->currdir = ftpc_rpwd((SESSION)session);
}
/****************************************************************************
* 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
}
/****************************************************************************

View File

@ -89,9 +89,6 @@
int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
FAR char *argv[])
{
#ifndef CONFIG_APPS_BINDIR
FAR const char * name;
#endif
int ret = OK;
/* Try to find command within pre-built application list. */
@ -99,30 +96,7 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
ret = exec_namedapp(cmd, argv);
if (ret < 0)
{
int err = -errno;
#ifndef CONFIG_APPS_BINDIR
int i;
/* On failure, list the set of available built-in commands */
nsh_output(vtbl, "Builtin Apps: ");
for (i = 0; (name = namedapp_getname(i)) != NULL; i++)
{
nsh_output(vtbl, "%s ", name);
}
nsh_output(vtbl, "\nand type 'help' for more NSH commands.\n\n");
/* If the failing command was '?', then do not report an error */
if (strcmp(cmd, "?") != 0)
{
return err;
}
return OK;
#else
return err;
#endif
return -errno;
}
#ifdef CONFIG_SCHED_WAITPID

View File

@ -140,6 +140,10 @@ static const struct cmdmap_s g_cmdmap[] =
{ "[", cmd_lbracket, 4, NSH_MAX_ARGUMENTS, "<expression> ]" },
#endif
#ifndef CONFIG_NSH_DISABLE_HELP
{ "?", cmd_help, 1, 1, NULL },
#endif
#if CONFIG_NFILE_DESCRIPTORS > 0
# ifndef CONFIG_NSH_DISABLE_CAT
{ "cat", cmd_cat, 2, NSH_MAX_ARGUMENTS, "<path> [<path> [<path> ...]]" },
@ -391,6 +395,10 @@ const char g_fmtsignalrecvd[] = "nsh: %s: Interrupted by signal\n";
static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
{
const struct cmdmap_s *ptr;
#ifdef CONFIG_NSH_BUILTIN_APPS
FAR const char * name;
int i;
#endif
nsh_output(vtbl, "NSH command forms:\n");
#ifndef CONFIG_NSH_DISABLEBG
@ -419,6 +427,17 @@ static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
nsh_output(vtbl, " %s\n", ptr->cmd);
}
}
/* List the set of available built-in commands */
#ifdef CONFIG_NSH_BUILTIN_APPS
nsh_output(vtbl, "\nBuiltin Apps: ");
for (i = 0; (name = namedapp_getname(i)) != NULL; i++)
{
nsh_output(vtbl, " %s\n", name);
}
#endif
return OK;
}
#endif