/* SFTP client context */
typedef struct {
SilcStream stream;
+ SilcSchedule schedule;
SilcSFTPVersionCallback version;
SilcSFTPErrorCallback error;
void *context;
silc_buffer_len(sftp->packet));
if (ret == -2) {
SILC_LOG_ERROR(("Error sending SFTP packet type %d", type));
- break;
+ sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_NO_CONNECTION,
+ sftp->context);
+ silc_buffer_reset(sftp->packet);
+ return;
+ }
+ if (ret == 0) {
+ sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_EOF, sftp->context);
+ silc_buffer_reset(sftp->packet);
+ return;
}
- if (ret <= 0)
- break;
+ if (ret == -1)
+ return;
+
silc_buffer_pull(sftp->packet, ret);
}
sftp->version = version_cb;
sftp->error = error_cb;
sftp->context = context;
+ sftp->schedule = schedule;
silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
/* We handle the stream now */
{
SilcSFTPClient sftp = (SilcSFTPClient)context;
- silc_stream_set_notifier(sftp->stream, NULL, NULL, NULL);
+ silc_stream_set_notifier(sftp->stream, sftp->schedule, NULL, NULL);
if (sftp->packet)
silc_buffer_free(sftp->packet);
silc_free(sftp);
SilcSFTPClient sftp = (SilcSFTPClient)context;
SilcSFTPRequest req;
SilcSFTPPacket type;
- const unsigned char *payload = NULL;
+ unsigned char *payload = NULL;
SilcUInt32 payload_len;
int ret;
SilcBufferStruct buf;
SILC_LOG_DEBUG(("Process SFTP packet"));
/* Parse the packet */
- type = silc_sftp_packet_decode(buffer, (unsigned char **)&payload,
- &payload_len);
+ type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
if (!type)
return;
- silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
+ silc_buffer_set(&buf, payload, payload_len);
switch (type) {
case SILC_SFTP_DATA:
ret =
silc_buffer_unformat(&buf,
SILC_STR_UI_INT(&id),
- SILC_STR_UI_XNSTRING(&data,
- silc_buffer_len(&buf) - 4),
+ SILC_STR_DATA(&data, silc_buffer_len(&buf) - 4),
SILC_STR_END);
if (ret < 0)
break;
ret = silc_buffer_unformat(&buf,
SILC_STR_UI_INT(&id),
- SILC_STR_UI_XNSTRING(&data, silc_buffer_len(&buf) - 4),
+ SILC_STR_DATA(&data,
+ silc_buffer_len(&buf) - 4),
SILC_STR_END);
if (ret < 0)
break;
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2004 Pekka Riikonen
+ Copyright (C) 2001 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Add `entry' to directory `dir'. */
-static bool mem_add_entry(MemFSEntry dir, MemFSEntry entry,
- bool check_perm)
+static SilcBool mem_add_entry(MemFSEntry dir, MemFSEntry entry,
+ SilcBool check_perm)
{
int i;
/* Removes entry `entry' and all entries under it recursively. */
-static bool mem_del_entry(MemFSEntry entry, bool check_perm)
+static SilcBool mem_del_entry(MemFSEntry entry, SilcBool check_perm)
{
int i;
/* Deletes entry by the name `name' from the directory `dir'. This does
not check subdirectories recursively. */
-static bool mem_del_entry_name(MemFSEntry dir, const char *name,
- SilcUInt32 name_len, bool check_perm)
+static SilcBool mem_del_entry_name(MemFSEntry dir, const char *name,
+ SilcUInt32 name_len, SilcBool check_perm)
{
MemFSEntry entry;
/* Deletes the handle and remove it from the open handle list. */
-static bool mem_del_handle(MemFS fs, MemFSFileHandle handle)
+static SilcBool mem_del_handle(MemFS fs, MemFSFileHandle handle)
{
if (handle->handle > fs->handles_count)
return FALSE;
fs->root_perm = perm;
fs->root->directory = TRUE;
fs->root->name = strdup(DIR_SEPARATOR);
+ if (!fs->root->name) {
+ silc_free(fs->root);
+ silc_free(fs);
+ }
filesystem = silc_calloc(1, sizeof(*filesystem));
if (!filesystem) {
+ silc_free(fs->root->name);
silc_free(fs->root);
silc_free(fs);
return NULL;
return NULL;
entry->perm = perm;
- entry->name = strdup(name);
entry->directory = TRUE;
entry->parent = dir ? dir : memfs->root;
+ entry->name = strdup(name);
+ if (!entry->name) {
+ silc_free(entry);
+ return NULL;
+ }
- if (!mem_add_entry(dir ? dir : memfs->root, entry, FALSE))
+ if (!mem_add_entry(dir ? dir : memfs->root, entry, FALSE)) {
+ silc_free(entry->name);
+ silc_free(entry);
return NULL;
+ }
return entry;
}
in memory file system. The filesystem does not allow removing directories
with remote access using the filesystem access function sftp_rmdir. */
-bool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir)
+SilcBool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir)
{
MemFS memfs = (MemFS)fs->fs_context;
- bool ret;
+ SilcBool ret;
if (dir)
return mem_del_entry(dir, FALSE);
memfs->root->perm = memfs->root_perm;
memfs->root->directory = TRUE;
memfs->root->name = strdup(DIR_SEPARATOR);
+ if (!memfs->root->name) {
+ silc_free(memfs->root);
+ memfs->root = NULL;
+ return FALSE;
+ }
return ret;
}
file and they work in POSIX style. Returns TRUE if the file was
added to the directory. */
-bool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
- SilcSFTPFSMemoryPerm perm,
- const char *filename,
- const char *realpath)
+SilcBool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
+ SilcSFTPFSMemoryPerm perm,
+ const char *filename,
+ const char *realpath)
{
MemFS memfs = (MemFS)fs->fs_context;
MemFSEntry entry;
return FALSE;
entry->perm = perm;
+ entry->directory = FALSE;
entry->name = strdup(filename);
entry->data = strdup(realpath);
- entry->directory = FALSE;
+ if (!entry->name || !entry->data) {
+ silc_free(entry->name);
+ silc_free(entry->data);
+ silc_free(entry);
+ return FALSE;
+ }
return mem_add_entry(dir ? dir : memfs->root, entry, FALSE);
}
/* Removes a file indicated by the `filename' from the directory
indicated by the `dir'. Returns TRUE if the removing was success. */
-bool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
- const char *filename)
+SilcBool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
+ const char *filename)
{
MemFS memfs = (MemFS)fs->fs_context;
/* SFTP Server context */
typedef struct {
SilcStream stream;
+ SilcSchedule schedule;
SilcSFTPMonitors monitors;
SilcSFTPMonitor monitor;
void *monitor_context;
silc_buffer_len(sftp->packet));
if (ret == -2) {
SILC_LOG_ERROR(("Error sending SFTP packet type %d", type));
- break;
+ sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_NO_CONNECTION,
+ sftp->context);
+ silc_buffer_reset(sftp->packet);
+ return;
+ }
+ if (ret == 0) {
+ sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_EOF, sftp->context);
+ silc_buffer_reset(sftp->packet);
+ return;
}
- if (ret <= 0)
- break;
+ if (ret == -1)
+ return;
+
silc_buffer_pull(sftp->packet, ret);
}
if (!server)
return NULL;
server->stream = stream;
+ server->schedule = schedule;
server->error = error_cb;
server->context = context;
server->fs = fs;
SILC_LOG_DEBUG(("Stopping SFTP server %p", server));
+ silc_stream_set_notifier(server->stream, server->schedule, NULL, NULL);
if (server->packet)
silc_buffer_free(server->packet);
silc_free(server);
}
/* Function that is called to process the incmoing SFTP packet. */
-/* XXX Some day this will go away and we have automatic receive callbacks
- for SilcSocketConnection API or SilcPacketContext API. */
static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer)
{
SilcSFTPServer server = (SilcSFTPServer)sftp;
SilcSFTPPacket type;
char *filename = NULL, *path = NULL;
- const unsigned char *payload = NULL;
+ unsigned char *payload = NULL;
SilcUInt32 payload_len;
int ret;
SilcBufferStruct buf;
SILC_LOG_DEBUG(("Start"));
/* Parse the packet */
- type = silc_sftp_packet_decode(buffer, (unsigned char **)&payload,
- &payload_len);
+ type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
if (!type)
return;
- silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
+ silc_buffer_set(&buf, payload, payload_len);
memset(&mdata, 0, sizeof(mdata));
switch (type) {
+ case SILC_SFTP_READ:
+ {
+ unsigned char *hdata;
+ SilcUInt32 hdata_len;
+ SilcUInt64 offset;
+ SilcUInt32 len;
+
+ SILC_LOG_DEBUG(("Read request"));
+
+ ret = silc_buffer_unformat(&buf,
+ SILC_STR_UI_INT(&id),
+ SILC_STR_UI32_NSTRING(&hdata,
+ &hdata_len),
+ SILC_STR_UI_INT64(&offset),
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END);
+ if (ret < 0)
+ goto failure;
+
+ /* Get the handle */
+ handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
+ (const unsigned char *)hdata,
+ hdata_len);
+ if (!handle) {
+ silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
+ break;
+ }
+
+ /* Read operation */
+ server->fs->fs->sftp_read(server->fs->fs_context, sftp,
+ handle, offset, len,
+ silc_sftp_server_data, SILC_32_TO_PTR(id));
+
+ /* Call monitor */
+ if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
+ mdata.offset = offset;
+ mdata.data_len = len;
+ (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
+ server->monitor_context);
+ }
+ }
+ break;
+
+ case SILC_SFTP_WRITE:
+ {
+ unsigned char *hdata;
+ SilcUInt32 hdata_len;
+ SilcUInt64 offset;
+ unsigned char *data;
+ SilcUInt32 data_len;
+
+ SILC_LOG_DEBUG(("Read request"));
+
+ ret = silc_buffer_unformat(&buf,
+ SILC_STR_UI_INT(&id),
+ SILC_STR_UI32_NSTRING(&hdata,
+ &hdata_len),
+ SILC_STR_UI_INT64(&offset),
+ SILC_STR_UI32_NSTRING(&data,
+ &data_len),
+ SILC_STR_END);
+ if (ret < 0)
+ goto failure;
+
+ /* Get the handle */
+ handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
+ (const unsigned char *)hdata,
+ hdata_len);
+ if (!handle) {
+ silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
+ break;
+ }
+
+ /* Write operation */
+ server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
+ (const unsigned char *)data, data_len,
+ silc_sftp_server_status, SILC_32_TO_PTR(id));
+
+ /* Call monitor */
+ if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
+ mdata.offset = offset;
+ mdata.data_len = data_len;
+ (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
+ server->monitor_context);
+ }
+ }
+ break;
+
case SILC_SFTP_INIT:
{
SilcSFTPVersion version;
}
break;
- case SILC_SFTP_READ:
- {
- unsigned char *hdata;
- SilcUInt32 hdata_len;
- SilcUInt64 offset;
- SilcUInt32 len;
-
- SILC_LOG_DEBUG(("Read request"));
-
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_INT(&id),
- SILC_STR_UI32_NSTRING(&hdata,
- &hdata_len),
- SILC_STR_UI_INT64(&offset),
- SILC_STR_UI_INT(&len),
- SILC_STR_END);
- if (ret < 0)
- goto failure;
-
- /* Get the handle */
- handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
- (const unsigned char *)hdata,
- hdata_len);
- if (!handle) {
- silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
- break;
- }
-
- /* Read operation */
- server->fs->fs->sftp_read(server->fs->fs_context, sftp,
- handle, offset, len,
- silc_sftp_server_data, SILC_32_TO_PTR(id));
-
- /* Call monitor */
- if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
- mdata.offset = offset;
- mdata.data_len = len;
- (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
- server->monitor_context);
- }
- }
- break;
-
- case SILC_SFTP_WRITE:
- {
- unsigned char *hdata;
- SilcUInt32 hdata_len;
- SilcUInt64 offset;
- unsigned char *data;
- SilcUInt32 data_len;
-
- SILC_LOG_DEBUG(("Read request"));
-
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_INT(&id),
- SILC_STR_UI32_NSTRING(&hdata,
- &hdata_len),
- SILC_STR_UI_INT64(&offset),
- SILC_STR_UI32_NSTRING(&data,
- &data_len),
- SILC_STR_END);
- if (ret < 0)
- goto failure;
-
- /* Get the handle */
- handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
- (const unsigned char *)hdata,
- hdata_len);
- if (!handle) {
- silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
- break;
- }
-
- /* Write operation */
- server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
- (const unsigned char *)data, data_len,
- silc_sftp_server_status, SILC_32_TO_PTR(id));
-
- /* Call monitor */
- if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
- mdata.offset = offset;
- mdata.data_len = data_len;
- (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
- server->monitor_context);
- }
- }
- break;
-
case SILC_SFTP_REMOVE:
{
SILC_LOG_DEBUG(("Remove request"));
/* Setstat operation */
server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
- silc_sftp_server_status, SILC_32_TO_PTR(id));
+ silc_sftp_server_status,
+ SILC_32_TO_PTR(id));
silc_sftp_attr_free(attrs);
silc_free(path);
/* Symlink operation */
server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
- silc_sftp_server_status, SILC_32_TO_PTR(id));
+ silc_sftp_server_status,
+ SILC_32_TO_PTR(id));
silc_free(path);
silc_free(target);
*
* SFTP Version type.
*
- * SOURCE
- */
+ ***/
typedef SilcUInt32 SilcSFTPVersion;
-/***/
/* SFTP protocol version */
#define SILC_SFTP_PROTOCOL_VERSION 3
*
* Error callback is called if a connection error occurs during SFTP
* session. If the connection or stream is closed this callback is
- * called. Other errors are delivered in other callbacks.
+ * called. Other errors are delivered in other callbacks. Only the
+ * SILC_SFTP_STATUS_EOF or SILC_SFTP_STATUS_NO_CONNECTION is delivered
+ * in this callback.
*
***/
typedef void (*SilcSFTPErrorCallback)(SilcSFTP sftp,
* DESCRIPTION
*
* Starts SFTP client and returns context to it. The version callback
- * indicated by the `callback' will be called after the SFTP session has
+ * indicated by the `version_cb' will be called after the SFTP session has
* been started and server has returned the version of the protocol. The
* SFTP client context is returned in the callback too. This returns the
* allocated SFTP client context or NULL on error. The `stream' will be
- * used to read and write the SFTP packets.
+ * used to read and write the SFTP packets. The `error_cb' will be called
+ * in case a stream error occurs, such as end of stream.
*
***/
SilcSFTP silc_sftp_client_start(SilcStream stream,
* DESCRIPTION
*
* Starts SFTP server and returns a context to it. This function returns
- * the allocated SFTP server context or NULL on error. The `send_packet'
- * is called by the library when it needs to send a packet. The `fs' is the
- * filesystem context allocated by the application. Each socket connection
- * should start its own server by calling this function.
+ * the allocated SFTP server context or NULL on error. The `stream' is
+ * the stream (connection) to the client. The `error_cb' will be called
+ * when the `stream' is ended (SILC_SFTP_STATUS_EOF). The caller is
+ * responsible of closing and destroying the `stream'. The `fs' is the
+ * filesystem context allocated by the application.
*
***/
SilcSFTP silc_sftp_server_start(SilcStream stream,
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2005 Pekka Riikonen
+ Copyright (C) 2001 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*
* SYNOPSIS
*
- * bool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir);
+ * SilcBool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir);
*
* DESCRIPTION
*
* access function sftp_rmdir.
*
***/
-bool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir);
+SilcBool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir);
/****f* silcsftp/SilcSFTPFSAPI/silc_sftp_fs_memory_add_file
*
* SYNOPSIS
*
- * bool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
- * SilcSFTPFSMemoryPerm perm,
- * const char *filename,
- * const char *realpath);
+ * SilcBool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
+ * SilcSFTPFSMemoryPerm perm,
+ * const char *filename,
+ * const char *realpath);
*
* DESCRIPTION
*
* was added to the directory.
*
***/
-bool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
- SilcSFTPFSMemoryPerm perm,
- const char *filename,
- const char *realpath);
+SilcBool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
+ SilcSFTPFSMemoryPerm perm,
+ const char *filename,
+ const char *realpath);
/****f* silcsftp/SilcSFTPFSAPI/silc_sftp_fs_memory_del_file
*
* SYNOPSIS
*
- * bool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
- * const char *filename);
+ * SilcBool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
+ * const char *filename);
*
* DESCRIPTION
*
* access function sftp_remove.
*
***/
-bool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
- const char *filename);
+SilcBool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
+ const char *filename);
#endif /* SILCSFTP_FS_H */