added Buffer "class" based on openssh/buffer.c, which is a really beautiful idea. I'll use this for file i/o and data handling

This commit is contained in:
git@daemon.de
2014-02-07 16:58:02 +01:00
parent cb873e3681
commit 5161e15c69
8 changed files with 327 additions and 3 deletions

View File

@@ -18,6 +18,7 @@ PCPEXPORT = pcp.h \
pcp/z85.h \
pcp/zmq_z85.h \
pcp/ed.h \
pcp/base85.h
pcp/base85.h \
pcp/buffer.h
nobase_include_HEADERS = $(PCPEXPORT)

View File

@@ -6,6 +6,7 @@ extern "C" {
#endif
#include "pcp/base85.h"
#include "pcp/buffer.h"
#include "pcp/config.h"
#include "pcp/crypto.h"
#include "pcp/defines.h"

97
include/pcp/buffer.h Normal file
View File

@@ -0,0 +1,97 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2014 T.v.Dein.
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
/*
Flexible buffer management, idea from openssh/buffer.c.
This allows us to dissect buffers into parts at will
whithout the hassle of boundary checking in each and every
line. Therefore it is more secure, since this system wraps
all this stuff from us, so in case we're attemt to overflow
a buffer or the like, the buffer functions will catch this,
warn us and die.
*/
#ifndef HAVE_PCP_BUFFER_H
#define HAVE_PCP_BUFFER_H
#include "mem.h"
#include "util.h"
#include "defines.h"
struct _pcp_buffer {
char *name; /* just for convenience in error messages and the
like, so we know which buffer cause trouble */
uint8_t allocated;
size_t blocksize;
size_t size;
size_t offset; /* read position */
size_t end; /* write position, data end */
void *buf;
};
typedef struct _pcp_buffer Buffer;
/* create a new buffer */
Buffer *buffer_new(size_t blocksize, char *name);
/* zero the buffer and free it, if allocated */
void buffer_free(Buffer *b);
/* zero the buffer, always called from buffer_free() */
void buffer_clear(Buffer *b);
/* add data to the buffer, memorize end position */
void buffer_add(Buffer *b, const void *data, size_t len);
/* resize the buffer if necessary */
void buffer_resize(Buffer *b, size_t len);
/* get some chunk of data from the buffer, starting from offset til len,
it doesn't allocate the returned data (void *buf, the 2nd argument).
*/
size_t buffer_get(Buffer *b, void *buf, size_t len);
/* same as buffer_get() but fetch some data chunk from somewhere
in the middle of the buffer */
size_t buffer_extract(Buffer *b, void *buf, size_t offset, size_t len);
/* dump the buffer contents to stderr */
void buffer_dump(const Buffer *b);
/* print buffer counters to stderr */
void buffer_info(const Buffer *b);
/* tell how much data there is in the buffer */
size_t buffer_size(const Buffer *b);
/* access the last byte(s) as numbers directly, save typing,
in contrast to buffer_get() it doesn't increment offset */
uint8_t buffer_last8(Buffer *b);
uint16_t buffer_last16(Buffer *b);
uint32_t buffer_last32(Buffer *b);
uint64_t buffer_last64(Buffer *b);
/* read from a file directly into a buffer object */
size_t buffer_fd_read(Buffer *b, FILE *in, size_t len);
#endif // HAVE_PCP_BUFFER_H

View File

@@ -30,6 +30,6 @@ libpcp1_la_SOURCES = mac.c mem.c pad.c version.c \
vault.c fatal.c jenhash.c digital_crc32.c \
crypto.c ed.c keyhash.c scrypt.c \
scrypt/crypto/sha256.c scrypt/crypto/crypto_scrypt-nosse.c \
base85.c util.c
base85.c util.c buffer.c
include_HEADERS = ../include/pcp.h

158
libpcp/buffer.c Normal file
View File

@@ -0,0 +1,158 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2014 T.v.Dein.
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tom AT vondein DOT org>.
*/
#include "buffer.h"
Buffer *buffer_new(size_t blocksize, char *name) {
Buffer *b = ucmalloc(sizeof(Buffer));
b->buf = ucmalloc(blocksize);
b->name = ucmalloc(strlen(name)+1);
b->size = blocksize;
b->allocated = 1;
b->offset = 0;
b->end = 0;
b->blocksize = blocksize;
memcpy(b->name, name, strlen(name)+1);
return b;
}
void buffer_free(Buffer *b) {
if(b != NULL) {
if(b->allocated > 0) {
buffer_clear(b);
free(b->buf);
free(b);
}
}
}
void buffer_clear(Buffer *b) {
b->offset = 0;
memset(b->buf, 0, b->size);
}
void buffer_add(Buffer *b, const void *data, size_t len) {
buffer_resize(b, len);
memcpy(b->buf + b->end, data, len);
b->end += len;
}
void buffer_resize(Buffer *b, size_t len) {
if((b->end > 0 && b->end + len > b->size) || (b->end == 0 && len > b->size) ) {
/* increase by buf blocksize */
size_t newsize = (((len / b->blocksize) +1) * b->blocksize) + b->size;
fprintf(stderr, "[buffer %s] resizing from %ld to %ld\n", b->name, b->size, newsize);
b->buf = ucrealloc(b->buf, b->size, newsize);
b->size = newsize;
}
}
size_t buffer_get(Buffer *b, void *buf, size_t len) {
if(len > b->end - b->offset || len == 0) {
fatal("[buffer %s] attempt to read %ld data from buffer with size %ld %p at offset %ld",
len, b->size, b->offset);
return 0;
}
memcpy(buf, b->buf + b->offset, len);
b->offset += len;
return len;
}
size_t buffer_extract(Buffer *b, void *buf, size_t offset, size_t len) {
if(len > b->end) {
fatal("[buffer %s] attempt to read %ld bytes past end of buffer at %ld\n", b->name, b->end - (b->offset + len), b->end);
return 0;
}
if(offset > b->end) {
fatal("[buffer %s] attempt to read at offset %ld past len to read %ld\n", b->name, offset, b->end);
return 0;
}
memcpy(buf, b->buf + offset, len);
return len - offset;
}
void buffer_dump(const Buffer *b) {
_dump(b->name, b->buf, b->size);
}
void buffer_info(const Buffer *b) {
fprintf(stderr, "blocksize: %ld\n", b->blocksize);
fprintf(stderr, " size: %ld\n", b->size);
fprintf(stderr, " offset: %ld\n", b->offset);
fprintf(stderr, " end: %ld\n", b->end);
fprintf(stderr, "allocated: %d\n", b->allocated);
}
size_t buffer_size(const Buffer *b) {
return b->end;
}
uint8_t buffer_last8(Buffer *b) {
uint8_t i;
if(buffer_extract(b, &i, b->end - 1, 1) > 0)
return i;
else
return 0;
}
uint16_t buffer_last16(Buffer *b) {
uint16_t i;
if(buffer_extract(b, &i, b->end - 2, 2) > 0)
return i;
else
return 0;
}
uint32_t buffer_last32(Buffer *b) {
uint32_t i;
if(buffer_extract(b, &i, b->end - 4, 4) > 0)
return i;
else
return 0;
}
uint64_t buffer_last64(Buffer *b) {
uint64_t i;
if(buffer_extract(b, &i, b->end - 8, 8) > 0)
return i;
else
return 0;
}
size_t buffer_fd_read(Buffer *b, FILE *in, size_t len) {
if(feof(in) || ferror(in)) {
return 0;
}
void *data = ucmalloc(len);
size_t s = fread(data, 1, len, in);
if(s < len) {
fatal("[buffer %s] attemt to read %ld bytes from FILE, but got %ld only\n", b->name, len, s);
return 0;
}
buffer_add(b, data, len);
return len;
}

View File

@@ -20,7 +20,7 @@
#
AM_CFLAGS = -I../include/pcp -I../src -I../libpcp/scrypt/crypto -Wall -g
check_PROGRAMS = col invalidkeys pwhashes gencheader statictest cpptest
check_PROGRAMS = col invalidkeys pwhashes gencheader statictest cpptest buffertest
gencheader_LDADD = ../libpcp/.libs/libpcp1.a
gencheader_SOURCES = gencheader.c
@@ -28,6 +28,9 @@ gencheader_SOURCES = gencheader.c
statictest_LDADD = ../libpcp/.libs/libpcp1.a
statictest_SOURCES = statictest.c
buffertest_LDADD = ../libpcp/.libs/libpcp1.a
buffertest_SOURCES = buffertest.c
col_LDADD = ../libpcp/.libs/libpcp1.a

58
tests/buffertest.c Normal file
View File

@@ -0,0 +1,58 @@
#include "buffertest.h"
int main() {
Buffer *test = buffer_new(16, "test");
byte *a = ucmalloc(32);
byte *b = ucmalloc(32);
memset(a, 'A', 32);
memset(b, 'B', 32);
fprintf(stderr, "initial\n");
buffer_info(test);
int i;
for(i=0; i<2; i++) {
fprintf(stderr, "\nadding As\n");
buffer_add(test, a, 32);
buffer_info(test);
buffer_dump(test);
fprintf(stderr, "\nadding Bs\n");
buffer_add(test, b, 32);
buffer_info(test);
buffer_dump(test);
}
free(a);
free(b);
size_t x;
size_t bs = buffer_size(test);
void *g = ucmalloc(32);
for(x=0; x < bs; x+=32) {
fprintf(stderr, "before get\n");
buffer_info(test);
if(buffer_get(test, g, 32) > 0) {
fprintf(stderr, "after get\n");
buffer_info(test);
_dump("got", g, 32);
}
fprintf(stderr, "\n");
}
buffer_extract(test, g, 28, 38);
_dump("extracted", g, 10);
uint8_t c = buffer_last8(test);
fprintf(stderr, "last byte: %c\n", c);
free(g);
buffer_free(test);
fatals_ifany();
return 0;
}

6
tests/buffertest.h Normal file
View File

@@ -0,0 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "buffer.h"