For Programmers: Free Programming Magazines  


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


Heiko

2004-12-29, 3:58 pm

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
Heiko

2004-12-29, 8:57 pm

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 ***
Heiko

2004-12-30, 8:57 am

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 ... :(
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com