1 /*############################################################################ 2 # Copyright 2016-2017 Intel Corporation 3 # 4 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # you may not use this file except in compliance with the License. 6 # You may obtain a copy of the License at 7 # 8 # http://www.apache.org/licenses/LICENSE-2.0 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under the License is distributed on an "AS IS" BASIS, 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 ############################################################################*/ 16 17 /*! 18 * \file 19 * \brief Buffer handling utilities implementation. 20 */ 21 22 #include <util/buffutil.h> 23 24 #include <ctype.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include "util/envutil.h" 28 29 /// file static variable that indicates verbose logging 30 static bool g_bufutil_verbose = false; 31 32 bool ToggleVerbosity() { 33 g_bufutil_verbose = (g_bufutil_verbose) ? false : true; 34 return g_bufutil_verbose; 35 } 36 37 bool FileExists(char const* filename) { 38 FILE* fp = NULL; 39 if (!filename || !filename[0]) { 40 return false; 41 } 42 fp = fopen(filename, "rb"); 43 if (fp) { 44 fclose(fp); 45 return true; 46 } 47 return false; 48 } 49 50 size_t GetFileSize(char const* filename) { 51 size_t file_length = 0; 52 FILE* fp = fopen(filename, "rb"); 53 if (fp) { 54 fseek(fp, 0, SEEK_END); 55 file_length = ftell(fp); 56 fclose(fp); 57 } 58 return file_length; 59 } 60 61 size_t GetFileSize_S(char const* filename, size_t max_size) { 62 size_t size = GetFileSize(filename); 63 if (size > max_size) { 64 return 0; 65 } else { 66 return size; 67 } 68 } 69 70 void* AllocBuffer(size_t size) { 71 void* buffer = NULL; 72 if (size) { 73 buffer = malloc(size); 74 } 75 if (!buffer) { 76 log_error("failed to allocate memory"); 77 } 78 return buffer; 79 } 80 81 void* NewBufferFromFile(const char* filename, size_t* size) { 82 void* buffer = NULL; 83 84 do { 85 size_t len = 0; 86 87 if (!FileExists(filename)) { 88 log_error("cannot access '%s'", filename); 89 break; 90 } 91 92 len = GetFileSize_S(filename, SIZE_MAX); 93 if (len == 0) { 94 log_error("cannot load empty file '%s'", filename); 95 break; 96 } 97 98 buffer = AllocBuffer(len); 99 100 if (buffer) { 101 if (0 != ReadLoud(filename, buffer, len)) { 102 free(buffer); 103 buffer = NULL; 104 break; 105 } 106 } 107 108 if (size) { 109 *size = len; 110 } 111 } while (0); 112 return buffer; 113 } 114 115 int ReadBufferFromFile(const char* filename, void* buffer, size_t size) { 116 int result = 0; 117 FILE* file = NULL; 118 do { 119 size_t bytes_read = 0; 120 size_t file_size = 0; 121 file = fopen(filename, "rb"); 122 if (!file) { 123 result = -1; 124 break; 125 } 126 fseek(file, 0, SEEK_END); 127 file_size = ftell(file); 128 fseek(file, 0, SEEK_SET); 129 if ((size_t)file_size != size) { 130 result = -1; 131 break; 132 } 133 134 if (buffer && (0 != size)) { 135 bytes_read = fread(buffer, 1, size, file); 136 if (bytes_read != size) { 137 result = -1; 138 break; 139 } 140 } 141 } while (0); 142 143 if (file) { 144 fclose(file); 145 } 146 147 return result; 148 } 149 150 int WriteBufferToFile(const void* buffer, size_t size, const char* filename) { 151 int result = 0; 152 FILE* file = NULL; 153 do { 154 size_t bytes_written = 0; 155 156 file = fopen(filename, "wb"); 157 if (!file) { 158 result = -1; 159 break; 160 } 161 bytes_written = fwrite(buffer, 1, size, file); 162 if (bytes_written != size) { 163 result = -1; 164 break; 165 } 166 } while (0); 167 168 if (file) { 169 fclose(file); 170 } 171 172 return result; 173 } 174 175 int ReadLoud(char const* filename, void* buf, size_t size) { 176 int result; 177 178 if (!buf || 0 == size) { 179 log_error("internal error: invalid buffer to ReadLoud"); 180 return -1; 181 } 182 183 if (g_bufutil_verbose) { 184 log_msg("reading %s", filename); 185 } 186 187 if (!FileExists(filename)) { 188 log_error("cannot access '%s' for reading", filename); 189 return -1; 190 } 191 192 if (size != GetFileSize(filename)) { 193 log_error("unexpected file size for '%s'. Expected: %d; got: %d", filename, 194 (int)size, (int)GetFileSize(filename)); 195 return -1; 196 } 197 198 result = ReadBufferFromFile(filename, buf, size); 199 if (0 != result) { 200 log_error("failed to read from `%s`", filename); 201 return result; 202 } 203 204 if (g_bufutil_verbose) { 205 PrintBuffer(buf, size); 206 } 207 208 return result; 209 } 210 211 int WriteLoud(void* buf, size_t size, char const* filename) { 212 int result = -1; 213 214 if (!buf || 0 == size) { 215 log_error("internal error: invalid buffer to WriteLoud"); 216 return -1; 217 } 218 219 if (g_bufutil_verbose) { 220 log_msg("writing %s", filename); 221 } 222 223 result = WriteBufferToFile(buf, size, filename); 224 225 if (0 != result) { 226 log_error("failed to write to `%s`", filename); 227 return result; 228 } 229 230 if (g_bufutil_verbose) { 231 PrintBuffer(buf, size); 232 } 233 234 return result; 235 } 236 237 void PrintBuffer(const void* buffer, size_t size) { 238 BufferPrintOptions opts; 239 opts.show_header = true; 240 opts.show_offset = true; 241 opts.show_hex = true; 242 opts.show_ascii = true; 243 opts.bytes_per_group = 2; 244 opts.groups_per_line = 8; 245 PrintBufferOpt(buffer, size, opts); 246 } 247 248 void PrintBufferOpt(const void* buffer, size_t size, BufferPrintOptions opts) { 249 unsigned char* bytes = (unsigned char*)buffer; 250 size_t bytes_per_line = opts.bytes_per_group * opts.groups_per_line; 251 size_t line_offset = 0; 252 size_t byte_offset = 0; 253 size_t byte_col = 0; 254 if (opts.show_header) { 255 if (opts.show_offset) { 256 log_fmt(" offset"); 257 log_fmt(": "); 258 } 259 260 if (opts.show_hex) { 261 byte_col = 0; 262 while (byte_col < bytes_per_line) { 263 log_fmt("%x%x", (int)byte_col, (int)byte_col); 264 if (0 == (byte_col + 1) % opts.bytes_per_group) { 265 log_fmt(" "); 266 } 267 byte_col += 1; 268 } 269 } 270 271 if (opts.show_hex && opts.show_ascii) { 272 log_fmt("| "); 273 } 274 275 if (opts.show_ascii) { 276 byte_col = 0; 277 while (byte_col < bytes_per_line) { 278 log_fmt("%x", (int)byte_col); 279 byte_col += 1; 280 } 281 } 282 283 log_fmt("\n"); 284 285 if (opts.show_offset) { 286 log_fmt("--------"); 287 log_fmt(": "); 288 } 289 290 if (opts.show_hex) { 291 byte_col = 0; 292 while (byte_col < bytes_per_line) { 293 log_fmt("--"); 294 if (0 == (byte_col + 1) % opts.bytes_per_group) { 295 log_fmt("-"); 296 } 297 byte_col += 1; 298 } 299 } 300 301 if (opts.show_hex && opts.show_ascii) { 302 log_fmt("|-"); 303 } 304 305 if (opts.show_ascii) { 306 byte_col = 0; 307 while (byte_col < bytes_per_line) { 308 log_fmt("-"); 309 byte_col += 1; 310 } 311 } 312 log_fmt("\n"); 313 } 314 315 line_offset = 0; 316 317 while (line_offset < size) { 318 if (opts.show_offset) { 319 log_fmt("%08x", (int)line_offset); 320 log_fmt(": "); 321 } 322 323 if (opts.show_hex) { 324 byte_col = 0; 325 while (byte_col < bytes_per_line) { 326 byte_offset = line_offset + byte_col; 327 if (byte_offset < size) { 328 log_fmt("%02x", (int)bytes[byte_offset]); 329 } else { 330 log_fmt(" "); 331 } 332 if (0 == (byte_col + 1) % opts.bytes_per_group) { 333 log_fmt(" "); 334 } 335 byte_col += 1; 336 } 337 } 338 339 if (opts.show_hex && opts.show_ascii) { 340 log_fmt("| "); 341 } 342 343 if (opts.show_ascii) { 344 byte_col = 0; 345 while (byte_col < bytes_per_line) { 346 byte_offset = line_offset + byte_col; 347 if (byte_offset < size) { 348 unsigned char ch = bytes[byte_offset]; 349 if (isprint(ch)) { 350 log_fmt("%c", ch); 351 } else { 352 log_fmt("."); 353 } 354 } else { 355 log_fmt(" "); 356 } 357 byte_col += 1; 358 } 359 } 360 361 log_fmt("\n"); 362 line_offset += bytes_per_line; 363 } 364 } 365