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
ToggleVerbosity()32 bool ToggleVerbosity() {
33 g_bufutil_verbose = (g_bufutil_verbose) ? false : true;
34 return g_bufutil_verbose;
35 }
36
FileExists(char const * filename)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
GetFileSize(char const * filename)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
GetFileSize_S(char const * filename,size_t max_size)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
AllocBuffer(size_t size)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
NewBufferFromFile(const char * filename,size_t * size)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
ReadBufferFromFile(const char * filename,void * buffer,size_t size)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
WriteBufferToFile(const void * buffer,size_t size,const char * filename)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
ReadLoud(char const * filename,void * buf,size_t size)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
WriteLoud(void * buf,size_t size,char const * filename)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
PrintBuffer(const void * buffer,size_t size)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
PrintBufferOpt(const void * buffer,size_t size,BufferPrintOptions opts)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