Reputation: 658
Here is my code snippet:
int fd;
bufsize = 30;
char buf[bufsize];
char cmd[100] = "file.txt";
int newfd = 1;
if (fd = open(cmd,O_RDONLY) >=0){
puts("wanna read");
while (read(fd,&bin_buf,bufsize)==1){
puts("reading");
write(newfd,&bin_buf,bufsize);
}
close(fd);
}
So here the program prints "wanna read"
but never prints "reading"
. I have also tried opening using nonblock flag, but no use. Can anybody help me? I must use open()
and read()
system calls only. Thanks.
Edit: I have made some clarifications in the code. Actually the newfd that I'm writing to is a socket descriptor, but I don't think that is important for this problem because it sticks on the read
which is before the write
.
Upvotes: 0
Views: 5446
Reputation: 144550
Your read()
call attempts to read bufsize
bytes and returns the number of bytes actually read. Unless bufsize ==
, it is quite unlikely read()
will return 1
, so the block is almost always skipped and nothing get written.
Also note that if (fd = open(cmd, O_RDONLY) >= 0)
is incorrect and would set fd
to 1
, the handle for standard output, if the file exists, causing the read
to fail as standard input is most likely not opened for reading.
Note that reading with the read
system call is tricky on some environments, because a return value of -1
may be restartable.
Here is an improved version:
int catenate_file(const char *cmd, int newfd, size_t bufsize) {
int fd;
char buf[bufsize];
if ((fd = open(cmd, O_RDONLY)) >= 0) {
puts("wanna read");
ssize_t nc;
while ((nc = read(fd, buf, bufsize)) != 0) {
if (nc < 0) {
if (errno == EINTR)
continue;
else
break;
}
printf("read %zd bytes\n", nc);
write(newfd, buf, nc);
}
close(fd);
return 0;
}
return -1;
}
Upvotes: 1
Reputation: 753475
The first problem is your if
statement. You forgot to use enough parentheses, so if the open()
works, the read tries to read from file descriptor 1, aka standard output. If that's your terminal (it probably is) on a Unix box, then that works — surprising though that may be; the program is waiting for you to type something.
Fix: use parentheses!
if ((fd = open(cmd, O_RDONLY)) >= 0)
The assignment is done before, not after, the comparison.
I observe in passing that you don't show how you set cmd
, but if you see the 'wanna read' message, it must be OK. You don't show how newfd
is initialized; maybe that's 1
too.
You also have the issue with 'what the read()
call returns'. You probably need:
int fd;
char buf[bufsize];
int newfd = 1;
if ((fd = open(cmd, O_RDONLY)) >= 0)
{
puts("wanna read");
int nbytes; // ssize_t if you prefer
while ((nbytes = read(fd, buf, sizeof(buf))) > 0)
{
puts("reading");
write(newfd, buf, nbytes);
}
close(fd);
}
You can demonstrate my primary observation by typing something ('Surprise', or 'Terminal file descriptors are often readable and writable' or something) with your original if
but my loop body and then writing that somewhere.
Upvotes: 2
Reputation: 15827
read
returns the number of bytes read from file that can be bufsize
or less if the remainder of the file that has to be read is shorter than bufsize
.
In your case most probably bufsize
is bigger than 1 and the file is bigger than 1 byte so the condition of the while loop is evaluated false, the code is skipped to the point where file is closed.
You should check if there if there are more bytes to be read:
while( read(fd,&bin_buf,bufsize) > 0 ) {
Upvotes: 1