1 #ifndef _WIMLIB_METADATA_H
2 #define _WIMLIB_METADATA_H
3
4 #include "wimlib/blob_table.h"
5 #include "wimlib/list.h"
6 #include "wimlib/types.h"
7 #include "wimlib/wim.h"
8
9 /*
10 * This structure holds the directory tree that comprises a WIM image, along
11 * with other information maintained at the image level. It is populated either
12 * by reading and parsing a metadata resource or by scanning new files.
13 *
14 * An image that hasn't been modified from its on-disk copy is considered
15 * "clean" and is loaded from its metadata resource on demand by
16 * select_wim_image(). Such an image may be unloaded later to save memory when
17 * a different image is selected. An image that has been modified or has been
18 * created from scratch, on the other hand, is considered "dirty" and is never
19 * automatically unloaded.
20 *
21 * To implement exports, it's allowed that multiple WIMStructs reference the
22 * same wim_image_metadata.
23 */
24 struct wim_image_metadata {
25
26 /* Number of WIMStructs that reference this image. This will always be
27 * >= 1. It may be > 1 if this image has been exported. */
28 u32 refcnt;
29
30 /* Number of WIMStructs that have this image selected as their
31 * current_image. This will always be <= 'refcnt' and may be 0. */
32 u32 selected_refcnt;
33
34 /* Pointer to the root dentry of this image, or NULL if this image is
35 * completely empty or is not currently loaded. */
36 struct wim_dentry *root_dentry;
37
38 /* Pointer to the security data of this image, or NULL if this image is
39 * not currently loaded. */
40 struct wim_security_data *security_data;
41
42 /* Pointer to the blob descriptor for this image's metadata resource.
43 * If this image metadata is sourced from a WIM file (as opposed to
44 * being created from scratch) and hasn't been modified from the version
45 * in that WIM file, then this blob descriptor's data corresponds to the
46 * WIM backing source. Otherwise, this blob descriptor is a dummy entry
47 * with blob_location==BLOB_NONEXISTENT. */
48 struct blob_descriptor *metadata_blob;
49
50 /* Linked list of 'struct wim_inode's for this image, or an empty list
51 * if this image is completely empty or is not currently loaded. */
52 struct hlist_head inode_list;
53
54 /* Linked list of 'struct blob_descriptor's for blobs that are
55 * referenced by this image's dentry tree, but have not had their SHA-1
56 * message digests calculated yet and therefore have not been inserted
57 * into the WIMStruct's blob table. This list is appended to when files
58 * are scanned for inclusion in this WIM image. */
59 struct list_head unhashed_blobs;
60
61 /* Are the filecount/bytecount stats (in the XML info) out of date for
62 * this image? */
63 bool stats_outdated;
64 };
65
66 /* Retrieve the metadata of the image in @wim currently selected with
67 * select_wim_image(). */
68 static inline struct wim_image_metadata *
wim_get_current_image_metadata(WIMStruct * wim)69 wim_get_current_image_metadata(WIMStruct *wim)
70 {
71 return wim->image_metadata[wim->current_image - 1];
72 }
73
74 /* Retrieve the root dentry of the image in @wim currently selected with
75 * select_wim_image(). */
76 static inline struct wim_dentry *
wim_get_current_root_dentry(WIMStruct * wim)77 wim_get_current_root_dentry(WIMStruct *wim)
78 {
79 return wim_get_current_image_metadata(wim)->root_dentry;
80 }
81
82 /* Retrieve the security data of the image in @wim currently selected with
83 * select_wim_image(). */
84 static inline struct wim_security_data *
wim_get_current_security_data(WIMStruct * wim)85 wim_get_current_security_data(WIMStruct *wim)
86 {
87 return wim_get_current_image_metadata(wim)->security_data;
88 }
89
90 /* Return true iff the specified image has been changed since being read from
91 * its backing file or has been created from scratch. */
92 static inline bool
is_image_dirty(const struct wim_image_metadata * imd)93 is_image_dirty(const struct wim_image_metadata *imd)
94 {
95 /* The only possible values here are BLOB_NONEXISTENT and BLOB_IN_WIM */
96 return imd->metadata_blob->blob_location == BLOB_NONEXISTENT;
97 }
98
99 /* Return true iff the specified image is unchanged since being read from the
100 * specified backing WIM file. */
101 static inline bool
is_image_unchanged_from_wim(const struct wim_image_metadata * imd,const WIMStruct * wim)102 is_image_unchanged_from_wim(const struct wim_image_metadata *imd,
103 const WIMStruct *wim)
104 {
105 return !is_image_dirty(imd) && imd->metadata_blob->rdesc->wim == wim;
106 }
107
108 /* Mark the metadata for the specified WIM image "dirty" following changes to
109 * the image's directory tree. This records that the metadata no longer matches
110 * the version in the WIM file (if any) and that its stats are out of date. */
111 static inline void
mark_image_dirty(struct wim_image_metadata * imd)112 mark_image_dirty(struct wim_image_metadata *imd)
113 {
114 blob_release_location(imd->metadata_blob);
115 imd->stats_outdated = true;
116 }
117
118 /* Return true iff the specified image is currently loaded into memory. */
119 static inline bool
is_image_loaded(const struct wim_image_metadata * imd)120 is_image_loaded(const struct wim_image_metadata *imd)
121 {
122 /* Check security_data rather than root_dentry, since root_dentry will
123 * be NULL for a completely empty image whereas security_data will still
124 * be non-NULL in that case. */
125 return imd->security_data != NULL;
126 }
127
128 /* Return true iff it is okay to unload the specified image. The image can be
129 * unloaded if no WIMStructs have it selected and it is not dirty. */
130 static inline bool
can_unload_image(const struct wim_image_metadata * imd)131 can_unload_image(const struct wim_image_metadata *imd)
132 {
133 return imd->selected_refcnt == 0 && !is_image_dirty(imd);
134 }
135
136 /* Iterate over each inode in a WIM image */
137 #define image_for_each_inode(inode, imd) \
138 hlist_for_each_entry(inode, &(imd)->inode_list, i_hlist_node)
139
140 /* Iterate over each inode in a WIM image (safe against inode removal) */
141 #define image_for_each_inode_safe(inode, tmp, imd) \
142 hlist_for_each_entry_safe(inode, tmp, &(imd)->inode_list, i_hlist_node)
143
144 /* Iterate over each blob in a WIM image that has not yet been hashed */
145 #define image_for_each_unhashed_blob(blob, imd) \
146 list_for_each_entry(blob, &(imd)->unhashed_blobs, unhashed_list)
147
148 /* Iterate over each blob in a WIM image that has not yet been hashed (safe
149 * against blob removal) */
150 #define image_for_each_unhashed_blob_safe(blob, tmp, imd) \
151 list_for_each_entry_safe(blob, tmp, &(imd)->unhashed_blobs, unhashed_list)
152
153 extern void
154 put_image_metadata(struct wim_image_metadata *imd);
155
156 extern int
157 append_image_metadata(WIMStruct *wim, struct wim_image_metadata *imd);
158
159 extern struct wim_image_metadata *
160 new_empty_image_metadata(void);
161
162 extern struct wim_image_metadata *
163 new_unloaded_image_metadata(struct blob_descriptor *metadata_blob);
164
165 #endif /* _WIMLIB_METADATA_H */
166