| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 22:29:06 +01:00
										 |  |  | #include <AK/ByteBuffer.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-06 15:04:03 +01:00
										 |  |  | #include <LibCore/IODevice.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-22 21:21:57 +02:00
										 |  |  | #include <errno.h>
 | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-08 12:05:14 +01:00
										 |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:48:06 +02:00
										 |  |  | #include <sys/select.h>
 | 
					
						
							| 
									
										
										
										
											2019-07-27 14:24:19 +02:00
										 |  |  | #include <sys/stat.h>
 | 
					
						
							| 
									
										
										
										
											2019-05-28 13:48:06 +02:00
										 |  |  | #include <sys/time.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | namespace Core { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IODevice::IODevice(Object* parent) | 
					
						
							|  |  |  |     : Object(parent) | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | IODevice::~IODevice() | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | const char* IODevice::error_string() const | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return strerror(m_error); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | int IODevice::read(u8* buffer, int length) | 
					
						
							| 
									
										
										
										
											2019-07-27 16:37:48 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     auto read_buffer = read(length); | 
					
						
							| 
									
										
										
										
											2019-09-11 21:13:14 +02:00
										 |  |  |     if (read_buffer.is_null()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-07-27 16:37:48 +02:00
										 |  |  |     memcpy(buffer, read_buffer.data(), length); | 
					
						
							|  |  |  |     return read_buffer.size(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  | ByteBuffer IODevice::read(size_t max_size) | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (m_fd < 0) | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:37 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |     if (!max_size) | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:37 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |     auto buffer = ByteBuffer::create_uninitialized(max_size); | 
					
						
							| 
									
										
										
										
											2019-09-30 08:57:01 +02:00
										 |  |  |     auto* buffer_ptr = (char*)buffer.data(); | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |     size_t remaining_buffer_space = buffer.size(); | 
					
						
							|  |  |  |     size_t taken_from_buffered = 0; | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |     if (!m_buffered_data.is_empty()) { | 
					
						
							| 
									
										
										
										
											2019-06-22 23:07:42 +02:00
										 |  |  |         taken_from_buffered = min(remaining_buffer_space, m_buffered_data.size()); | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |         memcpy(buffer_ptr, m_buffered_data.data(), taken_from_buffered); | 
					
						
							| 
									
										
										
										
											2019-07-03 21:17:35 +02:00
										 |  |  |         Vector<u8> new_buffered_data; | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |         new_buffered_data.append(m_buffered_data.data() + taken_from_buffered, m_buffered_data.size() - taken_from_buffered); | 
					
						
							|  |  |  |         m_buffered_data = move(new_buffered_data); | 
					
						
							|  |  |  |         remaining_buffer_space -= taken_from_buffered; | 
					
						
							|  |  |  |         buffer_ptr += taken_from_buffered; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!remaining_buffer_space) | 
					
						
							|  |  |  |         return buffer; | 
					
						
							|  |  |  |     int nread = ::read(m_fd, buffer_ptr, remaining_buffer_space); | 
					
						
							|  |  |  |     if (nread < 0) { | 
					
						
							| 
									
										
										
										
											2019-06-22 23:07:42 +02:00
										 |  |  |         if (taken_from_buffered) { | 
					
						
							|  |  |  |             buffer.trim(taken_from_buffered); | 
					
						
							|  |  |  |             return buffer; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |         set_error(errno); | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:37 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-07 14:36:10 +02:00
										 |  |  |     if (nread == 0) { | 
					
						
							|  |  |  |         set_eof(true); | 
					
						
							| 
									
										
										
										
											2019-06-22 23:07:42 +02:00
										 |  |  |         if (taken_from_buffered) { | 
					
						
							|  |  |  |             buffer.trim(taken_from_buffered); | 
					
						
							|  |  |  |             return buffer; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:37 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2019-04-07 14:36:10 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-22 23:07:42 +02:00
										 |  |  |     buffer.trim(taken_from_buffered + nread); | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |     return buffer; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | bool IODevice::can_read_from_fd() const | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-07 11:37:51 +13:00
										 |  |  |     // FIXME: Can we somehow remove this once Core::Socket is implemented using non-blocking sockets?
 | 
					
						
							| 
									
										
										
										
											2021-04-21 20:05:00 +02:00
										 |  |  |     fd_set rfds {}; | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  |     FD_ZERO(&rfds); | 
					
						
							|  |  |  |     FD_SET(m_fd, &rfds); | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:37 +02:00
										 |  |  |     struct timeval timeout { | 
					
						
							|  |  |  |         0, 0 | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-04-21 20:05:00 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (;;) { | 
					
						
							|  |  |  |         if (select(m_fd + 1, &rfds, nullptr, nullptr, &timeout) < 0) { | 
					
						
							|  |  |  |             if (errno == EINTR) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             perror("IODevice::can_read_from_fd: select"); | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     return FD_ISSET(m_fd, &rfds); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-15 10:45:09 +04:30
										 |  |  | bool IODevice::can_read_line() const | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (m_eof && !m_buffered_data.is_empty()) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     if (m_buffered_data.contains_slow('\n')) | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2019-03-18 14:38:30 +01:00
										 |  |  |     if (!can_read_from_fd()) | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     populate_read_buffer(); | 
					
						
							| 
									
										
										
										
											2020-10-25 13:34:52 +01:00
										 |  |  |     if (m_eof && !m_buffered_data.is_empty()) | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  |     return m_buffered_data.contains_slow('\n'); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | bool IODevice::can_read() const | 
					
						
							| 
									
										
										
										
											2019-03-18 14:38:30 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return !m_buffered_data.is_empty() || can_read_from_fd(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | ByteBuffer IODevice::read_all() | 
					
						
							| 
									
										
										
										
											2019-03-18 14:38:30 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-07-27 14:24:19 +02:00
										 |  |  |     off_t file_size = 0; | 
					
						
							|  |  |  |     struct stat st; | 
					
						
							|  |  |  |     int rc = fstat(fd(), &st); | 
					
						
							|  |  |  |     if (rc == 0) | 
					
						
							|  |  |  |         file_size = st.st_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Vector<u8> data; | 
					
						
							|  |  |  |     data.ensure_capacity(file_size); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-18 14:38:30 +01:00
										 |  |  |     if (!m_buffered_data.is_empty()) { | 
					
						
							| 
									
										
										
										
											2019-07-27 14:24:19 +02:00
										 |  |  |         data.append(m_buffered_data.data(), m_buffered_data.size()); | 
					
						
							| 
									
										
										
										
											2019-03-18 14:38:30 +01:00
										 |  |  |         m_buffered_data.clear(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-17 21:51:23 +03:00
										 |  |  |     while (true) { | 
					
						
							| 
									
										
										
										
											2019-03-18 14:38:30 +01:00
										 |  |  |         char read_buffer[4096]; | 
					
						
							|  |  |  |         int nread = ::read(m_fd, read_buffer, sizeof(read_buffer)); | 
					
						
							|  |  |  |         if (nread < 0) { | 
					
						
							| 
									
										
										
										
											2019-08-17 11:07:15 +02:00
										 |  |  |             set_error(errno); | 
					
						
							| 
									
										
										
										
											2019-09-11 19:33:51 +02:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2019-03-18 14:38:30 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (nread == 0) { | 
					
						
							|  |  |  |             set_eof(true); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-07-27 14:24:19 +02:00
										 |  |  |         data.append((const u8*)read_buffer, nread); | 
					
						
							| 
									
										
										
										
											2019-03-18 14:38:30 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-09-11 19:33:51 +02:00
										 |  |  |     if (data.is_empty()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2019-07-27 14:24:19 +02:00
										 |  |  |     return ByteBuffer::copy(data.data(), data.size()); | 
					
						
							| 
									
										
										
										
											2019-03-18 14:38:30 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-13 11:44:53 +01:00
										 |  |  | String IODevice::read_line(size_t max_size) | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-07 20:18:58 +02:00
										 |  |  |     if (m_fd < 0) | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:37 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2019-04-07 20:18:58 +02:00
										 |  |  |     if (!max_size) | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:37 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2019-04-07 20:18:58 +02:00
										 |  |  |     if (!can_read_line()) | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:37 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  |     if (m_eof) { | 
					
						
							|  |  |  |         if (m_buffered_data.size() > max_size) { | 
					
						
							| 
									
										
										
										
											2021-02-17 15:40:52 +01:00
										 |  |  |             dbgln("IODevice::read_line: At EOF but there's more than max_size({}) buffered", max_size); | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:37 +02:00
										 |  |  |             return {}; | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-13 11:44:53 +01:00
										 |  |  |         auto line = String((const char*)m_buffered_data.data(), m_buffered_data.size(), Chomp); | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  |         m_buffered_data.clear(); | 
					
						
							| 
									
										
										
										
											2020-12-13 11:44:53 +01:00
										 |  |  |         return line; | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     auto line = ByteBuffer::create_uninitialized(max_size + 1); | 
					
						
							| 
									
										
										
										
											2020-02-25 14:49:47 +01:00
										 |  |  |     size_t line_index = 0; | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  |     while (line_index < max_size) { | 
					
						
							| 
									
										
										
										
											2019-07-03 21:17:35 +02:00
										 |  |  |         u8 ch = m_buffered_data[line_index]; | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |         line[line_index++] = ch; | 
					
						
							|  |  |  |         if (ch == '\n') { | 
					
						
							| 
									
										
										
										
											2019-07-03 21:17:35 +02:00
										 |  |  |             Vector<u8> new_buffered_data; | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |             new_buffered_data.append(m_buffered_data.data() + line_index, m_buffered_data.size() - line_index); | 
					
						
							|  |  |  |             m_buffered_data = move(new_buffered_data); | 
					
						
							| 
									
										
										
										
											2020-11-28 18:10:03 +03:30
										 |  |  |             line.trim(line_index); | 
					
						
							| 
									
										
										
										
											2020-12-13 11:44:53 +01:00
										 |  |  |             return String::copy(line, Chomp); | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-07 11:46:37 +02:00
										 |  |  |     return {}; | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-15 10:45:09 +04:30
										 |  |  | bool IODevice::populate_read_buffer() const | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (m_fd < 0) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2019-07-03 21:17:35 +02:00
										 |  |  |     u8 buffer[1024]; | 
					
						
							| 
									
										
										
										
											2019-05-14 16:36:29 +02:00
										 |  |  |     int nread = ::read(m_fd, buffer, sizeof(buffer)); | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |     if (nread < 0) { | 
					
						
							|  |  |  |         set_error(errno); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (nread == 0) { | 
					
						
							|  |  |  |         set_eof(true); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-05-14 16:36:29 +02:00
										 |  |  |     m_buffered_data.append(buffer, nread); | 
					
						
							| 
									
										
										
										
											2019-03-17 15:54:43 +01:00
										 |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | bool IODevice::close() | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (fd() < 0 || mode() == NotOpen) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     int rc = ::close(fd()); | 
					
						
							|  |  |  |     if (rc < 0) { | 
					
						
							| 
									
										
										
										
											2019-08-17 11:07:15 +02:00
										 |  |  |         set_error(errno); | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     set_fd(-1); | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |     set_mode(IODevice::NotOpen); | 
					
						
							| 
									
										
										
										
											2019-03-18 14:09:58 +01:00
										 |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-16 00:51:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | bool IODevice::seek(i64 offset, SeekMode mode, off_t* pos) | 
					
						
							| 
									
										
										
										
											2019-04-16 00:51:05 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-16 15:02:17 +02:00
										 |  |  |     int m = SEEK_SET; | 
					
						
							|  |  |  |     switch (mode) { | 
					
						
							|  |  |  |     case SeekMode::SetPosition: | 
					
						
							|  |  |  |         m = SEEK_SET; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SeekMode::FromCurrentPosition: | 
					
						
							|  |  |  |         m = SEEK_CUR; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case SeekMode::FromEndPosition: | 
					
						
							|  |  |  |         m = SEEK_END; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     off_t rc = lseek(m_fd, offset, m); | 
					
						
							| 
									
										
										
										
											2019-04-16 00:51:05 +02:00
										 |  |  |     if (rc < 0) { | 
					
						
							| 
									
										
										
										
											2019-05-16 15:02:17 +02:00
										 |  |  |         set_error(errno); | 
					
						
							|  |  |  |         if (pos) | 
					
						
							|  |  |  |             *pos = -1; | 
					
						
							| 
									
										
										
										
											2019-04-16 00:51:05 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     m_buffered_data.clear(); | 
					
						
							| 
									
										
										
										
											2019-04-18 02:09:15 +02:00
										 |  |  |     m_eof = false; | 
					
						
							| 
									
										
										
										
											2019-05-16 15:02:17 +02:00
										 |  |  |     if (pos) | 
					
						
							|  |  |  |         *pos = rc; | 
					
						
							| 
									
										
										
										
											2019-04-16 00:51:05 +02:00
										 |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-05-08 04:38:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-06 16:09:26 +02:00
										 |  |  | bool IODevice::truncate(off_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int rc = ftruncate(m_fd, size); | 
					
						
							|  |  |  |     if (rc < 0) { | 
					
						
							|  |  |  |         set_error(errno); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | bool IODevice::write(const u8* data, int size) | 
					
						
							| 
									
										
										
										
											2019-05-08 04:38:41 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     int rc = ::write(m_fd, data, size); | 
					
						
							|  |  |  |     if (rc < 0) { | 
					
						
							| 
									
										
										
										
											2019-06-02 15:18:27 +02:00
										 |  |  |         set_error(errno); | 
					
						
							| 
									
										
										
										
											2021-04-10 19:17:30 +02:00
										 |  |  |         perror("IODevice::write: write"); | 
					
						
							| 
									
										
										
										
											2019-05-08 04:38:41 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return rc == size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | void IODevice::set_fd(int fd) | 
					
						
							| 
									
										
										
										
											2019-07-27 10:47:46 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (m_fd == fd) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_fd = fd; | 
					
						
							|  |  |  |     did_update_fd(fd); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-02-14 22:29:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | bool IODevice::write(const StringView& v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return write((const u8*)v.characters_without_null_termination(), v.length()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-11 21:40:09 +03:30
										 |  |  | LineIterator::LineIterator(IODevice& device, bool is_end) | 
					
						
							|  |  |  |     : m_device(device) | 
					
						
							|  |  |  |     , m_is_end(is_end) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ++*this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool LineIterator::at_end() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return m_device->eof(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LineIterator& LineIterator::operator++() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_buffer = m_device->read_line(); | 
					
						
							|  |  |  |     return *this; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | } |