Reputation: 70
I'm trying to create a keymanager for a simple UDP client-server application in C. I'm running into problems writing the keys to a text file. I'm currently storing structs into a txt file, but my output was the same when I used ints.
// ...
// if the principal is requesting to registering, store it in a file
if (req.request_type == regista) {
printf("Writing key to file...\n");
pFile = fopen("crypt.txt", "ab");
fwrite(&req, sizeof(struct P2Key), 1, pFile);
printf("Written: %u %i ", req.principal_id, req.public_key);
fclose(pFile);
printf("Done\n");
}
// if pincipal is requesting key
if (req.request_type == request_key) {
pFile = fopen("crypt.txt", "rb");
printf("Key requested for: %u %i ", req.principal_id, req.public_key);
printf("Searching for Requested Key\n");
while (fread(&res, sizeof(struct P2Key), 1, pFile) == 1) {
printf("Read: %u %i\n", res.principal_id, res.public_key);
printf("Line Number: %ld\n", ftell(pFile));
// if this is the client requested, send the key
if (req.principal_id == res.principal_id) {
send_key.principal_id = req.principal_id;
send_key.public_key = req.public_key;
printf("Sending Key...\n");
// ...
}
Here's the structure being written to the file
typedef struct P2Key {
enum {
regista, request_key
} request_type; /* same size as an unsigned int */
unsigned int principal_id; /* client or server identifier */
int public_key; /* public key */
} P2Key;
The output I'm getting when I attempt to read the file:
Writing key to file...
Written: 2 7 Done
...
Writing key to file...
Written: 1 7 Done
Key requested for: 2 7 Searching for Requested Key
Read: 512 1792
Line Number: 12
Read: 256 1792
Line Number: 24
End of file reached.
I've been at this for hours, any and all help is appreciated.
Upvotes: 0
Views: 655
Reputation: 33641
Your program appears to work here. Note that I'm using linux, but since you're using b
in your fopen
args, even if you are using WinX, it should still be the same.
I had to synthesize some missing elements to get a full program. I passed down req
from main
, so the [new] action
function had to use req->*
instead of req.*
, but, otherwise it should be the same as your code:
#include <stdio.h>
typedef struct P2Key {
enum {
regista, request_key
} request_type; /* same size as an unsigned int */
unsigned int principal_id; /* client or server identifier */
int public_key; /* public key */
} P2Key;
void
action(P2Key *req)
{
FILE *pFile;
P2Key res;
P2Key send_key;
printf("request_type=%d regista=%d request_key=%d\n",
req->request_type,regista,request_key);
// ...
// if the principal is requesting to registering, store it in a file
if (req->request_type == regista) {
printf("Writing key to file...\n");
pFile = fopen("crypt.txt", "ab");
fwrite(req, sizeof(struct P2Key), 1, pFile);
printf("Written: %u %i ", req->principal_id, req->public_key);
fclose(pFile);
printf("Done\n");
}
// if pincipal is requesting key
if (req->request_type == request_key) {
pFile = fopen("crypt.txt", "rb");
printf("Key requested for: %u %i ", req->principal_id, req->public_key);
printf("Searching for Requested Key\n");
while (fread(&res, sizeof(struct P2Key), 1, pFile) == 1) {
printf("Read: %u %i\n", res.principal_id, res.public_key);
printf("Line Number: %ld\n", ftell(pFile));
// if this is the client requested, send the key
if (req->principal_id == res.principal_id) {
send_key.principal_id = req->principal_id;
send_key.public_key = req->public_key;
printf("Sending Key...\n");
// ...
}
}
fclose(pFile);
}
}
int
main(void)
{
P2Key req;
while (1) {
printf("Cmd (regista=%d request_key=%d): ",regista,request_key);
fflush(stdout);
scanf("%d",&req.request_type);
scanf("%u %d",&req.principal_id,&req.public_key);
action(&req);
}
}
Here is the output I got:
Cmd (regista=0 request_key=1): 0 5 6
request_type=0 regista=0 request_key=1
Writing key to file...
Written: 5 6 Done
Cmd (regista=0 request_key=1): 0 8 9
request_type=0 regista=0 request_key=1
Writing key to file...
Written: 8 9 Done
Cmd (regista=0 request_key=1): 1 8 9
request_type=1 regista=0 request_key=1
Key requested for: 8 9 Searching for Requested Key
Read: 1 2
Line Number: 12
Read: 5 6
Line Number: 24
Read: 8 9
Line Number: 36
Sending Key...
Cmd (regista=0 request_key=1): ^C
Upvotes: 1
Reputation: 882716
You need to check your file, it appears that there may be an extra byte (or bytes) in there for some reason, which is causing you to read the structures at an incorrect offset.
I base this on the following:
256
. More importantly, they are 256
multiplied by 1
, 2
and 7
(256
, 512
and 1792
).An easy way to check is to simply delete the file (or empty it) and run your program again. Provided you don't have anything else writing to the file, it should work okay.
There are actually ways you can catch this sort of issue, should you be so inclined. They include, amongst others:
check_dead
and another at the end called check_beef
, which you always set to 0xdead
and 0xbeef
on writing a record and always check when reading one.Upvotes: 0
Reputation: 38
You are writing in append mode; have you re-created the file since you switched to writing the structs? You don't show or even test the number of bytes written, so you have no idea if the write succeeded or not.
My first suspect is that you have been appending to this file over time, and it has old data near the beginning that doesn't line up with your structure. I suggest first emptying the file. On UNIX/Linux, you can do this with "> crypt.txt" from the shell.
Now on to debugging the code. Capture the return value of all reads and writes, they return size_t, so you can at least look at the return value in the debugger. You may want to log an error, etc., if you didn't write the number of bytes you expected to -- the sizeof the struct. Step over the write and close in your debugger, then look at the file with a hex dump or similar utility. Do the values in the file look like what you expect? Does the file contain the same number of bytes as the sizeof your struct?
Then proceed to the read code. Watch the code load each value from the file with fread. Watch the return value you get from fread -- is it the sizeof your struct? Look at the values in the struct after the read completes. Does it look like it read what you wrote?
Upvotes: 1