FileHandle.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #include "FileHandle.h"
  2. #include "FileSystem.h"
  3. #include "CharacterDevice.h"
  4. #include "sys-errno.h"
  5. #include "UnixTypes.h"
  6. FileHandle::FileHandle(RetainPtr<VirtualFileSystem::Node>&& vnode)
  7. : m_vnode(move(vnode))
  8. {
  9. }
  10. FileHandle::~FileHandle()
  11. {
  12. }
  13. #ifndef SERENITY_KERNEL
  14. bool additionWouldOverflow(Unix::off_t a, Unix::off_t b)
  15. {
  16. ASSERT(a > 0);
  17. uint64_t ua = a;
  18. return (ua + b) > maxFileOffset;
  19. }
  20. #endif
  21. int FileHandle::stat(Unix::stat* buffer)
  22. {
  23. if (!m_vnode)
  24. return -EBADF;
  25. auto metadata = m_vnode->inode.metadata();
  26. if (!metadata.isValid())
  27. return -EIO;
  28. buffer->st_dev = 0; // FIXME
  29. buffer->st_ino = metadata.inode.index();
  30. buffer->st_mode = metadata.mode;
  31. buffer->st_nlink = metadata.linkCount;
  32. buffer->st_uid = metadata.uid;
  33. buffer->st_gid = metadata.gid;
  34. buffer->st_rdev = 0; // FIXME
  35. buffer->st_size = metadata.size;
  36. buffer->st_blksize = metadata.blockSize;
  37. buffer->st_blocks = metadata.blockCount;
  38. buffer->st_atime = metadata.atime;
  39. buffer->st_mtime = metadata.mtime;
  40. buffer->st_ctime = metadata.ctime;
  41. return 0;
  42. }
  43. Unix::off_t FileHandle::seek(Unix::off_t offset, int whence)
  44. {
  45. if (!m_vnode)
  46. return -EBADF;
  47. // FIXME: The file type should be cached on the vnode.
  48. // It's silly that we have to do a full metadata lookup here.
  49. auto metadata = m_vnode->inode.metadata();
  50. if (!metadata.isValid())
  51. return -EIO;
  52. if (metadata.isSocket() || metadata.isFIFO())
  53. return -ESPIPE;
  54. Unix::off_t newOffset;
  55. switch (whence) {
  56. case SEEK_SET:
  57. newOffset = offset;
  58. break;
  59. case SEEK_CUR:
  60. newOffset = m_currentOffset + offset;
  61. #ifndef SERENITY_KERNEL
  62. if (additionWouldOverflow(m_currentOffset, offset))
  63. return -EOVERFLOW;
  64. #endif
  65. if (newOffset < 0)
  66. return -EINVAL;
  67. break;
  68. case SEEK_END:
  69. // FIXME: Implement!
  70. notImplemented();
  71. newOffset = 0;
  72. break;
  73. default:
  74. return -EINVAL;
  75. }
  76. m_currentOffset = newOffset;
  77. return m_currentOffset;
  78. }
  79. Unix::ssize_t FileHandle::read(byte* buffer, Unix::size_t count)
  80. {
  81. if (m_vnode->isCharacterDevice()) {
  82. // FIXME: What should happen to m_currentOffset?
  83. return m_vnode->characterDevice()->read(buffer, count);
  84. }
  85. Unix::ssize_t nread = m_vnode->fileSystem()->readInodeBytes(m_vnode->inode, m_currentOffset, count, buffer);
  86. m_currentOffset += nread;
  87. return nread;
  88. }
  89. ByteBuffer FileHandle::readEntireFile()
  90. {
  91. if (m_vnode->isCharacterDevice()) {
  92. auto buffer = ByteBuffer::createUninitialized(1024);
  93. Unix::ssize_t nread = m_vnode->characterDevice()->read(buffer.pointer(), buffer.size());
  94. buffer.trim(nread);
  95. return buffer;
  96. }
  97. return m_vnode->fileSystem()->readEntireInode(m_vnode->inode);
  98. }