/* * Copyright 2014 Cloudius Systems */ #ifndef FILE_HH_ #define FILE_HH_ #include "stream.hh" #include "sstring.hh" #include #include #include #include enum class directory_entry_type { block_device, char_device, directory, fifo, link, regular, socket, }; struct directory_entry { sstring name; std::experimental::optional type; }; class file_impl { public: virtual ~file_impl() {} virtual future write_dma(uint64_t pos, const void* buffer, size_t len) = 0; virtual future write_dma(uint64_t pos, std::vector iov) = 0; virtual future read_dma(uint64_t pos, void* buffer, size_t len) = 0; virtual future read_dma(uint64_t pos, std::vector iov) = 0; virtual future<> flush(void) = 0; virtual future stat(void) = 0; virtual future<> discard(uint64_t offset, uint64_t length) = 0; virtual future size(void) = 0; virtual subscription list_directory(std::function (directory_entry de)> next) = 0; friend class reactor; }; class posix_file_impl : public file_impl { public: int _fd; posix_file_impl(int fd) : _fd(fd) {} ~posix_file_impl() { if (_fd != -1) { ::close(_fd); } } future write_dma(uint64_t pos, const void* buffer, size_t len); future write_dma(uint64_t pos, std::vector iov); future read_dma(uint64_t pos, void* buffer, size_t len); future read_dma(uint64_t pos, std::vector iov); future<> flush(void); future stat(void); future<> discard(uint64_t offset, uint64_t length); future size(void); virtual subscription list_directory(std::function (directory_entry de)> next) override; }; class blockdev_file_impl : public posix_file_impl { public: blockdev_file_impl(int fd) : posix_file_impl(fd) {} future<> discard(uint64_t offset, uint64_t length) override; future size(void) override; }; inline std::unique_ptr make_file_impl(int fd) { struct stat st; ::fstat(fd, &st); if (S_ISBLK(st.st_mode)) { return std::unique_ptr(new blockdev_file_impl(fd)); } else { return std::unique_ptr(new posix_file_impl(fd)); } } class file { std::unique_ptr _file_impl; private: explicit file(int fd) : _file_impl(make_file_impl(fd)) {} public: file(file&& x) : _file_impl(std::move(x._file_impl)) {} template future dma_read(uint64_t pos, CharType* buffer, size_t len) { return _file_impl->read_dma(pos, buffer, len); } future dma_read(uint64_t pos, std::vector iov) { return _file_impl->read_dma(pos, std::move(iov)); } template future dma_write(uint64_t pos, const CharType* buffer, size_t len) { return _file_impl->write_dma(pos, buffer, len); } future dma_write(uint64_t pos, std::vector iov) { return _file_impl->write_dma(pos, std::move(iov)); } future<> flush() { return _file_impl->flush(); } future stat() { return _file_impl->stat(); } future<> discard(uint64_t offset, uint64_t length) { return _file_impl->discard(offset, length); } future size() { return _file_impl->size(); } subscription list_directory(std::function (directory_entry de)> next) { return _file_impl->list_directory(std::move(next)); } friend class reactor; }; #endif /* FILE_HH_ */