]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/io/fileio/v2_0/src/io.cxx
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / io / fileio / v2_0 / src / io.cxx
1 //==========================================================================
2 //
3 //      io.cxx
4 //
5 //      Fileio IO operations
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2002 Gary Thomas
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
43 //
44 // Author(s):           nickg
45 // Contributors:        nickg
46 // Date:                2000-05-25
47 // Purpose:             Fileio IO operations
48 // Description:         These are the functions that operate on open files,
49 //                      such as read(), write(), fstat() etc.
50 //              
51 //              
52 //
53 //####DESCRIPTIONEND####
54 //
55 //==========================================================================
56
57 #include <pkgconf/hal.h>
58 #include <pkgconf/io_fileio.h>
59
60 #include <cyg/infra/cyg_trac.h>        // tracing macros
61 #include <cyg/infra/cyg_ass.h>         // assertion macros
62
63 #include <stdarg.h>                     // for fcntl()
64
65 #include "fio.h"                       // Private header
66
67
68 //==========================================================================
69 // File object locking
70
71 #define LOCK_FILE( fp ) cyg_file_lock( fp, fp->f_syncmode )
72
73 #define UNLOCK_FILE( fp ) cyg_file_unlock( fp, fp->f_syncmode )
74
75 //==========================================================================
76 // Common wrapper for read/write using an iovec descriptor 
77 // 'direction' should be O_RDONLY for readv, O_WRONLY for writev
78
79 static ssize_t 
80 readwritev( int fd, const cyg_iovec *_iov, int iov_len, int direction )
81 {
82     FILEIO_ENTRY();
83
84     CYG_CANCELLATION_POINT;
85     
86     ssize_t cnt, len;
87     int ret, _idx;
88     cyg_file *fp;
89     cyg_iovec iov[CYGNUM_FILEIO_IOVEC_MAX];
90     
91     if( iov_len > CYGNUM_FILEIO_IOVEC_MAX )
92         FILEIO_RETURN(EINVAL);
93
94     // Copy 'iovec' structure since it's supposed to be "const"
95     // and some lower level routines might want to change it.
96     // Also accumulate the length of the total I/O request
97     len = 0;
98     for (_idx = 0;  _idx < iov_len;  _idx++) {
99         len += _iov[_idx].iov_len;
100         iov[_idx].iov_base = _iov[_idx].iov_base;
101         iov[_idx].iov_len = _iov[_idx].iov_len;
102     }
103
104     if( len > SSIZE_MAX )
105         FILEIO_RETURN(EINVAL);
106     
107     fp = cyg_fp_get( fd );
108
109     if( fp == NULL )
110         FILEIO_RETURN(EBADF);
111
112     if( (fp->f_flag & direction) == 0 )
113     {
114         cyg_fp_free( fp );
115         FILEIO_RETURN(EBADF);        
116     }
117
118     cyg_uio uio;
119     cyg_fileop_readwrite *op;
120     
121     uio.uio_iov         = iov;
122     uio.uio_iovcnt      = iov_len;
123     uio.uio_resid       = len;
124     uio.uio_segflg      = UIO_USERSPACE;
125
126     cnt = len;
127
128     if( direction == O_RDONLY )
129         uio.uio_rw = UIO_READ, op = fp->f_ops->fo_read;
130     else
131         uio.uio_rw = UIO_WRITE, op = fp->f_ops->fo_write;
132         
133     LOCK_FILE( fp );
134     
135     ret = op( fp, &uio );
136     
137     UNLOCK_FILE( fp );
138     
139     cnt -= uio.uio_resid;
140
141     cyg_fp_free( fp );
142
143     CYG_CANCELLATION_POINT;
144
145     if( ret != 0 )
146     {
147         if ((ret == EWOULDBLOCK || ret == EAGAIN) && cnt)
148             FILEIO_RETURN_VALUE(cnt);
149         else
150             FILEIO_RETURN(ret);
151     }
152  
153     FILEIO_RETURN_VALUE(cnt);
154 }
155
156 //==========================================================================
157 // Read from file
158
159 __externC ssize_t read( int fd, void *buf, size_t len )
160 {
161     cyg_iovec _iov;
162
163     _iov.iov_base = buf;
164     _iov.iov_len = len;
165     return readwritev(fd, &_iov, 1, O_RDONLY);
166 }
167
168 //==========================================================================
169 // Write to a file
170
171 __externC ssize_t write( int fd, const void *buf, size_t len )
172 {
173     cyg_iovec _iov;
174
175     _iov.iov_base = (void *)buf;
176     _iov.iov_len = len;
177     return readwritev(fd, &_iov, 1, O_WRONLY);
178 }
179
180 //==========================================================================
181 // Read via an iovec
182 __externC ssize_t readv( int fd, const cyg_iovec *_iov, int iov_len )
183 {
184     return readwritev(fd, _iov, iov_len, O_RDONLY);
185 }
186
187 //==========================================================================
188 // Write via an iovec
189 __externC ssize_t writev( int fd, const cyg_iovec *_iov, int iov_len )
190 {
191     return readwritev(fd, _iov, iov_len, O_WRONLY);
192 }
193
194
195 //==========================================================================
196 // Close a file
197
198 __externC int close( int fd )
199 {
200     FILEIO_ENTRY();
201
202     CYG_CANCELLATION_POINT;
203     
204     int ret;
205     cyg_file *fp;
206     
207     fp = cyg_fp_get( fd );
208
209     if( fp == NULL )
210         FILEIO_RETURN(EBADF);
211
212     cyg_fp_free( fp );
213     
214     // The file's fo_close entry may be called as a side
215     // effect of this operation...
216     ret = cyg_fd_free( fd );
217
218     CYG_CANCELLATION_POINT;
219  
220     FILEIO_RETURN(ret);
221 }
222
223 //==========================================================================
224 // Seek a file
225
226 __externC off_t lseek( int fd, off_t pos, int whence )
227 {
228     FILEIO_ENTRY();
229
230     int ret;
231     cyg_file *fp;
232     
233     fp = cyg_fp_get( fd );
234
235     if( fp == NULL )
236         FILEIO_RETURN(EBADF);
237
238     LOCK_FILE( fp );
239     
240     ret = fp->f_ops->fo_lseek( fp, &pos, whence );
241
242     UNLOCK_FILE( fp );
243     
244     cyg_fp_free( fp );
245
246     if( ret != 0 )
247         FILEIO_RETURN(ret);
248     
249     FILEIO_RETURN_VALUE(pos);
250 }
251
252 //==========================================================================
253 // ioctl
254
255 __externC int ioctl( int fd, CYG_ADDRWORD com, ... )
256 {
257     FILEIO_ENTRY();
258
259     int ret;
260     cyg_file *fp;
261     va_list ap;
262     CYG_ADDRWORD data;
263
264     fp = cyg_fp_get( fd );
265
266     if( fp == NULL )
267         FILEIO_RETURN(EBADF);
268
269     va_start(ap, com);
270     data = va_arg(ap, CYG_ADDRWORD);
271     va_end(ap);
272     
273     LOCK_FILE( fp );
274     
275     ret = fp->f_ops->fo_ioctl( fp, com, data );
276
277     UNLOCK_FILE( fp );
278     
279     cyg_fp_free( fp );
280
281     FILEIO_RETURN(ret);
282 }
283
284 //==========================================================================
285 // fsync
286
287 __externC int fsync( int fd )
288 {
289     FILEIO_ENTRY();
290
291     CYG_CANCELLATION_POINT;
292     
293     int ret;
294     cyg_file *fp;
295     
296     fp = cyg_fp_get( fd );
297
298     if( fp == NULL )
299         FILEIO_RETURN(EBADF);
300
301     LOCK_FILE( fp );
302     
303     ret = fp->f_ops->fo_fsync( fp, CYG_FSYNC );
304
305     UNLOCK_FILE( fp );
306     
307     cyg_fp_free( fp );
308
309     CYG_CANCELLATION_POINT;
310     
311     FILEIO_RETURN(ret);
312 }
313
314 //==========================================================================
315 // fdatasync()
316
317 __externC int fdatasync( int fd )
318 {
319     FILEIO_ENTRY();
320
321     CYG_CANCELLATION_POINT;
322     
323     int ret;
324     cyg_file *fp;
325     
326     fp = cyg_fp_get( fd );
327
328     if( fp == NULL )
329         FILEIO_RETURN(EBADF);
330
331     LOCK_FILE( fp );
332     
333     ret = fp->f_ops->fo_fsync( fp, CYG_FDATASYNC );
334
335     UNLOCK_FILE( fp );
336     
337     cyg_fp_free( fp );
338
339     CYG_CANCELLATION_POINT;
340     
341     FILEIO_RETURN(ret);
342 }
343
344 //==========================================================================
345 // fstat
346
347 __externC int fstat( int fd, struct stat *buf )
348 {
349     FILEIO_ENTRY();
350
351     int ret;
352     cyg_file *fp;
353     
354     fp = cyg_fp_get( fd );
355
356     if( fp == NULL )
357         FILEIO_RETURN(EBADF);
358
359     LOCK_FILE( fp );
360     
361     ret = fp->f_ops->fo_fstat( fp, buf );
362
363     UNLOCK_FILE( fp );
364     
365     cyg_fp_free( fp );
366
367     FILEIO_RETURN(ret);
368 }
369
370 //==========================================================================
371 // fpathconf
372
373 __externC long fpathconf( int fd, int name )
374 {
375     FILEIO_ENTRY();
376
377     int ret;
378     cyg_file *fp;
379     
380     fp = cyg_fp_get( fd );
381
382     if( fp == NULL )
383         FILEIO_RETURN(EBADF);
384
385     struct cyg_pathconf_info info;
386
387     info.name = name;
388     info.value = 0;
389     
390     LOCK_FILE( fp );
391     
392     ret = fp->f_ops->fo_getinfo( fp, FILE_INFO_CONF, (char *)&info, sizeof(info) );
393
394     UNLOCK_FILE( fp );
395     
396     cyg_fp_free( fp );
397
398     if( ret != 0 )
399         FILEIO_RETURN(ret);
400
401     FILEIO_RETURN_VALUE(info.value);
402 }
403
404 //==========================================================================
405 // fcntl
406
407 __externC int fcntl( int fd, int cmd, ... )
408 {
409     FILEIO_ENTRY();
410
411     CYG_CANCELLATION_POINT;
412     
413     int ret = 0;
414     cyg_file *fp;
415     va_list a;
416
417     fp = cyg_fp_get( fd );
418
419     if( fp == NULL )
420         FILEIO_RETURN(EBADF);
421
422     va_start( a, cmd );
423         
424     switch( cmd )
425     {
426     case F_DUPFD:
427     {
428         int fda = va_arg(a, int);
429
430         if( fda < 0 || fda >= OPEN_MAX )
431         {
432             errno = EBADF;
433             break;
434         }
435         
436         int fd2 = cyg_fd_alloc( fda );
437
438         if( fd2 == -1 )
439         {
440             ret = EMFILE;
441             break;
442         }
443
444         cyg_fd_assign( fd2, fp );
445         
446         break;
447     }
448     
449     default:
450         ret = ENOTSUP;
451         break;
452     }
453
454     va_end(a);
455     
456     cyg_fp_free( fp );
457    
458     CYG_CANCELLATION_POINT;
459     
460     FILEIO_RETURN(ret);
461 }
462
463 //==========================================================================
464 // isatty()
465
466 __externC int isatty( int fd )
467 {
468     FILEIO_ENTRY();
469
470     int ret = 0;
471     struct stat buf;
472     int err;
473
474     err = fstat( fd, &buf );
475
476     // Any error and we return zero. If the client wants to
477     // they can always pick up the error code from errno.
478     if( err < 0 )
479         FILEIO_RETURN_VALUE(0);
480
481     // For now we assume that all char devices are ttys.
482     // In future we may need to have a special getinfo()
483     // call to decide this more specifically.
484     
485     if( S_ISCHR( buf.st_mode ) )
486         ret = 1;
487     
488     FILEIO_RETURN_VALUE(ret);
489 }
490
491 //==========================================================================
492 // File get info.
493
494 __externC int cyg_fs_fgetinfo( int fd, int key, void *buf, int len )
495 {
496     FILEIO_ENTRY();
497
498     int ret;
499     cyg_file *fp;
500
501     fp = cyg_fp_get( fd );
502
503     if( fp == NULL )
504         FILEIO_RETURN(EBADF);
505        
506     LOCK_FILE( fp );
507
508     ret = fp->f_ops->fo_getinfo( fp, key, buf, len );
509     
510     UNLOCK_FILE( fp );
511
512     cyg_fp_free( fp );    
513     
514     FILEIO_RETURN(ret);
515 }
516
517 //==========================================================================
518 // File set info.
519
520 __externC int cyg_fs_fsetinfo( int fd, int key, void *buf, int len )
521 {
522     FILEIO_ENTRY();
523
524     int ret;
525     cyg_file *fp;
526
527     fp = cyg_fp_get( fd );
528
529     if( fp == NULL )
530         FILEIO_RETURN(EBADF);
531        
532     LOCK_FILE( fp );
533
534     ret = fp->f_ops->fo_setinfo( fp, key, buf, len );
535     
536     UNLOCK_FILE( fp );
537
538     cyg_fp_free( fp );    
539     
540     FILEIO_RETURN(ret);
541 }
542
543 // -------------------------------------------------------------------------
544 // EOF io.cxx