[comp.unix.questions] Truncating an open file under BSD 4.3

badri@valhalla.ee.rochester.edu (Badri Lokanathan) (07/26/88)

What is the best way to empty an already open write-only file under BSD 4.3?
I have an application where I need large amounts of alphanumeric data dumped
to a file which then must be periodically emptied. I also need to be
able to scan this data occasionally with a pager.

I do not want to close and reopen the file since open is an
expensive call (prof claims it to take about 15ms/call on a SUN
3/110.) I tried truncate but it leaves holes in the file, which make
it unreadable. I also could not find a way with fcntl, which surprises me.
-- 
"We will fight for the right to be free {) badri@valhalla.ee.rochester.edu
 We will build our own society         //\\ {ames,cmcl2,columbia,cornell,
 And we will sing, we will sing       ///\\\ garp,harvard,ll-xn,rutgers}!
 We will sing our own song."  -UB40    _||_   rochester!ur-valhalla!badri

guy@gorodish.Sun.COM (Guy Harris) (07/26/88)

> What is the best way to empty an already open write-only file under BSD 4.3?

If by "empty" you mean "reduce to zero length", use "ftruncate".

> I tried truncate but it leaves holes in the file, which make
> it unreadable.

You must have done it wrong.  Note that, even though "ftruncate(fd, 0L)"
truncates the file to zero length, it does NOT move the seek pointer; thus,

	write(fd, lots of data, how much data);
	...
	ftruncate(fd, 0L);
	write(fd, more data, how much more data);

will NOT put the "more data" at the beginning of the file, but will put it at
the same place it would have had the "ftruncate" not been done; this results in
a hole of size equal to the size of the file before the "ftruncate".  Do an
"lseek(fd, 0L, 0)" after the "ftruncate".

Note that if you're using standard I/O to write to the file, you probably have
to "fflush" the file before doing the "ftruncate".

> I also could not find a way with fcntl, which surprises me.

Why?  "fcntl" was originally intended to manipulate descriptors, not the
objects they referred to; subsequently, "fcntl" has turned into something
similar to "ioctl" but different (e.g., it's used for file locking - I'm not
sure what the *intended* difference between "fcntl" and "ioctl" is), but
nobody's made "fcntl" do file truncation - yet.

chris@mimsy.UUCP (Chris Torek) (07/27/88)

In article <1392@valhalla.ee.rochester.edu> badri@valhalla.ee.rochester.edu
(Badri Lokanathan) writes:
>What is the best way to empty an already open write-only file under BSD 4.3?
>... I tried truncate but it leaves holes in the file, which make
>it unreadable.

You were on the right track.  truncate (or better, ftruncate) does not
`leave holes in the file'; rather, the sequence

	open
	seek
	write

`leave(s) holes in the file'.  Likewise, the sequence

	open
	write (moves seek pointer)
	ftruncate
	write

will create holes, since the second `write' is not at the beginning
of the file.  Hence the proper sequence is

	(void) ftruncate(fd, 0L);
	(void) lseek(fd, 0L, 0);
	/* in either order */

or (if using stdio)

	(void) fflush(fp);
	(void) fseek(fp, 0L, 0);
	(void) ftruncate(fileno(fp), 0L);
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

rbj@nav.icst.nbs.gov (Root Boy Jim) (07/28/88)

? From: Badri Lokanathan <badri@valhalla.ee.rochester.edu>

? What is the best way to empty an already open write-only file under BSD 4.3?

Guy Harris answered most of your questions, so I won't repeat what he said...

? I tried truncate but it leaves holes in the file, which make
? it unreadable.

...but he didn't address this point. I find this hard to believe. Holes
are supposed to be read as blocks of zeros. Maybe you tried to read
after the truncate without changing the seek pointer?

? "We will fight for the right to be free {) badri@valhalla.ee.rochester.edu
?  We will build our own society         //\\ {ames,cmcl2,columbia,cornell,
?  And we will sing, we will sing       ///\\\ garp,harvard,ll-xn,rutgers}!
?  We will sing our own song."  -UB40    _||_   rochester!ur-valhalla!badri

	(Root Boy) Jim Cottrell	<rbj@icst-cmr.arpa>
	National Bureau of Standards
	Flamer's Hotline: (301) 975-5688
	The opinions expressed are solely my own
	and do not reflect NBS policy or agreement
	Careful with that VAX Eugene!

badri@valhalla.ee.rochester.edu (Badri Lokanathan) (07/28/88)

In article <1392@valhalla.ee.rochester.edu>, I wrote:
> What is the best way to empty an already open write-only file under BSD 4.3?
> ... 
> 3/110.) I tried truncate but it leaves holes in the file, which make
> it unreadable.

Thanks to all who posted the right solution (fflush-ftruncate-lseek)
This was exactly what I had planned to check out; unfortunately I coded my
test program incorrectly (never code just before dinner time :-) causing
strange things to happen.

Hoping sys V has some equivalent form of ftruncate ....
-- 
"Don't blame me for wanting more         {) badri@valhalla.ee.rochester.edu
 The facts are too hard to ignore       //\\ {ames,cmcl2,columbia,cornell,
 I'm scared to death of poverty        ///\\\ garp,harvard,ll-xn,rutgers}!
 I only want what's best for me."-UB40   /\    rochester!ur-valhalla!badri

mre@beatnix.UUCP (Mike Eisler) (07/28/88)

In article <61401@sun.uucp> guy@gorodish.Sun.COM (Guy Harris) writes:
>
>> I also could not find a way [to truncate] with fcntl, which surprises me.
>
>Why?  "fcntl" was originally intended to manipulate descriptors, not the
>objects they referred to; subsequently, "fcntl" has turned into something
>similar to "ioctl" but different (e.g., it's used for file locking - I'm not
>sure what the *intended* difference between "fcntl" and "ioctl" is), but
>nobody's made "fcntl" do file truncation - yet.

AT&T's UN*X System V Release 3.1 does do file truncation with fcntl().
By using the same flock struct that F_SETLK, and F_GETLK use, the
intent appears to allow truncation even in the middle of the file (just
as record locks can be in the middle), but currently this isn't
implemented.  You can only truncate to the end of the file. The name
of the command is F_FREESP.

	-Mike Eisler
	{sun, uunet}!elxsi!mre

guy@gorodish.Sun.COM (Guy Harris) (07/28/88)

> Hoping sys V has some equivalent form of ftruncate ....

No current S5 releases from AT&T do, although some S5 systems may have added
it.

jerry@olivey.olivetti.com (Jerry Aguirre) (08/03/88)

In article <12684@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>
>	open
>	write (moves seek pointer)
>	ftruncate
>	write
>
>will create holes, since the second `write' is not at the beginning

What is interesting is that even if the open file has been placed in
FAPPEND mode there will still be holes.  I view this as a bug.  FAPPEND
is defined as possitioning each write at the end of the file, even if
some other process has changed where the end is located.  Certainly
truncating a file to zero length should be considered changing where the
file ends.
					Jerry Aguirre

chris@mimsy.UUCP (Chris Torek) (08/03/88)

-In article <12684@mimsy.UUCP> I wrote that the sequence
->	open
->	write (moves seek pointer)
->	ftruncate
->	write
->will create holes, since the second `write' is not at the beginning

In article <26556@oliveb.olivetti.com> jerry@olivey.olivetti.com
(Jerry Aguirre) notes:
-What is interesting is that even if the open file has been placed in
-FAPPEND mode there will still be holes.  I view this as a bug.

Fixed in 4.3BSD-tahoe (if not earlier).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris