mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 12:00:56 +01:00
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:
@@ -18,6 +18,7 @@ PCPEXPORT = pcp.h \
|
|||||||
pcp/z85.h \
|
pcp/z85.h \
|
||||||
pcp/zmq_z85.h \
|
pcp/zmq_z85.h \
|
||||||
pcp/ed.h \
|
pcp/ed.h \
|
||||||
pcp/base85.h
|
pcp/base85.h \
|
||||||
|
pcp/buffer.h
|
||||||
|
|
||||||
nobase_include_HEADERS = $(PCPEXPORT)
|
nobase_include_HEADERS = $(PCPEXPORT)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pcp/base85.h"
|
#include "pcp/base85.h"
|
||||||
|
#include "pcp/buffer.h"
|
||||||
#include "pcp/config.h"
|
#include "pcp/config.h"
|
||||||
#include "pcp/crypto.h"
|
#include "pcp/crypto.h"
|
||||||
#include "pcp/defines.h"
|
#include "pcp/defines.h"
|
||||||
|
|||||||
97
include/pcp/buffer.h
Normal file
97
include/pcp/buffer.h
Normal 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
|
||||||
@@ -30,6 +30,6 @@ libpcp1_la_SOURCES = mac.c mem.c pad.c version.c \
|
|||||||
vault.c fatal.c jenhash.c digital_crc32.c \
|
vault.c fatal.c jenhash.c digital_crc32.c \
|
||||||
crypto.c ed.c keyhash.c scrypt.c \
|
crypto.c ed.c keyhash.c scrypt.c \
|
||||||
scrypt/crypto/sha256.c scrypt/crypto/crypto_scrypt-nosse.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
|
include_HEADERS = ../include/pcp.h
|
||||||
|
|||||||
158
libpcp/buffer.c
Normal file
158
libpcp/buffer.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
AM_CFLAGS = -I../include/pcp -I../src -I../libpcp/scrypt/crypto -Wall -g
|
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_LDADD = ../libpcp/.libs/libpcp1.a
|
||||||
gencheader_SOURCES = gencheader.c
|
gencheader_SOURCES = gencheader.c
|
||||||
@@ -28,6 +28,9 @@ gencheader_SOURCES = gencheader.c
|
|||||||
statictest_LDADD = ../libpcp/.libs/libpcp1.a
|
statictest_LDADD = ../libpcp/.libs/libpcp1.a
|
||||||
statictest_SOURCES = statictest.c
|
statictest_SOURCES = statictest.c
|
||||||
|
|
||||||
|
buffertest_LDADD = ../libpcp/.libs/libpcp1.a
|
||||||
|
buffertest_SOURCES = buffertest.c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
col_LDADD = ../libpcp/.libs/libpcp1.a
|
col_LDADD = ../libpcp/.libs/libpcp1.a
|
||||||
|
|||||||
58
tests/buffertest.c
Normal file
58
tests/buffertest.c
Normal 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
6
tests/buffertest.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
Reference in New Issue
Block a user