I am trying to understand the standard I/O. I met a problem of calling fdopen().
What's the behavior if I call fdopen() on the same file descriptor as follows? Why do I get an ouput of '\377' (-1) ?
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
int fd1, fd2;
char c;
FILE *fp1, *fp2;
fd1 = open("foo.txt", O_RDONLY, 0);
fp1 = fdopen(fd1, "r");
fp2 = fdopen(fd1, "r");
if (fp2 == NULL)
printf("NULL\n");
if (errno)
printf("ERROR\n");
c = fgetc(fp1);
c = fgetc(fp2);
printf("c = %c\n", c);
exit(0);
}
Let's say your stdio buffer size is 4K. The first fgetc reads 4K into the buffer and returns the first byte. The fd is now advanced 4K into the file. The second fgetc reads from there. Your file is smaller than the buffer size, so you're at EOF. You print the EOF with %c and get a funny character.
Multiple fdopen on a single fd gets a vote of don't try it; it will hurt from me. With an exception for creating stdin, stdout, and stderr from a single tty descriptor if you're writing getty.
Multiple problems:
char is not the right type for storing the return value of fgetc. Use int.
You're accessing the same open file description via two different handles without performing the steps necessary to switch between them legally. This invokes undefined behavior.
Checking errno and inferring from it that there was an error is not valid. If you already know there was an error, errno tells you which one. It does not tell you whether or not an error occurred, and in case one did not, any nonzero value may have been written to errno.
We don't know your file contents so we can't know what you expect to be read.
Related
I am facing this strange problem, answer to which is clear to me but I am looking for alternative here. Whenever I open a file in "a+" mode, I am able to read using fread(), if I read it first and then write in it using fprintf(). If I instead write into file first and then read it, I get blank value in output.
I do not want to fclose() the FILE pointer fp after every write because I am doing operations like write->read->write->read.......n iterations.
Is there an optimal way to achieve this ?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <poll.h>
#include <linux/input.h>
int main(){
FILE * fp;
fp = fopen("myback.txt", "a+");
char buf[10];
fprintf(fp, "checking");
fread (buf,1,4,fp);
buf[4] = '\0'; //buf has read n bytes
printf("%s \n", buf);
return 0;
}
From this fopen reference:
In update mode ('+'), both input and output may be performed, but output cannot be followed by input without an intervening call to fflush, fseek, fsetpos or rewind, and input cannot be followed by output without an intervening call to fseek, fsetpos or rewind, unless the input operation encountered end of file. In update mode, implementations are permitted to use binary mode even when text mode is specified.
So you can't read or write directly after each other, you must explicitly set or reset the file position between each input and output function.
I am trying to write 2 programs that will talk to each other using fifo pipe.
I used the example here (section 5.2), but I changed the mknod there to mkfifo and tried to change gets to fgets.
This is the code (of one program which writes into the fifo):
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h> /*mkfifo, open */
#include <sys/wait.h>
#include <sys/stat.h> /* mkfifo, open */
#include <fcntl.h> /*open */
#define FIFO_PATH "/home/hana/Desktop"
#define BUFFER_SIZE 300
int main()
{
char buffer[BUFFER_SIZE];
int fd;
int wStatus;
mkfifo(FIFO_PATH, 666);
printf("waiting for readers\n");
fd = open(FIFO_PATH, O_RDWR);
while (fgets(buffer, BUFFER_SIZE, fd), !feof(stdin))
{
if ((wStatus = write(fd, buffer, strlen(buffer))) == -1)
perror("write");
else
printf("speak: wrote %d bytes\n", wStatus);
}
return 0;
}
I get a compilation error: passing argument 3 of fgets makes pointer from integer.
So fgets is expecting FILE* and not file descriptor.
What should I do? change something so that fgets works? use another function?
I am compiling with gcc (ansi, pedantic).
Thanks
The answer from whjm is the cause of your error diagnostic, but I think you probably meant
fgets(buffer, BUFFER_SIZE, stdin)
// ^^^^^
It doesn't make sense that you would read from a pipe and then immediately write the same thing back to the pipe. Also, if you never read from stdin, feof(stdin) will never be true.
Also, with fgets just check for a null result and then outside the loop, do the check for eof:
while (fgets(...) != NULL)
{
...
}
if (!feof(stdin))
{
// error handling
}
mkfifo() just creates special node in filesystem. And you are free to open it in any way. Actually there are two alternatives - POSIX "non-buffered" I/O: open()/write()/read() or standard buffered I/O: fopen()/fread()/fwrite(). First family operates on file descriptors while second one uses so called file streams: FILE. You can not mix these APIs freely. Just choose one and stick to it.
Standard I/O library offers some useful extra capabilities comparing to low-level non-buffered I/O. Like fgets() that you're trying to use. In this situation would be reasonable to use standard streams and replace open() with:
FILE* stream = fopen(FIFO_PATH, "r+");
Thus program will use FILE* instead of plain file descriptors. Also write() need to be changed to fwrite() immediately followed by fflush() to guarantee that written data are passed to FIFO.
P.S. In case of necessity it is possible to "wrap" low-level descriptors returned by open()(or something other) with standard FILE*. See fdopen(). But it is much like a workaround to use standard I/O API with special file objects that can not be opened with fopen().
I'm using debian and I have to transfer data from a serial port into a text file to then get read into a database. I think how im setting the port up is wrong, and I keep stumbling across so many different examples, My current code (below) keeps giving me 3 warnings, "assignment makes pointer from integer without a cast" I think it has to do with the values that are being returned, I did some reading on what pointers return, but it wasn't too clear to me, I was wondering if someone could give some insight on the issue, or if there are any glaringly obvious issues that I am missing. Any suggestions are much appreciated.
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <termios.h>
#include <string.h>
#define BAUDRATE B115200
#define MODEMDEVICE "/dev/ttyS0"
main()
{
int n;
FILE *file;
file = open(MODEMDEVICE, O_RDWR, O_NOCTTY);
if(file == NULL){
printf("initiation error. \n");
return 1;
}
FILE *fp;
fp = open("testfile.txt", O_RDWR);
while(1){
file = scanf("%d", &n);
fprintf(fp, "%d", n);
fclose(fp);
}
fclose(file);
}
so what i think this does, or what i intend it to do at least is set file to read data from the port, and then store those values in n, which then get printed in a text file.
This:
FILE *fp;
fp = open("testfile.txt", O_RDWR);
is wrong, you meant fopen() on the last line, don't confuse raw I/O with the C runtime library's buffered functions.
This is also one reason for your error, since the file descriptor (not a pointer) returned by open() is an integer (see the open() manual page and compare that to fopen()'s).
UPDATE: I also fail to understand what you're trying to do with the scanf() line.
If you want to read an integer from a FILE *, you should use fscanf(). The return value is the number of successful conversions, which is used in error-checking:
if(fscanf(file, "%d", &n) == 1)
fprintf(fp, "%d", n);
That will read an integer from the serial port file, and if successful print it out to the output file fp.
I keep getting this error
glibc double free or corruption (out) error
and so far everything i've read on it has been due to an improper use of malloc, which would point to memory space, however, i'm not using malloc. I think its Something about how fscanf is accepting the stream. But nothing I'm reading on fscanf makes any sense to me in relation to the error I'm getting. Here's the code.
#include <stdio.h>
#include <fcntl.h>
#include <sys.stat.h>
#inlcude <termios.h>
#inlcude <string.h>
#define BAUDRATE B115200
#define MODEMDEVICE "/dev/ttyS0"
main()
{
int n;
FILE *file
file = fopen(MODEMDEVICE, "a");
if(file == NULL){
printf("initiating error\n);
return 1;
}
FILE *fp;
fp = fopen("testfile.txt", "a");
while(1){
fscanf(file, "%02x", &n);
fprintf(fp, "%d", n);
fclose(fp);
fclose(file);
}
}
my intention of this code is to take data streams from a serial port and and store them in a text file. Any ideas on why i'm getting this error?
The while(1) loop reads data from one file and writes it to the other file, but then closes the files. Once the files are closed you can't read from or write to them anymore, though your while loop tries again.
This code won't compile. It is missing a ";".
It's also opening both files with mode "a"; but surely you meant to open one for reading.
Anyway the bug is that you're calling fclose in the loop.
I need to read with fread() the stuff from the read end of the pipe.
But while i expect the fread() to set EOF when there is nothing in the pipe, it instead sets the error indicator. I have checked the posix and C standards and found no clue there. Probably i'm doing something unintended (read, silly), right:)
Here's the excerpt:
#include <stdio.h>
#include <fcntl.h>
int main()
{
char buf[128];
FILE *f;
int pipe_fd[2], n;
pipe(pipe_fd);
fcntl(pipe_fd[0], F_SETFL, O_NONBLOCK);
f=fdopen(pipe_fd[0], "r");
n=fread(buf, 1, 1, f);
printf("read: %d, Error: %d, EOF: %d\n", n, ferror(f), feof(f));
return 0;
}
Since you're using a non-blocking pipe, I believe you would get:
errno==EAGAIN when there simply isn't anything there to read (meaning nothing now but maybe something later - try (e)again later).
EOF when the writing side of the pipe is closed (meaning no more data is coming).
See the manpage for read() about how read() behaves when O_NONBLOCK mode is set. fread() behavior should be consistent with read().