/* Reentrant versions of write system call. */ #include #include #include <_syslist.h> #include #include #include /* Some targets provides their own versions of this functions. Those targets should define REENTRANT_SYSCALLS_PROVIDED in TARGET_CFLAGS. */ #ifdef _REENT_ONLY #ifndef REENTRANT_SYSCALLS_PROVIDED #define REENTRANT_SYSCALLS_PROVIDED #endif #endif #ifndef REENTRANT_SYSCALLS_PROVIDED /* We use the errno variable used by the system dependent layer. */ /* FUNCTION <<_write_r>>---Reentrant version of write INDEX _write_r ANSI_SYNOPSIS #include _ssize_t _write_r(struct _reent *<[ptr]>, int <[fd]>, const void *<[buf]>, size_t <[cnt]>); TRAD_SYNOPSIS #include _ssize_t _write_r(<[ptr]>, <[fd]>, <[buf]>, <[cnt]>) struct _reent *<[ptr]>; int <[fd]>; char *<[buf]>; size_t <[cnt]>; DESCRIPTION This is a reentrant version of <>. It takes a pointer to the global data block, which holds <>. */ #define _WRITE 0x0002 /* file opened for writing */ #define _APPEND 0x0080 /* file opened for append */ #define _BINARY 0x0040 /* file is binary, skip CRLF processing */ #define _ISTTY 0x2000 /* is console device */ #define _FILEEXT 0x8000 /* lseek with positive offset has been done */ #define __handle_check( __h, __r ) \ if( (__h) < 0 || (__h) > __NFiles ) { \ ptr->_errno = EBADF; \ return( __r ); \ } extern unsigned __NFiles; #define PAD_SIZE 512 static int zero_pad(struct _reent *ptr, int handle ) /* 09-jan-95 */ /*******************************/ { int rc; long curPos, eodPos; long bytesToWrite; unsigned writeAmt; char zeroBuf[PAD_SIZE]; // Pad with zeros due to lseek() past EOF (POSIX) curPos = _lseek_r( ptr, handle, 0L, SEEK_CUR ); /* current offset */ if( curPos == -1 ) return( -1 ); eodPos = _lseek_r( ptr, handle, 0L, SEEK_END ); /* end of data offset */ if( eodPos == -1 ) return( -1 ); if( curPos > eodPos ) { bytesToWrite = curPos - eodPos; /* amount to pad by */ if( bytesToWrite > 0 ) { /* only write if needed */ memset( zeroBuf, 0x00, PAD_SIZE ); /* zero out a buffer */ do { /* loop until done */ if( bytesToWrite > PAD_SIZE ) writeAmt = 512; else writeAmt = (unsigned)bytesToWrite; rc = _write_r(ptr, handle, zeroBuf, writeAmt ); if( rc < 0 ) return( rc ); bytesToWrite -= writeAmt; /* more bytes written */ } while( bytesToWrite != 0 ); } } else { curPos = _lseek_r( ptr, handle, curPos, SEEK_SET ); if( curPos == -1 ) { return( -1 ); } } return( 0 ); /* return success code */ } static int os_write(struct _reent *ptr, int handle, const void *buffer, unsigned len, unsigned *amt ) /********************************************************************************/ { __file_handle *fh; int rc; rc = 0; *amt = 0; fh = (__file_handle*) __getOSHandle( handle ); rc = fh->write(fh->name,buffer,fh->offset,len,amt); fh->offset+= *amt; if( *amt != len ) { rc = ENOSPC; ptr->_errno = ENOSPC; } return( rc ); } _ssize_t _DEFUN (_write_r, (ptr, fd, buffer, cnt), struct _reent *ptr _AND int fd _AND _CONST _PTR buffer _AND size_t cnt) { _ssize_t ret; unsigned int iomode_flags; unsigned len_written, i, j; int rc2; char *buf; __file_handle *fh; __handle_check( fd, -1 ); iomode_flags = __GetIOMode( fd ); if( iomode_flags == 0 ) { ptr->_errno = EBADF; return( -1 ); } if( !(iomode_flags & _WRITE) ) { ptr->_errno = EACCES ; /* changed from EBADF to EACCES 23-feb-89 */ return( -1 ); } if( (iomode_flags & _APPEND) && !(iomode_flags & _ISTTY) ) { fh->offset = _lseek_r(ptr, fd, 0L, SEEK_END ); /* end of data offset */ } len_written = 0; rc2 = 0; // Pad the file with zeros if necessary if( iomode_flags & _FILEEXT ) { // turn off file extended flag __SetIOMode_nogrow( fd, iomode_flags&(~_FILEEXT) ); // It is not required to pad a file with zeroes on an NTFS file system; // unfortunately it is required on FAT (and probably FAT32). (JBS) rc2 = zero_pad( ptr, fd ); } if( rc2 == 0 ) { if( iomode_flags & _BINARY ) { /* if binary mode */ rc2 = os_write(ptr, fd, buffer, cnt, &len_written ); /* end of binary mode part */ } else { /* text mode */ int buf_size = 512; buf = (char*)alloca( buf_size ); j = 0; for( i = 0; i < cnt; ) { if( ((const char*)buffer)[i] == '\n' ) { buf[j] = '\r'; ++j; if( j == buf_size ) { rc2 = os_write(ptr, fd, buf, buf_size, &j ); if( rc2 == -1 ) break; len_written += j; if( rc2 == ENOSPC ) break; len_written = i; j = 0; } } buf[j] = ((const char*)buffer)[i]; ++i; ++j; if( j == buf_size ) { rc2 = os_write(ptr, fd, buf, buf_size, &j ); if( rc2 == -1 ) break; len_written += j; if( rc2 == ENOSPC ) break; len_written = i; j = 0; } } if( j ) { rc2 = os_write(ptr, fd, buf, j, &i ); if( rc2 == ENOSPC ) { len_written += i; } else { len_written = cnt; } } /* end of text mode part */ } } if( rc2 == -1 ) { return( rc2 ); } else { return( len_written ); } } _ssize_t _DEFUN (write, ( fd, buffer, cnt), int fd _AND _CONST _PTR buffer _AND size_t cnt) { return _write_r(_REENT, fd, buffer, cnt); } #endif /* ! defined (REENTRANT_SYSCALLS_PROVIDED) */