summaryrefslogtreecommitdiff
path: root/lib/sqfs/meta_writer.c
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-10 11:20:33 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-10 11:20:33 +0200
commitb57f3fe97074b2a374e52e9fb4920449bcb6b319 (patch)
tree502178243213567d7eab3a66d92d69bf22c71fcd /lib/sqfs/meta_writer.c
parent744daf0d3d72e71854f8248dbf2bc0b81fe110ec (diff)
Add a way to keep meta data blocks in memory
Instead of writing meta data blocks directly to disk, the writer can now alternatively keep the blocks in memory until explicitly told to write to disk. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs/meta_writer.c')
-rw-r--r--lib/sqfs/meta_writer.c122
1 files changed, 94 insertions, 28 deletions
diff --git a/lib/sqfs/meta_writer.c b/lib/sqfs/meta_writer.c
index 2dacaa0..ef869e7 100644
--- a/lib/sqfs/meta_writer.c
+++ b/lib/sqfs/meta_writer.c
@@ -8,6 +8,13 @@
#include <unistd.h>
#include <stdio.h>
+typedef struct meta_block_t {
+ struct meta_block_t *next;
+
+ /* possibly compressed data with 2 byte header */
+ uint8_t data[SQFS_META_BLOCK_SIZE + 2];
+} meta_block_t;
+
struct meta_writer_t {
/* A byte offset into the uncompressed data of the current block */
size_t offset;
@@ -22,13 +29,36 @@ struct meta_writer_t {
compressor_t *cmp;
/* The raw data chunk that data is appended to */
- uint8_t data[SQFS_META_BLOCK_SIZE + 2];
+ uint8_t data[SQFS_META_BLOCK_SIZE];
- /* Scratch buffer for compressing data */
- uint8_t scratch[SQFS_META_BLOCK_SIZE + 2];
+ bool keep_in_mem;
+ meta_block_t *list;
+ meta_block_t *list_end;
};
-meta_writer_t *meta_writer_create(int fd, compressor_t *cmp)
+static int write_block(int fd, meta_block_t *outblk)
+{
+ size_t count;
+ ssize_t ret;
+
+ count = le16toh(((uint16_t *)outblk->data)[0]) & 0x7FFF;
+
+ ret = write_retry(fd, outblk->data, count + 2);
+
+ if (ret < 0) {
+ perror("writing meta data block");
+ return -1;
+ }
+
+ if ((size_t)ret < count) {
+ fputs("meta data written to file was truncated\n", stderr);
+ return -1;
+ }
+
+ return 0;
+}
+
+meta_writer_t *meta_writer_create(int fd, compressor_t *cmp, bool keep_in_mem)
{
meta_writer_t *m = calloc(1, sizeof(*m));
@@ -39,53 +69,71 @@ meta_writer_t *meta_writer_create(int fd, compressor_t *cmp)
m->cmp = cmp;
m->outfd = fd;
+ m->keep_in_mem = keep_in_mem;
return m;
}
void meta_writer_destroy(meta_writer_t *m)
{
+ meta_block_t *blk;
+
+ while (m->list != NULL) {
+ blk = m->list;
+ m->list = blk->next;
+ free(blk);
+ }
+
free(m);
}
int meta_writer_flush(meta_writer_t *m)
{
- ssize_t ret, count;
- void *ptr;
+ meta_block_t *outblk;
+ size_t count;
+ ssize_t ret;
if (m->offset == 0)
return 0;
- ret = m->cmp->do_block(m->cmp, m->data + 2, m->offset,
- m->scratch + 2, sizeof(m->scratch) - 2);
- if (ret < 0)
+ outblk = calloc(1, sizeof(*outblk));
+ if (outblk == NULL) {
+ perror("generating meta data block");
+ return -1;
+ }
+
+ ret = m->cmp->do_block(m->cmp, m->data, m->offset,
+ outblk->data + 2, sizeof(outblk->data) - 2);
+ if (ret < 0) {
+ free(outblk);
return -1;
+ }
if (ret > 0) {
- ((uint16_t *)m->scratch)[0] = htole16(ret);
+ ((uint16_t *)outblk->data)[0] = htole16(ret);
count = ret + 2;
- ptr = m->scratch;
} else {
- ((uint16_t *)m->data)[0] = htole16(m->offset | 0x8000);
+ ((uint16_t *)outblk->data)[0] = htole16(m->offset | 0x8000);
+ memcpy(outblk->data + 2, m->data, m->offset);
count = m->offset + 2;
- ptr = m->data;
- }
-
- ret = write_retry(m->outfd, ptr, count);
-
- if (ret < 0) {
- perror("writing meta data");
- return -1;
}
- if (ret < count) {
- fputs("meta data written to file was truncated\n", stderr);
- return -1;
+ if (m->keep_in_mem) {
+ if (m->list == NULL) {
+ m->list = outblk;
+ } else {
+ m->list_end->next = outblk;
+ }
+ m->list_end = outblk;
+ ret = 0;
+ } else {
+ ret = write_block(m->outfd, outblk);
+ free(outblk);
}
memset(m->data, 0, sizeof(m->data));
m->offset = 0;
m->block_offset += count;
- return 0;
+ return ret;
}
int meta_writer_append(meta_writer_t *m, const void *data, size_t size)
@@ -93,24 +141,24 @@ int meta_writer_append(meta_writer_t *m, const void *data, size_t size)
size_t diff;
while (size != 0) {
- diff = sizeof(m->data) - 2 - m->offset;
+ diff = sizeof(m->data) - m->offset;
if (diff == 0) {
if (meta_writer_flush(m))
return -1;
- diff = sizeof(m->data) - 2;
+ diff = sizeof(m->data);
}
if (diff > size)
diff = size;
- memcpy(m->data + 2 + m->offset, data, diff);
+ memcpy(m->data + m->offset, data, diff);
m->offset += diff;
size -= diff;
data = (const char *)data + diff;
}
- if (m->offset == (sizeof(m->data) - 2))
+ if (m->offset == sizeof(m->data))
return meta_writer_flush(m);
return 0;
@@ -128,3 +176,21 @@ void meta_writer_reset(meta_writer_t *m)
m->block_offset = 0;
m->offset = 0;
}
+
+int meta_write_write_to_file(meta_writer_t *m)
+{
+ meta_block_t *blk;
+
+ while (m->list != NULL) {
+ blk = m->list;
+
+ if (write_block(m->outfd, blk))
+ return -1;
+
+ m->list = blk->next;
+ free(blk);
+ }
+
+ m->list_end = NULL;
+ return 0;
+}