FileDescriptor.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #ifdef SERENITY
  8. #include "TTY.h"
  9. #endif
  10. RetainPtr<FileDescriptor> FileDescriptor::create(RetainPtr<VirtualFileSystem::Node>&& vnode)
  11. {
  12. return adopt(*new FileDescriptor(move(vnode)));
  13. }
  14. FileDescriptor::FileDescriptor(RetainPtr<VirtualFileSystem::Node>&& vnode)
  15. : m_vnode(move(vnode))
  16. {
  17. }
  18. FileDescriptor::~FileDescriptor()
  19. {
  20. }
  21. RetainPtr<FileDescriptor> FileDescriptor::clone()
  22. {
  23. auto descriptor = FileDescriptor::create(m_vnode.copyRef());
  24. if (!descriptor)
  25. return nullptr;
  26. descriptor->m_currentOffset = m_currentOffset;
  27. #ifdef SERENITY
  28. descriptor->m_isBlocking = m_isBlocking;
  29. #endif
  30. return descriptor;
  31. }
  32. #ifndef SERENITY
  33. bool additionWouldOverflow(Unix::off_t a, Unix::off_t b)
  34. {
  35. ASSERT(a > 0);
  36. uint64_t ua = a;
  37. return (ua + b) > maxFileOffset;
  38. }
  39. #endif
  40. int FileDescriptor::stat(Unix::stat* buffer)
  41. {
  42. if (!m_vnode)
  43. return -EBADF;
  44. auto metadata = m_vnode->metadata();
  45. if (!metadata.isValid())
  46. return -EIO;
  47. buffer->st_dev = 0; // FIXME
  48. buffer->st_ino = metadata.inode.index();
  49. buffer->st_mode = metadata.mode;
  50. buffer->st_nlink = metadata.linkCount;
  51. buffer->st_uid = metadata.uid;
  52. buffer->st_gid = metadata.gid;
  53. buffer->st_rdev = 0; // FIXME
  54. buffer->st_size = metadata.size;
  55. buffer->st_blksize = metadata.blockSize;
  56. buffer->st_blocks = metadata.blockCount;
  57. buffer->st_atime = metadata.atime;
  58. buffer->st_mtime = metadata.mtime;
  59. buffer->st_ctime = metadata.ctime;
  60. return 0;
  61. }
  62. Unix::off_t FileDescriptor::seek(Unix::off_t offset, int whence)
  63. {
  64. if (!m_vnode)
  65. return -EBADF;
  66. // FIXME: The file type should be cached on the vnode.
  67. // It's silly that we have to do a full metadata lookup here.
  68. auto metadata = m_vnode->metadata();
  69. if (!metadata.isValid())
  70. return -EIO;
  71. if (metadata.isSocket() || metadata.isFIFO())
  72. return -ESPIPE;
  73. Unix::off_t newOffset;
  74. switch (whence) {
  75. case SEEK_SET:
  76. newOffset = offset;
  77. break;
  78. case SEEK_CUR:
  79. newOffset = m_currentOffset + offset;
  80. #ifndef SERENITY
  81. if (additionWouldOverflow(m_currentOffset, offset))
  82. return -EOVERFLOW;
  83. #endif
  84. if (newOffset < 0)
  85. return -EINVAL;
  86. break;
  87. case SEEK_END:
  88. ASSERT(metadata.size); // FIXME: What do I do?
  89. newOffset = metadata.size;
  90. break;
  91. default:
  92. return -EINVAL;
  93. }
  94. m_currentOffset = newOffset;
  95. return m_currentOffset;
  96. }
  97. Unix::ssize_t FileDescriptor::read(byte* buffer, Unix::size_t count)
  98. {
  99. if (m_vnode->isCharacterDevice()) {
  100. // FIXME: What should happen to m_currentOffset?
  101. return m_vnode->characterDevice()->read(buffer, count);
  102. }
  103. Unix::ssize_t nread = m_vnode->fileSystem()->readInodeBytes(m_vnode->inode, m_currentOffset, count, buffer, this);
  104. m_currentOffset += nread;
  105. return nread;
  106. }
  107. Unix::ssize_t FileDescriptor::write(const byte* data, Unix::size_t size)
  108. {
  109. if (m_vnode->isCharacterDevice()) {
  110. // FIXME: What should happen to m_currentOffset?
  111. return m_vnode->characterDevice()->write(data, size);
  112. }
  113. // FIXME: Implement non-device writes.
  114. ASSERT_NOT_REACHED();
  115. return -1;
  116. }
  117. bool FileDescriptor::hasDataAvailableForRead()
  118. {
  119. if (m_vnode->isCharacterDevice())
  120. return m_vnode->characterDevice()->hasDataAvailableForRead();
  121. return true;
  122. }
  123. ByteBuffer FileDescriptor::readEntireFile()
  124. {
  125. if (m_vnode->isCharacterDevice()) {
  126. auto buffer = ByteBuffer::createUninitialized(1024);
  127. Unix::ssize_t nread = m_vnode->characterDevice()->read(buffer.pointer(), buffer.size());
  128. buffer.trim(nread);
  129. return buffer;
  130. }
  131. return m_vnode->fileSystem()->readEntireInode(m_vnode->inode, this);
  132. }
  133. bool FileDescriptor::isDirectory() const
  134. {
  135. return m_vnode->metadata().isDirectory();
  136. }
  137. ssize_t FileDescriptor::get_dir_entries(byte* buffer, Unix::size_t size)
  138. {
  139. auto metadata = m_vnode->metadata();
  140. if (!metadata.isValid())
  141. return -EIO;
  142. if (!metadata.isDirectory())
  143. return -ENOTDIR;
  144. // FIXME: Compute the actual size needed.
  145. auto tempBuffer = ByteBuffer::createUninitialized(2048);
  146. BufferStream stream(tempBuffer);
  147. m_vnode->vfs()->enumerateDirectoryInode(m_vnode->inode, [&stream] (auto& entry) {
  148. stream << (dword)entry.inode.index();
  149. stream << (byte)entry.fileType;
  150. stream << (dword)entry.name.length();
  151. stream << entry.name;
  152. return true;
  153. });
  154. if (size < stream.offset())
  155. return -1;
  156. memcpy(buffer, tempBuffer.pointer(), stream.offset());
  157. return stream.offset();
  158. }
  159. \
  160. #ifdef SERENITY
  161. bool FileDescriptor::isTTY() const
  162. {
  163. if (auto* device = m_vnode->characterDevice())
  164. return device->isTTY();
  165. return false;
  166. }
  167. const TTY* FileDescriptor::tty() const
  168. {
  169. if (auto* device = m_vnode->characterDevice())
  170. return static_cast<const TTY*>(device);
  171. return nullptr;
  172. }
  173. TTY* FileDescriptor::tty()
  174. {
  175. if (auto* device = m_vnode->characterDevice())
  176. return static_cast<TTY*>(device);
  177. return nullptr;
  178. }
  179. #endif
  180. int FileDescriptor::close()
  181. {
  182. return 0;
  183. }
  184. String FileDescriptor::absolute_path() const
  185. {
  186. #ifdef SERENITY
  187. if (isTTY())
  188. return tty()->ttyName();
  189. #endif
  190. return VirtualFileSystem::the().absolutePath(m_vnode->inode);
  191. }