1.1 --- a/libfsclient/include/fsclient/client.h Mon May 06 01:14:09 2024 +0200
1.2 +++ b/libfsclient/include/fsclient/client.h Thu May 09 16:46:44 2024 +0200
1.3 @@ -46,7 +46,7 @@
1.4 file_t *client_opendir(const char *name);
1.5 file_t *client_opendir_using(const char *name, l4_cap_idx_t server);
1.6
1.7 -file_t *client_opendir_at(file_t *file);
1.8 +file_t *client_opendir_reader(file_t *file);
1.9 file_t *client_reopen(file_t *file, flags_t flags);
1.10
1.11 long client_pipe(file_t **reader, file_t **writer, flags_t flags);
1.12 @@ -96,6 +96,7 @@
1.13 /* Directory reading operations. */
1.14
1.15 struct dirent *client_readdir(file_t *file);
1.16 +void client_rewinddir(file_t *file);
1.17
1.18 /* Notification operations. */
1.19
2.1 --- a/libfsclient/include/fsclient/file.h Mon May 06 01:14:09 2024 +0200
2.2 +++ b/libfsclient/include/fsclient/file.h Thu May 09 16:46:44 2024 +0200
2.3 @@ -35,9 +35,11 @@
2.4
2.5 EXTERN_C_BEGIN
2.6
2.7 +struct file_t;
2.8 +
2.9 /* File access abstraction compatible with notifiable_base_t. */
2.10
2.11 -typedef struct
2.12 +typedef struct file_t
2.13 {
2.14 /* File object reference. */
2.15
2.16 @@ -77,6 +79,10 @@
2.17
2.18 long error;
2.19
2.20 + /* Metadata file object reference. */
2.21 +
2.22 + struct file_t *metadata;
2.23 +
2.24 } file_t;
2.25
2.26
3.1 --- a/libfsclient/lib/src/client.cc Mon May 06 01:14:09 2024 +0200
3.2 +++ b/libfsclient/lib/src/client.cc Thu May 09 16:46:44 2024 +0200
3.3 @@ -257,6 +257,9 @@
3.4 if (file == NULL)
3.5 return;
3.6
3.7 + if (file->metadata != NULL)
3.8 + client_close(file->metadata);
3.9 +
3.10 file_flush(file);
3.11 file_close(file);
3.12 free(file);
3.13 @@ -348,33 +351,30 @@
3.14 }
3.15
3.16 /* Open a directory listing stream via the given named directory and a named
3.17 - capability. */
3.18 + capability, returning the directory object with a metadata file object
3.19 + reference to the directory listing stream. */
3.20
3.21 file_t *client_opendir_using(const char *name, l4_cap_idx_t server)
3.22 {
3.23 file_t *file = client_open_using(name, O_DIRECTORY, server);
3.24
3.25 - if (file == NULL)
3.26 - return NULL;
3.27 -
3.28 /* Return the directory structure itself for error handling. */
3.29
3.30 if (!client_opened(file))
3.31 return file;
3.32
3.33 - file_t *reader = client_opendir_at(file);
3.34 + file->metadata = client_opendir_reader(file);
3.35
3.36 - /* Release the directory and return the reader even if an error occurs. */
3.37 + /* Return the directory even if an error occurs. */
3.38
3.39 - client_close(file);
3.40 - return reader;
3.41 + return file;
3.42 }
3.43
3.44
3.45
3.46 /* Open a directory listing stream via the given directory. */
3.47
3.48 -file_t *client_opendir_at(file_t *file)
3.49 +file_t *client_opendir_reader(file_t *file)
3.50 {
3.51 file_t *reader = (file_t *) malloc(sizeof(file_t));
3.52
3.53 @@ -640,8 +640,11 @@
3.54
3.55 struct dirent *client_readdir(file_t *file)
3.56 {
3.57 + if ((file == NULL) || (file->metadata == NULL))
3.58 + return NULL;
3.59 +
3.60 char buffer[DIRENT_CORE_SIZE];
3.61 - offset_t nread = client_read(file, buffer, DIRENT_CORE_SIZE);
3.62 + offset_t nread = client_read(file->metadata, buffer, DIRENT_CORE_SIZE);
3.63
3.64 /* Stop if no new structure can be successfully read. */
3.65
3.66 @@ -666,7 +669,7 @@
3.67
3.68 char *current = entry + DIRENT_CORE_SIZE;
3.69
3.70 - nread = client_read(file, current, remaining);
3.71 + nread = client_read(file->metadata, current, remaining);
3.72
3.73 /* Stop if no complete structure can be successfully read. */
3.74
3.75 @@ -679,6 +682,18 @@
3.76 return (struct dirent *) entry;
3.77 }
3.78
3.79 +/* Rewind directory reading. */
3.80 +
3.81 +void client_rewinddir(file_t *file)
3.82 +{
3.83 + if ((file == NULL) || (file->metadata == NULL))
3.84 + return;
3.85 +
3.86 + client_close(file->metadata);
3.87 +
3.88 + file->metadata = client_opendir_reader(file);
3.89 +}
3.90 +
3.91
3.92
3.93 /* Read from the filesystem object into the buffer provided. */
4.1 --- a/libfsclient/lib/src/file.cc Mon May 06 01:14:09 2024 +0200
4.2 +++ b/libfsclient/lib/src/file.cc Thu May 09 16:46:44 2024 +0200
4.3 @@ -91,6 +91,7 @@
4.4 file->can_block = 0;
4.5 file->flags = 0;
4.6 file->error = 0;
4.7 + file->metadata = NULL;
4.8
4.9 /* Initialise the notifiable section of the structure. */
4.10
5.1 --- a/tests/dstest_file_readdir.cc Mon May 06 01:14:09 2024 +0200
5.2 +++ b/tests/dstest_file_readdir.cc Thu May 09 16:46:44 2024 +0200
5.3 @@ -1,7 +1,7 @@
5.4 /*
5.5 * Test directory reading operations.
5.6 *
5.7 - * Copyright (C) 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
5.8 + * Copyright (C) 2020, 2021, 2022, 2024 Paul Boddie <paul@boddie.org.uk>
5.9 *
5.10 * This program is free software; you can redistribute it and/or
5.11 * modify it under the terms of the GNU General Public License as
5.12 @@ -122,16 +122,36 @@
5.13 return 1;
5.14 }
5.15
5.16 + char *name = NULL;
5.17 +
5.18 dirent = client_readdir(reader);
5.19
5.20 if (dirent != NULL)
5.21 {
5.22 + name = strdup(dirent->d_name);
5.23 printf("> %s\n", dirent->d_name);
5.24 free(dirent);
5.25 }
5.26
5.27 printf("Entry shown.\n");
5.28
5.29 + /* Rewind to show the same entry. */
5.30 +
5.31 + char *name2 = NULL;
5.32 +
5.33 + client_rewinddir(reader);
5.34 +
5.35 + dirent = client_readdir(reader);
5.36 +
5.37 + if (dirent != NULL)
5.38 + {
5.39 + name2 = strdup(dirent->d_name);
5.40 + printf("> %s\n", dirent->d_name);
5.41 + free(dirent);
5.42 + }
5.43 +
5.44 + printf("Entry shown and identical: %s\n", (name != NULL) && (name2 != NULL) && !strcmp(name, name2) ? "True" : "False");
5.45 +
5.46 printf("End of test.\n");
5.47 return 0;
5.48 }