Home > Archive > Unix Programming > December 2004 > Need to block on file eof read
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Need to block on file eof read
|
|
| James Johnson 2004-12-28, 4:00 pm |
|
I need to do something like this, but get the read (fgets in this case)
to block until there is a new line of data. Sort of like tail -f.
FILE *instream = fopen(fname, "rt");
if (instream==NULL) {
return 0;
}
fs (instream, 0L, SEEK_END);
while(1) {
cptr = fgets(buf, sizeof(buf), instream);
if (cptr==NULL) {
printf("exiting because there is no data\n");
break;
}
printf(cptr);
}
fclose(instream);
How can this be done in unix?
Jim
| |
| DINH Viet Hoa 2004-12-28, 4:00 pm |
| James Johnson wrote :
> I need to do something like this, but get the read (fgets in this case)
> to block until there is a new line of data. Sort of like tail -f.
>
> FILE *instream = fopen(fname, "rt");
> if (instream==NULL) {
> return 0;
> }
> fs (instream, 0L, SEEK_END);
>
> while(1) {
> cptr = fgets(buf, sizeof(buf), instream);
> if (cptr==NULL) {
> printf("exiting because there is no data\n");
> break;
> }
> printf(cptr);
> }
>
> fclose(instream);
>
>
> How can this be done in unix?
tail will poll for new data when it reaches the end of the file.
On some unix, you can use kqueue or the linux equivalent to avoid
polling.
--
DINH V. Hoa,
"tuning et dope, aucun rapport" -- b.
| |
| James Johnson 2004-12-28, 4:00 pm |
| On Tue, 28 Dec 2004 18:13:47 +0100, DINH Viet Hoa
<dinh.viet.hoa@free.fr> wrote:
>James Johnson wrote :
>
>
>tail will poll for new data when it reaches the end of the file.
>
>On some unix, you can use kqueue or the linux equivalent to avoid
>polling.
tail is a shell command. I want to do this in C.
Jim
| |
| Andrei Voropaev 2004-12-28, 4:00 pm |
| On 2004-12-28, James Johnson <jj@yaaho.com> wrote:
>
>
> I need to do something like this, but get the read (fgets in this case)
> to block until there is a new line of data. Sort of like tail -f.
>
> FILE *instream = fopen(fname, "rt");
> if (instream==NULL) {
> return 0;
> }
> fs (instream, 0L, SEEK_END);
>
> while(1) {
> cptr = fgets(buf, sizeof(buf), instream);
> if (cptr==NULL) {
> printf("exiting because there is no data\n");
> break;
> }
> printf(cptr);
> }
>
> fclose(instream);
>
>
> How can this be done in unix?
On linux, normally one calls fgets, if NULL then sleeps for a while, and
after that tries again. Check the strace of tail -f, you'll see it.
I don't believe (though I don't know it ;) that there's any other way.
Andrei
| |
| Chuck Dillon 2004-12-28, 4:00 pm |
| James Johnson wrote:
>
> I need to do something like this, but get the read (fgets in this case)
> to block until there is a new line of data. Sort of like tail -f.
"sort of"? I can't help you with "sort of" but if it needs to do what
tail does you have to periodically use stat/fstat to check the length
of the file and see if it has grown beyond the position you previous
read up to.
-- ced
>
> FILE *instream = fopen(fname, "rt");
> if (instream==NULL) {
> return 0;
> }
> fs (instream, 0L, SEEK_END);
>
> while(1) {
> cptr = fgets(buf, sizeof(buf), instream);
> if (cptr==NULL) {
> printf("exiting because there is no data\n");
> break;
> }
> printf(cptr);
> }
>
> fclose(instream);
>
>
> How can this be done in unix?
>
> Jim
>
>
--
Chuck Dillon
Senior Software Engineer
NimbleGen Systems Inc.
| |
| James Johnson 2004-12-28, 4:00 pm |
| On Tue, 28 Dec 2004 12:11:02 -0600, Chuck Dillon <spam@nimblegen.com>
wrote:
[color=darkred]
>James Johnson wrote:
>
>"sort of"? I can't help you with "sort of" but if it needs to do what
>tail does you have to periodically use stat/fstat to check the length
>of the file and see if it has grown beyond the position you previous
>read up to.
>
>-- ced
>
That's what I'm currently doing: if the filesize changes read until an
eof, then sleep. That "sort of" works the same as tail -f. I wasn't sure
if that's how it should be done. I heard that there was a way to read a
file that blocks until new data is available. That seems to be a better
way, since you don't have to poll the file size. If I knew how to do it
by a blocking read, I'd rather do it that way.
Jim
| |
| Chuck Dillon 2004-12-28, 8:58 pm |
| James Johnson wrote:
>
>
> That's what I'm currently doing: if the filesize changes read until an
> eof, then sleep. That "sort of" works the same as tail -f. I wasn't sure
> if that's how it should be done. I heard that there was a way to read a
> file that blocks until new data is available. That seems to be a better
> way, since you don't have to poll the file size. If I knew how to do it
> by a blocking read, I'd rather do it that way.
>
> Jim
>
There's no way to block until data is added to a regular file without
the writer providing some stimulus. Either of the stat or read loop
approaches should work. On SunOS(5.8) if you truss (system call
tracer) tail -f you will see alarms and reads so it is simply looping
on reads with a short sleep (i.e. 1 second). If you do the same (with
strace) on linux (2.4.7) you see nonosleeps and fstat64 calls so that
implementation is monitoring the size.
-- ced
--
Chuck Dillon
Senior Software Engineer
NimbleGen Systems Inc.
| |
| Floyd L. Davidson 2004-12-28, 8:58 pm |
| James Johnson <jj@yaaho.com> wrote:
>I need to do something like this, but get the read (fgets in this case)
>to block until there is a new line of data. Sort of like tail -f.
>
>FILE *instream = fopen(fname, "rt");
>if (instream==NULL) {
> return 0;
>}
>fs (instream, 0L, SEEK_END);
>
>while(1) {
> cptr = fgets(buf, sizeof(buf), instream);
> if (cptr==NULL) {
> printf("exiting because there is no data\n");
> break;
> }
> printf(cptr);
>}
>
>fclose(instream);
>
>How can this be done in unix?
You can do it with ANSI C, hence there is absolutely no
difference for various platforms. Consider this snippet:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
...
char buf[BUFSIZ];
fpos_t pos;
FILE *fp;
if (NULL == (fp = fopen(fname, "rt"))) {
fprintf(stderr,"Cannot find file: %s\n", fname);
exit(EXIT_FAILURE);
}
if ( 0 != fs (fp, 0, SEEK_END)) {
fprintf(stderr,"Cannot read file: %s\n", fname);
exit(EXIT_FAILURE);
}
if (-1 == fgetpos(fp, &pos)) {
fprintf(stderr,"Cannot read file: %s\n", fname);
exit(EXIT_FAILURE);
}
for (;;) {
fgets(buf, sizeof(buf), instream);
if (ferror(instream)) {
fprintf(stderr,"Error reading file: %s\n", name);
exit(EXIT_FAILURE);
}
if (feof(instream)) {
fsetpos(instream, &pos);
clearerr(instream);
usleep(10000); /* give up the cpu to other processes */
continue;
}
fgetpos(instream, &pos);
printf("%s", buf);
fflush(stdout);
}
--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) floyd@barrow.com
| |
| David Schwartz 2004-12-29, 3:58 am |
|
"James Johnson" <jj@yaaho.com> wrote in message
news:26a3t0togm9269t4rnh3sqt608qftlrcse@
4ax.com...
> That's what I'm currently doing: if the filesize changes read until an
> eof, then sleep. That "sort of" works the same as tail -f. I wasn't sure
> if that's how it should be done. I heard that there was a way to read a
> file that blocks until new data is available. That seems to be a better
> way, since you don't have to poll the file size. If I knew how to do it
> by a blocking read, I'd rather do it that way.
There is no direct way to block until new data is available. The file is
always readable, and so will never block. You might want to google (or check
your manual pages) for information on FAM (file alteration monitor). On
Linux, you can use 'gamin'.
http://oss.sgi.com/projects/fam/
http://www.gnome.org/~veillard/gamin/overview.html
Many UNIXes have platform-specific ways to do this too.
DS
| |
|
| James Johnson wrote:
> On Tue, 28 Dec 2004 18:13:47 +0100, DINH Viet Hoa
> <dinh.viet.hoa@free.fr> wrote:
>
>
>
> tail is a shell command. I want to do this in C.
I think the point here is that 'tail' is written in C...
Heiko
| |
| Maurizio Loreti 2004-12-29, 3:58 pm |
| Heiko <heiko.noordhof_A_xs4all.nl> writes:
> I think the point here is that 'tail' is written in C...
Are you asserting that this is required by POSIX? Are you asserting
that a 'tail' implementation *must* be written in C --- and not C++,
FORTRAN or awk or any other language?
--
Maurizio Loreti http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy ROT13: ybergv@cq.vasa.vg
| |
| Stefaan A Eeckels 2004-12-29, 3:58 pm |
| On 29 Dec 2004 14:38:55 +0100
Maurizio Loreti <mlo@foobar.it> wrote:
> Are you asserting that this is required by POSIX? Are you asserting
> that a 'tail' implementation *must* be written in C --- and not C++,
> FORTRAN or awk or any other language?
Your ability to read between the lines rivals the
soothsayer's art of glimpsing the future from rabbit
entrails - and is equally accurate.
--
Stefaan
--
As complexity rises, precise statements lose meaning,
and meaningful statements lose precision. -- Lotfi Zadeh
| |
|
| Maurizio Loreti wrote:
>
>
> Are you asserting that this is required by POSIX? Are you asserting
> that a 'tail' implementation *must* be written in C --- and not C++,
> FORTRAN or awk or any other language?
>
Of course not.
Try re-reading the thread if you don't understand what I meant to say.
Heiko
| |
| David Schwartz 2004-12-29, 8:57 pm |
|
"Maurizio Loreti" <mlo@foobar.it> wrote in message
news:rmacrx6x74.fsf@mlinux.pd.infn.it...
> Heiko <heiko.noordhof_A_xs4all.nl> writes:
[color=darkred]
> Are you asserting that this is required by POSIX? Are you asserting
> that a 'tail' implementation *must* be written in C --- and not C++,
> FORTRAN or awk or any other language?
Umm, no, he's asserting that 'tail' is in fact written in C. In fact,
you could even look at the source code to see how it does it.
DS
| |
| Barry Margolin 2004-12-30, 3:58 am |
| In article <rmacrx6x74.fsf@mlinux.pd.infn.it>,
Maurizio Loreti <mlo@foobar.it> wrote:
> Heiko <heiko.noordhof_A_xs4all.nl> writes:
>
>
> Are you asserting that this is required by POSIX? Are you asserting
> that a 'tail' implementation *must* be written in C --- and not C++,
> FORTRAN or awk or any other language?
I think he's asserting that most tail implementations *are* written in
C. So if you want to know how experienced Unix programmers would do
this, take a look at the source code of tail.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
| |
|
| Barry Margolin wrote:
> In article <rmacrx6x74.fsf@mlinux.pd.infn.it>,
> Maurizio Loreti <mlo@foobar.it> wrote:
>
>
>
>
> I think he's asserting that most tail implementations *are* written in
> C. So if you want to know how experienced Unix programmers would do
> this, take a look at the source code of tail.
>
(Obviously) correct.
I'm glad more people did get it than not.
Heiko
| |
| gopakita 2004-12-30, 6:16 pm |
| quote: Originally posted by James Johnson
I need to do something like this, but get the read (fgets in this case)
to block until there is a new line of data. Sort of like tail -f.
FILE *instream = fopen(fname, "rt");
if (instream==NULL) {
return 0;
}
fs (instream, 0L, SEEK_END);
while(1) {
cptr = fgets(buf, sizeof(buf), instream);
if (cptr==NULL) {
printf("exiting because there is no data\n");
break;
}
printf(cptr);
}
fclose(instream);
How can this be done in unix?
Jim
I'd try to ls ahead of EOF and select/pselect on the file descriptor
you may also play with O_NONBLOCK | |
| gopakita 2004-12-31, 12:46 am |
| quote: Originally posted by gopakita
I'd try to ls ahead of EOF and select/pselect on the file descriptor
you may also play with O_NONBLOCK
Apparently this approach doesn't work :(
May be there is some ioctl option? Could't find any suitable ... :( |
|
|
|
|