Home | History | Annotate | Download | only in src
      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