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 <stdlib.h> 24 #include <string.h> 25 #include <netdb.h> 26 #include "libssh/priv.h" 27 BUFFER *buffer_new(){ 28 BUFFER *buffer=malloc(sizeof(BUFFER)); 29 memset(buffer,0,sizeof(BUFFER)); 30 return buffer; 31 } 32 33 void buffer_free(BUFFER *buffer){ 34 if(buffer->data){ 35 memset(buffer->data,0,buffer->allocated); /* burn the data */ 36 free(buffer->data); 37 } 38 free(buffer); 39 } 40 41 void buffer_reinit(BUFFER *buffer){ 42 memset(buffer->data,0,buffer->used); 43 buffer->used=0; 44 buffer->pos=0; 45 } 46 47 static void realloc_buffer(BUFFER *buffer,int needed){ 48 needed=(needed+0x7f) & ~0x7f; 49 buffer->data=realloc(buffer->data,needed); 50 buffer->allocated=needed; 51 } 52 53 void buffer_add_data(BUFFER *buffer,void *data,int len){ 54 if(buffer->allocated < buffer->used+len) 55 realloc_buffer(buffer,buffer->used+len); 56 memcpy(buffer->data+buffer->used,data,len); 57 buffer->used+=len; 58 } 59 60 void buffer_add_ssh_string(BUFFER *buffer,STRING *string){ 61 u32 len=ntohl(string->size); 62 buffer_add_data(buffer,string,len+sizeof(u32)); 63 } 64 65 void buffer_add_u32(BUFFER *buffer,u32 data){ 66 buffer_add_data(buffer,&data,sizeof(data)); 67 } 68 69 void buffer_add_u64(BUFFER *buffer,u64 data){ 70 buffer_add_data(buffer,&data,sizeof(data)); 71 } 72 73 void buffer_add_u8(BUFFER *buffer,u8 data){ 74 buffer_add_data(buffer,&data,sizeof(u8)); 75 } 76 77 void buffer_add_data_begin(BUFFER *buffer, void *data, int len){ 78 if(buffer->allocated < buffer->used + len) 79 realloc_buffer(buffer,buffer->used+len); 80 memmove(buffer->data+len,buffer->data,buffer->used); 81 memcpy(buffer->data,data,len); 82 buffer->used+=len; 83 } 84 85 void buffer_add_buffer(BUFFER *buffer, BUFFER *source){ 86 buffer_add_data(buffer,buffer_get(source),buffer_get_len(source)); 87 } 88 89 void *buffer_get(BUFFER *buffer){ 90 return buffer->data; 91 } 92 93 void *buffer_get_rest(BUFFER *buffer){ 94 return buffer->data+buffer->pos; 95 } 96 97 int buffer_get_len(BUFFER *buffer){ 98 return buffer->used; 99 } 100 101 int buffer_get_rest_len(BUFFER *buffer){ 102 return buffer->used - buffer->pos; 103 } 104 105 int buffer_pass_bytes(BUFFER *buffer,int len){ 106 if(buffer->used < buffer->pos+len) 107 return 0; 108 buffer->pos+=len; 109 /* if the buffer is empty after having passed the whole bytes into it, we can clean it */ 110 if(buffer->pos==buffer->used){ 111 buffer->pos=0; 112 buffer->used=0; 113 } 114 return len; 115 } 116 117 int buffer_pass_bytes_end(BUFFER *buffer,int len){ 118 if(buffer->used < buffer->pos + len) 119 return 0; 120 buffer->used-=len; 121 return len; 122 } 123 124 int buffer_get_data(BUFFER *buffer, void *data, int len){ 125 if(buffer->pos+len>buffer->used) 126 return 0; /*no enough data in buffer */ 127 memcpy(data,buffer->data+buffer->pos,len); 128 buffer->pos+=len; 129 return len; /* no yet support for partial reads (is it really needed ?? ) */ 130 } 131 132 int buffer_get_u8(BUFFER *buffer, u8 *data){ 133 return buffer_get_data(buffer,data,sizeof(u8)); 134 } 135 136 int buffer_get_u32(BUFFER *buffer, u32 *data){ 137 return buffer_get_data(buffer,data,sizeof(u32)); 138 } 139 140 int buffer_get_u64(BUFFER *buffer, u64 *data){ 141 return buffer_get_data(buffer,data,sizeof(u64)); 142 } 143 144 STRING *buffer_get_ssh_string(BUFFER *buffer){ 145 u32 stringlen; 146 u32 hostlen; 147 STRING *str; 148 if(buffer_get_u32(buffer,&stringlen)==0) 149 return NULL; 150 hostlen=ntohl(stringlen); 151 /* verify if there is enough space in buffer to get it */ 152 if(buffer->pos+hostlen>buffer->used) 153 return 0; /* it is indeed */ 154 str=string_new(hostlen); 155 if(buffer_get_data(buffer,str->string,hostlen)!=hostlen){ 156 ssh_say(0,"buffer_get_ssh_string: oddish : second test failed when first was successful. len=%d",hostlen); 157 free(str); 158 return NULL; 159 } 160 return str; 161 } |