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