Subversion Repositories Kolibri OS

Rev

Rev 698 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
698 serge 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 
35
#include 
36
#include 
37
#include 
38
#include 
39
#include 
40
#include 
41
#include "iomode.h"
42
#include "fileacc.h"
43
#include "rtcheck.h"
44
#include "rtdata.h"
45
#include "seterrno.h"
46
#include "lseek.h"
727 serge 47
#include "kolibri.h"
698 serge 48
 
49
/*
50
    The _lwrite function writes data to the specified file.
51
 
52
    Note: This function is provided only for compatibility with 16-bit
53
    versions of Windows. Win32-based applications should use the WriteFile
54
    function.
55
 
56
    UINT _lwrite(
57
      HFILE hFile,  // handle to file
58
      LPCSTR lpBuffer,  // write data buffer
59
      UINT uBytes   // number of bytes to write
60
    );
61
 */
62
 
63
extern  void    __STKOVERFLOW();
64
 
65
/*
66
    Win32 Note:
67
    Note that it is not an error to set the file pointer to a position
68
    beyond the end of the file. The size of the file does not increase
69
    until you call the SetEndOfFile, WriteFile, or WriteFileEx function. A
70
    write operation increases the size of the file to the file pointer
71
    position plus the size of the buffer written, leaving the intervening
72
    bytes uninitialized.  Hence, the reason for zero-padding the file
73
    to achieve POSIX conformance.
74
*/
75
 
76
/*
77
    POSIX Note:
78
    When writing to a file that does not support seek operations (pipe,
79
    device, etc.), the O_APPEND flag is effectively ignored. POSIX does
80
    not explicitly state this, but it is implied. Also, ESPIPE (illegal
81
    seek error) is not listed for write(), only pwrite(). Hence we must
82
    either not attempt to seek on such devices, or ignore the failures.
83
*/
84
 
85
#define PAD_SIZE 512
86
 
87
typedef union {
88
    unsigned __int64    _64;
89
    long                _32[2];
90
} __i64;
91
 
92
static int zero_pad( int handle )           /* 09-jan-95 */
93
/*******************************/
94
{
95
    int         rc;
96
    long        curPos, eodPos;
97
    long        bytesToWrite;
98
    unsigned    writeAmt;
99
    char        zeroBuf[PAD_SIZE];
100
 
101
    // Pad with zeros due to lseek() past EOF (POSIX)
102
    curPos = __lseek( handle, 0L, SEEK_CUR );   /* current offset */
103
    if( curPos == -1 )
104
        return( -1 );
105
    eodPos = __lseek( handle, 0L, SEEK_END );   /* end of data offset */
106
    if( eodPos == -1 )
107
        return( -1 );
108
 
109
    if( curPos > eodPos ) {
110
        bytesToWrite = curPos - eodPos;         /* amount to pad by */
111
 
112
        if( bytesToWrite > 0 ) {                /* only write if needed */
113
            memset( zeroBuf, 0x00, PAD_SIZE );  /* zero out a buffer */
114
            do {                                /* loop until done */
115
                if( bytesToWrite > PAD_SIZE )
116
                    writeAmt = 512;
117
                else
118
                    writeAmt = (unsigned)bytesToWrite;
119
                rc = write( handle, zeroBuf, writeAmt );
120
                if( rc < 0 )
121
                    return( rc );
122
                bytesToWrite -= writeAmt;       /* more bytes written */
123
            } while( bytesToWrite != 0 );
124
        }
125
    } else {
126
        curPos = __lseek( handle, curPos, SEEK_SET );
127
        if( curPos == -1 ) {
128
            return( -1 );
129
        }
130
    }
131
 
132
    return( 0 );                /* return success code */
133
}
134
 
135
/*
136
    The os_write function returns 0 meaning no error, -1 meaning error, or
137
    ENOSPC meaning no space left on device.
138
*/
139
 
140
typedef struct
141
{
142
  char     *name;
143
  unsigned int offset;
144
}__file_handle;
145
 
146
static int os_write( int handle, const void *buffer, unsigned len, unsigned *amt )
147
/********************************************************************************/
148
{
149
    __file_handle *fh;
150
    int         rc;
151
 
152
    rc = 0;
153
 
154
    fh = (__file_handle*) __getOSHandle( handle );
155
 
727 serge 156
    rc = write_file(fh->name,buffer,fh->offset,len,amt);
157
    fh->offset+= *amt;
698 serge 158
 
159
    if( *amt != len )
160
    {
161
        rc = ENOSPC;
162
        __set_errno( rc );
163
    }
164
    return( rc );
165
}
166
 
167
  _WCRTLINK int write( int handle, const void *buffer, unsigned len )
168
/**********************************************************************/
169
{
170
    unsigned    iomode_flags;
171
    char        *buf;
172
    unsigned    buf_size;
173
    unsigned    len_written, i, j;
174
    int         rc2;
175
 
176
    __file_handle *fh;
177
 
178
    __handle_check( handle, -1 );
179
    iomode_flags = __GetIOMode( handle );
180
    if( iomode_flags == 0 )
181
    {
182
        __set_errno( EBADF );
183
        return( -1 );
184
    }
185
 
186
    if( !(iomode_flags & _WRITE) ) {
187
        __set_errno( EACCES );     /* changed from EBADF to EACCES 23-feb-89 */
188
        return( -1 );
189
    }
190
 
191
    fh = (__file_handle*) __getOSHandle( handle );
192
 
193
    // put a semaphore around our writes
194
 
195
    _AccessFileH( handle );
196
    if( (iomode_flags & _APPEND) && !(iomode_flags & _ISTTY) )
197
    {
198
      fh->offset = __lseek( handle, 0L, SEEK_END );   /* end of data offset */
199
    }
200
 
201
    len_written = 0;
202
    rc2 = 0;
203
 
204
    // Pad the file with zeros if necessary
205
    if( iomode_flags & _FILEEXT ) {
206
        // turn off file extended flag
207
        __SetIOMode_nogrow( handle, iomode_flags&(~_FILEEXT) );
208
 
209
        // It is not required to pad a file with zeroes on an NTFS file system;
210
        // unfortunately it is required on FAT (and probably FAT32). (JBS)
211
        rc2 = zero_pad( handle );
212
    }
213
 
214
    if( rc2 == 0 ) {
215
        if( iomode_flags & _BINARY ) {  /* if binary mode */
216
            rc2 = os_write( handle, buffer, len, &len_written );
217
            /* end of binary mode part */
218
        } else {    /* text mode */
219
            i = stackavail();
220
            if( i < 0x00b0 ) {
221
                __STKOVERFLOW();    /* not enough stack space */
222
            }
223
            buf_size = 512;
224
            if( i < (512 + 48) ) {
225
                buf_size = 128;
226
            }
227
 
228
            buf = __alloca( buf_size );
229
 
230
            j = 0;
231
            for( i = 0; i < len; )
232
            {
233
                if( ((const char*)buffer)[i] == '\n' )
234
                {
235
                    buf[j] = '\r';
236
                    ++j;
237
                    if( j == buf_size )
238
                    {
239
                        rc2 = os_write( handle, buf, buf_size, &j );
240
                        if( rc2 == -1 )
241
                            break;
242
                        len_written += j;
243
                        if( rc2 == ENOSPC )
244
                            break;
245
                        len_written = i;
246
                        j = 0;
247
                    }
248
                }
249
                buf[j] = ((const char*)buffer)[i];
250
                ++i;
251
                ++j;
252
                if( j == buf_size ) {
253
                    rc2 = os_write( handle, buf, buf_size, &j );
254
                    if( rc2 == -1 )
255
                        break;
256
                    len_written += j;
257
                    if( rc2 == ENOSPC )
258
                        break;
259
                    len_written = i;
260
                    j = 0;
261
                }
262
            }
263
            if( j ) {
264
                rc2 = os_write( handle, buf, j, &i );
265
                if( rc2 == ENOSPC ) {
266
                    len_written += i;
267
                } else {
268
                    len_written = len;
269
                }
270
            }
271
            /* end of text mode part */
272
        }
273
    }
274
    _ReleaseFileH( handle );
275
    if( rc2 == -1 ) {
276
        return( rc2 );
277
    } else {
278
        return( len_written );
279
    }
280
}
281