X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=include%2Fwimlib%2Finode.h;h=11c2361b81bf5da59dd6b2e71fe9d7c46c28f9b5;hp=9a94ce2fd8adff6a59da17b722c728e29b5f2c71;hb=b5fae0e5ddac332b25856e3df7556aa3ee7f69fb;hpb=71d3401258fb14dcfc921f53452ba972e27e8b8b diff --git a/include/wimlib/inode.h b/include/wimlib/inode.h index 9a94ce2f..11c2361b 100644 --- a/include/wimlib/inode.h +++ b/include/wimlib/inode.h @@ -1,25 +1,22 @@ #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/unix_data.h" - -#include +#include "wimlib/types.h" +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. * - * As mentioned in the comment above `struct wim_dentry', in the WIM file that + * 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. @@ -71,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; }; @@ -103,23 +100,36 @@ struct wim_inode { * has no ADS entries */ u8 i_canonical_streams : 1; + /* Cached value */ + u8 i_can_externally_back : 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; - /* 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. */ + /* 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; + + /* 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: in verify_inode(), called - * whenever a WIM image is loaded, out-of-bounds indices are set to -1, - * so the extraction code does not need to do bounds checks. */ + * 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 @@ -142,9 +152,6 @@ struct wim_inode { * wim_dentry_on_disk'. */ u64 i_ino; - /* UNIX data (wimlib extension) */ - struct wimlib_unix_data i_unix_data; - union { /* Device number, used only during image capture, so we can * identify hard linked files by the combination of inode number @@ -171,11 +178,24 @@ struct wim_inode { #endif }; + /* 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; + #ifdef WITH_FUSE - /* Used only during image mount: Table of file descriptors that - * have been opened to this inode. The table is automatically - * freed when the last file descriptor is closed. */ - struct wimfs_fd **i_fds; + struct { + /* Used only during image mount: Table of file + * descriptors that have been opened to this inode. + * This table is freed when the last file descriptor is + * closed. */ + struct wimfs_fd **i_fds; + + /* Lower bound on the index of the next available entry + * in 'i_fds'. */ + u16 i_next_fd; + }; #endif }; @@ -221,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; @@ -286,69 +304,29 @@ new_inode(void) _malloc_attribute; extern struct wim_inode * new_timeless_inode(void) _malloc_attribute; -extern void -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. */ -#define inode_add_dentry(dentry, inode) \ - 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, - u16 *idx_ret); - -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 int -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); + dentry_full_path(inode_first_dentry(inode)) extern void -inode_remove_ads(struct wim_inode *inode, u16 idx, - struct wim_lookup_table *lookup_table); +d_associate(struct wim_dentry *dentry, struct wim_inode *inode); -static inline bool -ads_entry_is_named_stream(const struct wim_ads_entry *entry) -{ - return entry->stream_name_nbytes != 0; -} +extern void +d_disassociate(struct wim_dentry *dentry); -static inline bool -inode_has_unix_data(const struct wim_inode *inode) -{ - return inode->i_unix_data.mode != 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. @@ -363,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) { @@ -394,116 +372,90 @@ 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; } -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 const u8 * -inode_unnamed_stream_hash(const struct wim_inode *inode); - -extern int -read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode, - size_t nbytes_remaining); - -extern int -verify_inode(struct wim_inode *inode, const struct wim_security_data *sd); +static inline u32 +inode_stream_idx_to_id(const struct wim_inode *inode, unsigned stream_idx) +{ + if (stream_idx == 0) + return 0; + return inode->i_ads_entries[stream_idx - 1].stream_id; +} extern void inode_ref_streams(struct wim_inode *inode); @@ -512,6 +464,13 @@ 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, + size_t *nbytes_remaining_p); + +extern void +check_inode(struct wim_inode *inode, const struct wim_security_data *sd); + /* inode_fixup.c */ extern int dentry_tree_fix_inodes(struct wim_dentry *root, struct list_head *inode_list);