[rtems commit] ftpfs: Open control connection during path eval

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


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

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

ftpfs: Open control connection during path eval

---

 cpukit/libnetworking/lib/ftpfs.c |  313 ++++++++++++++++++--------------------
 1 files changed, 151 insertions(+), 162 deletions(-)

diff --git a/cpukit/libnetworking/lib/ftpfs.c b/cpukit/libnetworking/lib/ftpfs.c
index fcdff3a..70251f5 100644
--- a/cpukit/libnetworking/lib/ftpfs.c
+++ b/cpukit/libnetworking/lib/ftpfs.c
@@ -69,6 +69,8 @@ typedef struct {
    */
   int ctrl_socket;
 
+  uint32_t client_address;
+
   /**
    * Data transfer socket.
    */
@@ -93,6 +95,20 @@ typedef struct {
    * End of file flag.
    */
   bool eof;
+
+  bool write;
+
+  ino_t ino;
+
+  const char *user;
+
+  const char *password;
+
+  const char *hostname;
+
+  const char *filename;
+
+  char buffer [];
 } rtems_ftpfs_entry;
 
 /**
@@ -108,6 +124,11 @@ typedef struct {
    * Timeout value
    */
   struct timeval timeout;
+
+  /**
+   * Inode counter.
+   */
+  ino_t ino;
 } rtems_ftpfs_mount_entry;
 
 static const rtems_filesystem_operations_table rtems_ftpfs_ops;
@@ -428,7 +449,7 @@ typedef enum {
   STATE_INVALID
 } split_state;
 
-static bool rtems_ftpfs_split_names (
+static int rtems_ftpfs_split_names (
   char *s,
   const char **user,
   const char **password,
@@ -441,9 +462,6 @@ static bool rtems_ftpfs_split_names (
   size_t i = 0;
 
   *user = s;
-  *password = NULL;
-  *hostname = NULL;
-  *path = NULL;
 
   for (i = 0; i < len; ++i) {
     char c = s [i];
@@ -519,7 +537,7 @@ done:
     *password = *user;
   }
 
-  return state == STATE_DONE;
+  return state == STATE_DONE ? 0 : ENOENT;
 }
 
 static socklen_t rtems_ftpfs_create_address(
@@ -538,65 +556,39 @@ static socklen_t rtems_ftpfs_create_address(
   return sizeof(*sa);
 }
 
-static int rtems_ftpfs_terminate(rtems_libio_t *iop, bool error)
+static int rtems_ftpfs_close_data_connection(
+  rtems_ftpfs_entry *e,
+  bool verbose,
+  bool error
+)
 {
   int eno = 0;
-  int rv = 0;
-  rtems_ftpfs_entry *e = iop->data1;
-  rtems_ftpfs_mount_entry *me = iop->pathinfo.mt_entry->fs_info;
-  bool verbose = me->verbose;
-  rtems_ftpfs_reply reply = RTEMS_FTPFS_REPLY_ERROR;
 
-  if (e != NULL) {
-    /* Close data connection if necessary */
-    if (e->data_socket >= 0) {
-      rv = close(e->data_socket);
-      if (rv != 0) {
-        eno = EIO;
-      }
+  /* Close data connection if necessary */
+  if (e->data_socket >= 0) {
+    int rv = close(e->data_socket);
 
-      /* For write connections we have to obtain the transfer reply  */
-      if (
-        e->ctrl_socket >= 0
-          && (iop->flags & LIBIO_FLAGS_WRITE) != 0
-          && !error
-      ) {
-        reply = rtems_ftpfs_get_reply(e, NULL, NULL, verbose);
-        if (reply != RTEMS_FTPFS_REPLY_2) {
-          eno = EIO;
-        }
-      }
+    e->data_socket = -1;
+    if (rv != 0) {
+      eno = EIO;
     }
 
-    /* Close control connection if necessary */
-    if (e->ctrl_socket >= 0) {
-      reply = rtems_ftpfs_send_command(e, "QUIT", NULL, verbose);
-      if (reply != RTEMS_FTPFS_REPLY_2) {
-        eno = EIO;
-      }
+    /* For write connections we have to obtain the transfer reply  */
+    if (e->write && !error) {
+      rtems_ftpfs_reply reply =
+        rtems_ftpfs_get_reply(e, NULL, NULL, verbose);
 
-      rv = close(e->ctrl_socket);
-      if (rv != 0) {
+      if (reply != RTEMS_FTPFS_REPLY_2) {
         eno = EIO;
       }
     }
-
-    /* Free connection entry */
-    free(e);
   }
 
-  /* Invalidate IO entry */
-  iop->data1 = NULL;
-
   return eno;
 }
 
 static int rtems_ftpfs_open_ctrl_connection(
   rtems_ftpfs_entry *e,
-  const char *user,
-  const char *password,
-  const char *hostname,
-  uint32_t *client_address,
   bool verbose,
   const struct timeval *timeout
 )
@@ -615,9 +607,9 @@ static int rtems_ftpfs_open_ctrl_connection(
   }
 
   /* Set up the server address from the hostname */
-  if (inet_aton(hostname, &address) == 0) {
+  if (inet_aton(e->hostname, &address) == 0) {
     /* Try to get the address by name */
-    struct hostent *he = gethostbyname(hostname);
+    struct hostent *he = gethostbyname(e->hostname);
 
     if (he != NULL) {
       memcpy(&address, he->h_addr, sizeof(address));
@@ -654,7 +646,7 @@ static int rtems_ftpfs_open_ctrl_connection(
   if (rv != 0) {
     return ENOMEM;
   }
-  *client_address = ntohl(sa.sin_addr.s_addr);
+  e->client_address = ntohl(sa.sin_addr.s_addr);
   DEBUG_PRINTF("client = %s\n", inet_ntoa(sa.sin_addr));
 
   /* Now we should get a welcome message from the server */
@@ -664,10 +656,10 @@ static int rtems_ftpfs_open_ctrl_connection(
   }
 
   /* Send USER command */
-  reply = rtems_ftpfs_send_command(e, "USER ", user, verbose);
+  reply = rtems_ftpfs_send_command(e, "USER ", e->user, verbose);
   if (reply == RTEMS_FTPFS_REPLY_3) {
     /* Send PASS command */
-    reply = rtems_ftpfs_send_command(e, "PASS ", password, verbose);
+    reply = rtems_ftpfs_send_command(e, "PASS ", e->password, verbose);
     if (reply != RTEMS_FTPFS_REPLY_2) {
       return EACCES;
     }
@@ -688,9 +680,7 @@ static int rtems_ftpfs_open_ctrl_connection(
 
 static int rtems_ftpfs_open_data_connection_active(
   rtems_ftpfs_entry *e,
-  uint32_t client_address,
   const char *file_command,
-  const char *filename,
   bool verbose,
   const struct timeval *timeout
 )
@@ -741,10 +731,10 @@ static int rtems_ftpfs_open_data_connection_active(
     port_command,
     sizeof(port_command),
     "PORT %lu,%lu,%lu,%lu,%lu,%lu",
-    (client_address >> 24) & 0xffUL,
-    (client_address >> 16) & 0xffUL,
-    (client_address >> 8) & 0xffUL,
-    (client_address >> 0) & 0xffUL,
+    (e->client_address >> 24) & 0xffUL,
+    (e->client_address >> 16) & 0xffUL,
+    (e->client_address >> 8) & 0xffUL,
+    (e->client_address >> 0) & 0xffUL,
     (data_port >> 8) & 0xffUL,
     (data_port >> 0) & 0xffUL
   );
@@ -762,7 +752,7 @@ static int rtems_ftpfs_open_data_connection_active(
   }
 
   /* Send RETR or STOR command with filename */
-  reply = rtems_ftpfs_send_command(e, file_command, filename, verbose);
+  reply = rtems_ftpfs_send_command(e, file_command, e->filename, verbose);
   if (reply != RTEMS_FTPFS_REPLY_1) {
     eno = EIO;
     goto cleanup;
@@ -869,9 +859,7 @@ static void rtems_ftpfs_pasv_parser(
 
 static int rtems_ftpfs_open_data_connection_passive(
   rtems_ftpfs_entry *e,
-  uint32_t client_address,
   const char *file_command,
-  const char *filename,
   bool verbose,
   const struct timeval *timeout
 )
@@ -926,7 +914,7 @@ static int rtems_ftpfs_open_data_connection_passive(
   }
 
   /* Send RETR or STOR command with filename */
-  reply = rtems_ftpfs_send_command(e, file_command, filename, verbose);
+  reply = rtems_ftpfs_send_command(e, file_command, e->filename, verbose);
   if (reply != RTEMS_FTPFS_REPLY_1) {
     return EIO;
   }
@@ -942,111 +930,51 @@ static int rtems_ftpfs_open(
 )
 {
   int eno = 0;
-  bool ok = false;
-  rtems_ftpfs_entry *e = NULL;
+  rtems_ftpfs_entry *e = iop->pathinfo.node_access;
   rtems_ftpfs_mount_entry *me = iop->pathinfo.mt_entry->fs_info;
   bool verbose = me->verbose;
   const struct timeval *timeout = &me->timeout;
-  const char *user = NULL;
-  const char *password = NULL;
-  const char *hostname = NULL;
-  const char *filename = NULL;
-  const char *file_command = (iop->flags & LIBIO_FLAGS_WRITE) != 0
-    ? "STOR "
-    : "RETR ";
-  uint32_t client_address = 0;
-  char *location = iop->pathinfo.node_access;
-
-  /* Invalidate data handle */
-  iop->data1 = NULL;
-
-  /* Split location into parts */
-  ok = rtems_ftpfs_split_names(
-      location,
-      &user,
-      &password,
-      &hostname,
-      &filename
-  );
-  if (!ok) {
-    rtems_set_errno_and_return_minus_one(ENOENT);
-  }
-  DEBUG_PRINTF(
-    "user = '%s', password = '%s', filename = '%s'\n",
-    user,
-    password,
-    filename
-  );
+
+  e->write = (iop->flags & LIBIO_FLAGS_WRITE) != 0;
 
   /* Check for either read-only or write-only flags */
   if (
     (iop->flags & LIBIO_FLAGS_WRITE) != 0
       && (iop->flags & LIBIO_FLAGS_READ) != 0
   ) {
-    rtems_set_errno_and_return_minus_one(ENOTSUP);
-  }
-
-  /* Allocate connection entry */
-  e = calloc(1, sizeof(*e));
-  if (e == NULL) {
-    rtems_set_errno_and_return_minus_one(ENOMEM);
+    eno = ENOTSUP;
   }
 
-  /* Initialize connection entry */
-  e->ctrl_socket = -1;
-  e->data_socket = -1;
-
-  /* Save connection state */
-  iop->data1 = e;
-
-  /* Open control connection */
-  eno = rtems_ftpfs_open_ctrl_connection(
-    e,
-    user,
-    password,
-    hostname,
-    &client_address,
-    verbose,
-    timeout
-  );
-  if (eno != 0) {
-    goto cleanup;
-  }
+  if (eno == 0) {
+    const char *file_command = e->write ? "STOR " : "RETR ";
 
-  /* Open passive data connection */
-  eno = rtems_ftpfs_open_data_connection_passive(
-    e,
-    client_address,
-    file_command,
-    filename,
-    verbose,
-    timeout
-  );
-  if (eno == ENOTSUP) {
-    /* Open active data connection */
-    eno = rtems_ftpfs_open_data_connection_active(
+    /* Open passive data connection */
+    eno = rtems_ftpfs_open_data_connection_passive(
       e,
-      client_address,
       file_command,
-      filename,
       verbose,
       timeout
     );
-  }
-  if (eno != 0) {
-    goto cleanup;
+    if (eno == ENOTSUP) {
+      /* Open active data connection */
+      eno = rtems_ftpfs_open_data_connection_active(
+        e,
+        file_command,
+        verbose,
+        timeout
+      );
+    }
   }
 
   /* Set data connection timeout */
-  eno = rtems_ftpfs_set_connection_timeout(e->data_socket, timeout);
-
-cleanup:
+  if (eno == 0) {
+    eno = rtems_ftpfs_set_connection_timeout(e->data_socket, timeout);
+  }
 
   if (eno == 0) {
     return 0;
   } else {
-    /* Free all resources if an error occured */
-    rtems_ftpfs_terminate(iop, true);
+    rtems_ftpfs_close_data_connection(e, verbose, true);
 
     rtems_set_errno_and_return_minus_one(eno);
   }
@@ -1058,8 +986,8 @@ static ssize_t rtems_ftpfs_read(
   size_t count
 )
 {
-  rtems_ftpfs_entry *e = iop->data1;
-  rtems_ftpfs_mount_entry *me = iop->pathinfo.mt_entry->fs_info;
+  rtems_ftpfs_entry *e = iop->pathinfo.node_access;
+  const rtems_ftpfs_mount_entry *me = iop->pathinfo.mt_entry->fs_info;
   bool verbose = me->verbose;
   char *in = buffer;
   size_t todo = count;
@@ -1098,7 +1026,7 @@ static ssize_t rtems_ftpfs_write(
   size_t count
 )
 {
-  rtems_ftpfs_entry *e = iop->data1;
+  rtems_ftpfs_entry *e = iop->pathinfo.node_access;
   const char *out = buffer;
   size_t todo = count;
 
@@ -1122,7 +1050,9 @@ static ssize_t rtems_ftpfs_write(
 
 static int rtems_ftpfs_close(rtems_libio_t *iop)
 {
-  int eno = rtems_ftpfs_terminate(iop, false);
+  rtems_ftpfs_entry *e = iop->pathinfo.node_access;
+  const rtems_ftpfs_mount_entry *me = iop->pathinfo.mt_entry->fs_info;
+  int eno = rtems_ftpfs_close_data_connection(e, me->verbose, false);
 
   if (eno == 0) {
     return 0;
@@ -1141,32 +1071,84 @@ static void rtems_ftpfs_eval_path(
   rtems_filesystem_eval_path_context_t *self
 )
 {
+  int eno = 0;
+
   rtems_filesystem_eval_path_eat_delimiter(self);
 
   if (rtems_filesystem_eval_path_has_path(self)) {
     const char *path = rtems_filesystem_eval_path_get_path(self);
     size_t pathlen = rtems_filesystem_eval_path_get_pathlen(self);
-    char *pathdup = malloc(pathlen + 1);
+    rtems_ftpfs_entry *e = calloc(1, sizeof(*e) + pathlen + 1);
 
     rtems_filesystem_eval_path_clear_path(self);
 
-    if (pathdup != NULL) {
-      rtems_filesystem_location_info_t *currentloc =
-        rtems_filesystem_eval_path_get_currentloc(self);
+    if (e != NULL) {
+      memcpy(e->buffer, path, pathlen);
+
+      eno = rtems_ftpfs_split_names(
+          e->buffer,
+          &e->user,
+          &e->password,
+          &e->hostname,
+          &e->filename
+      );
+
+      DEBUG_PRINTF(
+        "user = '%s', password = '%s', filename = '%s'\n",
+        e->user,
+        e->password,
+        e->filename
+      );
+
+      if (eno == 0) {
+        rtems_filesystem_location_info_t *currentloc =
+          rtems_filesystem_eval_path_get_currentloc(self);
+        rtems_ftpfs_mount_entry *me = currentloc->mt_entry->fs_info;
+
+        rtems_libio_lock();
+        ++me->ino;
+        e->ino = me->ino;
+        rtems_libio_unlock();
+
+        e->ctrl_socket = -1;
+
+        eno = rtems_ftpfs_open_ctrl_connection(
+          e,
+          me->verbose,
+          &me->timeout
+        );
+        if (eno == 0) {
+          currentloc->node_access = e;
+          currentloc->handlers = &rtems_ftpfs_handlers;
+        }
+      }
 
-      memcpy(pathdup, path, pathlen);
-      pathdup [pathlen] = '\0';
-      currentloc->node_access = pathdup;
-      currentloc->handlers = &rtems_ftpfs_handlers;
+      if (eno != 0) {
+        free(e);
+      }
     } else {
-      rtems_filesystem_eval_path_error(self, ENOMEM);
+      eno = ENOMEM;
     }
   }
+
+  if (eno != 0) {
+    rtems_filesystem_eval_path_error(self, eno);
+  }
 }
 
 static void rtems_ftpfs_free_node(const rtems_filesystem_location_info_t *loc)
 {
-  free(loc->node_access);
+  rtems_ftpfs_entry *e = loc->node_access;
+  const rtems_ftpfs_mount_entry *me = loc->mt_entry->fs_info;
+
+  /* Close control connection if necessary */
+  if (e->ctrl_socket >= 0) {
+    rtems_ftpfs_send_command(e, "QUIT", NULL, me->verbose);
+
+    close(e->ctrl_socket);
+  }
+
+  free(e);
 }
 
 static rtems_filesystem_node_types_t rtems_ftpfs_node_type(
@@ -1181,7 +1163,7 @@ int rtems_ftpfs_initialize(
   const void                           *d
 )
 {
-  rtems_ftpfs_mount_entry *me = malloc(sizeof(rtems_ftpfs_mount_entry));
+  rtems_ftpfs_mount_entry *me = calloc(1, sizeof(*me));
 
   /* Mount entry for FTP file system instance */
   e->fs_info = me;
@@ -1254,10 +1236,10 @@ static int rtems_ftpfs_fstat(
   struct stat *st
 )
 {
-  static unsigned ino = 0;
+  rtems_ftpfs_entry *e = loc->node_access;
 
   /* FIXME */
-  st->st_ino = ++ino;
+  st->st_ino = e->ino;
   st->st_dev = rtems_filesystem_make_dev_t(0xcc494cd6U, 0x1d970b4dU);
 
   st->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
@@ -1265,9 +1247,16 @@ static int rtems_ftpfs_fstat(
   return 0;
 }
 
+static void rtems_ftpfs_lock_or_unlock(
+  const rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+  /* Do nothing */
+}
+
 static const rtems_filesystem_operations_table rtems_ftpfs_ops = {
-  .lock_h = rtems_filesystem_default_lock,
-  .unlock_h = rtems_filesystem_default_unlock,
+  .lock_h = rtems_ftpfs_lock_or_unlock,
+  .unlock_h = rtems_ftpfs_lock_or_unlock,
   .eval_path_h = rtems_ftpfs_eval_path,
   .link_h = rtems_filesystem_default_link,
   .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,




More information about the vc mailing list