FrankTominc
FrankTominc

Reputation: 119

Getting garbage when trying to write to binary file

I'm struggling with binary files. I have the following class:

class __attribute__((__packed__)) FileEntry {

    unsigned char filename[8];
    unsigned char extension[3];
    unsigned char type;
    unsigned char reserved;
    unsigned char tenths_of_second;
    unsigned short creation_time;
    unsigned short creation_date;
    unsigned short last_accessed;
    unsigned short high_first_cluster;
    unsigned short last_modification_time;
    unsigned short last_modification_date;
    unsigned short low_first_cluster;
    unsigned int size;
};

I also have the following method, which is the one who is giving me the problem:

void Fat16FileSystem::writeToFS() {
    BootSector b(512,128,1,1,2048,0,0xf8,128,32,64,2048,4194304);
    FATTable f(b.total_sectors);
    FileEntry fe;
    char n = 0;
    memset(&fe, 0, sizeof(fe));
    //memset(&fi, 0, 512);
    b.WriteToFS(file);
    cout << "Writing the fillers" << endl;
    for (int j = 0; j < (b.bytes_per_sector - 512)/512; j++) {
        fwrite(&n, 1, 512, file);

    }
    cout << (b.bytes_per_sector - 512)/512 << " fillers was written" << endl;

    f.writeToFs(file);

    cout << "Writing " << b.directory_entries << " directory entries to FS" << endl;

    for (int i = 0; i < b.directory_entries; i++) {
        fwrite(&fe, sizeof(fe), 1, file);
    }
    fflush(file);

    cout << "Writing " << b.large_total_sectors << " fillers to FS";

    for (long k = 0; k < b.large_total_sectors; k++) {
        fwrite(&n, 1, 512, file);

    }

}

It seems to be working until the part where it writes the directory entries, after that it seems to rewrite the beggining of it. Using a Hex editor I could see that the characters it write matches with the bootsector part. Can someone explain why??

Upvotes: 0

Views: 778

Answers (2)

zdf
zdf

Reputation: 4818

A construct like: fwrite(&n, 1, 512, file); is error prone. To avoid errors, you should infer the size of item and number of items, from buffer:

// ...
FILE* f = 0;
char n[512];
// ...
fwrite( n, sizeof n[0], sizeof n / sizeof n[0], f );
// ...

If you change the type of n or its size, you still write what you're expecting; that is the content of buffer n (a name I wouldn't use for a buffer).

Regarding your comment below, "Isn't fwrite( what to write, size of what, how many times you want to write it, where to write)?". You misunderstood the meaning of 3rd parameter. From MSDN: The fwrite function writes up to count items, of size length each, from buffer to the output stream. In other words, the length of buffer, in bytes, must be parameter2 * parameter3, at most. Your buffer is 1 byte (char n), but you write 512 bytes. Since you ask fwrite to go beyond the size of your buffer, this is, probably, the origin of garbage.

Upvotes: 1

user207421
user207421

Reputation: 311050

for (int j = 0; j < (b.bytes_per_sector - 512)/512; j++) {
    fwrite(&n, 1, 512, file);
}

Undefined behaviour here. You are reading 512 bytes starting at the address of n, which is only a char. You're reading 511 bytes of junk at best: at worst, anything can happen, including nothing.

Are you sure (b.bytes_per_sector - 512)/512 is correct? It looks strange.

You're also ignoring the return value of fwrite().

for (int i = 0; i < b.directory_entries; i++) {
    fwrite(&fe, sizeof(fe), 1, file);
}

Poor practice here. You should use 1 as the second parameter and a byte count as the third parameter. Otherwise you can't be told about partial writes. This is a design flaw in fwrite() and fread().

for (long k = 0; k < b.large_total_sectors; k++) {
    fwrite(&n, 1, 512, file);
}

See above re writing 512 bytes from &n.

}

Upvotes: 0

Related Questions