/* * This file is open source software, licensed to you under the terms * of the Apache License, Version 2.0 (the "License"). See the NOTICE file * distributed with this work for additional information regarding copyright * ownership. You may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Copyright 2014 Cloudius Systems */ #ifndef FILE_HH_ #define FILE_HH_ #include "stream.hh" #include "sstring.hh" #include #include #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<> truncate(uint64_t length) = 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<> truncate(uint64_t length); 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<> truncate(uint64_t length) override; 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)) {} file& operator=(file&& x) noexcept = default; 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<> truncate(uint64_t length) { return _file_impl->truncate(length); } 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_ */