diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-06-03 20:27:30 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-06-03 20:27:30 +0000 |
commit | 92fd8f5221ca528c2def13897c712d558adf1675 (patch) | |
tree | 0c9d63fe3408864b46597a4eb1c20eace2ffc783 /apps/netutils | |
parent | 90e92459a9c7a33fb8a005f87ec3f512b760c487 (diff) | |
download | nuttx-92fd8f5221ca528c2def13897c712d558adf1675.tar.gz nuttx-92fd8f5221ca528c2def13897c712d558adf1675.tar.bz2 nuttx-92fd8f5221ca528c2def13897c712d558adf1675.zip |
More FTP bugfixes
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3665 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'apps/netutils')
-rw-r--r-- | apps/netutils/ftpc/Makefile | 2 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_cdup.c | 4 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_chdir.c | 2 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_chmod.c | 2 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_cmd.c | 4 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_connect.c | 10 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_disconnect.c | 8 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_filesize.c | 8 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_getfile.c | 65 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_idle.c | 7 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_internal.h | 31 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_listdir.c | 101 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_login.c | 16 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_putfile.c | 60 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_rpwd.c (renamed from apps/netutils/ftpc/ftpc_pwd.c) | 6 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_socket.c | 3 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_transfer.c | 114 | ||||
-rw-r--r-- | apps/netutils/ftpc/ftpc_utils.c | 41 |
18 files changed, 313 insertions, 171 deletions
diff --git a/apps/netutils/ftpc/Makefile b/apps/netutils/ftpc/Makefile index 9c5862a53..59121e3b7 100644 --- a/apps/netutils/ftpc/Makefile +++ b/apps/netutils/ftpc/Makefile @@ -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 diff --git a/apps/netutils/ftpc/ftpc_cdup.c b/apps/netutils/ftpc/ftpc_cdup.c index a5f22bbc2..75c02bd96 100644 --- a/apps/netutils/ftpc/ftpc_cdup.c +++ b/apps/netutils/ftpc/ftpc_cdup.c @@ -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; } diff --git a/apps/netutils/ftpc/ftpc_chdir.c b/apps/netutils/ftpc/ftpc_chdir.c index 0bc47ddf8..0081b4870 100644 --- a/apps/netutils/ftpc/ftpc_chdir.c +++ b/apps/netutils/ftpc/ftpc_chdir.c @@ -86,6 +86,6 @@ int ftpc_chdir(SESSION handle, FAR const char *path) return ret; } - ftpc_curdir(session); + ftpc_currdir(session); return OK; } diff --git a/apps/netutils/ftpc/ftpc_chmod.c b/apps/netutils/ftpc/ftpc_chmod.c index f349edb09..13d06f403 100644 --- a/apps/netutils/ftpc/ftpc_chmod.c +++ b/apps/netutils/ftpc/ftpc_chmod.c @@ -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" */ diff --git a/apps/netutils/ftpc/ftpc_cmd.c b/apps/netutils/ftpc/ftpc_cmd.c index ec89050ba..dc031790d 100644 --- a/apps/netutils/ftpc/ftpc_cmd.c +++ b/apps/netutils/ftpc/ftpc_cmd.c @@ -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 */ diff --git a/apps/netutils/ftpc/ftpc_connect.c b/apps/netutils/ftpc/ftpc_connect.c index 3af6ef65f..8affbdade 100644 --- a/apps/netutils/ftpc/ftpc_connect.c +++ b/apps/netutils/ftpc/ftpc_connect.c @@ -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(); diff --git a/apps/netutils/ftpc/ftpc_disconnect.c b/apps/netutils/ftpc/ftpc_disconnect.c index 90c47ee1d..787de5f1b 100644 --- a/apps/netutils/ftpc/ftpc_disconnect.c +++ b/apps/netutils/ftpc/ftpc_disconnect.c @@ -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); diff --git a/apps/netutils/ftpc/ftpc_filesize.c b/apps/netutils/ftpc/ftpc_filesize.c index 18561eb1d..d827f736e 100644 --- a/apps/netutils/ftpc/ftpc_filesize.c +++ b/apps/netutils/ftpc/ftpc_filesize.c @@ -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; } diff --git a/apps/netutils/ftpc/ftpc_getfile.c b/apps/netutils/ftpc/ftpc_getfile.c index e9816e5b4..bf9fc69ea 100644 --- a/apps/netutils/ftpc/ftpc_getfile.c +++ b/apps/netutils/ftpc/ftpc_getfile.c @@ -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,36 +326,33 @@ 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; + goto errout_with_abspath; } + /* Save the new local and remote file names */ + + free(session->rname); + free(session->lname); + session->rname = strdup(rname); + session->lname = abslpath; + 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_outstream; } } - /* Save the new local and remote file names */ - - free(session->rname); - free(session->lname); - session->rname = strdup(rname); - session->lname = strdup(lname); - /* And receive the new file data */ if (xfrmode == FTPC_XFRMODE_ASCII) @@ -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; } /**************************************************************************** diff --git a/apps/netutils/ftpc/ftpc_idle.c b/apps/netutils/ftpc/ftpc_idle.c index 2d049f8b4..95a94d233 100644 --- a/apps/netutils/ftpc/ftpc_idle.c +++ b/apps/netutils/ftpc/ftpc_idle.c @@ -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); } diff --git a/apps/netutils/ftpc/ftpc_internal.h b/apps/netutils/ftpc/ftpc_internal.h index 5e177b36b..6eab632a5 100644 --- a/apps/netutils/ftpc/ftpc_internal.h +++ b/apps/netutils/ftpc/ftpc_internal.h @@ -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 */ diff --git a/apps/netutils/ftpc/ftpc_listdir.c b/apps/netutils/ftpc/ftpc_listdir.c index 4c36445ad..e5309daed 100644 --- a/apps/netutils/ftpc/ftpc_listdir.c +++ b/apps/netutils/ftpc/ftpc_listdir.c @@ -74,79 +74,6 @@ typedef void (*callback_t)(FAR const char *name, FAR void *arg); ****************************************************************************/ /**************************************************************************** - * 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 * * Description: @@ -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; diff --git a/apps/netutils/ftpc/ftpc_login.c b/apps/netutils/ftpc/ftpc_login.c index 83d2cde05..1d6ff395c 100644 --- a/apps/netutils/ftpc/ftpc_login.c +++ b/apps/netutils/ftpc/ftpc_login.c @@ -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; diff --git a/apps/netutils/ftpc/ftpc_putfile.c b/apps/netutils/ftpc/ftpc_putfile.c index f0e85a0bc..c465cc66d 100644 --- a/apps/netutils/ftpc/ftpc_putfile.c +++ b/apps/netutils/ftpc/ftpc_putfile.c @@ -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; } diff --git a/apps/netutils/ftpc/ftpc_pwd.c b/apps/netutils/ftpc/ftpc_rpwd.c index e8cfaef70..091a12944 100644 --- a/apps/netutils/ftpc/ftpc_pwd.c +++ b/apps/netutils/ftpc/ftpc_rpwd.c @@ -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; diff --git a/apps/netutils/ftpc/ftpc_socket.c b/apps/netutils/ftpc/ftpc_socket.c index 129e6f565..d70bf1d63 100644 --- a/apps/netutils/ftpc/ftpc_socket.c +++ b/apps/netutils/ftpc/ftpc_socket.c @@ -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; diff --git a/apps/netutils/ftpc/ftpc_transfer.c b/apps/netutils/ftpc/ftpc_transfer.c index bc0ca8b03..8d1a577e9 100644 --- a/apps/netutils/ftpc/ftpc_transfer.c +++ b/apps/netutils/ftpc/ftpc_transfer.c @@ -159,6 +159,80 @@ static int ftp_pasvmode(struct ftpc_session_s *session, } /**************************************************************************** + * 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; +} + + diff --git a/apps/netutils/ftpc/ftpc_utils.c b/apps/netutils/ftpc/ftpc_utils.c index 9692cae4f..eec52ec8f 100644 --- a/apps/netutils/ftpc/ftpc_utils.c +++ b/apps/netutils/ftpc/ftpc_utils.c @@ -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 } /**************************************************************************** |