1.1 --- a/tests/dstest_host_readdir.cc Wed Aug 04 17:13:47 2021 +0200
1.2 +++ b/tests/dstest_host_readdir.cc Wed Aug 04 17:30:14 2021 +0200
1.3 @@ -1,7 +1,7 @@
1.4 /*
1.5 - * Test directory reading.
1.6 + * Test directory reading operations.
1.7 *
1.8 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
1.9 + * Copyright (C) 2020, 2021 Paul Boddie <paul@boddie.org.uk>
1.10 *
1.11 * This program is free software; you can redistribute it and/or
1.12 * modify it under the terms of the GNU General Public License as
1.13 @@ -19,34 +19,113 @@
1.14 * Boston, MA 02110-1301, USA
1.15 */
1.16
1.17 +#include <l4/re/env.h>
1.18 +#include <l4/sys/err.h>
1.19 +
1.20 #include <dirent.h>
1.21 #include <stdio.h>
1.22 +#include <string.h>
1.23 +#include <stdlib.h>
1.24 +
1.25 +#include <fsclient/client.h>
1.26 +#include <systypes/fcntl.h>
1.27
1.28
1.29
1.30 +#define DIRENT_CORE_SIZE (sizeof(struct dirent) - sizeof(((struct dirent *) 0)->d_name))
1.31 +
1.32 int main(int argc, char *argv[])
1.33 {
1.34 if (argc < 2)
1.35 {
1.36 - printf("Need directory name.\n");
1.37 + printf("Need a directory name and an optional user identifier (if used with a filesystem).\n");
1.38 + return 1;
1.39 + }
1.40 +
1.41 + char *filename = argv[1];
1.42 + bool have_uid = (argc > 2) && strlen(argv[2]);
1.43 + sys_uid_t uid = have_uid ? atoi(argv[2]) : 0;
1.44 + file_t *file;
1.45 +
1.46 + /* With a user, open a user-specific file opener. */
1.47 +
1.48 + if (have_uid)
1.49 + {
1.50 + l4_cap_idx_t opener = client_open_for_user((user_t) {uid, uid, 0022});
1.51 +
1.52 + if (l4_is_invalid_cap(opener))
1.53 + {
1.54 + printf("Could not obtain opener for file.\n");
1.55 + return 1;
1.56 + }
1.57 +
1.58 + /* Invoke the open method to receive the file reference. */
1.59 +
1.60 + file = client_open_using(filename, O_DIRECTORY, opener);
1.61 + }
1.62 + else
1.63 + {
1.64 + file = client_open(filename, O_DIRECTORY);
1.65 + }
1.66 +
1.67 + if (file == NULL)
1.68 + {
1.69 + printf("Could not obtain directory.\n");
1.70 return 1;
1.71 }
1.72
1.73 - /* Obtain directory name. */
1.74 + // NOTE: To be replaced by a proper mechanism identifying the nature of each
1.75 + // NOTE: obtained object.
1.76 +
1.77 + file->can_mmap = 0;
1.78 + file->has_size = 0;
1.79
1.80 - char *filename = argv[1];
1.81 - DIR *dir = opendir(filename);
1.82 + /* Register the reader for notification. */
1.83 +
1.84 + long err = client_set_blocking(file, NOTIFY_CONTENT_AVAILABLE);
1.85
1.86 - if (dir == NULL)
1.87 + if (err)
1.88 {
1.89 - printf("Could not obtain directory: %s\n", filename);
1.90 + printf("Could not subscribe to notifications: %s\n", l4sys_errtostr(err));
1.91 return 1;
1.92 }
1.93
1.94 - struct dirent *dirent;
1.95 + char buffer[DIRENT_CORE_SIZE];
1.96 + offset_t nread = client_read(file, buffer, DIRENT_CORE_SIZE);
1.97 + offset_t total = 0;
1.98 +
1.99 + while (nread)
1.100 + {
1.101 + total += nread;
1.102 +
1.103 + if (total == DIRENT_CORE_SIZE)
1.104 + {
1.105 + struct dirent *dirent = (struct dirent *) buffer;
1.106 + int remaining = dirent->d_reclen - DIRENT_CORE_SIZE;
1.107 + char entry[DIRENT_CORE_SIZE + remaining], *current;
1.108 +
1.109 + memcpy(entry, buffer, DIRENT_CORE_SIZE);
1.110 + current = entry + DIRENT_CORE_SIZE;
1.111
1.112 - while ((dirent = readdir(dir)) != NULL)
1.113 - printf("> %s\n", dirent->d_name);
1.114 + do
1.115 + {
1.116 + nread = client_read(file, current, remaining);
1.117 + remaining -= nread;
1.118 + current += nread;
1.119 + }
1.120 + while (nread && remaining);
1.121 +
1.122 + if (remaining)
1.123 + break;
1.124 +
1.125 + dirent = (struct dirent *) entry;
1.126 + printf("> %s\n", dirent->d_name);
1.127 +
1.128 + total = 0;
1.129 + }
1.130 +
1.131 + nread = client_read(file, buffer, DIRENT_CORE_SIZE);
1.132 + }
1.133
1.134 printf("Directory shown.\n");
1.135