summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2012-11-21 15:47:46 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2012-11-21 16:38:34 +0100
commitad5e0708a2a5506d1580d56390303330b706dbb9 (patch)
treeeece747f555eaad4e56d66f5baafc5ca42bfc2b1
parentftpfs: Format (diff)
downloadrtems-ad5e0708a2a5506d1580d56390303330b706dbb9.tar.bz2
ftpfs: Open control connection during path eval
-rw-r--r--cpukit/libnetworking/lib/ftpfs.c313
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,