1 /* 2 * Test directory reading operations, exploring concurrency issues. 3 * 4 * Copyright (C) 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/re/env.h> 23 #include <l4/sys/err.h> 24 25 #include <stdio.h> 26 #include <string.h> 27 #include <stdlib.h> 28 29 #include <fsclient/client.h> 30 #include <systypes/fcntl.h> 31 32 33 34 static int count_files(const char *filename, int *found) 35 { 36 file_t *reader = client_opendir(filename); 37 struct dirent *dirent; 38 39 if (!client_opened(reader)) 40 { 41 printf("Failed to open %s: %s\n", filename, reader != NULL ? l4sys_errtostr(reader->error) : "(no reader)"); 42 client_close(reader); 43 return 1; 44 } 45 46 *found = 0; 47 48 while ((dirent = client_readdir(reader)) != NULL) 49 { 50 free(dirent); 51 (*found)++; 52 } 53 54 client_close(reader); 55 return 0; 56 } 57 58 int main(int argc, char *argv[]) 59 { 60 if (argc < 2) 61 { 62 printf("Need a directory name.\n"); 63 return 1; 64 } 65 66 char *filename = argv[1]; 67 int original; 68 69 if (count_files(filename, &original)) 70 { 71 printf("Could not read from directory.\n"); 72 return 1; 73 } 74 75 printf("Files found: %d\n", original); 76 77 /* Operate on files with sequence numbering in a certain range. */ 78 79 int filenum_base = 1000, filenum = filenum_base; 80 int to_create = 100, remaining = to_create; 81 char buffer[strlen(filename) + strlen("/file-XXXX.txt") + 10]; 82 char data[256]; 83 int found = 0; 84 file_t *files[to_create]; 85 86 /* Open a directory for reading. */ 87 88 printf("Opening %s...\n", filename); 89 90 file_t *reader = client_opendir(filename); 91 92 if (!client_opened(reader)) 93 { 94 client_close(reader); 95 printf("Could not read from directory.\n"); 96 return 1; 97 } 98 99 /* Read entries from the directory. */ 100 101 struct dirent *dirent; 102 103 printf("Reading...\n"); 104 105 while ((dirent = client_readdir(reader)) != NULL) 106 { 107 free(dirent); 108 found++; 109 110 /* Create files while getting the listing. */ 111 112 if (remaining) 113 { 114 sprintf(buffer, "%s/file-%d.txt", filename, filenum); 115 116 file_t *file = client_open(buffer, O_RDWR | O_CREAT); 117 118 if (!client_opened(file)) 119 { 120 printf("Could not open file %s: %s\n", buffer, file != NULL ? l4sys_errtostr(file->error) : "(null)"); 121 client_close(file); 122 return 1; 123 } 124 125 /* Write something to each file. */ 126 127 sprintf(data, "Data in file-%d.txt", filenum); 128 client_write(file, data, strlen(data)); 129 130 /* Remember the file for later. */ 131 132 files[filenum - filenum_base] = file; 133 134 remaining--; 135 filenum++; 136 } 137 } 138 139 printf("Files found: %d\n", found); 140 141 /* Re-read, counting files. */ 142 143 if (count_files(filename, &found)) 144 { 145 printf("Could not read from directory.\n"); 146 return 1; 147 } 148 149 printf("Files found: %d\n", found); 150 151 /* Remove some files. */ 152 153 for (filenum = 1000, remaining = to_create; remaining > 0; remaining--, filenum++) 154 { 155 sprintf(buffer, "%s/file-%d.txt", filename, filenum); 156 157 long err = client_remove(buffer); 158 159 if (err) 160 { 161 printf("Could not remove file %s: %s\n", buffer, l4sys_errtostr(err)); 162 return 1; 163 } 164 } 165 166 /* Re-read, counting files. */ 167 168 if (count_files(filename, &found)) 169 { 170 printf("Could not read from directory.\n"); 171 return 1; 172 } 173 174 printf("Files found: %d\n", found); 175 176 /* Read from the still-open but now removed files. */ 177 178 found = 0; 179 180 for (filenum = 1000, remaining = 0; remaining < to_create; remaining++, filenum++) 181 { 182 file_t *file = files[filenum - filenum_base]; 183 char read_data[256]; 184 185 client_seek(file, SEEK_SET, 0); 186 offset_t nread = client_read(file, read_data, 256); 187 188 if (nread) 189 { 190 read_data[nread] = '\0'; 191 sprintf(data, "Data in file-%d.txt", filenum); 192 193 if (!strcmp(data, read_data)) 194 found++; 195 } 196 } 197 198 printf("Files still open: %d (%d)\n", found, to_create); 199 printf("All created files still open: %s\n", found == to_create ? "True" : "False"); 200 201 /* Close the files. */ 202 203 for (remaining = 0; remaining < to_create; remaining++) 204 client_close(files[remaining]); 205 206 printf("Closed files.\n"); 207 208 /* Re-read, counting files. */ 209 210 if (count_files(filename, &found)) 211 { 212 printf("Could not read from directory.\n"); 213 return 1; 214 } 215 216 printf("Files found: %d (%d)\n", found, original); 217 printf("Removed all surplus files: %s\n", found == original ? "True" : "False"); 218 printf("End of test.\n"); 219 return 0; 220 } 221 222 // vim: tabstop=2 expandtab shiftwidth=2