1 /****************************************************************************** 2 3 Simple POSIX I/O device interfaces and base classes, significantly 4 influenced by Tango's Conduit. 5 6 An input device is merely an ISelectable (a file descriptor) with a read() 7 method and an output an ISelectable device wih a write() method. read() and 8 write() wrap the POSIX function with the same name. 9 10 Copyright: 11 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 12 All rights reserved. 13 14 License: 15 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 16 Alternatively, this file may be distributed under the terms of the Tango 17 3-Clause BSD License (see LICENSE_BSD.txt for details). 18 19 ******************************************************************************/ 20 21 module ocean.io.device.IODevice; 22 23 24 import ocean.meta.types.Qualifiers; 25 26 import ocean.io.model.IConduit: ISelectable; 27 28 import core.sys.posix.unistd: read, write; 29 import core.sys.posix.sys.types: ssize_t; 30 31 /****************************************************************************** 32 33 Input device interface 34 35 ******************************************************************************/ 36 37 interface IInputDevice : ISelectable 38 { 39 /************************************************************************** 40 41 Convenience type alias for subclasses/interfaces 42 43 **************************************************************************/ 44 45 alias .ssize_t ssize_t; 46 47 /************************************************************************** 48 49 read() attempts to read up to dst.length bytes from the device 50 associated with the file descriptor of this instance into dst. 51 52 If dst.length is zero, read() returns zero and has no other results. If 53 count is greater than SSIZE_MAX, the result is unspecified. 54 55 Params: 56 dst = destination buffer 57 58 Returns: 59 On success, the number of bytes read is returned (zero indicates end 60 of file), and the file position is advanced by this number. It is 61 not an error if this number is smaller than the number of bytes 62 requested; this may happen for example because fewer bytes are actu‐ 63 ally available right now (maybe because we were close to end-of- 64 file, or because we are reading from a pipe, or from a terminal), or 65 because read() was interrupted by a signal. On error, -1 is 66 returned, and errno is set appropriately. In this case it is left 67 unspecified whether the file position (if any) changes. 68 69 Errors: 70 71 EAGAIN The file descriptor fd refers to a file other than a socket 72 and has been marked nonblocking (O_NONBLOCK), and the read 73 would block. 74 75 EAGAIN or EWOULDBLOCK 76 The file descriptor fd refers to a socket and has been marked 77 nonblocking (O_NONBLOCK), and the read would block. 78 POSIX.1-2001 allows either error to be returned for this 79 case, and does not require these constants to have the same 80 value, so a portable application should check for both possi‐ 81 bilities. 82 83 EBADF fd is not a valid file descriptor or is not open for reading. 84 85 EFAULT dst is outside your accessible address space. 86 87 EINTR The call was interrupted by a signal before any data was 88 read; see signal(7). 89 90 EINVAL fd is attached to an object which is unsuitable for reading; 91 or the file was opened with the O_DIRECT flag, and either the 92 address specified in dst, the value specified in count, or 93 the current file offset is not suitably aligned. 94 95 EINVAL fd was created via a call to timerfd_create(2) and the wrong 96 size buffer was given to read(); see timerfd_create(2) for 97 further information. 98 99 EIO I/O error. This will happen for example when the process is 100 in a background process group, tries to read from its con‐ 101 trolling tty, and either it is ignoring or blocking SIGTTIN 102 or its process group is orphaned. It may also occur when 103 there is a low-level I/O error while reading from a disk or 104 tape. 105 106 EISDIR fd refers to a directory. 107 108 Other errors may occur, depending on the object connected to fd. 109 POSIX allows a read() that is interrupted after reading some data to 110 return -1 (with errno set to EINTR) or to return the number of bytes 111 already read. 112 113 **************************************************************************/ 114 115 ssize_t read ( void[] dst ); 116 } 117 118 /****************************************************************************** 119 120 Output device interface 121 122 ******************************************************************************/ 123 124 interface IOutputDevice : ISelectable 125 { 126 /************************************************************************** 127 128 Convenience type alias for subclasses/interfaces 129 130 **************************************************************************/ 131 132 alias .ssize_t ssize_t; 133 134 /************************************************************************** 135 136 write() writes up to count bytes from the buffer pointed buf to the file 137 referred to by the file descriptor fd. 138 139 The number of bytes written may be less than count if, for example, 140 there is insufficient space on the underlying physical medium, or the 141 RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the 142 call was interrupted by a signal handler after having written less than 143 count bytes. (See also pipe(7).) 144 145 For a seekable file (i.e., one to which lseek(2) may be applied, for 146 example, a regular file) writing takes place at the current file offset, 147 and the file offset is incremented by the number of bytes actually writ‐ 148 ten. If the file was open(2)ed with O_APPEND, the file offset is first 149 set to the end of the file before writing. The adjustment of the file 150 offset and the write operation are performed as an atomic step. 151 152 POSIX requires that a read(2) which can be proved to occur after a 153 write() has returned returns the new data. Note that not all file sys‐ 154 tems are POSIX conforming. 155 156 Returns: 157 On success, the number of bytes written is returned (zero indicates 158 nothing was written). On error, -1 is returned, and errno is set 159 appropriately. 160 161 If count is zero and fd refers to a regular file, then write() may 162 return a failure status if one of the errors below is detected. If 163 no errors are detected, 0 will be returned without causing any other 164 effect. If count is zero and fd refers to a file other than a regu‐ 165 lar file, the results are not specified. 166 167 168 write() writes up to count bytes from the buffer pointed buf to the 169 file referred to by the file descriptor fd. 170 171 The number of bytes written may be less than count if, for example, 172 there is insufficient space on the underlying physical medium, or 173 the RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), 174 or the call was interrupted by a signal handler after having written 175 less than count bytes. (See also pipe(7).) 176 177 For a seekable file (i.e., one to which lseek(2) may be applied, for 178 example, a regular file) writing takes place at the current file 179 offset, and the file offset is incremented by the number of bytes 180 actually written. If the file was open(2)ed with O_APPEND, the file 181 offset is first set to the end of the file before writing. The 182 adjustment of the file offset and the write operation are performed 183 as an atomic step. 184 185 POSIX requires that a read(2) which can be proved to occur after a 186 write() has returned returns the new data. Note that not all file 187 systems are POSIX conforming. 188 189 Errors: 190 EAGAIN The file descriptor fd refers to a file other than a socket 191 and has been marked nonblocking (O_NONBLOCK), and the write 192 would block. 193 194 EAGAIN or EWOULDBLOCK 195 The file descriptor fd refers to a socket and has been marked 196 nonblocking (O_NONBLOCK), and the write would block. 197 POSIX.1-2001 allows either error to be returned for this 198 case, and does not require these constants to have the same 199 value, so a portable application should check for both possi‐ 200 bilities. 201 202 EBADF fd is not a valid file descriptor or is not open for writing. 203 204 EDESTADDRREQ 205 fd refers to a datagram socket for which a peer address has 206 not been set using connect(2). 207 208 EFAULT buf is outside your accessible address space. 209 210 EFBIG An attempt was made to write a file that exceeds the imple‐ 211 mentation-defined maximum file size or the process's file 212 size limit, or to write at a position past the maximum 213 allowed offset. 214 215 EINTR The call was interrupted by a signal before any data was 216 written; see signal(7). 217 218 EINVAL fd is attached to an object which is unsuitable for writing; 219 or the file was opened with the O_DIRECT flag, and either the 220 address specified in buf, the value specified in count, or 221 the current file offset is not suitably aligned. 222 223 EIO A low-level I/O error occurred while modifying the inode. 224 225 ENOSPC The device containing the file referred to by fd has no room 226 for the data. 227 228 EPIPE fd is connected to a pipe or socket whose reading end is 229 closed. When this happens the writing process will also 230 receive a SIGPIPE signal. (Thus, the write return value is 231 seen only if the program catches, blocks or ignores this sig‐ 232 nal.) 233 234 Other errors may occur, depending on the object connected to fd. 235 236 **************************************************************************/ 237 238 ssize_t write ( const(void)[] dst ); 239 } 240 241 /****************************************************************************** 242 243 Input device base class, may be used to conveniently implement an 244 IInputDevice. 245 246 ******************************************************************************/ 247 248 abstract class InputDevice : IInputDevice 249 { 250 /************************************************************************** 251 252 Attempts to read dst.length bytes, see IInputDevice.read() 253 documentation. 254 255 Params: 256 dst = destination data buffer 257 258 Returns 259 the number of bytes read and stored in dst on success, 0 on end-of- 260 file condition or -1 on error. On error errno is set appropriately. 261 262 **************************************************************************/ 263 264 public ssize_t read ( void[] dst ) 265 { 266 return .read(this.fileHandle(), dst.ptr, dst.length); 267 } 268 } 269 270 /****************************************************************************** 271 272 IODevice device base class, may be used to conveniently implement an I/O 273 class that is both an IInputDevice and IOutputDevice. 274 275 ******************************************************************************/ 276 277 abstract class IODevice : InputDevice, IOutputDevice 278 { 279 /************************************************************************** 280 281 Attempts to write src.length bytes, see IOutputDevice.write() 282 documentation. 283 284 Params: 285 src = source data buffer 286 287 Returns 288 the number of bytes written on success or -1 on error. On error 289 errno is set appropriately. 290 291 **************************************************************************/ 292 293 abstract public ssize_t write ( const(void)[] src ); 294 }