cbfstool: Add offset field to cbfstool directory's struct buffer

This allows calls to buffer_delete() to work on a buffer that has been
buffer_seek()ed or the buffer created by a buffer_splice(). The same
information could also be useful for other purposes, such as writing
slices back to a file at the offset they originally occupied.

BUG=chromium:470407
TEST=Attempt to perform the following sequence of buffer actions, then run it
through valgrind to check for memory errors:
for (int pos = 0; pos <= 3; ++pos) {
	struct buffer seek_test;
	buffer_create(&seek_test, 3, "seek_test");
	if (pos == 0) {
		buffer_delete(&seek_test);
		continue;
	}
	buffer_seek(&seek_test, 1);
	if (pos == 1) {
		buffer_delete(&seek_test);
		continue;
	}
	buffer_seek(&seek_test, 1);
	if (pos == 2) {
		buffer_delete(&seek_test);
		continue;
	}
	buffer_seek(&seek_test, 1);
	if (pos == 3) {
		buffer_delete(&seek_test);
		continue;
	}
}
for (int pos = 0; pos <= 14; ++pos) {
	struct buffer slice_test;
	buffer_create(&slice_test, 3, "slice_test");
	if (pos == 0) {
		buffer_delete(&slice_test);
		continue;
	}
	struct buffer sliced_once;
	buffer_splice(&sliced_once, &slice_test, 1, 2);
	if (pos == 1) {
		buffer_delete(&slice_test);
		continue;
	}
	if (pos == 2) {
		buffer_delete(&sliced_once);
		continue;
	}
	struct buffer sliced_twice;
	buffer_splice(&sliced_twice, &sliced_once, 2, 1);
	if (pos == 3) {
		buffer_delete(&slice_test);
		continue;
	}
	if (pos == 4) {
		buffer_delete(&sliced_once);
		continue;
	}
	if (pos == 5) {
		buffer_delete(&sliced_twice);
		continue;
	}
	struct buffer sliced_same;
	buffer_splice(&sliced_same, &slice_test, 1, 1);
	if (pos == 6) {
		buffer_delete(&slice_test);
		continue;
	}
	if (pos == 7) {
		buffer_delete(&sliced_once);
		continue;
	}
	if (pos == 8) {
		buffer_delete(&sliced_twice);
		continue;
	}
	if (pos == 9) {
		buffer_delete(&sliced_same);
		continue;
	}
	struct buffer sliced_thrice;
	buffer_splice(&sliced_thrice, &sliced_twice, 1, 0);
	if (pos == 10) {
		buffer_delete(&slice_test);
		continue;
	}
	if (pos == 11) {
		buffer_delete(&sliced_once);
		continue;
	}
	if (pos == 12) {
		buffer_delete(&sliced_twice);
		continue;
	}
	if (pos == 13) {
		buffer_delete(&sliced_same);
		continue;
	}
	if (pos == 14) {
		buffer_delete(&sliced_thrice);
		continue;
	}
}
BRANCH=None

Change-Id: Id67734654a62302c0de37746d8a978d49b240505
Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Commit-Id: 00c40982a21a91a488587dd3cead7109f3a30d98
Original-Change-Id: Ie99839d36500d3270e4924a3477e076a6d27ffc8
Original-Signed-off-by: Sol Boucher <solb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/267467
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10133
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Sol Boucher 2015-04-26 02:32:43 -07:00 committed by Patrick Georgi
parent 1a3349ffd1
commit 64c6cd73f3
2 changed files with 22 additions and 5 deletions

View File

@ -57,6 +57,7 @@ static off_t get_file_size(FILE *f)
int buffer_create(struct buffer *buffer, size_t size, const char *name) int buffer_create(struct buffer *buffer, size_t size, const char *name)
{ {
buffer->name = strdup(name); buffer->name = strdup(name);
buffer->offset = 0;
buffer->size = size; buffer->size = size;
buffer->data = (char *)malloc(buffer->size); buffer->data = (char *)malloc(buffer->size);
if (!buffer->data) { if (!buffer->data) {
@ -73,6 +74,7 @@ int buffer_from_file(struct buffer *buffer, const char *filename)
perror(filename); perror(filename);
return -1; return -1;
} }
buffer->offset = 0;
buffer->size = get_file_size(fp); buffer->size = get_file_size(fp);
if (buffer->size == -1u) { if (buffer->size == -1u) {
fprintf(stderr, "could not determine size of %s\n", filename); fprintf(stderr, "could not determine size of %s\n", filename);
@ -116,9 +118,10 @@ void buffer_delete(struct buffer *buffer)
buffer->name = NULL; buffer->name = NULL;
} }
if (buffer->data) { if (buffer->data) {
free(buffer->data); free(buffer->data - buffer->offset);
buffer->data = NULL; buffer->data = NULL;
} }
buffer->offset = 0;
buffer->size = 0; buffer->size = 0;
} }

View File

@ -59,6 +59,7 @@ static inline uint32_t align_up(uint32_t value, uint32_t align)
struct buffer { struct buffer {
char *name; char *name;
char *data; char *data;
size_t offset;
size_t size; size_t size;
}; };
@ -72,6 +73,9 @@ static inline size_t buffer_size(const struct buffer *b)
return b->size; return b->size;
} }
/*
* Shrink a buffer toward the beginning of its previous space.
* Afterward, buffer_delete() remains the means of cleaning it up. */
static inline void buffer_set_size(struct buffer *b, size_t size) static inline void buffer_set_size(struct buffer *b, size_t size)
{ {
b->size = size; b->size = size;
@ -87,22 +91,32 @@ static inline void buffer_init(struct buffer *b, char *name, void *data,
} }
/* Splice a buffer into another buffer. Note that it's up to the caller to /* Splice a buffer into another buffer. Note that it's up to the caller to
* bounds check the offset and size. */ * bounds check the offset and size. The resulting buffer is backed by the same
* storage as the original, so although it is valid to buffer_delete() either
* one of them, doing so releases both simultaneously. */
static inline void buffer_splice(struct buffer *dest, const struct buffer *src, static inline void buffer_splice(struct buffer *dest, const struct buffer *src,
size_t offset, size_t size) size_t offset, size_t size)
{ {
buffer_init(dest, src->name, src->data, src->size); dest->name = src->name;
dest->data += offset; dest->data = src->data + offset;
buffer_set_size(dest, size); dest->offset = src->offset + offset;
dest->size = size;
} }
/*
* Shallow copy a buffer. To clean up the resources, buffer_delete()
* either one, but not both. */
static inline void buffer_clone(struct buffer *dest, const struct buffer *src) static inline void buffer_clone(struct buffer *dest, const struct buffer *src)
{ {
buffer_splice(dest, src, 0, src->size); buffer_splice(dest, src, 0, src->size);
} }
/*
* Shrink a buffer toward the end of its previous space.
* Afterward, buffer_delete() remains the means of cleaning it up. */
static inline void buffer_seek(struct buffer *b, size_t size) static inline void buffer_seek(struct buffer *b, size_t size)
{ {
b->offset += size;
b->size -= size; b->size -= size;
b->data += size; b->data += size;
} }