Subversion Repositories Kolibri OS

Rev

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

  1. /* Reentrant versions of write system call. */
  2.  
  3. #include <reent.h>
  4. #include <unistd.h>
  5. #include <_syslist.h>
  6. #include <alloca.h>
  7. #include <errno.h>
  8. #include <string.h>
  9.  
  10.  
  11. /* Some targets provides their own versions of this functions.  Those
  12.    targets should define REENTRANT_SYSCALLS_PROVIDED in TARGET_CFLAGS.  */
  13.  
  14. #ifdef _REENT_ONLY
  15. #ifndef REENTRANT_SYSCALLS_PROVIDED
  16. #define REENTRANT_SYSCALLS_PROVIDED
  17. #endif
  18. #endif
  19.  
  20. #ifndef REENTRANT_SYSCALLS_PROVIDED
  21.  
  22. /* We use the errno variable used by the system dependent layer.  */
  23.  
  24. /*
  25. FUNCTION
  26.         <<_write_r>>---Reentrant version of write
  27.  
  28. INDEX
  29.         _write_r
  30.  
  31. ANSI_SYNOPSIS
  32.         #include <reent.h>
  33.         _ssize_t _write_r(struct _reent *<[ptr]>,
  34.                           int <[fd]>, const void *<[buf]>, size_t <[cnt]>);
  35.  
  36. TRAD_SYNOPSIS
  37.         #include <reent.h>
  38.         _ssize_t _write_r(<[ptr]>, <[fd]>, <[buf]>, <[cnt]>)
  39.         struct _reent *<[ptr]>;
  40.         int <[fd]>;
  41.         char *<[buf]>;
  42.         size_t <[cnt]>;
  43.  
  44. DESCRIPTION
  45.         This is a reentrant version of <<write>>.  It
  46.         takes a pointer to the global data block, which holds
  47.         <<errno>>.
  48. */
  49.  
  50.  
  51. #define _WRITE  0x0002  /* file opened for writing */
  52. #define _APPEND 0x0080  /* file opened for append */
  53. #define _BINARY 0x0040  /* file is binary, skip CRLF processing */
  54. #define _ISTTY  0x2000  /* is console device */
  55. #define _FILEEXT 0x8000 /* lseek with positive offset has been done */
  56.  
  57. #define __handle_check( __h, __r )                \
  58.         if( (__h) < 0  ||  (__h) > __NFiles ) {   \
  59.            ptr->_errno =  EBADF;                  \
  60.            return( __r );                         \
  61.         }
  62.  
  63. extern unsigned  __NFiles;
  64.  
  65. #define PAD_SIZE 512
  66.  
  67. static int zero_pad(struct _reent *ptr, int handle )           /* 09-jan-95 */
  68. /*******************************/
  69. {
  70.     int         rc;
  71.     long        curPos, eodPos;
  72.     long        bytesToWrite;
  73.     unsigned    writeAmt;
  74.     char        zeroBuf[PAD_SIZE];
  75.  
  76.     // Pad with zeros due to lseek() past EOF (POSIX)
  77.     curPos = _lseek_r( ptr, handle, 0L, SEEK_CUR );   /* current offset */
  78.     if( curPos == -1 )
  79.         return( -1 );
  80.     eodPos = _lseek_r( ptr, handle, 0L, SEEK_END );   /* end of data offset */
  81.     if( eodPos == -1 )
  82.         return( -1 );
  83.  
  84.     if( curPos > eodPos ) {
  85.         bytesToWrite = curPos - eodPos;         /* amount to pad by */
  86.  
  87.         if( bytesToWrite > 0 ) {                /* only write if needed */
  88.             memset( zeroBuf, 0x00, PAD_SIZE );  /* zero out a buffer */
  89.             do {                                /* loop until done */
  90.                 if( bytesToWrite > PAD_SIZE )
  91.                     writeAmt = 512;
  92.                 else
  93.                     writeAmt = (unsigned)bytesToWrite;
  94.                 rc = _write_r(ptr, handle, zeroBuf, writeAmt );
  95.                 if( rc < 0 )
  96.                     return( rc );
  97.                 bytesToWrite -= writeAmt;       /* more bytes written */
  98.             } while( bytesToWrite != 0 );
  99.         }
  100.     } else {
  101.         curPos = _lseek_r( ptr, handle, curPos, SEEK_SET );
  102.         if( curPos == -1 ) {
  103.             return( -1 );
  104.         }
  105.     }
  106.  
  107.     return( 0 );                /* return success code */
  108. }
  109.  
  110.  
  111. static int os_write(struct _reent *ptr, int handle,
  112.                     const void *buffer, unsigned len, unsigned *amt )
  113. /********************************************************************************/
  114. {
  115.     __file_handle *fh;
  116.     int         rc;
  117.  
  118.     rc   = 0;
  119.     *amt = 0;
  120.  
  121.     fh = (__file_handle*) __getOSHandle( handle );
  122.  
  123.     rc = fh->write(fh->name,buffer,fh->offset,len,amt);
  124.  
  125.     fh->offset+= *amt;
  126.  
  127.     if( *amt != len )
  128.     {
  129.         rc = ENOSPC;
  130.         ptr->_errno = ENOSPC;
  131.     }
  132.     return( rc );
  133. }
  134. _ssize_t
  135. _DEFUN (_write_r, (ptr, fd, buffer, cnt),
  136.      struct _reent *ptr _AND
  137.      int fd _AND
  138.      _CONST _PTR buffer _AND
  139.      size_t cnt)
  140. {
  141.     _ssize_t      ret;
  142.     unsigned int  iomode_flags;
  143.     unsigned      len_written, i, j;
  144.     int           rc2;
  145.     char        *buf;
  146.  
  147.     __file_handle  *fh;
  148.  
  149.     __handle_check( fd, -1 );
  150.  
  151.     iomode_flags = __GetIOMode( fd );
  152.     if( iomode_flags == 0 )
  153.     {
  154.         ptr->_errno = EBADF;
  155.         return( -1 );
  156.     }
  157.  
  158.     if( !(iomode_flags & _WRITE) ) {
  159.         ptr->_errno = EACCES ;     /* changed from EBADF to EACCES 23-feb-89 */
  160.         return( -1 );
  161.     }
  162.  
  163.     if( (iomode_flags & _APPEND) && !(iomode_flags & _ISTTY) )
  164.     {
  165.         fh->offset = _lseek_r(ptr, fd, 0L, SEEK_END );   /* end of data offset */
  166.     }
  167.  
  168.     len_written = 0;
  169.     rc2 = 0;
  170.  
  171.     // Pad the file with zeros if necessary
  172.     if( iomode_flags & _FILEEXT )
  173.     {
  174.         // turn off file extended flag
  175.         __SetIOMode_nogrow( fd, iomode_flags&(~_FILEEXT) );
  176.  
  177.         // It is not required to pad a file with zeroes on an NTFS file system;
  178.         // unfortunately it is required on FAT (and probably FAT32). (JBS)
  179.         rc2 = zero_pad( ptr, fd );
  180.     }
  181.  
  182.     if( rc2 == 0 )
  183.     {
  184.         if( iomode_flags & _BINARY ) {  /* if binary mode */
  185.             rc2 = os_write(ptr, fd, buffer, cnt, &len_written );
  186.             /* end of binary mode part */
  187.         } else {    /* text mode */
  188.  
  189.             int buf_size = 512;
  190.  
  191.             buf = (char*)alloca( buf_size );
  192.  
  193.             j = 0;
  194.             for( i = 0; i < cnt; )
  195.             {
  196.                 if( ((const char*)buffer)[i] == '\n' )
  197.                 {
  198.                     buf[j] = '\r';
  199.                     ++j;
  200.                     if( j == buf_size )
  201.                     {
  202.                         rc2 = os_write(ptr, fd, buf, buf_size, &j );
  203.                         if( rc2 == -1 )
  204.                             break;
  205.                         len_written += j;
  206.                         if( rc2 == ENOSPC )
  207.                             break;
  208.                         len_written = i;
  209.                         j = 0;
  210.                     }
  211.                 }
  212.                 buf[j] = ((const char*)buffer)[i];
  213.                 ++i;
  214.                 ++j;
  215.                 if( j == buf_size ) {
  216.                     rc2 = os_write(ptr, fd, buf, buf_size, &j );
  217.                     if( rc2 == -1 )
  218.                         break;
  219.                     len_written += j;
  220.                     if( rc2 == ENOSPC )
  221.                         break;
  222.                     len_written = i;
  223.                     j = 0;
  224.                 }
  225.             }
  226.             if( j ) {
  227.                 rc2 = os_write(ptr, fd, buf, j, &i );
  228.                 if( rc2 == ENOSPC ) {
  229.                     len_written += i;
  230.                 } else {
  231.                     len_written = cnt;
  232.                 }
  233.             }
  234.             /* end of text mode part */
  235.         }
  236.     }
  237.  
  238.     if( rc2 == -1 ) {
  239.         return( rc2 );
  240.     } else {
  241.         return( len_written );
  242.     }
  243. }
  244.  
  245. _ssize_t
  246. _DEFUN (write, ( fd, buffer, cnt),
  247.      int fd _AND
  248.      _CONST _PTR buffer _AND
  249.      size_t cnt)
  250.  
  251. {
  252.  
  253.     return _write_r(_REENT, fd, buffer, cnt);
  254.  
  255. }
  256.  
  257. #endif /* ! defined (REENTRANT_SYSCALLS_PROVIDED) */
  258.