summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2012-11-21 15:27:43 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2012-11-21 16:38:34 +0100
commitfe0f24ea392b6930828a46139bb4251a82f013a0 (patch)
tree51a4682c685a2c6721d4c1b4550420c65cb82a53
parentftpfs: Open control connection during path eval (diff)
downloadrtems-fe0f24ea392b6930828a46139bb4251a82f013a0.tar.bz2
ftpfs: Use SIZE command
-rw-r--r--cpukit/libnetworking/lib/ftpfs.c99
-rw-r--r--testsuites/libtests/ftp01/ftp01.scn18
-rw-r--r--testsuites/libtests/ftp01/init.c11
3 files changed, 127 insertions, 1 deletions
diff --git a/cpukit/libnetworking/lib/ftpfs.c b/cpukit/libnetworking/lib/ftpfs.c
index 70251f5c44..5ba7515400 100644
--- a/cpukit/libnetworking/lib/ftpfs.c
+++ b/cpukit/libnetworking/lib/ftpfs.c
@@ -98,6 +98,15 @@ typedef struct {
bool write;
+ /**
+ * Indicates if we should do a SIZE command.
+ *
+ * The first call to the rtems_ftpfs_fstat() handler is issued by the path
+ * evaluation to check for access permission. For this case we avoid the
+ * SIZE command.
+ */
+ bool do_size_command;
+
ino_t ino;
const char *user;
@@ -1225,6 +1234,65 @@ static int rtems_ftpfs_ioctl(
return 0;
}
+typedef enum {
+ RTEMS_FTPFS_SIZE_START = 0,
+ RTEMS_FTPFS_SIZE_SPACE,
+ RTEMS_FTPFS_SIZE_NUMBER,
+ RTEMS_FTPFS_SIZE_NL
+} rtems_ftpfs_size_state;
+
+typedef struct {
+ rtems_ftpfs_size_state state;
+ size_t index;
+ off_t size;
+} rtems_ftpfs_size_entry;
+
+static void rtems_ftpfs_size_parser(
+ const char* buf,
+ size_t len,
+ void *arg
+)
+{
+ rtems_ftpfs_size_entry *se = arg;
+ size_t i = 0;
+
+ for (i = 0; se->size >= 0 && i < len; ++i, ++se->index) {
+ int c = buf [i];
+
+ switch (se->state) {
+ case RTEMS_FTPFS_SIZE_START:
+ if (se->index == 2) {
+ se->state = RTEMS_FTPFS_SIZE_SPACE;
+ }
+ break;
+ case RTEMS_FTPFS_SIZE_SPACE:
+ if (c == ' ') {
+ se->state = RTEMS_FTPFS_SIZE_NUMBER;
+ } else {
+ se->size = -1;
+ }
+ break;
+ case RTEMS_FTPFS_SIZE_NUMBER:
+ if (isdigit(c)) {
+ se->size = 10 * se->size + c - '0';
+ } else if (c == '\r') {
+ se->state = RTEMS_FTPFS_SIZE_NL;
+ } else {
+ se->size = -1;
+ }
+ break;
+ case RTEMS_FTPFS_SIZE_NL:
+ if (c != '\n') {
+ se->size = -1;
+ }
+ break;
+ default:
+ se->size = -1;
+ break;
+ }
+ }
+}
+
/*
* The stat() support is intended only for the cp shell command. Each request
* will return that we have a regular file with read, write and execute
@@ -1236,6 +1304,7 @@ static int rtems_ftpfs_fstat(
struct stat *st
)
{
+ int eno = 0;
rtems_ftpfs_entry *e = loc->node_access;
/* FIXME */
@@ -1244,7 +1313,35 @@ static int rtems_ftpfs_fstat(
st->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
- return 0;
+ if (e->do_size_command) {
+ const rtems_ftpfs_mount_entry *me = loc->mt_entry->fs_info;
+ rtems_ftpfs_size_entry se;
+ rtems_ftpfs_reply reply = RTEMS_FTPFS_REPLY_ERROR;
+
+ memset(&se, 0, sizeof(se));
+
+ reply = rtems_ftpfs_send_command_with_parser(
+ e,
+ "SIZE ",
+ e->filename,
+ rtems_ftpfs_size_parser,
+ &se,
+ me->verbose
+ );
+ if (reply == RTEMS_FTPFS_REPLY_2 && se.size >= 0) {
+ st->st_size = se.size;
+ } else {
+ eno = EIO;
+ }
+ } else {
+ e->do_size_command = true;
+ }
+
+ if (eno == 0) {
+ return 0;
+ } else {
+ rtems_set_errno_and_return_minus_one(eno);
+ }
}
static void rtems_ftpfs_lock_or_unlock(
diff --git a/testsuites/libtests/ftp01/ftp01.scn b/testsuites/libtests/ftp01/ftp01.scn
index aa00f7f52c..a3292961c8 100644
--- a/testsuites/libtests/ftp01/ftp01.scn
+++ b/testsuites/libtests/ftp01/ftp01.scn
@@ -48,4 +48,22 @@ RETR b.txt
226 Transfer complete.
QUIT
221 Goodbye.
+220 RTEMS FTP server (Version 1.1-JWJ) ready.
+USER anonymous
+230 User logged in.
+TYPE I
+200 Type set to I.
+SIZE a.txt
+213 1102
+QUIT
+221 Goodbye.
+220 RTEMS FTP server (Version 1.1-JWJ) ready.
+USER anonymous
+230 User logged in.
+TYPE I
+200 Type set to I.
+SIZE b.txt
+213 1102
+QUIT
+221 Goodbye.
*** END OF TEST FTP 1 ***
diff --git a/testsuites/libtests/ftp01/init.c b/testsuites/libtests/ftp01/init.c
index c60cc56ee1..354c0f045a 100644
--- a/testsuites/libtests/ftp01/init.c
+++ b/testsuites/libtests/ftp01/init.c
@@ -142,6 +142,15 @@ static void copy_file(const char *src_path, const char *dest_path)
rtems_test_assert(rv == 0);
}
+static void check_file_size(const char *path, size_t size)
+{
+ struct stat st;
+ int rv = lstat(path, &st);
+
+ rtems_test_assert(rv == 0);
+ rtems_test_assert(st.st_size == (off_t) size);
+}
+
static void check_file(const char *path)
{
int rv = 0;
@@ -183,6 +192,8 @@ static void test(void)
create_file(file_a);
copy_file(file_a, file_b);
check_file(file_b);
+ check_file_size(file_a, sizeof(content));
+ check_file_size(file_b, sizeof(content));
}
static rtems_task Init(rtems_task_argument argument)