buffer.c revision 76259
157429Smarkm/* 257429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 357429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 457429Smarkm * All rights reserved 557429Smarkm * Functions for manipulating fifo buffers (that can grow if needed). 660573Skris * 765668Skris * As far as I am concerned, the code I have written for this software 865668Skris * can be used freely for any purpose. Any derived versions of this 965668Skris * software must be clearly marked as such, and if the derived work is 1065668Skris * incompatible with the protocol description in the RFC file, it must be 1165668Skris * called by a name other than "ssh" or "Secure Shell". 1257429Smarkm */ 1357429Smarkm 1457429Smarkm#include "includes.h" 1576259SgreenRCSID("$OpenBSD: buffer.c,v 1.13 2001/04/12 19:15:24 markus Exp $"); 1657429Smarkm 1757429Smarkm#include "xmalloc.h" 1857429Smarkm#include "buffer.h" 1976259Sgreen#include "log.h" 2057429Smarkm 2157429Smarkm/* Initializes the buffer structure. */ 2257429Smarkm 2360573Skrisvoid 2457429Smarkmbuffer_init(Buffer *buffer) 2557429Smarkm{ 2657429Smarkm buffer->alloc = 4096; 2757429Smarkm buffer->buf = xmalloc(buffer->alloc); 2857429Smarkm buffer->offset = 0; 2957429Smarkm buffer->end = 0; 3057429Smarkm} 3157429Smarkm 3257429Smarkm/* Frees any memory used for the buffer. */ 3357429Smarkm 3460573Skrisvoid 3557429Smarkmbuffer_free(Buffer *buffer) 3657429Smarkm{ 3757429Smarkm memset(buffer->buf, 0, buffer->alloc); 3857429Smarkm xfree(buffer->buf); 3957429Smarkm} 4057429Smarkm 4157429Smarkm/* 4257429Smarkm * Clears any data from the buffer, making it empty. This does not actually 4357429Smarkm * zero the memory. 4457429Smarkm */ 4557429Smarkm 4660573Skrisvoid 4757429Smarkmbuffer_clear(Buffer *buffer) 4857429Smarkm{ 4957429Smarkm buffer->offset = 0; 5057429Smarkm buffer->end = 0; 5157429Smarkm} 5257429Smarkm 5357429Smarkm/* Appends data to the buffer, expanding it if necessary. */ 5457429Smarkm 5560573Skrisvoid 5676259Sgreenbuffer_append(Buffer *buffer, const char *data, u_int len) 5757429Smarkm{ 5857429Smarkm char *cp; 5957429Smarkm buffer_append_space(buffer, &cp, len); 6057429Smarkm memcpy(cp, data, len); 6157429Smarkm} 6257429Smarkm 6357429Smarkm/* 6457429Smarkm * Appends space to the buffer, expanding the buffer if necessary. This does 6557429Smarkm * not actually copy the data into the buffer, but instead returns a pointer 6657429Smarkm * to the allocated region. 6757429Smarkm */ 6857429Smarkm 6960573Skrisvoid 7076259Sgreenbuffer_append_space(Buffer *buffer, char **datap, u_int len) 7157429Smarkm{ 7257429Smarkm /* If the buffer is empty, start using it from the beginning. */ 7357429Smarkm if (buffer->offset == buffer->end) { 7457429Smarkm buffer->offset = 0; 7557429Smarkm buffer->end = 0; 7657429Smarkm } 7757429Smarkmrestart: 7857429Smarkm /* If there is enough space to store all data, store it now. */ 7957429Smarkm if (buffer->end + len < buffer->alloc) { 8057429Smarkm *datap = buffer->buf + buffer->end; 8157429Smarkm buffer->end += len; 8257429Smarkm return; 8357429Smarkm } 8457429Smarkm /* 8557429Smarkm * If the buffer is quite empty, but all data is at the end, move the 8657429Smarkm * data to the beginning and retry. 8757429Smarkm */ 8857429Smarkm if (buffer->offset > buffer->alloc / 2) { 8957429Smarkm memmove(buffer->buf, buffer->buf + buffer->offset, 9057429Smarkm buffer->end - buffer->offset); 9157429Smarkm buffer->end -= buffer->offset; 9257429Smarkm buffer->offset = 0; 9357429Smarkm goto restart; 9457429Smarkm } 9557429Smarkm /* Increase the size of the buffer and retry. */ 9657429Smarkm buffer->alloc += len + 32768; 9757429Smarkm buffer->buf = xrealloc(buffer->buf, buffer->alloc); 9857429Smarkm goto restart; 9957429Smarkm} 10057429Smarkm 10157429Smarkm/* Returns the number of bytes of data in the buffer. */ 10257429Smarkm 10376259Sgreenu_int 10457429Smarkmbuffer_len(Buffer *buffer) 10557429Smarkm{ 10657429Smarkm return buffer->end - buffer->offset; 10757429Smarkm} 10857429Smarkm 10957429Smarkm/* Gets data from the beginning of the buffer. */ 11057429Smarkm 11160573Skrisvoid 11276259Sgreenbuffer_get(Buffer *buffer, char *buf, u_int len) 11357429Smarkm{ 11457429Smarkm if (len > buffer->end - buffer->offset) 11576259Sgreen fatal("buffer_get: trying to get more bytes %d than in buffer %d", 11676259Sgreen len, buffer->end - buffer->offset); 11757429Smarkm memcpy(buf, buffer->buf + buffer->offset, len); 11857429Smarkm buffer->offset += len; 11957429Smarkm} 12057429Smarkm 12157429Smarkm/* Consumes the given number of bytes from the beginning of the buffer. */ 12257429Smarkm 12360573Skrisvoid 12476259Sgreenbuffer_consume(Buffer *buffer, u_int bytes) 12557429Smarkm{ 12657429Smarkm if (bytes > buffer->end - buffer->offset) 12760573Skris fatal("buffer_consume: trying to get more bytes than in buffer"); 12857429Smarkm buffer->offset += bytes; 12957429Smarkm} 13057429Smarkm 13157429Smarkm/* Consumes the given number of bytes from the end of the buffer. */ 13257429Smarkm 13360573Skrisvoid 13476259Sgreenbuffer_consume_end(Buffer *buffer, u_int bytes) 13557429Smarkm{ 13657429Smarkm if (bytes > buffer->end - buffer->offset) 13760573Skris fatal("buffer_consume_end: trying to get more bytes than in buffer"); 13857429Smarkm buffer->end -= bytes; 13957429Smarkm} 14057429Smarkm 14157429Smarkm/* Returns a pointer to the first used byte in the buffer. */ 14257429Smarkm 14357429Smarkmchar * 14457429Smarkmbuffer_ptr(Buffer *buffer) 14557429Smarkm{ 14657429Smarkm return buffer->buf + buffer->offset; 14757429Smarkm} 14857429Smarkm 14957429Smarkm/* Dumps the contents of the buffer to stderr. */ 15057429Smarkm 15160573Skrisvoid 15257429Smarkmbuffer_dump(Buffer *buffer) 15357429Smarkm{ 15457429Smarkm int i; 15576259Sgreen u_char *ucp = (u_char *) buffer->buf; 15657429Smarkm 15776259Sgreen for (i = buffer->offset; i < buffer->end; i++) { 15876259Sgreen fprintf(stderr, "%02x", ucp[i]); 15976259Sgreen if ((i-buffer->offset)%16==15) 16076259Sgreen fprintf(stderr, "\r\n"); 16176259Sgreen else if ((i-buffer->offset)%2==1) 16276259Sgreen fprintf(stderr, " "); 16376259Sgreen } 16476259Sgreen fprintf(stderr, "\r\n"); 16557429Smarkm} 166