-/*
- * wimlib.h
- *
- * External header for wimlib.
+/**
+ * @file wimlib.h
+ * @brief External header for wimlib.
*
* This file contains extensive comments for generating documentation with
* Doxygen. The built HTML documentation can be viewed at
uint32_t is_free : 1;
uint32_t is_spanned : 1;
- uint32_t reserved_flags : 28;
+
+ /** 1 if this resource was not found in the 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;
+
+ uint32_t reserved_flags : 27;
uint64_t reserved[4];
};
* 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 resources needed to fill in
+ * the ::wimlib_resource_entry's for the iteration cannot be found in the lookup
+ * table of the ::WIMStruct. The default behavior without this flag is to fill
+ * in the SHA1 message digest of the ::wimlib_resource_entry and set the @ref
+ * wimlib_resource_entry::is_missing "is_missing" flag. */
+#define WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED 0x00000004
/**
* The WIM containing the image(s) over which to iterate, specified as a
* pointer to the ::WIMStruct for a standalone WIM file, a delta WIM file,
* or part 1 of a split WIM. In the case of a WIM file that is not
- * standalone, this ::WIMStruct must have had any needed external resources
- * previously referenced using wimlib_reference_resources() or
- * wimlib_reference_resource_files().
+ * standalone, this ::WIMStruct should have had any needed external
+ * resources previously referenced using wimlib_reference_resources() or
+ * wimlib_reference_resource_files(). If not, see
+ * ::WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED for information about
+ * the behavior when resources are missing.
*
* @param image
* The 1-based number of the image in @p wim that contains the files or
* Path in the WIM image at which to do the iteration.
*
* @param flags
- * Bitwise OR of ::WIMLIB_ITERATE_DIR_TREE_FLAG_RECURSIVE and/or
- * ::WIMLIB_ITERATE_DIR_TREE_FLAG_CHILDREN.
+ * Bitwise OR of flags prefixed with WIMLIB_ITERATE_DIR_TREE_FLAG.
*
* @param cb
* A callback function that will receive each directory entry.
bool force);
extern int
-resource_not_found_error(struct wim_inode *inode, const u8 *hash);
+resource_not_found_error(const struct wim_inode *inode, const u8 *hash);
extern void
inode_unresolve_ltes(struct wim_inode *inode);
extern struct wim_lookup_table_entry *
inode_unnamed_lte(const struct wim_inode *inode, const struct wim_lookup_table *table);
+extern const u8 *
+inode_unnamed_stream_hash(const struct wim_inode *inode);
+
extern u64
lookup_table_total_stream_size(struct wim_lookup_table *table);
static int
init_wimlib_dentry(struct wimlib_dir_entry *wdentry,
struct wim_dentry *dentry,
- const WIMStruct *wim)
+ const WIMStruct *wim,
+ int flags)
{
int ret;
size_t dummy;
const struct wim_inode *inode = dentry->d_inode;
struct wim_lookup_table_entry *lte;
+ const u8 *hash;
#if TCHAR_IS_UTF16LE
wdentry->filename = dentry->file_name;
wdentry->last_access_time = wim_timestamp_to_timespec(inode->i_last_access_time);
lte = inode_unnamed_lte(inode, wim->lookup_table);
- if (lte)
+ if (lte) {
lte_to_wimlib_resource_entry(lte, &wdentry->streams[0].resource);
+ } else if (!is_zero_hash(hash = inode_unnamed_stream_hash(inode))) {
+ if (flags & WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED)
+ return resource_not_found_error(inode, hash);
+ copy_hash(wdentry->streams[0].resource.sha1_hash, hash);
+ wdentry->streams[0].resource.is_missing = 1;
+ }
for (unsigned i = 0; i < inode->i_num_ads; i++) {
- if (inode->i_ads_entries[i].stream_name == NULL)
+ if (!ads_entry_is_named_stream(&inode->i_ads_entries[i]))
continue;
lte = inode_stream_lte(inode, i + 1, wim->lookup_table);
wdentry->num_named_streams++;
if (lte) {
lte_to_wimlib_resource_entry(lte, &wdentry->streams[
wdentry->num_named_streams].resource);
+ } else if (!is_zero_hash(hash = inode_stream_hash(inode, i + 1))) {
+ if (flags & WIMLIB_ITERATE_DIR_TREE_FLAG_RESOURCES_NEEDED)
+ return resource_not_found_error(inode, hash);
+ copy_hash(wdentry->streams[
+ wdentry->num_named_streams].resource.sha1_hash, hash);
+ wdentry->streams[
+ wdentry->num_named_streams].resource.is_missing = 1;
}
#if TCHAR_IS_UTF16LE
wdentry->streams[wdentry->num_named_streams].stream_name =
if (!wdentry)
goto out;
- ret = init_wimlib_dentry(wdentry, dentry, wim);
+ ret = init_wimlib_dentry(wdentry, dentry, wim, flags);
if (ret)
goto out_free_wimlib_dentry;
#endif
int
-resource_not_found_error(struct wim_inode *inode, const u8 *hash)
+resource_not_found_error(const struct wim_inode *inode, const u8 *hash)
{
if (wimlib_print_errors) {
ERROR("\"%"TS"\": resource not found", inode_first_full_path(inode));
return inode_unnamed_lte_unresolved(inode, table);
}
+const u8 *
+inode_unnamed_stream_hash(const struct wim_inode *inode)
+{
+ const u8 *hash;
+
+ for (unsigned i = 0; i <= inode->i_num_ads; i++) {
+ if (inode_stream_name_nbytes(inode, i) == 0) {
+ hash = inode_stream_hash(inode, i);
+ if (!is_zero_hash(hash))
+ return hash;
+ }
+ }
+ return NULL;
+}
+
+
static int
lte_add_stream_size(struct wim_lookup_table_entry *lte, void *total_bytes_p)
{