Fix file size tracking to use actual written bytes

Previously, file_size was calculated as num_chunks * chunk_size, which
incorrectly treated the file size as the full capacity of all allocated
chunks. The actual file size should be the offset of the last byte
written plus 1.

Changes:
- Added file_size field to File structure to track actual file extent
- Initialize file_size to 0 when creating new files
- Update file_size in file_tree_write() based on write offset + length
- Modified file_tree_read() to use file_size instead of num_chunks * chunk_size
- Updated serialization/deserialization to handle file_size field

This ensures that actual_bytes calculations correctly reflect the true
file size, not just the allocated chunk capacity.
This commit is contained in:
Claude
2025-11-22 22:33:15 +00:00
parent f856bd0e05
commit 7b0b1acf61
2 changed files with 13 additions and 7 deletions
+12 -7
View File
@@ -122,6 +122,7 @@ static void file_init(File *f, uint64_t chunk_size)
{ {
f->chunk_size = chunk_size; f->chunk_size = chunk_size;
f->num_chunks = 0; f->num_chunks = 0;
f->file_size = 0;
f->chunks = NULL; f->chunks = NULL;
} }
@@ -375,6 +376,11 @@ int file_tree_write(FileTree *ft, string path,
for (uint64_t i = first_chunk_index; i <= last_chunk_index; i++) for (uint64_t i = first_chunk_index; i <= last_chunk_index; i++)
f->chunks[i] = hashes[i - first_chunk_index]; f->chunks[i] = hashes[i - first_chunk_index];
// Update file size (last byte written + 1)
uint64_t new_size = off + len;
if (new_size > f->file_size)
f->file_size = new_size;
// Now check which old hashes are no longer used // Now check which old hashes are no longer used
// anywhere in the tree // anywhere in the tree
// //
@@ -432,14 +438,11 @@ int file_tree_read(FileTree *ft, string path,
*chunk_size = f->chunk_size; *chunk_size = f->chunk_size;
// Calculate file size (number of chunks * chunk size) // Calculate actual bytes that can be read based on actual file size
uint64_t file_size = f->num_chunks * f->chunk_size; if (off >= f->file_size) {
// Calculate actual bytes that can be read
if (off >= file_size) {
*actual_bytes = 0; *actual_bytes = 0;
} else if (off + len > file_size) { } else if (off + len > f->file_size) {
*actual_bytes = file_size - off; *actual_bytes = f->file_size - off;
} else { } else {
*actual_bytes = len; *actual_bytes = len;
} }
@@ -539,6 +542,7 @@ static void file_serialize(SerializeContext *sc, File *f)
{ {
sc_write_u64(sc, f->chunk_size); sc_write_u64(sc, f->chunk_size);
sc_write_u64(sc, f->num_chunks); sc_write_u64(sc, f->num_chunks);
sc_write_u64(sc, f->file_size);
for (uint64_t i = 0; i < f->num_chunks; i++) for (uint64_t i = 0; i < f->num_chunks; i++)
sc_write_hash(sc, f->chunks[i]); sc_write_hash(sc, f->chunks[i]);
} }
@@ -638,6 +642,7 @@ static void file_deserialize(DeserializeContext *dc, File *f)
{ {
dc_read_u64(dc, &f->chunk_size); dc_read_u64(dc, &f->chunk_size);
dc_read_u64(dc, &f->num_chunks); dc_read_u64(dc, &f->num_chunks);
dc_read_u64(dc, &f->file_size);
f->chunks = sys_malloc(f->num_chunks * sizeof(SHA256)); f->chunks = sys_malloc(f->num_chunks * sizeof(SHA256));
if (f->chunks == NULL) { if (f->chunks == NULL) {
+1
View File
@@ -18,6 +18,7 @@ typedef struct Entity Entity;
typedef struct { typedef struct {
uint64_t chunk_size; // TODO: this should be an u32 uint64_t chunk_size; // TODO: this should be an u32
uint64_t num_chunks; // TODO: and this too uint64_t num_chunks; // TODO: and this too
uint64_t file_size; // Offset of last byte written + 1
SHA256 *chunks; SHA256 *chunks;
} File; } File;