1 /* buffer.c */ 2 /* Well, buffers */ 3 /* 4 Copyright 2003 Aris Adamantiadis 5 6 This file is part of the SSH Library 7 8 The SSH Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 2.1 of the License, or (at your 11 option) any later version. 12 13 The SSH Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the SSH Library; see the file COPYING. If not, write to 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 21 MA 02111-1307, USA. */ 22 23 #include "libssh/priv.h" 24 #include <stdlib.h> 25 #include <string.h> 26 #ifdef HAVE_NETDB_H 27 #include <netdb.h> 28 #endif 29 BUFFER *buffer_new(){ 30 BUFFER *buffer=malloc(sizeof(BUFFER)); 31 memset(buffer,0,sizeof(BUFFER)); 32 return buffer; 33 } 34 35 void buffer_free(BUFFER *buffer){ 36 if(buffer->data){ 37 memset(buffer->data,0,buffer->allocated); /* burn the data */ 38 free(buffer->data); 39 } 40 free(buffer); 41 } 42 43 void buffer_reinit(BUFFER *buffer){ 44 memset(buffer->data,0,buffer->used); 45 buffer->used=0; 46 buffer->pos=0; 47 } 48 49 static void realloc_buffer(BUFFER *buffer,int needed){ 50 needed=(needed+0x7f) & ~0x7f; 51 buffer->data=realloc(buffer->data,needed); 52 buffer->allocated=needed; 53 } 54 55 void buffer_add_data(BUFFER *buffer,void *data,int len){ 56 if(buffer->allocated < buffer->used+len) 57 realloc_buffer(buffer,buffer->used+len); 58 memcpy(buffer->data+buffer->used,data,len); 59 buffer->used+=len; 60 } 61 62 void buffer_add_ssh_string(BUFFER *buffer,STRING *string){ 63 u32 len=ntohl(string->size); 64 buffer_add_data(buffer,string,len+sizeof(u32)); 65 } 66 67 void buffer_add_u32(BUFFER *buffer,u32 data){ 68 buffer_add_data(buffer,&data,sizeof(data)); 69 } 70 71 void buffer_add_u64(BUFFER *buffer,u64 data){ 72 buffer_add_data(buffer,&data,sizeof(data)); 73 } 74 75 void buffer_add_u8(BUFFER *buffer,u8 data){ 76 buffer_add_data(buffer,&data,sizeof(u8)); 77 } 78 79 void buffer_add_data_begin(BUFFER *buffer, void *data, int len){ 80 if(buffer->allocated < buffer->used + len) 81 realloc_buffer(buffer,buffer->used+len); 82 memmove(buffer->data+len,buffer->data,buffer->used); 83 memcpy(buffer->data,data,len); 84 buffer->used+=len; 85 } 86 87 void buffer_add_buffer(BUFFER *buffer, BUFFER *source){ 88 buffer_add_data(buffer,buffer_get(source),buffer_get_len(source)); 89 } 90 91 void *buffer_get(BUFFER *buffer){ 92 return buffer->data; 93 } 94 95 void *buffer_get_rest(BUFFER *buffer){ 96 return buffer->data+buffer->pos; 97 } 98 99 int buffer_get_len(BUFFER *buffer){ 100 return buffer->used; 101 } 102 103 int buffer_get_rest_len(BUFFER *buffer){ 104 return buffer->used - buffer->pos; 105 } 106 107 int buffer_pass_bytes(BUFFER *buffer,int len){ 108 if(buffer->used < buffer->pos+len) 109 return 0; 110 buffer->pos+=len; 111 /* if the buffer is empty after having passed the whole bytes into it, we can clean it */ 112 if(buffer->pos==buffer->used){ 113 buffer->pos=0; 114 buffer->used=0; 115 } 116 return len; 117 } 118 119 int buffer_pass_bytes_end(BUFFER *buffer,int len){ 120 if(buffer->used < buffer->pos + len) 121 return 0; 122 buffer->used-=len; 123 return len; 124 } 125 126 int buffer_get_data(BUFFER *buffer, void *data, int len){ 127 if(buffer->pos+len>buffer->used) 128 return 0; /*no enough data in buffer */ 129 memcpy(data,buffer->data+buffer->pos,len); 130 buffer->pos+=len; 131 return len; /* no yet support for partial reads (is it really needed ?? ) */ 132 } 133 134 int buffer_get_u8(BUFFER *buffer, u8 *data){ 135 return buffer_get_data(buffer,data,sizeof(u8)); 136 } 137 138 int buffer_get_u32(BUFFER *buffer, u32 *data){ 139 return buffer_get_data(buffer,data,sizeof(u32)); 140 } 141 142 int buffer_get_u64(BUFFER *buffer, u64 *data){ 143 return buffer_get_data(buffer,data,sizeof(u64)); 144 } 145 146 STRING *buffer_get_ssh_string(BUFFER *buffer){ 147 u32 stringlen; 148 u32 hostlen; 149 STRING *str; 150 if(buffer_get_u32(buffer,&stringlen)==0) 151 return NULL; 152 hostlen=ntohl(stringlen); 153 /* verify if there is enough space in buffer to get it */ 154 if(buffer->pos+hostlen>buffer->used) 155 return 0; /* it is indeed */ 156 str=string_new(hostlen); 157 if(buffer_get_data(buffer,str->string,hostlen)!=hostlen){ 158 ssh_say(0,"buffer_get_ssh_string: oddish : second test failed when first was successful. len=%d",hostlen); 159 free(str); 160 return NULL; 161 } 162 return str; 163 } |