FileDescriptor.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. #include "FileDescriptor.h"
  2. #include "FileSystem.h"
  3. #include "CharacterDevice.h"
  4. #include <LibC/errno_numbers.h>
  5. #include "UnixTypes.h"
  6. #include <AK/BufferStream.h>
  7. #include "FIFO.h"
  8. #ifdef SERENITY
  9. #include "TTY.h"
  10. #endif
  11. RetainPtr<FileDescriptor> FileDescriptor::create(RetainPtr<Vnode>&& vnode)
  12. {
  13. return adopt(*new FileDescriptor(move(vnode)));
  14. }
  15. RetainPtr<FileDescriptor> FileDescriptor::create_pipe_writer(FIFO& fifo)
  16. {
  17. return adopt(*new FileDescriptor(fifo, FIFO::Writer));
  18. }
  19. RetainPtr<FileDescriptor> FileDescriptor::create_pipe_reader(FIFO& fifo)
  20. {
  21. return adopt(*new FileDescriptor(fifo, FIFO::Reader));
  22. }
  23. FileDescriptor::FileDescriptor(RetainPtr<Vnode>&& vnode)
  24. : m_vnode(move(vnode))
  25. {
  26. }
  27. FileDescriptor::~FileDescriptor()
  28. {
  29. if (m_fifo)
  30. m_fifo->close(fifo_direction());
  31. }
  32. RetainPtr<FileDescriptor> FileDescriptor::clone()
  33. {
  34. RetainPtr<FileDescriptor> descriptor;
  35. if (is_fifo()) {
  36. descriptor = fifo_direction() == FIFO::Reader
  37. ? FileDescriptor::create_pipe_reader(*m_fifo)
  38. : FileDescriptor::create_pipe_writer(*m_fifo);
  39. } else {
  40. descriptor = FileDescriptor::create(m_vnode.copyRef());
  41. }
  42. if (!descriptor)
  43. return nullptr;
  44. descriptor->m_current_offset = m_current_offset;
  45. #ifdef SERENITY
  46. descriptor->m_is_blocking = m_is_blocking;
  47. descriptor->m_file_flags = m_file_flags;
  48. #endif
  49. return descriptor;
  50. }
  51. #ifndef SERENITY
  52. bool additionWouldOverflow(Unix::off_t a, Unix::off_t b)
  53. {
  54. ASSERT(a > 0);
  55. uint64_t ua = a;
  56. return (ua + b) > maxFileOffset;
  57. }
  58. #endif
  59. int FileDescriptor::stat(Unix::stat* buffer)
  60. {
  61. ASSERT(!is_fifo());
  62. if (!m_vnode)
  63. return -EBADF;
  64. auto metadata = m_vnode->metadata();
  65. if (!metadata.isValid())
  66. return -EIO;
  67. buffer->st_dev = 0; // FIXME
  68. buffer->st_ino = metadata.inode.index();
  69. buffer->st_mode = metadata.mode;
  70. buffer->st_nlink = metadata.linkCount;
  71. buffer->st_uid = metadata.uid;
  72. buffer->st_gid = metadata.gid;
  73. buffer->st_rdev = 0; // FIXME
  74. buffer->st_size = metadata.size;
  75. buffer->st_blksize = metadata.blockSize;
  76. buffer->st_blocks = metadata.blockCount;
  77. buffer->st_atime = metadata.atime;
  78. buffer->st_mtime = metadata.mtime;
  79. buffer->st_ctime = metadata.ctime;
  80. return 0;
  81. }
  82. Unix::off_t FileDescriptor::seek(Unix::off_t offset, int whence)
  83. {
  84. ASSERT(!is_fifo());
  85. if (!m_vnode)
  86. return -EBADF;
  87. // FIXME: The file type should be cached on the vnode.
  88. // It's silly that we have to do a full metadata lookup here.
  89. auto metadata = m_vnode->metadata();
  90. if (!metadata.isValid())
  91. return -EIO;
  92. if (metadata.isSocket() || metadata.isFIFO())
  93. return -ESPIPE;
  94. Unix::off_t newOffset;
  95. switch (whence) {
  96. case SEEK_SET:
  97. newOffset = offset;
  98. break;
  99. case SEEK_CUR:
  100. newOffset = m_current_offset + offset;
  101. #ifndef SERENITY
  102. if (additionWouldOverflow(m_currentOffset, offset))
  103. return -EOVERFLOW;
  104. #endif
  105. if (newOffset < 0)
  106. return -EINVAL;
  107. break;
  108. case SEEK_END:
  109. ASSERT(metadata.size); // FIXME: What do I do?
  110. newOffset = metadata.size;
  111. break;
  112. default:
  113. return -EINVAL;
  114. }
  115. m_current_offset = newOffset;
  116. return m_current_offset;
  117. }
  118. ssize_t FileDescriptor::read(byte* buffer, size_t count)
  119. {
  120. if (is_fifo()) {
  121. ASSERT(fifo_direction() == FIFO::Reader);
  122. return m_fifo->read(buffer, count);
  123. }
  124. if (m_vnode->isCharacterDevice()) {
  125. // FIXME: What should happen to m_currentOffset?
  126. return m_vnode->characterDevice()->read(buffer, count);
  127. }
  128. ASSERT(inode());
  129. ssize_t nread = inode()->read_bytes(m_current_offset, count, buffer, this);
  130. m_current_offset += nread;
  131. return nread;
  132. }
  133. ssize_t FileDescriptor::write(const byte* data, size_t size)
  134. {
  135. if (is_fifo()) {
  136. ASSERT(fifo_direction() == FIFO::Writer);
  137. return m_fifo->write(data, size);
  138. }
  139. if (m_vnode->isCharacterDevice()) {
  140. // FIXME: What should happen to m_currentOffset?
  141. return m_vnode->characterDevice()->write(data, size);
  142. }
  143. // FIXME: Implement non-device writes.
  144. ASSERT_NOT_REACHED();
  145. return -1;
  146. }
  147. bool FileDescriptor::can_write()
  148. {
  149. if (is_fifo()) {
  150. ASSERT(fifo_direction() == FIFO::Writer);
  151. return m_fifo->can_write();
  152. }
  153. return true;
  154. }
  155. bool FileDescriptor::has_data_available_for_reading(Process& process)
  156. {
  157. if (is_fifo()) {
  158. ASSERT(fifo_direction() == FIFO::Reader);
  159. return m_fifo->can_read();
  160. }
  161. if (m_vnode->isCharacterDevice())
  162. return m_vnode->characterDevice()->has_data_available_for_reading(process);
  163. return true;
  164. }
  165. ByteBuffer FileDescriptor::read_entire_file()
  166. {
  167. ASSERT(!is_fifo());
  168. if (m_vnode->isCharacterDevice()) {
  169. auto buffer = ByteBuffer::create_uninitialized(1024);
  170. ssize_t nread = m_vnode->characterDevice()->read(buffer.pointer(), buffer.size());
  171. buffer.trim(nread);
  172. return buffer;
  173. }
  174. ASSERT(inode());
  175. return inode()->read_entire(this);
  176. }
  177. bool FileDescriptor::is_directory() const
  178. {
  179. ASSERT(!is_fifo());
  180. return m_vnode->metadata().isDirectory();
  181. }
  182. ssize_t FileDescriptor::get_dir_entries(byte* buffer, size_t size)
  183. {
  184. auto metadata = m_vnode->metadata();
  185. if (!metadata.isValid())
  186. return -EIO;
  187. if (!metadata.isDirectory())
  188. return -ENOTDIR;
  189. // FIXME: Compute the actual size needed.
  190. auto tempBuffer = ByteBuffer::create_uninitialized(2048);
  191. BufferStream stream(tempBuffer);
  192. m_vnode->vfs()->traverse_directory_inode(*m_vnode->core_inode(), [&stream] (auto& entry) {
  193. stream << (dword)entry.inode.index();
  194. stream << (byte)entry.fileType;
  195. stream << (dword)entry.name_length;
  196. stream << entry.name;
  197. return true;
  198. });
  199. if (size < stream.offset())
  200. return -1;
  201. memcpy(buffer, tempBuffer.pointer(), stream.offset());
  202. return stream.offset();
  203. }
  204. \
  205. #ifdef SERENITY
  206. bool FileDescriptor::is_tty() const
  207. {
  208. if (is_fifo())
  209. return false;
  210. if (auto* device = m_vnode->characterDevice())
  211. return device->is_tty();
  212. return false;
  213. }
  214. const TTY* FileDescriptor::tty() const
  215. {
  216. if (is_fifo())
  217. return nullptr;
  218. if (auto* device = m_vnode->characterDevice())
  219. return static_cast<const TTY*>(device);
  220. return nullptr;
  221. }
  222. TTY* FileDescriptor::tty()
  223. {
  224. if (is_fifo())
  225. return nullptr;
  226. if (auto* device = m_vnode->characterDevice())
  227. return static_cast<TTY*>(device);
  228. return nullptr;
  229. }
  230. #endif
  231. int FileDescriptor::close()
  232. {
  233. return 0;
  234. }
  235. String FileDescriptor::absolute_path()
  236. {
  237. Stopwatch sw("absolute_path");
  238. #ifdef SERENITY
  239. if (is_tty())
  240. return tty()->tty_name();
  241. #endif
  242. if (is_fifo()) {
  243. char buf[32];
  244. ksprintf(buf, "fifo:%x", m_fifo.ptr());
  245. return buf;
  246. }
  247. ASSERT(m_vnode->core_inode());
  248. return VFS::the().absolute_path(*m_vnode->core_inode());
  249. }
  250. FileDescriptor::FileDescriptor(FIFO& fifo, FIFO::Direction direction)
  251. : m_is_blocking(true)
  252. , m_fifo(fifo)
  253. , m_fifo_direction(direction)
  254. {
  255. m_fifo->open(direction);
  256. }