aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-05-14 03:10:46 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-05-14 03:25:32 +0200
commit5e96ce975e021551006ebff744c104f20d49741b (patch)
tree2006c52a48718e1d04686693c3e08c32be0ee48e
parente501c9a4bc230dab034571c2078a12a8a856c67a (diff)
libio: merge directory iterator headers, document API and behavior
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--bin/gensquashfs/src/mkfs.h2
-rw-r--r--include/io/dir_iterator.h191
-rw-r--r--include/io/dir_tree_iterator.h54
-rw-r--r--lib/io/Makemodule.am2
-rw-r--r--lib/io/src/dir_tree_iterator.c2
-rw-r--r--lib/io/test/dir_tree_iterator.c2
-rw-r--r--lib/io/test/dir_tree_iterator2.c2
-rw-r--r--lib/io/test/dir_tree_iterator3.c2
8 files changed, 194 insertions, 63 deletions
diff --git a/bin/gensquashfs/src/mkfs.h b/bin/gensquashfs/src/mkfs.h
index f9eadc6..9205b7b 100644
--- a/bin/gensquashfs/src/mkfs.h
+++ b/bin/gensquashfs/src/mkfs.h
@@ -12,7 +12,7 @@
#include "common.h"
#include "fstree.h"
-#include "io/dir_tree_iterator.h"
+#include "io/dir_iterator.h"
#include "util/util.h"
#include "io/file.h"
diff --git a/include/io/dir_iterator.h b/include/io/dir_iterator.h
index 7080d65..74027f5 100644
--- a/include/io/dir_iterator.h
+++ b/include/io/dir_iterator.h
@@ -9,36 +9,221 @@
#include "sqfs/predef.h"
+/**
+ * @struct dir_entry_t
+ *
+ * @brief A directory entry returned by a @ref dir_iterator_t
+ */
typedef struct {
+ /**
+ * @brief Unix time stamp when the entry was last modified.
+ *
+ * If necessary, the OS native time stamp is converted to Unix time.
+ */
sqfs_s64 mtime;
+
+ /**
+ * @brief Device number where the entry is stored on.
+ *
+ * On Windows and other non-Unix OSes, a dummy value is stored here.
+ */
sqfs_u64 dev;
+
+ /**
+ * @brief Device number for device special files.
+ *
+ * On Windows and other non-Unix OSes, a dummy value is stored here.
+ */
sqfs_u64 rdev;
+
+ /**
+ * @brief ID of the user that owns the entry.
+ *
+ * On Windows and other non-Unix OSes, this always reports user 0.
+ */
sqfs_u32 uid;
+
+ /**
+ * @brief ID of the group that owns the entry.
+ *
+ * On Windows and other non-Unix OSes, this always reports group 0.
+ */
sqfs_u32 gid;
+
+ /**
+ * @brief Unix style permissions and entry type.
+ *
+ * On Windows and other non-Unix OSes, this is synthesized from the
+ * Unix-like file type, default 0755 permissions for directories or
+ * 0644 for files.
+ */
sqfs_u16 mode;
+ /**
+ * @brief Name of the entry
+ *
+ * On Unix-like OSes, the name is returned as-is. On systems like
+ * Windows with encoding-aware APIs, the name is converted to UTF-8.
+ */
char name[];
} dir_entry_t;
+/**
+ * @interface dir_iterator_t
+ *
+ * @brief An iterator over entries in a filesystem directory.
+ */
typedef struct dir_iterator_t {
sqfs_object_t obj;
+ /**
+ * @brief A device number for detecting mount points and hard links.
+ *
+ * On Unix-like systems this exposes the underlying device number
+ * backing this directory. Each entry returned by the iterator also
+ * has a device number and if it is different, you found a mount point.
+ *
+ * The device number, combined with inode number, are also needed to
+ * detect hard links. Entries with same device and inode number point
+ * to the same file.
+ */
sqfs_u64 dev;
- int (*next)(struct dir_iterator_t *it,
- dir_entry_t **out);
+ /**
+ * @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 dir_iterator_t *it, 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 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 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 dir_iterator_t *it,
struct dir_iterator_t **out);
} dir_iterator_t;
+enum {
+ DIR_SCAN_NO_SOCK = 0x0001,
+ DIR_SCAN_NO_SLINK = 0x0002,
+ DIR_SCAN_NO_FILE = 0x0004,
+ DIR_SCAN_NO_BLK = 0x0008,
+ DIR_SCAN_NO_DIR = 0x0010,
+ DIR_SCAN_NO_CHR = 0x0020,
+ DIR_SCAN_NO_FIFO = 0x0040,
+
+ DIR_SCAN_KEEP_TIME = 0x0100,
+ DIR_SCAN_KEEP_UID = 0x0200,
+ DIR_SCAN_KEEP_GID = 0x0400,
+ DIR_SCAN_KEEP_MODE = 0x0800,
+
+ DIR_SCAN_ONE_FILESYSTEM = 0x1000,
+ DIR_SCAN_NO_RECURSION = 0x2000,
+ DIR_SCAN_MATCH_FULL_PATH = 0x4000,
+};
+
+typedef struct {
+ sqfs_u32 flags;
+ sqfs_u32 def_uid;
+ sqfs_u32 def_gid;
+ sqfs_u32 def_mode;
+ sqfs_s64 def_mtime;
+
+ /**
+ * @brief A prefix to attach to all returend paths
+ *
+ * If not null, this string and an additional "/" are prepended to
+ * all entries returned by the iterator.
+ */
+ const char *prefix;
+
+ /**
+ * @brief A glob pattern that either the name must match
+ *
+ * If this is not NULL, only paths that match this globbing pattern
+ * are returned. If the flag DIR_SCAN_MATCH_FULL_PATH is set, the
+ * entire path must match, slashes cannot match wild card characters.
+ * If not set, only the last part of the path is tested. The iterator
+ * still recurses into directories, it simply doesn't report them if
+ * they don't match.
+ */
+ const char *name_pattern;
+} dir_tree_cfg_t;
+
#ifdef __cplusplus
extern "C" {
#endif
-dir_iterator_t *dir_iterator_create(const char *path);
+/**
+ * @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 dir_iterator_t implementation on success,
+ * NULL on error (message is printed to stderr).
+ */
+SQFS_INTERNAL 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
+ * and returns a flattened list of entries, where each entry represents a full
+ * path. Advanced filtering, path pre-fixing et cetera can be configured.
+ * The typical "." and ".." entries are filtered out as well.
+ *
+ * @param path A path to a directory on the file system.
+ * @param cfg A @ref dir_tree_cfg_t filtering configuration.
+ *
+ * @return A pointer to a dir_iterator_t implementation on success,
+ * NULL on error (message is printed to stderr).
+ */
+SQFS_INTERNAL
+dir_iterator_t *dir_tree_iterator_create(const char *path,
+ const dir_tree_cfg_t *cfg);
+
+/**
+ * @brief Skip a sub-hierarchy on a stacked iterator
+ *
+ * For an iterator returned by @ref dir_tree_iterator_create, if the last entry
+ * was a directory, do not recurse, but instead skip across the netire sub-tree.
+ *
+ * @param it A pointer to an iterator returned by @ref dir_tree_iterator_create
+ */
+SQFS_INTERNAL void dir_tree_iterator_skip(dir_iterator_t *it);
#ifdef __cplusplus
}
diff --git a/include/io/dir_tree_iterator.h b/include/io/dir_tree_iterator.h
deleted file mode 100644
index 557178b..0000000
--- a/include/io/dir_tree_iterator.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * dir_tree_iterator.h
- *
- * Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at>
- */
-#ifndef IO_DIR_TREE_ITERATOR_H
-#define IO_DIR_TREE_ITERATOR_H
-
-#include "io/dir_iterator.h"
-
-enum {
- DIR_SCAN_NO_SOCK = 0x0001,
- DIR_SCAN_NO_SLINK = 0x0002,
- DIR_SCAN_NO_FILE = 0x0004,
- DIR_SCAN_NO_BLK = 0x0008,
- DIR_SCAN_NO_DIR = 0x0010,
- DIR_SCAN_NO_CHR = 0x0020,
- DIR_SCAN_NO_FIFO = 0x0040,
-
- DIR_SCAN_KEEP_TIME = 0x0100,
- DIR_SCAN_KEEP_UID = 0x0200,
- DIR_SCAN_KEEP_GID = 0x0400,
- DIR_SCAN_KEEP_MODE = 0x0800,
-
- DIR_SCAN_ONE_FILESYSTEM = 0x1000,
- DIR_SCAN_NO_RECURSION = 0x2000,
- DIR_SCAN_MATCH_FULL_PATH = 0x4000,
-};
-
-typedef struct {
- sqfs_u32 flags;
- sqfs_u32 def_uid;
- sqfs_u32 def_gid;
- sqfs_u32 def_mode;
- sqfs_s64 def_mtime;
- const char *prefix;
- const char *name_pattern;
-} dir_tree_cfg_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-dir_iterator_t *dir_tree_iterator_create(const char *path,
- const dir_tree_cfg_t *cfg);
-
-void dir_tree_iterator_skip(dir_iterator_t *it);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* IO_DIR_TREE_ITERATOR_H */
diff --git a/lib/io/Makemodule.am b/lib/io/Makemodule.am
index 9f97540..2fcd1a7 100644
--- a/lib/io/Makemodule.am
+++ b/lib/io/Makemodule.am
@@ -1,6 +1,6 @@
libio_a_SOURCES = include/io/istream.h include/io/ostream.h include/io/xfrm.h \
include/io/file.h include/io/std.h \
- include/io/dir_iterator.h include/io/dir_tree_iterator.h \
+ include/io/dir_iterator.h \
lib/io/src/internal.h lib/io/src/ostream.c \
lib/io/src/istream.c lib/io/src/get_line.c lib/io/src/xfrm/ostream.c \
lib/io/src/xfrm/istream.c lib/io/src/dir_tree_iterator.c
diff --git a/lib/io/src/dir_tree_iterator.c b/lib/io/src/dir_tree_iterator.c
index b05eeb3..85b1c9f 100644
--- a/lib/io/src/dir_tree_iterator.c
+++ b/lib/io/src/dir_tree_iterator.c
@@ -5,7 +5,7 @@
* Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at>
*/
#include "config.h"
-#include "io/dir_tree_iterator.h"
+#include "io/dir_iterator.h"
#include "util/util.h"
#include "sqfs/error.h"
diff --git a/lib/io/test/dir_tree_iterator.c b/lib/io/test/dir_tree_iterator.c
index 75e32fb..46e0a56 100644
--- a/lib/io/test/dir_tree_iterator.c
+++ b/lib/io/test/dir_tree_iterator.c
@@ -6,7 +6,7 @@
*/
#include "config.h"
-#include "io/dir_tree_iterator.h"
+#include "io/dir_iterator.h"
#include "sqfs/error.h"
#include "util/test.h"
#include "compat.h"
diff --git a/lib/io/test/dir_tree_iterator2.c b/lib/io/test/dir_tree_iterator2.c
index d3c4990..280fa78 100644
--- a/lib/io/test/dir_tree_iterator2.c
+++ b/lib/io/test/dir_tree_iterator2.c
@@ -6,7 +6,7 @@
*/
#include "config.h"
-#include "io/dir_tree_iterator.h"
+#include "io/dir_iterator.h"
#include "sqfs/error.h"
#include "util/test.h"
#include "compat.h"
diff --git a/lib/io/test/dir_tree_iterator3.c b/lib/io/test/dir_tree_iterator3.c
index 6fce085..180beff 100644
--- a/lib/io/test/dir_tree_iterator3.c
+++ b/lib/io/test/dir_tree_iterator3.c
@@ -6,7 +6,7 @@
*/
#include "config.h"
-#include "io/dir_tree_iterator.h"
+#include "io/dir_iterator.h"
#include "sqfs/error.h"
#include "util/test.h"
#include "compat.h"