Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /****************************************************************************
  2. *
  3. *                            Open Watcom Project
  4. *
  5. *    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
  6. *
  7. *  ========================================================================
  8. *
  9. *    This file contains Original Code and/or Modifications of Original
  10. *    Code as defined in and that are subject to the Sybase Open Watcom
  11. *    Public License version 1.0 (the 'License'). You may not use this file
  12. *    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
  13. *    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
  14. *    provided with the Original Code and Modifications, and is also
  15. *    available at www.sybase.com/developer/opensource.
  16. *
  17. *    The Original Code and all software distributed under the License are
  18. *    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  19. *    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
  20. *    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
  21. *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
  22. *    NON-INFRINGEMENT. Please see the License for the specific language
  23. *    governing rights and limitations under the License.
  24. *
  25. *  ========================================================================
  26. *
  27. * Description:  C Runtime write() and _lwrite() implementation.
  28. *
  29. ****************************************************************************/
  30.  
  31.  
  32. #include "variety.h"
  33. #include "int64.h"
  34. #include <stdio.h>
  35. #include <io.h>
  36. #include <fcntl.h>
  37. #include <malloc.h>
  38. #include <errno.h>
  39. #include <stddef.h>
  40. #include <string.h>
  41. #include "iomode.h"
  42. #include "fileacc.h"
  43. #include "rtcheck.h"
  44. #include "rtdata.h"
  45. #include "seterrno.h"
  46. #include "lseek.h"
  47.  
  48. /*
  49.     The _lwrite function writes data to the specified file.
  50.  
  51.     Note: This function is provided only for compatibility with 16-bit
  52.     versions of Windows. Win32-based applications should use the WriteFile
  53.     function.
  54.  
  55.     UINT _lwrite(
  56.       HFILE hFile,  // handle to file
  57.       LPCSTR lpBuffer,  // write data buffer
  58.       UINT uBytes   // number of bytes to write
  59.     );
  60.  */
  61.  
  62. extern  void    __STKOVERFLOW();
  63.  
  64. /*
  65.     Win32 Note:
  66.     Note that it is not an error to set the file pointer to a position
  67.     beyond the end of the file. The size of the file does not increase
  68.     until you call the SetEndOfFile, WriteFile, or WriteFileEx function. A
  69.     write operation increases the size of the file to the file pointer
  70.     position plus the size of the buffer written, leaving the intervening
  71.     bytes uninitialized.  Hence, the reason for zero-padding the file
  72.     to achieve POSIX conformance.
  73. */
  74.  
  75. /*
  76.     POSIX Note:
  77.     When writing to a file that does not support seek operations (pipe,
  78.     device, etc.), the O_APPEND flag is effectively ignored. POSIX does
  79.     not explicitly state this, but it is implied. Also, ESPIPE (illegal
  80.     seek error) is not listed for write(), only pwrite(). Hence we must
  81.     either not attempt to seek on such devices, or ignore the failures.
  82. */
  83.  
  84. #define PAD_SIZE 512
  85.  
  86. typedef union {
  87.     unsigned __int64    _64;
  88.     long                _32[2];
  89. } __i64;
  90.  
  91. static int zero_pad( int handle )           /* 09-jan-95 */
  92. /*******************************/
  93. {
  94.     int         rc;
  95.     long        curPos, eodPos;
  96.     long        bytesToWrite;
  97.     unsigned    writeAmt;
  98.     char        zeroBuf[PAD_SIZE];
  99.  
  100.     // Pad with zeros due to lseek() past EOF (POSIX)
  101.     curPos = __lseek( handle, 0L, SEEK_CUR );   /* current offset */
  102.     if( curPos == -1 )
  103.         return( -1 );
  104.     eodPos = __lseek( handle, 0L, SEEK_END );   /* end of data offset */
  105.     if( eodPos == -1 )
  106.         return( -1 );
  107.  
  108.     if( curPos > eodPos ) {
  109.         bytesToWrite = curPos - eodPos;         /* amount to pad by */
  110.  
  111.         if( bytesToWrite > 0 ) {                /* only write if needed */
  112.             memset( zeroBuf, 0x00, PAD_SIZE );  /* zero out a buffer */
  113.             do {                                /* loop until done */
  114.                 if( bytesToWrite > PAD_SIZE )
  115.                     writeAmt = 512;
  116.                 else
  117.                     writeAmt = (unsigned)bytesToWrite;
  118.                 rc = write( handle, zeroBuf, writeAmt );
  119.                 if( rc < 0 )
  120.                     return( rc );
  121.                 bytesToWrite -= writeAmt;       /* more bytes written */
  122.             } while( bytesToWrite != 0 );
  123.         }
  124.     } else {
  125.         curPos = __lseek( handle, curPos, SEEK_SET );
  126.         if( curPos == -1 ) {
  127.             return( -1 );
  128.         }
  129.     }
  130.  
  131.     return( 0 );                /* return success code */
  132. }
  133.  
  134. /*
  135.     The os_write function returns 0 meaning no error, -1 meaning error, or
  136.     ENOSPC meaning no space left on device.
  137. */
  138.  
  139. typedef struct
  140. {
  141.   char     *name;
  142.   unsigned int offset;
  143. }__file_handle;
  144.  
  145. int _stdcall write_file (const char *name,const void* buff,unsigned offset, unsigned count,unsigned *reads);
  146.  
  147. static int os_write( int handle, const void *buffer, unsigned len, unsigned *amt )
  148. /********************************************************************************/
  149. {
  150.     __file_handle *fh;
  151.     int         rc;
  152.  
  153.     rc = 0;
  154.    
  155.     fh = (__file_handle*) __getOSHandle( handle );
  156.      
  157.     if(write_file(fh->name,buffer,fh->offset,len,amt))
  158.     {
  159.        rc = __set_errno_nt();
  160.     };
  161.  
  162.  
  163.     if( *amt != len )
  164.     {
  165.         rc = ENOSPC;
  166.         __set_errno( rc );
  167.     }
  168.     return( rc );
  169. }
  170.  
  171.   _WCRTLINK int write( int handle, const void *buffer, unsigned len )
  172. /**********************************************************************/
  173. {
  174.     unsigned    iomode_flags;
  175.     char        *buf;
  176.     unsigned    buf_size;
  177.     unsigned    len_written, i, j;
  178.     int         rc2;
  179.  
  180.     __file_handle *fh;
  181.  
  182.     __handle_check( handle, -1 );
  183.     iomode_flags = __GetIOMode( handle );
  184.     if( iomode_flags == 0 )
  185.     {
  186.         __set_errno( EBADF );
  187.         return( -1 );
  188.     }
  189.    
  190.     if( !(iomode_flags & _WRITE) ) {
  191.         __set_errno( EACCES );     /* changed from EBADF to EACCES 23-feb-89 */
  192.         return( -1 );
  193.     }
  194.  
  195.     fh = (__file_handle*) __getOSHandle( handle );
  196.  
  197.     // put a semaphore around our writes
  198.  
  199.     _AccessFileH( handle );
  200.     if( (iomode_flags & _APPEND) && !(iomode_flags & _ISTTY) )
  201.     {
  202.       fh->offset = __lseek( handle, 0L, SEEK_END );   /* end of data offset */
  203.     }
  204.  
  205.     len_written = 0;
  206.     rc2 = 0;
  207.  
  208.     // Pad the file with zeros if necessary
  209.     if( iomode_flags & _FILEEXT ) {
  210.         // turn off file extended flag
  211.         __SetIOMode_nogrow( handle, iomode_flags&(~_FILEEXT) );
  212.  
  213.         // It is not required to pad a file with zeroes on an NTFS file system;
  214.         // unfortunately it is required on FAT (and probably FAT32). (JBS)
  215.         rc2 = zero_pad( handle );
  216.     }
  217.  
  218.     if( rc2 == 0 ) {
  219.         if( iomode_flags & _BINARY ) {  /* if binary mode */
  220.             rc2 = os_write( handle, buffer, len, &len_written );
  221.             /* end of binary mode part */
  222.         } else {    /* text mode */
  223.             i = stackavail();
  224.             if( i < 0x00b0 ) {
  225.                 __STKOVERFLOW();    /* not enough stack space */
  226.             }
  227.             buf_size = 512;
  228.             if( i < (512 + 48) ) {
  229.                 buf_size = 128;
  230.             }
  231.  
  232.             buf = __alloca( buf_size );
  233.            
  234.             j = 0;
  235.             for( i = 0; i < len; )
  236.             {
  237.                 if( ((const char*)buffer)[i] == '\n' )
  238.                 {
  239.                     buf[j] = '\r';
  240.                     ++j;
  241.                     if( j == buf_size )
  242.                     {
  243.                         rc2 = os_write( handle, buf, buf_size, &j );
  244.                         if( rc2 == -1 )
  245.                             break;
  246.                         len_written += j;
  247.                         if( rc2 == ENOSPC )
  248.                             break;
  249.                         len_written = i;
  250.                         j = 0;
  251.                     }
  252.                 }
  253.                 buf[j] = ((const char*)buffer)[i];
  254.                 ++i;
  255.                 ++j;
  256.                 if( j == buf_size ) {
  257.                     rc2 = os_write( handle, buf, buf_size, &j );
  258.                     if( rc2 == -1 )
  259.                         break;
  260.                     len_written += j;
  261.                     if( rc2 == ENOSPC )
  262.                         break;
  263.                     len_written = i;
  264.                     j = 0;
  265.                 }
  266.             }
  267.             if( j ) {
  268.                 rc2 = os_write( handle, buf, j, &i );
  269.                 if( rc2 == ENOSPC ) {
  270.                     len_written += i;
  271.                 } else {
  272.                     len_written = len;
  273.                 }
  274.             }
  275.             /* end of text mode part */
  276.         }
  277.     }
  278.     _ReleaseFileH( handle );
  279.     if( rc2 == -1 ) {
  280.         return( rc2 );
  281.     } else {
  282.         return( len_written );
  283.     }
  284. }
  285.  
  286.  
  287.