| Bsoft 2.0.5 Bernard's software package

bfile.cpp
Go to the documentation of this file.
1
9 #include "options.h"
10 #include "utilities.h"
11 #include <fstream>
12
13 // Declaration of global variables
14 extern int verbose; // Level of output to the screen
15
16 // Function prototypes
17 int show_block(size_t start, size_t size, unsigned char* buf);
18 int show_block_hex(size_t start, size_t size, unsigned char* buf);
19 int show_char(size_t start, size_t size, unsigned char* buf);
20 int swap_block(size_t size, size_t nbytes, unsigned char* buf);
21 int show_table(size_t start, size_t size, unsigned char* buf);
22 int show_structure(size_t start, size_t size, int swap, char* strdef, unsigned char* buf);
23 int poke_value(fstream* fin, size_t loc, char typechar, double value);
24 int find_string(const char* string, size_t start, size_t size, unsigned char* buf);
25 int replace(fstream* fin, char* rstring1, char* rstring2);
26 char* string2byte(char* string);
27 size_t string_bytes(char* string);
28
29 const char* use[] = {
30 " ",
31 "Usage: bfile [options] infile [outfile]",
32 "---------------------------------------",
33 "Examines and modifies binary files.",
34 " ",
35 "Actions:",
36 "-blocks Character value blocks (16 per line).",
37 "-hexadecimal Character hexadecimal value blocks (16 per line).",
38 "-characters Character blocks (64 per line).",
39 "-format bbsif Output formatted according to a sequence of data types.",
40 "-find astring Find the given string.",
41 "-poke 3124,20.4,f Poking at a location a value of a specific data type.",
42 "-replace \"\\n,\\r\" Replace all occurrences of the first string by the second.",
43 " ",
44 "Parameters:",
45 "-verbose 1 Verbosity of output.",
46 "-bytes 128 Number of bytes to read (default 64).",
47 "-start 646 Starting position to read from (default 0).",
48 "-reverse 2 Reverse byte order for (2) bytes.",
49 "-VAX Convert VAX floating point numbers.",
50 " ",
51 "Data types:",
52 " b: byte or unsigned char (1 byte)",
53 " c: signed char (1 byte)",
54 " u: word or unsigned short (2 bytes)",
55 " s: short (2 bytes)",
56 " j: unsigned integer (4 bytes)",
57 " i: integer (4 bytes)",
58 " f: float (4 bytes)",
59 " d: double (8 bytes)",
60 " ",
61 NULL
62 };
63
64 int main(int argc, char **argv)
65 {
66 // Initialize variables
67 size_t buflen(64); /* Default buffer length */
68 size_t start(0); /* Default start of buffer */
69 size_t nbytes(0); /* Number of bytes to swap */
70 int setvax(0);
71 int setblock(0);
72 int sethex(0);
73 int setchar(0);
74 char* strdef = new char[128];
75 Bstring find; /* String to find */
76 int poke(0); /* Flag for poking values */
77 size_t loc(0); /* Location for poking values */
78 char typechar = 'u'; /* Default uchar for poking */
79 double pokevalue(0); /* Value for poking */
80 char rstring1[200] = ""; // String to replace
81 char rstring2[200] = ""; // New string
82 size_t i;
83
84 int optind;
85 Boption* option = get_option_list(use, argc, argv, optind);
86 Boption* curropt;
87 for ( curropt = option; curropt; curropt = curropt->next ) {
88 if ( curropt->tag == "bytes" ) buflen = curropt->value.integer();
89 if ( curropt->tag == "start" ) start = curropt->value.integer();
90 if ( curropt->tag == "reverse" ) nbytes = curropt->value.integer();
91 if ( curropt->tag == "VAX" ) setvax = 1;
92 if ( curropt->tag == "blocks" ) setblock = 1;
93 if ( curropt->tag == "hexadecimal" ) sethex = 1;
94 if ( curropt->tag == "characters" ) setchar = 1;
95 if ( curropt->tag == "format" ) sscanf(curropt->value.c_str(), "%s", strdef);
96 if ( curropt->tag == "find" ) find = curropt->value;
97 if ( curropt->tag == "poke" ) sscanf(curropt->value.c_str(), "%ld,%lf,%c", &loc, &pokevalue, &typechar);
98 if ( curropt->tag == "replace" ) {
99 memcpy(rstring1, &curropt->value[0], curropt->value.length()+1);
100 if ( strlen(rstring1) < 1 )
101 cerr << "-replace: Two strings must be specified!" << endl;
102 else {
103 i = strcspn(rstring1, ",");
104 strcpy(rstring2, rstring1+i+1);
105 rstring1[i] = 0;
106 }
107 }
108 }
109 option_kill(option);
110
111 fstream* fin = new fstream(argv[optind], fstream::in | fstream::out);
112 if ( fin->fail() ) {
113 cerr << "Error: File " << argv[optind] << " not read!" << endl << endl;
114 bexit(-1);
115 } else optind++;
116
117 if ( strlen(rstring1) > 0 ) {
118 replace(fin, rstring1, rstring2);
119 bexit(0);
120 }
121
122 if ( poke ) {
123 poke_value(fin, loc, typechar, pokevalue);
124 start = loc;
125 buflen = 8;
126 }
127
128 fin->seekg (0, ios::end);
129 size_t fsize = (size_t)fin->tellg() - start;
130 if ( buflen > fsize ) buflen = fsize;
131
132 size_t size = buflen*sizeof(unsigned char);
133 unsigned char* buf = new unsigned char[size];
134
135 fin->seekg (start, ios::beg);
136 fin->read((char *)buf, size);
137 fin->close();
138 delete fin;
139
140 if ( setblock ) {
141 show_block(start, size, buf);
142 bexit(0);
143 }
144
145 if ( sethex ) {
146 show_block_hex(start, size, buf);
147 bexit(0);
148 }
149
150 if ( setchar ) {
151 show_char(start, size, buf);
152 bexit(0);
153 }
154
155 if ( strlen(strdef) ) {
156 show_structure(start, size, nbytes, strdef, buf);
157 bexit(0);
158 }
159
160 if ( find.length() ) {
161 find_string(find.c_str(), start, size, buf);
162 // delete[] find;
163 find = 0;
164 bexit(0);
165 }
166
167 if ( setvax ) {
168 cout << "Getting VAX floating point" << endl;
169 for ( i=0; i<size; i+=4 ) vax2ieee((unsigned char *)(buf+i), 0);
170 }
171
172 if ( nbytes ) swap_block(size, nbytes, buf);
173
174 if ( verbose ) show_table(start, size, buf);
175
176 if ( optind < argc ) {
177 ofstream fout(argv[optind]);
178 if ( fout.fail() ) {
179 cerr << "Error: Unable to open " << argv[optind] << endl;
180 bexit(-1);
181 }
182 fout.write((char *)buf, size);
183 fout.close();
184 }
185
186 delete[] buf;
187
188 bexit(0);
189 }
190
191 int show_block(size_t start, size_t size, unsigned char* buf)
192 {
193 size_t i, j;
194
195 for ( i=0; i<size; i+=16 ) {
196 cout << setw(10) << i+start << ": ";
197 for ( j=i; j<i+16; j++ ) cout << setw(4) << (int) buf[j];
198 cout << " |";
199 for ( j=i; j<i+16; j++ ) {
200 if ( isprint(buf[j]) ) cout << buf[j];
201 else cout << " ";
202 }
203 cout << "|" << endl;
204 }
205
206 return 0;
207 }
208
209 int show_block_hex(size_t start, size_t size, unsigned char* buf)
210 {
211 size_t i, j;
212
213 for ( i=0; i<size; i+=16 ) {
214 cout << setw(10) << i+start << ": ";
215 for ( j=i; j<i+16; j++ ) cout << hex << setw(3) << (int) buf[j];
216 cout << " |";
217 for ( j=i; j<i+16; j++ ) {
218 if ( isprint(buf[j]) ) cout << buf[j];
219 else cout << " ";
220 }
221 cout << "|" << endl;
222 }
223
224 return 0;
225 }
226
227 int show_char(size_t start, size_t size, unsigned char* buf)
228 {
229 size_t i, j;
230
231 for ( i=0; i<size; i+=64 ) {
232 cout << setw(10) << i+start << ": ";
233 for ( j=i; j<i+64; j++ ) {
234 if ( isprint(buf[j]) ) cout << buf[j];
235 else cout << " ";
236 }
237 cout << endl;
238 }
239
240 return 0;
241 }
242
243 int swap_block(size_t size, size_t nbytes, unsigned char* buf)
244 {
245 size_t i, j;
246 unsigned char t[8];
247
248 cout << "Swapping byte order for " << nbytes << "-byte types" << endl;
249 for ( i=0; i<size; i+=nbytes ) {
250 memcpy(t, buf+i, nbytes);
251 for( j=0; j<nbytes; j++ ) buf[i+j] = t[nbytes-1-j];
252 }
253
254 return 0;
255 }
256
257 int show_table(size_t start, size_t size, unsigned char* buf)
258 {
259 unsigned char bits[9], thechar;
260 size_t i, j;
261 short* inshort = (short *) buf;
262 int* inint = (int *) buf;
263 long* inlong = (long *) buf;
264 float* infloat = (float *) buf;
265 double* indouble = (double *) buf;
266
267 cout << " loc char bits char short int long float double" << endl;
268 for ( i=0; i<size; i++ ) {
269 for ( j=0; j<8; j++) {
270 bits[j] = '0';
271 if ( ( buf[i] << j ) & 0x80 )
272 bits[j] = '1';
273 }
274 bits[8] = '\0';
275 thechar = (unsigned char)buf[i];
276 if ( !isprint(thechar) ) thechar = ' ';
277 cout << setw(10) << i+start << setw(4) << thechar << setw(10) << bits << setw(5) << (int)buf[i];
278 if ( i%2 == 0 ) cout << setw(8) << inshort[i/2];
279 if ( i%4 == 0 ) cout << setw(10) << inint[i/4];
280 if ( i%4 == 0 ) cout << setw(24) << infloat[i/4];
281 if ( i%8 == 1 ) cout << setw(36) << inlong[i/8];
282 if ( i%8 == 1 ) cout << setw(24) << indouble[i/8];
283 cout << endl;
284 }
285
286 return 0;
287 }
288
289 int show_structure(size_t start, size_t size, int swap, char* strdef, unsigned char* buf)
290 {
291 size_t i, j;
292 unsigned char* uchar;
293 signed char* schar;
294 unsigned short* ushort;
295 signed short* sshort;
296 int* integer;
297 float* floating;
298 double* doublefloat;
299
300 cout << "loc\ttype\tvalue" << endl;
301 i = j = 0;
302 while ( i<size ) {
303 switch ( strdef[j] ) {
304 case 'b':
305 uchar = (unsigned char *) (buf + i);
306 cout << i+start << tab << strdef[j] << tab << *uchar << endl;
307 i += sizeof(char);
308 break;
309 case 'c':
310 schar = (signed char *) (buf + i);
311 cout << i+start << tab << strdef[j] << tab << *schar << endl;
312 i += sizeof(char);
313 break;
314 case 'u':
315 ushort = (unsigned short *) (buf + i);
316 if ( swap ) swapbytes((unsigned char *) ushort, sizeof(short));
317 cout << i+start << tab << strdef[j] << tab << *ushort << endl;
318 i += sizeof(short);
319 break;
320 case 's':
321 sshort = (short *) (buf + i);
322 if ( swap ) swapbytes((unsigned char *) sshort, sizeof(short));
323 cout << i+start << tab << strdef[j] << tab << *sshort << endl;
324 i += sizeof(short);
325 break;
326 case 'i':
327 integer = (int *) (buf + i);
328 if ( swap ) swapbytes((unsigned char *) integer, sizeof(int));
329 cout << i+start << tab << strdef[j] << tab << *integer << endl;
330 i += sizeof(int);
331 break;
332 case 'f':
333 floating = (float *) (buf + i);
334 if ( swap ) swapbytes((unsigned char *) floating, sizeof(float));
335 cout << i+start << tab << strdef[j] << tab << *floating << endl;
336 i += sizeof(float);
337 break;
338 case 'd':
339 doublefloat = (double *) (buf + i);
340 if ( swap ) swapbytes((unsigned char *) doublefloat, sizeof(double));
341 cout << i+start << tab << strdef[j] << tab << *doublefloat << endl;
342 i += sizeof(double);
343 break;
344 default: break;
345 }
346 j++;
347 if ( j > strlen(strdef) ) j = 0;
348 }
349
350 return 0;
351 }
352
353 int find_string(const char* string, size_t start, size_t size, unsigned char* buf)
354 {
355 size_t i, j, n(0), ssize = strlen(string);
356
357 cout << "Searching for: " << string << endl;
358 for ( i=0; i<size - ssize + 1; i++, buf++ ) {
359 if ( strncasecmp(string, (char *)buf, ssize) == 0 ) {
360 cout << setw(10) << i+start << ":";
361 for ( j=0; j<64; j++ ) cout << buf[j];
362 cout << endl;
363 n++;
364 }
365 }
366 cout << "Found: " << n << endl;
367
368 return 0;
369 }
370
371 int poke_value(fstream* fin, size_t loc, char typechar, double value)
372 {
373 unsigned char bval = (unsigned char)value;
374 signed char cval = (signed char)value;
375 unsigned short uval = (unsigned short)value;
376 short sval = (short)value;
377 int ival = (int)value;
378 double dval = (double)value;
379
380 fin->seekg(loc, ios::beg);
381 switch ( typechar ) {
382 case 'b':
383 fin->write((char *)&bval, sizeof(char));
384 break;
385 case 'c':
386 fin->write((char *)&cval, sizeof(char));
387 break;
388 case 'u':
389 fin->write((char *)&uval, sizeof(short));
390 break;
391 case 's':
392 fin->write((char *)&sval, sizeof(short));
393 break;
394 case 'i':
395 fin->write((char *)&ival, sizeof(int));
396 break;
397 case 'f':
398 fin->write((char *)&value, sizeof(float));
399 break;
400 case 'd':
401 fin->write((char *)&dval, sizeof(double));
402 break;
403 default: break;
404 }
405
406 return 0;
407 }
408
409 int replace(fstream* fin, char* rstring1, char* rstring2)
410 {
411 size_t i, j, m, n, nr(0);
412
413 char* fromstr = string2byte(rstring1);
414 char* tostr = string2byte(rstring2);
415
416 if ( verbose )
417 cout << "Replacing \"" << rstring1 << "\" with \"" << rstring2 << "\"" << endl;
418
419 // if ( strlen(tostr) < 1 ) strcpy(tostr, " ");
420
421 if ( strlen(fromstr) < 1 ) {
422 cerr << "Error: The search string has zero length!" << endl;
423 return -1;
424 }
425
426 fin->seekg(0, ios::end);
427 size_t filesize = fin->tellg();
428 fin->seekg(0, ios::beg);
429
430 if ( verbose )
431 cout << "File size: " << filesize << endl;
432
433 char* buf = new char[filesize];
434 char* newbuf = new char[filesize];
435
436 fin->read(buf, filesize);
437
438 i = j = nr = 0;
439 m = string_bytes(fromstr);
440 n = string_bytes(tostr);
441 while ( i < filesize ) {
442 if ( memcmp(buf+i, fromstr, m) == 0 ) {
443 memcpy(newbuf+j, tostr, n);
444 i += m;
445 j += n;
446 nr++;
447 } else {
448 newbuf[j] = buf[i];
449 i++;
450 j++;
451 }
452 }
453
454 fin->seekg(0, ios::beg);
455
456 fin->write(newbuf, filesize);
457
458 fin->close();
459
460 if ( verbose )
461 cout << "Number of replacements: " << nr << endl << endl;
462
463 return 0;
464 }
465
466 char* string2byte(char* string)
467 {
468 size_t i, j, setcntl(0);
469 char* bytes = new char[strlen(string)+1];
470
471 j = 0;
472 for ( i=0; i<strlen(string); i++ ) {
473 bytes[j] = 0;
474 if ( setcntl ) {
475 if ( string[i] == 'a' ) bytes[j] = 7;
476 if ( string[i] == 'b' ) bytes[j] = 8;
477 if ( string[i] == 't' ) bytes[j] = 9;
478 if ( string[i] == 'n' ) bytes[j] = 10;
479 if ( string[i] == 'v' ) bytes[j] = 11;
480 if ( string[i] == 'f' ) bytes[j] = 12;
481 if ( string[i] == 'r' ) bytes[j] = 13;
482 if ( string[i] == '\\' ) bytes[j] = 28;
483 setcntl = 0;
484 j++;
485 } else if ( string[i] == '\\' ) {
486 setcntl = 1;
487 } else {
488 bytes[j] = string[i];
489 j++;
490 }
491 }
492
493 delete[] bytes;
494
495 return bytes;
496 }
497
498 size_t string_bytes(char* string)
499 {
500 size_t i(0), n(0);
501
502 for ( i=0; i<strlen(string); i++ ) if ( string[i] != '\\' ) n++;
503
504 return n;
505 }
506
verbose
int verbose
replace
int replace(fstream *fin, char *rstring1, char *rstring2)
Definition: bfile.cpp:409
main
int main(int argc, char **argv)
Definition: bfile.cpp:64
show_structure
int show_structure(size_t start, size_t size, int swap, char *strdef, unsigned char *buf)
Definition: bfile.cpp:289
utilities.h
Header file for general utilities.
Boption::value
Bstring value
Definition: options.h:30
Boption::tag
Bstring tag
Definition: options.h:29
Bstring::length
long length() const
Definition: Bstring.cpp:263
swap_block
int swap_block(size_t size, size_t nbytes, unsigned char *buf)
Definition: bfile.cpp:243
get_option_list
Boption * get_option_list(const char *use[], int argc, char *argv[], int &optind)
Parses command line arguments based on a template.
Definition: options.cpp:40
poke_value
int poke_value(fstream *fin, size_t loc, char typechar, double value)
Definition: bfile.cpp:371
show_char
int show_char(size_t start, size_t size, unsigned char *buf)
Definition: bfile.cpp:227
Boption
A class for a command line input option.
Definition: options.h:26
vax2ieee
void vax2ieee(unsigned char *v, int sb)
Converts VAX floating point format to IEEE floating point format.
Definition: utilities.cpp:548
find_string
int find_string(const char *string, size_t start, size_t size, unsigned char *buf)
Definition: bfile.cpp:353
string_bytes
size_t string_bytes(char *string)
Definition: bfile.cpp:498
show_block_hex
int show_block_hex(size_t start, size_t size, unsigned char *buf)
Definition: bfile.cpp:209
swapbytes
void swapbytes(unsigned char *v, size_t n)
Swaps bytes.
Definition: utilities.cpp:504
Bstring::c_str
const char * c_str()
Definition: Bstring.h:70
Boption::next
Boption * next
Definition: options.h:28
show_table
int show_table(size_t start, size_t size, unsigned char *buf)
Definition: bfile.cpp:257
Bstring
Definition: Bstring.h:29
use
const char * use[]
Definition: bfile.cpp:29
string2byte
char * string2byte(char *string)
Definition: bfile.cpp:466
option_kill
int option_kill(Boption *option)
Deallocates a linked list of option structures.
Definition: options.cpp:109
Bstring::integer
long integer()
Definition: Bstring.cpp:539
show_block
int show_block(size_t start, size_t size, unsigned char *buf)
Definition: bfile.cpp:191
options.h
Header file for option handlers.
bexit
int bexit(int value)
Exit function for cleanup and debugging.
Definition: utilities.cpp:273
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21