diff options
author | Kieran Bingham <kieran.bingham@ideasonboard.com> | 2021-06-16 10:34:07 +0100 |
---|---|---|
committer | Kieran Bingham <kieran.bingham@ideasonboard.com> | 2021-06-25 16:11:10 +0100 |
commit | b304bc013ef8022131ef0a146f20c6bad7ac45d5 (patch) | |
tree | 6ec2d13a59fcb1be0e1c7df9c2187edf607b3a6a /src/libcamera/file.cpp | |
parent | 27aff949fbc1b9aabfc594bbfd6f94be55a086ec (diff) |
libcamera/base: Move File to base library
The File abstraction is a base helper and not part of the libcamera
API. Move it to to allow usage by users of the base library.
Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'src/libcamera/file.cpp')
-rw-r--r-- | src/libcamera/file.cpp | 465 |
1 files changed, 0 insertions, 465 deletions
diff --git a/src/libcamera/file.cpp b/src/libcamera/file.cpp deleted file mode 100644 index def0f60d..00000000 --- a/src/libcamera/file.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2020, Google Inc. - * - * file.cpp - File I/O operations - */ - -#include "libcamera/internal/file.h" - -#include <errno.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include <libcamera/base/log.h> - -/** - * \file file.h - * \brief File I/O operations - */ - -namespace libcamera { - -LOG_DEFINE_CATEGORY(File) - -/** - * \class File - * \brief Interface for I/O operations on files - * - * The File class provides an interface to perform I/O operations on files. It - * wraps opening, closing and mapping files in memory, and handles the cleaning - * of allocated resources. - * - * File instances are usually constructed with a file name, but the name can be - * set later through the setFileName() function. Instances are not automatically - * opened when constructed, and shall be opened explictly with open(). - * - * Files can be mapped to the process memory with map(). Mapped regions can be - * unmapped manually with munmap(), and are automatically unmapped when the File - * is destroyed or when it is used to reference another file with setFileName(). - */ - -/** - * \enum File::MapFlag - * \brief Flags for the File::map() function - * \var File::MapNoOption - * \brief No option (used as default value) - * \var File::MapPrivate - * \brief The memory region is mapped as private, changes are not reflected in - * the file constents - */ - -/** - * \enum File::OpenMode - * \brief Mode in which a file is opened - * \var File::NotOpen - * \brief The file is not open - * \var File::ReadOnly - * \brief The file is open for reading - * \var File::WriteOnly - * \brief The file is open for writing - * \var File::ReadWrite - * \brief The file is open for reading and writing - */ - -/** - * \brief Construct a File to represent the file \a name - * \param[in] name The file name - * - * Upon construction the File object is closed and shall be opened with open() - * before performing I/O operations. - */ -File::File(const std::string &name) - : name_(name), fd_(-1), mode_(NotOpen), error_(0) -{ -} - -/** - * \brief Construct a File without an associated name - * - * Before being used for any purpose, the file name shall be set with - * setFileName(). - */ -File::File() - : fd_(-1), mode_(NotOpen), error_(0) -{ -} - -/** - * \brief Destroy a File instance - * - * Any memory mapping associated with the File is unmapped, and the File is - * closed if it is open. - */ -File::~File() -{ - unmapAll(); - close(); -} - -/** - * \fn const std::string &File::fileName() const - * \brief Retrieve the file name - * \return The file name - */ - -/** - * \brief Set the name of the file - * \param[in] name The name of the file - * - * The \a name can contain an absolute path, a relative path or no path at all. - * Calling this function on an open file results in undefined behaviour. - * - * Any memory mapping associated with the File is unmapped. - */ -void File::setFileName(const std::string &name) -{ - if (isOpen()) { - LOG(File, Error) - << "Can't set file name on already open file " << name_; - return; - } - - unmapAll(); - - name_ = name; -} - -/** - * \brief Check if the file specified by fileName() exists - * - * This function checks if the file specified by fileName() exists. The File - * instance doesn't need to be open to check for file existence, and this - * function may return false even if the file is open, if it was deleted from - * the file system. - * - * \return True if the the file exists, false otherwise - */ -bool File::exists() const -{ - return exists(name_); -} - -/** - * \brief Open the file in the given mode - * \param[in] mode The open mode - * - * This function opens the file specified by fileName() in \a mode. If the file - * doesn't exist and the mode is WriteOnly or ReadWrite, this function will - * attempt to create the file with initial permissions set to 0666 (modified by - * the process' umask). - * - * The error() status is updated. - * - * \return True on success, false otherwise - */ -bool File::open(File::OpenMode mode) -{ - if (isOpen()) { - LOG(File, Error) << "File " << name_ << " is already open"; - return false; - } - - int flags = (mode & ReadWrite) - 1; - if (mode & WriteOnly) - flags |= O_CREAT; - - fd_ = ::open(name_.c_str(), flags, 0666); - if (fd_ < 0) { - error_ = -errno; - return false; - } - - mode_ = mode; - error_ = 0; - return true; -} - -/** - * \fn bool File::isOpen() const - * \brief Check if the file is open - * \return True if the file is open, false otherwise - */ - -/** - * \fn OpenMode File::openMode() const - * \brief Retrieve the file open mode - * \return The file open mode - */ - -/** - * \brief Close the file - * - * This function closes the File. If the File is not open, it performs no - * operation. Memory mappings created with map() are not destroyed when the - * file is closed. - */ -void File::close() -{ - if (fd_ == -1) - return; - - ::close(fd_); - fd_ = -1; - mode_ = NotOpen; -} - -/** - * \fn int File::error() const - * \brief Retrieve the file error status - * - * This function retrieves the error status from the last file open or I/O - * operation. The error status is a negative number as defined by errno.h. If - * no error occurred, this function returns 0. - * - * \return The file error status - */ - -/** - * \brief Retrieve the file size - * - * This function retrieves the size of the file on the filesystem. The File - * instance shall be open to retrieve its size. The error() status is not - * modified, error codes are returned directly on failure. - * - * \return The file size in bytes on success, or a negative error code otherwise - */ -ssize_t File::size() const -{ - if (!isOpen()) - return -EINVAL; - - struct stat st; - int ret = fstat(fd_, &st); - if (ret < 0) - return -errno; - - return st.st_size; -} - -/** - * \brief Return current read or write position - * - * If the file is closed, this function returns 0. - * - * \return The current read or write position - */ -off_t File::pos() const -{ - if (!isOpen()) - return 0; - - return lseek(fd_, 0, SEEK_CUR); -} - -/** - * \brief Set the read or write position - * \param[in] pos The desired position - * \return The resulting offset from the beginning of the file on success, or a - * negative error code otherwise - */ -off_t File::seek(off_t pos) -{ - if (!isOpen()) - return -EINVAL; - - off_t ret = lseek(fd_, pos, SEEK_SET); - if (ret < 0) - return -errno; - - return ret; -} - -/** - * \brief Read data from the file - * \param[in] data Memory to read data into - * - * Read at most \a data.size() bytes from the file into \a data.data(), and - * return the number of bytes read. If less data than requested is available, - * the returned byte count may be smaller than the requested size. If no more - * data is available, 0 is returned. - * - * The position of the file as returned by pos() is advanced by the number of - * bytes read. If an error occurs, the position isn't modified. - * - * \return The number of bytes read on success, or a negative error code - * otherwise - */ -ssize_t File::read(const Span<uint8_t> &data) -{ - if (!isOpen()) - return -EINVAL; - - size_t readBytes = 0; - ssize_t ret = 0; - - /* Retry in case of interrupted system calls. */ - while (readBytes < data.size()) { - ret = ::read(fd_, data.data() + readBytes, - data.size() - readBytes); - if (ret <= 0) - break; - - readBytes += ret; - } - - if (ret < 0 && !readBytes) - return -errno; - - return readBytes; -} - -/** - * \brief Write data to the file - * \param[in] data Memory containing data to be written - * - * Write at most \a data.size() bytes from \a data.data() to the file, and - * return the number of bytes written. If the file system doesn't have enough - * space for the data, the returned byte count may be less than requested. - * - * The position of the file as returned by pos() is advanced by the number of - * bytes written. If an error occurs, the position isn't modified. - * - * \return The number of bytes written on success, or a negative error code - * otherwise - */ -ssize_t File::write(const Span<const uint8_t> &data) -{ - if (!isOpen()) - return -EINVAL; - - size_t writtenBytes = 0; - - /* Retry in case of interrupted system calls. */ - while (writtenBytes < data.size()) { - ssize_t ret = ::write(fd_, data.data() + writtenBytes, - data.size() - writtenBytes); - if (ret <= 0) - break; - - writtenBytes += ret; - } - - if (data.size() && !writtenBytes) - return -errno; - - return writtenBytes; -} - -/** - * \brief Map a region of the file in the process memory - * \param[in] offset The region offset within the file - * \param[in] size The region sise - * \param[in] flags The mapping flags - * - * This function maps a region of \a size bytes of the file starting at \a - * offset into the process memory. The File instance shall be open, but may be - * closed after mapping the region. Mappings stay valid when the File is - * closed, and are destroyed automatically when the File is deleted. - * - * If \a size is a negative value, this function maps the region starting at \a - * offset until the end of the file. - * - * The mapping memory protection is controlled by the file open mode, unless \a - * flags contains MapPrivate in which case the region is mapped in read/write - * mode. - * - * The error() status is updated. - * - * \return The mapped memory on success, or an empty span otherwise - */ -Span<uint8_t> File::map(off_t offset, ssize_t size, enum File::MapFlag flags) -{ - if (!isOpen()) { - error_ = -EBADF; - return {}; - } - - if (size < 0) { - size = File::size(); - if (size < 0) { - error_ = size; - return {}; - } - - size -= offset; - } - - int mmapFlags = flags & MapPrivate ? MAP_PRIVATE : MAP_SHARED; - - int prot = 0; - if (mode_ & ReadOnly) - prot |= PROT_READ; - if (mode_ & WriteOnly) - prot |= PROT_WRITE; - if (flags & MapPrivate) - prot |= PROT_WRITE; - - void *map = mmap(NULL, size, prot, mmapFlags, fd_, offset); - if (map == MAP_FAILED) { - error_ = -errno; - return {}; - } - - maps_.emplace(map, size); - - error_ = 0; - return { static_cast<uint8_t *>(map), static_cast<size_t>(size) }; -} - -/** - * \brief Unmap a region mapped with map() - * \param[in] addr The region address - * - * The error() status is updated. - * - * \return True on success, or false if an error occurs - */ -bool File::unmap(uint8_t *addr) -{ - auto iter = maps_.find(static_cast<void *>(addr)); - if (iter == maps_.end()) { - error_ = -ENOENT; - return false; - } - - int ret = munmap(addr, iter->second); - if (ret < 0) { - error_ = -errno; - return false; - } - - maps_.erase(iter); - - error_ = 0; - return true; -} - -void File::unmapAll() -{ - for (const auto &map : maps_) - munmap(map.first, map.second); - - maps_.clear(); -} - -/** - * \brief Check if the file specified by \a name exists - * \param[in] name The file name - * \return True if the file exists, false otherwise - */ -bool File::exists(const std::string &name) -{ - struct stat st; - int ret = stat(name.c_str(), &st); - if (ret < 0) - return false; - - /* Directories can not be handled here, even if they exist. */ - return !S_ISDIR(st.st_mode); -} - -} /* namespace libcamera */ |