From 1e255d0f6c472bb3c710aea1ea8dc5d27c0fba4a Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Fri, 4 Sep 2020 18:26:16 +0200 Subject: Add stream I/O abstraction library Signed-off-by: David Oberhollenzer --- include/compat.h | 2 + include/fstream.h | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 include/fstream.h (limited to 'include') diff --git a/include/compat.h b/include/compat.h index ee47ef9..343dcf5 100644 --- a/include/compat.h +++ b/include/compat.h @@ -163,6 +163,8 @@ int fchownat(int dirfd, const char *path, int uid, int gid, int flags); int fchmodat(int dirfd, const char *path, int mode, int flags); int chdir(const char *path); + +void w32_perror(const char *str); #else #include #include diff --git a/include/fstream.h b/include/fstream.h new file mode 100644 index 0000000..cc562ca --- /dev/null +++ b/include/fstream.h @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * fstream.h + * + * Copyright (C) 2019 David Oberhollenzer + */ +#ifndef FSTREAM_H +#define FSTREAM_H + +#include "sqfs/predef.h" + +/** + * @struct ostream_t + * + * @extends sqfs_object_t + * + * @brief An append-only data stream. + */ +typedef struct ostream_t { + sqfs_object_t base; + + int (*append)(struct ostream_t *strm, const void *data, size_t size); + + int (*append_sparse)(struct ostream_t *strm, size_t size); + + int (*flush)(struct ostream_t *strm); + + const char *(*get_filename)(struct ostream_t *strm); +} ostream_t; + +/** + * @struct istream_t + * + * @extends sqfs_object_t + * + * @brief A sequential, read-only data stream. + */ +typedef struct istream_t { + sqfs_object_t base; + + size_t buffer_used; + size_t buffer_offset; + bool eof; + + sqfs_u8 *buffer; + + int (*precache)(struct istream_t *strm); + + const char *(*get_filename)(struct istream_t *strm); +} istream_t; + + +enum { + OSTREAM_OPEN_OVERWRITE = 0x01, + OSTREAM_OPEN_SPARSE = 0x02, +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Create an output stream that writes to a file. + * + * @memberof ostream_t + * + * If the file does not yet exist, it is created. If it does exist this + * function fails, unless the flag OSTREAM_OPEN_OVERWRITE is set, in which + * case the file is opened and its contents are discarded. + * + * If the flag OSTREAM_OPEN_SPARSE is set, the underlying implementation tries + * to support sparse output files. If the flag is not set, holes will always + * be filled with zero bytes. + * + * @param path A path to the file to open or create. + * @param flags A combination of flags controling how to open/create the file. + * + * @return A pointer to an output stream on success, NULL on failure. + */ +SQFS_INTERNAL ostream_t *ostream_open_file(const char *path, int flags); + +/** + * @brief Create an output stream that writes to standard output. + * + * @memberof ostream_t + * + * @return A pointer to an output stream on success, NULL on failure. + */ +SQFS_INTERNAL ostream_t *ostream_open_stdout(void); + +/** + * @brief Create an input stream that reads from a file. + * + * @memberof istream_t + * + * @param path A path to the file to open or create. + * + * @return A pointer to an output stream on success, NULL on failure. + */ +SQFS_INTERNAL istream_t *istream_open_file(const char *path); + +/** + * @brief Create an input stream that reads from standard input. + * + * @memberof istream_t + * + * @return A pointer to an input stream on success, NULL on failure. + */ +SQFS_INTERNAL istream_t *istream_open_stdin(void); + +/** + * @brief Append a block of data to an output stream. + * + * @memberof ostream_t + * + * @param strm A pointer to an output stream. + * @param data A pointer to the data block to append. + * @param size The number of bytes to append. + * + * @return Zero on success, -1 on failure. + */ +SQFS_INTERNAL int ostream_append(ostream_t *strm, const void *data, + size_t size); + +/** + * @brief Append a number of zero bytes to an output stream. + * + * @memberof ostream_t + * + * If the unerlying implementation supports sparse files, this function can be + * used to create a "hole". If the implementation does not support it, a + * fallback is used that just appends a block of zeros manualy. + * + * @param strm A pointer to an output stream. + * @param size The number of zero bytes to append. + * + * @return Zero on success, -1 on failure. + */ +SQFS_INTERNAL int ostream_append_sparse(ostream_t *strm, size_t size); + +/** + * @brief Process all pending, buffered data and flush it to disk. + * + * @memberof ostream_t + * + * If the stream performs some kind of transformation (e.g. transparent data + * compression), flushing caues the wrapped format to insert a termination + * token. Only call this function when you are absolutely DONE appending data, + * shortly before destroying the stream. + * + * @param strm A pointer to an output stream. + * + * @return Zero on success, -1 on failure. + */ +SQFS_INTERNAL int ostream_flush(ostream_t *strm); + +/** + * @brief Get the underlying filename of a output stream. + * + * @memberof ostream_t + * + * @param strm The output stream to get the filename from. + * + * @return A string holding the underlying filename. + */ +SQFS_INTERNAL const char *ostream_get_filename(ostream_t *strm); + +/** + * @brief Printf like function that appends to an output stream + * + * @memberof ostream_t + * + * @param strm The output stream to append to. + * @param fmt A printf style format string. + * + * @return The number of characters written on success, -1 on failure. + */ +SQFS_INTERNAL int ostream_printf(ostream_t *strm, const char *fmt, ...); + +/** + * @brief Read data from an input stream + * + * @memberof istream_t + * + * @param strm A pointer to an input stream. + * @param data A buffer to read into. + * @param size The number of bytes to read into the buffer. + * + * @return The number of bytes actually read on success, -1 on failure, + * 0 on end-of-file. + */ +SQFS_INTERNAL sqfs_s32 istream_read(istream_t *strm, void *data, size_t size); + +/** + * @brief Adjust and refill the internal buffer of an input stream + * + * @memberof istream_t + * + * This function resets the buffer offset of an input stream (moving any unread + * data up front if it has to) and calls an internal callback of the input + * stream to fill the rest of the buffer to the extent possible. + * + * @param strm A pointer to an input stream. + * + * @return 0 on success, -1 on failure. + */ +SQFS_INTERNAL int istream_precache(istream_t *strm); + +/** + * @brief Get the underlying filename of an input stream. + * + * @memberof istream_t + * + * @param strm The input stream to get the filename from. + * + * @return A string holding the underlying filename. + */ +SQFS_INTERNAL const char *istream_get_filename(istream_t *strm); + +/** + * @brief Skip over a number of bytes in an input stream. + * + * @memberof istream_t + * + * @param strm A pointer to an input stream. + * @param size The number of bytes to seek forward. + * + * @return Zero on success, -1 on failure. + */ +SQFS_INTERNAL int istream_skip(istream_t *strm, sqfs_u64 size); + +/** + * @brief Read data from an input stream and append it to an output stream + * + * @memberof ostream_t + * + * @param out A pointer to an output stream to append to. + * @param in A pointer to an input stream to read from. + * @param size The number of bytes to copy over. + * + * @return The number of bytes copied on success, -1 on failure, + * 0 on end-of-file. + */ +SQFS_INTERNAL sqfs_s32 ostream_append_from_istream(ostream_t *out, + istream_t *in, + sqfs_u32 size); + +#ifdef __cplusplus +} +#endif + +#endif /* FSTREAM_H */ -- cgit v1.2.3