#include "wimlib/assert.h"
#include "wimlib/list.h"
-#include "wimlib/lookup_table.h"
#include "wimlib/sha1.h"
+#include "wimlib/types.h"
-#include <string.h>
-
-struct wim_ads_entry;
+struct avl_tree_node;
+struct blob_descriptor;
+struct blob_table;
struct wim_dentry;
+struct wim_inode_extra;
struct wim_security_data;
-struct wim_lookup_table;
struct wimfs_fd;
-struct avl_tree_node;
+
+/* Valid values for the 'stream_type' field of a 'struct wim_inode_stream' */
+enum wim_inode_stream_type {
+
+ /* Data stream, may be unnamed (usual case) or named */
+ STREAM_TYPE_DATA,
+
+ /* Reparse point stream. This is the same as the data of the on-disk
+ * reparse point attribute, except that the first 8 bytes of the on-disk
+ * attribute are omitted. The omitted bytes contain the reparse tag
+ * (which is instead stored in the on-disk WIM dentry), the reparse data
+ * size (which is redundant with the stream size), and a reserved field
+ * that is always zero. */
+ STREAM_TYPE_REPARSE_POINT,
+
+ /* Encrypted data in the "EFSRPC raw data format" specified by [MS-EFSR]
+ * section 2.2.3. This contains metadata for the Encrypting File System
+ * as well as the encrypted data of all the file's data streams. */
+ STREAM_TYPE_EFSRPC_RAW_DATA,
+
+ /* Stream type could not be determined */
+ STREAM_TYPE_UNKNOWN,
+};
+
+extern const utf16lechar NO_STREAM_NAME[1];
/*
- * WIM inode.
+ * 'struct wim_inode_stream' describes a "stream", which associates a blob of
+ * data with an inode. Each stream has a type and optionally a name.
+ *
+ * The most frequently seen kind of stream is the "unnamed data stream"
+ * (stream_type == STREAM_TYPE_DATA && stream_name == NO_STREAM_NAME), which is
+ * the "default file contents". Many inodes just have an unnamed data stream
+ * and no other streams. However, files on NTFS filesystems may have
+ * additional, "named" data streams, and this is supported by the WIM format.
*
- * As mentioned in the comment above `struct wim_dentry', in WIM files there
- * is no on-disk analogue of a real inode, as most of these fields are
- * duplicated in the dentries. Instead, a `struct wim_inode' is something we
- * create ourselves to simplify the handling of hard links.
+ * A "reparse point" is an inode with reparse data set. The reparse data is
+ * stored in a stream of type STREAM_TYPE_REPARSE_POINT. There should be only
+ * one such stream, and it should be unnamed. However, it is possible for an
+ * inode to have both a reparse point stream and an unnamed data stream, and
+ * even named data streams as well.
*/
-struct wim_inode {
- /* If i_resolved == 0:
- * SHA1 message digest of the contents of the unnamed-data stream
- * of this inode.
- *
- * If i_resolved == 1:
- * Pointer to the lookup table entry for the unnamed data stream
- * of this inode, or NULL.
+struct wim_inode_stream {
+
+ /* The name of the stream or NO_STREAM_NAME. */
+ utf16lechar *stream_name;
+
+ /*
+ * If 'stream_resolved' = 0, then 'stream_hash' is the SHA-1 message
+ * digest of the uncompressed data of this stream, or all zeroes if this
+ * stream is empty.
*
- * i_hash corresponds to the 'unnamed_stream_hash' field of the `struct
- * wim_dentry_on_disk' and the additional caveats documented about that
- * field apply here (for example, the quirks regarding all-zero hashes).
+ * If 'stream_resolved' = 1, then 'stream_blob' is a pointer directly to
+ * a descriptor for this stream's blob, or NULL if this stream is empty.
*/
union {
- u8 i_hash[SHA1_HASH_SIZE];
- struct wim_lookup_table_entry *i_lte;
- };
+ u8 _stream_hash[SHA1_HASH_SIZE];
+ struct blob_descriptor *_stream_blob;
+ } _packed_attribute; /* union is SHA1_HASH_SIZE bytes */
+
+ /* 'stream_resolved' determines whether 'stream_hash' or 'stream_blob'
+ * is valid as described above. */
+ u32 stream_resolved : 1;
+
+ /* A unique identifier for this stream within the context of its inode.
+ * This stays constant even if the streams array is reallocated. */
+ u32 stream_id : 28;
+
+ /* The type of this stream as one of the STREAM_TYPE_* values */
+ u32 stream_type : 3;
+};
+
+/*
+ * WIM inode - a "file" in an image which may be accessible via multiple paths
+ *
+ * Note: in WIM files there is no true on-disk analogue of an inode; there are
+ * only directory entries, and some fields are duplicated among all links to a
+ * file. However, wimlib uses inode structures internally to simplify handling
+ * of hard links.
+ */
+struct wim_inode {
+
+ /*
+ * The collection of streams for this inode. 'i_streams' points to
+ * either 'i_embedded_streams' or an allocated array.
+ */
+ struct wim_inode_stream *i_streams;
+ struct wim_inode_stream i_embedded_streams[1];
+ unsigned i_num_streams;
- /* Corresponds to the 'attributes' field of `struct wim_dentry_on_disk';
- * bitwise OR of the FILE_ATTRIBUTE_* flags that give the attributes of
- * this inode. */
+ /* Windows file attribute flags (FILE_ATTRIBUTE_*). */
u32 i_attributes;
/* Root of a balanced binary search tree storing the child directory
- * entries of this inode, if any. Keyed by wim_dentry->file_name, case
+ * entries of this inode, if any. Keyed by wim_dentry->d_name, case
* sensitively. If this inode is not a directory or if it has no
* children then this will be an empty tree (NULL). */
struct avl_tree_node *i_children;
/* Root of a balanced binary search tree storing the child directory
- * entries of this inode, if any. Keyed by wim_dentry->file_name, case
+ * entries of this inode, if any. Keyed by wim_dentry->d_name, case
* insensitively. If this inode is not a directory or if it has no
* children then this will be an empty tree (NULL). */
struct avl_tree_node *i_children_ci;
/* List of dentries that are aliases for this inode. There will be
* i_nlink dentries in this list. */
- struct list_head i_dentry;
+ struct hlist_head i_alias_list;
- /* Field to place this inode into a list. */
- union {
- /* Hash list node- used in inode_fixup.c when the inodes are
- * placed into a hash table keyed by inode number and optionally
- * device number, in order to detect dentries that are aliases
- * 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. */
- struct list_head i_list;
- };
+ /* Field to place this inode into a list. While reading a WIM image or
+ * adding files to a WIM image this is owned by the inode table;
+ * otherwise this links the inodes for the WIM image. */
+ struct hlist_node i_hlist_node;
/* Number of dentries that are aliases for this inode. */
- u32 i_nlink;
-
- /* Number of alternate data streams (ADS) associated with this inode */
- u16 i_num_ads;
-
- /* Flag that indicates whether this inode's streams have been
- * "resolved". By default, the inode starts as "unresolved", meaning
- * that the i_hash field, along with the hash field of any associated
- * wim_ads_entry's, are valid and should be used as keys in the WIM
- * lookup table to find the associated `struct wim_lookup_table_entry'.
- * But if the inode has been resolved, then each of these fields is
- * replaced with a pointer directly to the appropriate `struct
- * wim_lookup_table_entry', or NULL if the stream is empty. */
- u8 i_resolved : 1;
-
- /* Flag used to mark this inode as visited; this is used when visiting
- * all the inodes in a dentry tree exactly once. It will be 0 by
- * default and must be cleared following the tree traversal, even in
- * error paths. */
- u8 i_visited : 1;
-
- /* 1 iff all ADS entries of this inode are named or if this inode
- * has no ADS entries */
- u8 i_canonical_streams : 1;
+ u32 i_nlink : 30;
- /* Cached value */
- u8 i_can_externally_back : 1;
+ /* Flag used by some code to mark this inode as visited. It will be 0
+ * by default, and it always must be cleared after use. */
+ u32 i_visited : 1;
- /* Pointer to a malloc()ed array of i_num_ads alternate data stream
- * entries for this inode. */
- struct wim_ads_entry *i_ads_entries;
+ /* Cached value */
+ u32 i_can_externally_back : 1;
/* If not NULL, a pointer to the extra data that was read from the
* dentry. This should be a series of tagged items, each of which
* represents a bit of extra metadata, such as the file's object ID.
* See tagged_items.c for more information. */
- void *i_extra;
+ struct wim_inode_extra *i_extra;
- /* 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;
/* Corresponds to 'security_id' in `struct wim_dentry_on_disk': The
* index of this inode's security descriptor in the WIM image's table of
- * security descriptors, or -1. Note: when a WIM image is loaded,
- * wimlib sets out-of-bounds indices and values less than -1 in this
- * field to -1. So the extraction code need not do an upper bound check
- * after checking for -1 (or equivalently < 0). */
- int32_t i_security_id;
-
- /* Identity of a reparse point. See
- * http://msdn.microsoft.com/en-us/library/windows/desktop/aa365503(v=vs.85).aspx
- * for what a reparse point is. */
- u32 i_reparse_tag;
+ * security descriptors, or -1 if this inode does not have a security
+ * descriptor. */
+ s32 i_security_id;
- /* Unused/unknown fields that we just read into memory so we can
- * re-write them unchanged. */
- u32 i_rp_unknown_1;
- u16 i_rp_unknown_2;
+ /* Unknown field that we only read into memory so we can re-write it
+ * unchanged. Probably it's actually just padding... */
+ u32 i_unknown_0x54;
- /* Corresponds to not_rpfixed in `struct wim_dentry_on_disk': Set to 0
- * if reparse point fixups have been done. Otherwise set to 1. Note:
- * this actually may reflect the SYMBOLIC_LINK_RELATIVE flag.
- */
- u16 i_not_rpfixed;
+ /* The following fields correspond to 'reparse_tag', 'rp_reserved', and
+ * 'rp_flags' in `struct wim_dentry_on_disk'. They are only meaningful
+ * for reparse point files. */
+ u32 i_reparse_tag;
+ u16 i_rp_reserved;
+ u16 i_rp_flags;
/* Inode number; corresponds to hard_link_group_id in the `struct
* wim_dentry_on_disk'. */
/* Device number, used only during image capture, so we can
* identify hard linked files by the combination of inode number
* and device number (rather than just inode number, which could
- * be ambigious if the captured tree spans a mountpoint). Set
+ * be ambiguous if the captured tree spans a mountpoint). Set
* to 0 otherwise. */
u64 i_devno;
/* Fields used only during extraction */
struct {
- /* List of aliases of this dentry that are being
- * extracted in the current extraction operation. This
- * will be a (possibly nonproper) subset of the dentries
- * in the i_dentry list. This list will be constructed
+ /* A singly linked list of aliases of this inode that
+ * are being extracted in the current extraction
+ * operation. This list may be shorter than the inode's
+ * full alias list. This list will be constructed
* regardless of whether the extraction backend supports
* hard links or not. */
- struct list_head i_extraction_aliases;
+ struct wim_dentry *i_first_extraction_alias;
#ifdef WITH_NTFS_3G
/* In NTFS-3g extraction mode, this is set to the Master
/* Used during WIM writing with
* WIMLIB_WRITE_FLAG_SEND_DONE_WITH_FILE_MESSAGES: the number
- * of data streams this inode has that have not yet been fully
- * read. */
- u32 num_remaining_streams;
+ * of streams this inode has that have not yet been fully read.
+ * */
+ u32 i_num_remaining_streams;
#ifdef WITH_FUSE
struct {
u16 i_num_allocated_fds;
#endif
- /* Next alternate data stream ID to be assigned */
+ /* Next stream ID to be assigned */
u32 i_next_stream_id;
};
-/* Alternate data stream entry.
- *
- * We read this from disk in the read_ads_entries() function; see that function
- * for more explanation. */
-struct wim_ads_entry {
- union {
- /* SHA-1 message digest of stream contents */
- u8 hash[SHA1_HASH_SIZE];
-
- /* The corresponding lookup table entry (only for resolved
- * streams) */
- struct wim_lookup_table_entry *lte;
- };
-
- /* Length of UTF16-encoded stream name, in bytes, not including the
- * terminating null character; or 0 if the stream is unnamed. */
- u16 stream_name_nbytes;
-
- /* Number to identify an alternate data stream even after it's possibly
- * been moved or renamed. */
- u32 stream_id;
-
- /* Stream name (UTF-16LE), null-terminated, or NULL if the stream is
- * unnamed. */
- utf16lechar *stream_name;
-
- /* Reserved field. We read it into memory so we can write it out
- * unchanged. */
- u64 reserved;
+/* Optional extra data for a WIM inode */
+struct wim_inode_extra {
+ size_t size; /* Size of the extra data in bytes */
+ u8 data[]; /* The extra data */
};
-/* 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;
-
- le64 reserved;
-
- /* SHA1 message digest of the uncompressed stream; or, alternatively,
- * 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.
- * */
- utf16lechar stream_name[];
-} _packed_attribute;
-
-#define WIM_ADS_ENTRY_DISK_SIZE 38
-
/*
- * Reparse tags documented at
- * http://msdn.microsoft.com/en-us/library/dd541667(v=prot.10).aspx
+ * The available reparse tags are documented at
+ * http://msdn.microsoft.com/en-us/library/dd541667(v=prot.10).aspx.
+ * Here we only define the ones of interest to us.
*/
-#define WIM_IO_REPARSE_TAG_RESERVED_ZERO 0x00000000
-#define WIM_IO_REPARSE_TAG_RESERVED_ONE 0x00000001
#define WIM_IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
-#define WIM_IO_REPARSE_TAG_HSM 0xC0000004
-#define WIM_IO_REPARSE_TAG_HSM2 0x80000006
-#define WIM_IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
-#define WIM_IO_REPARSE_TAG_SIS 0x80000007
-#define WIM_IO_REPARSE_TAG_DFS 0x8000000A
-#define WIM_IO_REPARSE_TAG_DFSR 0x80000012
-#define WIM_IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
#define WIM_IO_REPARSE_TAG_SYMLINK 0xA000000C
+#define WIM_IO_REPARSE_TAG_WOF 0x80000017
+/* Flags for the rp_flags field. Currently the only known flag is NOT_FIXED,
+ * which indicates that the target of the absolute symbolic link or junction was
+ * not changed when it was stored. */
+#define WIM_RP_FLAG_NOT_FIXED 0x0001
+
+/* Windows file attribute flags */
#define FILE_ATTRIBUTE_READONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
#define FILE_ATTRIBUTE_VIRTUAL 0x00010000
extern struct wim_inode *
-new_inode(void) _malloc_attribute;
-
-extern struct wim_inode *
-new_timeless_inode(void) _malloc_attribute;
-
-extern void
-put_inode(struct wim_inode *inode);
+new_inode(struct wim_dentry *dentry, bool set_timestamps);
-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)
-
-/* Add a new alias for an inode. Does not increment i_nlink; that must be done
- * separately. */
-#define inode_add_dentry(dentry, inode) \
- list_add_tail(&(dentry)->d_alias, &(inode)->i_dentry)
-
-/* Return an alias of an inode. */
-#define inode_first_dentry(inode) \
- 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. */
-#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);
+ hlist_for_each_entry((dentry), &(inode)->i_alias_list, d_alias_node)
-extern struct wim_ads_entry *
-inode_add_ads(struct wim_inode *dentry, const tchar *stream_name);
+/* Return an alias of the specified inode. */
+#define inode_any_dentry(inode) \
+ hlist_entry(inode->i_alias_list.first, struct wim_dentry, d_alias_node)
-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);
+/* Return the full path of an alias of the specified inode, or NULL if a full
+ * path could not be determined. */
+#define inode_any_full_path(inode) \
+ dentry_full_path(inode_any_dentry(inode))
-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
+d_associate(struct wim_dentry *dentry, struct wim_inode *inode);
extern void
-inode_remove_ads(struct wim_inode *inode, struct wim_ads_entry *entry,
- struct wim_lookup_table *lookup_table);
+d_disassociate(struct wim_dentry *dentry);
-/*
- * 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;
-}
+#ifdef WITH_FUSE
+extern void
+inode_dec_num_opened_fds(struct wim_inode *inode);
+#endif
/* Is the inode a directory?
* This doesn't count directories with reparse data.
== FILE_ATTRIBUTE_DIRECTORY;
}
-/* 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). */
-static inline bool
-inode_is_encrypted_directory(const struct wim_inode *inode)
-{
- return ((inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
- FILE_ATTRIBUTE_ENCRYPTED))
- == (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ENCRYPTED));
-}
-
/* Is the inode a symbolic link?
* This returns true iff the inode is a reparse point that is either a "real"
* symbolic link or a junction point. */
inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT);
}
-/* Does the inode have children?
- * Currently (based on read_dentry_tree()), this can only return true for inodes
- * for which inode_is_directory() returns true. (This also returns false on
- * empty directories.) */
+/* Does the inode have children? Currently (based on read_dentry_tree() as well
+ * as the various build-dentry-tree implementations), this can only return true
+ * for inodes for which inode_is_directory() returns true. */
static inline bool
inode_has_children(const struct wim_inode *inode)
{
return inode->i_children != NULL;
}
-extern int
-inode_resolve_streams(struct wim_inode *inode, struct wim_lookup_table *table,
- bool force);
+/* Does the inode have a security descriptor? */
+static inline bool
+inode_has_security_descriptor(const struct wim_inode *inode)
+{
+ return inode->i_security_id >= 0;
+}
-extern int
-stream_not_found_error(const struct wim_inode *inode, const u8 *hash);
+extern struct wim_inode_stream *
+inode_get_stream(const struct wim_inode *inode, int stream_type,
+ const utf16lechar *stream_name);
-extern void
-inode_unresolve_streams(struct wim_inode *inode);
+extern struct wim_inode_stream *
+inode_get_unnamed_stream(const struct wim_inode *inode, int stream_type);
-static inline struct wim_lookup_table_entry *
-inode_stream_lte_resolved(const struct wim_inode *inode, unsigned stream_idx)
+static inline struct wim_inode_stream *
+inode_get_unnamed_data_stream(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_lte;
- else
- return inode->i_ads_entries[stream_idx - 1].lte;
+ return inode_get_unnamed_stream(inode, STREAM_TYPE_DATA);
}
-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);
-}
+extern struct wim_inode_stream *
+inode_add_stream(struct wim_inode *inode, int stream_type,
+ const utf16lechar *stream_name, struct blob_descriptor *blob);
-extern struct wim_lookup_table_entry *
-inode_stream_lte(const struct wim_inode *inode, unsigned stream_idx,
- const struct wim_lookup_table *table);
+extern void
+inode_replace_stream_blob(struct wim_inode *inode,
+ struct wim_inode_stream *strm,
+ struct blob_descriptor *new_blob,
+ struct blob_table *blob_table);
-static inline const u8 *
-inode_stream_hash_unresolved(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_hash;
- else
- return inode->i_ads_entries[stream_idx - 1].hash;
-}
+extern bool
+inode_replace_stream_data(struct wim_inode *inode,
+ struct wim_inode_stream *strm,
+ const void *data, size_t size,
+ struct blob_table *blob_table);
+extern bool
+inode_add_stream_with_data(struct wim_inode *inode,
+ int stream_type, const utf16lechar *stream_name,
+ const void *data, size_t size,
+ struct blob_table *blob_table);
-static inline const u8 *
-inode_stream_hash_resolved(const struct wim_inode *inode, unsigned stream_idx)
+extern void
+inode_remove_stream(struct wim_inode *inode, struct wim_inode_stream *strm,
+ struct blob_table *blob_table);
+
+static inline struct blob_descriptor *
+stream_blob_resolved(const struct wim_inode_stream *strm)
{
- struct wim_lookup_table_entry *lte;
- lte = inode_stream_lte_resolved(inode, stream_idx);
- if (lte)
- return lte->hash;
- else
- return zero_hash;
+ wimlib_assert(strm->stream_resolved);
+ return strm->_stream_blob;
}
-/*
- * 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)
+static inline bool
+stream_is_named(const struct wim_inode_stream *strm)
{
- if (inode->i_resolved)
- return inode_stream_hash_resolved(inode, stream_idx);
- else
- return inode_stream_hash_unresolved(inode, stream_idx);
+ return strm->stream_name != NO_STREAM_NAME;
}
-static inline u16
-inode_stream_name_nbytes(const struct wim_inode *inode, unsigned stream_idx)
+static inline bool
+stream_is_unnamed_data_stream(const struct wim_inode_stream *strm)
{
- 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 strm->stream_type == STREAM_TYPE_DATA && !stream_is_named(strm);
}
-static inline u32
-inode_stream_idx_to_id(const struct wim_inode *inode, unsigned stream_idx)
+static inline bool
+stream_is_named_data_stream(const struct wim_inode_stream *strm)
{
- if (stream_idx == 0)
- return 0;
- else
- return inode->i_ads_entries[stream_idx - 1].stream_id;
+ return strm->stream_type == STREAM_TYPE_DATA && stream_is_named(strm);
}
-extern struct wim_lookup_table_entry *
-inode_unnamed_stream_resolved(const struct wim_inode *inode, u16 *stream_idx_ret);
+extern bool
+inode_has_named_data_stream(const struct wim_inode *inode);
+
+extern int
+inode_resolve_streams(struct wim_inode *inode, struct blob_table *table,
+ bool force);
+
+extern int
+blob_not_found_error(const struct wim_inode *inode, const u8 *hash);
-extern struct wim_lookup_table_entry *
-inode_unnamed_lte_resolved(const struct wim_inode *inode);
+extern struct blob_descriptor *
+stream_blob(const struct wim_inode_stream *strm, const struct blob_table *table);
-extern struct wim_lookup_table_entry *
-inode_unnamed_lte_unresolved(const struct wim_inode *inode,
- const struct wim_lookup_table *table);
+extern struct blob_descriptor *
+inode_get_blob_for_unnamed_data_stream(const struct wim_inode *inode,
+ const struct blob_table *blob_table);
-extern struct wim_lookup_table_entry *
-inode_unnamed_lte(const struct wim_inode *inode, const struct wim_lookup_table *table);
+extern struct blob_descriptor *
+inode_get_blob_for_unnamed_data_stream_resolved(const struct wim_inode *inode);
extern const u8 *
-inode_unnamed_stream_hash(const struct wim_inode *inode);
+stream_hash(const struct wim_inode_stream *strm);
-extern int
-read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode,
- size_t *nbytes_remaining_p);
-
-extern void
-check_inode(struct wim_inode *inode, const struct wim_security_data *sd);
+extern const u8 *
+inode_get_hash_of_unnamed_data_stream(const struct wim_inode *inode);
extern void
-inode_ref_streams(struct wim_inode *inode);
+inode_ref_blobs(struct wim_inode *inode);
extern void
-inode_unref_streams(struct wim_inode *inode,
- struct wim_lookup_table *lookup_table);
+inode_unref_blobs(struct wim_inode *inode, struct blob_table *blob_table);
/* inode_fixup.c */
extern int
-dentry_tree_fix_inodes(struct wim_dentry *root, struct list_head *inode_list);
+dentry_tree_fix_inodes(struct wim_dentry *root, struct hlist_head *inode_list);
#endif /* _WIMLIB_INODE_H */