1.1 --- a/libfsclient/include/fsclient/client.h Tue Aug 10 23:41:21 2021 +0200
1.2 +++ b/libfsclient/include/fsclient/client.h Tue Aug 10 23:41:57 2021 +0200
1.3 @@ -21,6 +21,7 @@
1.4
1.5 #pragma once
1.6
1.7 +#include <dirent.h>
1.8 #include <fsclient/file.h>
1.9
1.10
1.11 @@ -61,6 +62,10 @@
1.12 offset_t client_seek(file_t *file, offset_t offset, int whence);
1.13 long client_tell(file_t *file);
1.14
1.15 +/* Directory reading operations. */
1.16 +
1.17 +struct dirent *client_readdir(file_t *file);
1.18 +
1.19 /* Notification operations. */
1.20
1.21 long client_set_blocking(file_t *file, notify_flags_t flags);
2.1 --- a/libfsclient/lib/src/client.cc Tue Aug 10 23:41:21 2021 +0200
2.2 +++ b/libfsclient/lib/src/client.cc Tue Aug 10 23:41:57 2021 +0200
2.3 @@ -23,6 +23,7 @@
2.4
2.5 #include <stdio.h>
2.6 #include <stdlib.h>
2.7 +#include <string.h>
2.8
2.9 #include "client.h"
2.10
2.11 @@ -32,6 +33,10 @@
2.12
2.13 const offset_t DEFAULT_PIPE_SIZE = 4096;
2.14
2.15 +/* Size of the core member region of a directory entry structure. */
2.16 +
2.17 +const offset_t DIRENT_CORE_SIZE = (sizeof(struct dirent) - sizeof(((struct dirent *) 0)->d_name));
2.18 +
2.19
2.20
2.21 /* Access the given position and synchronise state with the file object. Pipe
2.22 @@ -271,6 +276,18 @@
2.23
2.24
2.25
2.26 +/* Obtain the current region of a pipe. */
2.27 +
2.28 +long client_current_region(file_t *file)
2.29 +{
2.30 + if (file == NULL)
2.31 + return -L4_EINVAL;
2.32 +
2.33 + return pipe_current(file);
2.34 +}
2.35 +
2.36 +
2.37 +
2.38 /* Flush data explicitly to the filesystem object. */
2.39
2.40 long client_flush(file_t *file)
2.41 @@ -297,18 +314,6 @@
2.42
2.43
2.44
2.45 -/* Obtain the current region of a pipe. */
2.46 -
2.47 -long client_current_region(file_t *file)
2.48 -{
2.49 - if (file == NULL)
2.50 - return -L4_EINVAL;
2.51 -
2.52 - return pipe_current(file);
2.53 -}
2.54 -
2.55 -
2.56 -
2.57 /* Obtain the next region of a pipe. */
2.58
2.59 long client_next_region(file_t *file)
2.60 @@ -321,6 +326,51 @@
2.61
2.62
2.63
2.64 +/* Read a directory entry. This must be freed by the caller after use. */
2.65 +
2.66 +struct dirent *client_readdir(file_t *file)
2.67 +{
2.68 + char buffer[DIRENT_CORE_SIZE];
2.69 + offset_t nread = client_read(file, buffer, DIRENT_CORE_SIZE);
2.70 +
2.71 + /* Stop if no new structure can be successfully read. */
2.72 +
2.73 + if (nread != DIRENT_CORE_SIZE)
2.74 + return NULL;
2.75 +
2.76 + struct dirent *dirent = (struct dirent *) buffer;
2.77 + offset_t remaining = dirent->d_reclen - DIRENT_CORE_SIZE;
2.78 +
2.79 + /* Allocate a buffer for the complete structure. */
2.80 +
2.81 + char *entry = (char *) calloc(DIRENT_CORE_SIZE + remaining, sizeof(char));
2.82 +
2.83 + if (entry == NULL)
2.84 + return NULL;
2.85 +
2.86 + /* Copy the start of the entry into a new buffer. */
2.87 +
2.88 + memcpy(entry, buffer, DIRENT_CORE_SIZE);
2.89 +
2.90 + /* Append to the entry buffer. */
2.91 +
2.92 + char *current = entry + DIRENT_CORE_SIZE;
2.93 +
2.94 + nread = client_read(file, current, remaining);
2.95 +
2.96 + /* Stop if no complete structure can be successfully read. */
2.97 +
2.98 + if (nread != remaining)
2.99 + {
2.100 + free(entry);
2.101 + return NULL;
2.102 + }
2.103 +
2.104 + return (struct dirent *) entry;
2.105 +}
2.106 +
2.107 +
2.108 +
2.109 /* Read from the filesystem object into the buffer provided. */
2.110
2.111 offset_t client_read(file_t *file, void *buf, offset_t count)
3.1 --- a/tests/dstest_file_readdir.cc Tue Aug 10 23:41:21 2021 +0200
3.2 +++ b/tests/dstest_file_readdir.cc Tue Aug 10 23:41:57 2021 +0200
3.3 @@ -22,7 +22,6 @@
3.4 #include <l4/re/env.h>
3.5 #include <l4/sys/err.h>
3.6
3.7 -#include <dirent.h>
3.8 #include <stdio.h>
3.9 #include <string.h>
3.10 #include <stdlib.h>
3.11 @@ -32,55 +31,6 @@
3.12
3.13
3.14
3.15 -#define DIRENT_CORE_SIZE (sizeof(struct dirent) - sizeof(((struct dirent *) 0)->d_name))
3.16 -
3.17 -
3.18 -
3.19 -/* Return a directory entry. This must be freed by the caller after use. */
3.20 -
3.21 -static struct dirent *read_directory_entry(file_t *file)
3.22 -{
3.23 - char buffer[DIRENT_CORE_SIZE];
3.24 - offset_t nread = client_read(file, buffer, DIRENT_CORE_SIZE);
3.25 -
3.26 - /* Stop if no new structure can be successfully read. */
3.27 -
3.28 - if (nread != DIRENT_CORE_SIZE)
3.29 - return NULL;
3.30 -
3.31 - struct dirent *dirent = (struct dirent *) buffer;
3.32 - offset_t remaining = dirent->d_reclen - DIRENT_CORE_SIZE;
3.33 -
3.34 - /* Allocate a buffer for the complete structure. */
3.35 -
3.36 - char *entry = (char *) calloc(DIRENT_CORE_SIZE + remaining, sizeof(char));
3.37 -
3.38 - if (entry == NULL)
3.39 - return NULL;
3.40 -
3.41 - /* Copy the start of the entry into a new buffer. */
3.42 -
3.43 - memcpy(entry, buffer, DIRENT_CORE_SIZE);
3.44 -
3.45 - /* Append to the entry buffer. */
3.46 -
3.47 - char *current = entry + DIRENT_CORE_SIZE;
3.48 -
3.49 - nread = client_read(file, current, remaining);
3.50 -
3.51 - /* Stop if no complete structure can be successfully read. */
3.52 -
3.53 - if (nread != remaining)
3.54 - {
3.55 - free(entry);
3.56 - return NULL;
3.57 - }
3.58 -
3.59 - return (struct dirent *) entry;
3.60 -}
3.61 -
3.62 -
3.63 -
3.64 static file_t *open_file(char *filename, bool have_uid, sys_uid_t uid)
3.65 {
3.66 /* With a user, open a user-specific file opener. */
3.67 @@ -145,7 +95,7 @@
3.68
3.69 struct dirent *dirent;
3.70
3.71 - while ((dirent = read_directory_entry(file)) != NULL)
3.72 + while ((dirent = client_readdir(file)) != NULL)
3.73 {
3.74 printf("> %s\n", dirent->d_name);
3.75 free(dirent);
3.76 @@ -171,7 +121,7 @@
3.77 return 1;
3.78 }
3.79
3.80 - dirent = read_directory_entry(file);
3.81 + dirent = client_readdir(file);
3.82
3.83 if (dirent != NULL)
3.84 {