From 7251c7d0afac3b738dda1c4f45e6d3d3090f2622 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 14 Dec 2014 15:03:40 -0600 Subject: [PATCH] inode.h, inode.c cleanup --- Makefile.am | 1 + include/wimlib/inode.h | 245 +++++++------------- src/compress.c | 1 - src/decompress_common.c | 1 + src/extract.c | 9 +- src/inode.c | 492 +++++++++++++--------------------------- src/inode_table.c | 192 ++++++++++++++++ src/iterate_dir.c | 2 +- src/metadata_resource.c | 1 + src/mount_image.c | 13 +- src/ntfs-3g_apply.c | 1 + src/ntfs-3g_capture.c | 1 + src/template.c | 1 + src/textfile.c | 1 - src/unix_apply.c | 1 + src/update_image.c | 1 + src/wim.c | 1 + src/win32_apply.c | 1 + src/win32_capture.c | 1 + src/write.c | 1 + src/xml.c | 1 + 21 files changed, 458 insertions(+), 510 deletions(-) create mode 100644 src/inode_table.c diff --git a/Makefile.am b/Makefile.am index c19b7fcc..ed7ac511 100644 --- a/Makefile.am +++ b/Makefile.am @@ -38,6 +38,7 @@ libwim_la_SOURCES = \ src/header.c \ src/inode.c \ src/inode_fixup.c \ + src/inode_table.c \ src/integrity.c \ src/iterate_dir.c \ src/join.c \ diff --git a/include/wimlib/inode.h b/include/wimlib/inode.h index 733d3847..4b956775 100644 --- a/include/wimlib/inode.h +++ b/include/wimlib/inode.h @@ -1,19 +1,17 @@ #ifndef _WIMLIB_INODE_H #define _WIMLIB_INODE_H -#include "wimlib/assert.h" #include "wimlib/list.h" -#include "wimlib/lookup_table.h" #include "wimlib/sha1.h" +#include "wimlib/types.h" -#include - +struct avl_tree_node; struct wim_ads_entry; struct wim_dentry; -struct wim_security_data; struct wim_lookup_table; +struct wim_lookup_table_entry; +struct wim_security_data; struct wimfs_fd; -struct avl_tree_node; /* * WIM inode. @@ -70,9 +68,9 @@ struct wim_inode { * for the same inode. */ struct hlist_node i_hlist; - /* Normal list node- used to connect all the inodes of a WIM image - * into a single linked list referenced from the - * `struct wim_image_metadata' for that image. */ + /* Normal list node- used to connect all the inodes of a WIM + * image into a single linked list referenced from the `struct + * wim_image_metadata' for that image. */ struct list_head i_list; }; @@ -118,10 +116,10 @@ struct wim_inode { /* Size of @i_extra buffer in bytes. If 0, there is no extra data. */ size_t i_extra_size; - /* Creation time, last access time, and last write time for this inode, in - * 100-nanosecond intervals since 12:00 a.m UTC January 1, 1601. They - * should correspond to the times gotten by calling GetFileTime() on - * Windows. */ + /* Creation time, last access time, and last write time for this inode, + * in 100-nanosecond intervals since 12:00 a.m UTC January 1, 1601. + * They should correspond to the times gotten by calling GetFileTime() + * on Windows. */ u64 i_creation_time; u64 i_last_access_time; u64 i_last_write_time; @@ -243,28 +241,26 @@ struct wim_ads_entry { /* WIM alternate data stream entry (on-disk format) */ struct wim_ads_entry_on_disk { - /* Length of the entry, in bytes. This apparently includes all - * fixed-length fields, plus the stream name and null terminator if - * present, and the padding up to an 8 byte boundary. wimlib is a - * little less strict when reading the entries, and only requires that - * the number of bytes from this field is at least as large as the size - * of the fixed length fields and stream name without null terminator. - * */ - le64 length; + /* Length of the entry, in bytes. This includes all fixed-length + * fields, plus the stream name and null terminator if present, and the + * padding up to an 8 byte boundary. wimlib is a little less strict + * when reading the entries, and only requires that the number of bytes + * from this field is at least as large as the size of the fixed length + * fields and stream name without null terminator. */ + le64 length; - le64 reserved; + le64 reserved; /* SHA1 message digest of the uncompressed stream; or, alternatively, - * can be all zeroes if the stream has zero length. */ + * can be all zeroes if the stream has zero length. */ u8 hash[SHA1_HASH_SIZE]; /* Length of the stream name, in bytes. 0 if the stream is unnamed. */ le16 stream_name_nbytes; /* Stream name in UTF-16LE. It is @stream_name_nbytes bytes long, - * excluding the null terminator. There is a null terminator - * character if @stream_name_nbytes != 0; i.e., if this stream is named. - * */ + * excluding the null terminator. There is a null terminator character + * if @stream_name_nbytes != 0; i.e., if this stream is named. */ utf16lechar stream_name[]; } _packed_attribute; @@ -314,62 +310,23 @@ put_inode(struct wim_inode *inode); extern void free_inode(struct wim_inode *inode); -/* Iterate through each alias of an inode. */ +/* Iterate through each alias of the specified inode. */ #define inode_for_each_dentry(dentry, inode) \ - list_for_each_entry((dentry), &(inode)->i_dentry, d_alias) + list_for_each_entry((dentry), &(inode)->i_dentry, d_alias) -/* Add a new alias for an inode. Does not increment i_nlink; that must be done - * separately. */ +/* Add a new alias for the specified inode. Does not increment i_nlink; that + * must be done separately if needed. */ #define inode_add_dentry(dentry, inode) \ - list_add_tail(&(dentry)->d_alias, &(inode)->i_dentry) + list_add_tail(&(dentry)->d_alias, &(inode)->i_dentry) -/* Return an alias of an inode. */ +/* Return an alias of the specified inode. */ #define inode_first_dentry(inode) \ - container_of(inode->i_dentry.next, struct wim_dentry, d_alias) + container_of(inode->i_dentry.next, struct wim_dentry, d_alias) -/* Return the full path of an alias of an inode, or NULL if it could not be - * determined. */ +/* Return the full path of an alias of the specified inode, or NULL if a full + * path could not be determined. */ #define inode_first_full_path(inode) \ - dentry_full_path(inode_first_dentry(inode)) - -extern struct wim_ads_entry * -inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name); - -extern struct wim_ads_entry * -inode_add_ads_utf16le(struct wim_inode *inode, - const utf16lechar *stream_name, - size_t stream_name_nbytes); - -extern struct wim_ads_entry * -inode_add_ads(struct wim_inode *dentry, const tchar *stream_name); - -extern struct wim_ads_entry * -inode_add_ads_with_data(struct wim_inode *inode, const tchar *name, - const void *value, size_t size, - struct wim_lookup_table *lookup_table); - -extern bool -inode_has_named_stream(const struct wim_inode *inode); - -extern int -inode_set_unnamed_stream(struct wim_inode *inode, const void *data, size_t len, - struct wim_lookup_table *lookup_table); - -extern void -inode_remove_ads(struct wim_inode *inode, struct wim_ads_entry *entry, - struct wim_lookup_table *lookup_table); - -/* - * Does the specified alternate data stream entry correspond to a named stream? - * - * See inode_needs_dummy_stream() for explanation of why an alternate data - * stream entry might, in fact, not be named... - */ -static inline bool -ads_entry_is_named_stream(const struct wim_ads_entry *entry) -{ - return entry->stream_name_nbytes != 0; -} + dentry_full_path(inode_first_dentry(inode)) /* Is the inode a directory? * This doesn't count directories with reparse data. @@ -384,8 +341,8 @@ inode_is_directory(const struct wim_inode *inode) } /* Is the inode a directory with the encrypted attribute set? - * This currently returns true for encrypted directories even if they have - * reparse data (not sure if such files can even exist). */ + * This returns true for encrypted directories even if they have reparse data + * (I'm not sure if such files can even exist!). */ static inline bool inode_is_encrypted_directory(const struct wim_inode *inode) { @@ -415,92 +372,81 @@ inode_has_children(const struct wim_inode *inode) return inode->i_children != NULL; } +extern struct wim_ads_entry * +inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name); + +extern struct wim_ads_entry * +inode_add_ads_utf16le(struct wim_inode *inode, const utf16lechar *stream_name, + size_t stream_name_nbytes); + +extern struct wim_ads_entry * +inode_add_ads(struct wim_inode *dentry, const tchar *stream_name); + +extern struct wim_ads_entry * +inode_add_ads_with_data(struct wim_inode *inode, const tchar *name, + const void *value, size_t size, + struct wim_lookup_table *lookup_table); + +extern void +inode_remove_ads(struct wim_inode *inode, struct wim_ads_entry *entry, + struct wim_lookup_table *lookup_table); + +extern bool +inode_has_named_stream(const struct wim_inode *inode); + extern int -inode_resolve_streams(struct wim_inode *inode, struct wim_lookup_table *table, - bool force); +inode_set_unnamed_stream(struct wim_inode *inode, const void *data, size_t len, + struct wim_lookup_table *lookup_table); extern int -stream_not_found_error(const struct wim_inode *inode, const u8 *hash); +inode_resolve_streams(struct wim_inode *inode, struct wim_lookup_table *table, + bool force); extern void inode_unresolve_streams(struct wim_inode *inode); +extern int +stream_not_found_error(const struct wim_inode *inode, const u8 *hash); + static inline struct wim_lookup_table_entry * inode_stream_lte_resolved(const struct wim_inode *inode, unsigned stream_idx) { - wimlib_assert(inode->i_resolved); - wimlib_assert(stream_idx <= inode->i_num_ads); if (stream_idx == 0) return inode->i_lte; - else - return inode->i_ads_entries[stream_idx - 1].lte; -} - -static inline struct wim_lookup_table_entry * -inode_stream_lte_unresolved(const struct wim_inode *inode, unsigned stream_idx, - const struct wim_lookup_table *table) -{ - wimlib_assert(!inode->i_resolved); - wimlib_assert(stream_idx <= inode->i_num_ads); - if (table == NULL) - return NULL; - if (stream_idx == 0) - return lookup_stream(table, inode->i_hash); - else - return lookup_stream(table, inode->i_ads_entries[ stream_idx - 1].hash); + return inode->i_ads_entries[stream_idx - 1].lte; } extern struct wim_lookup_table_entry * inode_stream_lte(const struct wim_inode *inode, unsigned stream_idx, const struct wim_lookup_table *table); -static inline const u8 * -inode_stream_hash_unresolved(const struct wim_inode *inode, unsigned stream_idx) +extern struct wim_lookup_table_entry * +inode_unnamed_stream_resolved(const struct wim_inode *inode, + unsigned *stream_idx_ret); + +static inline struct wim_lookup_table_entry * +inode_unnamed_lte_resolved(const struct wim_inode *inode) { - wimlib_assert(!inode->i_resolved); - wimlib_assert(stream_idx <= inode->i_num_ads); - if (stream_idx == 0) - return inode->i_hash; - else - return inode->i_ads_entries[stream_idx - 1].hash; + unsigned stream_idx; + return inode_unnamed_stream_resolved(inode, &stream_idx); } +extern struct wim_lookup_table_entry * +inode_unnamed_lte(const struct wim_inode *inode, + const struct wim_lookup_table *table); -static inline const u8 * -inode_stream_hash_resolved(const struct wim_inode *inode, unsigned stream_idx) -{ - struct wim_lookup_table_entry *lte; - lte = inode_stream_lte_resolved(inode, stream_idx); - if (lte) - return lte->hash; - else - return zero_hash; -} +extern const u8 * +inode_stream_hash(const struct wim_inode *inode, unsigned stream_idx); -/* - * Returns the hash for stream @stream_idx of the inode, where stream_idx = 0 - * means the default un-named file stream, and stream_idx >= 1 corresponds to an - * alternate data stream. - * - * This works for both resolved and un-resolved dentries. - */ -static inline const u8 * -inode_stream_hash(const struct wim_inode *inode, unsigned stream_idx) -{ - if (inode->i_resolved) - return inode_stream_hash_resolved(inode, stream_idx); - else - return inode_stream_hash_unresolved(inode, stream_idx); -} +extern const u8 * +inode_unnamed_stream_hash(const struct wim_inode *inode); -static inline u16 +static inline unsigned inode_stream_name_nbytes(const struct wim_inode *inode, unsigned stream_idx) { - wimlib_assert(stream_idx <= inode->i_num_ads); if (stream_idx == 0) return 0; - else - return inode->i_ads_entries[stream_idx - 1].stream_name_nbytes; + return inode->i_ads_entries[stream_idx - 1].stream_name_nbytes; } static inline u32 @@ -508,25 +454,15 @@ inode_stream_idx_to_id(const struct wim_inode *inode, unsigned stream_idx) { if (stream_idx == 0) return 0; - else - return inode->i_ads_entries[stream_idx - 1].stream_id; + return inode->i_ads_entries[stream_idx - 1].stream_id; } -extern struct wim_lookup_table_entry * -inode_unnamed_stream_resolved(const struct wim_inode *inode, u16 *stream_idx_ret); - -extern struct wim_lookup_table_entry * -inode_unnamed_lte_resolved(const struct wim_inode *inode); - -extern struct wim_lookup_table_entry * -inode_unnamed_lte_unresolved(const struct wim_inode *inode, - const struct wim_lookup_table *table); - -extern struct wim_lookup_table_entry * -inode_unnamed_lte(const struct wim_inode *inode, const struct wim_lookup_table *table); +extern void +inode_ref_streams(struct wim_inode *inode); -extern const u8 * -inode_unnamed_stream_hash(const struct wim_inode *inode); +extern void +inode_unref_streams(struct wim_inode *inode, + struct wim_lookup_table *lookup_table); extern int read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode, @@ -535,13 +471,6 @@ read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode, extern void check_inode(struct wim_inode *inode, const struct wim_security_data *sd); -extern void -inode_ref_streams(struct wim_inode *inode); - -extern void -inode_unref_streams(struct wim_inode *inode, - struct wim_lookup_table *lookup_table); - /* inode_fixup.c */ extern int dentry_tree_fix_inodes(struct wim_dentry *root, struct list_head *inode_list); diff --git a/src/compress.c b/src/compress.c index 414fad0f..19765792 100644 --- a/src/compress.c +++ b/src/compress.c @@ -27,7 +27,6 @@ #endif #include "wimlib.h" -#include "wimlib/assert.h" #include "wimlib/error.h" #include "wimlib/compressor_ops.h" #include "wimlib/util.h" diff --git a/src/decompress_common.c b/src/decompress_common.c index 4ab9ccbe..b08a3b4b 100644 --- a/src/decompress_common.c +++ b/src/decompress_common.c @@ -14,6 +14,7 @@ # include "config.h" #endif +#include "wimlib/assert.h" #include "wimlib/decompress_common.h" #include diff --git a/src/extract.c b/src/extract.c index 39899c40..ac50fa8f 100644 --- a/src/extract.c +++ b/src/extract.c @@ -40,6 +40,7 @@ #endif #include "wimlib/apply.h" +#include "wimlib/assert.h" #include "wimlib/dentry.h" #include "wimlib/encoding.h" #include "wimlib/endianness.h" @@ -1008,7 +1009,7 @@ dentry_list_resolve_streams(struct list_head *dentry_list, } static int -ref_stream(struct wim_lookup_table_entry *lte, u32 stream_idx, +ref_stream(struct wim_lookup_table_entry *lte, unsigned stream_idx, struct wim_dentry *dentry, struct apply_ctx *ctx) { struct wim_inode *inode = dentry->d_inode; @@ -1083,7 +1084,7 @@ ref_unnamed_stream(struct wim_dentry *dentry, struct apply_ctx *ctx) { struct wim_inode *inode = dentry->d_inode; int ret; - u16 stream_idx; + unsigned stream_idx; struct wim_lookup_table_entry *stream; if (unlikely(inode_is_encrypted_directory(inode))) @@ -1120,8 +1121,8 @@ dentry_ref_streams(struct wim_dentry *dentry, struct apply_ctx *ctx) * extraction mode and volume, and to avoid complications, if not doing * a linked extraction. */ if (ctx->supported_features.named_data_streams) { - for (u16 i = 0; i < inode->i_num_ads; i++) { - if (!ads_entry_is_named_stream(&inode->i_ads_entries[i])) + for (unsigned i = 0; i < inode->i_num_ads; i++) { + if (!inode->i_ads_entries[i].stream_name_nbytes) continue; ret = ref_stream(inode->i_ads_entries[i].lte, i + 1, dentry, ctx); diff --git a/src/inode.c b/src/inode.c index 585ed21a..9e4177c9 100644 --- a/src/inode.c +++ b/src/inode.c @@ -28,21 +28,18 @@ # include "config.h" #endif +#include + #include "wimlib/assert.h" -#include "wimlib/dentry.h" /* Only for dentry_full_path(). Otherwise the code - in this file doesn't care about file names/paths. - */ +#include "wimlib/dentry.h" #include "wimlib/encoding.h" #include "wimlib/endianness.h" #include "wimlib/error.h" #include "wimlib/inode.h" -#include "wimlib/inode_table.h" #include "wimlib/lookup_table.h" #include "wimlib/security.h" #include "wimlib/timestamp.h" -#include - /* Allocate a new inode. Set the timestamps to the current time. */ struct wim_inode * new_inode(void) @@ -74,7 +71,7 @@ new_timeless_inode(void) return inode; } -/* Decrement link count on an inode. */ +/* Decrement an inode's link count. */ void put_inode(struct wim_inode *inode) { @@ -105,7 +102,7 @@ free_inode(struct wim_inode *inode) return; if (unlikely(inode->i_ads_entries)) { - for (u16 i = 0; i < inode->i_num_ads; i++) + for (unsigned i = 0; i < inode->i_num_ads; i++) destroy_ads_entry(&inode->i_ads_entries[i]); FREE(inode->i_ads_entries); } @@ -118,20 +115,6 @@ free_inode(struct wim_inode *inode) FREE(inode); } -/* Return %true iff the alternate data stream entry @entry has the UTF-16LE - * stream name @name that has length @name_nbytes bytes. */ -static inline bool -ads_entry_has_name(const struct wim_ads_entry *entry, - const utf16lechar *name, size_t name_nbytes, - bool ignore_case) -{ - return 0 == cmp_utf16le_strings(name, - name_nbytes / 2, - entry->stream_name, - entry->stream_name_nbytes / 2, - ignore_case); -} - /* * Returns the alternate data stream entry belonging to @inode that has the * stream name @stream_name, or NULL if the inode has no alternate data stream @@ -148,7 +131,7 @@ inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name) int ret; const utf16lechar *stream_name_utf16le; size_t stream_name_utf16le_nbytes; - u16 i; + unsigned i; struct wim_ads_entry *result; if (inode->i_num_ads == 0) { @@ -169,10 +152,13 @@ inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name) i = 0; result = NULL; do { - if (ads_entry_has_name(&inode->i_ads_entries[i], - stream_name_utf16le, - stream_name_utf16le_nbytes, - default_ignore_case)) + if (!cmp_utf16le_strings(inode->i_ads_entries[i].stream_name, + inode->i_ads_entries[i].stream_name_nbytes / + sizeof(utf16lechar), + stream_name_utf16le, + stream_name_utf16le_nbytes / + sizeof(utf16lechar), + default_ignore_case)) { result = &inode->i_ads_entries[i]; break; @@ -190,11 +176,11 @@ static struct wim_ads_entry * do_inode_add_ads(struct wim_inode *inode, utf16lechar *stream_name, size_t stream_name_nbytes) { - u16 num_ads; + unsigned num_ads; struct wim_ads_entry *ads_entries; struct wim_ads_entry *new_entry; - if (inode->i_num_ads >= 0xfffe) { + if (unlikely(inode->i_num_ads >= 0xfffe)) { ERROR("File \"%"TS"\" has too many alternate data streams!", inode_first_full_path(inode)); errno = EFBIG; @@ -288,44 +274,17 @@ inode_add_ads_with_data(struct wim_inode *inode, const tchar *name, wimlib_assert(inode->i_resolved); new_entry = inode_add_ads(inode, name); - if (!new_entry) + if (unlikely(!new_entry)) return NULL; new_entry->lte = new_stream_from_data_buffer(value, size, lookup_table); - if (!new_entry->lte) { + if (unlikely(!new_entry->lte)) { inode_remove_ads(inode, new_entry, NULL); return NULL; } return new_entry; } -/* - * Does the inode have any named data streams? - */ -bool -inode_has_named_stream(const struct wim_inode *inode) -{ - for (u16 i = 0; i < inode->i_num_ads; i++) - if (ads_entry_is_named_stream(&inode->i_ads_entries[i])) - return true; - return false; -} - -/* Set the unnamed stream of a WIM inode, given a data buffer containing the - * stream contents. The inode must be resolved and cannot have an unnamed - * stream specified already. */ -int -inode_set_unnamed_stream(struct wim_inode *inode, const void *data, size_t len, - struct wim_lookup_table *lookup_table) -{ - wimlib_assert(inode->i_resolved); - wimlib_assert(!inode->i_lte); - inode->i_lte = new_stream_from_data_buffer(data, len, lookup_table); - if (!inode->i_lte) - return WIMLIB_ERR_NOMEM; - return 0; -} - /* Remove an alternate data stream from a WIM inode. */ void inode_remove_ads(struct wim_inode *inode, struct wim_ads_entry *entry, @@ -349,6 +308,32 @@ inode_remove_ads(struct wim_inode *inode, struct wim_ads_entry *entry, inode->i_num_ads--; } +/* Return true iff the specified inode has at least one named data stream. */ +bool +inode_has_named_stream(const struct wim_inode *inode) +{ + for (unsigned i = 0; i < inode->i_num_ads; i++) + if (inode->i_ads_entries[i].stream_name_nbytes) + return true; + return false; +} + +/* Set the unnamed stream of a WIM inode, given a data buffer containing the + * stream contents. The inode must be resolved and cannot already have an + * unnamed stream. */ +int +inode_set_unnamed_stream(struct wim_inode *inode, const void *data, size_t len, + struct wim_lookup_table *lookup_table) +{ + wimlib_assert(inode->i_resolved); + wimlib_assert(!inode->i_lte); + + inode->i_lte = new_stream_from_data_buffer(data, len, lookup_table); + if (!inode->i_lte) + return WIMLIB_ERR_NOMEM; + return 0; +} + /* * Resolve an inode's single-instance streams. * @@ -403,7 +388,7 @@ inode_resolve_streams(struct wim_inode *inode, struct wim_lookup_table *table, } /* Resolve the alternate data streams */ - for (u16 i = 0; i < inode->i_num_ads; i++) { + for (unsigned i = 0; i < inode->i_num_ads; i++) { struct wim_ads_entry *cur_entry; ads_lte = NULL; @@ -426,7 +411,7 @@ inode_resolve_streams(struct wim_inode *inode, struct wim_lookup_table *table, ads_ltes[i] = ads_lte; } inode->i_lte = lte; - for (u16 i = 0; i < inode->i_num_ads; i++) + for (unsigned i = 0; i < inode->i_num_ads; i++) inode->i_ads_entries[i].lte = ads_ltes[i]; inode->i_resolved = 1; return 0; @@ -451,7 +436,7 @@ inode_unresolve_streams(struct wim_inode *inode) else zero_out_hash(inode->i_hash); - for (u16 i = 0; i < inode->i_num_ads; i++) { + for (unsigned i = 0; i < inode->i_num_ads; i++) { if (inode->i_ads_entries[i].lte) copy_hash(inode->i_ads_entries[i].hash, inode->i_ads_entries[i].lte->hash); @@ -478,11 +463,11 @@ stream_not_found_error(const struct wim_inode *inode, const u8 *hash) } /* - * Return the lookup table entry for stream @stream_idx of the inode, where - * stream_idx = 0 means the default un-named file stream, and stream_idx >= 1 - * corresponds to an alternate data stream. + * Return the lookup table entry for the specified stream of the inode, or NULL + * if the specified stream is empty or not available. * - * This works for both resolved and un-resolved inodes. + * stream_idx = 0: default data stream + * stream_idx > 0: alternate data stream */ struct wim_lookup_table_entry * inode_stream_lte(const struct wim_inode *inode, unsigned stream_idx, @@ -490,56 +475,32 @@ inode_stream_lte(const struct wim_inode *inode, unsigned stream_idx, { if (inode->i_resolved) return inode_stream_lte_resolved(inode, stream_idx); - else - return inode_stream_lte_unresolved(inode, stream_idx, table); + if (stream_idx == 0) + return lookup_stream(table, inode->i_hash); + return lookup_stream(table, inode->i_ads_entries[stream_idx - 1].hash); } /* * Return the lookup table entry for the unnamed data stream of a *resolved* - * inode, or NULL if there is none. Also return the 0-based index of the - * corresponding stream in *stream_idx_ret. + * inode, or NULL if the inode's unnamed data stream is empty. Also return the + * 0-based index of the unnamed data stream in *stream_idx_ret. */ struct wim_lookup_table_entry * -inode_unnamed_stream_resolved(const struct wim_inode *inode, u16 *stream_idx_ret) +inode_unnamed_stream_resolved(const struct wim_inode *inode, + unsigned *stream_idx_ret) { wimlib_assert(inode->i_resolved); - for (unsigned i = 0; i <= inode->i_num_ads; i++) { - if (inode_stream_name_nbytes(inode, i) == 0 && - !is_zero_hash(inode_stream_hash_resolved(inode, i))) - { - *stream_idx_ret = i; - return inode_stream_lte_resolved(inode, i); - } - } - *stream_idx_ret = 0; - return NULL; -} -/* - * Return the lookup table entry for the unnamed data stream of a *resolved* - * inode, or NULL if there is none. - */ -struct wim_lookup_table_entry * -inode_unnamed_lte_resolved(const struct wim_inode *inode) -{ - u16 stream_idx; - return inode_unnamed_stream_resolved(inode, &stream_idx); -} + *stream_idx_ret = 0; + if (likely(inode->i_lte)) + return inode->i_lte; -/* - * Return the lookup table entry for the unnamed data stream of an *unresolved* - * inode, or NULL if there is none. - */ -struct wim_lookup_table_entry * -inode_unnamed_lte_unresolved(const struct wim_inode *inode, - const struct wim_lookup_table *table) -{ - wimlib_assert(!inode->i_resolved); - for (unsigned i = 0; i <= inode->i_num_ads; i++) { - if (inode_stream_name_nbytes(inode, i) == 0 && - !is_zero_hash(inode_stream_hash_unresolved(inode, i))) + for (unsigned i = 0; i < inode->i_num_ads; i++) { + if (inode->i_ads_entries[i].stream_name_nbytes == 0 && + inode->i_ads_entries[i].lte) { - return inode_stream_lte_unresolved(inode, i, table); + *stream_idx_ret = i + 1; + return inode->i_ads_entries[i].lte; } } return NULL; @@ -547,37 +508,54 @@ inode_unnamed_lte_unresolved(const struct wim_inode *inode, /* * Return the lookup table entry for the unnamed data stream of an inode, or - * NULL if there is none. - * - * You'd think this would be easier than it actually is, since the unnamed data - * stream should be the one referenced from the inode itself. Alas, if there - * are named data streams, Microsoft's "imagex.exe" program will put the unnamed - * data stream in one of the alternate data streams instead of inside the WIM - * dentry itself. So we need to check the alternate data streams too. + * NULL if the inode's unnamed data stream is empty or not available. * - * Also, note that a dentry may appear to have more than one unnamed stream, but - * if the SHA-1 message digest is all 0's then the corresponding stream does not - * really "count" (this is the case for the inode's own file stream when the - * file stream that should be there is actually in one of the alternate stream - * entries.). This is despite the fact that we may need to extract such a - * missing entry as an empty file or empty named data stream. + * Note: this is complicated by the fact that WIMGAPI may put the unnamed data + * stream in an alternate data stream entry rather than in the dentry itself. */ struct wim_lookup_table_entry * inode_unnamed_lte(const struct wim_inode *inode, const struct wim_lookup_table *table) { + struct wim_lookup_table_entry *lte; + if (inode->i_resolved) return inode_unnamed_lte_resolved(inode); - else - return inode_unnamed_lte_unresolved(inode, table); + + lte = lookup_stream(table, inode->i_hash); + if (likely(lte)) + return lte; + + for (unsigned i = 0; i < inode->i_num_ads; i++) { + if (inode->i_ads_entries[i].stream_name_nbytes) + continue; + lte = lookup_stream(table, inode->i_ads_entries[i].hash); + if (lte) + return lte; + } + return NULL; } -/* - * Return the SHA-1 message digest of the unnamed data stream of a WIM inode. - * - * If inode does not have an unnamed data stream, this returns a void SHA-1 - * message digest containing all zero bytes. - */ +/* Return the SHA-1 message digest of the specified stream of the inode, or a + * void SHA-1 of all zeroes if the specified stream is empty. */ +const u8 * +inode_stream_hash(const struct wim_inode *inode, unsigned stream_idx) +{ + if (inode->i_resolved) { + struct wim_lookup_table_entry *lte; + + lte = inode_stream_lte_resolved(inode, stream_idx); + if (lte) + return lte->hash; + return zero_hash; + } + if (stream_idx == 0) + return inode->i_hash; + return inode->i_ads_entries[stream_idx - 1].hash; +} + +/* Return the SHA-1 message digest of the unnamed data stream of the inode, or a + * void SHA-1 of all zeroes if the inode's unnamed data stream is empty. */ const u8 * inode_unnamed_stream_hash(const struct wim_inode *inode) { @@ -593,29 +571,35 @@ inode_unnamed_stream_hash(const struct wim_inode *inode) return zero_hash; } -/* - * Translate a single-instance stream entry into the pointer contained in the - * inode (or ads entry of an inode) that references it. +/* Acquire another reference to each single-instance stream referenced by this + * inode. This is necessary when creating a hard link to this inode. * - * This is only possible for "unhashed" streams, which are guaranteed to have - * only one reference, and that reference is guaranteed to be in a resolved - * inode. (It can't be in an unresolved inode, since that would imply the hash - * is known!) - */ -struct wim_lookup_table_entry ** -retrieve_lte_pointer(struct wim_lookup_table_entry *lte) + * The inode must be resolved. */ +void +inode_ref_streams(struct wim_inode *inode) { - wimlib_assert(lte->unhashed); - struct wim_inode *inode = lte->back_inode; - u32 stream_id = lte->back_stream_id; - if (stream_id == 0) - return &inode->i_lte; - else - for (u16 i = 0; i < inode->i_num_ads; i++) - if (inode->i_ads_entries[i].stream_id == stream_id) - return &inode->i_ads_entries[i].lte; - wimlib_assert(0); - return NULL; + wimlib_assert(inode->i_resolved); + + if (inode->i_lte) + inode->i_lte->refcnt++; + for (unsigned i = 0; i < inode->i_num_ads; i++) + if (inode->i_ads_entries[i].lte) + inode->i_ads_entries[i].lte->refcnt++; +} + +/* Drop a reference to each single-instance stream referenced by this inode. + * This is necessary when deleting a hard link to this inode. */ +void +inode_unref_streams(struct wim_inode *inode, + struct wim_lookup_table *lookup_table) +{ + for (unsigned i = 0; i <= inode->i_num_ads; i++) { + struct wim_lookup_table_entry *lte; + + lte = inode_stream_lte(inode, i, lookup_table); + if (lte) + lte_decrement_refcnt(lte, lookup_table); + } } /* @@ -646,7 +630,7 @@ read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode, size_t *nbytes_remaining_p) { size_t nbytes_remaining = *nbytes_remaining_p; - u16 num_ads; + unsigned num_ads; struct wim_ads_entry *ads_entries; int ret; @@ -660,7 +644,7 @@ read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode, goto out_of_memory; /* Read the entries into our newly allocated buffer. */ - for (u16 i = 0; i < num_ads; i++) { + for (unsigned i = 0; i < num_ads; i++) { u64 length; struct wim_ads_entry *cur_entry; const struct wim_ads_entry_on_disk *disk_entry = @@ -722,7 +706,7 @@ read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode, /* It's expected that the size of every ADS entry is a multiple * of 8. However, to be safe, I'm allowing the possibility of * an ADS entry at the very end of the metadata resource ending - * un-aligned. So although we still need to increment the input + * unaligned. So although we still need to increment the input * pointer by @length to reach the next ADS entry, it's possible * that less than @length is actually remaining in the metadata * resource. We should set the remaining bytes to 0 if this @@ -747,7 +731,7 @@ out_invalid: ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE; out_free_ads_entries: if (ads_entries) { - for (u16 i = 0; i < num_ads; i++) + for (unsigned i = 0; i < num_ads; i++) destroy_ads_entry(&ads_entries[i]); FREE(ads_entries); } @@ -780,203 +764,33 @@ check_inode(struct wim_inode *inode, const struct wim_security_data *sd) num_unnamed_streams++; } if (num_unnamed_streams > 1) { - WARNING("\"%"TS"\" has multiple (%u) un-named streams", + WARNING("\"%"TS"\" has multiple (%u) unnamed streams", inode_first_full_path(inode), num_unnamed_streams); /* We currently don't treat this as an error and will just end * up using the first unnamed data stream in the inode. */ } } -/* Acquire another reference to each single-instance stream referenced by this - * inode. This is necessary when creating a hard link to this inode. - * - * The inode must be resolved. */ -void -inode_ref_streams(struct wim_inode *inode) -{ - for (unsigned i = 0; i <= inode->i_num_ads; i++) { - struct wim_lookup_table_entry *lte; - - lte = inode_stream_lte_resolved(inode, i); - if (lte) - lte->refcnt++; - } -} - -/* Drop a reference to each single-instance stream referenced by this inode. - * This is necessary when deleting a hard link to this inode. */ -void -inode_unref_streams(struct wim_inode *inode, - struct wim_lookup_table *lookup_table) -{ - for (unsigned i = 0; i <= inode->i_num_ads; i++) { - struct wim_lookup_table_entry *lte; - - lte = inode_stream_lte(inode, i, lookup_table); - if (lte) - lte_decrement_refcnt(lte, lookup_table); - } -} - -/* Initialize a hash table for hard link detection. */ -int -init_inode_table(struct wim_inode_table *table, size_t capacity) -{ - table->array = CALLOC(capacity, sizeof(table->array[0])); - if (!table->array) - return WIMLIB_ERR_NOMEM; - table->num_entries = 0; - table->capacity = capacity; - INIT_LIST_HEAD(&table->extra_inodes); - return 0; -} - -/* Free the memory allocated by init_inode_table(). */ -void -destroy_inode_table(struct wim_inode_table *table) -{ - FREE(table->array); -} - -static struct wim_inode * -inode_table_get_inode(struct wim_inode_table *table, u64 ino, u64 devno) -{ - u64 hash = hash_u64(hash_u64(ino) + hash_u64(devno)); - size_t pos = hash % table->capacity; - struct wim_inode *inode; - struct hlist_node *cur; - - /* Search for an existing inode having the same inode number and device - * number. */ - hlist_for_each_entry(inode, cur, &table->array[pos], i_hlist) { - if (inode->i_ino == ino && inode->i_devno == devno) { - /* Found; use the existing inode. */ - inode->i_nlink++; - return inode; - } - } - - /* Create a new inode and insert it into the table. */ - inode = new_timeless_inode(); - if (inode) { - inode->i_ino = ino; - inode->i_devno = devno; - hlist_add_head(&inode->i_hlist, &table->array[pos]); - table->num_entries++; - } - return inode; -} - /* - * Allocate a new dentry, with hard link detection. - * - * @table - * The inode table being used for the current directory scan operation. It - * will contain the mapping from (ino, devno) pairs to inodes. - * - * @name - * The name to give the new dentry. - * - * @ino - * The inode number of the file, read from the filesystem. - * - * @devno - * The device number of the file, read from the filesystem. Proper setting - * of this parameter prevents cross-device hardlinks from being created. - * If this is not a problem (perhaps because the current directory scan - * operation is guaranteed to never traverse a filesystem boundary), then - * this parameter can just be a fixed value such as 0. - * - * @noshare - * If %true, the new dentry will not be hard linked to any existing inode, - * regardless of the values of @ino and @devno. If %false, normal hard - * link detection will be done. - * - * @dentry_ret - * On success, a pointer to the new dentry will be returned in this - * location. If i_nlink of the dentry's inode is greater than 1, then this - * function created a hard link to an existing inode rather than creating a - * new inode. + * Translate a single-instance stream entry into the pointer contained in the + * inode (or ads entry of an inode) that references it. * - * On success, returns 0. On failure, returns WIMLIB_ERR_NOMEM or an error code - * resulting from a failed string conversion. - */ -int -inode_table_new_dentry(struct wim_inode_table *table, const tchar *name, - u64 ino, u64 devno, bool noshare, - struct wim_dentry **dentry_ret) -{ - struct wim_dentry *dentry; - struct wim_inode *inode; - int ret; - - if (noshare) { - /* File that cannot be hardlinked--- Return a new inode with its - * inode and device numbers left at 0. */ - ret = new_dentry_with_timeless_inode(name, &dentry); - if (ret) - return ret; - list_add_tail(&dentry->d_inode->i_list, &table->extra_inodes); - } else { - /* File that can be hardlinked--- search the table for an - * existing inode matching the inode number and device; - * otherwise create a new inode. */ - ret = new_dentry(name, &dentry); - if (ret) - return ret; - inode = inode_table_get_inode(table, ino, devno); - if (!inode) { - free_dentry(dentry); - return WIMLIB_ERR_NOMEM; - } - /* If using an existing inode, we need to gain a reference to - * each of its streams. */ - if (inode->i_nlink > 1) - inode_ref_streams(inode); - dentry->d_inode = inode; - inode_add_dentry(dentry, inode); - } - *dentry_ret = dentry; - return 0; -} - - - -/* - * Following the allocation of dentries with hard link detection using - * inode_table_new_dentry(), this function will assign consecutive inode numbers - * to the new set of inodes. It will also append the list of new inodes to the - * list @head, which must contain any inodes already existing in the WIM image. + * This is only possible for "unhashed" streams, which are guaranteed to have + * only one reference, and that reference is guaranteed to be in a resolved + * inode. (It can't be in an unresolved inode, since that would imply the hash + * is known!) */ -void -inode_table_prepare_inode_list(struct wim_inode_table *table, - struct list_head *head) +struct wim_lookup_table_entry ** +retrieve_lte_pointer(struct wim_lookup_table_entry *lte) { - struct wim_inode *inode, *tmp_inode; - struct hlist_node *cur, *tmp; - u64 cur_ino = 1; - - /* Re-assign inode numbers in the existing list to avoid duplicates. */ - list_for_each_entry(inode, head, i_list) - inode->i_ino = cur_ino++; - - /* Assign inode numbers to the new inodes and move them to the image's - * inode list. */ - for (size_t i = 0; i < table->capacity; i++) { - hlist_for_each_entry_safe(inode, cur, tmp, &table->array[i], i_hlist) - { - inode->i_ino = cur_ino++; - inode->i_devno = 0; - list_add_tail(&inode->i_list, head); - } - INIT_HLIST_HEAD(&table->array[i]); - } - list_for_each_entry_safe(inode, tmp_inode, &table->extra_inodes, i_list) - { - inode->i_ino = cur_ino++; - inode->i_devno = 0; - list_add_tail(&inode->i_list, head); - } - INIT_LIST_HEAD(&table->extra_inodes); - table->num_entries = 0; + wimlib_assert(lte->unhashed); + struct wim_inode *inode = lte->back_inode; + u32 stream_id = lte->back_stream_id; + if (stream_id == 0) + return &inode->i_lte; + for (unsigned i = 0; i < inode->i_num_ads; i++) + if (inode->i_ads_entries[i].stream_id == stream_id) + return &inode->i_ads_entries[i].lte; + wimlib_assert(0); + return NULL; } diff --git a/src/inode_table.c b/src/inode_table.c new file mode 100644 index 00000000..6e1c143b --- /dev/null +++ b/src/inode_table.c @@ -0,0 +1,192 @@ +/* + * inode_table.c - hard link detection + */ + +/* + * Copyright (C) 2012, 2013, 2014 Eric Biggers + * + * This file is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. + * + * This file is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this file; if not, see http://www.gnu.org/licenses/. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/dentry.h" +#include "wimlib/error.h" +#include "wimlib/inode.h" +#include "wimlib/inode_table.h" +#include "wimlib/list.h" +#include "wimlib/util.h" + +/* Initialize a hash table for hard link detection. */ +int +init_inode_table(struct wim_inode_table *table, size_t capacity) +{ + table->array = CALLOC(capacity, sizeof(table->array[0])); + if (!table->array) + return WIMLIB_ERR_NOMEM; + table->num_entries = 0; + table->capacity = capacity; + INIT_LIST_HEAD(&table->extra_inodes); + return 0; +} + +/* Free the memory allocated by init_inode_table(). */ +void +destroy_inode_table(struct wim_inode_table *table) +{ + FREE(table->array); +} + +static struct wim_inode * +inode_table_get_inode(struct wim_inode_table *table, u64 ino, u64 devno) +{ + size_t pos; + struct wim_inode *inode; + struct hlist_node *cur; + + /* Search for an existing inode having the same inode number and device + * number. */ + pos = hash_u64(hash_u64(ino) + hash_u64(devno)) % table->capacity; + hlist_for_each_entry(inode, cur, &table->array[pos], i_hlist) { + if (inode->i_ino == ino && inode->i_devno == devno) { + /* Found; use the existing inode. */ + inode->i_nlink++; + return inode; + } + } + + /* Create a new inode and insert it into the table. */ + inode = new_timeless_inode(); + if (inode) { + inode->i_ino = ino; + inode->i_devno = devno; + hlist_add_head(&inode->i_hlist, &table->array[pos]); + table->num_entries++; + } + return inode; +} + +/* + * Allocate a new dentry, with hard link detection. + * + * @table + * The inode table being used for the current directory scan operation. It + * will contain the mapping from (ino, devno) pairs to inodes. + * + * @name + * The name to give the new dentry. + * + * @ino + * The inode number of the file, read from the filesystem. + * + * @devno + * The device number of the file, read from the filesystem. Proper setting + * of this parameter prevents cross-device hardlinks from being created. + * If this is not a problem (perhaps because the current directory scan + * operation is guaranteed to never traverse a filesystem boundary), then + * this parameter can just be a fixed value such as 0. + * + * @noshare + * If %true, the new dentry will not be hard linked to any existing inode, + * regardless of the values of @ino and @devno. If %false, normal hard + * link detection will be done. + * + * @dentry_ret + * On success, a pointer to the new dentry will be returned in this + * location. If i_nlink of the dentry's inode is greater than 1, then this + * function created a hard link to an existing inode rather than creating a + * new inode. + * + * On success, returns 0. On failure, returns WIMLIB_ERR_NOMEM or an error code + * resulting from a failed string conversion. + */ +int +inode_table_new_dentry(struct wim_inode_table *table, const tchar *name, + u64 ino, u64 devno, bool noshare, + struct wim_dentry **dentry_ret) +{ + struct wim_dentry *dentry; + struct wim_inode *inode; + int ret; + + if (noshare) { + /* File that cannot be hardlinked--- Return a new inode with its + * inode and device numbers left at 0. */ + ret = new_dentry_with_timeless_inode(name, &dentry); + if (ret) + return ret; + list_add_tail(&dentry->d_inode->i_list, &table->extra_inodes); + } else { + /* File that can be hardlinked--- search the table for an + * existing inode matching the inode number and device; + * otherwise create a new inode. */ + ret = new_dentry(name, &dentry); + if (ret) + return ret; + inode = inode_table_get_inode(table, ino, devno); + if (!inode) { + free_dentry(dentry); + return WIMLIB_ERR_NOMEM; + } + /* If using an existing inode, we need to gain a reference to + * each of its streams. */ + if (inode->i_nlink > 1) + inode_ref_streams(inode); + dentry->d_inode = inode; + inode_add_dentry(dentry, inode); + } + *dentry_ret = dentry; + return 0; +} + +/* + * Following the allocation of dentries with hard link detection using + * inode_table_new_dentry(), this function will assign consecutive inode numbers + * to the new set of inodes. It will also append the list of new inodes to the + * list @head, which must contain any inodes already existing in the WIM image. + */ +void +inode_table_prepare_inode_list(struct wim_inode_table *table, + struct list_head *head) +{ + struct wim_inode *inode, *tmp_inode; + struct hlist_node *cur, *tmp; + u64 cur_ino = 1; + + /* Re-assign inode numbers in the existing list to avoid duplicates. */ + list_for_each_entry(inode, head, i_list) + inode->i_ino = cur_ino++; + + /* Assign inode numbers to the new inodes and move them to the image's + * inode list. */ + for (size_t i = 0; i < table->capacity; i++) { + hlist_for_each_entry_safe(inode, cur, tmp, &table->array[i], i_hlist) + { + inode->i_ino = cur_ino++; + inode->i_devno = 0; + list_add_tail(&inode->i_list, head); + } + INIT_HLIST_HEAD(&table->array[i]); + } + list_for_each_entry_safe(inode, tmp_inode, &table->extra_inodes, i_list) + { + inode->i_ino = cur_ino++; + inode->i_devno = 0; + list_add_tail(&inode->i_list, head); + } + INIT_LIST_HEAD(&table->extra_inodes); + table->num_entries = 0; +} diff --git a/src/iterate_dir.c b/src/iterate_dir.c index fb2c1b36..8e7f6cc3 100644 --- a/src/iterate_dir.c +++ b/src/iterate_dir.c @@ -99,7 +99,7 @@ init_wimlib_dentry(struct wimlib_dir_entry *wdentry, struct wim_dentry *dentry, } for (unsigned i = 0; i < inode->i_num_ads; i++) { - if (!ads_entry_is_named_stream(&inode->i_ads_entries[i])) + if (!inode->i_ads_entries[i].stream_name_nbytes) continue; lte = inode_stream_lte(inode, i + 1, wim->lookup_table); wdentry->num_named_streams++; diff --git a/src/metadata_resource.c b/src/metadata_resource.c index 54730598..54ea9153 100644 --- a/src/metadata_resource.c +++ b/src/metadata_resource.c @@ -23,6 +23,7 @@ # include "config.h" #endif +#include "wimlib/assert.h" #include "wimlib/dentry.h" #include "wimlib/error.h" #include "wimlib/lookup_table.h" diff --git a/src/mount_image.c b/src/mount_image.c index 94feb4ee..0bd4a1f1 100644 --- a/src/mount_image.c +++ b/src/mount_image.c @@ -39,6 +39,7 @@ #include "wimlib/dentry.h" #include "wimlib/encoding.h" +#include "wimlib/lookup_table.h" #include "wimlib/metadata.h" #include "wimlib/paths.h" #include "wimlib/progress.h" @@ -371,12 +372,12 @@ wim_pathname_to_stream(const struct wimfs_context *ctx, const char *path, int lookup_flags, struct wim_dentry **dentry_ret, struct wim_lookup_table_entry **lte_ret, - u16 *stream_idx_ret) + unsigned *stream_idx_ret) { WIMStruct *wim = ctx->wim; struct wim_dentry *dentry; struct wim_lookup_table_entry *lte; - u16 stream_idx; + unsigned stream_idx; const char *stream_name = NULL; struct wim_inode *inode; char *p = NULL; @@ -679,7 +680,7 @@ retry: */ static int extract_resource_to_staging_dir(struct wim_inode *inode, - u16 stream_idx, + unsigned stream_idx, struct wim_lookup_table_entry **lte_ptr, off_t size, const struct wimfs_context *ctx) @@ -1584,7 +1585,7 @@ wimfs_open(const char *path, struct fuse_file_info *fi) struct wim_dentry *dentry; struct wim_inode *inode; struct wim_lookup_table_entry *lte; - u16 stream_idx; + unsigned stream_idx; struct wimfs_fd *fd; int ret; @@ -1912,7 +1913,7 @@ wimfs_truncate(const char *path, off_t size) const struct wimfs_context *ctx = wimfs_get_context(); struct wim_dentry *dentry; struct wim_lookup_table_entry *lte; - u16 stream_idx; + unsigned stream_idx; int ret; int fd; @@ -1946,7 +1947,7 @@ wimfs_unlink(const char *path) { const struct wimfs_context *ctx = wimfs_get_context(); struct wim_dentry *dentry; - u16 stream_idx; + unsigned stream_idx; int ret; ret = wim_pathname_to_stream(ctx, path, 0, &dentry, NULL, &stream_idx); diff --git a/src/ntfs-3g_apply.c b/src/ntfs-3g_apply.c index f589fb52..ef4346f6 100644 --- a/src/ntfs-3g_apply.c +++ b/src/ntfs-3g_apply.c @@ -42,6 +42,7 @@ #include "wimlib/dentry.h" #include "wimlib/encoding.h" #include "wimlib/error.h" +#include "wimlib/lookup_table.h" #include "wimlib/metadata.h" #include "wimlib/ntfs_3g.h" #include "wimlib/reparse.h" diff --git a/src/ntfs-3g_capture.c b/src/ntfs-3g_capture.c index 78199efa..cd0758ac 100644 --- a/src/ntfs-3g_capture.c +++ b/src/ntfs-3g_capture.c @@ -40,6 +40,7 @@ #include #include +#include "wimlib/assert.h" #include "wimlib/capture.h" #include "wimlib/dentry.h" #include "wimlib/encoding.h" diff --git a/src/template.c b/src/template.c index 438ff25c..1c0e205f 100644 --- a/src/template.c +++ b/src/template.c @@ -26,6 +26,7 @@ #endif #include "wimlib.h" +#include "wimlib/assert.h" #include "wimlib/dentry.h" #include "wimlib/error.h" #include "wimlib/lookup_table.h" diff --git a/src/textfile.c b/src/textfile.c index 8c6efbe3..01c39592 100644 --- a/src/textfile.c +++ b/src/textfile.c @@ -23,7 +23,6 @@ # include "config.h" #endif -#include "wimlib/assert.h" #include "wimlib/encoding.h" #include "wimlib/error.h" #include "wimlib/file_io.h" diff --git a/src/unix_apply.c b/src/unix_apply.c index d0870299..27f26576 100644 --- a/src/unix_apply.c +++ b/src/unix_apply.c @@ -28,6 +28,7 @@ #include "wimlib/dentry.h" #include "wimlib/error.h" #include "wimlib/file_io.h" +#include "wimlib/lookup_table.h" #include "wimlib/reparse.h" #include "wimlib/timestamp.h" #include "wimlib/unix_data.h" diff --git a/src/update_image.c b/src/update_image.c index facdfff2..65389e15 100644 --- a/src/update_image.c +++ b/src/update_image.c @@ -49,6 +49,7 @@ # include "config.h" #endif +#include "wimlib/assert.h" #include "wimlib/capture.h" #include "wimlib/dentry.h" #include "wimlib/encoding.h" diff --git a/src/wim.c b/src/wim.c index 880fa7ec..1c0e6efd 100644 --- a/src/wim.c +++ b/src/wim.c @@ -24,6 +24,7 @@ #endif #include "wimlib.h" +#include "wimlib/assert.h" #include "wimlib/bitops.h" #include "wimlib/dentry.h" #include "wimlib/encoding.h" diff --git a/src/win32_apply.c b/src/win32_apply.c index 7580a718..54c247ce 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -28,6 +28,7 @@ #include "wimlib/win32_common.h" #include "wimlib/apply.h" +#include "wimlib/assert.h" #include "wimlib/capture.h" /* for mangle_pat() and match_pattern_list() */ #include "wimlib/dentry.h" #include "wimlib/error.h" diff --git a/src/win32_capture.c b/src/win32_capture.c index 4adf3364..ab572cb2 100644 --- a/src/win32_capture.c +++ b/src/win32_capture.c @@ -29,6 +29,7 @@ #include "wimlib/win32_common.h" +#include "wimlib/assert.h" #include "wimlib/capture.h" #include "wimlib/dentry.h" #include "wimlib/encoding.h" diff --git a/src/write.c b/src/write.c index 1de3e7a9..fcc5983f 100644 --- a/src/write.c +++ b/src/write.c @@ -32,6 +32,7 @@ # include #endif +#include "wimlib/assert.h" #include "wimlib/chunk_compressor.h" #include "wimlib/endianness.h" #include "wimlib/error.h" diff --git a/src/xml.c b/src/xml.c index 1dd4d839..be5a3f80 100644 --- a/src/xml.c +++ b/src/xml.c @@ -25,6 +25,7 @@ # include "config.h" #endif +#include "wimlib/assert.h" #include "wimlib/dentry.h" #include "wimlib/encoding.h" #include "wimlib/error.h" -- 2.43.0