aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-07-15 17:13:48 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-08-10 09:28:27 +0200
commit0a1d93062463133e6f40e3398c0fe53371c47ab0 (patch)
treeee289539381c33a3ae3a24098907ed87686a7c94
parentf572a1ed601267438c34c61a201ae1ab051da7a3 (diff)
Move dir_iterator_t from libio into libsquashfs
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--include/io/dir_iterator.h100
-rw-r--r--include/sqfs/io.h107
-rw-r--r--include/sqfs/predef.h1
-rw-r--r--lib/io/Makemodule.am7
-rw-r--r--lib/io/src/dir_tree_iterator.c7
-rw-r--r--lib/io/test/dir_iterator.c15
-rw-r--r--lib/io/test/dir_tree_iterator.c1
-rw-r--r--lib/io/test/dir_tree_iterator2.c1
-rw-r--r--lib/io/test/dir_tree_iterator3.c1
-rw-r--r--lib/sqfs/Makemodule.am4
-rw-r--r--lib/sqfs/src/io/dir_unix.c (renamed from lib/io/src/unix/dir_iterator.c)22
-rw-r--r--lib/sqfs/src/io/dir_win32.c (renamed from lib/io/src/win32/dir_iterator.c)75
12 files changed, 185 insertions, 156 deletions
diff --git a/include/io/dir_iterator.h b/include/io/dir_iterator.h
index e14b2ee..210316f 100644
--- a/include/io/dir_iterator.h
+++ b/include/io/dir_iterator.h
@@ -10,87 +10,6 @@
#include "sqfs/dir_entry.h"
#include "sqfs/predef.h"
-/**
- * @interface sqfs_dir_iterator_t
- *
- * @brief An iterator over entries in a filesystem directory.
- */
-typedef struct sqfs_dir_iterator_t {
- sqfs_object_t obj;
-
- /**
- * @brief Read the next entry and update internal state relating to it
- *
- * @param it A pointer to the iterator itself
- * @param out Returns a pointer to an entry on success
- *
- * @return Zero on success, postivie value if the end of the list was
- * reached, negative @ref SQFS_ERROR value on failure.
- */
- int (*next)(struct sqfs_dir_iterator_t *it, sqfs_dir_entry_t **out);
-
- /**
- * @brief If the last entry was a symlink, extract the target path
- *
- * @param it A pointer to the iterator itself.
- * @param out Returns a pointer to a string on success. Has to be
- * released with free().
- *
- * @return Zero on success, negative @ref SQFS_ERROR value on failure.
- */
- int (*read_link)(struct sqfs_dir_iterator_t *it, char **out);
-
- /**
- * @brief If the last entry was a directory, open it.
- *
- * If next() returned a directory, this can be used to create a brand
- * new sqfs_dir_iterator_t for it, that is independent of the current
- * one and returns the sub-directories entries.
- *
- * @param it A pointer to the iterator itself.
- * @param out Returns a pointer to a directory iterator on success.
- *
- * @return Zero on success, negative @ref SQFS_ERROR value on failure.
- */
- int (*open_subdir)(struct sqfs_dir_iterator_t *it,
- struct sqfs_dir_iterator_t **out);
-
- /**
- * @brief Skip a sub-hierarchy on a stacked iterator
- *
- * If an iterator would ordinarily recurse into a sub-directory,
- * tell it to skip those entries. On simple, flag iterators like the
- * one returned by @ref dir_iterator_create, this has no effect.
- *
- * @param it A pointer to the iterator itself.
- */
- void (*ignore_subdir)(struct sqfs_dir_iterator_t *it);
-
- /**
- * @brief If the last entry was a regular file, open it.
- *
- * If next() returned a file, this can be used to create an istream
- * to read from it.
- *
- * @param it A pointer to the iterator itself.
- * @param out Returns a pointer to a @ref sqfs_istream_t on success.
- *
- * @return Zero on success, negative @ref SQFS_ERROR value on failure.
- */
- int (*open_file_ro)(struct sqfs_dir_iterator_t *it,
- sqfs_istream_t **out);
-
- /**
- * @brief Read extended attributes associated with the current entry
- *
- * @param it A pointer to the iterator itself.
- * @param out Returns a linked list of xattr entries.
- *
- * @return Zero on success, negative @ref SQFS_ERROR value on failure.
- */
- int (*read_xattr)(struct sqfs_dir_iterator_t *it, sqfs_xattr_t **out);
-} sqfs_dir_iterator_t;
-
enum {
DIR_SCAN_NO_SOCK = 0x0001,
DIR_SCAN_NO_SLINK = 0x0002,
@@ -143,25 +62,6 @@ extern "C" {
#endif
/**
- * @brief Construct a simple directory iterator given a path
- *
- * On systems with encoding aware file I/O (like Windows), the path is
- * interpreted to be UTF-8 encoded and converted to the native system API
- * encoding to open the directory. For each directory entry, the name in
- * the native encoding is converted back to UTF-8 when reading.
- *
- * The implementation returned by this is simple, non-recursive, reporting
- * directory contents as returned by the OS native API, i.e. not sorted,
- * and including the "." and ".." entries.
- *
- * @param path A path to a directory on the file system.
- *
- * @return A pointer to a sqfs_dir_iterator_t implementation on success,
- * NULL on error (message is printed to stderr).
- */
-SQFS_INTERNAL sqfs_dir_iterator_t *dir_iterator_create(const char *path);
-
-/**
* @brief Create a stacked, recursive directory tree iterator
*
* The underlying implementation automatically recurses into sub directories
diff --git a/include/sqfs/io.h b/include/sqfs/io.h
index 389f875..e851ea1 100644
--- a/include/sqfs/io.h
+++ b/include/sqfs/io.h
@@ -292,6 +292,90 @@ struct sqfs_ostream_t {
const char *(*get_filename)(sqfs_ostream_t *strm);
};
+/**
+ * @interface sqfs_dir_iterator_t
+ *
+ * @extends sqfs_object_t
+ *
+ * @brief An iterator over entries in a filesystem directory.
+ */
+struct sqfs_dir_iterator_t {
+ sqfs_object_t obj;
+
+ /**
+ * @brief Read the next entry and update internal state relating to it
+ *
+ * @param it A pointer to the iterator itself
+ * @param out Returns a pointer to an entry on success. Has to be
+ * released with @ref sqfs_free().
+ *
+ * @return Zero on success, postivie value if the end of the list was
+ * reached, negative @ref SQFS_ERROR value on failure.
+ */
+ int (*next)(sqfs_dir_iterator_t *it, sqfs_dir_entry_t **out);
+
+ /**
+ * @brief If the last entry was a symlink, extract the target path
+ *
+ * @param it A pointer to the iterator itself.
+ * @param out Returns a pointer to a string on success. Has to be
+ * released with @ref sqfs_free().
+ *
+ * @return Zero on success, negative @ref SQFS_ERROR value on failure.
+ */
+ int (*read_link)(sqfs_dir_iterator_t *it, char **out);
+
+ /**
+ * @brief If the last entry was a directory, open it.
+ *
+ * If next() returned a directory, this can be used to create a brand
+ * new sqfs_dir_iterator_t for it, that is independent of the current
+ * one and returns the sub-directories entries.
+ *
+ * @param it A pointer to the iterator itself.
+ * @param out Returns a pointer to a directory iterator on success.
+ *
+ * @return Zero on success, negative @ref SQFS_ERROR value on failure.
+ */
+ int (*open_subdir)(sqfs_dir_iterator_t *it,
+ sqfs_dir_iterator_t **out);
+
+ /**
+ * @brief Skip a sub-hierarchy on a stacked iterator
+ *
+ * If an iterator would ordinarily recurse into a sub-directory,
+ * tell it to skip those entries. On simple, flag iterators like the
+ * one returned by @ref dir_iterator_create, this has no effect.
+ *
+ * @param it A pointer to the iterator itself.
+ */
+ void (*ignore_subdir)(sqfs_dir_iterator_t *it);
+
+ /**
+ * @brief If the last entry was a regular file, open it.
+ *
+ * If next() returned a file, this can be used to create an istream
+ * to read from it.
+ *
+ * @param it A pointer to the iterator itself.
+ * @param out Returns a pointer to a @ref sqfs_istream_t on success.
+ *
+ * @return Zero on success, negative @ref SQFS_ERROR value on failure.
+ */
+ int (*open_file_ro)(sqfs_dir_iterator_t *it, sqfs_istream_t **out);
+
+ /**
+ * @brief Read extended attributes associated with the current entry
+ *
+ * @param it A pointer to the iterator itself.
+ * @param out Returns a linked list of xattr entries. Has to be
+ * released with @ref sqfs_xattr_list_free().
+ *
+ * @return Zero on success, negative @ref SQFS_ERROR value on failure.
+ */
+ int (*read_xattr)(sqfs_dir_iterator_t *it, sqfs_xattr_t **out);
+};
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -499,6 +583,29 @@ SQFS_API int sqfs_istream_skip(sqfs_istream_t *strm, sqfs_u64 size);
SQFS_API sqfs_s32 sqfs_istream_splice(sqfs_istream_t *in, sqfs_ostream_t *out,
sqfs_u32 size);
+/**
+ * @brief Construct a simple directory iterator given a path
+ *
+ * @memberof sqfs_dir_iterator_t
+ *
+ * On systems with encoding aware file I/O (like Windows), the path is
+ * interpreted to be UTF-8 encoded and converted to the native system API
+ * encoding to open the directory. For each directory entry, the name in
+ * the native encoding is converted back to UTF-8 when reading.
+ *
+ * The implementation returned by this is simple, non-recursive, reporting
+ * directory contents as returned by the OS native API, i.e. not sorted,
+ * and including the "." and ".." entries.
+ *
+ * @param path A path to a directory on the file system.
+ *
+ * @return A pointer to a sqfs_dir_iterator_t implementation on success,
+ * NULL on error (message is printed to stderr).
+ */
+SQFS_API int sqfs_dir_iterator_create_native(sqfs_dir_iterator_t **out,
+ const char *path,
+ sqfs_u32 flags);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/sqfs/predef.h b/include/sqfs/predef.h
index 12ed7c7..9e32b42 100644
--- a/include/sqfs/predef.h
+++ b/include/sqfs/predef.h
@@ -99,6 +99,7 @@ typedef struct sqfs_xattr_t sqfs_xattr_t;
typedef struct sqfs_istream_t sqfs_istream_t;
typedef struct sqfs_ostream_t sqfs_ostream_t;
typedef struct sqfs_dir_entry_t sqfs_dir_entry_t;
+typedef struct sqfs_dir_iterator_t sqfs_dir_iterator_t;
typedef struct sqfs_fragment_t sqfs_fragment_t;
typedef struct sqfs_dir_header_t sqfs_dir_header_t;
diff --git a/lib/io/Makemodule.am b/lib/io/Makemodule.am
index c2d1a15..d342063 100644
--- a/lib/io/Makemodule.am
+++ b/lib/io/Makemodule.am
@@ -6,13 +6,6 @@ libio_a_SOURCES = include/io/xfrm.h include/io/std.h \
libio_a_CFLAGS = $(AM_CFLAGS) $(ZLIB_CFLAGS) $(XZ_CFLAGS)
libio_a_CFLAGS += $(ZSTD_CFLAGS) $(BZIP2_CFLAGS)
-if WINDOWS
-libio_a_SOURCES += lib/io/src/win32/dir_iterator.c
-libio_a_CFLAGS += -DWINVER=0x0600 -D_WIN32_WINNT=0x0600
-else
-libio_a_SOURCES += lib/io/src/unix/dir_iterator.c
-endif
-
noinst_LIBRARIES += libio.a
LIBIO_TESTS = test_istream_mem test_dir_iterator \
diff --git a/lib/io/src/dir_tree_iterator.c b/lib/io/src/dir_tree_iterator.c
index 6370743..0ec478c 100644
--- a/lib/io/src/dir_tree_iterator.c
+++ b/lib/io/src/dir_tree_iterator.c
@@ -8,6 +8,7 @@
#include "io/dir_iterator.h"
#include "util/util.h"
#include "sqfs/error.h"
+#include "sqfs/io.h"
#include <stdlib.h>
#include <string.h>
@@ -311,9 +312,11 @@ sqfs_dir_iterator_t *dir_tree_iterator_create(const char *path,
it->cfg = *cfg;
- dir = dir_iterator_create(path);
- if (dir == NULL)
+ ret = sqfs_dir_iterator_create_native(&dir, path, 0);
+ if (ret) {
+ perror(path);
goto fail;
+ }
ret = push(it, "", dir);
dir = sqfs_drop(dir);
diff --git a/lib/io/test/dir_iterator.c b/lib/io/test/dir_iterator.c
index 013e41e..56610b6 100644
--- a/lib/io/test/dir_iterator.c
+++ b/lib/io/test/dir_iterator.c
@@ -40,7 +40,8 @@ int main(int argc, char **argv)
(void)argc; (void)argv;
/* scan the top level hierarchy */
- dir = dir_iterator_create(TEST_PATH);
+ ret = sqfs_dir_iterator_create_native(&dir, TEST_PATH, 0);
+ TEST_EQUAL_I(ret, 0);
TEST_NOT_NULL(dir);
ret = dir->next(dir, &ent[0]);
@@ -86,7 +87,8 @@ int main(int argc, char **argv)
free(ent[i]);
/* scan first sub hierarchy */
- dir = dir_iterator_create(TEST_PATH "/dira");
+ ret = sqfs_dir_iterator_create_native(&dir, TEST_PATH "/dira", 0);
+ TEST_EQUAL_I(ret, 0);
TEST_NOT_NULL(dir);
ret = dir->next(dir, &ent[0]);
@@ -132,7 +134,8 @@ int main(int argc, char **argv)
free(ent[i]);
/* scan second sub hierarchy */
- dir = dir_iterator_create(TEST_PATH "/dirb");
+ ret = sqfs_dir_iterator_create_native(&dir, TEST_PATH "/dirb", 0);
+ TEST_EQUAL_I(ret, 0);
TEST_NOT_NULL(dir);
ret = dir->next(dir, &ent[0]);
@@ -184,7 +187,8 @@ int main(int argc, char **argv)
free(ent[i]);
/* scan first sub hierarchy */
- dir = dir_iterator_create(TEST_PATH "/dirc");
+ ret = sqfs_dir_iterator_create_native(&dir, TEST_PATH "/dirc", 0);
+ TEST_EQUAL_I(ret, 0);
TEST_NOT_NULL(dir);
ret = dir->next(dir, &ent[0]);
@@ -234,7 +238,8 @@ int main(int argc, char **argv)
subb = NULL;
subc = NULL;
- dir = dir_iterator_create(TEST_PATH);
+ ret = sqfs_dir_iterator_create_native(&dir, TEST_PATH, 0);
+ TEST_EQUAL_I(ret, 0);
TEST_NOT_NULL(dir);
for (i = 0; i < 5; ++i) {
diff --git a/lib/io/test/dir_tree_iterator.c b/lib/io/test/dir_tree_iterator.c
index 8e11e2a..a6e7fcb 100644
--- a/lib/io/test/dir_tree_iterator.c
+++ b/lib/io/test/dir_tree_iterator.c
@@ -9,6 +9,7 @@
#include "io/dir_iterator.h"
#include "sqfs/error.h"
#include "util/test.h"
+#include "sqfs/io.h"
#include "compat.h"
static int compare_entries(const void *a, const void *b)
diff --git a/lib/io/test/dir_tree_iterator2.c b/lib/io/test/dir_tree_iterator2.c
index 2833dc5..0ffb86e 100644
--- a/lib/io/test/dir_tree_iterator2.c
+++ b/lib/io/test/dir_tree_iterator2.c
@@ -9,6 +9,7 @@
#include "io/dir_iterator.h"
#include "sqfs/error.h"
#include "util/test.h"
+#include "sqfs/io.h"
#include "compat.h"
static int compare_entries(const void *a, const void *b)
diff --git a/lib/io/test/dir_tree_iterator3.c b/lib/io/test/dir_tree_iterator3.c
index b82934f..4ac947c 100644
--- a/lib/io/test/dir_tree_iterator3.c
+++ b/lib/io/test/dir_tree_iterator3.c
@@ -9,6 +9,7 @@
#include "io/dir_iterator.h"
#include "sqfs/error.h"
#include "util/test.h"
+#include "sqfs/io.h"
#include "compat.h"
static int compare_entries(const void *a, const void *b)
diff --git a/lib/sqfs/Makemodule.am b/lib/sqfs/Makemodule.am
index 0efd39b..5005c48 100644
--- a/lib/sqfs/Makemodule.am
+++ b/lib/sqfs/Makemodule.am
@@ -61,13 +61,13 @@ libsquashfs_la_SOURCES += lib/util/src/mempool.c include/util/mempool.h
endif
if WINDOWS
-libsquashfs_la_SOURCES += lib/sqfs/src/io/win32.c
+libsquashfs_la_SOURCES += lib/sqfs/src/io/win32.c lib/sqfs/src/io/dir_win32.c
libsquashfs_la_CFLAGS += -DWINVER=0x0600 -D_WIN32_WINNT=0x0600
libsquashfs_la_CFLAGS += -Wc,-static-libgcc
libsquashfs_la_LDFLAGS += -no-undefined -avoid-version
else
-libsquashfs_la_SOURCES += lib/sqfs/src/io/unix.c
+libsquashfs_la_SOURCES += lib/sqfs/src/io/unix.c lib/sqfs/src/io/dir_unix.c
endif
if HAVE_PTHREAD
diff --git a/lib/io/src/unix/dir_iterator.c b/lib/sqfs/src/io/dir_unix.c
index 74ac953..83127ec 100644
--- a/lib/io/src/unix/dir_iterator.c
+++ b/lib/sqfs/src/io/dir_unix.c
@@ -1,12 +1,14 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/*
- * dir_iterator.c
+ * dir_unix.c
*
* Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at>
*/
+#define SQFS_BUILDING_DLL
#include "config.h"
-#include "io/dir_iterator.h"
+
#include "util/util.h"
+#include "sqfs/dir_entry.h"
#include "sqfs/error.h"
#include "sqfs/io.h"
@@ -226,16 +228,18 @@ static int create_iterator(sqfs_dir_iterator_t **out, DIR *dir)
return 0;
}
-sqfs_dir_iterator_t *dir_iterator_create(const char *path)
+int sqfs_dir_iterator_create_native(sqfs_dir_iterator_t **out,
+ const char *path, sqfs_u32 flags)
{
- sqfs_dir_iterator_t *out;
DIR *dir;
+ *out = NULL;
+ if (flags & (~SQFS_FILE_OPEN_NO_CHARSET_XFRM))
+ return SQFS_ERROR_UNSUPPORTED;
+
dir = opendir(path);
- if (dir == NULL || create_iterator(&out, dir) != 0) {
- perror(path);
- return NULL;
- }
+ if (dir == NULL)
+ return SQFS_ERROR_IO;
- return out;
+ return create_iterator(out, dir);
}
diff --git a/lib/io/src/win32/dir_iterator.c b/lib/sqfs/src/io/dir_win32.c
index 15cfbc5..5875ae5 100644
--- a/lib/io/src/win32/dir_iterator.c
+++ b/lib/sqfs/src/io/dir_win32.c
@@ -1,12 +1,14 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/*
- * dir_iterator.c
+ * dir_win32.c
*
* Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at>
*/
+#define SQFS_BUILDING_DLL
#include "config.h"
-#include "io/dir_iterator.h"
+
#include "util/util.h"
+#include "sqfs/dir_entry.h"
#include "sqfs/error.h"
#include "sqfs/io.h"
@@ -226,8 +228,10 @@ static int dir_iterator_open_subdir(sqfs_dir_iterator_t *it,
ret = dir_iterator_init(sub);
if (ret != 0) {
+ os_error_t err = get_os_error_state();
free(sub);
sub = NULL;
+ set_os_error_state(err);
}
*out = (sqfs_dir_iterator_t *)sub;
@@ -254,56 +258,65 @@ static int dir_iterator_init(dir_iterator_win32_t *it)
return 0;
}
-sqfs_dir_iterator_t *dir_iterator_create(const char *path)
+int sqfs_dir_iterator_create_native(sqfs_dir_iterator_t **out,
+ const char *path, sqfs_u32 flags)
{
dir_iterator_win32_t *it;
- size_t len, newlen;
WCHAR *wpath = NULL;
void *new = NULL;
+ DWORD length;
+ size_t len;
+ int ret;
- /* convert path to UTF-16, append "\\*" */
- wpath = path_to_windows(path);
- if (wpath == NULL)
- goto fail_alloc;
+ *out = NULL;
+ if (flags & (~SQFS_FILE_OPEN_NO_CHARSET_XFRM))
+ return SQFS_ERROR_UNSUPPORTED;
- len = wcslen(wpath);
- newlen = len + 1;
+ /* convert path to UTF-16, append "\\*" */
+ len = strlen(path);
+ while (len > 0 && (path[len - 1] == '/' || path[len - 1] == '\\'))
+ --len;
- if (len > 0 && wpath[len - 1] != '\\')
- newlen += 1;
+ length = MultiByteToWideChar(CP_UTF8, 0, path, len, NULL, 0);
+ if (length <= 0)
+ return SQFS_ERROR_ALLOC;
- new = realloc(wpath, sizeof(wpath[0]) * (newlen + 1));
- if (new == NULL)
- goto fail_alloc;
+ wpath = calloc(sizeof(wpath[0]), length + 3);
+ if (wpath == NULL)
+ return SQFS_ERROR_ALLOC;
- wpath = new;
+ MultiByteToWideChar(CP_UTF8, 0, path, len, wpath, length + 1);
- if (len > 0 && wpath[len - 1] != '\\')
- wpath[len++] = '\\';
+ for (DWORD i = 0; i < length; ++i) {
+ if (wpath[i] == '/')
+ wpath[i] = '\\';
+ }
- wpath[len++] = '*';
- wpath[len++] = '\0';
+ wpath[length++] = '\\';
+ wpath[length++] = '*';
+ wpath[length++] = '\0';
/* create the sourrounding iterator structure */
- new = realloc(wpath, sizeof(*it) + len * sizeof(wpath[0]));
- if (new == NULL)
- goto fail_alloc;
+ new = realloc(wpath, sizeof(*it) + length * sizeof(wpath[0]));
+ if (new == NULL) {
+ free(wpath);
+ return SQFS_ERROR_ALLOC;
+ }
it = new;
wpath = NULL;
- memmove(it->path, new, len * sizeof(wpath[0]));
+ memmove(it->path, new, length * sizeof(wpath[0]));
/* initialize */
memset(it, 0, offsetof(dir_iterator_win32_t, path));
- if (dir_iterator_init(it) != 0) {
- w32_perror(path);
+ ret = dir_iterator_init(it);
+ if (ret != 0) {
+ os_error_t err = get_os_error_state();
free(it);
it = NULL;
+ set_os_error_state(err);
}
- return (sqfs_dir_iterator_t *)it;
-fail_alloc:
- fprintf(stderr, "%s: allocation failure.\n", path);
- free(wpath);
- return NULL;
+ *out = (sqfs_dir_iterator_t *)it;
+ return ret;
}