+/**
+ * Information about a "blob", which is a fixed length sequence of binary data.
+ * Each nonempty stream of each file in a WIM image is associated with a blob.
+ * Blobs are deduplicated within a WIM file.
+ *
+ * TODO: this struct needs to be renamed, and perhaps made into a union since
+ * there are several cases. I'll try to list them below:
+ *
+ * 1. The blob is "missing", meaning that it is referenced by hash but not
+ * actually present in the WIM file. In this case we only know the
+ * sha1_hash. This case can only occur with wimlib_iterate_dir_tree(), never
+ * wimlib_iterate_lookup_table().
+ *
+ * 2. Otherwise we know the sha1_hash, the uncompressed_size, the
+ * reference_count, and the is_metadata flag. In addition:
+ *
+ * A. If the blob is located in a non-solid WIM resource, then we also know
+ * the compressed_size and offset.
+ *
+ * B. If the blob is located in a solid WIM resource, then we also know the
+ * offset, raw_resource_offset_in_wim, raw_resource_compressed_size, and
+ * raw_resource_uncompressed_size. But the "offset" is actually the
+ * offset in the uncompressed solid resource rather than the offset from
+ * the beginning of the WIM file.
+ *
+ * C. If the blob is *not* located in any type of WIM resource, then we don't
+ * know any additional information.
+ *
+ * Unknown or irrelevant fields are left zeroed.
+ */
+struct wimlib_resource_entry {
+
+ /** If this blob is not missing, then this is the uncompressed size of
+ * this blob in bytes. */
+ uint64_t uncompressed_size;
+
+ /** If this blob is located in a non-solid WIM resource, then this is
+ * the compressed size of that resource. */
+ uint64_t compressed_size;
+
+ /** If this blob is located in a non-solid WIM resource, then this is
+ * the offset of that resource within the WIM file containing it. If
+ * this blob is located in a solid WIM resource, then this is the offset
+ * of this blob within that solid resource when uncompressed. */
+ uint64_t offset;
+
+ /** The SHA-1 message digest of the blob's uncompressed contents. */
+ uint8_t sha1_hash[20];
+
+ /** If this blob is located in a WIM resource, then this is the part
+ * number of the WIM file containing it. */
+ uint32_t part_number;
+
+ /** If this blob is not missing, then this is the number of times this
+ * blob is referenced over all images in the WIM. This number is not
+ * guaranteed to be correct. */
+ uint32_t reference_count;
+
+ /** 1 iff this blob is located in a non-solid compressed WIM resource.
+ */
+ uint32_t is_compressed : 1;
+
+ /** 1 iff this blob contains the metadata for an image. */
+ uint32_t is_metadata : 1;
+
+ uint32_t is_free : 1;
+ uint32_t is_spanned : 1;
+
+ /** 1 iff a blob with this hash was not found in the blob lookup table
+ * of the ::WIMStruct. This normally implies a missing call to
+ * wimlib_reference_resource_files() or wimlib_reference_resources(). */
+ uint32_t is_missing : 1;
+
+ /** 1 iff this blob is located in a solid resource. */
+ uint32_t packed : 1;
+
+ uint32_t reserved_flags : 26;
+
+ /** If this blob is located in a solid WIM resource, then this is the
+ * offset of that solid resource within the WIM file containing it. */
+ uint64_t raw_resource_offset_in_wim;
+
+ /** If this blob is located in a solid WIM resource, then this is the
+ * compressed size of that solid resource. */
+ uint64_t raw_resource_compressed_size;
+
+ /** If this blob is located in a solid WIM resource, then this is the
+ * uncompressed size of that solid resource. */
+ uint64_t raw_resource_uncompressed_size;
+
+ uint64_t reserved[1];
+};
+
+/**
+ * Information about a stream of a particular file in the WIM.
+ *
+ * Normally, only WIM images captured from NTFS filesystems will have multiple
+ * streams per file. In practice, this is a rarely used feature of the
+ * filesystem.
+ *
+ * TODO: the library now explicitly tracks stream types, which allows it to have
+ * multiple unnamed streams (e.g. both a reparse point stream and unnamed data
+ * stream). However, this isn't yet exposed by wimlib_iterate_dir_tree().
+ */
+struct wimlib_stream_entry {
+
+ /** Name of the stream, or NULL if the stream is unnamed. */
+ const wimlib_tchar *stream_name;
+
+ /** Info about this stream's data, such as its hash and size if known.*/
+ struct wimlib_resource_entry resource;
+
+ uint64_t reserved[4];
+};
+
+/** Structure passed to the wimlib_iterate_dir_tree() callback function.
+ * Roughly, the information about a "file" in the WIM--- but really a directory
+ * entry ("dentry") because hard links are allowed. The hard_link_group_id
+ * field can be used to distinguish actual file inodes. */
+struct wimlib_dir_entry {
+ /** Name of the file, or NULL if this file is unnamed. Only the root
+ * directory of an image will be unnamed. */
+ const wimlib_tchar *filename;
+
+ /** 8.3 name (or "DOS name", or "short name") of this file; or NULL if
+ * this file has no such name. */
+ const wimlib_tchar *dos_name;
+
+ /** Full path to this file within the WIM image. Path separators will
+ * be ::WIMLIB_WIM_PATH_SEPARATOR. */
+ const wimlib_tchar *full_path;
+
+ /** Depth of this directory entry, where 0 is the root, 1 is the root's
+ * children, ..., etc. */
+ size_t depth;
+
+ /** Pointer to the security descriptor for this file, in Windows
+ * SECURITY_DESCRIPTOR_RELATIVE format, or NULL if this file has no
+ * security descriptor. */
+ const char *security_descriptor;
+
+ /** Length of the above security descriptor. */
+ size_t security_descriptor_size;
+
+#define WIMLIB_FILE_ATTRIBUTE_READONLY 0x00000001
+#define WIMLIB_FILE_ATTRIBUTE_HIDDEN 0x00000002
+#define WIMLIB_FILE_ATTRIBUTE_SYSTEM 0x00000004
+#define WIMLIB_FILE_ATTRIBUTE_DIRECTORY 0x00000010
+#define WIMLIB_FILE_ATTRIBUTE_ARCHIVE 0x00000020
+#define WIMLIB_FILE_ATTRIBUTE_DEVICE 0x00000040
+#define WIMLIB_FILE_ATTRIBUTE_NORMAL 0x00000080
+#define WIMLIB_FILE_ATTRIBUTE_TEMPORARY 0x00000100
+#define WIMLIB_FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
+#define WIMLIB_FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
+#define WIMLIB_FILE_ATTRIBUTE_COMPRESSED 0x00000800
+#define WIMLIB_FILE_ATTRIBUTE_OFFLINE 0x00001000
+#define WIMLIB_FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
+#define WIMLIB_FILE_ATTRIBUTE_ENCRYPTED 0x00004000
+#define WIMLIB_FILE_ATTRIBUTE_VIRTUAL 0x00010000
+ /** File attributes, such as whether the file is a directory or not.
+ * These are the "standard" Windows FILE_ATTRIBUTE_* values, although in
+ * wimlib.h they are defined as WIMLIB_FILE_ATTRIBUTE_* for convenience
+ * on other platforms. */
+ uint32_t attributes;
+
+#define WIMLIB_REPARSE_TAG_RESERVED_ZERO 0x00000000
+#define WIMLIB_REPARSE_TAG_RESERVED_ONE 0x00000001
+#define WIMLIB_REPARSE_TAG_MOUNT_POINT 0xA0000003
+#define WIMLIB_REPARSE_TAG_HSM 0xC0000004
+#define WIMLIB_REPARSE_TAG_HSM2 0x80000006
+#define WIMLIB_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
+#define WIMLIB_REPARSE_TAG_SIS 0x80000007
+#define WIMLIB_REPARSE_TAG_DFS 0x8000000A
+#define WIMLIB_REPARSE_TAG_DFSR 0x80000012
+#define WIMLIB_REPARSE_TAG_FILTER_MANAGER 0x8000000B
+#define WIMLIB_REPARSE_TAG_WOF 0x80000017
+#define WIMLIB_REPARSE_TAG_SYMLINK 0xA000000C
+ /** If the file is a reparse point (FILE_ATTRIBUTE_REPARSE_POINT set in
+ * the attributes), this will give the reparse tag. This tells you
+ * whether the reparse point is a symbolic link, junction point, or some
+ * other, more unusual kind of reparse point. */
+ uint32_t reparse_tag;
+
+ /** Number of links to this file's inode (hard links).
+ *
+ * Currently, this will always be 1 for directories. However, it can be
+ * greater than 1 for nondirectory files. */
+ uint32_t num_links;
+
+ /** Number of named data streams this file has. Normally 0. */
+ uint32_t num_named_streams;
+
+ /** A unique identifier for this file's inode. However, as a special
+ * case, if the inode only has a single link (@p num_links == 1), this
+ * value may be 0.
+ *
+ * Note: if a WIM image is captured from a filesystem, this value is not
+ * guaranteed to be the same as the original number of the inode on the
+ * filesystem. */
+ uint64_t hard_link_group_id;
+
+ /** Time this file was created. */
+ struct timespec creation_time;
+
+ /** Time this file was last written to. */
+ struct timespec last_write_time;
+
+ /** Time this file was last accessed. */
+ struct timespec last_access_time;
+
+ /** The UNIX user ID of this file. This is a wimlib extension.
+ *
+ * This field is only valid if @p unix_mode != 0. */
+ uint32_t unix_uid;
+
+ /** The UNIX group ID of this file. This is a wimlib extension.
+ *
+ * This field is only valid if @p unix_mode != 0. */
+ uint32_t unix_gid;
+
+ /** The UNIX mode of this file. This is a wimlib extension.
+ *
+ * If this field is 0, then @p unix_uid, @p unix_gid, @p unix_mode, and
+ * @p unix_rdev are all unknown (fields are not present in the WIM
+ * image). */
+ uint32_t unix_mode;
+
+ /** The UNIX device ID (major and minor number) of this file. This is a
+ * wimlib extension.
+ *
+ * This field is only valid if @p unix_mode != 0. */
+ uint32_t unix_rdev;
+
+ uint64_t reserved[14];
+
+ /**
+ * Array of streams that make up this file.
+ *
+ * The first entry will always exist and will correspond to the unnamed
+ * data stream (default file contents), so it will have <c>stream_name
+ * == NULL</c>. Alternatively, for reparse point files, the first entry
+ * will correspond to the reparse data stream. Alternatively, for
+ * encrypted files, the first entry will correspond to the encrypted
+ * data.
+ *
+ * Then, following the first entry, there be @p num_named_streams
+ * additional entries that specify the named data streams, if any, each
+ * of which will have <c>stream_name != NULL</c>.
+ */
+ struct wimlib_stream_entry streams[];
+};
+
+/**
+ * Type of a callback function to wimlib_iterate_dir_tree(). Must return 0 on
+ * success.
+ */
+typedef int (*wimlib_iterate_dir_tree_callback_t)(const struct wimlib_dir_entry *dentry,
+ void *user_ctx);
+
+/**
+ * Type of a callback function to wimlib_iterate_lookup_table(). Must return 0
+ * on success.
+ */
+typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resource_entry *resource,
+ void *user_ctx);
+
+/** For wimlib_iterate_dir_tree(): Iterate recursively on children rather than
+ * just on the specified path. */
+#define WIMLIB_ITERATE_DIR_TREE_FLAG_RECURSIVE 0x00000001
+
+/** For wimlib_iterate_dir_tree(): Don't iterate on the file or directory
+ * itself; only its children (in the case of a non-empty directory) */
+#define WIMLIB_ITERATE_DIR_TREE_FLAG_CHILDREN 0x00000002
+
+/** Return ::WIMLIB_ERR_RESOURCE_NOT_FOUND if any file data blobs needed to fill
+ * in the ::wimlib_resource_entry's for the iteration cannot be found in the
+ * blob lookup table of the ::WIMStruct. The default behavior without this flag
+ * is to fill in the @ref wimlib_resource_entry::sha1_hash "sha1_hash" and set
+ * the @ref wimlib_resource_entry::is_missing "is_missing" flag. */
+#define WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED 0x00000004