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