Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* Reentrant versions of write system call. */ |
2 | |||
3 | #include |
||
4 | #include |
||
5 | #include <_syslist.h> |
||
6 | #include |
||
7 | #include |
||
8 | #include |
||
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 |
||
33 | _ssize_t _write_r(struct _reent *<[ptr]>, |
||
34 | int <[fd]>, const void *<[buf]>, size_t <[cnt]>); |
||
35 | |||
36 | TRAD_SYNOPSIS |
||
37 | #include |
||
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 < |
||
46 | takes a pointer to the global data block, which holds |
||
47 | < |
||
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) */>>> |