[Patch]: Truncate

Pierre A. Humblet pierre@phumblet.no-ip.org
Sun Aug 22 21:13:00 GMT 2004

At 05:55 PM 8/22/2004 +0200, you wrote:
>Hi Pierre,
>Looks good to me.  But wouldn't it be better to fill in the zeros only
>if SetEndOfFile succeeded?  That would avoid a lengthy write operation
>if the application was, say, too optimistic about the space left on disk.

In that case we can't reuse the code already present in ::write
because when ::write calls GetFileSize it will get the length
already updated by SetEndOfFile.

The way ::write is written, it will restore the FilePointer at
the beginning of the 0 filled region if the disk gets full. But
because 0's may have been written, the EOF may have moved and the
file may have been extended.
When ftruncate calls SetEndOfFile, it will succeed and truncate
the file back to its original position. That's OK, but it should
then return an error. See updated patch below. 

As an aside, should ::write also call SetEndOfFile to truncate the
0's it has written? What do Cygwin on NT and Linux do when lseek
has been optimistic (and sparse files are off)?


2004-08-23  Pierre Humblet <pierre.humblet@ieee.org>
 	* syscalls.cc (ftruncate64): On 9x, call write with a zero length
 	to zero fill when the file is extended.

Index: syscalls.cc
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v
retrieving revision 1.342
diff -u -p -r1.342 syscalls.cc
--- syscalls.cc 3 Aug 2004 14:37:26 -0000       1.342
+++ syscalls.cc 22 Aug 2004 21:00:49 -0000
@@ -1675,7 +1675,7 @@ setmode (int fd, int mode)
 extern "C" int
 ftruncate64 (int fd, _off64_t length)
-  int res = -1;
+  int res = -1, res_bug = 0;
   if (length < 0)
     set_errno (EINVAL);
@@ -1692,10 +1692,15 @@ ftruncate64 (int fd, _off64_t length)
              _off64_t prev_loc = cfd->lseek (0, SEEK_CUR);
              cfd->lseek (length, SEEK_SET);
+             /* Fill the space with 0, if needed */
+             if (wincap.has_lseek_bug ())
+               res_bug = cfd->write (&res, 0);
+             /* In the lseek_bug case, this may restore the file to
+                its initial length */
              if (!SetEndOfFile (h))
                __seterrno ();
-               res = 0;
+               res = res_bug;
              /* restore original file pointer location */
              cfd->lseek (prev_loc, SEEK_SET);

More information about the Cygwin-patches mailing list