1 /*===========================================================================
2 *
3 *                            PUBLIC DOMAIN NOTICE
4 *               National Center for Biotechnology Information
5 *
6 *  This software/database is a "United States Government Work" under the
7 *  terms of the United States Copyright Act.  It was written as part of
8 *  the author's official duties as a United States Government employee and
9 *  thus cannot be copyrighted.  This software/database is freely available
10 *  to the public for use. The National Library of Medicine and the U.S.
11 *  Government have not placed any restriction on its use or reproduction.
12 *
13 *  Although all reasonable efforts have been taken to ensure the accuracy
14 *  and reliability of the software and data, the NLM and the U.S.
15 *  Government do not and cannot warrant the performance or results that
16 *  may be obtained by using this software or data. The NLM and the U.S.
17 *  Government disclaim all warranties, express or implied, including
18 *  warranties of performance, merchantability or fitness for any particular
19 *  purpose.
20 *
21 *  Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26 
27 #include <kfc/fd.hpp>
28 #include <kfc/callstk.hpp>
29 #include <kfc/rsrc.hpp>
30 #include <kfc/caps.hpp>
31 #include <kfc/except.hpp>
32 #include <kfc/syserr.hpp>
33 #include <kfc/array.hpp>
34 
35 #if UNIX
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <errno.h>
39 #else
40 #error "unsupported target platform"
41 #endif
42 
43 namespace vdb3
44 {
45 
46     /*------------------------------------------------------------------
47      * FileDescImpl
48      *  a Unix file-descriptor
49      */
50 
51     // StreamItf
read(const bytes_t & num_bytes,Mem & dst,const bytes_t & start)52     bytes_t FileDescImpl :: read ( const bytes_t & num_bytes,
53         Mem & dst, const bytes_t & start )
54     {
55         FUNC_ENTRY ();
56 
57         // parameters have already been checked
58         assert ( start < dst . size () );
59         assert ( start + num_bytes <= dst . size () );
60 
61         // interfacing with native OS requires exceptional access
62         Array < U8 > a = dst;
63         void * addr = & a [ start ];
64 
65 #if UNIX
66         ssize_t num_read = 0;
67         while ( 1 )
68         {
69             num_read = :: read ( fd, addr, ( size_t ) ( U64 ) num_bytes );
70             if ( num_read >= 0 )
71                 break;
72 
73             int _fd = fd;
74             int status = errno;
75             switch ( status )
76             {
77             case EINTR:
78                 break;
79             case EBADF:
80                 fd = -1;
81                 owned = false;
82                 THROW ( xc_param_err, "bad fd: %d", _fd );
83             case EFAULT:
84                 // super-internal error, wow.
85                 THROW ( xc_internal_err, "bad address from meory: 0x016X", ( U64 ) addr );
86             case EAGAIN:
87                 // this is essentially a timeout error
88             case EINVAL:
89             case EIO:
90             case EISDIR:
91             default:
92                 THROW_OSERR ( read, status );
93             }
94         }
95 
96         return bytes_t ( num_read );
97 #endif
98     }
99 
write(const bytes_t & num_bytes,const Mem & src,const bytes_t & start)100     bytes_t FileDescImpl :: write ( const bytes_t & num_bytes,
101         const Mem & src, const bytes_t & start )
102     {
103         FUNC_ENTRY ();
104 
105         // parameters have already been checked
106         assert ( start < src . size () );
107         assert ( start + num_bytes <= src . size () );
108 
109         // interfacing with native OS requires exceptional access
110         const Array < U8 > a = src;
111         const void * addr = & a [ start ];
112 
113 #if UNIX
114         ssize_t num_writ = 0;
115         while ( 1 )
116         {
117             num_writ = :: write ( fd, addr, ( size_t ) ( U64 ) num_bytes );
118             if ( num_writ >= 0 )
119                 break;
120 
121             int _fd = fd;
122             int status = errno;
123             switch ( status )
124             {
125             case EINTR:
126                 break;
127             case ENOSPC:
128                 THROW ( xc_no_mem, "attempt to write %lu bytes exceeds volume limits", ( U64 ) num_bytes );
129             case EFBIG:
130                 THROW ( xc_bounds_err, "attempt to write %lu bytes exceeds limit", ( U64 ) num_bytes );
131             case EBADF:
132                 fd = -1;
133                 owned = false;
134                 THROW ( xc_param_err, "bad fd: %d", _fd );
135             case EFAULT:
136                 // super-internal error, wow.
137                 THROW ( xc_internal_err, "bad address from meory: 0x016X", ( U64 ) addr );
138             case EAGAIN:
139                 // this is essentially a timeout error
140             case EINVAL:
141             case EIO:
142             case EISDIR:
143             default:
144                 THROW_OSERR ( write, status );
145             }
146         }
147 
148         return bytes_t ( num_writ );
149 #endif
150     }
151 
get_mtu() const152     bytes_t FileDescImpl :: get_mtu () const
153     {
154         FUNC_ENTRY ();
155 
156         // TBD - determine proper MTU for device
157         return bytes_t ( 4096 );
158     }
159 
160     // C++
FileDescImpl(int _fd,bool _owned)161     FileDescImpl :: FileDescImpl ( int _fd, bool _owned )
162         : fd ( _fd )
163         , owned ( _owned )
164     {
165         assert ( _fd >= 0 );
166     }
167 
~FileDescImpl()168     FileDescImpl :: ~ FileDescImpl ()
169     {
170         if ( owned )
171             close ( fd );
172     }
173 
174 
175     /*------------------------------------------------------------------
176      * FileDesc
177      *  a reference to a Unix file-descriptor
178      */
179 
FileDesc()180     FileDesc :: FileDesc ()
181     {
182     }
183 
FileDesc(const FileDesc & r)184     FileDesc :: FileDesc ( const FileDesc & r )
185         : Ref < FileDescImpl > ( r )
186     {
187     }
188 
operator =(const FileDesc & r)189     void FileDesc :: operator = ( const FileDesc & r )
190     {
191         Ref < FileDescImpl > :: operator = ( r );
192     }
193 
FileDesc(const FileDesc & r,caps_t reduce)194     FileDesc :: FileDesc ( const FileDesc & r, caps_t reduce )
195         : Ref < FileDescImpl > ( r, reduce )
196     {
197     }
198 
FileDesc(FileDescImpl * obj,caps_t caps)199     FileDesc :: FileDesc ( FileDescImpl * obj, caps_t caps )
200         : Ref < FileDescImpl > ( obj, caps )
201     {
202     }
203 
204 }
205