难道一个简单的C程序模仿默认“XXD”命令,使得其输出diff'd将返回0?

问题描述 投票:0回答:1

我试图写一个C的可执行文件,会产生相同的输出到一个默认xxd命令。例如,可以说我有一个名为test.txt一个相当小的文本文件,可执行文件名为myxxd

所以,我首先用做比较的基准:

$ touch correct-xxdoutput.txt test-output.txt
$ xxd test.txt > correct-xxdoutput.txt

然后用我的可执行文件进行同样的操作,但以不同的输出文件:

$ ./myxxd test.txt > test-output.txt
$ diff correct-xxdoutput.txt test-output.txt
$

我有很接近的一些猜测,但我的格式永远是错不知何故,我真的不明白xxd具体是如何产生hexDumps。感觉就像我刚接手一个完全错误的做法在这里,但也许任务只是我的潜力,我目前的Ç知识水平。

我的代码(参见:https://pastebin.com/Vjkm8Wb4):

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define SIZE 256

//Prototypes
void hexDump(void*, int);

int main(int argc, char *argv[])
{
    //Create and open filestream
    FILE *myfile;
    myfile =fopen(argv[1],"rb");

    for ( ; ; )
    {
        unsigned char buffer[SIZE];
        size_t n = fread(buffer, 1, SIZE, myfile);

        if (n > 0)
            hexDump(buffer, n);
        if (n < SIZE)
            break;
    }

    fclose(myfile);
    return 0;
}


void hexDump (void *addr, int len)
{
    int i;
    unsigned char bufferLine[17];
    unsigned char *pc = (unsigned char*)addr;

    for (i = 0; i < len; i++)
    {
        if ((i % 16) == 0)
        {
            if (i != 0)
                printf (" %s\n", bufferLine);

            if (pc[i] == 0x00) exit(0);
            printf ("%08x: ", i);
        }

        // Prints Hexcdoes that represent each chars.
        printf ("%02x", pc[i]);
        if ((i % 2) == 1)
            printf (" ");

        if ((pc[i] < 0x20) || (pc[i] > 0x7e))
        {
            bufferLine[i % 16] = '.';
        }

        else
        {
           bufferLine[i % 16] = pc[i];
        }    

        bufferLine[(i % 16) + 1] = '\0'; //Clears the next array buffLine
    }

    while ((i % 16) != 0)
    {
        printf ("  ");
        i++;
    }

    printf ("     %s\n", bufferLine);
}
c hex diff hexdump xxd
1个回答
2
投票

有伴的你的代码,其中包括多个问题:

  • 你不检查你有一个文件名打开。
  • 你不检查你打开那个被命名的文件。
  • 你没有一个机制来处理的偏移量输出,所以在第一个块之后的行开始时的地址是错的。
  • 对于一个零字节代码测试和退出默默地当它遇到一个。这是坏的 - 的两倍。一旦因为,是为了处理二进制数据必须处理零个字节以及从值1..255的程序;而一旦因为默默退出(和声称与exit(0)启动成功)是坏的。你应该有一个错误状态报告的问题(在标准错误,而不是标准输出)和出口 - 一个非零状态。

核心格式似乎主要OK;存在与填充数据的在该文件的末尾的短路线,也有问题。

我想出了这个代码,这是密切基于你的(但重新格式化,以适应至少我的一些风格偏见 - 但我的风格是不是远离你的大部分时间删除):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 256

void hexDump(size_t, void *, int);

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s file\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    FILE *myfile = fopen(argv[1], "rb");
    if (myfile == 0)
    {
        fprintf(stderr, "%s: failed to open file '%s' for reading\n", argv[0], argv[1]);
        exit(EXIT_FAILURE);
    }

    unsigned char buffer[SIZE];
    size_t n;
    size_t offset = 0;
    while ((n = fread(buffer, 1, SIZE, myfile)) > 0)
    {
        hexDump(offset, buffer, n);
        if (n < SIZE)
            break;
        offset += n;
    }

    fclose(myfile);
    return 0;
}

void hexDump(size_t offset, void *addr, int len)
{
    int i;
    unsigned char bufferLine[17];
    unsigned char *pc = (unsigned char *)addr;

    for (i = 0; i < len; i++)
    {
        if ((i % 16) == 0)
        {
            if (i != 0)
                printf(" %s\n", bufferLine);
            // Bogus test for zero bytes!
            //if (pc[i] == 0x00)
            //    exit(0);
            printf("%08zx: ", offset);
            offset += (i % 16 == 0) ? 16 : i % 16;
        }

        printf("%02x", pc[i]);
        if ((i % 2) == 1)
            printf(" ");

        if ((pc[i] < 0x20) || (pc[i] > 0x7e))
        {
            bufferLine[i % 16] = '.';
        }
        else
        {
            bufferLine[i % 16] = pc[i];
        }

        bufferLine[(i % 16) + 1] = '\0';
    }

    while ((i % 16) != 0)
    {
        printf("  ");
        if (i % 2 == 1)
            putchar(' ');
        i++;
    }
    printf(" %s\n", bufferLine);

}

当你的原来的源代码运行,并从系统xxd输出相比,有没有差异。我还只有16个字符(abcdefghijklmno加上一个换行符)检查的话对一个文件;输出是一样的也有。我查它自己的二进制 - 发现和固定的零字节和未宣布提前退出的问题。

© www.soinside.com 2019 - 2024. All rights reserved.