mirror of
https://github.com/adulau/dcfldd.git
synced 2024-12-22 16:56:03 +00:00
207 lines
7.8 KiB
C
207 lines
7.8 KiB
C
/* $Id: translate.c,v 1.4 2005/05/15 20:15:28 harbourn Exp $
|
|
* dcfldd - The Enhanced Forensic DD
|
|
* By Nicholas Harbour
|
|
*/
|
|
|
|
/* Copyright (C) 85, 90, 91, 1995-2001, 2005 Free Software Foundation, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software Foundation,
|
|
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|
|
|
/* GNU dd originally written by Paul Rubin, David MacKenzie, and Stuart Kemp. */
|
|
|
|
#include "dcfldd.h"
|
|
#include "log.h"
|
|
|
|
/* Output representation of newline and space characters.
|
|
They change if we're converting to EBCDIC. */
|
|
unsigned char newline_character = '\n';
|
|
unsigned char space_character = ' ';
|
|
|
|
/* Translation table formed by applying successive transformations. */
|
|
unsigned char trans_table[256];
|
|
|
|
unsigned char const ascii_to_ebcdic[] =
|
|
{
|
|
0, 01, 02, 03, 067, 055, 056, 057,
|
|
026, 05, 045, 013, 014, 015, 016, 017,
|
|
020, 021, 022, 023, 074, 075, 062, 046,
|
|
030, 031, 077, 047, 034, 035, 036, 037,
|
|
0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175,
|
|
0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
|
|
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
|
|
0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
|
|
0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
|
|
0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
|
|
0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
|
|
0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155,
|
|
0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
|
|
0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
|
|
0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
|
|
0247, 0250, 0251, 0300, 0152, 0320, 0241, 07,
|
|
040, 041, 042, 043, 044, 025, 06, 027,
|
|
050, 051, 052, 053, 054, 011, 012, 033,
|
|
060, 061, 032, 063, 064, 065, 066, 010,
|
|
070, 071, 072, 073, 04, 024, 076, 0341,
|
|
0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
|
|
0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
|
|
0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
|
|
0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
|
|
0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
|
|
0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
|
|
0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
|
|
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
|
|
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
|
|
0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
|
|
0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
|
|
0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377
|
|
};
|
|
|
|
unsigned char const ascii_to_ibm[] =
|
|
{
|
|
0, 01, 02, 03, 067, 055, 056, 057,
|
|
026, 05, 045, 013, 014, 015, 016, 017,
|
|
020, 021, 022, 023, 074, 075, 062, 046,
|
|
030, 031, 077, 047, 034, 035, 036, 037,
|
|
0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175,
|
|
0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
|
|
0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
|
|
0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
|
|
0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
|
|
0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
|
|
0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
|
|
0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155,
|
|
0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
|
|
0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
|
|
0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
|
|
0247, 0250, 0251, 0300, 0117, 0320, 0241, 07,
|
|
040, 041, 042, 043, 044, 025, 06, 027,
|
|
050, 051, 052, 053, 054, 011, 012, 033,
|
|
060, 061, 032, 063, 064, 065, 066, 010,
|
|
070, 071, 072, 073, 04, 024, 076, 0341,
|
|
0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
|
|
0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
|
|
0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
|
|
0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
|
|
0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
|
|
0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
|
|
0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
|
|
0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
|
|
0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
|
|
0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
|
|
0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
|
|
0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377
|
|
};
|
|
|
|
unsigned char const ebcdic_to_ascii[] =
|
|
{
|
|
0, 01, 02, 03, 0234, 011, 0206, 0177,
|
|
0227, 0215, 0216, 013, 014, 015, 016, 017,
|
|
020, 021, 022, 023, 0235, 0205, 010, 0207,
|
|
030, 031, 0222, 0217, 034, 035, 036, 037,
|
|
0200, 0201, 0202, 0203, 0204, 012, 027, 033,
|
|
0210, 0211, 0212, 0213, 0214, 05, 06, 07,
|
|
0220, 0221, 026, 0223, 0224, 0225, 0226, 04,
|
|
0230, 0231, 0232, 0233, 024, 025, 0236, 032,
|
|
040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
|
|
0247, 0250, 0133, 056, 074, 050, 053, 041,
|
|
046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
|
|
0260, 0261, 0135, 044, 052, 051, 073, 0136,
|
|
055, 057, 0262, 0263, 0264, 0265, 0266, 0267,
|
|
0270, 0271, 0174, 054, 045, 0137, 076, 077,
|
|
0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
|
|
0302, 0140, 072, 043, 0100, 047, 075, 042,
|
|
0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
|
|
0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
|
|
0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
|
|
0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320,
|
|
0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170,
|
|
0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327,
|
|
0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
|
|
0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
|
|
0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
|
|
0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
|
|
0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
|
|
0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
|
|
0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
|
|
0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
|
|
060, 061, 062, 063, 064, 065, 066, 067,
|
|
070, 071, 0372, 0373, 0374, 0375, 0376, 0377
|
|
};
|
|
|
|
|
|
static void translate_charset(const unsigned char *new_trans)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
trans_table[i] = new_trans[trans_table[i]];
|
|
translation_needed = 1;
|
|
}
|
|
|
|
/* Fix up translation table. */
|
|
|
|
void apply_translations(void)
|
|
{
|
|
unsigned int i;
|
|
|
|
#define MX(a) (bit_count (conversions_mask & (a)))
|
|
if ((MX (C_ASCII | C_EBCDIC | C_IBM) > 1)
|
|
|| (MX (C_BLOCK | C_UNBLOCK) > 1)
|
|
|| (MX (C_LCASE | C_UCASE) > 1)
|
|
|| (MX (C_UNBLOCK | C_SYNC) > 1))
|
|
{
|
|
log_info("\
|
|
only one conv in {ascii,ebcdic,ibm}, {lcase,ucase}, {block,unblock}, {unblock,sync}");
|
|
}
|
|
#undef MX
|
|
|
|
if (conversions_mask & C_ASCII)
|
|
translate_charset(ebcdic_to_ascii);
|
|
|
|
if (conversions_mask & C_UCASE) {
|
|
for (i = 0; i < 256; i++)
|
|
if (ISLOWER(trans_table[i]))
|
|
trans_table[i] = TOUPPER(trans_table[i]);
|
|
translation_needed = 1;
|
|
} else if (conversions_mask & C_LCASE) {
|
|
for (i = 0; i < 256; i++)
|
|
if (ISUPPER(trans_table[i]))
|
|
trans_table[i] = TOLOWER(trans_table[i]);
|
|
translation_needed = 1;
|
|
}
|
|
|
|
if (conversions_mask & C_EBCDIC) {
|
|
translate_charset (ascii_to_ebcdic);
|
|
newline_character = ascii_to_ebcdic['\n'];
|
|
space_character = ascii_to_ebcdic[' '];
|
|
} else if (conversions_mask & C_IBM) {
|
|
translate_charset (ascii_to_ibm);
|
|
newline_character = ascii_to_ibm['\n'];
|
|
space_character = ascii_to_ibm[' '];
|
|
}
|
|
}
|
|
|
|
/* Apply the character-set translations specified by the user
|
|
to the NREAD bytes in BUF. */
|
|
|
|
void translate_buffer(unsigned char *buf, size_t nread)
|
|
{
|
|
unsigned char *cp;
|
|
size_t i;
|
|
|
|
for (i = nread, cp = buf; i; i--, cp++)
|
|
*cp = trans_table[*cp];
|
|
}
|
|
|