-3
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
Kenny
  • 1
  • 1
  • It would be easier to help you if you supplied a [mre]. Either supply input file (you can use xxd to get a hex dump) or use `memfd_create()` to create a file handle with the data. There is not 12 lines before hitting the `if` statement; body of your if statement has a `getc()` but you don't increment count which looks suspicious. – Allan Wind Apr 24 '23 at 05:16
  • 1
    What do you mean by "messes up the hexadecimal values in the file"? You can use `ungetc()` to put the extra byte that you read back into the stream, so the next iteration will read it. – Barmar Apr 24 '23 at 05:18
  • I think when you get to byte 12 you should read the length instead of processing it as a hash. You're treating it as a hash and also as the length. – Barmar Apr 24 '23 at 05:19
  • Note that [`while (EOF)` is most often wrong](https://stackoverflow.com/q/5605125/1270789). – Ken Y-N Apr 24 '23 at 05:28
  • @SupportUkraine somehow when i remove the code inside of the if(statement) i get the correct output. But i need that code because I want to extract the final byte of the file – Kenny Apr 24 '23 at 05:34
  • @Barmar I really want to find another way of reading the 12th and 13th hexadecimal value which is a little-endian number normally 0 n 0 0 (n ranges from (0-9)) and converting it into decimal. But without reversing the bytes I don't really know how to. – Kenny Apr 24 '23 at 05:36
  • @SupportUkraine, Sorry i jst noticed i copied the older output. This is the output as of now. – Kenny Apr 24 '23 at 05:40
  • @SupportUkraine my bad poor formatting ;( – Kenny Apr 24 '23 at 05:44
  • Just use the character that you've already read when the count is 12 or 13. `if (count == 12) {pathname_length = c & 0xff;} else if (count == 13) {pathname_length += (c & 0xff) << 8;}` – user3386109 Apr 24 '23 at 05:44
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Apr 24 '23 at 08:20

1 Answers1

1

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++;    
}
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63