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