Mail Archives: djgpp-workers/2001/03/16/19:44:18
This version shrinks _write.c by merging some code. And the fill gap code
should now work with any handle. I don't see any issues with FSEXTs since any
FSEXTs will always be called prior to any of the fill gap support work is
done.
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/17 00:23:07
*************** extern "C" {
*** 13,20 ****
#ifndef _POSIX_SOURCE
/* Delete file when the last descriptor referencing it is closed. */
! #define FILE_DESC_TEMPORARY 0x01
typedef struct fd_properties fd_properties;
struct fd_properties
--- 13,24 ----
#ifndef _POSIX_SOURCE
/* 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_ZERO_FILL_EOF_GAP 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/17 00:23:13
***************
*** 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,17 ****
--- 8,21 ----
#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)
{
__dpmi_regs r;
+ int has_props;
+
__FSEXT_Function *func = __FSEXT_get_function(handle);
if (func)
{
*************** lseek(int handle, off_t offset, int when
*** 31,35 ****
--- 35,51 ----
errno = __doserr_to_errno(r.x.ax);
return -1;
}
+
+ has_props = __has_fd_properties(handle);
+ if (offset > 0)
+ {
+ if (!has_props)
+ has_props = (__set_fd_properties(handle, NULL, 0) == 0);
+ if (has_props)
+ __set_fd_flags(handle, FILE_DESC_ZERO_FILL_EOF_GAP);
+ }
+ else if (has_props && (whence == SEEK_SET || whence == SEEK_END))
+ __clear_fd_flags(handle, FILE_DESC_ZERO_FILL_EOF_GAP);
+
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/17 00:23:19
***************
*** 1,3 ****
--- 1,5 ----
+
+ /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */
/*
* File llseek.c.
*
***************
*** 14,25 ****
#include <errno.h>
#include <libc/dosio.h>
#include <sys/fsext.h>
!
offset_t
llseek( int handle, offset_t offset, int whence )
{
__dpmi_regs r;
__FSEXT_Function *func = __FSEXT_get_function(handle);
if( func )
--- 16,28 ----
#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 )
{
__dpmi_regs r;
+ int has_props;
__FSEXT_Function *func = __FSEXT_get_function(handle);
if( func )
*************** llseek( int handle, offset_t offset, int
*** 42,47 ****
--- 45,62 ----
errno = __doserr_to_errno(r.x.ax);
return -1;
}
+
+ has_props = __has_fd_properties(handle);
+ if (offset > 0)
+ {
+ if (!has_props)
+ has_props = (__set_fd_properties(handle, NULL, 0) == 0);
+ if (has_props)
+ __set_fd_flags(handle, FILE_DESC_ZERO_FILL_EOF_GAP);
+ }
+ else if (has_props && (whence == SEEK_SET || whence == SEEK_END))
+ __clear_fd_flags(handle, FILE_DESC_ZERO_FILL_EOF_GAP);
+
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/17 00:23:25
***************
*** 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_ZERO_FILL_EOF_GAP))
+ {
+ 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/17 00:23:31
***************
*** 10,24 ****
#include <sys/fsext.h>
#include <libc/dosio.h>
int
_write(int handle, const void* buffer, size_t count)
{
- size_t j, i;
- int nput;
- unsigned long tbsize;
- __dpmi_regs r;
-
__FSEXT_Function *func = __FSEXT_get_function(handle);
if (func)
{
--- 10,25 ----
#include <sys/fsext.h>
#include <libc/dosio.h>
+ #include <libc/fd_props.h>
+ #include <libc/farptrgs.h>
+ int _write_fill_seek_gap(int fd);
+
+ static int write_int(int fd, const char *buffer, size_t count);
+
int
_write(int handle, const void* buffer, size_t count)
{
__FSEXT_Function *func = __FSEXT_get_function(handle);
if (func)
{
*************** _write(int handle, const void* buffer, s
*** 27,60 ****
return rv;
}
tbsize = _go32_info_block.size_of_transfer_buffer;
! nput = 0;
! do {
! j = (count <= tbsize) ? count : tbsize;
! if (j)
! dosmemput(buffer, j, __tb);
r.x.ax = 0x4000;
! r.x.bx = handle;
! r.x.cx = j;
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;
}
! i = r.x.ax;
! count -= i;
! buffer = (void *)((int)buffer + i);
! nput += i;
! } while(count && (i == j));
! if (count && nput == 0)
{
errno = ENOSPC;
return -1;
}
! return nput;
}
--- 28,139 ----
return rv;
}
+ if (__has_fd_properties(handle)
+ && (__fd_properties[handle]->flags & FILE_DESC_ZERO_FILL_EOF_GAP))
+ {
+ if (_write_fill_seek_gap(handle) < 0)
+ return -1;
+ }
+
+ return write_int(handle, buffer, count);
+ }
+
+ /* 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;
+
+ __clear_fd_flags(fd, FILE_DESC_ZERO_FILL_EOF_GAP);
+
+ if (isatty(fd))
+ return 0;
+
+ /* Quit when unable to get the file length. */
+ eof_off = lfilelength (fd);
+ if (eof_off < 0)
+ return 0;
+
+ /* Quit when unable to get the current file offset. */
+ cur_off = llseek (fd, 0, SEEK_CUR);
+ if (cur_off < 0)
+ return 0;
+
+ /* Quit 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 0;
+
+ /* Clear once again because the llseek call above will
+ set the fill test flag. */
+ __clear_fd_flags(fd, FILE_DESC_ZERO_FILL_EOF_GAP);
+
+ /* 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;
! }
!
! return write_int(fd, NULL, fill_count);
! }
!
!
! static int
! write_int(int fd, const char *buffer, size_t write_count)
! {
! unsigned long buf_size, tb_size;
! unsigned long chunk_count;
! int total_written;
! unsigned short bytes_written;
! __dpmi_regs r;
!
! tb_size = _go32_info_block.size_of_transfer_buffer;
! buf_size = (write_count > tb_size) ? tb_size : write_count;
!
! total_written = 0;
! do
! {
! chunk_count = (write_count <= buf_size) ? write_count : buf_size;
! if (buffer && chunk_count)
! dosmemput(buffer, chunk_count, __tb);
r.x.ax = 0x4000;
! r.x.bx = fd;
! r.x.cx = chunk_count;
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;
}
! bytes_written = r.x.ax;
! write_count -= bytes_written;
! total_written += bytes_written;
! if (buffer)
! buffer += bytes_written;
! } while (write_count && (chunk_count == bytes_written));
! if (write_count && total_written == 0)
{
errno = ENOSPC;
return -1;
}
! return total_written;
}
- Raw text -