I'm writing a program to read a specified piece of data from one file and write it into a specified offset of a second file, but I have a problem. The fwrite
function for some reason isn't writing the data read from the first file. Instead, it writes a non-printing character (possibly null character, idk) at the offset of the second file. Here's the code:
int main(int argc, char **args)
{
if (argc < 7)
{
print_usage(args[0]);
exit(EXIT_FAILURE);
}
else if (argc > 7)
{
printf("Too many parameters\n");
exit(EXIT_FAILURE);
}
if (geteuid() != 0)
{
printf("This program requires root privileges\n");
exit(EXIT_FAILURE);
}
unsigned long offset;
unsigned long size;
char *partpath;
char *filepath;
int c;
for (c = 0; c < argc; c )
{
char *arg = args[c];
if (strcmp(arg, "-o") == 0)
{
offset = strtoul(args[ c], NULL, 0);
continue;
}
if (strcmp(arg, "-s") == 0)
{
size = strtoul(args[ c], NULL, 0);
continue;
}
if (c == argc - 2)
partpath = args[c];
if (c == argc - 1)
filepath = args[c];
}
printf("offset: %lu (0x%lx)\nsize: %lu (0x%lx)\npartition: %s\nfile: %s\n", offset, offset, size, size, partpath, filepath);
flash_part(partpath, offset, filepath, size);
return 0;
}
void flash_part(const char *partition_path, unsigned long offset, const char *file_to_flash, unsigned long size)
{
log("Opening files...");
FILE *partition = fopen(partition_path, "r ");
FILE *flash_file = fopen(file_to_flash, "r");
log("Jumping to partition offset...");
// jump to partition offset
fseek(partition, offset, SEEK_SET);
// start flashing chunk by chunk
log("Start flashing...");
void *chk = calloc(1, sizeof(void*));
size_t count = read_chk(flash_file, chk);
printf("readed %d bytes\n", count);
write_chk(partition, chk, count);
free(chk);
while (count >= CHK_SIZE)
{
chk = calloc(1, sizeof(void*));
count = read_chk(flash_file, chk);
write_chk(partition, chk, count);
free(chk);
}
log("Partition flashed, closing files...");
fclose(partition);
fclose(flash_file);
}
size_t read_chk(FILE *file, void *out)
{
char *chk_data = calloc(CHK_SIZE, 1);
size_t readed = fread(chk_data, 1, CHK_SIZE, file);
out = chk_data;
return readed;
}
void write_chk(FILE *file, void *data, unsigned int size)
{
fwrite(data, 1, size, file);
}
What's wrong with it?
CodePudding user response:
Your read_chk
is completely broken. You accept a pointer from the user, ignore it, allocate a completely different thing, populate that, replace the pointer received (rather than copying data to where it points; assigning to a pointer changes that pointer, and not the copy of the same pointer the caller holds), so from the point of view of the caller, nothing happened; it passed a pointer to a zeroed buffer, you didn't put anything in the buffer, so it's still got the original zeroes (the "caller" might notice eventually when the program crashes from the progressive memory leak from read_chk
's calloc
calls that are never free
d, but that's not useful feedback really).
Essentially, nothing is wrong with your writing, it's accurately writing out all the zeroes you told it to write.
The solution depends on the value of CHK_SIZE
; if it's the same as sizeof(void*)
, then just get rid of chk_data
and directly pass out
to fread
in its place. If it's larger, you do the same thing, but change the caller to calloc
using CHK_SIZE
instead of sizeof(void*)
. Either way, read_chk
changes to look like:
size_t read_chk(FILE *file, void *out)
{
return fread(out, 1, CHK_SIZE, file);
}
leaving it to the caller to provide a CHK_SIZE
buffer to use. The caller could skip the calloc
entirely too; a stack array of char buf[CHK_SIZE];
could be used and remove the need for dynamic allocation and freeing.