From: "Mark E." To: djgpp-workers AT delorie DOT com Date: Tue, 13 Mar 2001 13:59:57 -0500 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT 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 *************** *** 7,12 **** --- 8,14 ---- #include #include #include + #include 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 #include #include - offset_t llseek( int handle, offset_t offset, int whence ) { --- 15,22 ---- #include #include #include + #include 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 #include #include + #include #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 #include + #include + #include + 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; + } +