Subversion Repositories Kolibri OS

Rev

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 <>.  It
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) */