aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-09-08 18:49:54 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-09-08 18:49:54 +0200
commitd5e2c6a3146c20354ab11f1dae48ab755996fa96 (patch)
tree02b766305a0636fb81dbb2f18320cae2fa0d828e
parent4955f80f2fdc6ffeda77e0d569e9a010642772d2 (diff)
libsqfs: bring sqfs_file_t in line with stream API
Rename the open function to sqfs_file_open, use an argument for the return pointer and pass back and error number on failure. Also add an inermediate function to open an sqfs_file_t using a handle, similar to the stream API. The get_file_size function is moved to the native wrappers and some of the implementation is cleaned up a little. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--bin/gensquashfs/src/mkfs.c6
-rw-r--r--bin/rdsquashfs/src/rdsquashfs.c6
-rw-r--r--bin/sqfs2tar/src/sqfs2tar.c6
-rw-r--r--bin/sqfsdiff/src/sqfsdiff.c4
-rw-r--r--doc/mainpage.dox2
-rw-r--r--extras/browse.c5
-rw-r--r--extras/extract_one.c6
-rw-r--r--extras/list_files.c5
-rw-r--r--extras/mk42sqfs.c3
-rw-r--r--extras/mknastyfs.c3
-rw-r--r--include/sqfs/io.h56
-rw-r--r--lib/common/src/writer/init.c6
-rw-r--r--lib/sqfs/src/io/file.c87
-rw-r--r--lib/sqfs/src/io/unix.c14
-rw-r--r--lib/sqfs/src/io/win32.c13
15 files changed, 140 insertions, 82 deletions
diff --git a/bin/gensquashfs/src/mkfs.c b/bin/gensquashfs/src/mkfs.c
index a178066..6d04040 100644
--- a/bin/gensquashfs/src/mkfs.c
+++ b/bin/gensquashfs/src/mkfs.c
@@ -40,9 +40,9 @@ static int pack_files(sqfs_block_processor_t *data, fstree_t *fs,
if (!opt->cfg.quiet)
printf("packing %s\n", path);
- file = sqfs_open_file(path, SQFS_FILE_OPEN_READ_ONLY);
- if (file == NULL) {
- perror(path);
+ ret = sqfs_file_open(&file, path, SQFS_FILE_OPEN_READ_ONLY);
+ if (ret) {
+ sqfs_perror(path, "open", ret);
free(node_path);
return -1;
}
diff --git a/bin/rdsquashfs/src/rdsquashfs.c b/bin/rdsquashfs/src/rdsquashfs.c
index 9d8f3ba..2f5c50d 100644
--- a/bin/rdsquashfs/src/rdsquashfs.c
+++ b/bin/rdsquashfs/src/rdsquashfs.c
@@ -114,9 +114,9 @@ int main(int argc, char **argv)
process_command_line(&opt, argc, argv);
- file = sqfs_open_file(opt.image_name, SQFS_FILE_OPEN_READ_ONLY);
- if (file == NULL) {
- perror(opt.image_name);
+ ret = sqfs_file_open(&file, opt.image_name, SQFS_FILE_OPEN_READ_ONLY);
+ if (ret) {
+ sqfs_perror(opt.image_name, "open", ret);
goto out;
}
diff --git a/bin/sqfs2tar/src/sqfs2tar.c b/bin/sqfs2tar/src/sqfs2tar.c
index 714f6db..e21cd7a 100644
--- a/bin/sqfs2tar/src/sqfs2tar.c
+++ b/bin/sqfs2tar/src/sqfs2tar.c
@@ -139,9 +139,9 @@ int main(int argc, char **argv)
goto out;
}
- file = sqfs_open_file(filename, SQFS_FILE_OPEN_READ_ONLY);
- if (file == NULL) {
- perror(filename);
+ ret = sqfs_file_open(&file, filename, SQFS_FILE_OPEN_READ_ONLY);
+ if (ret) {
+ sqfs_perror(filename, "open", ret);
goto out;
}
diff --git a/bin/sqfsdiff/src/sqfsdiff.c b/bin/sqfsdiff/src/sqfsdiff.c
index d789fe1..1bbf62c 100644
--- a/bin/sqfsdiff/src/sqfsdiff.c
+++ b/bin/sqfsdiff/src/sqfsdiff.c
@@ -22,9 +22,9 @@ static int open_sfqs(sqfs_state_t *state, const char *path)
memset(state, 0, sizeof(*state));
- state->file = sqfs_open_file(path, SQFS_FILE_OPEN_READ_ONLY);
+ ret = sqfs_file_open(&state->file, path, SQFS_FILE_OPEN_READ_ONLY);
if (state->file == NULL) {
- perror(path);
+ sqfs_perror(path, "open", ret);
return -1;
}
diff --git a/doc/mainpage.dox b/doc/mainpage.dox
index b9822ac..cd71ba0 100644
--- a/doc/mainpage.dox
+++ b/doc/mainpage.dox
@@ -10,7 +10,7 @@
*
* All disk I/O is abstracted away through the \ref sqfs_file_t interface. A
* reference implementation that uses native file I/O can be instatiated
- * using @ref sqfs_open_file. Providing a custom implementation allows reading
+ * using @ref sqfs_file_open. Providing a custom implementation allows reading
* or writing SquashFS images to something other than regular files, embedding
* SquashFS in a custom container format or applying custom transformations on
* the raw byte level.
diff --git a/extras/browse.c b/extras/browse.c
index c0c9995..a608021 100644
--- a/extras/browse.c
+++ b/extras/browse.c
@@ -506,9 +506,8 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
- file = sqfs_open_file(argv[1], SQFS_FILE_OPEN_READ_ONLY);
- if (file == NULL) {
- perror(argv[1]);
+ if (sqfs_file_open(&file, argv[1], SQFS_FILE_OPEN_READ_ONLY)) {
+ fprintf(stderr, "%s: error opening file.\n", argv[1]);
return EXIT_FAILURE;
}
diff --git a/extras/extract_one.c b/extras/extract_one.c
index 63c83f9..d0fe1b9 100644
--- a/extras/extract_one.c
+++ b/extras/extract_one.c
@@ -43,9 +43,9 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
- file = sqfs_open_file(argv[1], SQFS_FILE_OPEN_READ_ONLY);
- if (file == NULL) {
- perror(argv[1]);
+ ret = sqfs_file_open(&file, argv[1], SQFS_FILE_OPEN_READ_ONLY);
+ if (ret) {
+ fprintf(stderr, "%s: error opening file.\n", argv[1]);
return EXIT_FAILURE;
}
diff --git a/extras/list_files.c b/extras/list_files.c
index d1e0a64..89a1f30 100644
--- a/extras/list_files.c
+++ b/extras/list_files.c
@@ -70,9 +70,8 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
- file = sqfs_open_file(argv[1], SQFS_FILE_OPEN_READ_ONLY);
- if (file == NULL) {
- perror(argv[1]);
+ if (sqfs_file_open(&file, argv[1], SQFS_FILE_OPEN_READ_ONLY)) {
+ fprintf(stderr, "%s: error opening file.\n", argv[1]);
return EXIT_FAILURE;
}
diff --git a/extras/mk42sqfs.c b/extras/mk42sqfs.c
index 87e1523..abad4b4 100644
--- a/extras/mk42sqfs.c
+++ b/extras/mk42sqfs.c
@@ -71,8 +71,7 @@ int main(int argc, char **argv)
(void)argc; (void)argv;
/* get a file object referring to our destination file */
- file = sqfs_open_file("42.sqfs", SQFS_FILE_OPEN_OVERWRITE);
- if (file == NULL) {
+ if (sqfs_file_open(&file, "42.sqfs", SQFS_FILE_OPEN_OVERWRITE)) {
fputs("Error opening output file.\n", stderr);
return EXIT_FAILURE;
}
diff --git a/extras/mknastyfs.c b/extras/mknastyfs.c
index c72bd7d..5984828 100644
--- a/extras/mknastyfs.c
+++ b/extras/mknastyfs.c
@@ -66,8 +66,7 @@ int main(int argc, char **argv)
(void)argc; (void)argv;
/* get a file object referring to our destination file */
- file = sqfs_open_file("nasty.sqfs", 0);
- if (file == NULL) {
+ if (sqfs_file_open(&file, "nasty.sqfs", 0)) {
fputs("Error opening output file.\n", stderr);
return EXIT_FAILURE;
}
diff --git a/include/sqfs/io.h b/include/sqfs/io.h
index f148502..bf104f9 100644
--- a/include/sqfs/io.h
+++ b/include/sqfs/io.h
@@ -27,7 +27,7 @@
*
* @brief Contains low-level interfaces for abstracting file I/O
*
- * The @ref sqfs_file_t interface abstracts I/O on a random-acces sread/write
+ * The @ref sqfs_file_t interface abstracts I/O on a random-acces read/write
* file, @ref sqfs_ostream_t represents a buffered, sequential, append only
* data stream, @ref sqfs_istream_t represents a buffered, sequential, read only
* data stream.
@@ -50,7 +50,7 @@ typedef int sqfs_file_handle_t;
/**
* @enum SQFS_FILE_OPEN_FLAGS
*
- * @brief Flags for @ref sqfs_open_file
+ * @brief Flags for file I/O related data structures and functions
*/
typedef enum {
/**
@@ -91,9 +91,8 @@ typedef enum {
/**
* @brief Do not use sparse file I/O APIs, always fill in zero bytes
*
- * This flag currently has no effect on @ref sqfs_open_file, it changes
- * the behavior of @ref sqfs_ostream_open_file and
- * @ref sqfs_ostream_open_handle.
+ * This flag currently has no effect on @ref sqfs_file_t, it changes
+ * the behavior of @ref sqfs_ostream_t when appending sparse data.
*/
SQFS_FILE_OPEN_NO_SPARSE = 0x08,
@@ -439,23 +438,54 @@ SQFS_API int sqfs_native_file_seek(sqfs_file_handle_t hnd,
sqfs_s64 offset, sqfs_u32 flags);
/**
+ * @brief Try to query the current on-disk size from a native file handle
+ *
+ * @param hnd A native OS file handle
+ * @param out Returns the file size on success
+ *
+ * @return Zero on success, a negative @ref SQFS_ERROR code on failure.
+ */
+SQFS_API int sqfs_native_file_get_size(sqfs_file_handle_t hnd, sqfs_u64 *out);
+
+/**
* @brief Open a file through the operating systems filesystem API
*
+ * @memberof sqfs_file_t
+ *
+ * This function basically combines @ref sqfs_native_file_open
+ * and @ref sqfs_file_open_handle to conveniently open a file object in
+ * one operation
+ *
+ * @param out Returns a pointer to an @ref sqfs_file_t on success.
+ * @param filename The name of the file to open.
+ * @param flags A set of @ref SQFS_FILE_OPEN_FLAGS.
+ *
+ * @return Zero on success, a negative @ref SQFS_ERROR code on failure.
+ */
+SQFS_API int sqfs_file_open(sqfs_file_t **out, const char *filename,
+ sqfs_u32 flags);
+
+/**
+ * @brief Create an @ref sqfs_file_t implementation from a native file handle
+ *
+ * @memberof sqfs_file_t
+ *
* This function internally creates an instance of a reference implementation
* of the @ref sqfs_file_t interface that uses the operating systems native
* API for file I/O.
*
- * On Unix-like systems, if the open call fails, this function makes sure to
- * preserves the value in errno indicating the underlying problem. Similarly,
- * on Windows, the implementation tries to preserve the GetLastError value.
+ * It takes up ownership of the file handle and takes care of cleaning it up.
+ * On failure, the handle remains usable, and ownership remains with the caller.
*
- * @param filename The name of the file to open.
- * @param flags A set of @ref SQFS_FILE_OPEN_FLAGS.
+ * @param out Returns a pointer to a file object on success.
+ * @param filename The name to associate with the handle.
+ * @param fd A native file handle.
+ * @param flags A combination of @ref SQFS_FILE_OPEN_FLAGS flags.
*
- * @return A pointer to a file object on success, NULL on allocation failure,
- * failure to open the file or if an unknown flag was set.
+ * @return Zero on success, a negative @ref SQFS_ERROR number on failure
*/
-SQFS_API sqfs_file_t *sqfs_open_file(const char *filename, sqfs_u32 flags);
+SQFS_API int sqfs_file_open_handle(sqfs_file_t **out, const char *filename,
+ sqfs_file_handle_t fd, sqfs_u32 flags);
/**
* @brief Create an input stream for an OS native file handle.
diff --git a/lib/common/src/writer/init.c b/lib/common/src/writer/init.c
index 60d7a12..bf1d2ca 100644
--- a/lib/common/src/writer/init.c
+++ b/lib/common/src/writer/init.c
@@ -57,9 +57,9 @@ int sqfs_writer_init(sqfs_writer_t *sqfs, const sqfs_writer_cfg_t *wrcfg)
return -1;
}
- sqfs->outfile = sqfs_open_file(wrcfg->filename, wrcfg->outmode);
- if (sqfs->outfile == NULL) {
- perror(wrcfg->filename);
+ ret = sqfs_file_open(&sqfs->outfile, wrcfg->filename, wrcfg->outmode);
+ if (ret) {
+ sqfs_perror(wrcfg->filename, "open", ret);
return -1;
}
diff --git a/lib/sqfs/src/io/file.c b/lib/sqfs/src/io/file.c
index 27ab5d6..e6b7ee3 100644
--- a/lib/sqfs/src/io/file.c
+++ b/lib/sqfs/src/io/file.c
@@ -13,29 +13,14 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
-#if defined(_WIN32) || defined(__WINDOWS__)
-static int get_file_size(HANDLE fd, sqfs_u64 *out)
-{
- LARGE_INTEGER size;
- if (!GetFileSizeEx(fd, &size))
- return -1;
- *out = size.QuadPart;
- return 0;
-}
-#else
-#include <sys/stat.h>
+#if !defined(_WIN32) && !defined(__WINDOWS__)
#include <unistd.h>
-#include <errno.h>
-static int get_file_size(int fd, sqfs_u64 *out)
-{
- struct stat sb;
- if (fstat(fd, &sb))
- return -1;
- *out = sb.st_size;
- return 0;
-}
+#define ERROR_NOT_ENOUGH_MEMORY ENOMEM
+#define ERROR_NOT_SUPPORTED ENOTSUP
+#define SetLastError(x) errno = (x)
#endif
typedef struct {
@@ -64,11 +49,7 @@ static sqfs_object_t *stdio_copy(const sqfs_object_t *base)
size_t size;
if (!file->readonly) {
-#if defined(_WIN32) || defined(__WINDOWS__)
SetLastError(ERROR_NOT_SUPPORTED);
-#else
- errno = ENOTSUP;
-#endif
return NULL;
}
@@ -232,13 +213,16 @@ static const char *stdio_get_filename(sqfs_file_t *file)
return ((sqfs_file_stdio_t *)file)->name;
}
-sqfs_file_t *sqfs_open_file(const char *filename, sqfs_u32 flags)
+int sqfs_file_open_handle(sqfs_file_t **out, const char *filename,
+ sqfs_file_handle_t fd, sqfs_u32 flags)
{
- bool file_opened = false;
sqfs_file_stdio_t *file;
size_t size, namelen;
sqfs_file_t *base;
os_error_t err;
+ int ret;
+
+ *out = NULL;
namelen = strlen(filename);
size = sizeof(*file) + 1;
@@ -254,12 +238,15 @@ sqfs_file_t *sqfs_open_file(const char *filename, sqfs_u32 flags)
sqfs_object_init(file, stdio_destroy, stdio_copy);
memcpy(file->name, filename, namelen);
- if (sqfs_native_file_open(&file->fd, filename, flags))
- goto fail;
+ ret = sqfs_native_file_get_size(fd, &file->size);
+ if (ret)
+ goto fail_free;
+
+ ret = sqfs_native_file_duplicate(fd, &file->fd);
+ if (ret)
+ goto fail_free;
- file_opened = true;
- if (get_file_size(file->fd, &file->size))
- goto fail;
+ sqfs_native_file_close(fd);
file->readonly = (flags & SQFS_FILE_OPEN_READ_ONLY) != 0;
@@ -268,19 +255,37 @@ sqfs_file_t *sqfs_open_file(const char *filename, sqfs_u32 flags)
base->get_size = stdio_get_size;
base->truncate = stdio_truncate;
base->get_filename = stdio_get_filename;
- return base;
-fail:
+
+ *out = base;
+ return 0;
+fail_free:
err = get_os_error_state();
- if (file_opened)
- sqfs_native_file_close(file->fd);
free(file);
set_os_error_state(err);
- return NULL;
+ return ret;
fail_no_mem:
-#if defined(_WIN32) || defined(__WINDOWS__)
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-#else
- errno = ENOMEM;
-#endif
- return NULL;
+ return SQFS_ERROR_ALLOC;
+}
+
+int sqfs_file_open(sqfs_file_t **out, const char *filename, sqfs_u32 flags)
+{
+ sqfs_file_handle_t fd;
+ int ret;
+
+ ret = sqfs_native_file_open(&fd, filename, flags);
+ if (ret) {
+ *out = NULL;
+ return ret;
+ }
+
+ ret = sqfs_file_open_handle(out, filename, fd, flags);
+ if (ret) {
+ os_error_t err = get_os_error_state();
+ sqfs_native_file_close(fd);
+ set_os_error_state(err);
+ return ret;
+ }
+
+ return 0;
}
diff --git a/lib/sqfs/src/io/unix.c b/lib/sqfs/src/io/unix.c
index 2e97394..cac8e55 100644
--- a/lib/sqfs/src/io/unix.c
+++ b/lib/sqfs/src/io/unix.c
@@ -10,6 +10,7 @@
#include "sqfs/io.h"
#include "sqfs/error.h"
+#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
@@ -85,3 +86,16 @@ int sqfs_native_file_seek(sqfs_file_handle_t fd,
return 0;
}
+
+int sqfs_native_file_get_size(sqfs_file_handle_t hnd, sqfs_u64 *out)
+{
+ struct stat sb;
+
+ if (fstat(hnd, &sb)) {
+ *out = 0;
+ return SQFS_ERROR_IO;
+ }
+
+ *out = sb.st_size;
+ return 0;
+}
diff --git a/lib/sqfs/src/io/win32.c b/lib/sqfs/src/io/win32.c
index bc625e4..fd10ab1 100644
--- a/lib/sqfs/src/io/win32.c
+++ b/lib/sqfs/src/io/win32.c
@@ -118,3 +118,16 @@ int sqfs_native_file_seek(sqfs_file_handle_t fd,
return 0;
}
+
+int sqfs_native_file_get_size(sqfs_file_handle_t hnd, sqfs_u64 *out)
+{
+ LARGE_INTEGER size;
+
+ if (!GetFileSizeEx(hnd, &size)) {
+ *out = 0;
+ return SQFS_ERROR_IO;
+ }
+
+ *out = size.QuadPart;
+ return 0;
+}