summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2001-03-05 23:01:43 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2001-03-05 23:01:43 +0000
commit07fbfcedf04e1d64472ad508c81207c782e021e1 (patch)
treede231bf8d489af1a8f4a04848ce07737a1c23cf9
parent2001-02-18 Ralf Corsepiu <corsepius@faw.uni-ulm.de> (diff)
downloadrtems-07fbfcedf04e1d64472ad508c81207c782e021e1.tar.bz2
2001-01-31 Sergei Organov <osv@javad.ru>
* rtems_servers/ftp.d: Following changes: - Hacks with current dir and root dir removed in favor of new libio support for task-local current and root directories. - Bug in `close_data_socket()' introduced by previous change fixed. - `command_pasv()' changed to set timeout on socket we are listening on and code fixed to don't close socket twice on error. - `serr()' changed to clear `errno'. - `data_socket()' changed to clear `errno' before `bind()'. - `session()' changed to clear `errno' before processing session. - `close_data_socket()' fixed to close both active and passive sockets - Initialize info->data_socket to -1 in `daemon()' - Initialize `fname' to empty string in `exec_command()'
-rw-r--r--c/src/exec/libnetworking/ChangeLog15
-rw-r--r--c/src/libnetworking/ChangeLog15
-rw-r--r--c/src/libnetworking/rtems_servers/ftpd.c426
-rw-r--r--cpukit/ftpd/ftpd.c426
-rw-r--r--cpukit/libnetworking/ChangeLog15
5 files changed, 367 insertions, 530 deletions
diff --git a/c/src/exec/libnetworking/ChangeLog b/c/src/exec/libnetworking/ChangeLog
index 1df7067298..8b8215ab06 100644
--- a/c/src/exec/libnetworking/ChangeLog
+++ b/c/src/exec/libnetworking/ChangeLog
@@ -1,3 +1,18 @@
+2001-01-31 Sergei Organov <osv@javad.ru>
+
+ * rtems_servers/ftp.d: Following changes:
+ - Hacks with current dir and root dir removed in favor of new libio
+ support for task-local current and root directories.
+ - Bug in `close_data_socket()' introduced by previous change fixed.
+ - `command_pasv()' changed to set timeout on socket we are listening
+ on and code fixed to don't close socket twice on error.
+ - `serr()' changed to clear `errno'.
+ - `data_socket()' changed to clear `errno' before `bind()'.
+ - `session()' changed to clear `errno' before processing session.
+ - `close_data_socket()' fixed to close both active and passive sockets
+ - Initialize info->data_socket to -1 in `daemon()'
+ - Initialize `fname' to empty string in `exec_command()'
+
2001-02-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* Makefile.am, arpa/Makefile.am, machine/Makefile.am, net/Makefile.am,
diff --git a/c/src/libnetworking/ChangeLog b/c/src/libnetworking/ChangeLog
index 1df7067298..8b8215ab06 100644
--- a/c/src/libnetworking/ChangeLog
+++ b/c/src/libnetworking/ChangeLog
@@ -1,3 +1,18 @@
+2001-01-31 Sergei Organov <osv@javad.ru>
+
+ * rtems_servers/ftp.d: Following changes:
+ - Hacks with current dir and root dir removed in favor of new libio
+ support for task-local current and root directories.
+ - Bug in `close_data_socket()' introduced by previous change fixed.
+ - `command_pasv()' changed to set timeout on socket we are listening
+ on and code fixed to don't close socket twice on error.
+ - `serr()' changed to clear `errno'.
+ - `data_socket()' changed to clear `errno' before `bind()'.
+ - `session()' changed to clear `errno' before processing session.
+ - `close_data_socket()' fixed to close both active and passive sockets
+ - Initialize info->data_socket to -1 in `daemon()'
+ - Initialize `fname' to empty string in `exec_command()'
+
2001-02-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* Makefile.am, arpa/Makefile.am, machine/Makefile.am, net/Makefile.am,
diff --git a/c/src/libnetworking/rtems_servers/ftpd.c b/c/src/libnetworking/rtems_servers/ftpd.c
index ec3627523b..f238bd8654 100644
--- a/c/src/libnetworking/rtems_servers/ftpd.c
+++ b/c/src/libnetworking/rtems_servers/ftpd.c
@@ -15,6 +15,26 @@
*
* Changes:
*
+ * 2001-01-31 Sergei Organov <osv@javad.ru>
+ *
+ * * Hacks with current dir and root dir removed in favor of new libio
+ * support for task-local current and root directories.
+ *
+ * 2001-01-30 Sergei Organov <osv@javad.ru>
+ *
+ * * Bug in `close_data_socket()' introduced by previous change fixed.
+ * * `command_pasv()' changed to set timeout on socket we are listening on
+ * and code fixed to don't close socket twice on error.
+ * * `serr()' changed to clear `errno'.
+ * * `data_socket()' changed to clear `errno' before `bind()'.
+ * * `session()' changed to clear `errno' before processing session.
+ *
+ * 2001-01-29 Sergei Organov <osv@javad.ru>
+ *
+ * * `close_data_socket()' fixed to close both active and passive sockets
+ * * Initialize info->data_socket to -1 in `daemon()'
+ * * Initialize `fname' to empty string in `exec_command()'
+ *
* 2001-01-22 Sergei Organov <osv@javad.ru>
*
* * Timeouts on sockets implemented. 'idle' field added to
@@ -169,6 +189,7 @@
#include <rtems.h>
#include <rtems/rtems_bsdnet.h>
#include <rtems/error.h>
+#include <rtems/libio.h>
#include <syslog.h>
#include <sys/types.h>
@@ -235,7 +256,6 @@ typedef struct
int pasv_socket; /* Socket for PASV connection */
int data_socket; /* Socket for data connection */
int idle; /* Timeout in seconds */
- char cwd[FTPD_BUFSIZE]; /* Current working directory */
int xfer_mode; /* Transfer mode (ASCII/binary) */
rtems_id tid; /* Task id */
} FTPD_SessionInfo_t;
@@ -261,10 +281,10 @@ typedef struct
static FTPD_TaskPool_t task_pool;
/*
- * Root node for FTPD without trailing slash. Even '/' node is denoted as
- * empty string here.
+ * Root directory
*/
-static char ftpd_root[FTPD_BUFSIZE];
+
+static char const* ftpd_root = "/";
/*
* Default idle timeout for sockets in seconds.
@@ -286,7 +306,9 @@ static int ftpd_access = 0;
static char const*
serr(void)
{
- return strerror(errno);
+ int err = errno;
+ errno = 0;
+ return strerror(err);
}
/*PAGE
@@ -309,172 +331,6 @@ can_write(void)
/*PAGE
*
- * Utility routines to manage root directory and session local
- * current working directory.
- *
- */
-
-
-/*PAGE
- *
- * is_dir
- *
- * Return 1 if file with given 'name' exists and is directory, 0 otherwise.
- *
- */
-static int
-is_dir(char const* name)
-{
- struct stat s;
- int res = stat(name, &s) == 0 && S_ISDIR(s.st_mode);
- return res;
-}
-
-/*PAGE
- *
- * squeeze_path
- *
- * Squeezes path according to OS rules, i.e., eliminates /./, /../, and //
- * from the path. Does nothing if the path is relative, i.e. doesn't begin
- * with '/'. The trailing slash is always removed, even when alone, i.e. "/"
- * will be "" after squeeze.
- *
- * Input parameters:
- * path - the path to be squeezed
- * full - full file name or NULL (assumed that it points to the beginning of
- * buffer, and 'path' also points somewhere into the same buffer). Is
- * used to check if intermediate names are directories.
- *
- * Output parameters:
- * path - squeezed path
- * returns 1 on success, 0 on failure (if any name that supposed to denote
- * directory is not a directory).
- *
- */
-static int
-squeeze_path(char* path, char* full)
-{
- if(path[0] == '/')
- {
- char* e = path + 1;
- int rest = strlen(e);
- while(rest >= 0)
- {
- int len;
- char* s = e;
- e = strchr(s, '/');
- if(e)
- {
- char c = *e;
- *e = '\0';
- if(full && !is_dir(full))
- {
- *e = c;
- return 0;
- }
- *e++ = c;
- }
- else
- e = s + rest + 1;
- len = e - s;
- rest -= len;
- if(len == 1 || (len == 2 && s[0] == '.'))
- {
- if(rest >= 0)
- memmove(s, e, rest + 1);
- else
- *s++ = '\0';
- e = s;
- }
- else if(len == 3 && s[0] == '.' && s[1] == '.')
- {
- char* ps = s;
- if(ps - 1 > path) {
- do
- --ps;
- while(ps[-1] != '/');
- }
- if(rest >= 0)
- memmove(ps, e, rest + 1);
- else
- *ps++ = '\0';
- e = ps;
- }
- }
- if(e[-2] == '/')
- {
- e[-2] = '\0';
- if(full && !is_dir(full))
- return 0;
- }
- }
- return 1;
-}
-
-
-/*PAGE
- *
- * make_path
- *
- * Makes full path given file name, current working directory and root
- * directory (file scope variable 'root').
- *
- * Input parameters:
- * cwd - current working directory
- * name - file name
- * root (file scope variable) - FTPD root directory
- *
- * Output parameters:
- * buf - full path
- * returns pointer to non-root part of the 'buf', i.e. to first character
- * different from '/' after root part.
- *
- */
-static char const*
-make_path(char* buf, char const* cwd, char const* name)
-{
- char* res = NULL;
-
- int rlen = strlen(ftpd_root);
- int clen = strlen(cwd);
- int nlen = strlen(name);
- int len = rlen + nlen;
-
- if (name[0] != '/')
- {
- ++len;
- if (clen > 0)
- len += clen + 1;
- }
-
- if (FTPD_BUFSIZE > len)
- {
- char* b = buf;
- memcpy(b, ftpd_root, rlen); b += rlen;
- if (name[0] != '/')
- {
- *b++ = '/';
- if (clen > 0)
- {
- memcpy(b, cwd, clen); b += clen;
- *b++ = '/';
- }
- }
- memcpy(b, name, nlen); b += nlen;
- *b = '\0';
-
- res = buf + rlen;
- while(rlen-- > 0 && res[-1] == '/')
- --res;
- if(!squeeze_path(res, buf))
- res = NULL;
- }
-
- return res;
-}
-
-/*PAGE
- *
* Task pool management routines
*
*/
@@ -602,8 +458,6 @@ task_pool_init(int count, rtems_task_priority priority)
return 0;
}
task_pool.queue[i] = task_pool.info + i;
- info->ctrl_fp = NULL;
- info->ctrl_socket = -1;
if (++id > 'z')
id = 'a';
}
@@ -637,8 +491,6 @@ task_pool_obtain()
info = task_pool.queue[task_pool.head];
if(++task_pool.head >= task_pool.count)
task_pool.head = 0;
- info->ctrl_socket = -1;
- info->ctrl_fp = NULL;
rtems_semaphore_release(task_pool.mutex);
}
return info;
@@ -800,6 +652,7 @@ data_socket(FTPD_SessionInfo_t *info)
data_source.sin_port = htons(20); /* ftp-data port */
for(tries = 1; tries < 10; ++tries)
{
+ errno = 0;
if(bind(s, (struct sockaddr *)&data_source, sizeof(data_source)) >= 0)
break;
if (errno != EADDRINUSE)
@@ -849,9 +702,11 @@ data_socket(FTPD_SessionInfo_t *info)
static void
close_data_socket(FTPD_SessionInfo_t *info)
{
- int s = info->pasv_socket;
+ /* As at most one data socket could be open simultaneously and in some cases
+ data_socket == pasv_socket, we select socket to close, then close it. */
+ int s = info->data_socket;
if(0 > s)
- s = info->data_socket;
+ s = info->pasv_socket;
if(!close_socket(s))
syslog(LOG_ERR, "ftpd: Error closing data socket.");
info->data_socket = -1;
@@ -936,7 +791,6 @@ command_retrieve(FTPD_SessionInfo_t *info, char const *filename)
int fd = -1;
char buf[FTPD_DATASIZE];
int res = 0;
- char const* r = NULL;
if(!can_read())
{
@@ -944,9 +798,7 @@ command_retrieve(FTPD_SessionInfo_t *info, char const *filename)
return;
}
- r = make_path(buf, info->cwd, filename);
-
- if (NULL == r || 0 > (fd = open(buf, O_RDONLY)))
+ if (0 > (fd = open(filename, O_RDONLY)))
{
send_reply(info, 550, "Error opening file.");
return;
@@ -1030,6 +882,29 @@ command_retrieve(FTPD_SessionInfo_t *info, char const *filename)
/*PAGE
*
+ * discard
+ *
+ * Analog of `write' routine that just discards passed data
+ *
+ * Input parameters:
+ * fd - file descriptor (ignored)
+ * buf - data to write (ignored)
+ * count - number of bytes in `buf'
+ *
+ * Output parameters:
+ * returns `count'
+ *
+ */
+static ssize_t
+discard(int fd, void const* buf, size_t count)
+{
+ (void)fd;
+ (void)buf;
+ return count;
+}
+
+/*PAGE
+ *
* command_store
*
* Performs the "STOR" command (receive data from client).
@@ -1051,8 +926,9 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
char buf[FTPD_DATASIZE];
int res = 1;
int bare_lfs = 0;
-
- int null = !strcmp("/dev/null", filename);
+ int null = 0;
+ typedef ssize_t (*WriteProc)(int, void const*, size_t);
+ WriteProc wrt = &write;
if(!can_write())
{
@@ -1060,33 +936,23 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
return;
}
- if(!null)
- {
- if (NULL == make_path(buf, info->cwd, filename))
- {
- send_reply(info, 550, "Error creating file.");
- return;
- }
- }
-
send_mode_reply(info);
s = data_socket(info);
if(0 > s)
return;
-
+ null = !strcmp("/dev/null", filename);
if (null)
{
/* File "/dev/null" just throws data away.
- * FIXME: this is hack. Using /dev/null filesystem entry would be
- * better. However, it's not clear how to handle root directory other
- * than '/' then.
+ * FIXME: this is hack. Using `/dev/null' filesystem entry would be
+ * better.
*/
- while ((n = recv(s, buf, FTPD_DATASIZE, 0)) > 0)
- ;
+ wrt = &discard;
}
- else if (rtems_ftpd_configuration.hooks != NULL)
+
+ if (!null && rtems_ftpd_configuration.hooks != NULL)
{
/* Search our list of hooks to see if we need to do something special. */
@@ -1159,9 +1025,12 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
}
else
{
- /* Data transfer to regular file. */
- int fd =
- creat(buf, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ /* Data transfer to regular file or /dev/null. */
+ int fd = 0;
+
+ if(!null)
+ fd = creat(filename,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (0 > fd)
{
@@ -1174,7 +1043,7 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
{
while ((n = recv(s, buf, FTPD_DATASIZE, 0)) > 0)
{
- if (write(fd, buf, n) != n)
+ if (wrt(fd, buf, n) != n)
{
res = 0;
break;
@@ -1196,7 +1065,7 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
{
char const lf = '\r';
pended_cr = 0;
- if(write(fd, &lf, 1) != 1)
+ if(wrt(fd, &lf, 1) != 1)
{
res = 0;
break;
@@ -1231,12 +1100,12 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
if(res == 0)
break;
count = i - sub - pended_cr;
- if(count > 0 && write(fd, b, count) != count)
+ if(count > 0 && wrt(fd, b, count) != count)
{
res = 0;
break;
}
- if(sub == 2 && write(fd, e - 1, 1) != 1)
+ if(sub == 2 && wrt(fd, e - 1, 1) != 1)
res = 0;
}
while((rest -= i) > 0);
@@ -1384,10 +1253,7 @@ command_list(FTPD_SessionInfo_t *info, char const *fname, int wide)
struct dirent *dp = 0;
struct stat stat_buf;
char buf[FTPD_BUFSIZE];
- char path[FTPD_BUFSIZE];
time_t curTime;
- char const* res;
- char const* cwd = info->cwd;
int sc = 1;
send_reply(info, 150, "Opening ASCII mode data connection for LIST.");
@@ -1402,15 +1268,13 @@ command_list(FTPD_SessionInfo_t *info, char const *fname, int wide)
if(fname[0] == '\0')
fname = ".";
- res = make_path(path, cwd, fname);
-
- if (NULL == res || 0 > stat(path, &stat_buf))
+ if (0 > stat(fname, &stat_buf))
{
snprintf(buf, FTPD_BUFSIZE,
"%s: No such file or directory.\r\n", fname);
send(s, buf, strlen(buf), 0);
}
- else if (S_ISDIR(stat_buf.st_mode) && (NULL == (dirp = opendir(path))))
+ else if (S_ISDIR(stat_buf.st_mode) && (NULL == (dirp = opendir(fname))))
{
snprintf(buf, FTPD_BUFSIZE,
"%s: Can not open directory.\r\n", fname);
@@ -1420,15 +1284,15 @@ command_list(FTPD_SessionInfo_t *info, char const *fname, int wide)
{
time(&curTime);
if(!dirp && *fname)
- sc = sc && send_dirline(s, wide, curTime, path, "", fname, buf);
+ sc = sc && send_dirline(s, wide, curTime, fname, "", fname, buf);
else {
/* FIXME: need "." and ".." only when '-a' option is given */
- sc = sc && send_dirline(s, wide, curTime, path, "", ".", buf);
- sc = sc && send_dirline(s, wide, curTime, path,
- (strcmp(path, ftpd_root) ? ".." : ""), "..", buf);
+ sc = sc && send_dirline(s, wide, curTime, fname, "", ".", buf);
+ sc = sc && send_dirline(s, wide, curTime, fname,
+ (strcmp(fname, ftpd_root) ? ".." : ""), "..", buf);
while (sc && (dp = readdir(dirp)) != NULL)
sc = sc &&
- send_dirline(s, wide, curTime, path, dp->d_name, dp->d_name, buf);
+ send_dirline(s, wide, curTime, fname, dp->d_name, dp->d_name, buf);
}
}
@@ -1445,38 +1309,64 @@ command_list(FTPD_SessionInfo_t *info, char const *fname, int wide)
/*PAGE
*
- * rtems_ftpd_cwd
+ * command_cwd
*
- * Change current working directory. We use 'chdir' here only to validate the
- * new directory. We keep track of current working directory ourselves because
- * current working directory in RTEMS isn't thread local, but we need it to be
- * session local.
+ * Change current working directory.
*
* Input parameters:
* info - corresponding SessionInfo structure
* dir - directory name passed in CWD command
*
* Output parameters:
- * info->cwd is set to new CWD value.
+ * NONE
*
*/
static void
-rtems_ftpd_cwd(FTPD_SessionInfo_t *info, char *dir)
+command_cwd(FTPD_SessionInfo_t *info, char *dir)
{
- char buf[FTPD_BUFSIZE];
- char const* cwd = make_path(buf, info->cwd, dir);
- if(cwd && chdir(buf) == 0)
- {
+ if(chdir(dir) == 0)
send_reply(info, 250, "CWD command successful.");
- strcpy(info->cwd, cwd);
- }
else
- {
send_reply(info, 550, "CWD command failed.");
- }
}
+/*PAGE
+ *
+ * command_pwd
+ *
+ * Send current working directory to client.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ *
+ * Output parameters:
+ * NONE
+ */
+static void
+command_pwd(FTPD_SessionInfo_t *info)
+{
+ char buf[FTPD_BUFSIZE];
+ char const* cwd;
+ errno = 0;
+ buf[0] = '"';
+ cwd = getcwd(buf + 1, FTPD_BUFSIZE - 4);
+ if(cwd)
+ {
+ int len = strlen(cwd);
+ static char const txt[] = "\" is the current directory.";
+ int size = sizeof(txt);
+ if(len + size + 1 >= FTPD_BUFSIZE)
+ size = FTPD_BUFSIZE - len - 2;
+ memcpy(buf + len + 1, txt, size);
+ buf[len + size] = '\0';
+ send_reply(info, 250, buf);
+ }
+ else {
+ snprintf(buf, FTPD_BUFSIZE, "Error: %s.", serr());
+ send_reply(info, 452, buf);
+ }
+}
/*PAGE
*
@@ -1497,7 +1387,7 @@ command_mdtm(FTPD_SessionInfo_t *info, char const* fname)
struct stat stbuf;
char buf[FTPD_BUFSIZE];
- if (NULL == make_path(buf, info->cwd, fname) || 0 > stat(buf, &stbuf))
+ if (0 > stat(fname, &stbuf))
{
snprintf(buf, FTPD_BUFSIZE, "%s: %s.", fname, serr());
send_reply(info, 550, buf);
@@ -1614,7 +1504,7 @@ command_pasv(FTPD_SessionInfo_t *info)
syslog(LOG_ERR, "ftpd: Error binding PASV socket: %s", serr());
else if (0 > listen(s, 1))
syslog(LOG_ERR, "ftpd: Error listening on PASV socket: %s", serr());
- else
+ else if(set_socket_timeout(s, info->idle))
{
char buf[FTPD_BUFSIZE];
unsigned char const *ip, *p;
@@ -1627,11 +1517,14 @@ command_pasv(FTPD_SessionInfo_t *info)
send_reply(info, 227, buf);
info->pasv_socket = accept(s, (struct sockaddr *)&addr, &addrLen);
- close_socket(s);
if (0 > info->pasv_socket)
syslog(LOG_ERR, "ftpd: Error accepting PASV connection: %s", serr());
else
+ {
+ close_socket(s);
+ s = -1;
err = 0;
+ }
}
}
if(err)
@@ -1746,17 +1639,18 @@ split_command(char *buf, char **cmd, char **opts, char **args)
* info - corresponding SessionInfo structure
* cmd - command to be executed (upper-case)
* args - arguments of the command
- * buf - beginning of buffer where 'cmd' and 'args' reside.
*
* Output parameters:
* NONE
*/
static void
-exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
+exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args)
{
char fname[FTPD_BUFSIZE];
int wrong_command = 0;
+ fname[0] = '\0';
+
if (!strcmp("PORT", cmd))
{
command_port(info, args);
@@ -1824,8 +1718,7 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
}
else if (
1 == sscanf(args, "%254s", fname) &&
- NULL != make_path(buf, info->cwd, fname) &&
- unlink(buf) == 0)
+ unlink(fname) == 0)
{
send_reply(info, 257, "DELE successful.");
}
@@ -1848,8 +1741,7 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
}
else if(
2 == sscanf(args, "%o %254s", &mask, fname) &&
- NULL != make_path(buf, info->cwd, fname) &&
- chmod(buf, (mode_t)mask) == 0)
+ chmod(fname, (mode_t)mask) == 0)
{
send_reply(info, 257, "CHMOD successful.");
}
@@ -1869,8 +1761,7 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
}
else if (
1 == sscanf(args, "%254s", fname) &&
- NULL != make_path(buf, info->cwd, fname) &&
- rmdir(buf) == 0)
+ rmdir(fname) == 0)
{
send_reply(info, 257, "RMD successful.");
}
@@ -1887,8 +1778,7 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
}
else if (
1 == sscanf(args, "%254s", fname) &&
- NULL != make_path(buf, info->cwd, fname) &&
- mkdir(buf, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
{
send_reply(info, 257, "MKD successful.");
}
@@ -1900,20 +1790,15 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
else if (!strcmp("CWD", cmd))
{
sscanf(args, "%254s", fname);
- rtems_ftpd_cwd(info, fname);
+ command_cwd(info, fname);
}
else if (!strcmp("CDUP", cmd))
{
- rtems_ftpd_cwd(info, "..");
+ command_cwd(info, "..");
}
else if (!strcmp("PWD", cmd))
{
- char const* cwd = "/";
- if(info->cwd[0])
- cwd = info->cwd;
- snprintf(buf, FTPD_BUFSIZE,
- "\"%s\" is the current directory.", cwd);
- send_reply(info, 250, buf);
+ command_pwd(info);
}
else
wrong_command = 1;
@@ -1943,14 +1828,26 @@ static void
session(rtems_task_argument arg)
{
FTPD_SessionInfo_t *const info = (FTPD_SessionInfo_t *)arg;
+ int chroot_made = 0;
+
+ rtems_libio_set_private_env();
+
+ /* chroot() can fail here because the directory may not exist yet. */
+ chroot_made = chroot(ftpd_root) == 0;
while(1)
{
rtems_event_set set;
+ char buf[128];
rtems_event_receive(FTPD_RTEMS_EVENT, RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT,
&set);
+ chroot_made = chroot_made || chroot(ftpd_root) == 0;
+ chdir("/");
+
+ errno = 0;
+
send_reply(info, 220, FTPD_SERVER_MESSAGE);
while (1)
@@ -1973,7 +1870,7 @@ session(rtems_task_argument arg)
}
else
{
- exec_command(info, cmd, args, buf);
+ exec_command(info, cmd, args);
}
}
@@ -2061,8 +1958,8 @@ daemon()
info->use_default = 1;
info->ctrl_addr = addr;
info->pasv_socket = -1;
- info->xfer_mode = TYPE_A;
- info->cwd[0] = '\0';
+ info->data_socket = -1;
+ info->xfer_mode = TYPE_A;
info->data_addr.sin_port =
htons(ntohs(info->ctrl_addr.sin_port) - 1);
info->idle = ftpd_timeout;
@@ -2149,18 +2046,17 @@ rtems_initialize_ftpd()
return RTEMS_UNSATISFIED;
}
- ftpd_root[0] = '\0';
+ ftpd_root = "/";
if (
rtems_ftpd_configuration.root &&
- strlen(rtems_ftpd_configuration.root) < FTPD_BUFSIZE &&
- rtems_ftpd_configuration.root[0] == '/')
- {
- strcpy(ftpd_root, rtems_ftpd_configuration.root);
- squeeze_path(ftpd_root, NULL);
- rtems_ftpd_configuration.root = ftpd_root;
- }
+ rtems_ftpd_configuration.root[0] == '/'
+ )
+ ftpd_root = rtems_ftpd_configuration.root;
+
+ rtems_ftpd_configuration.root = ftpd_root;
syslog(LOG_INFO, "ftpd: FTP daemon started (%d session%s max)",
count, ((count > 1) ? "s" : ""));
+
return RTEMS_SUCCESSFUL;
}
diff --git a/cpukit/ftpd/ftpd.c b/cpukit/ftpd/ftpd.c
index ec3627523b..f238bd8654 100644
--- a/cpukit/ftpd/ftpd.c
+++ b/cpukit/ftpd/ftpd.c
@@ -15,6 +15,26 @@
*
* Changes:
*
+ * 2001-01-31 Sergei Organov <osv@javad.ru>
+ *
+ * * Hacks with current dir and root dir removed in favor of new libio
+ * support for task-local current and root directories.
+ *
+ * 2001-01-30 Sergei Organov <osv@javad.ru>
+ *
+ * * Bug in `close_data_socket()' introduced by previous change fixed.
+ * * `command_pasv()' changed to set timeout on socket we are listening on
+ * and code fixed to don't close socket twice on error.
+ * * `serr()' changed to clear `errno'.
+ * * `data_socket()' changed to clear `errno' before `bind()'.
+ * * `session()' changed to clear `errno' before processing session.
+ *
+ * 2001-01-29 Sergei Organov <osv@javad.ru>
+ *
+ * * `close_data_socket()' fixed to close both active and passive sockets
+ * * Initialize info->data_socket to -1 in `daemon()'
+ * * Initialize `fname' to empty string in `exec_command()'
+ *
* 2001-01-22 Sergei Organov <osv@javad.ru>
*
* * Timeouts on sockets implemented. 'idle' field added to
@@ -169,6 +189,7 @@
#include <rtems.h>
#include <rtems/rtems_bsdnet.h>
#include <rtems/error.h>
+#include <rtems/libio.h>
#include <syslog.h>
#include <sys/types.h>
@@ -235,7 +256,6 @@ typedef struct
int pasv_socket; /* Socket for PASV connection */
int data_socket; /* Socket for data connection */
int idle; /* Timeout in seconds */
- char cwd[FTPD_BUFSIZE]; /* Current working directory */
int xfer_mode; /* Transfer mode (ASCII/binary) */
rtems_id tid; /* Task id */
} FTPD_SessionInfo_t;
@@ -261,10 +281,10 @@ typedef struct
static FTPD_TaskPool_t task_pool;
/*
- * Root node for FTPD without trailing slash. Even '/' node is denoted as
- * empty string here.
+ * Root directory
*/
-static char ftpd_root[FTPD_BUFSIZE];
+
+static char const* ftpd_root = "/";
/*
* Default idle timeout for sockets in seconds.
@@ -286,7 +306,9 @@ static int ftpd_access = 0;
static char const*
serr(void)
{
- return strerror(errno);
+ int err = errno;
+ errno = 0;
+ return strerror(err);
}
/*PAGE
@@ -309,172 +331,6 @@ can_write(void)
/*PAGE
*
- * Utility routines to manage root directory and session local
- * current working directory.
- *
- */
-
-
-/*PAGE
- *
- * is_dir
- *
- * Return 1 if file with given 'name' exists and is directory, 0 otherwise.
- *
- */
-static int
-is_dir(char const* name)
-{
- struct stat s;
- int res = stat(name, &s) == 0 && S_ISDIR(s.st_mode);
- return res;
-}
-
-/*PAGE
- *
- * squeeze_path
- *
- * Squeezes path according to OS rules, i.e., eliminates /./, /../, and //
- * from the path. Does nothing if the path is relative, i.e. doesn't begin
- * with '/'. The trailing slash is always removed, even when alone, i.e. "/"
- * will be "" after squeeze.
- *
- * Input parameters:
- * path - the path to be squeezed
- * full - full file name or NULL (assumed that it points to the beginning of
- * buffer, and 'path' also points somewhere into the same buffer). Is
- * used to check if intermediate names are directories.
- *
- * Output parameters:
- * path - squeezed path
- * returns 1 on success, 0 on failure (if any name that supposed to denote
- * directory is not a directory).
- *
- */
-static int
-squeeze_path(char* path, char* full)
-{
- if(path[0] == '/')
- {
- char* e = path + 1;
- int rest = strlen(e);
- while(rest >= 0)
- {
- int len;
- char* s = e;
- e = strchr(s, '/');
- if(e)
- {
- char c = *e;
- *e = '\0';
- if(full && !is_dir(full))
- {
- *e = c;
- return 0;
- }
- *e++ = c;
- }
- else
- e = s + rest + 1;
- len = e - s;
- rest -= len;
- if(len == 1 || (len == 2 && s[0] == '.'))
- {
- if(rest >= 0)
- memmove(s, e, rest + 1);
- else
- *s++ = '\0';
- e = s;
- }
- else if(len == 3 && s[0] == '.' && s[1] == '.')
- {
- char* ps = s;
- if(ps - 1 > path) {
- do
- --ps;
- while(ps[-1] != '/');
- }
- if(rest >= 0)
- memmove(ps, e, rest + 1);
- else
- *ps++ = '\0';
- e = ps;
- }
- }
- if(e[-2] == '/')
- {
- e[-2] = '\0';
- if(full && !is_dir(full))
- return 0;
- }
- }
- return 1;
-}
-
-
-/*PAGE
- *
- * make_path
- *
- * Makes full path given file name, current working directory and root
- * directory (file scope variable 'root').
- *
- * Input parameters:
- * cwd - current working directory
- * name - file name
- * root (file scope variable) - FTPD root directory
- *
- * Output parameters:
- * buf - full path
- * returns pointer to non-root part of the 'buf', i.e. to first character
- * different from '/' after root part.
- *
- */
-static char const*
-make_path(char* buf, char const* cwd, char const* name)
-{
- char* res = NULL;
-
- int rlen = strlen(ftpd_root);
- int clen = strlen(cwd);
- int nlen = strlen(name);
- int len = rlen + nlen;
-
- if (name[0] != '/')
- {
- ++len;
- if (clen > 0)
- len += clen + 1;
- }
-
- if (FTPD_BUFSIZE > len)
- {
- char* b = buf;
- memcpy(b, ftpd_root, rlen); b += rlen;
- if (name[0] != '/')
- {
- *b++ = '/';
- if (clen > 0)
- {
- memcpy(b, cwd, clen); b += clen;
- *b++ = '/';
- }
- }
- memcpy(b, name, nlen); b += nlen;
- *b = '\0';
-
- res = buf + rlen;
- while(rlen-- > 0 && res[-1] == '/')
- --res;
- if(!squeeze_path(res, buf))
- res = NULL;
- }
-
- return res;
-}
-
-/*PAGE
- *
* Task pool management routines
*
*/
@@ -602,8 +458,6 @@ task_pool_init(int count, rtems_task_priority priority)
return 0;
}
task_pool.queue[i] = task_pool.info + i;
- info->ctrl_fp = NULL;
- info->ctrl_socket = -1;
if (++id > 'z')
id = 'a';
}
@@ -637,8 +491,6 @@ task_pool_obtain()
info = task_pool.queue[task_pool.head];
if(++task_pool.head >= task_pool.count)
task_pool.head = 0;
- info->ctrl_socket = -1;
- info->ctrl_fp = NULL;
rtems_semaphore_release(task_pool.mutex);
}
return info;
@@ -800,6 +652,7 @@ data_socket(FTPD_SessionInfo_t *info)
data_source.sin_port = htons(20); /* ftp-data port */
for(tries = 1; tries < 10; ++tries)
{
+ errno = 0;
if(bind(s, (struct sockaddr *)&data_source, sizeof(data_source)) >= 0)
break;
if (errno != EADDRINUSE)
@@ -849,9 +702,11 @@ data_socket(FTPD_SessionInfo_t *info)
static void
close_data_socket(FTPD_SessionInfo_t *info)
{
- int s = info->pasv_socket;
+ /* As at most one data socket could be open simultaneously and in some cases
+ data_socket == pasv_socket, we select socket to close, then close it. */
+ int s = info->data_socket;
if(0 > s)
- s = info->data_socket;
+ s = info->pasv_socket;
if(!close_socket(s))
syslog(LOG_ERR, "ftpd: Error closing data socket.");
info->data_socket = -1;
@@ -936,7 +791,6 @@ command_retrieve(FTPD_SessionInfo_t *info, char const *filename)
int fd = -1;
char buf[FTPD_DATASIZE];
int res = 0;
- char const* r = NULL;
if(!can_read())
{
@@ -944,9 +798,7 @@ command_retrieve(FTPD_SessionInfo_t *info, char const *filename)
return;
}
- r = make_path(buf, info->cwd, filename);
-
- if (NULL == r || 0 > (fd = open(buf, O_RDONLY)))
+ if (0 > (fd = open(filename, O_RDONLY)))
{
send_reply(info, 550, "Error opening file.");
return;
@@ -1030,6 +882,29 @@ command_retrieve(FTPD_SessionInfo_t *info, char const *filename)
/*PAGE
*
+ * discard
+ *
+ * Analog of `write' routine that just discards passed data
+ *
+ * Input parameters:
+ * fd - file descriptor (ignored)
+ * buf - data to write (ignored)
+ * count - number of bytes in `buf'
+ *
+ * Output parameters:
+ * returns `count'
+ *
+ */
+static ssize_t
+discard(int fd, void const* buf, size_t count)
+{
+ (void)fd;
+ (void)buf;
+ return count;
+}
+
+/*PAGE
+ *
* command_store
*
* Performs the "STOR" command (receive data from client).
@@ -1051,8 +926,9 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
char buf[FTPD_DATASIZE];
int res = 1;
int bare_lfs = 0;
-
- int null = !strcmp("/dev/null", filename);
+ int null = 0;
+ typedef ssize_t (*WriteProc)(int, void const*, size_t);
+ WriteProc wrt = &write;
if(!can_write())
{
@@ -1060,33 +936,23 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
return;
}
- if(!null)
- {
- if (NULL == make_path(buf, info->cwd, filename))
- {
- send_reply(info, 550, "Error creating file.");
- return;
- }
- }
-
send_mode_reply(info);
s = data_socket(info);
if(0 > s)
return;
-
+ null = !strcmp("/dev/null", filename);
if (null)
{
/* File "/dev/null" just throws data away.
- * FIXME: this is hack. Using /dev/null filesystem entry would be
- * better. However, it's not clear how to handle root directory other
- * than '/' then.
+ * FIXME: this is hack. Using `/dev/null' filesystem entry would be
+ * better.
*/
- while ((n = recv(s, buf, FTPD_DATASIZE, 0)) > 0)
- ;
+ wrt = &discard;
}
- else if (rtems_ftpd_configuration.hooks != NULL)
+
+ if (!null && rtems_ftpd_configuration.hooks != NULL)
{
/* Search our list of hooks to see if we need to do something special. */
@@ -1159,9 +1025,12 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
}
else
{
- /* Data transfer to regular file. */
- int fd =
- creat(buf, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ /* Data transfer to regular file or /dev/null. */
+ int fd = 0;
+
+ if(!null)
+ fd = creat(filename,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (0 > fd)
{
@@ -1174,7 +1043,7 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
{
while ((n = recv(s, buf, FTPD_DATASIZE, 0)) > 0)
{
- if (write(fd, buf, n) != n)
+ if (wrt(fd, buf, n) != n)
{
res = 0;
break;
@@ -1196,7 +1065,7 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
{
char const lf = '\r';
pended_cr = 0;
- if(write(fd, &lf, 1) != 1)
+ if(wrt(fd, &lf, 1) != 1)
{
res = 0;
break;
@@ -1231,12 +1100,12 @@ command_store(FTPD_SessionInfo_t *info, char const *filename)
if(res == 0)
break;
count = i - sub - pended_cr;
- if(count > 0 && write(fd, b, count) != count)
+ if(count > 0 && wrt(fd, b, count) != count)
{
res = 0;
break;
}
- if(sub == 2 && write(fd, e - 1, 1) != 1)
+ if(sub == 2 && wrt(fd, e - 1, 1) != 1)
res = 0;
}
while((rest -= i) > 0);
@@ -1384,10 +1253,7 @@ command_list(FTPD_SessionInfo_t *info, char const *fname, int wide)
struct dirent *dp = 0;
struct stat stat_buf;
char buf[FTPD_BUFSIZE];
- char path[FTPD_BUFSIZE];
time_t curTime;
- char const* res;
- char const* cwd = info->cwd;
int sc = 1;
send_reply(info, 150, "Opening ASCII mode data connection for LIST.");
@@ -1402,15 +1268,13 @@ command_list(FTPD_SessionInfo_t *info, char const *fname, int wide)
if(fname[0] == '\0')
fname = ".";
- res = make_path(path, cwd, fname);
-
- if (NULL == res || 0 > stat(path, &stat_buf))
+ if (0 > stat(fname, &stat_buf))
{
snprintf(buf, FTPD_BUFSIZE,
"%s: No such file or directory.\r\n", fname);
send(s, buf, strlen(buf), 0);
}
- else if (S_ISDIR(stat_buf.st_mode) && (NULL == (dirp = opendir(path))))
+ else if (S_ISDIR(stat_buf.st_mode) && (NULL == (dirp = opendir(fname))))
{
snprintf(buf, FTPD_BUFSIZE,
"%s: Can not open directory.\r\n", fname);
@@ -1420,15 +1284,15 @@ command_list(FTPD_SessionInfo_t *info, char const *fname, int wide)
{
time(&curTime);
if(!dirp && *fname)
- sc = sc && send_dirline(s, wide, curTime, path, "", fname, buf);
+ sc = sc && send_dirline(s, wide, curTime, fname, "", fname, buf);
else {
/* FIXME: need "." and ".." only when '-a' option is given */
- sc = sc && send_dirline(s, wide, curTime, path, "", ".", buf);
- sc = sc && send_dirline(s, wide, curTime, path,
- (strcmp(path, ftpd_root) ? ".." : ""), "..", buf);
+ sc = sc && send_dirline(s, wide, curTime, fname, "", ".", buf);
+ sc = sc && send_dirline(s, wide, curTime, fname,
+ (strcmp(fname, ftpd_root) ? ".." : ""), "..", buf);
while (sc && (dp = readdir(dirp)) != NULL)
sc = sc &&
- send_dirline(s, wide, curTime, path, dp->d_name, dp->d_name, buf);
+ send_dirline(s, wide, curTime, fname, dp->d_name, dp->d_name, buf);
}
}
@@ -1445,38 +1309,64 @@ command_list(FTPD_SessionInfo_t *info, char const *fname, int wide)
/*PAGE
*
- * rtems_ftpd_cwd
+ * command_cwd
*
- * Change current working directory. We use 'chdir' here only to validate the
- * new directory. We keep track of current working directory ourselves because
- * current working directory in RTEMS isn't thread local, but we need it to be
- * session local.
+ * Change current working directory.
*
* Input parameters:
* info - corresponding SessionInfo structure
* dir - directory name passed in CWD command
*
* Output parameters:
- * info->cwd is set to new CWD value.
+ * NONE
*
*/
static void
-rtems_ftpd_cwd(FTPD_SessionInfo_t *info, char *dir)
+command_cwd(FTPD_SessionInfo_t *info, char *dir)
{
- char buf[FTPD_BUFSIZE];
- char const* cwd = make_path(buf, info->cwd, dir);
- if(cwd && chdir(buf) == 0)
- {
+ if(chdir(dir) == 0)
send_reply(info, 250, "CWD command successful.");
- strcpy(info->cwd, cwd);
- }
else
- {
send_reply(info, 550, "CWD command failed.");
- }
}
+/*PAGE
+ *
+ * command_pwd
+ *
+ * Send current working directory to client.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ *
+ * Output parameters:
+ * NONE
+ */
+static void
+command_pwd(FTPD_SessionInfo_t *info)
+{
+ char buf[FTPD_BUFSIZE];
+ char const* cwd;
+ errno = 0;
+ buf[0] = '"';
+ cwd = getcwd(buf + 1, FTPD_BUFSIZE - 4);
+ if(cwd)
+ {
+ int len = strlen(cwd);
+ static char const txt[] = "\" is the current directory.";
+ int size = sizeof(txt);
+ if(len + size + 1 >= FTPD_BUFSIZE)
+ size = FTPD_BUFSIZE - len - 2;
+ memcpy(buf + len + 1, txt, size);
+ buf[len + size] = '\0';
+ send_reply(info, 250, buf);
+ }
+ else {
+ snprintf(buf, FTPD_BUFSIZE, "Error: %s.", serr());
+ send_reply(info, 452, buf);
+ }
+}
/*PAGE
*
@@ -1497,7 +1387,7 @@ command_mdtm(FTPD_SessionInfo_t *info, char const* fname)
struct stat stbuf;
char buf[FTPD_BUFSIZE];
- if (NULL == make_path(buf, info->cwd, fname) || 0 > stat(buf, &stbuf))
+ if (0 > stat(fname, &stbuf))
{
snprintf(buf, FTPD_BUFSIZE, "%s: %s.", fname, serr());
send_reply(info, 550, buf);
@@ -1614,7 +1504,7 @@ command_pasv(FTPD_SessionInfo_t *info)
syslog(LOG_ERR, "ftpd: Error binding PASV socket: %s", serr());
else if (0 > listen(s, 1))
syslog(LOG_ERR, "ftpd: Error listening on PASV socket: %s", serr());
- else
+ else if(set_socket_timeout(s, info->idle))
{
char buf[FTPD_BUFSIZE];
unsigned char const *ip, *p;
@@ -1627,11 +1517,14 @@ command_pasv(FTPD_SessionInfo_t *info)
send_reply(info, 227, buf);
info->pasv_socket = accept(s, (struct sockaddr *)&addr, &addrLen);
- close_socket(s);
if (0 > info->pasv_socket)
syslog(LOG_ERR, "ftpd: Error accepting PASV connection: %s", serr());
else
+ {
+ close_socket(s);
+ s = -1;
err = 0;
+ }
}
}
if(err)
@@ -1746,17 +1639,18 @@ split_command(char *buf, char **cmd, char **opts, char **args)
* info - corresponding SessionInfo structure
* cmd - command to be executed (upper-case)
* args - arguments of the command
- * buf - beginning of buffer where 'cmd' and 'args' reside.
*
* Output parameters:
* NONE
*/
static void
-exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
+exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args)
{
char fname[FTPD_BUFSIZE];
int wrong_command = 0;
+ fname[0] = '\0';
+
if (!strcmp("PORT", cmd))
{
command_port(info, args);
@@ -1824,8 +1718,7 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
}
else if (
1 == sscanf(args, "%254s", fname) &&
- NULL != make_path(buf, info->cwd, fname) &&
- unlink(buf) == 0)
+ unlink(fname) == 0)
{
send_reply(info, 257, "DELE successful.");
}
@@ -1848,8 +1741,7 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
}
else if(
2 == sscanf(args, "%o %254s", &mask, fname) &&
- NULL != make_path(buf, info->cwd, fname) &&
- chmod(buf, (mode_t)mask) == 0)
+ chmod(fname, (mode_t)mask) == 0)
{
send_reply(info, 257, "CHMOD successful.");
}
@@ -1869,8 +1761,7 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
}
else if (
1 == sscanf(args, "%254s", fname) &&
- NULL != make_path(buf, info->cwd, fname) &&
- rmdir(buf) == 0)
+ rmdir(fname) == 0)
{
send_reply(info, 257, "RMD successful.");
}
@@ -1887,8 +1778,7 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
}
else if (
1 == sscanf(args, "%254s", fname) &&
- NULL != make_path(buf, info->cwd, fname) &&
- mkdir(buf, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
{
send_reply(info, 257, "MKD successful.");
}
@@ -1900,20 +1790,15 @@ exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args, char* buf)
else if (!strcmp("CWD", cmd))
{
sscanf(args, "%254s", fname);
- rtems_ftpd_cwd(info, fname);
+ command_cwd(info, fname);
}
else if (!strcmp("CDUP", cmd))
{
- rtems_ftpd_cwd(info, "..");
+ command_cwd(info, "..");
}
else if (!strcmp("PWD", cmd))
{
- char const* cwd = "/";
- if(info->cwd[0])
- cwd = info->cwd;
- snprintf(buf, FTPD_BUFSIZE,
- "\"%s\" is the current directory.", cwd);
- send_reply(info, 250, buf);
+ command_pwd(info);
}
else
wrong_command = 1;
@@ -1943,14 +1828,26 @@ static void
session(rtems_task_argument arg)
{
FTPD_SessionInfo_t *const info = (FTPD_SessionInfo_t *)arg;
+ int chroot_made = 0;
+
+ rtems_libio_set_private_env();
+
+ /* chroot() can fail here because the directory may not exist yet. */
+ chroot_made = chroot(ftpd_root) == 0;
while(1)
{
rtems_event_set set;
+ char buf[128];
rtems_event_receive(FTPD_RTEMS_EVENT, RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT,
&set);
+ chroot_made = chroot_made || chroot(ftpd_root) == 0;
+ chdir("/");
+
+ errno = 0;
+
send_reply(info, 220, FTPD_SERVER_MESSAGE);
while (1)
@@ -1973,7 +1870,7 @@ session(rtems_task_argument arg)
}
else
{
- exec_command(info, cmd, args, buf);
+ exec_command(info, cmd, args);
}
}
@@ -2061,8 +1958,8 @@ daemon()
info->use_default = 1;
info->ctrl_addr = addr;
info->pasv_socket = -1;
- info->xfer_mode = TYPE_A;
- info->cwd[0] = '\0';
+ info->data_socket = -1;
+ info->xfer_mode = TYPE_A;
info->data_addr.sin_port =
htons(ntohs(info->ctrl_addr.sin_port) - 1);
info->idle = ftpd_timeout;
@@ -2149,18 +2046,17 @@ rtems_initialize_ftpd()
return RTEMS_UNSATISFIED;
}
- ftpd_root[0] = '\0';
+ ftpd_root = "/";
if (
rtems_ftpd_configuration.root &&
- strlen(rtems_ftpd_configuration.root) < FTPD_BUFSIZE &&
- rtems_ftpd_configuration.root[0] == '/')
- {
- strcpy(ftpd_root, rtems_ftpd_configuration.root);
- squeeze_path(ftpd_root, NULL);
- rtems_ftpd_configuration.root = ftpd_root;
- }
+ rtems_ftpd_configuration.root[0] == '/'
+ )
+ ftpd_root = rtems_ftpd_configuration.root;
+
+ rtems_ftpd_configuration.root = ftpd_root;
syslog(LOG_INFO, "ftpd: FTP daemon started (%d session%s max)",
count, ((count > 1) ? "s" : ""));
+
return RTEMS_SUCCESSFUL;
}
diff --git a/cpukit/libnetworking/ChangeLog b/cpukit/libnetworking/ChangeLog
index 1df7067298..8b8215ab06 100644
--- a/cpukit/libnetworking/ChangeLog
+++ b/cpukit/libnetworking/ChangeLog
@@ -1,3 +1,18 @@
+2001-01-31 Sergei Organov <osv@javad.ru>
+
+ * rtems_servers/ftp.d: Following changes:
+ - Hacks with current dir and root dir removed in favor of new libio
+ support for task-local current and root directories.
+ - Bug in `close_data_socket()' introduced by previous change fixed.
+ - `command_pasv()' changed to set timeout on socket we are listening
+ on and code fixed to don't close socket twice on error.
+ - `serr()' changed to clear `errno'.
+ - `data_socket()' changed to clear `errno' before `bind()'.
+ - `session()' changed to clear `errno' before processing session.
+ - `close_data_socket()' fixed to close both active and passive sockets
+ - Initialize info->data_socket to -1 in `daemon()'
+ - Initialize `fname' to empty string in `exec_command()'
+
2001-02-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* Makefile.am, arpa/Makefile.am, machine/Makefile.am, net/Makefile.am,