Subversion Repositories Kolibri OS

Rev

Rev 698 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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