Serenity Operating System
at hosted 307 lines 8.3 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/ByteBuffer.h> 28#include <AK/PrintfImplementation.h> 29#include <LibCore/IODevice.h> 30#include <LibCore/SyscallUtils.h> 31#include <errno.h> 32#include <stdio.h> 33#include <string.h> 34#include <sys/select.h> 35#include <sys/stat.h> 36#include <sys/time.h> 37#include <unistd.h> 38 39namespace Core { 40 41IODevice::IODevice(Object* parent) 42 : Object(parent) 43{ 44} 45 46IODevice::~IODevice() 47{ 48} 49 50const char* IODevice::error_string() const 51{ 52 return strerror(m_error); 53} 54 55int IODevice::read(u8* buffer, int length) 56{ 57 auto read_buffer = read(length); 58 if (read_buffer.is_null()) 59 return 0; 60 memcpy(buffer, read_buffer.data(), length); 61 return read_buffer.size(); 62} 63 64ByteBuffer IODevice::read(size_t max_size) 65{ 66 if (m_fd < 0) 67 return {}; 68 if (!max_size) 69 return {}; 70 auto buffer = ByteBuffer::create_uninitialized(max_size); 71 auto* buffer_ptr = (char*)buffer.data(); 72 size_t remaining_buffer_space = buffer.size(); 73 size_t taken_from_buffered = 0; 74 if (!m_buffered_data.is_empty()) { 75 taken_from_buffered = min(remaining_buffer_space, m_buffered_data.size()); 76 memcpy(buffer_ptr, m_buffered_data.data(), taken_from_buffered); 77 Vector<u8> new_buffered_data; 78 new_buffered_data.append(m_buffered_data.data() + taken_from_buffered, m_buffered_data.size() - taken_from_buffered); 79 m_buffered_data = move(new_buffered_data); 80 remaining_buffer_space -= taken_from_buffered; 81 buffer_ptr += taken_from_buffered; 82 } 83 if (!remaining_buffer_space) 84 return buffer; 85 int nread = ::read(m_fd, buffer_ptr, remaining_buffer_space); 86 if (nread < 0) { 87 if (taken_from_buffered) { 88 buffer.trim(taken_from_buffered); 89 return buffer; 90 } 91 set_error(errno); 92 return {}; 93 } 94 if (nread == 0) { 95 set_eof(true); 96 if (taken_from_buffered) { 97 buffer.trim(taken_from_buffered); 98 return buffer; 99 } 100 return {}; 101 } 102 buffer.trim(taken_from_buffered + nread); 103 return buffer; 104} 105 106bool IODevice::can_read_from_fd() const 107{ 108 // FIXME: Can we somehow remove this once Core::Socket is implemented using non-blocking sockets? 109 fd_set rfds; 110 FD_ZERO(&rfds); 111 FD_SET(m_fd, &rfds); 112 struct timeval timeout { 113 0, 0 114 }; 115 int rc = Core::safe_syscall(select, m_fd + 1, &rfds, nullptr, nullptr, &timeout); 116 if (rc < 0) { 117 // NOTE: We don't set m_error here. 118 perror("IODevice::can_read: select"); 119 return false; 120 } 121 return FD_ISSET(m_fd, &rfds); 122} 123 124bool IODevice::can_read_line() 125{ 126 if (m_eof && !m_buffered_data.is_empty()) 127 return true; 128 if (m_buffered_data.contains_slow('\n')) 129 return true; 130 if (!can_read_from_fd()) 131 return false; 132 populate_read_buffer(); 133 return m_buffered_data.contains_slow('\n'); 134} 135 136bool IODevice::can_read() const 137{ 138 return !m_buffered_data.is_empty() || can_read_from_fd(); 139} 140 141ByteBuffer IODevice::read_all() 142{ 143 off_t file_size = 0; 144 struct stat st; 145 int rc = fstat(fd(), &st); 146 if (rc == 0) 147 file_size = st.st_size; 148 149 Vector<u8> data; 150 data.ensure_capacity(file_size); 151 152 if (!m_buffered_data.is_empty()) { 153 data.append(m_buffered_data.data(), m_buffered_data.size()); 154 m_buffered_data.clear(); 155 } 156 157 while (true) { 158 char read_buffer[4096]; 159 int nread = ::read(m_fd, read_buffer, sizeof(read_buffer)); 160 if (nread < 0) { 161 set_error(errno); 162 break; 163 } 164 if (nread == 0) { 165 set_eof(true); 166 break; 167 } 168 data.append((const u8*)read_buffer, nread); 169 } 170 if (data.is_empty()) 171 return {}; 172 return ByteBuffer::copy(data.data(), data.size()); 173} 174 175ByteBuffer IODevice::read_line(size_t max_size) 176{ 177 if (m_fd < 0) 178 return {}; 179 if (!max_size) 180 return {}; 181 if (!can_read_line()) 182 return {}; 183 if (m_eof) { 184 if (m_buffered_data.size() > max_size) { 185 dbgprintf("IODevice::read_line: At EOF but there's more than max_size(%zu) buffered\n", max_size); 186 return {}; 187 } 188 auto buffer = ByteBuffer::copy(m_buffered_data.data(), m_buffered_data.size()); 189 m_buffered_data.clear(); 190 return buffer; 191 } 192 auto line = ByteBuffer::create_uninitialized(max_size + 1); 193 size_t line_index = 0; 194 while (line_index < max_size) { 195 u8 ch = m_buffered_data[line_index]; 196 line[line_index++] = ch; 197 if (ch == '\n') { 198 Vector<u8> new_buffered_data; 199 new_buffered_data.append(m_buffered_data.data() + line_index, m_buffered_data.size() - line_index); 200 m_buffered_data = move(new_buffered_data); 201 line[line_index] = '\0'; 202 line.trim(line_index + 1); 203 return line; 204 } 205 } 206 return {}; 207} 208 209bool IODevice::populate_read_buffer() 210{ 211 if (m_fd < 0) 212 return false; 213 u8 buffer[1024]; 214 int nread = ::read(m_fd, buffer, sizeof(buffer)); 215 if (nread < 0) { 216 set_error(errno); 217 return false; 218 } 219 if (nread == 0) { 220 set_eof(true); 221 return false; 222 } 223 m_buffered_data.append(buffer, nread); 224 return true; 225} 226 227bool IODevice::close() 228{ 229 if (fd() < 0 || mode() == NotOpen) 230 return false; 231 int rc = ::close(fd()); 232 if (rc < 0) { 233 set_error(errno); 234 return false; 235 } 236 set_fd(-1); 237 set_mode(IODevice::NotOpen); 238 return true; 239} 240 241bool IODevice::seek(i64 offset, SeekMode mode, off_t* pos) 242{ 243 int m = SEEK_SET; 244 switch (mode) { 245 case SeekMode::SetPosition: 246 m = SEEK_SET; 247 break; 248 case SeekMode::FromCurrentPosition: 249 m = SEEK_CUR; 250 break; 251 case SeekMode::FromEndPosition: 252 m = SEEK_END; 253 break; 254 } 255 off_t rc = lseek(m_fd, offset, m); 256 if (rc < 0) { 257 set_error(errno); 258 if (pos) 259 *pos = -1; 260 return false; 261 } 262 m_buffered_data.clear(); 263 m_eof = false; 264 if (pos) 265 *pos = rc; 266 return true; 267} 268 269bool IODevice::write(const u8* data, int size) 270{ 271 int rc = ::write(m_fd, data, size); 272 if (rc < 0) { 273 perror("IODevice::write: write"); 274 set_error(errno); 275 return false; 276 } 277 return rc == size; 278} 279 280int IODevice::printf(const char* format, ...) 281{ 282 va_list ap; 283 va_start(ap, format); 284 // FIXME: We're not propagating write() failures to client here! 285 int ret = printf_internal([this](char*&, char ch) { 286 write((const u8*)&ch, 1); 287 }, 288 nullptr, format, ap); 289 va_end(ap); 290 return ret; 291} 292 293void IODevice::set_fd(int fd) 294{ 295 if (m_fd == fd) 296 return; 297 298 m_fd = fd; 299 did_update_fd(fd); 300} 301 302bool IODevice::write(const StringView& v) 303{ 304 return write((const u8*)v.characters_without_null_termination(), v.length()); 305} 306 307}