1 /******************************************************************************* 2 3 Copyright: 4 Copyright (c) 2004 Kris Bell. 5 Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH. 6 All rights reserved. 7 8 License: 9 Tango Dual License: 3-Clause BSD License / Academic Free License v3.0. 10 See LICENSE_TANGO.txt for details. 11 12 Version: May 2005: Initial release 13 14 Authors: Kris 15 16 *******************************************************************************/ 17 18 module ocean.io.device.Device; 19 20 import ocean.meta.types.Qualifiers; 21 22 import ocean.sys.Common; 23 24 public import ocean.io.device.Conduit; 25 26 /******************************************************************************* 27 28 Implements a means of reading and writing a file device. Conduits 29 are the primary means of accessing external data, and this one is 30 used as a superclass for the console, for files, sockets etc. 31 32 *******************************************************************************/ 33 34 class Device : Conduit, ISelectable 35 { 36 import core.stdc.errno; 37 import core.sys.posix.sys.types: off_t; 38 39 /// expose superclass definition also 40 public alias Conduit.error error; 41 42 /*********************************************************************** 43 44 Throw an IOException noting the last error. 45 46 ***********************************************************************/ 47 48 final void error () 49 { 50 error (this.toString ~ " :: " ~ SysError.lastMsg); 51 } 52 53 /*********************************************************************** 54 55 Return the name of this device. 56 57 ***********************************************************************/ 58 59 override istring toString () 60 { 61 return "<device>"; 62 } 63 64 /*********************************************************************** 65 66 Return a preferred size for buffering conduit I/O. 67 68 ***********************************************************************/ 69 70 override size_t bufferSize () 71 { 72 return 1024 * 16; 73 } 74 75 /*********************************************************************** 76 77 Sets the device in the non-blocking mode. 78 79 Throws: 80 IOException if setting the device mode fails 81 82 ***********************************************************************/ 83 84 public void setNonBlock () 85 { 86 auto existing_flags = fcntl(this.fileHandle(), F_GETFL, 0); 87 88 if (existing_flags == -1) 89 { 90 this.error(errno, "fcntl"); 91 } 92 93 if (fcntl(this.fileHandle(), F_SETFL, existing_flags | O_NONBLOCK) < 0) 94 { 95 this.error(errno, "fcntl"); 96 } 97 } 98 99 protected int handle = -1; 100 101 /*************************************************************************** 102 103 Allow adjustment of standard IO handles. 104 105 ***************************************************************************/ 106 107 public void reopen (Handle handle) 108 { 109 this.handle = handle; 110 } 111 112 /*************************************************************************** 113 114 Returns: 115 the file descriptor of this Conduit. 116 117 ***************************************************************************/ 118 119 final Handle fileHandle () 120 { 121 return cast(Handle) handle; 122 } 123 124 /*************************************************************************** 125 126 Release the underlying file. 127 128 ***************************************************************************/ 129 130 override void detach () 131 { 132 if (handle >= 0) 133 { 134 //if (scheduler) 135 // TODO Not supported on Posix 136 // scheduler.close (handle, toString); 137 posix.close (handle); 138 } 139 handle = -1; 140 } 141 142 /*************************************************************************** 143 144 Read a chunk of bytes from the file into the provided array 145 146 Returns: 147 the number of bytes read, or Eof where there is no further data. 148 149 ***************************************************************************/ 150 151 override size_t read (void[] dst) 152 { 153 ssize_t read; 154 155 do 156 { 157 read = posix.read (handle, dst.ptr, dst.length); 158 } 159 while (read == -1 && errno == EINTR); 160 161 if (read is -1) 162 error(errno, "read"); 163 else 164 if (read is 0 && dst.length > 0) 165 return Eof; 166 return read; 167 } 168 169 /*************************************************************************** 170 171 Write a chunk of bytes to the file from the provided array. 172 173 Returns: 174 the number of bytes written, or Eof if the output is 175 no longer available. 176 177 ***************************************************************************/ 178 179 override size_t write (const(void)[] src) 180 { 181 ssize_t written; 182 183 do 184 { 185 written = posix.write (handle, src.ptr, src.length); 186 } 187 while (written == -1 && errno == EINTR); 188 189 if (written is -1) 190 error(errno, "write"); 191 return written; 192 } 193 194 /*************************************************************************** 195 196 Read a chunk of bytes from the file from the given offset, 197 into the provided array 198 199 Params: 200 dst = destination buffer to fill 201 offset = offset to start reading from 202 203 Returns: 204 number of bytes read or Eof if there's no further data 205 206 Throws: 207 `File.IOException` on failure 208 209 ***************************************************************************/ 210 211 public size_t pread (void[] dst, off_t offset) 212 { 213 ssize_t read; 214 215 do 216 { 217 read = posix.pread (handle, dst.ptr, dst.length, 218 offset); 219 } 220 while (read == -1 && errno == EINTR); 221 222 if (read is -1) 223 error(errno, "pread"); 224 else 225 if (read is 0 && dst.length > 0) 226 return Eof; 227 return read; 228 } 229 230 /*************************************************************************** 231 232 Write a chunk of bytes to the file starting from the given offset, 233 from the provided array 234 235 Params: 236 src = source buffer to write data from 237 offset = offset to start writing from 238 239 Returns: 240 number of bytes written 241 242 Throws: 243 `File.IOException` on failure 244 245 ***************************************************************************/ 246 247 public size_t pwrite (const(void)[] src, off_t offset) 248 { 249 ssize_t written; 250 251 do 252 { 253 written = posix.pwrite (handle, src.ptr, src.length, 254 offset); 255 } 256 while (written == -1 && errno == EINTR); 257 258 if (written is -1) 259 error(errno, "pwrite"); 260 return written; 261 } 262 }