Merged from silc_1_0_branch.
[silc.git] / lib / silcsftp / sftp_util.c
index eb4652accfde62761205aac15da665dca6fd77e5..dc2f5cff67e19fab735a3a158518b0e0289e298a 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2002 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
 /* 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,13 +45,30 @@ 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);
+  if (packet_buf) {
+    if (packet_buf->truelen < 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, SILC_BUFFER_END(buffer));
   silc_buffer_format(buffer, 
                     SILC_STR_UI_INT(len),
@@ -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;
   }
 
@@ -73,10 +94,10 @@ SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, uint32 len,
 
 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,
@@ -112,7 +133,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;
@@ -131,8 +153,9 @@ SilcBuffer silc_sftp_attr_encode(SilcSFTPAttributes attr)
     }
   }
 
-  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), 
@@ -202,6 +225,8 @@ 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), 
@@ -262,9 +287,12 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer)
                                      sizeof(*attr->extended_type));
     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, 
                               SILC_STR_UI32_NSTRING(&tmp, &tmp_len),
@@ -274,6 +302,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);
 
@@ -315,6 +345,8 @@ void silc_sftp_name_add(SilcSFTPName name, const char *short_name,
                                     (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);
@@ -332,13 +364,20 @@ 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]);
+    if (!attr_buf[i])
+      return NULL;
     len += attr_buf[i]->len;
   }
 
   buffer = silc_buffer_alloc(len);
+  if (!buffer)
+    return NULL;
   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
 
   silc_buffer_format(buffer,
@@ -371,16 +410,22 @@ 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++) {
@@ -399,6 +444,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;
@@ -435,7 +484,6 @@ SilcSFTPStatus silc_sftp_map_errno(int err)
   case ENOENT:
   case ENOTDIR:
   case EBADF:
-  case ELOOP:
     ret = SILC_SFTP_STATUS_NO_SUCH_FILE;
     break;
   case EPERM: