I have a basic program that opens a file contained in the same directory as the C file (in root). The file is called myfile1, which is a simple file containing text.
This program is supposed to open the file, count the number of characters and display it. For some reason, I compile the program, run it with a.out and the program gets input from the user and finishes when Ctrl+D is pressed, when it is supposed to get input from the file.
Any ideas as to what could be going on? Thank you very much, here is what I have so far:
#include <fcntl.h>
void main(){
char buff[512];
int fd = 0;
int j=0;
long total=0;
if(fd=open("myfile1",O_RDONLY)<0){
printf("Error");
return 1;
}
while((j=read(fd,buff,512))>0)
total = total+j;
printf("%d\n",total);
close(fd);
return 0;
}
The problem is with your if condition: fd=open("myfile1",O_RDONLY)<0. Less-than comparison have higher precedence than assignment. It should be (fd=open("myfile1",O_RDONLY))<0.
In your code, as ketlat said, the if logic is problematic.
If you put a debug print inside your code and check the fd, you'll see
Code:
if(fd=open("myfile1",O_RDONLY)<0){
printf("Error");
return 1;
}
printf("obtained fd = %d\n", fd);
O/P:
obtained fd = 0
Reason
< has higher preceidence over =. Hence, when the open() is success, it will return a non-negative value, which is not less than 0, and the comparison open("myfile1",O_RDONLY)<0 will evaluate to false , represented as 0, and the same will be assigned to fd.
Nw, this fd value will be used in your read() call. FD 0 means stdin or the standard input. So, as per your logic, the code behaves correctly.
However, to achieve your goal, you need to change
fd=open("myfile1",O_RDONLY)<0
to
(fd=open("myfile1",O_RDONLY))<0
With the changed code, a sample run is likely to yield an o/p like
obtained fd = 3.
Be notified, YMMV.
Related
I wrote code below
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main() {
int fd = 3;
char c[100] = "Testing\n";
ssize_t nbytes = write(fd, (void *) c, strlen(c));
return 0;
}
compiled/linked, and executed
$ ./io
$ ./io 3> io_3.txt
The first line produced no output. The second line gave me file io_3.txt containing Testing.
This is all expected behaviour (I guess).
Even if in my tests it produced the expected output,
I am not certain if, to avoid potential problems, undefined behavior, etc., I should do anything prior to the first write, like checking if fd=3 is in use (and in that case, how... this may apply), if it is suitably open, etc.
And I am not certain if I should perform some action after the last write, for the same reasons.
Perhaps the way I did is "non-risky", the only potential issue being that nothing is written, which I could detect by checking the value of nbytes... I wouldn't know.
Any clarification is welcome.
If you write a program like this, executing it without fd 3 open is a usage bug. Normally the only file descriptors that should be used by number without having opened them yourself are 0 (stdin), 1 (stdout), and 2 (stderr). If a program needs to take additional pre-opened file descriptors as input, the standard idiom is to pass the fd numbers on the command line or environment variables rather than hard-coding them. For example:
int main(int argc, char **argv) {
if (argc<2 || !isdigit(argv[1][0])) return 1;
int fd = strtol(argv[1], 0, 0);
char c[100] = "Testing\n";
ssize_t nbytes = write(fd, (void *) c, strlen(c));
return 0;
}
In practice, a trivial program like yours is probably safe with the write just failing if fd 3 wasn't open. But as soon as you do anything that might open file descriptors (possibly internal to the implementation, like syslog, or date/time functions opening timezone data, or message translation catalogs, etc.), it might happen that fd 3 now refers to such an open file, and you wrongly attempt a write to it. Using file descriptors like this is a serious bug.
I have a solution here that supposedly opens a file and changes the last character of it. I don't quite understand how this works. Could you please explain?
void readlast()
{
int handle = open("./file.txt", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
if (handle < 0)
{
return;
}
Okay, this part opens the file and if it doesn't work, returns.
First question: Why is a file opening an integer (int handle)? What is being stored in it?
char c='N';
lseek(handle, -2*sizeof(c), SEEK_END);
lseek apparently changes the location of a reader. So I guess this sets the reader to the end of a file(SEEK_END). But why do we need an offset of -2*sizeof(c) if we just want to write one character?
write(handle, &c, sizeof(c));
close(handle);
}
I do understand this last part.
Thank you!
Normally a file descriptor is returned by open() and it is an integer. 0 and 1 are customarily standard I/O.
File size - 2 [octets] is the offset of last character/byte.
I am conducting n simulations using a program and albeit everything being correct, there is only one mistake which I am able to see in the output files.
I am printing the outputs of the program to a csv file.
I check the file before I print to it to get it's size which if it is 0, I print the headers. Here is the function which does the same:
void Data_Output(FILE *fp, int node_num, int agg_num, int cnode, int sysdelay, int bwdth_reqt)
{
struct stat buf;
int fd = fileno(fp);
fstat(fd, &buf);
//Debug Statement
fprintf(stderr,"%d-",buf.st_size);
if (!buf.st_size) {
// Writing Headers
fprintf(fp,"Tot_Nodes_Num,Agg_Nodes_Num,Central_Node_Num,Tot_System_Delay,Bandwidth_Reqt\n");
}
// Writing Data
fprintf(fp,"%d,%d,%d,%d,%d\n",node_num,agg_num,cnode,sysdelay,bwdth_reqt);
}
For 100 simulations, the output I get from the debug shows me:
0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-
What am I doing wrong? I suspect that the program stores everything in a buffer and only prints everything to the file after it is done with the simulations and the files are closed.
Note: I open and close the files only once during the whole program and not for each simulation.
You are correct. Stdio has it's own output buffering and fstat is only concerned with logical files. So the file writes do get delayed. Try putting fflush(fp); for the last line in your Data_Output function. I hope that helps.
I am writing a C program on unix which should redirect it's output to the file, and write to it some text every second in infinite loop:
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(void) {
int outDes = open("./output.txt", O_APPEND | O_WRONLY);
dup2(outDes, 1);
while(1) {
printf("output text\n");
sleep(1);
}
}
But it writes nothing to the output file. I tried to change the 'while' loop for 'for' with 10 loops, and I found that it writes all 10 lines to the file at once after the series ends. It is not very good for me, while I need to have an infinite loop.
When I'm not redirecting output, it is all ok, and new line appears every second on terminal.
I also tried to put one
printf("text\n");
before redirecting output to the file. Then the program wrote the lines to the file in real time, which is good, but wrote there the first (non redirected) line too. I don't want this first line in my output file, I don't understand how it could be written into file when output was not redirected yet (maybe redirect remained there since last run?), and how it could cause that the lines are suddenly written in real time.
Can anyone explain me how does it work?
You are not checking the return value of open() and dup2(). If either open() or dup2() failed, it won't write anything in output.txt.
if (outDes < -1) {
perror("open");
return 1;
}
if (dup2(outDes, 1) == -1) {
perror("dup2");
return 1;
}
stdio streams are buffered, and the writes happen in memory before being done on the real file description.
Try adding a fflush(stdout) after printf().
You're running afoul of a poorly documented DWIMmy feature in many Unix C libraries. The first time you write to stdout or stderr, the library probes the underlying file descriptor (with isatty(3)). If it's a (pseudo-)terminal, the library puts the FILE in "line buffered" mode, meaning that it'll buffer input until a newline is written and then flush it all to the OS. But if the file descriptor is not a terminal, it puts the FILE in "fully buffered" mode, where it'll buffer something like BUFSIZ bytes of output before flushing them, and pays no attention to line breaks.
This is normally the behavior you want, but if you don't want it (as in this case), you can change it with setvbuf(3). This function (although not the behavior I described above) is ISO standard C. Here's how to use it in your case.
#include <stdio.h>
#include <unistd.h>
int
main(void)
{
if (freopen("output.txt", "a", stdout)) {
perror("freopen");
return 1;
}
if (setvbuf(stdout, 0, _IOLBF, 0)) {
perror("setvbuf");
return 1;
}
for (;;) {
puts("output text");
sleep(1);
}
/* not reached */
}
I'm trying to read binary data in a C program with read() but EOF test doesn't work. Instead it keeps running forever reading the last bit of the file.
#include <stdio.h>
#include <fcntl.h>
int main() {
// writing binary numbers to a file
int fd = open("afile", O_WRONLY | O_CREAT, 0644);
int i;
for (i = 0; i < 10; i++) {
write(fd, &i, sizeof(int));
}
close(fd);
//trying to read them until EOF
fd = open("afile", O_RDONLY, 0);
while (read(fd, &i, sizeof(int)) != EOF) {
printf("%d", i);
}
close(fd);
}
read returns the number of characters it read. When it reaches the end of the file, it won't be able to read any more (at all) and it'll return 0, not EOF.
You must check for errors. On some (common) errors you want to call read again!
If read() returns -1 you have to check errno for the error code. If errno equals either EAGAIN or EINTR, you want to restart the read() call, without using its (incomplete) returned values. (On other errors, you maybe want to exit the program with the appropriate error message (from strerror))
Example: a wrapper called xread() from git's source code
POSIX rasys return == 0 for end of file
http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html
If no process has the pipe open for writing, read() shall return 0 to indicate end-of-file.
This confirms Jerry's answer.
EOF is returned by some ANSI functions, e.g. man getc says:
fgetc(), getc() and getchar() return the character read as an unsigned char cast to an int or EOF on end of file or error.
ungetc() returns c on success, or EOF on error.
so you still can't use it to distinguish error and end of file in that case, feof is needed.
See also: How to use EOF to run through a text file in C?