libcamera: file: Add read/write support

Add basic support to read and write data from/to a file, along with
retrieving and setting the current read/write position.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Laurent Pinchart 2020-04-16 01:01:53 +03:00
parent d5446e9f32
commit 25288281d1
2 changed files with 115 additions and 0 deletions

View file

@ -49,6 +49,12 @@ public:
int error() const { return error_; } int error() const { return error_; }
ssize_t size() const; ssize_t size() const;
off_t pos() const;
off_t seek(off_t pos);
ssize_t read(const Span<uint8_t> &data);
ssize_t write(const Span<const uint8_t> &data);
Span<uint8_t> map(off_t offset = 0, ssize_t size = -1, Span<uint8_t> map(off_t offset = 0, ssize_t size = -1,
MapFlag flags = MapNoOption); MapFlag flags = MapNoOption);
bool unmap(uint8_t *addr); bool unmap(uint8_t *addr);

View file

@ -237,6 +237,115 @@ ssize_t File::size() const
return st.st_size; 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 * \brief Map a region of the file in the process memory
* \param[in] offset The region offset within the file * \param[in] offset The region offset within the file