How to reverse the byte shifts after I have extracted a value in C?

76 views Asked by At
void check_drop(char *drop_pathname) {
    FILE *fp;
    fp = fopen(drop_pathname, "rb");
    int count = 0, pathname_length = 0, c;
    uint8_t drop_hash = 0, current_hash = 0;

    while ((c = fgetc(fp)) != EOF) {
        drop_hash = droplet_hash(current_hash, c);
        printf("\ndroplet_hash(0x%02x, 0x%02x) = 0x%02x", current_hash, c, drop_hash);
        current_hash = drop_hash;

        if (count == 12) {
            unsigned int small_hex_val = 0;
            small_hex_val |= (c & 0xFF); // Add the lower byte
            small_hex_val |= ((fgetc(fp) & 0xFF) << 8); // Add the higher byte, taking into account little-endianness
            pathname_length = (int)small_hex_val; // Convert to decimal
        }
        count++;    
    }
    fclose(fp); 
}

Ok, this is a function that checks a file that is filled with hexadecimal values. It's supposed to go through the file that I input in and scan the file in a specific pattern until it reaches the hash of the file and restart the scan. Whenever the 12th byte is reached, there is a 2 byte unsigned, 16-bit, little-endian value, which in this case is 01 00. I am able to extract that value in that if statement above and convert that to an integer value of 1 which is correct. But when I do that through shifting the bytes, it messes up the hexadecimal values in the file fp.Is there anyway that I can extract the pathname_length without affected the bytes in file fp? I tried shifting the bytes but I am not exactly sure how to revert the shifts I have done. The printf statement provides this output:

droplet_hash(0x00, 0x63) = 0x63
droplet_hash(0x63, 0x38) = 0xfb
droplet_hash(0xfb, 0x2d) = 0x76
droplet_hash(0x76, 0x72) = 0x44
droplet_hash(0x44, 0x77) = 0xb3
droplet_hash(0xb3, 0x2d) = 0x3e
droplet_hash(0x3e, 0x72) = 0x8c
droplet_hash(0x8c, 0x2d) = 0x21
droplet_hash(0x21, 0x2d) = 0x6c
droplet_hash(0x6c, 0x72) = 0x9e
droplet_hash(0x9e, 0x2d) = 0x73
droplet_hash(0x73, 0x2d) = 0xfe
droplet_hash(0xfe, 0x01) = 0xbf -- after this line it messes up. 
droplet_hash(0xbf, 0x61) = 0xfe
droplet_hash(0xfe, 0x01) = 0xbf
droplet_hash(0xbf, 0x00) = 0x9f
droplet_hash(0x9f, 0x00) = 0x7f
droplet_hash(0x7f, 0x00) = 0x5f
droplet_hash(0x5f, 0x00) = 0x3f
droplet_hash(0x3f, 0x00) = 0x1f
droplet_hash(0x1f, 0x0a) = 0xf5
droplet_hash(0xf5, 0x15) = 0x80

This is the correct output:
droplet_hash(0x00, 0x63) = 0x63
droplet_hash(0x63, 0x38) = 0xfb
droplet_hash(0xfb, 0x2d) = 0x76
droplet_hash(0x76, 0x72) = 0x44
droplet_hash(0x44, 0x77) = 0xb3
droplet_hash(0xb3, 0x2d) = 0x3e
droplet_hash(0x3e, 0x72) = 0x8c
droplet_hash(0x8c, 0x2d) = 0x21
droplet_hash(0x21, 0x2d) = 0x6c
droplet_hash(0x6c, 0x72) = 0x9e
droplet_hash(0x9e, 0x2d) = 0x73
droplet_hash(0x73, 0x2d) = 0xfe
droplet_hash(0xfe, 0x01) = 0xbf
droplet_hash(0xbf, 0x00) = 0x9f
droplet_hash(0x9f, 0x61) = 0x1e
droplet_hash(0x1e, 0x01) = 0xdf
droplet_hash(0xdf, 0x00) = 0xbf
droplet_hash(0xbf, 0x00) = 0x9f
droplet_hash(0x9f, 0x00) = 0x7f
droplet_hash(0x7f, 0x00) = 0x5f
droplet_hash(0x5f, 0x00) = 0x3f
droplet_hash(0x3f, 0x0a) = 0x15
1

There are 1 answers

1
Support Ukraine On

The output will differ when you run the code with and without the if block. It's not due to any of the bit shifting. It's because you read a character using fgetc inside the if block and consequently never calls droplet_hash with that character.

There are many ways to solve that. You can put a call of the function (and a print out) inside the if block. Or you can put that character back using ungetc. Or you can calculate pathname_length using two if blocks.

Another problem with your current code is that you don't check for EOF inside the if block. By using two if statements, you can solve that.

Something like the pseudo code below:

while ((c = fgetc(fp)) != EOF) {
    .. call function and print ...

    if (count == 12) {
        ... use current c to calculate first part of pathname_length ...
    } else if (count == 13) {
        ... use current c to calculate final pathname_length ...
    }

    count++;    
}