Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | 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"
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