Changed SILC code to use new SRT and SCT APIs.
[silc.git] / lib / silcsftp / sftp_util.c
index 86cca1f975a37cb38446aea41428f63c2b4768ac..6ec07bba94c2aec6b414bde5dcaa5cdf8f7f0cfb 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  sftp_util.c 
+  sftp_util.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2008 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 "sftp_util.h"
 
 /* Encodes a SFTP packet of type `packet' of length `len'. The variable
    argument list is encoded as data payload to the buffer. Returns the
    encoded packet or NULL on error. The caller must free the returned
-   buffer. */
+   buffer. If `packet_buf' is non-NULL then the new packet data is put
+   to that buffer instead of allocating new one.  If the new data cannot
+   fit to `packet_buf' will be reallocated. */
 
-SilcBuffer silc_sftp_packet_encode(SilcSFTPPacket packet, uint32 len, ...)
+SilcBuffer silc_sftp_packet_encode(SilcSFTPPacket packet,
+                                  SilcBuffer packet_buf, SilcUInt32 len, ...)
 {
   SilcBuffer buffer;
   va_list vp;
 
   va_start(vp, len);
-  buffer = silc_sftp_packet_encode_vp(packet, len, vp);
+  buffer = silc_sftp_packet_encode_vp(packet, packet_buf, len, vp);
   va_end(vp);
 
   return buffer;
@@ -42,15 +45,32 @@ SilcBuffer silc_sftp_packet_encode(SilcSFTPPacket packet, uint32 len, ...)
 /* Same as silc_sftp_packet_encode but takes the variable argument list
    pointer as argument. */
 
-SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, uint32 len, 
+SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet,
+                                     SilcBuffer packet_buf, SilcUInt32 len,
                                      va_list vp)
 {
   SilcBuffer buffer;
+  bool dyn;
   int ret;
 
-  buffer = silc_buffer_alloc(4 + 1 + len);
-  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
-  silc_buffer_format(buffer, 
+  if (packet_buf) {
+    if (silc_buffer_truelen(packet_buf) < 4 + 1 + len) {
+      packet_buf = silc_buffer_realloc(packet_buf, 4 + 1 + len);
+      if (!packet_buf)
+       return NULL;
+    }
+
+    buffer = packet_buf;
+    dyn = FALSE;
+  } else {
+    buffer = silc_buffer_alloc(4 + 1 + len);
+    if (!buffer)
+      return NULL;
+    dyn = TRUE;
+  }
+
+  silc_buffer_pull_tail(buffer, 4 + 1 + len);
+  silc_buffer_format(buffer,
                     SILC_STR_UI_INT(len),
                     SILC_STR_UI_CHAR(packet),
                     SILC_STR_END);
@@ -58,7 +78,8 @@ SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, uint32 len,
 
   ret = silc_buffer_format_vp(buffer, vp);
   if (ret < 0) {
-    silc_buffer_free(buffer);
+    if (dyn)
+      silc_buffer_free(buffer);
     return NULL;
   }
 
@@ -69,14 +90,15 @@ SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, uint32 len,
 
 /* Decodes the SFTP packet data `packet' and return the SFTP packet type.
    The payload of the packet is returned to the `payload' pointer. Returns
-   0 if error occurred during decoding. */
+   0 if error occurred during decoding and -1 if partial packet was
+   received. */
 
 SilcSFTPPacket silc_sftp_packet_decode(SilcBuffer packet,
                                       unsigned char **payload,
-                                      uint32 *payload_len)
+                                      SilcUInt32 *payload_len)
 {
-  uint32 len;
-  uint8 type;
+  SilcUInt32 len;
+  SilcUInt8 type;
   int ret;
 
   ret = silc_buffer_unformat(packet,
@@ -89,11 +111,11 @@ SilcSFTPPacket silc_sftp_packet_decode(SilcBuffer packet,
   if (type < SILC_SFTP_INIT || type > SILC_SFTP_EXTENDED_REPLY)
     return 0;
 
-  if (len > (packet->len - 5))
-    return 0;
+  if (len > (silc_buffer_len(packet) - 5))
+    return -1;
 
   silc_buffer_pull(packet, 5);
-  ret = silc_buffer_unformat(packet, 
+  ret = silc_buffer_unformat(packet,
                             SILC_STR_UI_XNSTRING(payload, len),
                             SILC_STR_END);
   if (ret < 0)
@@ -112,7 +134,8 @@ SilcSFTPPacket silc_sftp_packet_decode(SilcBuffer packet,
 SilcBuffer silc_sftp_attr_encode(SilcSFTPAttributes attr)
 {
   SilcBuffer buffer;
-  int i, ret, len = 4;
+  int i, ret;
+  SilcUInt32 len = 4;
 
   if (attr->flags & SILC_SFTP_ATTR_SIZE)
     len += 8;
@@ -126,65 +149,67 @@ SilcBuffer silc_sftp_attr_encode(SilcSFTPAttributes attr)
     len += 4;
     for (i = 0; i < attr->extended_count; i++) {
       len += 8;
-      len += attr->extended_type[i]->len;
-      len += attr->extended_data[i]->len;
+      len += silc_buffer_len(attr->extended_type[i]);
+      len += silc_buffer_len(attr->extended_data[i]);
     }
   }
 
-  buffer = silc_buffer_alloc(len);
-  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+  buffer = silc_buffer_alloc_size(len);
+  if (!buffer)
+    return NULL;
 
-  silc_buffer_format(buffer, 
-                    SILC_STR_UI_INT(attr->flags), 
+  silc_buffer_format(buffer,
+                    SILC_STR_UI_INT(attr->flags),
                     SILC_STR_END);
   silc_buffer_pull(buffer, 4);
 
   if (attr->flags & SILC_SFTP_ATTR_SIZE) {
-    silc_buffer_format(buffer, 
-                      SILC_STR_UI_INT64(attr->size), 
+    silc_buffer_format(buffer,
+                      SILC_STR_UI_INT64(attr->size),
                       SILC_STR_END);
     silc_buffer_pull(buffer, 8);
   }
 
   if (attr->flags & SILC_SFTP_ATTR_UIDGID) {
-    silc_buffer_format(buffer, 
-                      SILC_STR_UI_INT(attr->uid), 
-                      SILC_STR_UI_INT(attr->gid), 
+    silc_buffer_format(buffer,
+                      SILC_STR_UI_INT(attr->uid),
+                      SILC_STR_UI_INT(attr->gid),
                       SILC_STR_END);
     silc_buffer_pull(buffer, 8);
   }
 
   if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) {
-    silc_buffer_format(buffer, 
-                      SILC_STR_UI_INT(attr->permissions), 
+    silc_buffer_format(buffer,
+                      SILC_STR_UI_INT(attr->permissions),
                       SILC_STR_END);
     silc_buffer_pull(buffer, 4);
   }
 
   if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) {
-    silc_buffer_format(buffer, 
-                      SILC_STR_UI_INT(attr->atime), 
-                      SILC_STR_UI_INT(attr->mtime), 
+    silc_buffer_format(buffer,
+                      SILC_STR_UI_INT(attr->atime),
+                      SILC_STR_UI_INT(attr->mtime),
                       SILC_STR_END);
     silc_buffer_pull(buffer, 8);
   }
 
   if (attr->flags & SILC_SFTP_ATTR_EXTENDED) {
-    silc_buffer_format(buffer, 
-                      SILC_STR_UI_INT(attr->extended_count), 
+    silc_buffer_format(buffer,
+                      SILC_STR_UI_INT(attr->extended_count),
                       SILC_STR_END);
     silc_buffer_pull(buffer, 4);
 
     for (i = 0; i < attr->extended_count; i++) {
-      ret = 
-       silc_buffer_format(buffer, 
-                          SILC_STR_UI_INT(attr->extended_type[i]->len),
-                          SILC_STR_UI_XNSTRING(attr->extended_type[i]->data,
-                                               attr->extended_type[i]->len),
-                          SILC_STR_UI_INT(attr->extended_data[i]->len),
-                          SILC_STR_UI_XNSTRING(attr->extended_data[i]->data,
-                                               attr->extended_data[i]->len),
-                          SILC_STR_END);
+      ret =
+       silc_buffer_format(
+                  buffer,
+                  SILC_STR_UI_INT(silc_buffer_len(attr->extended_type[i])),
+                  SILC_STR_DATA(silc_buffer_data(attr->extended_type[i]),
+                                silc_buffer_len(attr->extended_type[i])),
+                  SILC_STR_UI_INT(silc_buffer_len(attr->extended_data[i])),
+                  SILC_STR_DATA(silc_buffer_data(attr->extended_data[i]),
+                                silc_buffer_len(attr->extended_data[i])),
+                  SILC_STR_END);
       silc_buffer_pull(buffer, ret);
     }
   }
@@ -202,17 +227,19 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer)
   SilcSFTPAttributes attr;
 
   attr = silc_calloc(1, sizeof(*attr));
+  if (!attr)
+    return NULL;
 
-  if (silc_buffer_unformat(buffer, 
-                          SILC_STR_UI_INT(&attr->flags), 
+  if (silc_buffer_unformat(buffer,
+                          SILC_STR_UI_INT(&attr->flags),
                           SILC_STR_END) < 0)
     goto out;
 
   silc_buffer_pull(buffer, 4);
 
   if (attr->flags & SILC_SFTP_ATTR_SIZE) {
-    if (silc_buffer_unformat(buffer, 
-                            SILC_STR_UI_INT64(&attr->size), 
+    if (silc_buffer_unformat(buffer,
+                            SILC_STR_UI_INT64(&attr->size),
                             SILC_STR_END) < 0)
       goto out;
 
@@ -220,9 +247,9 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer)
   }
 
   if (attr->flags & SILC_SFTP_ATTR_UIDGID) {
-    if (silc_buffer_unformat(buffer, 
-                            SILC_STR_UI_INT(&attr->uid), 
-                            SILC_STR_UI_INT(&attr->gid), 
+    if (silc_buffer_unformat(buffer,
+                            SILC_STR_UI_INT(&attr->uid),
+                            SILC_STR_UI_INT(&attr->gid),
                             SILC_STR_END) < 0)
       goto out;
 
@@ -230,8 +257,8 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer)
   }
 
   if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) {
-    if (silc_buffer_unformat(buffer, 
-                            SILC_STR_UI_INT(&attr->permissions), 
+    if (silc_buffer_unformat(buffer,
+                            SILC_STR_UI_INT(&attr->permissions),
                             SILC_STR_END) < 0)
       goto out;
 
@@ -239,9 +266,9 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer)
   }
 
   if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) {
-    if (silc_buffer_unformat(buffer, 
-                            SILC_STR_UI_INT(&attr->atime), 
-                            SILC_STR_UI_INT(&attr->mtime), 
+    if (silc_buffer_unformat(buffer,
+                            SILC_STR_UI_INT(&attr->atime),
+                            SILC_STR_UI_INT(&attr->mtime),
                             SILC_STR_END) < 0)
       goto out;
 
@@ -251,22 +278,25 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer)
   if (attr->flags & SILC_SFTP_ATTR_EXTENDED) {
     int i;
 
-    if (silc_buffer_unformat(buffer, 
-                            SILC_STR_UI_INT(&attr->extended_count), 
+    if (silc_buffer_unformat(buffer,
+                            SILC_STR_UI_INT(&attr->extended_count),
                             SILC_STR_END) < 0)
       goto out;
 
     silc_buffer_pull(buffer, 4);
 
-    attr->extended_type = silc_calloc(attr->extended_count, 
+    attr->extended_type = silc_calloc(attr->extended_count,
                                      sizeof(*attr->extended_type));
-    attr->extended_data = silc_calloc(attr->extended_count, 
+    attr->extended_data = silc_calloc(attr->extended_count,
                                      sizeof(*attr->extended_data));
+    if (!attr->extended_type || !attr->extended_data)
+      return NULL;
+
     for (i = 0; i < attr->extended_count; i++) {
       unsigned char *tmp, *tmp2;
-      uint32 tmp_len, tmp2_len;
+      SilcUInt32 tmp_len, tmp2_len;
 
-      if (silc_buffer_unformat(buffer, 
+      if (silc_buffer_unformat(buffer,
                               SILC_STR_UI32_NSTRING(&tmp, &tmp_len),
                               SILC_STR_UI32_NSTRING(&tmp2, &tmp2_len),
                               SILC_STR_END) < 0)
@@ -274,6 +304,8 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer)
 
       attr->extended_type[i] = silc_buffer_alloc(tmp_len);
       attr->extended_data[i] = silc_buffer_alloc(tmp2_len);
+      if (!attr->extended_type[i] || !attr->extended_data[i])
+       return NULL;
       silc_buffer_put(attr->extended_type[i], tmp, tmp_len);
       silc_buffer_put(attr->extended_data[i], tmp2, tmp2_len);
 
@@ -310,11 +342,13 @@ void silc_sftp_name_add(SilcSFTPName name, const char *short_name,
 {
   name->filename = silc_realloc(name->filename, sizeof(*name->filename) *
                                (name->count + 1));
-  name->long_filename = silc_realloc(name->long_filename, 
+  name->long_filename = silc_realloc(name->long_filename,
                                     sizeof(*name->long_filename) *
                                     (name->count + 1));
   name->attrs = silc_realloc(name->attrs, sizeof(*name->attrs) *
                             (name->count + 1));
+  if (!name->filename || !name->long_filename || !name->attrs)
+    return;
 
   name->filename[name->count] = strdup(short_name);
   name->long_filename[name->count] = strdup(long_name);
@@ -322,7 +356,7 @@ void silc_sftp_name_add(SilcSFTPName name, const char *short_name,
   name->count++;
 }
 
-/* Encodes the SilcSFTPName to a buffer and returns the allocated buffer. 
+/* Encodes the SilcSFTPName to a buffer and returns the allocated buffer.
    The caller must free the buffer. */
 
 SilcBuffer silc_sftp_name_encode(SilcSFTPName name)
@@ -332,14 +366,21 @@ SilcBuffer silc_sftp_name_encode(SilcSFTPName name)
   SilcBuffer *attr_buf;
 
   attr_buf = silc_calloc(name->count, sizeof(*attr_buf));
+  if (!attr_buf)
+    return NULL;
+
   for (i = 0; i < name->count; i++) {
     len += (8 + strlen(name->filename[i]) + strlen(name->long_filename[i]));
     attr_buf[i] = silc_sftp_attr_encode(name->attrs[i]);
-    len += attr_buf[i]->len;
+    if (!attr_buf[i])
+      return NULL;
+    len += silc_buffer_len(attr_buf[i]);
   }
 
   buffer = silc_buffer_alloc(len);
-  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+  if (!buffer)
+    return NULL;
+  silc_buffer_end(buffer);
 
   silc_buffer_format(buffer,
                     SILC_STR_UI_INT(name->count),
@@ -353,8 +394,8 @@ SilcBuffer silc_sftp_name_encode(SilcSFTPName name)
                         SILC_STR_UI32_STRING(name->filename[i]),
                         SILC_STR_UI_INT(strlen(name->long_filename[i])),
                         SILC_STR_UI32_STRING(name->long_filename[i]),
-                        SILC_STR_UI_XNSTRING(attr_buf[i]->data,
-                                             attr_buf[i]->len),
+                        SILC_STR_DATA(silc_buffer_data(attr_buf[i]),
+                                      silc_buffer_len(attr_buf[i])),
                         SILC_STR_END);
 
     silc_buffer_pull(buffer, len);
@@ -371,20 +412,26 @@ SilcBuffer silc_sftp_name_encode(SilcSFTPName name)
    `count' many name, longname and attribute values. Returns the allocated
    structure or NULL on error. */
 
-SilcSFTPName silc_sftp_name_decode(uint32 count, SilcBuffer buffer)
+SilcSFTPName silc_sftp_name_decode(SilcUInt32 count, SilcBuffer buffer)
 {
   SilcSFTPName name;
   int i;
   int ret;
 
   name = silc_calloc(1, sizeof(*name));
+  if (!name)
+    return NULL;
   name->filename = silc_calloc(count, sizeof(*name->filename));
   name->long_filename = silc_calloc(count, sizeof(*name->filename));
   name->attrs = silc_calloc(count, sizeof(*name->attrs));
+  if (!name->filename || !name->long_filename || !name->attrs) {
+    silc_sftp_name_free(name);
+    return NULL;
+  }
   name->count = count;
 
   for (i = 0; i < count; i++) {
-    ret = 
+    ret =
       silc_buffer_unformat(buffer,
                           SILC_STR_UI32_STRING_ALLOC(&name->filename[i]),
                           SILC_STR_UI32_STRING_ALLOC(&name->long_filename[i]),
@@ -399,6 +446,10 @@ SilcSFTPName silc_sftp_name_decode(uint32 count, SilcBuffer buffer)
     /* Decode attributes, this will pull the `buffer' to correct place
        for next round automatically. */
     name->attrs[i] = silc_sftp_attr_decode(buffer);
+    if (!name->attrs[i]) {
+      silc_sftp_name_free(name);
+      return NULL;
+    }
   }
 
   return name;
@@ -424,7 +475,7 @@ void silc_sftp_name_free(SilcSFTPName name)
 
 /* Maps errno to SFTP status message. */
 
-SilcSFTPStatus silc_sftp_map_errno(int err)
+SilcSFTPStatus silc_sftp_map_errno(SilcResult err)
 {
   SilcSFTPStatus ret;
 
@@ -432,18 +483,15 @@ SilcSFTPStatus silc_sftp_map_errno(int err)
   case 0:
     ret = SILC_SFTP_STATUS_OK;
     break;
-  case ENOENT:
-  case ENOTDIR:
-  case EBADF:
+  case SILC_ERR_NOT_DIRECTORY:
+  case SILC_ERR_NO_SUCH_FILE:
+  case SILC_ERR_BAD_FD:
     ret = SILC_SFTP_STATUS_NO_SUCH_FILE;
     break;
-  case EPERM:
-  case EACCES:
-  case EFAULT:
+  case SILC_ERR_PERMISSION_DENIED:
     ret = SILC_SFTP_STATUS_PERMISSION_DENIED;
     break;
-  case ENAMETOOLONG:
-  case EINVAL:
+  case SILC_ERR_INVALID_ARGUMENT:
     ret = SILC_SFTP_STATUS_BAD_MESSAGE;
     break;
   default: