1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/tests/dstest_file_monitor.cc Sat Oct 02 23:57:02 2021 +0200
1.3 @@ -0,0 +1,149 @@
1.4 +/*
1.5 + * Test directory monitoring operations.
1.6 + *
1.7 + * Copyright (C) 2020, 2021 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#include <l4/re/env.h>
1.26 +#include <l4/sys/err.h>
1.27 +
1.28 +#include <thread>
1.29 +
1.30 +#include <stdio.h>
1.31 +#include <string.h>
1.32 +#include <stdlib.h>
1.33 +#include <unistd.h>
1.34 +
1.35 +#include <fsclient/client.h>
1.36 +#include <systypes/fcntl.h>
1.37 +
1.38 +
1.39 +
1.40 +static file_t *open_object(char *filename, flags_t flags, bool have_uid, sys_uid_t uid)
1.41 +{
1.42 + /* With a user, open a user-specific file opener. */
1.43 +
1.44 + if (have_uid)
1.45 + {
1.46 + l4_cap_idx_t opener = client_open_for_user((user_t) {uid, uid, 0022});
1.47 +
1.48 + if (l4_is_invalid_cap(opener))
1.49 + {
1.50 + printf("Could not obtain opener for file.\n");
1.51 + return NULL;
1.52 + }
1.53 +
1.54 + /* Invoke the open method to receive the reference. */
1.55 +
1.56 + return client_open_using(filename, flags, opener);
1.57 + }
1.58 + else
1.59 + {
1.60 + return client_open(filename, flags);
1.61 + }
1.62 +}
1.63 +
1.64 +
1.65 +
1.66 +/* Open files in the directory given by filename. */
1.67 +
1.68 +static void open_files(const char *filename, bool have_uid, sys_uid_t uid)
1.69 +{
1.70 + char *buffer = (char *) calloc(strlen(filename) + 10, sizeof(char));
1.71 +
1.72 + if (buffer == NULL)
1.73 + {
1.74 + printf("Could not allocate buffer.\n");
1.75 + return;
1.76 + }
1.77 +
1.78 + for (int i = 0; i < 10; i++)
1.79 + {
1.80 + sprintf(buffer, "%s/file%02d", filename, i);
1.81 +
1.82 + open_object(buffer, O_CREAT | O_RDWR, have_uid, uid);
1.83 + sleep(1);
1.84 + }
1.85 +}
1.86 +
1.87 +/* Monitor files in the given directory. */
1.88 +
1.89 +static void monitor_files(file_t *directory)
1.90 +{
1.91 + long err = client_subscribe(directory, NOTIFY_FILE_OPENED, client_notifier_task());
1.92 +
1.93 + if (err)
1.94 + {
1.95 + printf("Could not subscribe to events on directory.\n");
1.96 + return;
1.97 + }
1.98 +
1.99 + while (1)
1.100 + {
1.101 + /* Wait for notification of content. */
1.102 +
1.103 + err = client_wait_file(directory, client_notifier_task());
1.104 +
1.105 + if (err)
1.106 + {
1.107 + printf("Error waiting for notifications: %s\n", l4sys_errtostr(err));
1.108 + return;
1.109 + }
1.110 +
1.111 + printf("Notified with conditions:%s\n", directory->notifications & NOTIFY_FILE_OPENED ? " file opened" : "");
1.112 + }
1.113 +}
1.114 +
1.115 +
1.116 +
1.117 +int main(int argc, char *argv[])
1.118 +{
1.119 + if (argc < 2)
1.120 + {
1.121 + printf("Need a directory name and an optional user identifier (if used with a filesystem).\n");
1.122 + return 1;
1.123 + }
1.124 +
1.125 + char *filename = argv[1];
1.126 + bool have_uid = (argc > 2) && strlen(argv[2]);
1.127 + sys_uid_t uid = have_uid ? atoi(argv[2]) : 0;
1.128 +
1.129 + printf("Opening %s...\n", filename);
1.130 +
1.131 + file_t *directory = open_object(filename, O_DIRECTORY, have_uid, uid);
1.132 +
1.133 + if (directory == NULL)
1.134 + {
1.135 + printf("Could not open directory.\n");
1.136 + return 1;
1.137 + }
1.138 +
1.139 + /* Schedule threads. */
1.140 +
1.141 + std::thread *activities[2];
1.142 +
1.143 + activities[0] = new std::thread(open_files, filename, have_uid, uid);
1.144 + activities[1] = new std::thread(monitor_files, directory);
1.145 +
1.146 + for (int i = 0; i < 2; i++)
1.147 + activities[i]->join();
1.148 +
1.149 + return 0;
1.150 +}
1.151 +
1.152 +// vim: tabstop=2 expandtab shiftwidth=2