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 | }>>>> |