1 /* 2 * Test dataspace operations. 3 * 4 * Copyright (C) 2020, 2021, 2022, 2023 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 <systypes/env.h> 26 #include <systypes/fcntl.h> 27 #include <systypes/format.h> 28 29 #define FMToffsetd "%" pFMToffset "d" 30 31 #include <stdio.h> 32 #include <string.h> 33 #include <stdlib.h> 34 35 #include <fsclient/file.h> 36 #include <mem/memory_utils.h> 37 38 39 40 static void show(file_t *file, offset_t step, offset_t sample) 41 { 42 /* Allocate a buffer for sampling from the file. */ 43 44 char buf[sample + 1]; 45 46 for (offset_t offset = 0; offset < file_populated_span(file); offset += step) 47 { 48 offset_t remaining = file_populated_span(file) - offset; 49 offset_t sample_remaining = remaining < sample ? remaining : sample; 50 51 printf(FMToffsetd " bytes from %p...\n", sample_remaining, (file->memory + offset)); 52 memcpy(buf, (file->memory + offset), sample_remaining); 53 buf[sample_remaining] = '\0'; 54 55 offset_t leading = 0; 56 char *outbuf = buf; 57 58 /* Skip leading zero bytes. */ 59 60 while ((*outbuf == '\0') && (leading < sample_remaining)) 61 { 62 outbuf++; 63 leading++; 64 } 65 66 offset_t trailing = 0; 67 char *outbuf_end = outbuf + strlen(outbuf), *end = buf + sample_remaining - 1; 68 69 while ((*end == '\0') && (end >= outbuf_end)) 70 { 71 end--; 72 trailing++; 73 } 74 75 printf("----\n%s\n----\n", outbuf); 76 77 printf("[" FMToffsetd " zero bytes at start]\n", leading); 78 printf("[%zd bytes shown]\n", strlen(outbuf)); 79 printf("[" FMToffsetd " bytes after string]\n", sample_remaining - leading - strlen(outbuf)); 80 printf("[" FMToffsetd " zero bytes at end]\n", trailing); 81 } 82 } 83 84 int main(int argc, char *argv[]) 85 { 86 if (argc < 4) 87 { 88 printf("Need filename, step and sample size.\n"); 89 return 1; 90 } 91 92 /* Obtain filename and access parameters. */ 93 94 char *filename = argv[1]; 95 offset_t step = atoi(argv[2]); 96 offset_t sample = atoi(argv[3]); 97 98 /* Obtain access to the filesystem. */ 99 100 l4_cap_idx_t server = l4re_env_get_cap(ENV_FILESYSTEM_SERVER_NAME); 101 102 /* Invoke the open method to receive the file reference. */ 103 104 file_t file; 105 long err = file_open(&file, filename, O_RDWR, server); 106 107 if (err) 108 { 109 printf("Could not obtain file: %s\n", l4sys_errtostr(err)); 110 return 1; 111 } 112 113 offset_t original_size = file.size; 114 115 /* A region of the file is mapped. Here, the start and length is not provided 116 as page-aligned offsets, but the region is nevertheless not masked, and the 117 region limits will be page-aligned in any case. */ 118 119 err = file_mmap(&file, 10, original_size - 20, 0, 0, file_region_flags(file.flags)); 120 121 if (err) 122 { 123 printf("Could not map file region: %s\n", l4sys_errtostr(err)); 124 return 1; 125 } 126 127 printf("Region " FMToffsetd "..." FMToffsetd " populated size " FMToffsetd 128 " size " FMToffsetd ".\n", 129 file.start_pos, file.end_pos, file_populated_span(&file), file.size); 130 printf("File contents:\n"); 131 132 show(&file, step, sample); 133 134 printf("File shown.\n"); 135 printf("Expected...\n" 136 "[0 zero bytes at start]\n" 137 "[" FMToffsetd " bytes shown]\n" 138 "[0 bytes after string]\n" 139 "[0 zero bytes at end]\n\n", 140 original_size); 141 142 /* A region of the file is mapped. Here, the resulting offsets will be used to 143 define a masked region. */ 144 145 err = file_mmap(&file, 10, original_size - 20, 10, original_size - 10, file_region_flags(file.flags)); 146 147 if (err) 148 { 149 printf("Could not map file region: %s\n", l4sys_errtostr(err)); 150 return 1; 151 } 152 153 printf("Region " FMToffsetd "..." FMToffsetd " populated size " FMToffsetd 154 " size " FMToffsetd ".\n", 155 file.start_pos, file.end_pos, file_populated_span(&file), file.size); 156 printf("File contents:\n"); 157 158 show(&file, step, sample); 159 160 printf("File shown.\n"); 161 printf("Expected...\n" 162 "[10 zero bytes at start]\n" 163 "[" FMToffsetd " bytes shown]\n" 164 "[" FMToffsetd " bytes after string]\n" 165 "[" FMToffsetd " zero bytes at end]\n\n", 166 original_size - 20, 10ULL, 10ULL); 167 168 /* Resizing must occur before writing beyond the end of file. Otherwise, the 169 data may get discarded if the supporting flexpage needs to be flushed. */ 170 171 offset_t old_populated_size = file_populated_span(&file); 172 offset_t old_size = file.size; 173 offset_t old_populated_size_rounded = round(old_populated_size, page(1)); 174 offset_t new_size = old_populated_size_rounded + old_populated_size; 175 offset_t new_region = round(new_size, page(1)); 176 177 printf("Resize to " FMToffsetd "...\n", new_size); 178 179 err = file_resize(&file, new_size); 180 181 if (err) 182 { 183 printf("Could not resize file: %s\n", l4sys_errtostr(err)); 184 return 1; 185 } 186 187 printf("Resized file...\n"); 188 printf("Region " FMToffsetd "..." FMToffsetd " populated size " FMToffsetd 189 " size " FMToffsetd ".\n", 190 file.start_pos, file.end_pos, file_populated_span(&file), file.size); 191 printf("Expected " FMToffsetd "..." FMToffsetd " populated size " FMToffsetd 192 " size " FMToffsetd ".\n\n", 193 0ULL, old_populated_size_rounded, old_populated_size_rounded, new_size); 194 195 /* Re-map to avoid masking the region. */ 196 197 err = file_mmap(&file, 0, new_size, 0, 0, file_region_flags(file.flags)); 198 199 if (err) 200 { 201 printf("Could not map file region: %s\n", l4sys_errtostr(err)); 202 return 1; 203 } 204 205 printf("Remapped file without masking...\n"); 206 printf("Region " FMToffsetd "..." FMToffsetd " populated size " FMToffsetd 207 " size " FMToffsetd ".\n", 208 file.start_pos, file.end_pos, file_populated_span(&file), file.size); 209 printf("Expected " FMToffsetd "..." FMToffsetd " populated size " FMToffsetd 210 " size " FMToffsetd ".\n\n", 211 0ULL, new_region, old_populated_size, old_size); 212 213 printf("Resize to " FMToffsetd "...\n", new_size); 214 215 err = file_resize(&file, new_size); 216 217 if (err) 218 { 219 printf("Could not resize file: %s\n", l4sys_errtostr(err)); 220 return 1; 221 } 222 223 printf("Resized file...\n"); 224 printf("Region " FMToffsetd "..." FMToffsetd " populated size " FMToffsetd 225 " size " FMToffsetd ".\n", 226 file.start_pos, file.end_pos, file_populated_span(&file), file.size); 227 printf("Expected " FMToffsetd "..." FMToffsetd " populated size " FMToffsetd 228 " size " FMToffsetd ".\n\n", 229 0ULL, round(new_size, page(1)), new_size, new_size); 230 231 /* Copy the file data to another file region. */ 232 233 printf("Copy data to " FMToffsetd "...\n", old_populated_size_rounded); 234 235 memcpy(file.memory + old_populated_size_rounded, file.memory, old_size); 236 237 printf("Region " FMToffsetd "..." FMToffsetd " populated size " FMToffsetd 238 " size " FMToffsetd ".\n", 239 file.start_pos, file.end_pos, file_populated_span(&file), file.size); 240 printf("File contents:\n"); 241 242 show(&file, step, sample); 243 244 printf("File shown.\n"); 245 printf("Expected...\n" 246 "[0 zero bytes at start]\n" 247 "[" FMToffsetd " bytes shown]\n" 248 "[" FMToffsetd " bytes after string]\n" 249 "[" FMToffsetd " zero bytes at end]\n" 250 "...\n" 251 "[0 zero bytes at start]\n" 252 "[" FMToffsetd " bytes shown]\n" 253 "[0 bytes after string]\n" 254 "[0 zero bytes at end]\n\n", 255 original_size, sample - original_size, sample - original_size, 256 original_size); 257 258 /* Re-map to mask the region again. */ 259 260 err = file_mmap(&file, 0, new_size, 10, new_size - 10, file_region_flags(file.flags)); 261 262 if (err) 263 { 264 printf("Could not map file region: %s\n", l4sys_errtostr(err)); 265 return 1; 266 } 267 268 printf("Region " FMToffsetd "..." FMToffsetd " populated size " FMToffsetd 269 " size " FMToffsetd ".\n", 270 file.start_pos, file.end_pos, file_populated_span(&file), file.size); 271 printf("File contents:\n"); 272 273 show(&file, step, sample); 274 275 printf("File shown.\n"); 276 printf("Expected...\n" 277 "[10 zero bytes at start]\n" 278 "[" FMToffsetd " bytes shown]\n" 279 "[" FMToffsetd " bytes after string]\n" 280 "[" FMToffsetd " zero bytes at end]\n" 281 "...\n" 282 "[0 zero bytes at start]\n" 283 "[" FMToffsetd " bytes shown]\n" 284 "[10 bytes after string]\n" 285 "[10 zero bytes at end]\n", 286 original_size - 10, sample - original_size, sample - original_size, 287 original_size - 10); 288 289 printf("End of test.\n"); 290 return 0; 291 } 292 293 // vim: tabstop=2 expandtab shiftwidth=2