fwrite a pid_t not working - c

I have the follwoing code:
...
printf("Started %d", pid);
FILE * fh;
fh = fopen("run/source.pid", "wb");
fwrite(&pid, sizeof(int), 1, fh);
fclose(fh);
However the written pid file writes jargon, and not the integer, I though pid_t was just an int, I even tied doing sizeof(pid_t) for the second argument I get similar issues.
Any ideas? Thanks for the help in advance.
Thanks

well I do not understand quite well the question (too little context), but the issue may be is that you are seeing the file in a text editor, terminal, etc..
fwrite() writes raw data, for example, suppose you have a pid number, lets say 12, and you write that number using fwrite like this:
fwrite(&pid, sizeof(int), 1, file);
fwrite() will write a 32 bit integer into the file file, that is, depending in your processor type, a byte sequence like this: 00 00 00 12
However
fprintf() will write a byte sequence of : 49 50 (ASCII characters platform independent) visible among all terminals or text editors.
Hope this helps.

Related

What does the "size" argument in fread() refer to?

I'm trying to make a basic program which copies the header of a .wav file, this was my attempt:
#include <stdio.h>
#include <stdint.h>
int main (void)
{
FILE* input = fopen("input.wav", "r");
FILE* output = fopen("output.wav", "w");
uint8_t header [44];
fread(header, sizeof(uint8_t), 44, input);
fwrite(header, sizeof(uint8_t), 44, output);
fclose(input);
fclose(output);
}
However, after failing to make it work, I looked up how to do it and apparently
fread(header, sizeof(uint8_t), 44, input);
fwrite(header, sizeof(uint8_t), 44, output);
should be
fread(header, 44, 1, input);
fwrite(header, 44, 1, output);
This is very confusing to me, as I thought that the second argument was supposed to be the size of the type of data unit you want to fread. Can anyone help me understand what I'm missing? Many thanks.
The first size parameter specifies the size of a single record. The second size parameter defines how many records you want to load. fread returns the number of records it loaded.
So if you have a structure which is 20 bytes, and you have a file where you have stored 5 of the records then you can pass it like this.
if(fread(ptr, 20, 5, strm) != 5)
printf("Unable to load 5 records\n");
Alternativaly you could load the same file like this:
if(fread(ptr, 1, 5*20, strm) != 5*20)
printf("Unable to load 5 records\n");
The effect is the same, but the first version is more readable, because usually you may read records not just "bytes". It's easier to understand in the context of your application logic. And of course you don't have to deal with calculating the number of bytes yourself, thus reducing a chance for errors.
The same applies to fwrite.
So in your above example I would rather write it like this:
// Your header is 44 bytes long (which is sizeof) but you want to read ONE header
if(fread(header, sizeof(header), 1, input) != 1)
... error reading 1 header ....
sizeof(uint8_t) is guaranteed to be 1 . Some people think it good style to use the sizeof expression instead of the number.
You can either write 44 "blocks" of size 1, or 1 block of size 44. In either case , you tried to write 44 bytes -- the writing part is the same either way.
The difference is in the return value, which reports how many blocks were successfully written. So if you use the 1, 44 order then it will tell you exactly how many bytes were written. If you use the 44, 1 order then you will either get 0 or 1 as the return value (and no way to know if it partially succeeded).
The same consideration applies to fread.
The FILE* input = fopen("input.wav", "r"); part is incorrect: this specifies to open the file in text mode, which may perform translations on the input, such as changing the line endings.
Instead, open in binary mode with "rb" mode string.

How does C store the information into a file really?

In the simple code below, I'm writing an int number (10) into a file and then reading it back to make sure it's done successfully and it is. However, when I open the file (tried both notepad++ and vscode) I see something like this:
???
Here's the code:
int main(){
int var = 10;
FILE* fp = fopen("testfile","w");
rewind(fp);
fwrite(&var,sizeof(int),1,fp);
fflush(fp);
fclose(fp);
int var2 = 0;
fopen("testfile","r+");
fread(&var2,sizeof(int),1,fp);
printf("num: %d\n",var2);
return 0;
}
Of course I thought maybe it's written in a special format which vscode is unable to recognize, but recently I learned coding a simple database, and it used just the same way to save the records in files and when you opened its output file with vscode, it showed both ???s AND the information, however, here it shows only ???s WITHOUT the information. So although it seems be a very basic problem, I can't find the answer to it, so how is 10 really stored in that file? Thanks in advance.
When you write to the file with fwrite, it reads the raw bytes that make up var and writes those to disk. This is the binary representation of the number.
If you use a tool like od, it will print out the bytes the files contains:
[dbush#db-centos7 ~]$ od -tx1 testfile
0000000 0a 00 00 00
0000004
You can see here that the first byte contains the value 10 and the next 3 contain the value 0. This tells us that an int takes up 4 bytes and is stored in little-endian format, meaning the least significant byte comes first.
Had you instead uses fprintf to write the value:
fprintf(fp, "%d\n", var);
It would have written the text representation to the file. The file would then look something like this:
[dbush#db-centos7 ~]$ cat testfile
10
[dbush#db-centos7 ~]$ od -tx1 testfile
0000000 31 30 0a
0000003
We can see here that printing the file shows readable text, and od shows us the ASCII codes for the characters '1' and '0', as well as a newline.
You are writing a binary file. It cannot be read with an editor. The value 10 is probably stored as 0x0000000A or 0x0A000000 something like that, depending on if the system is big or small endian.
But the point is that it is stored in binary format and not text format.
If you open this file in a text editor, it will likely be interpreted as three NULL characters and then a LF (line feed) character.

How to write to specific offset in empty file

I have a file in which I read in data. Suppose the file has the string "abcdefghij". Now, I'm going to be reading from the file at random times from different processes and they store that byte and offset somewhere. For instance, I save 'c' as my character with an offset of '3' because that is its location. For reference, I've been using lseek to get the offset in my files.
Next, I want to write this to a new file. Is it possible to write to a specific offset in an empty file? So, I want to write 'c' to position '3' in the file and then another process will write 'j' to the file at position 10.
#include <stdio.h>
int main ()
{
FILE * f = fopen ("/tmp/x.txt", "w");
fseek (f, 3, SEEK_SET);
fwrite ("c", 1, 1, f);
fseek (f, 10, SEEK_SET);
fwrite ("j", 1, 1, f);
fclose (f);
}
When this runs, the hexdump of /tmp/x.txt is
00 00 00 63 00 00 00 00 00 00 6a | ...c.... ..j
fseek is based on lseek which is capable of recognising "holes" in files (ranges of zeroes which haven't been written yet) but the underlying file system needs to support this.
It's not brilliantly clear to me from the manpage that the holes are strictly required to be zeroes, but that seems to be the case in practice.
Look into ftello. Then use fwrite.
You can also use lseek/write, if you're using fd's instead of FILE*s.

Reading binary files in C, on UNIX systems (Ubuntu 10.10)

this is my first time programming in C, and on a UNIX system. I am trying to do something fairly simple. I have a binary file that is an image of a Compact Flash camera card, and consists of a few JPG images. I am trying to read through the file, find the byte sequence corresponding to FF D8 FF E0, or FF D8 FF E1, the signifiers of the beginning of a JPG file, then writing everything between that signifier and the next to a new jpg file.
At the moment I am just trying to get my computer to print out the file as is, by reading it in 512 size blocks, the stated size of the blocks in the original file system. I have the following code:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main (int argc, char *argv[])
{
FILE * raw;
FILE * currentimage;
char buf[512];
char beg1[32] = "11111111110110001111111111100001";
char beg2[32] = "11111111110110001111111111100000";
raw = fopen("card.raw", "rb");
while((fread(buf, sizeof(raw), 512, raw) > 0))
{
printf(buf);
printf("\n");
}
}
It just prints out the file formatted into what I presume is ASCII, so it looks like a bunch of gobbledegook. How can I get this data formatted to either binary 1's and 0's or, even better, hex 0-F's?
Any help would be much appreciated.
P.S. beg1 and beg2 correspond to the binary values of the hex values I am looking for, but they are not really relevant to the rest of the code I have at the moment.
Instead of printf(buf); you would need to loop through each byte and do printf("%02x ", byte). Take a look at the source of hexdump here:
http://qa.coreboot.org/docs/doxygen/hexdump_8c_source.html
You should read up on what printf() does, as in NO PROGRAMMING LANGUAGE that I know, should you EVER use data as the first argument to printf. The first argument should be a template, which the way you used it should be "%s". To see hex output, replace your loop with this:
int size;
while((size = (fread(buf, sizeof(raw), 512, raw)) > 0))
{
for (int i = 0; i < size; i++)
{
printf("%2X", buf[i]);
}
printf("\n");
}
To answer your question about comparision in C before printing:
The numerical data is right there in buf -- buf[i] is an char from -127 to 128 that contains the value. If you want to look at its hex representation, you can do:
sprintf(some_other_buffer, "%2X", buf[i]);
Then you can perform string manipulation on some_other_buffer, knowing it's a 2 character string.

fread Only first 5 bytes of .PNG file

I've made a simple resource packer for packing the resources for my game into one file. Everything was going fine until I began writing the unpacker.
I noticed the .txt file - 26 bytes - that I had packed, came out of the resource file fine, without anyway issues, all data preserved.
However when reading the .PNG file I had packed in the resource file, the first 5 bytes were intact while the rest was completely nullified.
I traced this down to the packing process, and I noticed that fread is only reading the first 5 bytes of the .PNG file and I can't for the life of me figure out why. It even triggers 'EOF' indicating that the file is only 5 bytes long, when in fact it is a 787 byte PNG of a small polygon, 100px by 100px.
I even tested this problem by making a separate application to simply read this PNG file into a buffer, I get the same results and only 5-bytes are read.
Here is the code of that small separate application:
#include <cstdio>
int main(int argc, char** argv)
{
char buffer[1024] = { 0 };
FILE* f = fopen("test.png", "r");
fread(buffer, 1, sizeof(buffer), f);
fclose(f); //<- I use a breakpoint here to verify the buffer contents
return 0;
}
Can somebody please point out my stupid mistake?
Can somebody please point out my stupid mistake?
Windows platform, I guess?
Use this:
FILE* f = fopen("test.png", "rb");
instead of this:
FILE* f = fopen("test.png", "r");
See msdn for explanation.
Extending the correct answer from SigTerm, here is some background of why you got the effect you did for opening a PNG file in text mode:
The PNG format explains its 8-byte file header as follows:
The first eight bytes of a PNG file always contain the following values:
(decimal) 137 80 78 71 13 10 26 10
(hexadecimal) 89 50 4e 47 0d 0a 1a 0a
(ASCII C notation) \211 P N G \r \n \032 \n
This signature both identifies the file as a PNG file and provides for immediate detection of common file-transfer problems. The first two bytes distinguish PNG files on systems that expect the first two bytes to identify the file type uniquely. The first byte is chosen as a non-ASCII value to reduce the probability that a text file may be misrecognized as a PNG file; also, it catches bad file transfers that clear bit 7. Bytes two through four name the format. The CR-LF sequence catches bad file transfers that alter newline sequences. The control-Z character stops file display under MS-DOS. The final line feed checks for the inverse of the CR-LF translation problem.
I believe that in text mode, the call to fread() was terminated when it read the sixth byte which contains a Ctrl+Z character. Ctrl+Z was historically used in MSDOS (and in CPM before it) to indicate the end of a file, which was necessary because the file system stored the size of a file as a count of blocks, not a count of bytes.
By reading the file in text mode instead of binary mode, you triggered the protection against accidentally using the TYPE command to display a PNG file.
One thing you could do that would have helped diagnose this error is to use fread() slightly differently. You didn't test the return value from fread(). You should. Further, you should call it like this:
...
size_t nread;
...
nread = fread(buffer, sizeof(buffer), 1, f);
so that nread is a count of the bytes actually written to the buffer. For the PNG file in text mode, it would have told you on the first read that it only read 5 bytes. Since the file cannot be that small, you would have had a clue that something else was going on. The remaining bytes of the buffer were never modified by fread(), which would have been seen if you initialized the buffer to some other fill value.

Resources