#include "os_internal.h" #include #include #include #include namespace OS { namespace Internal { //std::deque FDTable; std::deque FDEntry::FDTable; FDEntry& FDEntry::allocate(int fd) { std::string noname; return allocate(fd, noname); } FDEntry& FDEntry::allocate(int fd, std::string &&filename) { if (fd < 0) throw std::out_of_range("Invalid FD"); if (FDTable.size() <= fd) FDTable.resize(fd + 1); auto &e = FDTable[fd]; e.refcount = 1; e.text = false; e.resource = false; e.filename = std::move(filename); return e; } FDEntry& FDEntry::allocate(int fd, const std::string &filename) { if (fd < 0) throw std::out_of_range("Invalid FD"); if (FDTable.size() <= fd) FDTable.resize(fd + 1); auto &e = FDTable[fd]; e.refcount = 1; e.text = false; e.resource = false; e.filename = filename; return e; } int FDEntry::close(int fd, bool force) { if (fd < 0 || fd >= FDTable.size()) { errno = EBADF; return -1; } auto &e = FDTable[fd]; if (!e.refcount) { errno = EBADF; return -1; } if (--e.refcount == 0 || force) { e.refcount = 0; return ::close(fd); } return 0; } ssize_t FDEntry::read(int fd, void *buffer, size_t count) { if (fd < 0 || fd >= FDTable.size()) { errno = EBADF; return -1; } auto const &e = FDTable[fd]; if (!e.refcount) { errno = EBADF; return -1; } // hmm... keep a current seek position? ssize_t size; if (e.text) { std::unique_ptr trbuffer(new uint8_t[count]); size = ::read(fd, trbuffer.get(), count); if (size > 0) { std::transform(trbuffer.get(), trbuffer.get() + size, (uint8_t *)buffer, [](uint8_t c) { return c == '\n' ? '\r' : c; } ); } } else { size = ::read(fd, buffer, count); } return size; } ssize_t FDEntry::write(int fd, const void *buffer, size_t count) { if (fd < 0 || fd >= FDTable.size()) { errno = EBADF; return -1; } auto const &e = FDTable[fd]; if (!e.refcount) { errno = EBADF; return -1; } // hmm... keep a current seek position? ssize_t size; if (e.text) { std::unique_ptr trbuffer(new uint8_t[count]); if (count > 0) { std::transform((const uint8_t *)buffer, (const uint8_t *)buffer + count, trbuffer.get(), [](uint8_t c) { return c == '\r' ? '\n' : c; } ); } size = ::write(fd, trbuffer.get(), count); } else { size = ::write(fd, buffer, count); } return size; } } }