0

All I want to do is write one long int to offset 0x18 and another separate long int to offset 0x1C into a file I've opened. These offsets always contain the relevant data for the file format I'm processing, so there's no need to worry about that--all I need to do is make the value at these addresses equal to some specified number. I have no problem opening the file, but I'm not sure how to accomplish this since I'm not very experienced with C.

Right now I'm opening the file in write mode with fopen(), seeking to 0x18 with fseek, writing "XXXXX" with fputs (XXXXX is just some number), seeking again to 0x1C, doing the same thing again, and closing the file. Not only do I feel like this approach is mistaken, it also does nothing and I have no idea why. Am I right and I should be going about this some other way, or am I just missing something?

EDIT: Code:

void modify_data(unsigned long int samp1, unsigned long int samp2, char fname[]) {
FILE * newfile;
newfile = fopen(fname, "w");
fseek(newfile, 0x18, SEEK_SET);
fputs("180000", newfile); // 180000 is a placeholder while I test
fseek(newfile, 0x1C, SEEK_SET);
fputs("600000", newfile); // 600000 is a placeholder while I test
fclose(newfile);
}

int main(int argc, char * argv[]) {
char fname[sizeof(argv[1])];
strcpy(fname, argv[1]);
modify_data(0, 0, fname); // the first two arguments are placeholders while I test
return 0;
}
Kurausukun
  • 91
  • 9
  • 2
    The lack of *any* code showing what you're *really* doing doesn't help your question whatsoever. Provide a [minimal, **complete**, and verifiable example](https://stackoverflow.com/help/mcve) of what you have, and what you've done so far to narrow down the problem. – WhozCraig Sep 28 '16 at 06:35
  • What makes you think that this approach is mistaken ? – Jabberwocky Sep 28 '16 at 06:38
  • 1
    BTW: `fputs` is not the function you need here. You must use the `fwrite` function. – Jabberwocky Sep 28 '16 at 06:39
  • On my machine, the data at 0x18 will overlap with the data at 0x1C for machine type `long`. You must be using a 32-bit system. However, `fseek()` and `fwrite()` are the functions you need. – Jonathan Leffler Sep 28 '16 at 06:39
  • No, I'm using a 64-bit system. I might be mistaken, but I thought long ints were 32 bits and long long ints were 64; I could very well be mistaken, though. – Kurausukun Sep 28 '16 at 06:41
  • @WhozCraig, I'll paste my code in just a second, sorry. – Kurausukun Sep 28 '16 at 06:41
  • You could be using a 64-bit Windows system; they use 32-bit `long`. Unix-based 64-bit systems all use 64-bit `long` (as well as 64-bit `long long`) — the difference between LP64 and LLP64 (look it up, along with ILP32 for 32-bit systems). Note, if you're on Windows, you need to add `b` to the mode string for `fopen()` for reliability, and you would not be using `"w"` (or `"wb"`) because those clobber the file contents. You need `"r+b"`! – Jonathan Leffler Sep 28 '16 at 06:57
  • `char fname[sizeof(argv[1])];` is wrong, `sizeof(argv[1])`is not what you think it is. If you want to get the length of the `argv[1]` string, you need the use the `strlen` function. And you need to allocate one more char for the terminating NUL character. So you should write `strlen(argv[1]) + 1` instead of `sizeof(argv[1])`. But actually there is not need to copy the filename. You can just pass `argv[1]` to the `modify_data` function. – Jabberwocky Sep 28 '16 at 07:02
  • use intN_t and uintN_t for that. if you use any other type, the size will be different at some platform. – 12431234123412341234123 Sep 28 '16 at 08:13
  • you should also check for errors in fseek(), fopen() and and fwrite(). generel, check every possible error, only of you sure you cant do anything about it, only then ignore it. – 12431234123412341234123 Sep 28 '16 at 08:16

2 Answers2

2

Non error checking non tested code fragment:

long value1 = 18000;
long value2 = 60000;

FILE *fp = fopen("thefile", "r+");  // or "r+b" on Windows
fseek(fp, 0x18, SEEK_SET);
fwrite(&value1, sizeof long, 1, fp);
fseek(fp, 0x1c SEEK_SET);
fwrite(&value2, sizeof long, 1, fp);

If the size of long is not 32 bits on your platform, you need to subsitute long with an appropriate 32 bit type, most likely int.

Your solution with fputs wont work.

fputs("180000", newfile);

writes the string "180000" to the file and not the 32 bit value 18000.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • Yeah, that's what I thought, but the documentation for fwrite said they were for binary files, which I may have misinterpreted. I'll give this a go. Can you explain why I have to use the & operator? Would just saying value1 not write value1? – Kurausukun Sep 28 '16 at 06:46
  • So is your file a binary file or not, maybe you should show that file, or at least the beginning of that file. `fwrite` wants a memory address therefore you need the & operator, read the fwrite man page. The string "18000" and the number 18000 are two very different things. – Jabberwocky Sep 28 '16 at 06:47
  • It's definitely not plaintext, if that's what you mean. It would look pretty ugly to copy and paste the hex here. It's an audio file. – Kurausukun Sep 28 '16 at 06:49
  • Then you certainly need `fwrite`. BTW in the final verson of your program you need to add error checking, especially testing if `fopen` return `NULL`, which means that the file could not be opened for some reason (mostly, because it does not exist). – Jabberwocky Sep 28 '16 at 06:49
  • I made edits to my code and it now edits the addresses properly, but it also makes every other value 0 and crashes immediately after editing 0x1C, making me think it's creating a new file. Do I need w+ for overwriting? – Kurausukun Sep 28 '16 at 06:57
  • @Kurausukun: Note that the use of `"w"` means that the file is clobbered (truncated to zero length). If the intent is to update the file, the mode should be `"r+"` or `"r+b"` (the `b` matters critically on Windows and matters not at all on Unix). – Jonathan Leffler Sep 28 '16 at 06:58
  • Thanks for the help; the program still crashes, though, and it's not writing the correct values. I assume the issue with the values is because I'm using the wrong size in some capacity, but I have no idea why it's crashing. – Kurausukun Sep 28 '16 at 07:04
  • @Kurausukun concerning your program crashing you probably should ask another question and provide a [mcve]. Did you check if `fopen` returns NULL ? If it returns NULL and you don't check, it's quite normal your program crashes. Also read by last comment in your original question, that may be a cause for the crash. – Jabberwocky Sep 28 '16 at 07:05
  • Alright, I fixed the crashing, but I'm still writing the wrong values. I wrote some code to check, and it turns out that on my system, both int and long int are 4 bytes, so there shouldn't be a problem there. – Kurausukun Sep 28 '16 at 07:14
1

You probably want this:

#include <stdio.h>

void modify_data(unsigned int samp1, unsigned int samp2, char fname[])
{
  FILE * newfile;
  newfile = fopen(fname, "r+");  // or "r+b" on Windows
  if (newfile != NULL)
  {
    printf("Could not open file");
    return;
  }

  fseek(newfile, 0x18, SEEK_SET);
  fwrite(&samp1, sizeof (unsigned int), 1, newfile);
  fseek(newfile, 0x1c, SEEK_SET);
  fwrite(&samp2, sizeof (unsigned int), 1, newfile);
}

int main(int argc, char * argv[])
{
  modify_data(0, 0, argv[1]); // the first two arguments are placeholders while I test
  return 0;
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • I just realized the problem: it IS writing properly, but it's writing in little-endian; I need it to be big-endian. I don't suppose there's a good way to do that? – Kurausukun Sep 28 '16 at 07:20
  • Easy, you just need to [convert your value to big endian](http://stackoverflow.com/questions/2182002/convert-big-endian-to-little-endian-in-c-without-using-provided-func) prior to writing it to the file. – Jabberwocky Sep 28 '16 at 07:22
  • Well yes, but the issue is how I do that. I've never worked with bitshift operators before, which is what I feel like I would need to use to do this. Unless there's a built-in function in some library (there probably isn't). – Kurausukun Sep 28 '16 at 07:24
  • Click on the link in my comment. – Jabberwocky Sep 28 '16 at 07:24
  • Finally got it working after tracking down the library. Thanks a lot for putting up with me. – Kurausukun Sep 28 '16 at 07:39