Write bitstream to file in C

432 views Asked by At

I'm currently trying to use a CMP decompressor: https://web.archive.org/web/20070113004119/http://rewiki.regengedanken.de:80/wiki/.CMP

It does in fact decompress the cmp, but it does not write it into a file. So i tried myself.

int main(int argc, char** argv)
{
    int length, dstLength;
    unsigned char* fileInMem; //compressed data
    unsigned char* dstFile; //decompressed data

    if (argc < 2) {
        fprintf(stderr, "give filename.cmp as parameter\n");
        return 1;
    }

    printf("%s", argv[1]);

    fileInMem = loadFile(argv[1], &length); //compressed data read
    if (fileInMem == NULL) {
        return 1;
    }

    dstFile = parseCmp(fileInMem, length, &dstLength); //decompress and assign data to dstFile
    if (dstFile) {
        /* Now we can save the file from dstFile, dstLength bytes */
        printf("%d bytes depacked\n", dstLength);

        for (int i = 0; i < 16; i++) {
            dataArray[i] = fileInMem[i];
        }

            FILE *writer = fopen(argv[2], "r+");
            //fputs(fileInMem, writer);
            //fputs(dstFile, writer);
         
            fclose(writer);
        free(dstFile);
    }

    free(fileInMem);

    return 0;
}

As you can see the decompressed data is a pointer to an unsigned char (according to the website a bitstream) and I tried fputs() from stdio.h, but the resulting file contains only 4 Bytes when viewed in a hex-editor.

If you need more information, please comment.

Thank you in advance.

Edit: This is what I was able to change thanks to your help, but when I open the file, it is still empty:

FILE* writer = fopen(argv[2], "wb");
fwrite(dstFile, 192, 192, writer);

192, because the length of the first decompressed Image is 192 Bytes large.

1

There are 1 answers

8
Miguel Sandoval On

This is a common issue.

First, you need to open the output file writer for writing in binary mode ("wb").

FILE *writer = fopen(argv[2], "wb");

Second, you can't use fputs to write arbitrary data to a file, since it expects a string. Use fwrite instead: (assuming writer is the output file, dstFile the decompressed data and dstLength the amount of bytes to write)

fwrite(dstFile, 1, dstLength, writer);

If you examine the resulting file with an hex editor, you will see it is identical to the decompressed data.

Test-update

I wrote some test-code to see what is wrong, share your results so we can help you.

Add these functions to your code:

void printDataToScreen(unsigned char *dataptr, int datalen)
{
    if (dataptr == NULL)
    {
        printf("[!] ERROR, NULL POINTER PROVIDED!\n");
        return;
    }
    printf("> Dumping %d bytes of data into the terminal...\n", datalen);
    for (int i = 0; i < datalen; i++)
    {
        if (i % 16 == 0)
            printf("\n   ");
        printf("%02X ", dataptr[i]);
    }
    printf("\n\n");
}

void writeDataToFile(char *fileName, unsigned char *dataptr, int datalen)
{
    FILE *file = fopen(fileName, "wb");
    if (dataptr == NULL)
    {
        printf("[!] ERROR, NULL POINTER PROVIDED!\n");
        return;
    } else if (file == NULL)
    {
        printf("[!] ERROR WHILE OPENING FILE '%s'!\n", fileName);
        return;
    }
    
    printf("> Writting %d bytes of data to '%s'...\n", datalen, fileName);
    int writtenBytes = fwrite(dataptr, 1, datalen, file);
    printf("   Done, %d bytes written!\n\n", writtenBytes);
    
    fclose(file);
}

void runTest(char *fileName, unsigned char *dataptr, int datalen)
{
    printf("Running tests... [0/2 done]\n");
    printDataToScreen(dataptr, datalen);
    printf("Running tests... [1/2 done]\n");
    writeDataToFile(fileName, dataptr, datalen);
    printf("Finished! [2/2 done]\n");
}

Call it like this:

runTest(argv[2], dstFile, dstLength);

Add the call to this place in your code (comment this code, also the line where you close writer):

FILE *writer = fopen(argv[2], "r+");
//fputs(fileInMem, writer);
//fputs(dstFile, writer);

Please share your results.