www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/03/13/14:00:07

From: "Mark E." <snowball3 AT bigfoot DOT com>
To: djgpp-workers AT delorie DOT com
Date: Tue, 13 Mar 2001 13:59:57 -0500
MIME-Version: 1.0
Subject: zero fill the eof gap (complete patch)
Message-ID: <3AAE27DD.8570.57C673@localhost>
X-mailer: Pegasus Mail for Win32 (v3.12c)
Reply-To: djgpp-workers AT delorie DOT com

Hi guys,

Below is the complete patch for filling the 'EOF gap'. I added write.c and 
llseek.c to this patch in case there are problems I didn't catch. The only 
changes were to add and revise some comments. I assume a blurb for wc204.txi 
is appropriate since this solves a problem that keeps coming up on c.o.m.d.

Index: include/libc/fd_props.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/libc/fd_props.h,v
retrieving revision 1.1
diff -c -p -r1.1 fd_props.h
*** fd_props.h	2001/03/07 05:34:26	1.1
--- fd_props.h	2001/03/13 18:47:06
*************** extern "C" {
*** 15,20 ****
--- 15,24 ----
  /* Delete file when the last descriptor referencing it is closed.  */
  #define FILE_DESC_TEMPORARY 0x01
  
+ /* Tell write and _write to test for file offset greater than EOF.  If so,
+    they will fill the gap with zeroes.  */
+ #define FILE_DESC_FILL_TEST 0x02
+ 
  typedef struct fd_properties fd_properties;
  
  struct fd_properties
*************** int __clear_fd_properties(int _fd);
*** 35,40 ****
--- 39,54 ----
  static __inline__ int __has_fd_properties(int _fd)
  {
    return __fd_properties && __fd_properties[_fd];
+ }
+ 
+ static __inline__ void __set_fd_flags(int _fd, unsigned long _flags)
+ {
+   __fd_properties[_fd]->flags |= _flags;  
+ }
+ 
+ static __inline__ void __clear_fd_flags(int _fd, unsigned long _flags)
+ {
+   __fd_properties[_fd]->flags &= ~_flags;
  }
  
  #endif /* !_POSIX_SOURCE */
Index: src/libc/posix/unistd/lseek.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/unistd/lseek.c,v
retrieving revision 1.2
diff -c -p -r1.2 lseek.c
*** lseek.c	1998/06/28 17:29:36	1.2
--- lseek.c	2001/03/13 18:47:55
***************
*** 1,3 ****
--- 1,4 ----
+ /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  #include <libc/stubs.h>
***************
*** 7,12 ****
--- 8,14 ----
  #include <dpmi.h>
  #include <sys/fsext.h>
  #include <libc/dosio.h>
+ #include <libc/fd_props.h>
  
  off_t
  lseek(int handle, off_t offset, int whence)
*************** lseek(int handle, off_t offset, int when
*** 31,35 ****
--- 33,48 ----
      errno = __doserr_to_errno(r.x.ax);
      return -1;
    }
+ 
+   if (__has_fd_properties(handle))
+   {
+     /* Set the fill test flag when the file pointer may move past EOF.
+        Clear the fill test flag when the file pointer can't be past EOF. */
+     if (offset > 0)
+       __set_fd_flags(handle, FILE_DESC_FILL_TEST);
+     else if (whence == SEEK_SET || whence == SEEK_END)
+       __clear_fd_flags(handle, FILE_DESC_FILL_TEST);
+   }
+     
    return (r.x.dx << 16) + r.x.ax;
  }
Index: src/libc/compat/unistd/llseek.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/compat/unistd/llseek.c,v
retrieving revision 1.1
diff -c -p -r1.1 llseek.c
*** llseek.c	2000/06/19 18:00:56	1.1
--- llseek.c	2001/03/13 18:48:18
***************
*** 1,3 ****
--- 1,4 ----
+ /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
  /*
   * File llseek.c.
   *
***************
*** 14,21 ****
  #include <errno.h>
  #include <libc/dosio.h>
  #include <sys/fsext.h>
  
- 
  offset_t
  llseek( int handle, offset_t offset, int whence )
  {
--- 15,22 ----
  #include <errno.h>
  #include <libc/dosio.h>
  #include <sys/fsext.h>
+ #include <libc/fd_props.h>
  
  offset_t
  llseek( int handle, offset_t offset, int whence )
  {
*************** llseek( int handle, offset_t offset, int
*** 41,46 ****
--- 42,57 ----
    {
      errno = __doserr_to_errno(r.x.ax);
      return -1;
+   }
+ 
+   if (__has_fd_properties(handle))
+   {
+     /* Set the fill test flag when the file pointer may move past EOF.
+        Clear the fill test flag when the file pointer can't be past EOF. */
+     if (offset > 0)
+       __set_fd_flags(handle, FILE_DESC_FILL_TEST);
+     else if (whence == SEEK_SET || whence == SEEK_END)
+       __clear_fd_flags(handle, FILE_DESC_FILL_TEST);
    }
    return( ( ( (unsigned)r.x.dx ) << 16) + r.x.ax );
  }
Index: src/libc/posix/unistd/write.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/unistd/write.c,v
retrieving revision 1.3
diff -c -p -r1.3 write.c
*** write.c	1997/08/31 17:49:14	1.3
--- write.c	2001/03/13 18:50:48
***************
*** 1,3 ****
--- 1,4 ----
+ /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
***************
*** 12,23 ****
--- 13,27 ----
  #include <sys/fsext.h>
  #include <libc/dosio.h>
  #include <libc/ttyprvt.h>
+ #include <libc/fd_props.h>
  
  #define tblen _go32_info_block.size_of_transfer_buffer
  
  int (*__libc_write_termios_hook)(int handle, const void *buffer, size_t 
count,
  				 ssize_t *rv) = NULL;
  
+ int _write_fill_seek_gap(int fd);
+ 
  ssize_t
  write(int handle, const void* buffer, size_t count)
  {
*************** write(int handle, const void* buffer, si
*** 45,50 ****
--- 49,61 ----
       func(__FSEXT_write, &rv, &handle)) /* ... call extension ... */
        return rv;			/* ... and exit if handled. */
  
+   if (__has_fd_properties(handle)
+       && (__fd_properties[handle]->flags & FILE_DESC_FILL_TEST))
+   {
+     if (_write_fill_seek_gap(handle) < 0)
+       return -1;
+   }
+       
    while (offset_into_buf < count)
    {
      _farsetsel(_dos_ds);
Index: src/libc/dos/io/_write.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/dos/io/_write.c,v
retrieving revision 1.3
diff -c -p -r1.3 _write.c
*** _write.c	1996/10/24 23:26:26	1.3
--- _write.c	2001/03/13 18:50:55
***************
*** 10,16 ****
--- 10,20 ----
  #include <sys/fsext.h>
  
  #include <libc/dosio.h>
+ #include <libc/fd_props.h>
+ #include <libc/farptrgs.h>
  
+ int _write_fill_seek_gap(int fd);
+ 
  int
  _write(int handle, const void* buffer, size_t count)
  {
*************** _write(int handle, const void* buffer, s
*** 27,32 ****
--- 31,43 ----
        return rv;
    }
  
+   if (__has_fd_properties(handle)
+       && (__fd_properties[handle]->flags & FILE_DESC_FILL_TEST))
+   {
+     if (_write_fill_seek_gap(handle) < 0)
+       return -1;
+   }
+       
    tbsize = _go32_info_block.size_of_transfer_buffer;
    nput = 0;
    do {
*************** _write(int handle, const void* buffer, s
*** 58,60 ****
--- 69,153 ----
  
    return nput;
  }
+ 
+ /* If the file pointer offset is beyond EOF, fill the gap between EOF and
+    the file pointer offset with zeroes.  This emulates the behavior 
described
+    in the POSIX documentation for lseek.  */
+ int
+ _write_fill_seek_gap(int fd)
+ {
+   offset_t eof_off, cur_off, fill_count;
+   unsigned long tbsize, buf_size;
+   unsigned long i, write_size, out_count;
+   __dpmi_regs r;
+ 
+   __clear_fd_flags(fd, FILE_DESC_FILL_TEST);
+   
+   if (isatty(fd))
+     return -1;
+   
+   /* Quit when unable to get the file length.  */    
+   eof_off = lfilelength (fd);
+   if (eof_off < 0)
+     return -1;
+   
+   /* Quit when unable to get the current file offset.  */
+   cur_off = llseek (fd, 0, SEEK_CUR);
+   if (cur_off < 0)
+     return -1;
+ 
+   /* Quit (but return success) if the current offset is not past EOF.  */
+   if (cur_off <= eof_off)
+     return 0;
+     
+   /* Quit when unable to seek to EOF.  */
+   if (llseek (fd, eof_off, SEEK_SET) == -1)
+     return -1;
+ 
+   /* Clear once again because the llseek call above will
+      set the fill test flag.  */
+   __clear_fd_flags(fd, FILE_DESC_FILL_TEST);
+   
+   /* Fill the transfer buffer with zeros.  */
+   tbsize = _go32_info_block.size_of_transfer_buffer;
+   fill_count = cur_off - eof_off;
+ 
+   buf_size = (fill_count > tbsize) ? tbsize : fill_count;
+ 
+   i = 0;
+   _farsetsel(_dos_ds);
+   while (i < buf_size)
+   {
+     _farnspokel(__tb + i, 0);
+     i += 4;
+   }
+ 
+   /* Write out the zeros.  */
+   out_count = 0;
+   do
+   {
+     r.x.ax = 0x4000;
+     r.x.bx = fd;
+     write_size = (fill_count > buf_size) ? buf_size : fill_count;
+     r.x.cx = write_size;
+     r.x.dx = __tb & 15;
+     r.x.ds = __tb / 16;
+     __dpmi_int (0x21, &r);
+     if (r.x.flags & 1)
+     {
+       errno =__doserr_to_errno (r.x.ax);
+       return -1;
+     }
+     fill_count -= r.x.ax;
+     out_count += r.x.ax;
+   } while (fill_count && (write_size == r.x.ax));
+ 
+   if (fill_count && out_count == 0)
+   {
+     errno = ENOSPC;
+     return -1;
+   }
+ 
+   return 0;
+ }
+ 

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019