1 // Copyright 2020 Michael Reilly (mreilly@resiliware.com). 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions 5 // are met: 6 // 1. Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // 2. Redistributions in binary form must reproduce the above copyright 9 // notice, this list of conditions and the following disclaimer in the 10 // documentation and/or other materials provided with the distribution. 11 // 3. Neither the names of the copyright holders nor the names of the 12 // contributors may be used to endorse or promote products derived from 13 // this software without specific prior written permission. 14 // 15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 19 // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #ifndef _HEXPEEK_H_ 28 #define _HEXPEEK_H_ 29 30 #define _FILE_OFFSET_BITS 64 31 32 #include <resiliware_util.h> 33 34 #include <stdio.h> 35 #include <stdint.h> 36 #include <stdbool.h> 37 #include <inttypes.h> 38 #include <ctype.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <unistd.h> 42 43 //----------------------------- Build Parameters -----------------------------// 44 45 // WARNING: hexpeek is a trademark. Modified redistributions under the same 46 // name should uncomment HEXPEEK_MODIFIED below. Feel free to add more 47 // information such as "modified by X" or "modified for Y". See the root 48 // project directory README for more information. 49 #define HEXPEEK_PROGRAM_NAME "hexpeek" 50 //#define HEXPEEK_MODIFIED " [modified]" 51 #define HEXPEEK_PROGRAM_VERSION "1.0.20200804" 52 #define HEXPEEK_URL "https://www.hexpeek.com" 53 #define HEXPEEK_EMAIL "hexpeek@hexpeek.com" 54 55 //#define HEXPEEK_BETA Set by Makefile 56 //#define HEXPEEK_EDITABLE_CONSOLE 57 58 #define HEXPEEK_TRACE 59 //#define HEXPEEK_TRACE_EXTENDED 60 #define HEXPEEK_UNIQUE_INFILES 61 //#define HEXPEEK_ALWAYS_FILECPY 62 //#define HEXPEEK_PLUGINS 63 64 //---------------------------- Basic Definitions -----------------------------// 65 66 #define PRGNM HEXPEEK_PROGRAM_NAME 67 #define viwNM "hexview" 68 #define DmpNM "hexDump" 69 #define pckNM "hexpack" 70 #define dffNM "hexdiff" 71 72 #define PAGESZ 0x1000 73 #define BUFSZ 0x10000 74 #define SRCHSZ BUFSZ 75 #define MAXW_LINE BUFSZ 76 #define MAXW_GROUP BUFSZ 77 78 #define DEF_SCALAR_BASE 0x10 79 80 #define MAX_INFILES 2 81 82 #define BACKUP_FILE_COUNT 2 83 84 #define PERM (S_IRUSR | S_IWUSR) 85 86 #define TERMINAL_WIDTH 80 87 88 //------------------------------- Return Codes -------------------------------// 89 90 #define RC_NIL -1 91 #define RC_OK 0 92 #define RC_DIFF 1 93 #define RC_DONE 2 94 #define RC_UNSPEC 3 // any function that returns this has a bug 95 #define RC_USER 4 96 #define RC_CRIT 5 97 98 #define checkrc(r) if((r) != RC_OK) goto end; 99 100 //--------------------------- Numeric Format Modes ---------------------------// 101 102 #define MODE_HEX 0 103 #define MODE_BITS 1 104 #define MODE_COUNT 2 105 106 #define HEX_CHCNT 2 107 #define BITS_CHCNT 8 108 #define MODE_CHCNT(m) ((m) ? BITS_CHCNT : HEX_CHCNT) 109 #define DISP_CHCNT MODE_CHCNT(Params.disp_mode) 110 111 //----------------------------- Command Indices ------------------------------// 112 113 #define CMD_NONE 0 114 #define CMD_QUIT 1 115 #define CMD_STOP 2 116 #define CMD_HELP 3 117 #define CMD_FILES 4 118 #define CMD_RESET 5 119 #define CMD_SETTINGS 6 120 #define CMD_ENDIAN 7 121 #define CMD_HEX 8 122 #define CMD_BITS 9 123 #define CMD_RLEN 10 124 #define CMD_SLEN 11 125 #define CMD_LINE 12 126 #define CMD_COLS 13 127 #define CMD_GROUP 14 128 #define CMD_MARGIN 15 129 #define CMD_SCALAR 16 130 #define CMD_PREFIX 17 131 #define CMD_AUTOSKIP 18 132 #define CMD_DIFFSKIP 19 133 #define CMD_TEXT 20 134 #define CMD_RULER 21 135 #define CMD_NUMERIC 22 136 #define CMD_PRINT 23 137 #define CMD_OFFSET 24 138 #define CMD_SEARCH 25 139 #define CMD_DIFF 26 140 #define CMD_REPLACE 27 141 #define CMD_INSERT 28 142 #define CMD_KILL 29 143 #define CMD_OPS 30 144 #define CMD_UNDO 31 145 #define CMD_MIN CMD_QUIT 146 #define CMD_MAX CMD_UNDO 147 148 //----------------------------- Type Definitions -----------------------------// 149 150 typedef int rc_t; 151 #define TRC_rc "%d" 152 153 typedef off_t hoff_t; 154 155 #define HOFF_NIL -0x2F46 // little endian 2's complement looks like bad0ffff 156 #define HOFF_HEX_FULL_WIDTH 0x10 157 #define HOFF_HEX_DEFAULT_WIDTH HOFF_HEX_FULL_WIDTH 158 159 // Indirection for platforms where printf("%jX") is not recognized 160 #define PRI_hxpkint "X" "%!!hxpknum" 161 #define PRI_hxpkmax PRIXMAX "%!!hxpknum" // @!!X_IN_PRIXMAX 162 163 #define FORMAT_HOFF(n, x) \ 164 ((n) < 0 ? "-" : ""), (x), ((uintmax_t)(((n) < 0) ? -(n) : (n))) 165 #define HoffPrefix (Params.print_prefix ? "0x" : "") 166 #define PRI_hoff "%s%s%" PRI_hxpkmax 167 #define prihoff(n) FORMAT_HOFF(n, HoffPrefix) 168 #define prihcnt(n) FORMAT_HOFF(n, HoffPrefix), ((n) == 1 ? "" : "s") 169 #define TRC_hoff "%s%s%" PRIXMAX 170 #define trchoff(n) FORMAT_HOFF(n, "0x") 171 172 typedef struct 173 { 174 char *path; 175 char *name_mal; 176 int open_flags; 177 int fd; 178 hoff_t at; 179 hoff_t last_at; 180 hoff_t track; 181 bool created; 182 uint64_t opcnt; 183 char *bk_path_mal[BACKUP_FILE_COUNT]; 184 char *bk_name_mal[BACKUP_FILE_COUNT]; 185 int bk_fds[BACKUP_FILE_COUNT]; 186 } FileAttr; 187 188 typedef struct 189 { 190 int scalar_base; 191 int disp_mode; 192 int hexlower; 193 hoff_t mode_print_defs[MODE_COUNT]; 194 hoff_t mode_search_defs[MODE_COUNT]; 195 hoff_t mode_lines[MODE_COUNT]; 196 hoff_t mode_groups[MODE_COUNT]; 197 bool endian_big; 198 int margin; 199 int autoskip; 200 bool diffskip; 201 char const *line_term; 202 char const *group_pre[2]; 203 char const *group_term; 204 int print_text; 205 int text_encoding; 206 bool ruler; 207 bool print_prefix; 208 bool allow_ik; 209 bool infer; 210 bool tolerate_eof; 211 bool assume_unique_infiles; 212 int assume_ttys; 213 bool recover_interactive; 214 bool recover_auto; 215 long backup_depth; 216 bool backup_sync; 217 int fail_strict; 218 int editable_console; 219 char *command; 220 bool do_pack; 221 FileAttr infiles[MAX_INFILES]; 222 FILE *trace_fp; 223 } Settings; 224 225 void Settings_init(Settings *st); 226 227 #define FILE_INDEX_NIL -1 228 #define FILE_INDEX_LATER -2 229 230 typedef struct 231 { 232 int fi; // index to Params.infiles[] 233 hoff_t start; 234 hoff_t len; 235 bool tolerate_eof; 236 } FileZone; 237 238 void FileZone_init(FileZone *zone); 239 240 typedef struct 241 { 242 struct 243 { 244 hoff_t sz; 245 hoff_t count; 246 uint8_t *octets_mal; 247 uint8_t *masks_mal; 248 } mem; 249 FileZone fz; 250 } ConvertedText; 251 252 void ConvertedText_init(ConvertedText *converted_text); 253 254 typedef struct 255 { 256 char const *origcmd; 257 int cmd; 258 int subtype; // only used by shared commands 259 FileZone fz; 260 bool incr_pre; 261 bool incr_post; 262 bool print_off; 263 bool print_verbose; 264 bool diff_srch; 265 char const *arg_t; 266 ConvertedText arg_cv; 267 } ParsedCommand; 268 269 void ParsedCommand_init(ParsedCommand *parsed_command); 270 271 //------------------------------ Constant Data -------------------------------// 272 273 extern char const VersionShort[]; 274 extern char const VersionLong[]; 275 276 extern char const LicenseString[]; 277 extern char const AuthorshipString[]; 278 extern char const UsageStringShort[]; 279 extern char const UsageStringExtended[]; 280 281 extern char const HelpCmdList[]; 282 extern char const HelpCmdHdr[]; 283 extern char const * HelpText[]; 284 extern char const HelpOther[]; 285 286 #define OCTET_COUNT 0x100 287 288 extern char const *BinLookup_hexl[OCTET_COUNT]; 289 290 extern char const *BinLookup_hexu[OCTET_COUNT]; 291 292 extern char const *BinLookup_bits[OCTET_COUNT]; 293 294 #define CODEPAGE_ASCII 1 295 #define CODEPAGE_EBCDIC 2 296 #define CODEPAGE_NIL 3 297 298 char *getEncoded(int codepage, uint8_t *in, size_t len, char *out); 299 300 char const *getEncodedVerbose(int codepage, uint8_t data); 301 302 char const *encodingName(int codepage); 303 304 #define EofErrString "unexpectedly reached end of file while reading from %s\n" 305 306 //----------------- Global Variables and Run-Time Constants ------------------// 307 308 extern hoff_t HOFF_MAX; 309 310 #define MASK_COUNT (sizeof(uintmax_t) * HEX_CHCNT + 1) 311 312 extern uintmax_t Masks[MASK_COUNT]; 313 314 extern uint8_t CharLookup[OCTET_COUNT]; 315 316 extern char *GeneratedCommand_mal; 317 318 extern char *CleanString_mal; 319 320 extern char *LnInput_mal; 321 322 extern size_t LnInputSz; 323 324 extern bool BackupUnlinkAllowed; 325 326 extern Settings Params; 327 328 void initialize(); 329 330 void cleanup(); 331 332 //-------------------------------- Shortcuts ---------------------------------// 333 334 #define DT_PATH(i) Params.infiles[i].path 335 #define DT_NAME(i) Params.infiles[i].name_mal 336 #define DT_MODE(i) Params.infiles[i].open_flags 337 #define DT_FD(i) Params.infiles[i].fd 338 #define DT_AT(i) Params.infiles[i].at 339 #define DT_OPCNT(i) Params.infiles[i].opcnt 340 341 #define BK_PATH(i, j) Params.infiles[i].bk_path_mal[j] 342 #define BK_NAME(i, j) Params.infiles[i].bk_name_mal[j] 343 #define BK_FD(i, j) Params.infiles[i].bk_fds[j] 344 345 #define DispMode Params.disp_mode 346 #define DispPrDef Params.mode_print_defs[Params.disp_mode] 347 #define DispSrchDef Params.mode_search_defs[Params.disp_mode] 348 #define DispLine Params.mode_lines[Params.disp_mode] 349 #define DispGroup Params.mode_groups[Params.disp_mode] 350 #define BackupDepth Params.backup_depth 351 352 //---------------------------- Output Formatting -----------------------------// 353 354 #define LineTerm Params.line_term 355 #define GroupPre(li) ((li) ? Params.group_pre[1] : Params.group_pre[0]) 356 #define GroupTerm Params.group_term 357 358 #define PromptString "> " 359 #define MarginPost ": " 360 #define GroupFmtGroup "%_g" 361 #define GroupFmtLiTern "%_l?" 362 #define DiffSplit "|" 363 #define AutoskipOutput "*" 364 365 //--------------------------------- Tracing ----------------------------------// 366 367 #ifdef HEXPEEK_TRACE 368 #define trace(...) tracef(Params.trace_fp, "" __VA_ARGS__) 369 #define traceEntry(...) tracefEntry(Params.trace_fp, "" __VA_ARGS__) 370 #define traceExit(...) tracefExit(Params.trace_fp, "" __VA_ARGS__) 371 #define closeTrace() trace_close(Params.trace_fp) 372 #else 373 #define trace(...) 374 #define traceEntry(...) 375 #define traceExit(...) 376 #define closeTrace() 377 #endif 378 379 //------------------------------ Miscellaneous -------------------------------// 380 381 void *Malloc(size_t sz); 382 383 bool promptable(); 384 385 bool interactive(); 386 387 size_t slprintf(char *buf, char *lim, char const *format, ...); 388 389 rc_t strtooff(char const *str, char const **endptr, hoff_t *result, int infi); 390 391 rc_t strtosz(char const *str, hoff_t *result); 392 393 void endianize(uint8_t *buf, hoff_t len); 394 395 #define maxOctetWidth(l) ( ((l) / DISP_CHCNT) + (((l) % DISP_CHCNT) ? 1 : 0) ) 396 397 rc_t textToOctetArray(char const *str, int mode, hoff_t *b_sz, 398 uint8_t *buf, uint8_t *masks); 399 400 char *cleanstring(char const *original_path); 401 402 void outputProgress(hoff_t complete, hoff_t total, int isbackup); 403 404 #ifdef HEXPEEK_EDITABLE_CONSOLE 405 #define progress(c, t, i) outputProgress(c, t, i) 406 #else 407 #define progress(c, t, i) 408 #endif 409 410 //------------------------------ Error Handling ------------------------------// 411 412 void terminate(int result); 413 414 void doErr(char const *file, int line, int op, char const *fmt, ...); 415 416 #define PGPRE PRGNM ": " 417 418 #define prerr(...) doErr(SRCNAME, __LINE__, 0, PGPRE __VA_ARGS__) 419 #define malcmd(...) doErr(SRCNAME, __LINE__, 0, PGPRE "malformed command: " __VA_ARGS__) 420 #define malnum(...) doErr(SRCNAME, __LINE__, 0, PGPRE "malformed number: " __VA_ARGS__) 421 422 #define prwarn(...) doErr(SRCNAME, __LINE__, 1, PGPRE "warning: " __VA_ARGS__) 423 424 void doDie(char const *file, int line); 425 426 #define die() doDie(SRCNAME, __LINE__) 427 428 bool doCheck(char const *file, int line, char const *msg, bool exp); 429 430 #define assert(e) doCheck(SRCNAME, __LINE__, (#e), (e)) 431 432 //------------------------------- Console I/O --------------------------------// 433 434 void consoleInit(); 435 436 void consoleClose(); 437 438 char *consoleIn(); 439 440 void console(char const *format, ...); 441 442 void hexpeek_genf(char *out, char const *in); 443 444 void consoleOutf(char const *format, ...); 445 446 void consoleFlush(); 447 448 int consoleAsk(char const *format, ...); 449 450 //--------------------------------- File I/O ---------------------------------// 451 452 char const *fdname(int fd); 453 454 rc_t hexpeek_open(char const *path, int flags, mode_t mode, int *fd); 455 456 hoff_t hexpeek_seek(int descriptor, hoff_t offset, int whence); 457 458 #define SAVE_OFFSET(d, o) \ 459 assert(((o) = hexpeek_seek((d), 0, SEEK_CUR)) != -1); 460 461 #define RESTORE_OFFSET(d, o) \ 462 assert(hexpeek_seek((d), (o), SEEK_SET) == (o)); 463 464 rc_t seekto(int descriptor, hoff_t offset); 465 466 ssize_t readfull(int descriptor, void *buf, size_t count); 467 468 hoff_t hexpeek_read(int descriptor, void *buf, hoff_t count); 469 470 hoff_t hexpeek_write(int descriptor, const void *buf, hoff_t count); 471 472 rc_t hexpeek_stat(int descriptor, struct stat *fileinfo); 473 474 rc_t hexpeek_sync(int descriptor); 475 476 rc_t hexpeek_syncdir(char const *path); 477 478 rc_t hexpeek_truncate(int descriptor, hoff_t len); 479 480 int sameness(int fd0, int fd1); 481 482 bool isseekable(int file_index); 483 484 hoff_t filesize(int file_index); 485 486 hoff_t pathsize(char const *path); 487 488 rc_t readat(int descriptor, hoff_t at, void *buf, hoff_t count); 489 490 rc_t writeat(int descriptor, hoff_t at, const void *buf, hoff_t count); 491 492 rc_t filecpy(int src_fd, hoff_t src_at, hoff_t src_len, 493 int dst_fd, hoff_t dst_at, hoff_t dst_len); 494 495 rc_t lclcpy(int fd, hoff_t src_at, hoff_t dst_at, hoff_t length); 496 497 rc_t adjustSize(int data_fi, hoff_t pos, hoff_t amt, int backup_fd); 498 499 //------------------------------- Backup File --------------------------------// 500 501 #define BACKUP_EXT PRGNM "-backup" 502 503 #define MAX_BACKUP_DEPTH 0x20 504 #define DEFAULT_BACKUP_DEPTH 8 505 506 int backupFd(int data_fi); 507 508 rc_t makeBackup(ParsedCommand const *ppc); 509 510 rc_t makeAdjBackup(int data_fi, int backup_fd, hoff_t sv_from); 511 512 rc_t clearAdjBackup(int backup_fd, void *vp); 513 514 rc_t recoverBackup(int data_fi, int what); 515 516 //--------------------------- Settings Processing ----------------------------// 517 518 hoff_t outputWidth(int part, int formode, hoff_t linewh); 519 520 int ascertainShared(char const *str, int *subtype, char const **post); 521 522 rc_t processShared(int cmd, int subtype, char const *arg, int formode); 523 524 rc_t parseArgv(int argc, char **argv); 525 526 //------------------------------- Test Plugins -------------------------------// 527 528 #ifdef HEXPEEK_PLUGINS 529 rc_t plugin_argv(int argc, char **argv, int *which); 530 void* plugin(int type, void *vp); 531 #else 532 #define plugin_argv(a, v, w) RC_NIL 533 #define plugin(t, v) 534 #endif 535 536 #endif 537