From e67850971d60936e8bc7d93f4a57a8712a5dc2e3 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 11 Jan 2020 18:32:40 -0600 Subject: [PATCH] apps/netutils/ftpd/ftpd.c: Fixes several problems: 1. This fixes the issue reported in Bitbucket apps/ Issue 15. That is, if fopen() fails, the NULL stream handle would be used in subsequent logic. The handling of the failure was incomplete. 2. Some of the error handling was fixed. In the event of an error, it was return return an error value ONLY if we failure to report the error and even then the wrong error would be reported. This change now preserves and returns the correct error number that is the root cause of the failure. 3. Ran the file through tools/nxstyle and cleaned up many formatting problems. --- netutils/ftpd/ftpd.c | 503 ++++++++++++++++++++++++------------------- 1 file changed, 287 insertions(+), 216 deletions(-) diff --git a/netutils/ftpd/ftpd.c b/netutils/ftpd/ftpd.c index 53c233c6b..602442ef8 100644 --- a/netutils/ftpd/ftpd.c +++ b/netutils/ftpd/ftpd.c @@ -1,7 +1,7 @@ /**************************************************************************** * apps/n etutils/ftpd.c * - * Copyright (C) 2012, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2012, 2015, 2020 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Includes original code as well as logic adapted from hwport_ftpd, written @@ -75,6 +75,7 @@ /**************************************************************************** * Private Function Prototypes ****************************************************************************/ + /* Account functions */ static FAR struct ftpd_account_s *ftpd_account_new(FAR const char *user, @@ -113,7 +114,8 @@ static ssize_t ftpd_response(int sd, int timeout, FAR const char *fmt, ...); static int ftpd_dataopen(FAR struct ftpd_session_s *session); static int ftpd_dataclose(FAR struct ftpd_session_s *session); -static FAR struct ftpd_server_s *ftpd_openserver(int port, sa_family_t family); +static FAR struct ftpd_server_s *ftpd_openserver(int port, + sa_family_t family); /* Path helpers */ @@ -251,7 +253,8 @@ static const char g_respfmt2[] = "%03u%c%s%s\r\n"; /* Integer, character, two s static const char *g_monthtab[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec" }; static const char *g_ftpdhelp[] = @@ -265,16 +268,13 @@ static const char *g_ftpdhelp[] = "APPE REST ABOR USER PASS ACCT* REIN* LIST", "NLST STAT* SITE* MLSD* MLST*", "Direct comments to " CONFIG_FTPD_VENDORID, - NULL + NULL }; /**************************************************************************** * Private Functions ****************************************************************************/ -/**************************************************************************** - * Account Functions - ****************************************************************************/ /**************************************************************************** * Name: ftpd_account_new ****************************************************************************/ @@ -506,12 +506,14 @@ ftpd_account_search_user(FAR struct ftpd_session_s *session, newaccount = ftpd_account_new(NULL, accountflags); if (newaccount) { - if (ftpd_account_setpassword(newaccount, account->password) < 0) + if (ftpd_account_setpassword(newaccount, + account->password) < 0) { ftpd_account_free(newaccount); newaccount = NULL; } - else if (ftpd_account_sethome(newaccount, account->home) < 0) + else if (ftpd_account_sethome(newaccount, + account->home) < 0) { ftpd_account_free(newaccount); newaccount = NULL; @@ -534,17 +536,20 @@ ftpd_account_search_user(FAR struct ftpd_session_s *session, newaccount = ftpd_account_new(account->user, accountflags); if (newaccount) { - if (ftpd_account_setpassword(newaccount, account->password) != 0) + if (ftpd_account_setpassword(newaccount, + account->password) != 0) { ftpd_account_free(newaccount); newaccount = NULL; } - else if (ftpd_account_sethome(newaccount, account->home) != 0) + else if (ftpd_account_sethome(newaccount, + account->home) != 0) { ftpd_account_free(newaccount); newaccount = NULL; } } + break; } } @@ -623,20 +628,17 @@ ftpd_account_login(FAR struct ftpd_session_s *session, session->work = strdup(!home ? "/" : home); } else - { - /* normal user */ + { + /* normal user */ - session->home = strdup(!home ? "/" : home); - session->work = strdup("/"); - } + session->home = strdup(!home ? "/" : home); + session->work = strdup("/"); + } ftpd_account_free(account); return account; } -/**************************************************************************** - * Parsing Functions - ****************************************************************************/ /**************************************************************************** * Name: ftpd_strtok ****************************************************************************/ @@ -682,10 +684,10 @@ static FAR char *ftpd_strtok(bool skipspace, FAR const char *delimiters, sptr++; } - /* Save the place where we will resuming searching */ + /* Save the place where we will resuming searching */ - *str = sptr; - return ret; + *str = sptr; + return ret; } /**************************************************************************** @@ -745,30 +747,28 @@ static FAR char *ftpd_strtok_alloc(bool skipspace, FAR const char *delimiters, } } - /* Allocate memory large enough to hold the entire sub-string (including - * the NUL terminator. - */ + /* Allocate memory large enough to hold the entire sub-string (including + * the NUL terminator. + */ - tokenlen = (size_t)(right - left); - ret = (FAR char *)malloc(tokenlen + 1); - if (ret) - { - if (tokenlen > 0) - { - memcpy(ret, left, tokenlen); - } - ret[tokenlen] = '\0'; - } + tokenlen = (size_t)(right - left); + ret = (FAR char *)malloc(tokenlen + 1); + if (ret) + { + if (tokenlen > 0) + { + memcpy(ret, left, tokenlen); + } - /* Save the place where we will resuming searching */ + ret[tokenlen] = '\0'; + } - *str = sptr; - return ret; + /* Save the place where we will resuming searching */ + + *str = sptr; + return ret; } -/**************************************************************************** - * Socket Helpers - ****************************************************************************/ /**************************************************************************** * Name: ftpd_rxpoll ****************************************************************************/ @@ -796,7 +796,6 @@ static int ftpd_rxpoll(int sd, int timeout) if (ret == 0) { - //ninfo("poll() timed out\n"); return -ETIMEDOUT; } else if (ret < 0) @@ -878,6 +877,7 @@ static int ftpd_accept(int sd, FAR void *addr, FAR socklen_t *addrlen, nerr("ERROR: ftpd_rxpoll() failed: %d\n", ret); } #endif + return ret; } } @@ -937,7 +937,8 @@ static ssize_t ftpd_recv(int sd, FAR void *data, size_t size, int timeout) * Name: ftpd_send ****************************************************************************/ -static ssize_t ftpd_send(int sd, FAR const void *data, size_t size, int timeout) +static ssize_t ftpd_send(int sd, FAR const void *data, size_t size, + int timeout) { ssize_t ret; @@ -1027,7 +1028,8 @@ static int ftpd_dataopen(FAR struct ftpd_session_s *session) } session->data.addrlen = (socklen_t)sizeof(session->data.addr); - ret = connect(session->data.sd, (FAR const struct sockaddr *)(&session->data.addr), + ret = connect(session->data.sd, + (FAR const struct sockaddr *)(&session->data.addr), session->data.addrlen); if (ret < 0) { @@ -1044,9 +1046,10 @@ static int ftpd_dataopen(FAR struct ftpd_session_s *session) struct linger ling; memset(&ling, 0, sizeof(ling)); - ling.l_onoff = 1; + ling.l_onoff = 1; ling.l_linger = 4; - setsockopt(session->data.sd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)); + setsockopt(session->data.sd, SOL_SOCKET, SO_LINGER, &ling, + sizeof(ling)); } #endif @@ -1174,7 +1177,7 @@ static FAR struct ftpd_server_s *ftpd_openserver(int port, sa_family_t family) #ifdef CONFIG_NET_HAVE_REUSEADDR { int reuse = 1; - setsockopt(server->sd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + setsockopt(server->sd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); } #endif @@ -1199,9 +1202,6 @@ static FAR struct ftpd_server_s *ftpd_openserver(int port, sa_family_t family) return (FTPD_SESSION)server; } -/**************************************************************************** - * Path Helpers - ****************************************************************************/ /**************************************************************************** * Name: ftpd_pathignore ****************************************************************************/ @@ -1238,8 +1238,10 @@ static int ftpd_pathignore(FAR struct ftpd_pathnode_s *currpath) { node->ignore = true; } + break; } + node = node->blink; } @@ -1272,6 +1274,7 @@ static void ftpd_nodefree(FAR struct ftpd_pathnode_s *node) { free(prev->name); } + free(prev); } } @@ -1305,7 +1308,8 @@ static FAR struct ftpd_pathnode_s *ftpd_path2node(FAR const char *path) path++; } - newnode = (FAR struct ftpd_pathnode_s *)malloc(sizeof(struct ftpd_pathnode_s)); + newnode = (FAR struct ftpd_pathnode_s *) + malloc(sizeof(struct ftpd_pathnode_s)); if (!newnode) { free(name); @@ -1597,9 +1601,6 @@ static int ftpd_getpath(FAR struct ftpd_session_s *session, return OK; } -/**************************************************************************** - * Command Helpers - ****************************************************************************/ /**************************************************************************** * Name: ftpd_changedir ****************************************************************************/ @@ -1612,31 +1613,39 @@ static int ftpd_changedir(FAR struct ftpd_session_s *session, struct stat st; int ret; - ret = ftpd_getpath(session, rempath, (char **)(&abspath), (char **)(&workpath)); + ret = ftpd_getpath(session, rempath, (FAR char **)(&abspath), + (FAR char **)(&workpath)); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not change directory !"); + free(workpath); + free(abspath); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not change directory !"); + return ret; } ret = stat(abspath, &st); if (ret < 0) { + ret = -errno; + free(workpath); free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', rempath, - ": No such file or directory"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', rempath, + ": No such file or directory"); + return ret; } if (S_ISDIR(st.st_mode) == 0) { free(workpath); free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', rempath, - ": No such file or directory"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', rempath, + ": No such file or directory"); + return -ENOTDIR; } free(abspath); @@ -1644,6 +1653,7 @@ static int ftpd_changedir(FAR struct ftpd_session_s *session, { free(session->work); } + session->work = workpath; return ftpd_response(session->cmd.sd, session->txtimeout, @@ -1674,20 +1684,22 @@ static off_t ftpd_offsatoi(FAR const char *filename, off_t offset) if (offset == (off_t)(-1)) { - for (;;) + for (; ; ) { ch = getc(outstream); if (ch == EOF) { break; } + ret++; if (ch == '\n') { ret++; } } - /* ret is ascii mode size */ + + /* ret is ascii mode size */ } else { @@ -1742,6 +1754,7 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) g_respfmt1, 550, ' ', "Stream error !"); goto errout; } + path = abspath; ret = ftpd_dataopen(session); @@ -1863,7 +1876,7 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) goto errout_with_session; } - pos += (off_t)seekoffs; + pos += (off_t)seekoffs; } /* Send success message */ @@ -1876,7 +1889,7 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) goto errout_with_session; } - for (;;) + for (; ; ) { /* Read from the source (file or TCP connection) */ @@ -1903,8 +1916,8 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) } else { - /* Read from the TCP connection, ftpd_recve returns the negated error - * condition. + /* Read from the TCP connection, ftpd_recve returns the negated + * error condition. */ rdbytes = ftpd_recv(session->data.sd, session->data.buffer, @@ -1959,6 +1972,7 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) { buffer[buflen++] = '\r'; } + buffer[buflen++] = session->data.buffer[offset++]; } } @@ -1972,7 +1986,8 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) { /* Write to the TCP connection */ - wrbytes = ftpd_send(session->data.sd, buffer, buflen, session->txtimeout); + wrbytes = ftpd_send(session->data.sd, buffer, buflen, + session->txtimeout); if (wrbytes < 0) { errval = -wrbytes; @@ -2016,7 +2031,8 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) if (wrbytes != ((ssize_t)buflen)) { - nerr("ERROR: Write failed: wrbytes=%d errval=%d\n", wrbytes, errval); + nerr("ERROR: Write failed: wrbytes=%d errval=%d\n", + wrbytes, errval); ftpd_response(session->cmd.sd, session->txtimeout, g_respfmt1, 550, ' ', "Data send error !"); ret = -errval; @@ -2241,24 +2257,29 @@ static int ftpd_listbuffer(FAR struct ftpd_session_s *session, FAR char *path, #ifdef __NUTTX__ /* Fake nlink, user id, and group id */ - offset += snprintf(&buffer[offset], buflen - offset, "%4u %8u %8u", 1, 1001, 512); + offset += snprintf(&buffer[offset], buflen - offset, "%4u %8u %8u", + 1, 1001, 512); #else /* nlink */ - offset += snprintf(&buffer[offset], buflen - offset, "%4u", st->st_nlink); + offset += snprintf(&buffer[offset], buflen - offset, "%4u", + st->st_nlink); /* user id */ - offset += snprintf(&buffer[offset], buflen - offset, " %8u", st->st_uid); + offset += snprintf(&buffer[offset], buflen - offset, + " %8u", st->st_uid); /* group id */ - offset += snprintf(&buffer[offset], buflen - offset, " %8u", st->st_gid); + offset += snprintf(&buffer[offset], buflen - offset, " %8u", + st->st_gid); #endif /* size */ - offset += snprintf(&buffer[offset], buflen - offset, " %8u", st->st_size); + offset += snprintf(&buffer[offset], buflen - offset, + " %8u", st->st_size); /* time */ @@ -2298,7 +2319,8 @@ static int ftpd_listbuffer(FAR struct ftpd_session_s *session, FAR char *path, temp[namelen] = '\0'; } - offset += snprintf(&buffer[offset], buflen - offset, " -> %s", temp); + offset += snprintf(&buffer[offset], buflen - offset, + " -> %s", temp); free(temp); } } @@ -2358,7 +2380,7 @@ static int fptd_listscan(FAR struct ftpd_session_s *session, FAR char *path, return -errval; } - for (;;) + for (; ; ) { entry = readdir(dir); if (!entry) @@ -2425,9 +2447,6 @@ static int ftpd_list(FAR struct ftpd_session_s *session, unsigned int opton) return ret; } -/**************************************************************************** - * Command Handlers - ****************************************************************************/ /**************************************************************************** * Name: ftpd_command_user ****************************************************************************/ @@ -2463,6 +2482,7 @@ static int ftpd_command_user(FAR struct ftpd_session_s *session) return ftpd_response(session->cmd.sd, session->txtimeout, g_respfmt1, 451, ' ', "Memory exhausted !"); } + session->flags |= FTPD_SESSIONFLAG_USER; /* If there is no account information, then no login is required. */ @@ -2482,6 +2502,7 @@ static int ftpd_command_user(FAR struct ftpd_session_s *session) { session->curr = NULL; } + return ret; } @@ -2498,6 +2519,7 @@ static int ftpd_command_user(FAR struct ftpd_session_s *session) { session->curr = NULL; } + return ret; } @@ -2531,6 +2553,7 @@ static int ftpd_command_pass(FAR struct ftpd_session_s *session) { session->curr = NULL; } + return ret; } @@ -2598,13 +2621,15 @@ static int ftpd_command_type(FAR struct ftpd_session_s *session) { session->type = FTPD_SESSIONTYPE_L8; return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 200, ' ', "Type set to L 8"); + g_respfmt1, 200, ' ', + "Type set to L 8"); } else { session->type = FTPD_SESSIONTYPE_NONE; return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 504, ' ', "Byte size must be 8 !"); + g_respfmt1, 504, ' ', + "Byte size must be 8 !"); } } } @@ -2748,7 +2773,8 @@ static int ftpd_command_port(FAR struct ftpd_session_s *session) session->data.addr.in4.sin_family = AF_INET; - utemp = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | (value[3]); + utemp = (value[0] << 24) | (value[1] << 16) | + (value[2] << 8) | (value[3]); session->data.addr.in4.sin_addr.s_addr = htonl(utemp); } @@ -2761,7 +2787,8 @@ static int ftpd_command_port(FAR struct ftpd_session_s *session) session->data.addr.in4.sin_family = AF_INET; - utemp = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | (value[3]); + utemp = (value[0] << 24) | (value[1] << 16) | + (value[2] << 8) | (value[3]); session->data.addr.in4.sin_addr.s_addr = htonl(utemp); } @@ -2805,6 +2832,7 @@ static int ftpd_command_eprt(FAR struct ftpd_session_s *session) "EPRT command not implemented !"); return -EINVAL; } + right--; while (session->param[left] != '\0') @@ -2814,6 +2842,7 @@ static int ftpd_command_eprt(FAR struct ftpd_session_s *session) left++; break; } + left++; } @@ -2837,15 +2866,15 @@ static int ftpd_command_eprt(FAR struct ftpd_session_s *session) for (index = 0; index < count && *str != '\0'; index++) { field[index] = ftpd_strtok_alloc(true, ",|)", &str); - if (!field[index]) - { - break; - } + if (!field[index]) + { + break; + } - if (*str != '\0') - { - str++; - } + if (*str != '\0') + { + str++; + } } if (index < count) @@ -2861,7 +2890,7 @@ static int ftpd_command_eprt(FAR struct ftpd_session_s *session) ftpd_response(session->cmd.sd, session->txtimeout, g_respfmt1, 502, ' ', "EPRT command not implemented !"); - return -EINVAL; + return -EINVAL; } ftpd_dataclose(session); @@ -2895,7 +2924,7 @@ static int ftpd_command_eprt(FAR struct ftpd_session_s *session) family = AF_UNSPEC; } - for (index = 0;index < count;index++) + for (index = 0; index < count; index++) { if (field[index]) { @@ -2968,9 +2997,10 @@ static int ftpd_command_rmd(FAR struct ftpd_session_s *session) ret = ftpd_getpath(session, session->param, &abspath, &workpath); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not remove directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not remove directory !"); + return ret; } if (strcmp(session->home, abspath) == 0) @@ -2978,9 +3008,10 @@ static int ftpd_command_rmd(FAR struct ftpd_session_s *session) free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not remove home directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not remove home directory !"); + return -EINVAL; } if (strcmp(session->work, workpath) == 0) @@ -2988,20 +3019,23 @@ static int ftpd_command_rmd(FAR struct ftpd_session_s *session) free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not remove current directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not remove current directory !"); + return -EINVAL; } ret = rmdir(abspath); if (ret < 0) { + ret = -errno; free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not remove directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not remove directory !"); + return ret; } free(abspath); @@ -3024,17 +3058,21 @@ static int ftpd_command_mkd(FAR struct ftpd_session_s *session) ret = ftpd_getpath(session, session->param, &abspath, NULL); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not make directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not make directory !"); + return ret; } - ret = mkdir(abspath, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + ret = mkdir(abspath, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | + S_IXGRP | S_IROTH | S_IXOTH); if (ret < 0) { + ret = -errno; free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "Can not make directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "Can not make directory !"); + return ret; } free(abspath); @@ -3055,8 +3093,9 @@ static int ftpd_command_dele(FAR struct ftpd_session_s *session) ret = ftpd_getpath(session, session->param, &abspath, &workpath); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "Can not delete file !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "Can not delete file !"); + return ret; } if (strcmp(session->home, abspath) == 0) @@ -3064,9 +3103,10 @@ static int ftpd_command_dele(FAR struct ftpd_session_s *session) free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not delete home directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not delete home directory !"); + return -EINVAL; } if (strcmp(session->work, workpath) == 0) @@ -3074,19 +3114,22 @@ static int ftpd_command_dele(FAR struct ftpd_session_s *session) free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not delete current directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not delete current directory !"); + return -EINVAL; } ret = unlink(abspath); if (ret < 0) { + ret = -errno; free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "Can not delete file !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "Can not delete file !"); + return ret; } free(abspath); @@ -3116,10 +3159,12 @@ static int ftpd_command_pasv(FAR struct ftpd_session_s *session) { ftpd_dataclose(session); return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 425, ' ', "PASV socket create fail !"); + g_respfmt1, 425, ' ', + "PASV socket create fail !"); } - ret = getsockname(session->cmd.sd, (FAR struct sockaddr *)&session->data.addr, + ret = getsockname(session->cmd.sd, + (FAR struct sockaddr *)&session->data.addr, &session->data.addrlen); if (ret < 0) { @@ -3129,28 +3174,29 @@ static int ftpd_command_pasv(FAR struct ftpd_session_s *session) } #ifdef CONFIG_NET_IPv6 - if (session->data.addr.ss.ss_family == AF_INET6) - { - /* Convert ipv6 to ipv4 */ + if (session->data.addr.ss.ss_family == AF_INET6) + { + /* Convert ipv6 to ipv4 */ - if ((IN6_IS_ADDR_V4MAPPED(&session->data.addr.in6.sin6_addr) != 0) || - (IN6_IS_ADDR_V4COMPAT(&session->data.addr.in6.sin6_addr) != 0)) - { - /* convert ipv6 to ipv4 */ + if ((IN6_IS_ADDR_V4MAPPED(&session->data.addr.in6.sin6_addr) != 0) || + (IN6_IS_ADDR_V4COMPAT(&session->data.addr.in6.sin6_addr) != 0)) + { + /* convert ipv6 to ipv4 */ - in_addr in4addr; + in_addr in4addr; - in4addr.s_addr = session->data.addr.in6.sin6_addr.s6_addr32[3]; + in4addr.s_addr = session->data.addr.in6.sin6_addr.s6_addr32[3]; - memset(&session->data.addr, 0, sizeof(session->data.addr)); - session->data.addr.in4.sin_family = AF_INET; - session->data.addr.in4.sin_addr.s_addr = in4addr.s_addr; + memset(&session->data.addr, 0, sizeof(session->data.addr)); + session->data.addr.in4.sin_family = AF_INET; + session->data.addr.in4.sin_addr.s_addr = in4addr.s_addr; } } #endif session->data.addr.in4.sin_port = 0; - ret = bind(session->data.sd, (FAR const struct sockaddr *)&session->data.addr, + ret = bind(session->data.sd, + (FAR const struct sockaddr *)&session->data.addr, session->data.addrlen); if (ret < 0) { @@ -3159,7 +3205,8 @@ static int ftpd_command_pasv(FAR struct ftpd_session_s *session) g_respfmt1, 425, ' ', "PASV bind fail !"); } - ret = getsockname(session->data.sd, (FAR struct sockaddr *)&session->data.addr, + ret = getsockname(session->data.sd, + (FAR struct sockaddr *)&session->data.addr, &session->data.addrlen); if (ret < 0) { @@ -3236,7 +3283,8 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) { #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) int ipv6only = 0; - setsockopt(session->data.sd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)); + setsockopt(session->data.sd, IPPROTO_IPV6, IPV6_V6ONLY, + &ipv6only, sizeof(ipv6only)); #endif } #else @@ -3251,8 +3299,9 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) return ret; } - ret = getsockname(session->cmd.sd, (FAR struct sockaddr *)&session->data.addr, - &session->data.addrlen); + ret = getsockname(session->cmd.sd, + (FAR struct sockaddr *)&session->data.addr, + &session->data.addrlen); if (ret < 0) { ret = ftpd_response(session->cmd.sd, session->txtimeout, @@ -3282,7 +3331,8 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) return ret; } - ret = bind(session->data.sd, (FAR const struct sockaddr *)&session->data.addr, + ret = bind(session->data.sd, + (FAR const struct sockaddr *)&session->data.addr, session->data.addrlen); if (ret < 0) { @@ -3292,7 +3342,8 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) return ret; } - ret = getsockname(session->data.sd, (FAR struct sockaddr *)&session->data.addr, + ret = getsockname(session->data.sd, + (FAR struct sockaddr *)&session->data.addr, &session->data.addrlen); if (ret < 0) { @@ -3315,7 +3366,8 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) if (session->data.addr.ss.ss_family == AF_INET6) { ret = ftpd_response(session->cmd.sd, session->txtimeout, - "%03u%cEntering Extended Passive Mode (|||%u|).\r\n", + "%03u%cEntering Extended Passive Mode " + "(|||%u|).\r\n", 229, ' ', ntohs(session->data.addr.in6.sin6_port)); if (ret < 0) @@ -3329,7 +3381,8 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) if (session->data.addr.ss.ss_family == AF_INET) { ret = ftpd_response(session->cmd.sd, session->txtimeout, - "%03u%cEntering Extended Passive Mode (|%u||%u|).\r\n", + "%03u%cEntering Extended Passive Mode " + "(|%u||%u|).\r\n", 229, ' ', 1, ntohs(session->data.addr.in4.sin_port)); if (ret < 0) @@ -3424,7 +3477,8 @@ static int ftpd_command_nlst(FAR struct ftpd_session_s *session) static int ftpd_command_acct(FAR struct ftpd_session_s *session) { return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 502, ' ', "ACCT command not implemented !"); + g_respfmt1, 502, ' ', + "ACCT command not implemented !"); } /**************************************************************************** @@ -3445,9 +3499,11 @@ static int ftpd_command_size(FAR struct ftpd_session_s *session) ret = ftpd_getpath(session, session->param, &abspath, NULL); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "Unknown size !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "Unknown size !"); + return ret; } + path = abspath; ret = 0; @@ -3473,7 +3529,8 @@ static int ftpd_command_size(FAR struct ftpd_session_s *session) else { ret = ftpd_response(session->cmd.sd, session->txtimeout, - "%03u%c%llu\r\n", 213, ' ', (unsigned long long)st.st_size); + "%03u%c%llu\r\n", 213, ' ', + (unsigned long long)st.st_size); } } break; @@ -3483,40 +3540,33 @@ static int ftpd_command_size(FAR struct ftpd_session_s *session) status = stat(path, &st); if (status < 0) { - ret = ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', session->param, - ": not a regular file."); - if (ret < 0) - { - return ret; - } + ret = -errno; + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', session->param, + ": not a regular file."); + goto errout_with_abspath; } else if (!S_ISREG(st.st_mode)) { ret = ftpd_response(session->cmd.sd, session->txtimeout, g_respfmt2, 550, ' ', session->param, ": not a regular file."); - if (ret < 0) - { - return ret; - } + ret = -EPERM; + goto errout_with_abspath; } - outstream = fopen(path, "r"); if (!outstream) { - ret = ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', session->param, - ": Can not open file !"); - if (ret < 0) - { - return ret; - } - } + ret = -errno; + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', session->param, + ": Can not open file !"); + goto errout_with_abspath; + } offset = 0; - for (;;) + for (; ; ) { ch = getc(outstream); if (ch == EOF) @@ -3527,23 +3577,27 @@ static int ftpd_command_size(FAR struct ftpd_session_s *session) { offset++; } + offset++; } fclose(outstream); ret = ftpd_response(session->cmd.sd, session->txtimeout, - "%03u%c%llu\r\n", 213, ' ', (unsigned long long)offset); + "%03u%c%llu\r\n", 213, ' ', + (unsigned long long)offset); } break; default: { ret = ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 504, ' ', "SIZE not implemented for type"); + g_respfmt1, 504, ' ', + "SIZE not implemented for type"); } break; } +errout_with_abspath: free(abspath); return ret; } @@ -3555,7 +3609,8 @@ static int ftpd_command_size(FAR struct ftpd_session_s *session) static int ftpd_command_stru(FAR struct ftpd_session_s *session) { return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 502, ' ', "STRU command not implemented !"); + g_respfmt1, 502, ' ', + "STRU command not implemented !"); } /**************************************************************************** @@ -3565,7 +3620,6 @@ static int ftpd_command_stru(FAR struct ftpd_session_s *session) static int ftpd_command_rnfr(FAR struct ftpd_session_s *session) { FAR char *abspath; - FAR char *path; struct stat st; int ret; @@ -3578,12 +3632,12 @@ static int ftpd_command_rnfr(FAR struct ftpd_session_s *session) ret = ftpd_getpath(session, session->param, &abspath, NULL); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "RNFR error !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "RNFR error !"); + return ret; } - path = abspath; - ret = stat(path, &st); + ret = stat(abspath, &st); if (ret < 0) { free(abspath); @@ -3612,22 +3666,26 @@ static int ftpd_command_rnto(FAR struct ftpd_session_s *session) { return ftpd_response(session->cmd.sd, session->txtimeout, g_respfmt1, 550, ' ', "RNTO error !"); + return ret; } ret = ftpd_getpath(session, session->param, &abspath, NULL); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "RNTO error !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "RNTO error !"); + return ret; } ret = rename(session->renamefrom, abspath); if (ret < 0) { + ret = -errno; free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', session->param, - ": Rename error."); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', session->param, + ": Rename error."); + return ret; } free(abspath); @@ -3641,7 +3699,7 @@ static int ftpd_command_rnto(FAR struct ftpd_session_s *session) static int ftpd_command_retr(FAR struct ftpd_session_s *session) { - return ftpd_stream(session, 0); + return ftpd_stream(session, 0); } /**************************************************************************** @@ -3650,7 +3708,7 @@ static int ftpd_command_retr(FAR struct ftpd_session_s *session) static int ftpd_command_stor(FAR struct ftpd_session_s *session) { - return ftpd_stream(session, 1); + return ftpd_stream(session, 1); } /**************************************************************************** @@ -3659,7 +3717,7 @@ static int ftpd_command_stor(FAR struct ftpd_session_s *session) static int ftpd_command_appe(FAR struct ftpd_session_s *session) { - return ftpd_stream(session, 2); + return ftpd_stream(session, 2); } /**************************************************************************** @@ -3669,14 +3727,14 @@ static int ftpd_command_appe(FAR struct ftpd_session_s *session) static int ftpd_command_rest(FAR struct ftpd_session_s *session) { #ifdef CONFIG_HAVE_LONG_LONG - session->restartpos = (off_t)atoll(session->param); + session->restartpos = (off_t)atoll(session->param); #else - session->restartpos = (off_t)atoi(session->param); + session->restartpos = (off_t)atoi(session->param); #endif - session->flags |= FTPD_SESSIONFLAG_RESTARTPOS; + session->flags |= FTPD_SESSIONFLAG_RESTARTPOS; - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 320, ' ', "Restart position ready"); + return ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 320, ' ', "Restart position ready"); } /**************************************************************************** @@ -3692,28 +3750,33 @@ static int ftpd_command_mdtm(FAR struct ftpd_session_s *session) int ret; ret = ftpd_getpath(session, session->param, &abspath, NULL); - if (ret <0) + if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "Unknown size !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "Unknown size !"); + return ret; } + path = abspath; ret = stat(path, &st); if (ret < 0) { + ret = -errno; free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', session->param, - ": not a plain file."); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', session->param, + ": not a plain file."); + return ret; } - if (!S_ISREG(st.st_mode)) - { - free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', session->param, - ": not a plain file."); + if (!S_ISREG(st.st_mode)) + { + free(abspath); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', session->param, + ": not a plain file."); + return -EISDIR; } free(abspath); @@ -3751,6 +3814,7 @@ static int ftpd_command_opts(FAR struct ftpd_session_s *session) *str = '\0'; str++; } + value = str; if (strcasecmp(option, "UTF8") == 0 || strcasecmp(option, "UTF-8") == 0) @@ -3760,10 +3824,11 @@ static int ftpd_command_opts(FAR struct ftpd_session_s *session) if (value[0] == '\0' || strcasecmp(value, "ON") == 0 || strcasecmp(value, "ENABLE") == 0 || strcasecmp(value, "TRUE") == 0) { - remote = true; + remote = true; } - else { - remote = false; + else + { + remote = false; } lang = getenv("LANG"); @@ -3807,7 +3872,8 @@ static int ftpd_command_opts(FAR struct ftpd_session_s *session) static int ftpd_command_site(FAR struct ftpd_session_s *session) { return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 502, ' ', "SITE command not implemented !"); + g_respfmt1, 502, ' ', + "SITE command not implemented !"); } /**************************************************************************** @@ -3903,6 +3969,7 @@ static int ftpd_command(FAR struct ftpd_session_s *session) /**************************************************************************** * Worker Thread ****************************************************************************/ + /**************************************************************************** * Name: ftpd_startworker ****************************************************************************/ @@ -4071,7 +4138,7 @@ static FAR void *ftpd_worker(FAR void *arg) /* Then loop processing FTP commands */ - for (;;) + for (; ; ) { /* Receive the next command */ @@ -4103,12 +4170,13 @@ static FAR void *ftpd_worker(FAR void *arg) while (recvbytes > 0) { ch = session->cmd.buffer[offset]; - if (ch != 0xff && ch != 0xf4 && ch != 0xf2) - { - break; - } + if (ch != 0xff && ch != 0xf4 && ch != 0xf2) + { + break; + } - ftpd_send(session->cmd.sd, &session->cmd.buffer[offset], 1, session->txtimeout); + ftpd_send(session->cmd.sd, &session->cmd.buffer[offset], 1, + session->txtimeout); offset++; recvbytes--; @@ -4132,6 +4200,7 @@ static FAR void *ftpd_worker(FAR void *arg) session->cmd.buffer[offset] = '\0'; break; } + offset++; } @@ -4302,7 +4371,8 @@ int ftpd_session(FTPD_SESSION handle, int timeout) /* Allocate a session */ - session = (FAR struct ftpd_session_s *)zalloc(sizeof(struct ftpd_session_s)); + session = (FAR struct ftpd_session_s *) + zalloc(sizeof(struct ftpd_session_s)); if (!session) { nerr("ERROR: Failed to allocate session\n"); @@ -4370,6 +4440,7 @@ int ftpd_session(FTPD_SESSION handle, int timeout) nerr("ERROR: ftpd_accept() failed: %d\n", session->cmd.sd); } #endif + ret = session->cmd.sd; goto errout_with_session; }