From 10e031ba9e0f5c803fd4678f6e46628514cf0671 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Mon, 24 Feb 2025 15:54:52 +0000 Subject: [PATCH] add byte-wise i/o to tags open in sequential write-only mode --- src/tag.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/tag.h | 14 ++++++-- 2 files changed, 107 insertions(+), 6 deletions(-) diff --git a/src/tag.c b/src/tag.c index 9e41f0a..453f579 100644 --- a/src/tag.c +++ b/src/tag.c @@ -8,6 +8,8 @@ #include #include +static enum ec3_status flush_seq_buffer(struct ec3_tag_ioctx *tag); + static enum ec3_status init_seq_write_temp_files(struct ec3_tag_ioctx *tag) { b_status status = b_file_open_temp( @@ -78,6 +80,17 @@ enum ec3_status ec3_tag_ioctx_create( enum ec3_status ec3_tag_ioctx_close(struct ec3_tag_ioctx *tag) { + enum ec3_status status = EC3_SUCCESS; + + if ((tag->io_mode & (EC3_TAG_IO_SEQUENTIAL)) + && tag->io_seq_data_ptr > 0) { + status = flush_seq_buffer(tag); + } + + if (status != EC3_SUCCESS) { + return status; + } + enum ec3_tag_ioctx_mode mode = tag->io_mode; tag->io_mode |= EC3_TAG_IO_CLOSED; @@ -146,6 +159,12 @@ enum ec3_status ec3_tag_ioctx_read_cluster( cluster_id, &physical_cluster_id); + if (status == EC3_ERR_OUT_OF_BOUNDS) { + /* reached the end of the tag data */ + *nr_read = 0; + return EC3_SUCCESS; + } + if (status != EC3_SUCCESS) { return status; } @@ -166,7 +185,8 @@ enum ec3_status ec3_tag_ioctx_read_cluster( return EC3_ERR_BAD_FORMAT; } - size_t offset = tag->io_cluster_data_offset + cluster_info.c_base; + size_t offset = tag->io_parent->io_header.img_cluster_data_offset + + cluster_info.c_base; size_t r; enum b_status status2 = b_file_read( tag->io_f_image, @@ -198,7 +218,7 @@ enum ec3_status ec3_tag_ioctx_read_cluster( enum ec3_status ec3_tag_ioctx_write_cluster( struct ec3_tag_ioctx *tag, size_t cluster_id, - void *buf, + const void *buf, size_t len, size_t *nr_written) { @@ -210,7 +230,7 @@ enum ec3_status ec3_tag_ioctx_write_cluster( if (!(tag->io_mode & EC3_TAG_IO_SEQUENTIAL)) { status = cluster_cache_put( - tag->io_cluster_buf, + &tag->io_cache, cluster_id, buf, len); @@ -264,6 +284,79 @@ enum ec3_status ec3_tag_ioctx_write_cluster( return EC3_SUCCESS; } +static enum ec3_status flush_seq_buffer(struct ec3_tag_ioctx *tag) +{ + size_t nr_written = 0; + enum ec3_status status = ec3_tag_ioctx_write_cluster( + tag, + tag->io_seq_cluster_id, + tag->io_cluster_buf, + tag->io_seq_data_ptr, + &nr_written); + + if (status != EC3_SUCCESS) { + return status; + } + + tag->io_seq_data_ptr = 0; + + return status; +} + +enum ec3_status ec3_tag_ioctx_write( + struct ec3_tag_ioctx *tag, + const void *p, + size_t len, + size_t *nr_written) +{ + if (!(tag->io_mode & EC3_TAG_IO_WRITE)) { + return EC3_ERR_NOT_SUPPORTED; + } + + if (!(tag->io_mode & EC3_TAG_IO_SEQUENTIAL)) { + return EC3_ERR_NOT_SUPPORTED; + } + + enum ec3_status status = EC3_SUCCESS; + size_t cluster_size = tag->io_parent->io_header.img_cluster_size; + + const unsigned char *buf = p; + size_t written = 0; + + while (len > 0) { + size_t space_remaining = cluster_size - tag->io_seq_data_ptr; + + size_t to_copy = len; + if (to_copy > space_remaining) { + to_copy = space_remaining; + } + + const unsigned char *src = buf + written; + unsigned char *dest + = tag->io_cluster_buf + tag->io_seq_data_ptr; + + memcpy(dest, src, to_copy); + + tag->io_seq_data_ptr += to_copy; + written += to_copy; + + len -= to_copy; + space_remaining -= to_copy; + + if (space_remaining == 0) { + status = flush_seq_buffer(tag); + } + + if (status != EC3_SUCCESS) { + return status; + } + } + + *nr_written = written; + + return EC3_SUCCESS; +} + enum ec3_status ec3_tag_ioctx_get_nr_clusters( struct ec3_tag_ioctx *tag, size_t *out_nr_clusters) diff --git a/src/tag.h b/src/tag.h index 6e86cbb..f9be46a 100644 --- a/src/tag.h +++ b/src/tag.h @@ -36,8 +36,6 @@ struct ec3_tag_ioctx { /* temp buffer of cluster size, used for pipeline operations */ void *io_cluster_buf; - /* the offset to the start of the cluster table in io_f_rotag */ - size_t io_cluster_data_offset; /* this points to memory belonging to ec3_image_ioctx */ struct ec3_tag_info io_tag_info; @@ -82,6 +80,10 @@ struct ec3_tag_ioctx { struct cluster_table io_cluster_table; /* how many clusters have been written sequentially to this tag */ size_t io_seq_cluster_id; + /* how many bytes have been written to io_cluster_buf using + * ec3_tag_ioctx_write. when this reaches the cluster size (or + * ec3_tag_ioctx_close is called) this is reset to 0. */ + size_t io_seq_data_ptr; }; extern enum ec3_status ec3_tag_ioctx_create( @@ -98,7 +100,13 @@ extern enum ec3_status ec3_tag_ioctx_read_cluster( extern enum ec3_status ec3_tag_ioctx_write_cluster( struct ec3_tag_ioctx *tag, size_t cluster_id, - void *buf, + const void *buf, + size_t len, + size_t *nr_written); + +extern enum ec3_status ec3_tag_ioctx_write( + struct ec3_tag_ioctx *tag, + const void *buf, size_t len, size_t *nr_written);