X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=include%2Fwimlib%2Fmetadata.h;h=030b0b12dd644daaa8298a2d700fbef1b2566da1;hb=81d03c562d98c865fb2c03978231c250f68cb0a7;hp=31b95cef045f41ddf027fe85f0974f6d2359d08d;hpb=00a775dc256d1fc8254d4f055e362e67f25b66d8;p=wimlib diff --git a/include/wimlib/metadata.h b/include/wimlib/metadata.h index 31b95cef..030b0b12 100644 --- a/include/wimlib/metadata.h +++ b/include/wimlib/metadata.h @@ -1,111 +1,165 @@ #ifndef _WIMLIB_METADATA_H #define _WIMLIB_METADATA_H +#include "wimlib/blob_table.h" #include "wimlib/list.h" #include "wimlib/types.h" #include "wimlib/wim.h" -#ifdef WITH_NTFS_3G -struct _ntfs_volume; -#endif - -/* Metadata for a WIM image */ +/* + * This structure holds the directory tree that comprises a WIM image, along + * with other information maintained at the image level. It is populated either + * by reading and parsing a metadata resource or by scanning new files. + * + * An image that hasn't been modified from its on-disk copy is considered + * "clean" and is loaded from its metadata resource on demand by + * select_wim_image(). Such an image may be unloaded later to save memory when + * a different image is selected. An image that has been modified or has been + * created from scratch, on the other hand, is considered "dirty" and is never + * automatically unloaded. + * + * To implement exports, it's allowed that multiple WIMStructs reference the + * same wim_image_metadata. + */ struct wim_image_metadata { - /* Number of WIMStruct's that are sharing this image metadata (from - * calls to wimlib_export_image().) */ - unsigned long refcnt; + /* Number of WIMStructs that reference this image. This will always be + * >= 1. It may be > 1 if this image has been exported. */ + u32 refcnt; + + /* Number of WIMStructs that have this image selected as their + * current_image. This will always be <= 'refcnt' and may be 0. */ + u32 selected_refcnt; - /* Pointer to the root dentry of the image. */ + /* Pointer to the root dentry of this image, or NULL if this image is + * completely empty or is not currently loaded. */ struct wim_dentry *root_dentry; - /* Pointer to the security data of the image. */ + /* Pointer to the security data of this image, or NULL if this image is + * not currently loaded. */ struct wim_security_data *security_data; - /* Pointer to the lookup table entry for this image's metadata resource - */ - struct wim_lookup_table_entry *metadata_lte; - - /* Linked list of 'struct wim_inode's for this image. */ - struct list_head inode_list; - - /* Linked list of 'struct wim_lookup_table_entry's for this image that - * are referred to in the dentry tree, but have not had a SHA1 message - * digest calculated yet and therefore have not been inserted into the - * WIM's lookup table. This list is added to during wimlib_add_image() - * and wimlib_mount_image() (read-write only). */ - struct list_head unhashed_streams; - - /* 1 iff the dentry tree has been modified. If this is the case, the - * memory for the dentry tree should not be freed when switching to a - * different WIM image. */ - u8 modified : 1; - -#ifdef WITH_NTFS_3G - struct _ntfs_volume *ntfs_vol; -#endif + /* Pointer to the blob descriptor for this image's metadata resource. + * If this image metadata is sourced from a WIM file (as opposed to + * being created from scratch) and hasn't been modified from the version + * in that WIM file, then this blob descriptor's data corresponds to the + * WIM backing source. Otherwise, this blob descriptor is a dummy entry + * with blob_location==BLOB_NONEXISTENT. */ + struct blob_descriptor *metadata_blob; + + /* Linked list of 'struct wim_inode's for this image, or an empty list + * if this image is completely empty or is not currently loaded. */ + struct hlist_head inode_list; + + /* Linked list of 'struct blob_descriptor's for blobs that are + * referenced by this image's dentry tree, but have not had their SHA-1 + * message digests calculated yet and therefore have not been inserted + * into the WIMStruct's blob table. This list is appended to when files + * are scanned for inclusion in this WIM image. */ + struct list_head unhashed_blobs; + + /* Are the filecount/bytecount stats (in the XML info) out of date for + * this image? */ + bool stats_outdated; }; +/* Retrieve the metadata of the image in @wim currently selected with + * select_wim_image(). */ static inline struct wim_image_metadata * wim_get_current_image_metadata(WIMStruct *wim) { return wim->image_metadata[wim->current_image - 1]; } -static inline const struct wim_image_metadata * -wim_get_const_current_image_metadata(const WIMStruct *wim) -{ - return wim->image_metadata[wim->current_image - 1]; -} - +/* Retrieve the root dentry of the image in @wim currently selected with + * select_wim_image(). */ static inline struct wim_dentry * -wim_root_dentry(WIMStruct *wim) +wim_get_current_root_dentry(WIMStruct *wim) { return wim_get_current_image_metadata(wim)->root_dentry; } +/* Retrieve the security data of the image in @wim currently selected with + * select_wim_image(). */ static inline struct wim_security_data * -wim_security_data(WIMStruct *wim) +wim_get_current_security_data(WIMStruct *wim) { return wim_get_current_image_metadata(wim)->security_data; } -static inline const struct wim_security_data * -wim_const_security_data(const WIMStruct *wim) +/* Return true iff the specified image has been changed since being read from + * its backing file or has been created from scratch. */ +static inline bool +is_image_dirty(const struct wim_image_metadata *imd) +{ + /* The only possible values here are BLOB_NONEXISTENT and BLOB_IN_WIM */ + return imd->metadata_blob->blob_location == BLOB_NONEXISTENT; +} + +/* Return true iff the specified image is unchanged since being read from the + * specified backing WIM file. */ +static inline bool +is_image_unchanged_from_wim(const struct wim_image_metadata *imd, + const WIMStruct *wim) { - return wim_get_const_current_image_metadata(wim)->security_data; + return !is_image_dirty(imd) && imd->metadata_blob->rdesc->wim == wim; } -/* Iterate over each inode in a WIM image that has not yet been hashed */ +/* Mark the metadata for the specified WIM image "dirty" following changes to + * the image's directory tree. This records that the metadata no longer matches + * the version in the WIM file (if any) and that its stats are out of date. */ +static inline void +mark_image_dirty(struct wim_image_metadata *imd) +{ + blob_release_location(imd->metadata_blob); + imd->stats_outdated = true; +} + +/* Return true iff the specified image is currently loaded into memory. */ +static inline bool +is_image_loaded(const struct wim_image_metadata *imd) +{ + /* Check security_data rather than root_dentry, since root_dentry will + * be NULL for a completely empty image whereas security_data will still + * be non-NULL in that case. */ + return imd->security_data != NULL; +} + +/* Return true iff it is okay to unload the specified image. The image can be + * unloaded if no WIMStructs have it selected and it is not dirty. */ +static inline bool +can_unload_image(const struct wim_image_metadata *imd) +{ + return imd->selected_refcnt == 0 && !is_image_dirty(imd); +} + +/* Iterate over each inode in a WIM image */ #define image_for_each_inode(inode, imd) \ - list_for_each_entry(inode, &imd->inode_list, i_list) + hlist_for_each_entry(inode, &(imd)->inode_list, i_hlist_node) -/* Iterate over each stream in a WIM image that has not yet been hashed */ -#define image_for_each_unhashed_stream(lte, imd) \ - list_for_each_entry(lte, &imd->unhashed_streams, unhashed_list) +/* Iterate over each inode in a WIM image (safe against inode removal) */ +#define image_for_each_inode_safe(inode, tmp, imd) \ + hlist_for_each_entry_safe(inode, tmp, &(imd)->inode_list, i_hlist_node) -/* Iterate over each stream in a WIM image that has not yet been hashed (safe - * against stream removal) */ -#define image_for_each_unhashed_stream_safe(lte, tmp, imd) \ - list_for_each_entry_safe(lte, tmp, &imd->unhashed_streams, unhashed_list) +/* Iterate over each blob in a WIM image that has not yet been hashed */ +#define image_for_each_unhashed_blob(blob, imd) \ + list_for_each_entry(blob, &(imd)->unhashed_blobs, unhashed_list) -extern void -destroy_image_metadata(struct wim_image_metadata *imd, - struct wim_lookup_table *table, - bool free_metadata_lte); +/* Iterate over each blob in a WIM image that has not yet been hashed (safe + * against blob removal) */ +#define image_for_each_unhashed_blob_safe(blob, tmp, imd) \ + list_for_each_entry_safe(blob, tmp, &(imd)->unhashed_blobs, unhashed_list) extern void -put_image_metadata(struct wim_image_metadata *imd, - struct wim_lookup_table *table); +put_image_metadata(struct wim_image_metadata *imd); extern int append_image_metadata(WIMStruct *wim, struct wim_image_metadata *imd); extern struct wim_image_metadata * -new_image_metadata(void); - -extern struct wim_image_metadata ** -new_image_metadata_array(unsigned num_images); +new_empty_image_metadata(void); +extern struct wim_image_metadata * +new_unloaded_image_metadata(struct blob_descriptor *metadata_blob); #endif /* _WIMLIB_METADATA_H */