+Fri Oct 12 18:37:24 EDT 2001 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed the backup resuming protocol to work in multiple
+ router environment. Affected file silcd/server_backup.c.
+
+ * Route packet only to one router in the function
+ silc_server_packet_send_to_channel. Affected file is
+ silcd/packet_send.c.
+
+ * Fixed silc_server_send_notify_dest to set the broadcast
+ flag. Fixed the silc_server_send_notify_topic to actually
+ send the TOPIC_CHANGE notify and not SERVER_SIGNOFF notify.
+ Affected file silcd/packet_send.c.
+
Thu Oct 11 22:19:26 EDT 2001 Pekka Riikonen <priikone@silcnet.org>
* Changed the backup router adding and getting interfaces
packet->data, packet->len, TRUE);
silc_buffer_free(packet);
- /* Mark the server disabled. The data sent earlier will go but nothing
+ /* Mark the router disabled. The data sent earlier will go but nothing
after this does not go to this connection. */
idata->status |= SILC_IDLIST_STATUS_DISABLED;
}
SilcHashTableList htl;
SilcIDListData idata;
uint32 routed_count = 0;
+ bool gone = FALSE;
/* This doesn't send channel message packets */
assert(type != SILC_PACKET_CHANNEL_MESSAGE);
if (sender && sock == sender)
continue;
+ /* Route only once to router */
+ if (sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ if (gone)
+ continue;
+ gone = TRUE;
+ }
+
/* Send the packet */
silc_server_packet_send_to_channel_real(server, sock, &packetdata,
idata->send_key,
void silc_server_send_notify(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcNotifyType type,
uint32 argc, ...)
{
void silc_server_send_notify_args(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcNotifyType type,
uint32 argc,
SilcBuffer args)
void silc_server_send_notify_channel_change(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelID *old_id,
SilcChannelID *new_id)
{
void silc_server_send_notify_nick_change(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcClientID *old_id,
SilcClientID *new_id)
{
void silc_server_send_notify_join(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id)
{
void silc_server_send_notify_leave(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id)
{
void silc_server_send_notify_cmode(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
uint32 mode_mask,
void *id, SilcIdType id_type,
void silc_server_send_notify_cumode(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
uint32 mode_mask,
void *id, SilcIdType id_type,
void silc_server_send_notify_signoff(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcClientID *client_id,
char *message)
{
void silc_server_send_notify_topic_set(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
char *topic)
idp = silc_id_payload_encode((void *)client_id, SILC_ID_CLIENT);
silc_server_send_notify(server, sock, broadcast,
- SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
+ SILC_NOTIFY_TYPE_TOPIC_SET,
topic ? 2 : 1,
idp->data, idp->len,
topic, topic ? strlen(topic) : 0);
void silc_server_send_notify_kicked(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
char *comment)
void silc_server_send_notify_killed(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcClientID *client_id,
char *comment)
{
void silc_server_send_notify_umode(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcClientID *client_id,
uint32 mode_mask)
{
void silc_server_send_notify_ban(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
char *add, char *del)
{
void silc_server_send_notify_invite(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
char *add, char *del)
void silc_server_send_notify_dest(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
void *dest_id,
SilcIdType dest_id_type,
SilcNotifyType type,
va_start(ap, argc);
packet = silc_notify_payload_encode(type, argc, ap);
- silc_server_packet_send_dest(server, sock, SILC_PACKET_NOTIFY, 0,
+ silc_server_packet_send_dest(server, sock, SILC_PACKET_NOTIFY,
+ broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
dest_id, dest_id_type,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
void silc_server_send_new_id(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
void *id, SilcIdType id_type,
uint32 id_len)
{
void silc_server_send_new_channel(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
char *channel_name,
void *channel_id,
uint32 channel_id_len,
const char *fmt, ...);
void silc_server_send_notify(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcNotifyType type,
uint32 argc, ...);
void silc_server_send_notify_args(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcNotifyType type,
uint32 argc,
SilcBuffer args);
void silc_server_send_notify_channel_change(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelID *old_id,
SilcChannelID *new_id);
void silc_server_send_notify_nick_change(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcClientID *old_id,
SilcClientID *new_id);
void silc_server_send_notify_join(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id);
void silc_server_send_notify_leave(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id);
void silc_server_send_notify_cmode(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
uint32 mode_mask,
void *id, SilcIdType id_type,
char *cipher, char *hmac);
void silc_server_send_notify_cumode(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
uint32 mode_mask,
void *id, SilcIdType id_type,
SilcClientID *target);
void silc_server_send_notify_signoff(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcClientID *client_id,
char *message);
void silc_server_send_notify_topic_set(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
char *topic);
void silc_server_send_notify_kicked(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
char *comment);
void silc_server_send_notify_killed(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcClientID *client_id,
char *comment);
void silc_server_send_notify_umode(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcClientID *client_id,
uint32 mode_mask);
void silc_server_send_notify_ban(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
char *add, char *del);
void silc_server_send_notify_invite(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
SilcChannelEntry channel,
SilcClientID *client_id,
char *add, char *del);
void silc_server_send_notify_dest(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
void *dest_id,
SilcIdType dest_id_type,
SilcNotifyType type,
uint32 argc, ...);
void silc_server_send_new_id(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
void *id, SilcIdType id_type,
uint32 id_len);
void silc_server_send_new_channel(SilcServer server,
SilcSocketConnection sock,
- int broadcast,
+ bool broadcast,
char *channel_name,
void *channel_id,
uint32 channel_id_len,
SilcPacketContext *packet)
{
uint8 type, session;
- int ret;
+ SilcServerBackupProtocolContext ctx;
+ int i, ret;
if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
sock->type == SILC_SOCKET_TYPE_UNKNOWN)
SILC_LOG_DEBUG(("Start"));
- SILC_LOG_DEBUG(("********************************"));
ret = silc_buffer_unformat(packet->buffer,
SILC_STR_UI_CHAR(&type),
SILC_STR_UI_CHAR(&session),
if (ret < 0)
return;
- SILC_LOG_DEBUG(("********************************"));
+ /* Activate the protocol for this socket if necessary */
+ if ((type == SILC_SERVER_BACKUP_RESUMED ||
+ type == SILC_SERVER_BACKUP_RESUMED_GLOBAL) &&
+ sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol &&
+ ((SilcIDListData)sock->user_data)->status &
+ SILC_IDLIST_STATUS_DISABLED) {
+ SilcServerEntry backup_router;
+
+ if (silc_server_backup_replaced_get(server,
+ ((SilcServerEntry)sock->
+ user_data)->id,
+ &backup_router)) {
+ SilcSocketConnection bsock =
+ (SilcSocketConnection)backup_router->connection;
+ if (bsock->protocol && bsock->protocol->protocol &&
+ bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
+ sock->protocol = bsock->protocol;
+ ctx = sock->protocol->context;
+ ctx->sock = sock;
+ }
+ }
+ }
+
/* If the backup resuming protocol is active then process the packet
in the protocol. */
if (sock->protocol && sock->protocol->protocol &&
sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
- SilcServerBackupProtocolContext ctx = sock->protocol->context;
- int i;
-
+ ctx = sock->protocol->context;
ctx->type = type;
SILC_LOG_DEBUG(("********************************"));
return;
}
- SILC_LOG_DEBUG(("********************************"));
/* We don't have protocol active. If we are router and the packet is
coming from our primary router then lets check whether it means we've
been replaced by an backup router in my cell. This is usually received
SilcIDListData idata = (SilcIDListData)sock->user_data;
SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
- "wait untill backup resuming protocol is executed"));
+ "wait until backup resuming protocol is executed"));
SILC_LOG_DEBUG(("We are replaced by an backup router in this cell"));
idata->status |= SILC_IDLIST_STATUS_DISABLED;
return;
}
- SILC_LOG_DEBUG(("********************************"));
if (type == SILC_SERVER_BACKUP_START ||
type == SILC_SERVER_BACKUP_START_GLOBAL) {
/* We have received a start for resuming protocol. */
silc_server_protocol_backup_done);
silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
}
- SILC_LOG_DEBUG(("EEEEEEEEEEEEEEEEEEEEEEEEe"));
}
/* Timeout task callback to connect to remote router */
silc_buffer_free(packet);
+ SILC_LOG_INFO(("We are now the primary router of our cell again"));
+
/* For us this is the end of this protocol. */
if (protocol->final_callback)
silc_protocol_execute_final(protocol, server->schedule);
case SILC_PROTOCOL_STATE_END:
{
SilcIDListData idata;
- SilcServerEntry primary;
- SilcServerEntry backup_router;
+ SilcServerEntry router, backup_router;
/* We should have been received RESUMED packet from our primary
router. */
if (server->backup_router)
server->server_type = SILC_BACKUP_ROUTER;
- primary = (SilcServerEntry)ctx->sock->user_data;
- if (silc_server_backup_replaced_get(server, primary->id,
+ router = (SilcServerEntry)ctx->sock->user_data;
+ if (silc_server_backup_replaced_get(server, router->id,
&backup_router)) {
if (backup_router == server->router) {
- server->id_entry->router = ctx->sock->user_data;
- server->router = ctx->sock->user_data;
SILC_LOG_INFO(("Switching back to primary router %s",
server->router->server_name));
- SILC_LOG_DEBUG(("********************************"));
SILC_LOG_DEBUG(("Switching back to primary router %s",
server->router->server_name));
- idata = (SilcIDListData)server->router;
- idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
-
- /* Update the client entries of the backup router to the new
- primary router. */
- silc_server_update_clients_by_server(server, backup_router,
- primary, TRUE, FALSE);
- silc_server_backup_replaced_del(server, backup_router);
- silc_server_backup_add(server, backup_router,
- ((SilcSocketConnection)primary->
- connection)->ip,
- ((SilcSocketConnection)primary->
- connection)->port,
- backup_router->server_type != SILC_ROUTER ?
- TRUE : FALSE);
+ server->id_entry->router = router;
+ server->router = router;
+ } else {
+ SILC_LOG_INFO(("Resuming the use of router %s",
+ router->server_name));
+ SILC_LOG_DEBUG(("Resuming the use of router %s",
+ router->server_name));
}
- /* Announce all of our information to the new primary router. */
+ idata = (SilcIDListData)server->router;
+ idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
+
+ /* Update the client entries of the backup router to the new router */
+ silc_server_update_clients_by_server(server, backup_router,
+ router, FALSE, FALSE);
+ silc_server_backup_replaced_del(server, backup_router);
+ silc_server_backup_add(server, backup_router,
+ ctx->sock->ip, ctx->sock->port,
+ backup_router->server_type != SILC_ROUTER ?
+ TRUE : FALSE);
+
+ /* Announce all of our information to the router. */
if (server->server_type == SILC_ROUTER)
- silc_server_announce_servers(server, FALSE, 0,
- server->router->connection);
+ silc_server_announce_servers(server, FALSE, 0, router->connection);
/* Announce our clients and channels to the router */
- silc_server_announce_clients(server, 0,
- server->router->connection);
- silc_server_announce_channels(server, 0,
- server->router->connection);
+ silc_server_announce_clients(server, 0, router->connection);
+ silc_server_announce_channels(server, 0, router->connection);
}
/* Protocol has ended, call the final callback */
SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
}
+ /* Remove this protocol from all server entries that has it */
if (silc_idcache_get_all(server->local_list->servers, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
server_entry = (SilcServerEntry)id_cache->context;
sock = (SilcSocketConnection)server_entry->connection;
- if (sock->protocol && sock->protocol->protocol &&
- sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP)
+ if (sock->protocol == protocol) {
sock->protocol = NULL;
+
+ if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
+ server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+ }
if (!silc_idcache_list_next(list, &id_cache))
break;
SILC_LOG_DEBUG(("Start"));
+ SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
+ SILC_ID_SERVER)));
+ SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
+ SILC_ID_SERVER)));
+
if (silc_idcache_get_all(server->local_list->clients, &list)) {
if (silc_idcache_list_first(list, &id_cache)) {
while (id_cache) {
if (client->router == from) {
/* Skip clients that are *really* owned by the `from' */
- if (SILC_ID_COMPARE(from->id, client->id,
- client->id->ip.data_len)) {
+ if (remove_from && SILC_ID_COMPARE(from->id, client->id,
+ client->id->ip.data_len)) {
SILC_LOG_DEBUG(("Found really owned client, skip it"));
if (!silc_idcache_list_next(list, &id_cache))
break;
if (client->router == from) {
/* Skip clients that are *really* owned by the `from' */
- if (SILC_ID_COMPARE(from->id, client->id,
- client->id->ip.data_len)) {
+ if (remove_from && SILC_ID_COMPARE(from->id, client->id,
+ client->id->ip.data_len)) {
SILC_LOG_DEBUG(("Found really owned client, skip it"));
if (!silc_idcache_list_next(list, &id_cache))
break;
212.146.42.100:212.146.42.100:706
[Logging]
-#infologfile:silcd2.log:10000
-#warninglogfile:/var/log/silcd_warning.log:10000
-#errorlogfile:silcd2.log:10000
-#fatallogfile:/var/log/silcd_error.log:
+infologfile:cell1_backup.log:
+warninglogfile:cell1_backup.log:
+errorlogfile:cell1_backup.log:
+fatallogfile:cell1_backup.log:
[ConnectionClass]
1:100:100:100
212.146.42.250:212.146.42.250:706
[Logging]
-#infologfile:silcd2.log:10000
-#warninglogfile:/var/log/silcd_warning.log:10000
-#errorlogfile:silcd2.log:10000
-#fatallogfile:/var/log/silcd_error.log:
+infologfile:cell1_router.log:
+warninglogfile:cell1_router.log:
+errorlogfile:cell1_router.log:
+fatallogfile:cell1_router.log:
[ConnectionClass]
1:100:100:100
212.146.42.251:212.146.42.251:706
[Logging]
-#infologfile:silcd2.log:10000
-#warninglogfile:/var/log/silcd_warning.log:10000
-#errorlogfile:silcd2.log:10000
-#fatallogfile:/var/log/silcd_error.log:
+infologfile:cell2_router.log:
+warninglogfile:cell2_router.log:
+errorlogfile:cell2_router.log:
+fatallogfile:cell2_router.log:
[ConnectionClass]
1:100:100:100
212.146.42.252:212.146.42.252:706
[Logging]
-#infologfile:silcd2.log:10000
-#warninglogfile:/var/log/silcd_warning.log:10000
-#errorlogfile:silcd2.log:10000
-#fatallogfile:/var/log/silcd_error.log:
+infologfile:cell3_router.log:
+warninglogfile:cell3_router.log:
+errorlogfile:cell3_router.log:
+fatallogfile:cell3_router.log:
[ConnectionClass]
1:100:100:100
#define DIR_SEPARATOR "/"
+struct SilcSFTPFilesystemOpsStruct silc_sftp_fs_memory;
+
/* Memory filesystem entry */
typedef struct MemFSEntryStruct {
char *name; /* Name of the entry */
silc_sftp_fs_memory_free. The `perm' is the permissions for the root
directory of the filesystem (/ dir). */
-void *silc_sftp_fs_memory_alloc(SilcSFTPFSMemoryPerm perm)
+SilcSFTPFilesystem silc_sftp_fs_memory_alloc(SilcSFTPFSMemoryPerm perm)
{
+ SilcSFTPFilesystem filesystem;
MemFS fs;
fs = silc_calloc(1, sizeof(*fs));
fs->root->directory = TRUE;
fs->root->name = strdup(DIR_SEPARATOR);
- return (void *)fs;
+ filesystem = silc_calloc(1, sizeof(*filesystem));
+ filesystem->fs = &silc_sftp_fs_memory;
+ filesystem->fs_context = (void *)fs;
+
+ return filesystem;
}
/* Frees the memory filesystem context. */
-void silc_sftp_fs_memory_free(void *context)
+void silc_sftp_fs_memory_free(SilcSFTPFilesystem fs)
{
- MemFS fs = (MemFS)context;
+ MemFS memfs = (MemFS)fs->fs_context;
- silc_free(fs->root);
- silc_free(fs);
+ silc_free(memfs->root);
+ silc_free(memfs);
}
/* Adds a new directory to the memory filesystem. Returns the directory
not free the returned context. The `perm' will indicate the permissions
for the directory and they work in POSIX style. */
-void *silc_sftp_fs_memory_add_dir(void *context, void *dir,
+void *silc_sftp_fs_memory_add_dir(SilcSFTPFilesystem fs, void *dir,
SilcSFTPFSMemoryPerm perm,
const char *name)
{
- MemFS fs = (MemFS)context;
+ MemFS memfs = (MemFS)fs->fs_context;
MemFSEntry entry;
entry = silc_calloc(1, sizeof(*entry));
entry->perm = perm;
entry->name = strdup(name);
entry->directory = TRUE;
- entry->parent = dir ? dir : fs->root;
+ entry->parent = dir ? dir : memfs->root;
- if (!mem_add_entry(dir ? dir : fs->root, entry, FALSE))
+ if (!mem_add_entry(dir ? dir : memfs->root, entry, FALSE))
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(void *context, void *dir)
+bool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir)
{
- MemFS fs = (MemFS)context;
+ MemFS memfs = (MemFS)fs->fs_context;
bool ret;
if (dir)
return mem_del_entry(dir, FALSE);
/* Remove from root */
- ret = mem_del_entry(fs->root, FALSE);
+ ret = mem_del_entry(memfs->root, FALSE);
- fs->root = silc_calloc(1, sizeof(*fs->root));
- fs->root->perm = fs->root_perm;
- fs->root->directory = TRUE;
- fs->root->name = strdup(DIR_SEPARATOR);
+ memfs->root = silc_calloc(1, sizeof(*memfs->root));
+ memfs->root->perm = memfs->root_perm;
+ memfs->root->directory = TRUE;
+ memfs->root->name = strdup(DIR_SEPARATOR);
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(void *context,
- void *dir,
+bool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
SilcSFTPFSMemoryPerm perm,
const char *filename,
const char *realpath)
{
- MemFS fs = (MemFS)context;
+ MemFS memfs = (MemFS)fs->fs_context;
MemFSEntry entry;
entry = silc_calloc(1, sizeof(*entry));
entry->data = strdup(realpath);
entry->directory = FALSE;
- return mem_add_entry(dir ? dir : fs->root, entry, 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(void *context, void *dir,
+bool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
const char *filename)
{
- MemFS fs = (MemFS)context;
+ MemFS memfs = (MemFS)fs->fs_context;
if (!filename)
return FALSE;
- return mem_del_entry_name(dir ? dir : fs->root, filename,
+ return mem_del_entry_name(dir ? dir : memfs->root, filename,
strlen(filename), FALSE);
}
callback_context);
}
-struct SilcSFTPFilesystemStruct silc_sftp_fs_memory = {
+struct SilcSFTPFilesystemOpsStruct silc_sftp_fs_memory = {
mem_get_handle,
mem_encode_handle,
mem_open,
#include "silcincludes.h"
#include "silcsftp.h"
+#include "silcsftp_fs.h"
#include "sftp_util.h"
/* SFTP Server context */
SilcSFTPSendPacketCallback send_packet;
void *send_context;
SilcSFTPFilesystem fs;
- void *fs_context;
} *SilcSFTPServer;
/* General routine to send SFTP packet to the SFTP client. */
return;
}
- hdata = server->fs->sftp_encode_handle(server->fs_context, sftp,
- handle, &hdata_len);
+ hdata = server->fs->fs->sftp_encode_handle(server->fs->fs_context, sftp,
+ handle, &hdata_len);
if (!hdata) {
silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
return;
SilcSFTP silc_sftp_server_start(SilcSocketConnection sock,
SilcSFTPSendPacketCallback send_packet,
void *send_context,
- SilcSFTPFilesystem fs,
- void *fs_context)
+ SilcSFTPFilesystem fs)
{
SilcSFTPServer server;
server->send_packet = send_packet;
server->send_context = send_context;
server->fs = fs;
- server->fs_context = fs_context;
SILC_LOG_DEBUG(("Starting SFTP server %p", server));
}
/* Open operation */
- server->fs->sftp_open(server->fs_context, sftp, filename, pflags,
- attrs, silc_sftp_server_handle, (void *)id);
+ server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
+ attrs, silc_sftp_server_handle, (void *)id);
silc_free(filename);
silc_sftp_attr_free(attrs);
goto failure;
/* Get the handle */
- handle = server->fs->sftp_get_handle(server->fs_context, sftp,
- (const unsigned char *)hdata,
- hdata_len);
+ 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;
}
/* Close operation */
- server->fs->sftp_close(server->fs_context, sftp, handle,
- silc_sftp_server_status, (void *)id);
+ server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
+ silc_sftp_server_status, (void *)id);
}
break;
goto failure;
/* Get the handle */
- handle = server->fs->sftp_get_handle(server->fs_context, sftp,
- (const unsigned char *)hdata,
- hdata_len);
+ 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->sftp_read(server->fs_context, sftp, handle, offset, len,
- silc_sftp_server_data, (void *)id);
+ server->fs->fs->sftp_read(server->fs->fs_context, sftp,
+ handle, offset, len,
+ silc_sftp_server_data, (void *)id);
}
break;
goto failure;
/* Get the handle */
- handle = server->fs->sftp_get_handle(server->fs_context, sftp,
- (const unsigned char *)hdata,
- hdata_len);
+ 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->sftp_write(server->fs_context, sftp, handle, offset,
- (const unsigned char *)data, data_len,
- silc_sftp_server_status, (void *)id);
+ server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
+ (const unsigned char *)data, data_len,
+ silc_sftp_server_status, (void *)id);
}
break;
goto failure;
/* Remove operation */
- server->fs->sftp_remove(server->fs_context, sftp, filename,
- silc_sftp_server_status, (void *)id);
+ server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
+ silc_sftp_server_status, (void *)id);
silc_free(filename);
}
goto failure;
/* Rename operation */
- server->fs->sftp_rename(server->fs_context, sftp, filename, newname,
- silc_sftp_server_status, (void *)id);
+ server->fs->fs->sftp_rename(server->fs->fs_context, sftp, filename, newname,
+ silc_sftp_server_status, (void *)id);
silc_free(filename);
silc_free(newname);
}
/* Mkdir operation */
- server->fs->sftp_mkdir(server->fs_context, sftp, path, attrs,
- silc_sftp_server_status, (void *)id);
+ server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
+ silc_sftp_server_status, (void *)id);
silc_sftp_attr_free(attrs);
silc_free(path);
goto failure;
/* Rmdir operation */
- server->fs->sftp_rmdir(server->fs_context, sftp, path,
- silc_sftp_server_status, (void *)id);
+ server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
+ silc_sftp_server_status, (void *)id);
silc_free(path);
}
goto failure;
/* Opendir operation */
- server->fs->sftp_opendir(server->fs_context, sftp, path,
- silc_sftp_server_handle, (void *)id);
+ server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
+ silc_sftp_server_handle, (void *)id);
silc_free(path);
}
goto failure;
/* Get the handle */
- handle = server->fs->sftp_get_handle(server->fs_context, sftp,
- (const unsigned char *)hdata,
- hdata_len);
+ 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;
}
/* Readdir operation */
- server->fs->sftp_readdir(server->fs_context, sftp, handle,
- silc_sftp_server_name, (void *)id);
+ server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
+ silc_sftp_server_name, (void *)id);
}
break;
goto failure;
/* Stat operation */
- server->fs->sftp_stat(server->fs_context, sftp, path,
- silc_sftp_server_attr, (void *)id);
+ server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
+ silc_sftp_server_attr, (void *)id);
silc_free(path);
}
goto failure;
/* Lstat operation */
- server->fs->sftp_lstat(server->fs_context, sftp, path,
- silc_sftp_server_attr, (void *)id);
+ server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
+ silc_sftp_server_attr, (void *)id);
silc_free(path);
}
goto failure;
/* Get the handle */
- handle = server->fs->sftp_get_handle(server->fs_context, sftp,
- (const unsigned char *)hdata,
- hdata_len);
+ 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;
}
/* Fstat operation */
- server->fs->sftp_fstat(server->fs_context, sftp, handle,
- silc_sftp_server_attr, (void *)id);
+ server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
+ silc_sftp_server_attr, (void *)id);
}
break;
}
/* Setstat operation */
- server->fs->sftp_setstat(server->fs_context, sftp, path, attrs,
- silc_sftp_server_status, (void *)id);
+ server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
+ silc_sftp_server_status, (void *)id);
silc_sftp_attr_free(attrs);
silc_free(path);
}
/* Get the handle */
- handle = server->fs->sftp_get_handle(server->fs_context, sftp,
- (const unsigned char *)hdata,
- hdata_len);
+ 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;
}
/* Fsetstat operation */
- server->fs->sftp_fsetstat(server->fs_context, sftp, handle, attrs,
- silc_sftp_server_status, (void *)id);
+ server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp, handle, attrs,
+ silc_sftp_server_status, (void *)id);
silc_sftp_attr_free(attrs);
}
goto failure;
/* Readlink operation */
- server->fs->sftp_readlink(server->fs_context, sftp, path,
- silc_sftp_server_name, (void *)id);
+ server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
+ silc_sftp_server_name, (void *)id);
silc_free(path);
}
goto failure;
/* Symlink operation */
- server->fs->sftp_symlink(server->fs_context, sftp, path, target,
- silc_sftp_server_status, (void *)id);
+ server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
+ silc_sftp_server_status, (void *)id);
silc_free(path);
silc_free(target);
goto failure;
/* Realpath operation */
- server->fs->sftp_realpath(server->fs_context, sftp, path,
- silc_sftp_server_name, (void *)id);
+ server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
+ silc_sftp_server_name, (void *)id);
silc_free(path);
}
data_len = buf.len;
/* Extended operation */
- server->fs->sftp_extended(server->fs_context, sftp,
- request, data, data_len,
- silc_sftp_server_extended, (void *)id);
+ server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
+ request, data, data_len,
+ silc_sftp_server_extended, (void *)id);
silc_free(request);
}
/* SFTP Server Interface */
-/****s* silcsftp/SilcSFTPAPI/SilcSFTPFilesystem
- *
- * NAME
- *
- * typedef struct SilcSFTPFilesystemStruct { ... } *SilcSFTPFilesystem;
- *
- * DESCRIPTION
- *
- * This structure defines the generic filesystem access. When the
- * filesystem is accessed these functions are called to do the requested
- * filesystem operation. The level that implements the actual filesystem
- * must fill this structure with the callback functions providing the
- * access to the filesystem. The structure is will be given as
- * argument to the silc_sftp_server_start function.
- *
- * SOURCE
- */
-typedef struct SilcSFTPFilesystemStruct {
- /* Find a file handle by the file handle data indicated by the `data'.
- If the handle is not found this returns NULL. */
- SilcSFTPHandle (*sftp_get_handle)(void *context, SilcSFTP sftp,
- const unsigned char *data,
- uint32 data_len);
-
- /* Return encoded handle of `handle' or NULL on error. The caller
- must free the returned buffer. */
- unsigned char *(*sftp_encode_handle)(void *context, SilcSFTP sftp,
- SilcSFTPHandle handle,
- uint32 *handle_len);
-
- /* Open a file indicated by the `filename' with flags indicated by the
- `pflags', and with attributes indicated by the `attr'. Calls the
- `callback' to return the opened file handle. */
- void (*sftp_open)(void *context, SilcSFTP sftp,
- const char *filename,
- SilcSFTPFileOperation pflags,
- SilcSFTPAttributes attr,
- SilcSFTPHandleCallback callback,
- void *callback_context);
-
- /* Closes the file indicated by the file handle `handle'. Calls the
- `callback' to indicate the status of the closing. */
- void (*sftp_close)(void *context, SilcSFTP sftp,
- SilcSFTPHandle handle,
- SilcSFTPStatusCallback callback,
- void *callback_context);
-
- /* Reads data from the file indicated by the file handle `handle' starting
- from the offset of `offset' at most `len' bytes. The `callback' is
- called to return the read data. */
- void (*sftp_read)(void *context, SilcSFTP sftp,
- SilcSFTPHandle handle,
- uint64 offset,
- uint32 len,
- SilcSFTPDataCallback callback,
- void *callback_context);
-
- /* Writes to a file indicated by the file handle `handle' starting from
- offset of `offset' at most `data_len' bytes of `data'. The `callback'
- is called to indicate the status of the writing. */
- void (*sftp_write)(void *context, SilcSFTP sftp,
- SilcSFTPHandle handle,
- uint64 offset,
- const unsigned char *data,
- uint32 data_len,
- SilcSFTPStatusCallback callback,
- void *callback_context);
-
- /* Removes a file indicated by the `filename'. Calls the `callback'
- to indicate the status of the removing. */
- void (*sftp_remove)(void *context, SilcSFTP sftp,
- const char *filename,
- SilcSFTPStatusCallback callback,
- void *callback_context);
-
- /* Renames a file indicated by the `oldname' to the name `newname'. The
- `callback' is called to indicate the status of the renaming. */
- void (*sftp_rename)(void *context, SilcSFTP sftp,
- const char *oldname,
- const char *newname,
- SilcSFTPStatusCallback callback,
- void *callback_context);
-
- /* Creates a new directory indicated by the `path' with attributes indicated
- by the `attrs'. The `callback' is called to indicate the status of the
- creation. */
- void (*sftp_mkdir)(void *context, SilcSFTP sftp,
- const char *path,
- SilcSFTPAttributes attrs,
- SilcSFTPStatusCallback callback,
- void *callback_context);
-
- /* Removes a directory indicated by the `path' and calls the `callback'
- to indicate the status of the removal. */
- void (*sftp_rmdir)(void *context, SilcSFTP sftp,
- const char *path,
- SilcSFTPStatusCallback callback,
- void *callback_context);
-
- /* Opens a directory indicated by the `path'. The `callback' is called
- to return the opened file handle. */
- void (*sftp_opendir)(void *context, SilcSFTP sftp,
- const char *path,
- SilcSFTPHandleCallback callback,
- void *callback_context);
-
- /* Reads the contents of the directory indicated by the `handle' and
- calls the `callback' to return the read file(s) from the directory. */
- void (*sftp_readdir)(void *context, SilcSFTP sftp,
- SilcSFTPHandle handle,
- SilcSFTPNameCallback callback,
- void *callback_context);
-
- /* Gets the file attributes for a file indicated by the `path'. This
- will follow symbolic links also. Calls the `callback' to return the
- file attributes. */
- void (*sftp_stat)(void *context, SilcSFTP sftp,
- const char *path,
- SilcSFTPAttrCallback callback,
- void *callback_context);
-
- /* Gets the file attributes for a file indicated by the `path'. This
- will not follow symbolic links. Calls the `callback' to return the
- file attributes. */
- void (*sftp_lstat)(void *context, SilcSFTP sftp,
- const char *path,
- SilcSFTPAttrCallback callback,
- void *callback_context);
-
- /* Gets a file attributes for a opened file indicated by the `handle'.
- Calls the `callback' to return the file attributes. */
- void (*sftp_fstat)(void *context, SilcSFTP sftp,
- SilcSFTPHandle handle,
- SilcSFTPAttrCallback callback,
- void *callback_context);
-
- /* Sets a file attributes to a file indicated by the `path' with the
- attributes indicated by the `attrs'. Calls the `callback' to indicate
- the status of the setting. */
- void (*sftp_setstat)(void *context, SilcSFTP sftp,
- const char *path,
- SilcSFTPAttributes attrs,
- SilcSFTPStatusCallback callback,
- void *callback_context);
-
- /* Sets a file attributes to a opened file indicated by the `handle' with
- the attributes indicated by the `attrs'. Calls the `callback' to
- indicate the status of the setting. */
- void (*sftp_fsetstat)(void *context, SilcSFTP sftp,
- SilcSFTPHandle handle,
- SilcSFTPAttributes attrs,
- SilcSFTPStatusCallback callback,
- void *callback_context);
-
- /* Reads the target of a symbolic link indicated by the `path'. The
- `callback' is called to return the target of the symbolic link. */
- void (*sftp_readlink)(void *context, SilcSFTP sftp,
- const char *path,
- SilcSFTPNameCallback callback,
- void *callback_context);
-
- /* Creates a new symbolic link indicated by the `linkpath' to the target
- indicated by the `targetpath'. The `callback' is called to indicate
- the status of creation. */
- void (*sftp_symlink)(void *context, SilcSFTP sftp,
- const char *linkpath,
- const char *targetpath,
- SilcSFTPStatusCallback callback,
- void *callback_context);
-
- /* Canonicalizes the path indicated by the `path' to a absolute path.
- The `callback' is called to return the absolute path. */
- void (*sftp_realpath)(void *context, SilcSFTP sftp,
- const char *path,
- SilcSFTPNameCallback callback,
- void *callback_context);
-
- /* Performs an extended operation indicated by the `request' with
- optional extended operation data indicated by the `data'. The callback
- is called to return any data associated with the extended request. */
- void (*sftp_extended)(void *context, SilcSFTP sftp,
- const char *request,
- const unsigned char *data,
- uint32 data_len,
- SilcSFTPExtendedCallback callback,
- void *callback_context);
-} *SilcSFTPFilesystem;
-/****/
+#include "silcsftp_fs.h"
/****f* silcsftp/SilcSFTPAPI/silc_sftp_server_start
*
* SilcSFTP silc_sftp_server_start(SilcSocketConnection sock,
* SilcSFTPSendPacketCallback send_packet,
* void *send_context, SilcSFTP sftp,
- * SilcSFTPFilesystem fs,
- * void *fs_context);
+ * SilcSFTPFilesystem fs);
*
* DESCRIPTION
*
* created SFTP server context. This function returns the allocated
* SFTP client context or NULL on error. The `send_packet' is called
* by the library when it needs to send a packet. The `fs' is the
- * structure containing filesystem access callbacks.
+ * filesystem context allocated by the application.
*
***/
SilcSFTP silc_sftp_server_start(SilcSocketConnection sock,
SilcSFTPSendPacketCallback send_packet,
void *send_context,
- SilcSFTPFilesystem fs,
- void *fs_context);
+ SilcSFTPFilesystem fs);
/****f* silcsftp/SilcSFTPAPI/silc_sftp_server_shutdown
*
*
***/
-/* Available filesystems. These can be given as argument to the
- silc_sftp_server_start function. */
-extern struct SilcSFTPFilesystemStruct silc_sftp_fs_memory;
+/****s* silcsftp/SilcSFTPFSAPI/SilcSFTPFilesystemOps
+ *
+ * NAME
+ *
+ * typedef struct SilcSFTPFilesystemOpsStruct { ... }
+ * *SilcSFTPFilesystemOps;
+ *
+ * DESCRIPTION
+ *
+ * This structure defines the generic filesystem access. When the
+ * filesystem is accessed these functions are called to do the requested
+ * filesystem operation. The level that implements the actual filesystem
+ * must fill this structure with the callback functions providing the
+ * access to the filesystem.
+ *
+ * SOURCE
+ */
+typedef struct SilcSFTPFilesystemOpsStruct {
+ /* Find a file handle by the file handle data indicated by the `data'.
+ If the handle is not found this returns NULL. */
+ SilcSFTPHandle (*sftp_get_handle)(void *context, SilcSFTP sftp,
+ const unsigned char *data,
+ uint32 data_len);
+
+ /* Return encoded handle of `handle' or NULL on error. The caller
+ must free the returned buffer. */
+ unsigned char *(*sftp_encode_handle)(void *context, SilcSFTP sftp,
+ SilcSFTPHandle handle,
+ uint32 *handle_len);
+
+ /* Open a file indicated by the `filename' with flags indicated by the
+ `pflags', and with attributes indicated by the `attr'. Calls the
+ `callback' to return the opened file handle. */
+ void (*sftp_open)(void *context, SilcSFTP sftp,
+ const char *filename,
+ SilcSFTPFileOperation pflags,
+ SilcSFTPAttributes attr,
+ SilcSFTPHandleCallback callback,
+ void *callback_context);
+
+ /* Closes the file indicated by the file handle `handle'. Calls the
+ `callback' to indicate the status of the closing. */
+ void (*sftp_close)(void *context, SilcSFTP sftp,
+ SilcSFTPHandle handle,
+ SilcSFTPStatusCallback callback,
+ void *callback_context);
+
+ /* Reads data from the file indicated by the file handle `handle' starting
+ from the offset of `offset' at most `len' bytes. The `callback' is
+ called to return the read data. */
+ void (*sftp_read)(void *context, SilcSFTP sftp,
+ SilcSFTPHandle handle,
+ uint64 offset,
+ uint32 len,
+ SilcSFTPDataCallback callback,
+ void *callback_context);
+
+ /* Writes to a file indicated by the file handle `handle' starting from
+ offset of `offset' at most `data_len' bytes of `data'. The `callback'
+ is called to indicate the status of the writing. */
+ void (*sftp_write)(void *context, SilcSFTP sftp,
+ SilcSFTPHandle handle,
+ uint64 offset,
+ const unsigned char *data,
+ uint32 data_len,
+ SilcSFTPStatusCallback callback,
+ void *callback_context);
+
+ /* Removes a file indicated by the `filename'. Calls the `callback'
+ to indicate the status of the removing. */
+ void (*sftp_remove)(void *context, SilcSFTP sftp,
+ const char *filename,
+ SilcSFTPStatusCallback callback,
+ void *callback_context);
+
+ /* Renames a file indicated by the `oldname' to the name `newname'. The
+ `callback' is called to indicate the status of the renaming. */
+ void (*sftp_rename)(void *context, SilcSFTP sftp,
+ const char *oldname,
+ const char *newname,
+ SilcSFTPStatusCallback callback,
+ void *callback_context);
+
+ /* Creates a new directory indicated by the `path' with attributes indicated
+ by the `attrs'. The `callback' is called to indicate the status of the
+ creation. */
+ void (*sftp_mkdir)(void *context, SilcSFTP sftp,
+ const char *path,
+ SilcSFTPAttributes attrs,
+ SilcSFTPStatusCallback callback,
+ void *callback_context);
+
+ /* Removes a directory indicated by the `path' and calls the `callback'
+ to indicate the status of the removal. */
+ void (*sftp_rmdir)(void *context, SilcSFTP sftp,
+ const char *path,
+ SilcSFTPStatusCallback callback,
+ void *callback_context);
+
+ /* Opens a directory indicated by the `path'. The `callback' is called
+ to return the opened file handle. */
+ void (*sftp_opendir)(void *context, SilcSFTP sftp,
+ const char *path,
+ SilcSFTPHandleCallback callback,
+ void *callback_context);
+ /* Reads the contents of the directory indicated by the `handle' and
+ calls the `callback' to return the read file(s) from the directory. */
+ void (*sftp_readdir)(void *context, SilcSFTP sftp,
+ SilcSFTPHandle handle,
+ SilcSFTPNameCallback callback,
+ void *callback_context);
+
+ /* Gets the file attributes for a file indicated by the `path'. This
+ will follow symbolic links also. Calls the `callback' to return the
+ file attributes. */
+ void (*sftp_stat)(void *context, SilcSFTP sftp,
+ const char *path,
+ SilcSFTPAttrCallback callback,
+ void *callback_context);
+
+ /* Gets the file attributes for a file indicated by the `path'. This
+ will not follow symbolic links. Calls the `callback' to return the
+ file attributes. */
+ void (*sftp_lstat)(void *context, SilcSFTP sftp,
+ const char *path,
+ SilcSFTPAttrCallback callback,
+ void *callback_context);
+
+ /* Gets a file attributes for a opened file indicated by the `handle'.
+ Calls the `callback' to return the file attributes. */
+ void (*sftp_fstat)(void *context, SilcSFTP sftp,
+ SilcSFTPHandle handle,
+ SilcSFTPAttrCallback callback,
+ void *callback_context);
+
+ /* Sets a file attributes to a file indicated by the `path' with the
+ attributes indicated by the `attrs'. Calls the `callback' to indicate
+ the status of the setting. */
+ void (*sftp_setstat)(void *context, SilcSFTP sftp,
+ const char *path,
+ SilcSFTPAttributes attrs,
+ SilcSFTPStatusCallback callback,
+ void *callback_context);
+
+ /* Sets a file attributes to a opened file indicated by the `handle' with
+ the attributes indicated by the `attrs'. Calls the `callback' to
+ indicate the status of the setting. */
+ void (*sftp_fsetstat)(void *context, SilcSFTP sftp,
+ SilcSFTPHandle handle,
+ SilcSFTPAttributes attrs,
+ SilcSFTPStatusCallback callback,
+ void *callback_context);
+
+ /* Reads the target of a symbolic link indicated by the `path'. The
+ `callback' is called to return the target of the symbolic link. */
+ void (*sftp_readlink)(void *context, SilcSFTP sftp,
+ const char *path,
+ SilcSFTPNameCallback callback,
+ void *callback_context);
+
+ /* Creates a new symbolic link indicated by the `linkpath' to the target
+ indicated by the `targetpath'. The `callback' is called to indicate
+ the status of creation. */
+ void (*sftp_symlink)(void *context, SilcSFTP sftp,
+ const char *linkpath,
+ const char *targetpath,
+ SilcSFTPStatusCallback callback,
+ void *callback_context);
+
+ /* Canonicalizes the path indicated by the `path' to a absolute path.
+ The `callback' is called to return the absolute path. */
+ void (*sftp_realpath)(void *context, SilcSFTP sftp,
+ const char *path,
+ SilcSFTPNameCallback callback,
+ void *callback_context);
+
+ /* Performs an extended operation indicated by the `request' with
+ optional extended operation data indicated by the `data'. The callback
+ is called to return any data associated with the extended request. */
+ void (*sftp_extended)(void *context, SilcSFTP sftp,
+ const char *request,
+ const unsigned char *data,
+ uint32 data_len,
+ SilcSFTPExtendedCallback callback,
+ void *callback_context);
+} *SilcSFTPFilesystemOps;
+/****/
+
+/****s* silcsftp/SilcSFTPFSAPI/SilcSFTPFilesystem
+ *
+ * NAME
+ *
+ * typedef struct { ... } *SilcSFTPFilesystem;
+ *
+ * DESCRIPTION
+ *
+ * This context is allocated and returned by all filesystem allocation
+ * routines. The returned context is given as argument to the
+ * silc_sftp_server_start function. The caller must also free the
+ * context after the SFTP server is shutdown.
+ *
+ * SOURCE
+ */
+typedef struct {
+ SilcSFTPFilesystemOps fs;
+ void *fs_context;
+} *SilcSFTPFilesystem;
+/***/
/* Memory filesystem */
* directory of the filesystem (/ dir).
*
***/
-void *silc_sftp_fs_memory_alloc(SilcSFTPFSMemoryPerm perm);
+SilcSFTPFilesystem silc_sftp_fs_memory_alloc(SilcSFTPFSMemoryPerm perm);
/****f* silcsftp/SilcSFTPFSAPI/silc_sftp_fs_memory_free
*
* Frees the memory filesystem context.
*
***/
-void silc_sftp_fs_memory_free(void *context);
+void silc_sftp_fs_memory_free(SilcSFTPFilesystem fs);
/****f* silcsftp/SilcSFTPFSAPI/silc_sftp_fs_memory_add_dir
*
* style.
*
***/
-void *silc_sftp_fs_memory_add_dir(void *context, void *dir,
+void *silc_sftp_fs_memory_add_dir(SilcSFTPFilesystem fs, void *dir,
SilcSFTPFSMemoryPerm perm,
const char *name);
*
* SYNOPSIS
*
- * bool silc_sftp_fs_memory_del_dir(void *context, void *dir);
+ * bool silc_sftp_fs_memory_del_dir(SilcSFTPFilesystem fs, void *dir);
*
* DESCRIPTION
*
* access function sftp_rmdir.
*
***/
-bool silc_sftp_fs_memory_del_dir(void *context, void *dir);
+bool 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(void *context, void *dir,
+ * bool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
* SilcSFTPFSMemoryPerm perm,
* const char *filename,
* const char *realpath);
* was added to the directory.
*
***/
-bool silc_sftp_fs_memory_add_file(void *context, void *dir,
+bool silc_sftp_fs_memory_add_file(SilcSFTPFilesystem fs, void *dir,
SilcSFTPFSMemoryPerm perm,
const char *filename,
const char *realpath);
*
* SYNOPSIS
*
- * bool silc_sftp_fs_memory_del_file(void *context, void *dir,
+ * bool 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(void *context, void *dir,
+bool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
const char *filename);
#endif /* SILCSFTP_FS_H */
#include "silcincludes.h"
#include "silcsftp.h"
-#include "silcsftp_fs.h"
typedef struct {
SilcSchedule schedule;
int sock;
- void *fs;
+ SilcSFTPFilesystem fs;
SilcSocketConnection socks[100];
SilcSFTP sftp[100];
} *Server;
server->socks[sock] = sc;
server->sftp[sock] =
silc_sftp_server_start(sc, send_packet, server,
- (SilcSFTPFilesystem)&silc_sftp_fs_memory,
server->fs);
silc_schedule_task_add(server->schedule, sock, packet_process,
server, 0, 0, SILC_TASK_GENERIC,