diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2012-11-21 15:47:46 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2012-11-21 16:38:34 +0100 |
commit | ad5e0708a2a5506d1580d56390303330b706dbb9 (patch) | |
tree | eece747f555eaad4e56d66f5baafc5ca42bfc2b1 /cpukit/libnetworking | |
parent | ftpfs: Format (diff) | |
download | rtems-ad5e0708a2a5506d1580d56390303330b706dbb9.tar.bz2 |
ftpfs: Open control connection during path eval
Diffstat (limited to 'cpukit/libnetworking')
-rw-r--r-- | 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 fcdff3a17c..70251f5c44 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, |