Merge commit 'origin/silc.1.1.branch'
[silc.git] / lib / silcsftp / sftp_server.c
index 119dbf1f36d7c58d5886087fb3e20d96d339d6c6..b22e21fba5c8c55e80aee0411be951c5193f3a11 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  sftp_server.c 
+  sftp_server.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 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
 */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcsftp.h"
 #include "silcsftp_fs.h"
 #include "sftp_util.h"
 
 /* SFTP Server context */
 typedef struct {
-  SilcSocketConnection sock;
-  SilcSFTPSendPacketCallback send_packet;
-  void *send_context;
+  SilcStream stream;
+  SilcSchedule schedule;
   SilcSFTPMonitors monitors;
   SilcSFTPMonitor monitor;
   void *monitor_context;
   SilcSFTPFilesystem fs;
+  SilcBuffer packet;
+  SilcSFTPErrorCallback error;
+  void *context;
 } *SilcSFTPServer;
 
+static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer);
+
 /* General routine to send SFTP packet to the SFTP client. */
 
 static void silc_sftp_send_packet(SilcSFTPServer sftp,
-                                 SilcSFTPPacket type, 
-                                 uint32 len, ...)
+                                 SilcSFTPPacket type,
+                                 SilcUInt32 len, ...)
 {
-  SilcBuffer packet;
+  SilcBuffer tmp;
   va_list vp;
+  int ret;
 
   va_start(vp, len);
-  packet = silc_sftp_packet_encode_vp(type, len, vp);
+  tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
   va_end(vp);
-
-  if (!packet)
+  if (!tmp)
     return;
+  sftp->packet = tmp;
 
-  SILC_LOG_HEXDUMP(("SFTP packet to client"), packet->data, packet->len);
+  SILC_LOG_HEXDUMP(("SFTP packet to client"), silc_buffer_data(sftp->packet),
+                  silc_buffer_len(sftp->packet));
 
   /* Send the packet */
-  (*sftp->send_packet)(sftp->sock, packet, sftp->send_context);
+  while (silc_buffer_len(sftp->packet) > 0) {
+    ret = silc_stream_write(sftp->stream, silc_buffer_data(sftp->packet),
+                           silc_buffer_len(sftp->packet));
+    if (ret == -2) {
+      SILC_LOG_ERROR(("Error sending SFTP packet type %d", type));
+      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 == -1)
+      return;
+
+    silc_buffer_pull(sftp->packet, ret);
+  }
 
-  silc_buffer_free(packet);
+  /* Clear packet */
+  silc_buffer_reset(sftp->packet);
+}
+
+/* Handles stream I/O */
+
+static void silc_sftp_server_io(SilcStream stream, SilcStreamStatus status,
+                               void *context)
+{
+  SilcSFTPServer sftp = context;
+  unsigned char inbuf[33792];
+  SilcBufferStruct packet;
+  int ret;
+
+  switch (status) {
+  case SILC_STREAM_CAN_READ:
+    SILC_LOG_DEBUG(("Reading data from stream"));
+
+    /* Read data from stream */
+    ret = silc_stream_read(stream, inbuf, sizeof(inbuf));
+    if (ret <= 0) {
+      if (ret == 0)
+       sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
+      if (ret == -2)
+       sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
+      return;
+    }
+
+    /* Now process the SFTP packet */
+    silc_buffer_set(&packet, inbuf, ret);
+    silc_sftp_server_receive_process(context, &packet);
+    break;
+
+  case SILC_STREAM_CAN_WRITE:
+    if (!silc_buffer_headlen(sftp->packet))
+      return;
+
+    SILC_LOG_DEBUG(("Writing pending data to stream"));
+
+    /* Write pending data to stream */
+    silc_buffer_push(sftp->packet, silc_buffer_headlen(sftp->packet));
+    while (silc_buffer_len(sftp->packet) > 0) {
+      ret = silc_stream_write(stream, sftp->packet->data,
+                             silc_buffer_len(sftp->packet));
+      if (ret == 0) {
+       sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
+       silc_buffer_reset(sftp->packet);
+       return;
+      }
+
+      if (ret == -2) {
+       sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
+       silc_buffer_reset(sftp->packet);
+       return;
+      }
+
+      if (ret == -1)
+       return;
+
+      /* Wrote data */
+      silc_buffer_pull(sftp->packet, ret);
+    }
+    break;
+
+  default:
+    break;
+  }
 }
 
 /* Sends error to the client */
 
 static void silc_sftp_send_error(SilcSFTPServer sftp,
                                 SilcSFTPStatus status,
-                                uint32 id)
+                                SilcUInt32 id)
 {
   SILC_LOG_DEBUG(("Send error %d", status));
 
@@ -83,12 +174,12 @@ static void silc_sftp_server_status(SilcSFTP sftp,
                                    void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  uint32 id = (uint32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   int mlen, llen;
 
   SILC_LOG_DEBUG(("Status callback"));
   SILC_LOG_DEBUG(("Request ID: %d", id));
-  
+
   if (!message)
     message = "";
   if (!language_tag)
@@ -114,9 +205,9 @@ static void silc_sftp_server_handle(SilcSFTP sftp,
                                    void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  uint32 id = (uint32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   unsigned char *hdata;
-  uint32 hdata_len;
+  SilcUInt32 hdata_len;
 
   SILC_LOG_DEBUG(("Handle callback"));
   SILC_LOG_DEBUG(("Request ID: %d", id));
@@ -145,11 +236,11 @@ static void silc_sftp_server_handle(SilcSFTP sftp,
 static void silc_sftp_server_data(SilcSFTP sftp,
                                  SilcSFTPStatus status,
                                  const unsigned char *data,
-                                 uint32 data_len,
+                                 SilcUInt32 data_len,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  uint32 id = (uint32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
 
   SILC_LOG_DEBUG(("Data callback"));
   SILC_LOG_DEBUG(("Request ID: %d", id));
@@ -174,7 +265,7 @@ static void silc_sftp_server_name(SilcSFTP sftp,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  uint32 id = (uint32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   SilcBuffer namebuf;
 
   SILC_LOG_DEBUG(("Name callback"));
@@ -191,9 +282,10 @@ static void silc_sftp_server_name(SilcSFTP sftp,
     return;
   }
 
-  silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + namebuf->len,
+  silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + silc_buffer_len(namebuf),
                        SILC_STR_UI_INT(id),
-                       SILC_STR_UI_XNSTRING(namebuf->data, namebuf->len),
+                       SILC_STR_DATA(silc_buffer_data(namebuf),
+                                     silc_buffer_len(namebuf)),
                        SILC_STR_END);
 }
 
@@ -205,7 +297,7 @@ static void silc_sftp_server_attr(SilcSFTP sftp,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  uint32 id = (uint32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   SilcBuffer attr_buf;
 
   SILC_LOG_DEBUG(("Attr callback"));
@@ -217,10 +309,15 @@ static void silc_sftp_server_attr(SilcSFTP sftp,
   }
 
   attr_buf = silc_sftp_attr_encode(attrs);
+  if (!attr_buf) {
+    silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
+    return;
+  }
 
-  silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + attr_buf->len,
+  silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + silc_buffer_len(attr_buf),
                        SILC_STR_UI_INT(id),
-                       SILC_STR_UI_XNSTRING(attr_buf->data, attr_buf->len),
+                       SILC_STR_DATA(silc_buffer_data(attr_buf),
+                                     silc_buffer_len(attr_buf)),
                        SILC_STR_END);
 
   silc_buffer_free(attr_buf);
@@ -231,11 +328,11 @@ static void silc_sftp_server_attr(SilcSFTP sftp,
 static void silc_sftp_server_extended(SilcSFTP sftp,
                                      SilcSFTPStatus status,
                                      const unsigned char *data,
-                                     uint32 data_len,
+                                     SilcUInt32 data_len,
                                      void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  uint32 id = (uint32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
 
   SILC_LOG_DEBUG(("Extended callback"));
   SILC_LOG_DEBUG(("Request ID: %d", id));
@@ -251,25 +348,34 @@ static void silc_sftp_server_extended(SilcSFTP sftp,
                        SILC_STR_END);
 }
 
-/* Starts SFTP server by associating the socket connection `sock' to the
-   created SFTP server context.  This function returns the allocated
-   SFTP client context or NULL on error. The `send_packet' is called
+/* Starts SFTP server and returns context to it.  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. */
 
-SilcSFTP silc_sftp_server_start(SilcSocketConnection sock,
-                               SilcSFTPSendPacketCallback send_packet,
-                               void *send_context,
+SilcSFTP silc_sftp_server_start(SilcStream stream,
+                               SilcSchedule schedule,
+                               SilcSFTPErrorCallback error_cb,
+                               void *context,
                                SilcSFTPFilesystem fs)
 {
   SilcSFTPServer server;
 
+  if (!schedule)
+    schedule = silc_schedule_get_global();
+
   server = silc_calloc(1, sizeof(*server));
-  server->sock = sock;
-  server->send_packet = send_packet;
-  server->send_context = send_context;
+  if (!server)
+    return NULL;
+  server->stream = stream;
+  server->schedule = schedule;
+  server->error = error_cb;
+  server->context = context;
   server->fs = fs;
 
+  /* We handle the stream now */
+  silc_stream_set_notifier(stream, schedule, silc_sftp_server_io, server);
+
   SILC_LOG_DEBUG(("Starting SFTP server %p", server));
 
   return (SilcSFTP)server;
@@ -285,6 +391,9 @@ void silc_sftp_server_shutdown(SilcSFTP sftp)
 
   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);
 }
 
@@ -292,7 +401,7 @@ void silc_sftp_server_shutdown(SilcSFTP sftp)
 
 void silc_sftp_server_set_monitor(SilcSFTP sftp,
                                  SilcSFTPMonitors monitors,
-                                 SilcSFTPMonitor monitor, 
+                                 SilcSFTPMonitor monitor,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
@@ -302,21 +411,17 @@ void silc_sftp_server_set_monitor(SilcSFTP sftp,
 }
 
 /* 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. */
 
-void silc_sftp_server_receive_process(SilcSFTP sftp,
-                                     SilcSocketConnection sock,
-                                     SilcPacketContext *packet)
+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;
-  uint32 payload_len;
+  unsigned char *payload = NULL;
+  SilcUInt32 payload_len;
   int ret;
   SilcBufferStruct buf;
-  uint32 id;
+  SilcUInt32 id;
   SilcSFTPAttributes attrs;
   SilcSFTPHandle handle;
   SilcSFTPMonitorDataStruct mdata;
@@ -324,16 +429,103 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
   SILC_LOG_DEBUG(("Start"));
 
   /* Parse the packet */
-  type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload, 
-                                &payload_len);
-  if (!type)
+  type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
+  if (type <= 0)
     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;
@@ -363,7 +555,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
     {
       SilcSFTPFileOperation pflags;
       unsigned char *attr_buf;
-      uint32 attr_len = 0;
+      SilcUInt32 attr_len = 0;
       SilcBufferStruct tmpbuf;
 
       SILC_LOG_DEBUG(("Open request"));
@@ -372,7 +564,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
                                 SILC_STR_UI_INT(&id),
                                 SILC_STR_UI32_STRING_ALLOC(&filename),
                                 SILC_STR_UI_INT(&pflags),
-                                SILC_STR_UI32_NSTRING(&attr_buf, 
+                                SILC_STR_UI32_NSTRING(&attr_buf,
                                                       &attr_len),
                                 SILC_STR_END);
       if (ret < 0)
@@ -381,8 +573,12 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       if (attr_len) {
        silc_buffer_set(&tmpbuf, attr_buf, attr_len);
        attrs = silc_sftp_attr_decode(&tmpbuf);
+       if (!attrs)
+         goto failure;
       } else {
        attrs = silc_calloc(1, sizeof(*attrs));
+       if (!attrs)
+         goto failure;
       }
 
       /* Call monitor */
@@ -395,7 +591,8 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Open operation */
       server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
-                               attrs, silc_sftp_server_handle, (void *)id);
+                               attrs, silc_sftp_server_handle,
+                               SILC_32_TO_PTR(id));
 
       silc_free(filename);
       silc_sftp_attr_free(attrs);
@@ -405,13 +602,13 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
   case SILC_SFTP_CLOSE:
     {
       unsigned char *hdata;
-      uint32 hdata_len;
+      SilcUInt32 hdata_len;
 
       SILC_LOG_DEBUG(("Close request"));
 
       ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&hdata, 
+                                SILC_STR_UI32_NSTRING(&hdata,
                                                       &hdata_len),
                                 SILC_STR_END);
       if (ret < 0)
@@ -434,95 +631,8 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Close operation */
       server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
-                                silc_sftp_server_status, (void *)id);
-    }
-    break;
+                                silc_sftp_server_status, SILC_32_TO_PTR(id));
 
-  case SILC_SFTP_READ:
-    {
-      unsigned char *hdata;
-      uint32 hdata_len;
-      uint64 offset;
-      uint32 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;
-      }
-
-      /* 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);
-      }
-
-      /* Read operation */
-      server->fs->fs->sftp_read(server->fs->fs_context, sftp, 
-                               handle, offset, len,
-                               silc_sftp_server_data, (void *)id);
-    }
-    break;
-
-  case SILC_SFTP_WRITE:
-    {
-      unsigned char *hdata;
-      uint32 hdata_len;
-      uint64 offset;
-      unsigned char *data;
-      uint32 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;
-      }
-
-      /* 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);
-      }
-
-      /* Write operation */
-      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;
 
@@ -546,7 +656,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Remove operation */
       server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
-                                 silc_sftp_server_status, (void *)id);
+                                 silc_sftp_server_status, SILC_32_TO_PTR(id));
 
       silc_free(filename);
     }
@@ -575,9 +685,9 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       }
 
       /* Rename operation */
-      server->fs->fs->sftp_rename(server->fs->fs_context, sftp, 
+      server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
                                  filename, newname,
-                                 silc_sftp_server_status, (void *)id);
+                                 silc_sftp_server_status, SILC_32_TO_PTR(id));
 
       silc_free(filename);
       silc_free(newname);
@@ -587,7 +697,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
   case SILC_SFTP_MKDIR:
     {
       unsigned char *attr_buf;
-      uint32 attr_len = 0;
+      SilcUInt32 attr_len = 0;
       SilcBufferStruct tmpbuf;
 
       SILC_LOG_DEBUG(("Mkdir request"));
@@ -604,8 +714,12 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       if (attr_len) {
        silc_buffer_set(&tmpbuf, attr_buf, attr_len);
        attrs = silc_sftp_attr_decode(&tmpbuf);
+       if (!attrs)
+         goto failure;
       } else {
        attrs = silc_calloc(1, sizeof(*attrs));
+       if (!attrs)
+         goto failure;
       }
 
       /* Call monitor */
@@ -617,7 +731,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Mkdir operation */
       server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
-                                silc_sftp_server_status, (void *)id);
+                                silc_sftp_server_status, SILC_32_TO_PTR(id));
 
       silc_sftp_attr_free(attrs);
       silc_free(path);
@@ -644,7 +758,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Rmdir operation */
       server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
-                                silc_sftp_server_status, (void *)id);
+                                silc_sftp_server_status, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -670,7 +784,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Opendir operation */
       server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
-                                  silc_sftp_server_handle, (void *)id);
+                                  silc_sftp_server_handle, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -679,13 +793,13 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
   case SILC_SFTP_READDIR:
     {
       unsigned char *hdata;
-      uint32 hdata_len;
+      SilcUInt32 hdata_len;
 
       SILC_LOG_DEBUG(("Readdir request"));
 
       ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&hdata, 
+                                SILC_STR_UI32_NSTRING(&hdata,
                                                       &hdata_len),
                                 SILC_STR_END);
       if (ret < 0)
@@ -708,7 +822,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Readdir operation */
       server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
-                                  silc_sftp_server_name, (void *)id);
+                                  silc_sftp_server_name, SILC_32_TO_PTR(id));
     }
     break;
 
@@ -732,7 +846,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Stat operation */
       server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
-                               silc_sftp_server_attr, (void *)id);
+                               silc_sftp_server_attr, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -758,7 +872,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Lstat operation */
       server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
-                                silc_sftp_server_attr, (void *)id);
+                                silc_sftp_server_attr, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -767,13 +881,13 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
   case SILC_SFTP_FSTAT:
     {
       unsigned char *hdata;
-      uint32 hdata_len;
+      SilcUInt32 hdata_len;
 
       SILC_LOG_DEBUG(("Fstat request"));
 
       ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&hdata, 
+                                SILC_STR_UI32_NSTRING(&hdata,
                                                       &hdata_len),
                                 SILC_STR_END);
       if (ret < 0)
@@ -796,14 +910,14 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Fstat operation */
       server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
-                                silc_sftp_server_attr, (void *)id);
+                                silc_sftp_server_attr, SILC_32_TO_PTR(id));
     }
     break;
 
   case SILC_SFTP_SETSTAT:
     {
       unsigned char *attr_buf;
-      uint32 attr_len = 0;
+      SilcUInt32 attr_len = 0;
       SilcBufferStruct tmpbuf;
 
       SILC_LOG_DEBUG(("Setstat request"));
@@ -820,8 +934,12 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       if (attr_len) {
        silc_buffer_set(&tmpbuf, attr_buf, attr_len);
        attrs = silc_sftp_attr_decode(&tmpbuf);
+       if (!attrs)
+         goto failure;
       } else {
        attrs = silc_calloc(1, sizeof(*attrs));
+       if (!attrs)
+         goto failure;
       }
 
       /* Call monitor */
@@ -833,7 +951,8 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Setstat operation */
       server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
-                                  silc_sftp_server_status, (void *)id);
+                                  silc_sftp_server_status,
+                                  SILC_32_TO_PTR(id));
 
       silc_sftp_attr_free(attrs);
       silc_free(path);
@@ -843,14 +962,14 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
   case SILC_SFTP_FSETSTAT:
     {
       unsigned char *hdata, *attr_buf;
-      uint32 hdata_len, attr_len = 0;
+      SilcUInt32 hdata_len, attr_len = 0;
       SilcBufferStruct tmpbuf;
 
       SILC_LOG_DEBUG(("Fsetstat request"));
 
       ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&hdata, 
+                                SILC_STR_UI32_NSTRING(&hdata,
                                                       &hdata_len),
                                 SILC_STR_UI32_NSTRING(&attr_buf,
                                                       &attr_len),
@@ -861,8 +980,12 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       if (attr_len) {
        silc_buffer_set(&tmpbuf, attr_buf, attr_len);
        attrs = silc_sftp_attr_decode(&tmpbuf);
+       if (!attrs)
+         goto failure;
       } else {
        attrs = silc_calloc(1, sizeof(*attrs));
+       if (!attrs)
+         goto failure;
       }
 
       /* Get the handle */
@@ -881,9 +1004,10 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       }
 
       /* Fsetstat operation */
-      server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp, 
+      server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
                                    handle, attrs,
-                                   silc_sftp_server_status, (void *)id);
+                                   silc_sftp_server_status,
+                                   SILC_32_TO_PTR(id));
 
       silc_sftp_attr_free(attrs);
     }
@@ -909,7 +1033,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Readlink operation */
       server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
-                                   silc_sftp_server_name, (void *)id);
+                                   silc_sftp_server_name, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -939,7 +1063,8 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Symlink operation */
       server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
-                                  silc_sftp_server_status, (void *)id);
+                                  silc_sftp_server_status,
+                                  SILC_32_TO_PTR(id));
 
       silc_free(path);
       silc_free(target);
@@ -966,7 +1091,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Realpath operation */
       server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
-                                   silc_sftp_server_name, (void *)id);
+                                   silc_sftp_server_name, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -976,7 +1101,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
     {
       char *request = NULL;
       unsigned char *data;
-      uint32 data_len;
+      SilcUInt32 data_len;
 
       SILC_LOG_DEBUG(("Extended request"));
 
@@ -990,11 +1115,11 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       data_len = 8 + strlen(request);
       silc_buffer_pull(&buf, data_len);
       ret = silc_buffer_unformat(&buf,
-                                SILC_STR_UI_XNSTRING(&data, buf.len),
+                                SILC_STR_DATA(&data, silc_buffer_len(&buf)),
                                 SILC_STR_END);
       if (ret < 0)
        goto failure;
-      data_len = buf.len;
+      data_len = silc_buffer_len(&buf);
 
       /* Call monitor */
       if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
@@ -1003,9 +1128,10 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       }
 
       /* Extended operation */
-      server->fs->fs->sftp_extended(server->fs->fs_context, sftp, 
+      server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
                                    request, data, data_len,
-                                   silc_sftp_server_extended, (void *)id);
+                                   silc_sftp_server_extended,
+                                   SILC_32_TO_PTR(id));
 
       silc_free(request);
     }