From 0d099a1fa639f0e94c7d4760ad0b86ff2d37c6af Mon Sep 17 00:00:00 2001 From: Francesco Cozzuto Date: Tue, 25 Nov 2025 12:08:33 +0100 Subject: [PATCH] Return version tags in directory listing --- inc/ToastyFS.h | 1 + misc/PROTOCOL.txt | 3 ++- src/client.c | 9 +++++++++ src/file_tree.c | 1 + src/file_tree.h | 1 + src/metadata_server.c | 2 ++ 6 files changed, 16 insertions(+), 1 deletion(-) diff --git a/inc/ToastyFS.h b/inc/ToastyFS.h index ceb587d..e68c4ad 100644 --- a/inc/ToastyFS.h +++ b/inc/ToastyFS.h @@ -85,6 +85,7 @@ int toasty_delete(ToastyFS *toasty, ToastyString path, ToastyVersionTag vtag); typedef struct { char name[128]; // TODO: Implement a proper name length bool is_dir; + ToastyVersionTag vtag; } ToastyListingEntry; typedef struct { diff --git a/misc/PROTOCOL.txt b/misc/PROTOCOL.txt index 89fd141..33abafe 100644 --- a/misc/PROTOCOL.txt +++ b/misc/PROTOCOL.txt @@ -178,6 +178,7 @@ The following is the list of messages the Metadata Server may send to a Client: When a client sends a LIST request to the metadata server and it succedes, the server replies with a LIST_SUCCESSS message with the following layout: struct ListItem { + uint64_t gen; uint8_t is_dir; uint16_t name_len; char name[name_len]; @@ -191,7 +192,7 @@ The following is the list of messages the Metadata Server may send to a Client: ListItem items[item_count]; }; - The gen field contains the generation counter for the directory. + The ListSuccessMessage gen field contains the generation counter for the directory, while the gen field in ListItem is the counter for that specific child. If the truncated field is non-zero, the actual item count for this directory is greater than the one sent in the message. diff --git a/src/client.c b/src/client.c index 7629873..f595675 100644 --- a/src/client.c +++ b/src/client.c @@ -950,6 +950,14 @@ static void process_event_for_list(ToastyFS *toasty, // Parse each list item for (uint32_t i = 0; i < item_count; i++) { + + uint64_t gen; + if (!binary_read(&reader, &gen, sizeof(gen))) { + toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_LIST_ERROR, .user=toasty->operations[opidx].user }; + sys_free(entities); + return; + } + uint8_t is_dir; if (!binary_read(&reader, &is_dir, sizeof(is_dir))) { toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_LIST_ERROR, .user=toasty->operations[opidx].user }; @@ -971,6 +979,7 @@ static void process_event_for_list(ToastyFS *toasty, return; } + entities[i].vtag = gen; entities[i].is_dir = is_dir; if (name_len > sizeof(entities[i].name)-1) { diff --git a/src/file_tree.c b/src/file_tree.c index 483037d..65a2d2e 100644 --- a/src/file_tree.c +++ b/src/file_tree.c @@ -257,6 +257,7 @@ int file_tree_list(FileTree *ft, string path, items[i].name_len = name_cpy; items[i].is_dir = c->is_dir; + items[i].gen = c->gen; } assert(e->gen != NO_GENERATION); diff --git a/src/file_tree.h b/src/file_tree.h index 60e67fc..bec2d55 100644 --- a/src/file_tree.h +++ b/src/file_tree.h @@ -51,6 +51,7 @@ typedef struct { char name[1<<8]; int name_len; bool is_dir; + uint64_t gen; } ListItem; #define MAX_COMPS 32 diff --git a/src/metadata_server.c b/src/metadata_server.c index bf4ebf9..b512320 100644 --- a/src/metadata_server.c +++ b/src/metadata_server.c @@ -362,6 +362,8 @@ process_client_list(MetadataServer *state, int conn_idx, ByteView msg) for (int i = 0; i < ret && i < MAX_LIST_SIZE; i++) { + message_write(&writer, &items[i].gen, sizeof(items[i].gen)); + uint8_t is_dir = items[i].is_dir; message_write(&writer, &is_dir, sizeof(is_dir));