struct blob_descriptor;
struct blob_table;
struct wim_dentry;
+struct wim_inode_extra;
struct wim_security_data;
struct wimfs_fd;
union {
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 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;
+ u32 i_nlink : 30;
- /* 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;
+ /* 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;
/* Cached value */
- u8 i_can_externally_back : 1;
+ 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;
-
- /* Size of @i_extra buffer in bytes. If 0, there is no extra data. */
- size_t i_extra_size;
+ struct wim_inode_extra *i_extra;
/* 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.
/* 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
* WIMLIB_WRITE_FLAG_SEND_DONE_WITH_FILE_MESSAGES: the number
* of streams this inode has that have not yet been fully read.
* */
- u32 num_remaining_streams;
+ u32 i_num_remaining_streams;
#ifdef WITH_FUSE
struct {
u32 i_next_stream_id;
};
+/* 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 */
+};
+
/*
- * 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
/* 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)
+ hlist_for_each_entry((dentry), &(inode)->i_alias_list, d_alias_node)
/* Return an alias of the specified inode. */
-#define inode_first_dentry(inode) \
- container_of(inode->i_dentry.next, struct wim_dentry, d_alias)
+#define inode_any_dentry(inode) \
+ hlist_entry(inode->i_alias_list.first, struct wim_dentry, d_alias_node)
/* 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))
+#define inode_any_full_path(inode) \
+ dentry_full_path(inode_any_dentry(inode))
extern void
d_associate(struct wim_dentry *dentry, struct wim_inode *inode);
return inode->i_children != NULL;
}
+/* 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 struct wim_inode_stream *
inode_get_stream(const struct wim_inode *inode, int stream_type,
const utf16lechar *stream_name);
extern struct wim_inode_stream *
inode_get_unnamed_stream(const struct wim_inode *inode, int stream_type);
+static inline struct wim_inode_stream *
+inode_get_unnamed_data_stream(const struct wim_inode *inode)
+{
+ return inode_get_unnamed_stream(inode, STREAM_TYPE_DATA);
+}
+
extern struct wim_inode_stream *
inode_add_stream(struct wim_inode *inode, int stream_type,
const utf16lechar *stream_name, struct blob_descriptor *blob);
struct blob_table *blob_table);
extern bool
-inode_add_stream_with_data(struct wim_inode *inode, int stream_type,
- const utf16lechar *stream_name,
+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);
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 void
-inode_unresolve_streams(struct wim_inode *inode);
+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);
/* 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 */