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, unsigned long step, unsigned long sample) 37 { 38 /* Allocate a buffer for sampling from the file. */ 39 40 char buf[sample + 1]; 41 42 for (unsigned long offset = 0; offset < file_populated_span(file); offset += step) 43 { 44 unsigned long remaining = file_populated_span(file) - offset; 45 unsigned long sample_remaining = remaining < sample ? remaining : sample; 46 47 printf("%ld bytes from %p...\n", sample_remaining, (file->memory + offset)); 48 memcpy(buf, (file->memory + offset), sample_remaining); 49 buf[sample_remaining] = '\0'; 50 51 unsigned long leading = 0; 52 char *outbuf = buf; 53 54 while ((*outbuf == '\0') && (leading < sample_remaining)) 55 { 56 outbuf++; 57 leading++; 58 } 59 60 if (leading) 61 printf("[%ld zero bytes]\n", leading); 62 63 printf("%s\n", outbuf); 64 65 printf("[%ld bytes after string]\n", sample_remaining - leading - strlen(outbuf)); 66 } 67 } 68 69 int main(int argc, char *argv[]) 70 { 71 if (argc < 4) 72 { 73 printf("Need filename, step and sample size.\n"); 74 return 1; 75 } 76 77 /* Obtain filename and access parameters. */ 78 79 char *filename = argv[1]; 80 unsigned long step = atoi(argv[2]); 81 unsigned long sample = atoi(argv[3]); 82 83 /* Obtain access to the filesystem. */ 84 85 l4_cap_idx_t server = l4re_env_get_cap("server"); 86 87 /* Invoke the open method to receive the file reference. */ 88 89 file_t file; 90 long err = file_open(&file, filename, O_RDWR, server); 91 92 if (err) 93 { 94 printf("Could not obtain file: %s\n", l4sys_errtostr(err)); 95 return 1; 96 } 97 98 /* A region of the file is mapped. Here, the start and length will not provide 99 page-aligned offsets, but the region is nevertheless not masked. */ 100 101 err = file_mmap(&file, 10, 290, 0, 0, file_region_flags(file.flags)); 102 103 if (err) 104 { 105 printf("Could not map file region: %s\n", l4sys_errtostr(err)); 106 return 1; 107 } 108 109 printf("File contents:\n"); 110 111 show(&file, step, sample); 112 113 printf("File shown.\n"); 114 115 /* A region of the file is mapped. Here, the resulting offsets will be used to 116 define a masked region. */ 117 118 err = file_mmap(&file, 10, 290, 10, 290, 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("File contents:\n"); 127 128 show(&file, step, sample); 129 130 printf("File shown.\n"); 131 132 /* Resizing must occur before writing beyond the end of file. Otherwise, the 133 data may get discarded if the supporting flexpage needs to be flushed. */ 134 135 offset_t old_size = file_populated_span(&file); 136 offset_t new_region = round(old_size, page(1)); 137 offset_t new_size = new_region + old_size; 138 139 printf("Resize to %ld...\n", new_size); 140 141 err = file_resize(&file, new_size); 142 143 if (err) 144 { 145 printf("Could not resize file: %s\n", l4sys_errtostr(err)); 146 return 1; 147 } 148 149 printf("Resized file...\n"); 150 151 /* Re-map to avoid masking the region. */ 152 153 err = file_mmap(&file, 10, new_size - 20, 0, 0, file_region_flags(file.flags)); 154 155 if (err) 156 { 157 printf("Could not map file region: %s\n", l4sys_errtostr(err)); 158 return 1; 159 } 160 161 /* Copy the sampled data to another file region. */ 162 163 printf("Copy data to %ld...\n", new_region); 164 165 for (unsigned long offset = 0; offset < old_size; offset += step) 166 { 167 printf("Copying to %ld...\n", new_region + offset); 168 memcpy(file.memory + new_region + offset, file.memory + offset, sample); 169 if (step > sample) 170 memset(file.memory + new_region + offset + sample, 0, step - sample); 171 } 172 173 printf("File contents:\n"); 174 175 show(&file, step, sample); 176 177 printf("File shown.\n"); 178 179 /* Re-map to mask the region again. */ 180 181 err = file_mmap(&file, 0, new_size, 10, new_size - 20, file_region_flags(file.flags)); 182 183 if (err) 184 { 185 printf("Could not map file region: %s\n", l4sys_errtostr(err)); 186 return 1; 187 } 188 189 printf("File contents:\n"); 190 191 show(&file, step, sample); 192 193 printf("File shown.\n"); 194 195 return 0; 196 } 197 198 // vim: tabstop=2 expandtab shiftwidth=2