[rtems commit] ftpfs: Use SIZE command

Sebastian Huber sebh at rtems.org
Wed Nov 21 15:36:30 UTC 2012


Module:    rtems
Branch:    master
Commit:    fe0f24ea392b6930828a46139bb4251a82f013a0
Changeset: http://git.rtems.org/rtems/commit/?id=fe0f24ea392b6930828a46139bb4251a82f013a0

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Nov 21 15:27:43 2012 +0100

ftpfs: Use SIZE command

---

 cpukit/libnetworking/lib/ftpfs.c    |   99 ++++++++++++++++++++++++++++++++++-
 testsuites/libtests/ftp01/ftp01.scn |   18 ++++++
 testsuites/libtests/ftp01/init.c    |   11 ++++
 3 files changed, 127 insertions(+), 1 deletions(-)

diff --git a/cpukit/libnetworking/lib/ftpfs.c b/cpukit/libnetworking/lib/ftpfs.c
index 70251f5..5ba7515 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 aa00f7f..a329296 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 c60cc56..354c0f0 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)




More information about the vc mailing list