Make WIMStructs reference-counted
[wimlib] / include / wimlib / wim.h
index 50db70d..00de8a5 100644 (file)
+/*
+ * wim.h - WIMStruct definition and helper functions
+ */
+
 #ifndef _WIMLIB_WIM_H
 #define _WIMLIB_WIM_H
 
 #include "wimlib.h"
-#include "wimlib/header.h"
-#include "wimlib/types.h"
 #include "wimlib/file_io.h"
+#include "wimlib/header.h"
 #include "wimlib/list.h"
 
-struct wim_info;
-struct wim_lookup_table;
 struct wim_image_metadata;
-
-/* The opaque structure exposed to the wimlib API. */
+struct wim_xml_info;
+struct blob_table;
+
+/*
+ * WIMStruct - represents a WIM, or a part of a non-standalone WIM
+ *
+ * Note 1: there are three ways in which a WIMStruct can be created:
+ *
+ *     1. open an on-disk WIM file
+ *     2. start to extract a pipable WIM from a file descriptor
+ *     3. create a new WIMStruct directly
+ *
+ * For (1) and (2), the WIMStruct has a backing file; for (3) it does not.  For
+ * (1), the backing file is a real "on-disk" file from the filesystem, whereas
+ * for (2) the backing file is a file descriptor which may be a pipe.
+ *
+ * Note 2: although this is the top-level data structure in wimlib, there do
+ * exist cases in which a WIMStruct is not standalone:
+ *     - blobs have been referenced from another WIMStruct
+ *     - an image has been imported into this WIMStruct from another
+ *       (as this references the metadata rather than copies it)
+ *
+ * Note 3: It is unsafe for multiple threads to operate on the same WIMStruct at
+ * the same time.  This extends to references to other WIMStructs as noted
+ * above.  But besides this, it is safe to operate on *different* WIMStructs in
+ * different threads concurrently.
+ */
 struct WIMStruct {
 
-       /* File descriptor for the WIM file, opened for reading.  in_fd.fd is -1
-        * if the WIM file has not been opened or there is no associated file
-        * backing it yet. */
-       struct filedes in_fd;
-
-       /* File descriptor, opened either for writing only or for
-        * reading+writing, for the WIM file (if any) currently being written.
-        * */
-       struct filedes out_fd;
+       /* Information from the header of the WIM file.
+        *
+        * This is also maintained for a WIMStruct not backed by a file, but in
+        * that case the 'reshdr' fields are left zeroed.  */
+       struct wim_header hdr;
 
-       /* The name of the WIM file (if any) that has been opened. */
-       tchar *filename;
+       /* If the library is currently writing this WIMStruct out to a file,
+        * then this is the header being created for that file.  */
+       struct wim_header out_hdr;
 
-       /* The lookup table for the WIM file. */
-       struct wim_lookup_table *lookup_table;
+       /* Array of image metadata, one for each image in the WIM (array length
+        * hdr.image_count).  Or, this will be NULL if this WIM does not contain
+        * metadata, which implies that this WIMStruct either represents part of
+        * a non-standalone WIM, or represents a standalone WIM that, oddly
+        * enough, actually contains 0 images.  */
+       struct wim_image_metadata **image_metadata;
 
-       /* Information retrieved from the XML data, arranged in an orderly
-        * manner. */
-       struct wim_info *wim_info;
+       /* Information from the XML data of the WIM file.  This information is
+        * also maintained for a WIMStruct not backed by a file.  */
+       struct wim_xml_info *xml_info;
+
+       /* The blob table for this WIMStruct.  If this WIMStruct has a backing
+        * file, then this table will index the blobs contained in that file.
+        * In addition, this table may index blobs that were added by updates or
+        * referenced from other WIMStructs.  */
+       struct blob_table *blob_table;
+
+       /* The number of references to this WIMStruct.  This is equal to the
+        * number of resource descriptors that reference this WIMStruct, plus 1
+        * if wimlib_free() still needs to be called.  */
+       ssize_t refcnt;
+
+       /*
+        * The 1-based index of the currently selected image in this WIMStruct,
+        * or WIMLIB_NO_IMAGE if no image is currently selected.
+        *
+        * The metadata for the current image is image_metadata[current_image -
+        * 1].  Since we load image metadata lazily, only the metadata for the
+        * current image is guaranteed to actually be present in memory.
+        */
+       int current_image;
 
-       /* Array of the image metadata, one for each image in the WIM. */
-       struct wim_image_metadata **image_metadata;
+       /* The absolute path to the on-disk file backing this WIMStruct, or NULL
+        * if this WIMStruct is not backed by an on-disk file.  */
+       tchar *filename;
 
-       /* The header of the WIM file. */
-       struct wim_header hdr;
+       /* If this WIMStruct has a backing file, then this is a file descriptor
+        * open to that file with read access.  Otherwise, this field is invalid
+        * (!filedes_valid(&in_fd)).  */
+       struct filedes in_fd;
 
-       /* Temporary field */
-       void *private;
+       /* If the library is currently writing this WIMStruct out to a file,
+        * then this is a file descriptor open to that file with write access.
+        * Otherwise, this field is invalid (!filedes_valid(&out_fd)).  */
+       struct filedes out_fd;
 
+       /*
+        * This is the cached decompressor for this WIM file, or NULL if no
+        * decompressor is cached yet.  Normally, all the compressed data in a
+        * WIM file has the same compression type and chunk size, so the same
+        * decompressor can be used for all data --- and that decompressor will
+        * be cached here.  However, if we do encounter any data with a
+        * different compression type or chunk size (this is possible in solid
+        * resources), then this cached decompressor will be replaced with a new
+        * one.
+        */
        struct wimlib_decompressor *decompressor;
        u8 decompressor_ctype;
        u32 decompressor_max_block_size;
 
-       struct list_head subwims;
-
-       struct list_head subwim_node;
-
-       /* The currently selected image, indexed starting at 1.  If not 0,
-        * subtract 1 from this to get the index of the current image in the
-        * image_metadata array. */
-       int current_image;
+       /* Temporary field; use sparingly  */
+       void *private;
 
-       /* Have any images been deleted? */
-       u8 deletion_occurred : 1;
+       /* 1 if any images have been deleted from this WIMStruct, otherwise 0 */
+       u8 image_deletion_occurred : 1;
 
-       /* Has the underlying WIM file been locked for appending?  */
+       /* 1 if the WIM file has been locked for appending, otherwise 0  */
        u8 locked_for_append : 1;
 
-       /* One of WIMLIB_COMPRESSION_TYPE_*, cached from the header flags. */
+       /* 1 if the WIM file is currently being compacted by wimlib_overwrite()
+        * with WIMLIB_WRITE_FLAG_UNSAFE_COMPACT  */
+       u8 being_compacted : 1;
+
+       /* If this WIM is backed by a file, then this is the compression type
+        * for non-solid resources in that file.  */
        u8 compression_type;
 
        /* Overridden compression type for wimlib_overwrite() or wimlib_write().
@@ -70,12 +132,12 @@ struct WIMStruct {
         * the same as compression_type.  */
        u8 out_compression_type;
 
-       /* Compression type for writing packed streams; can be set with
+       /* Compression type for writing solid resources; can be set with
         * wimlib_set_output_pack_compression_type().  */
-       u8 out_pack_compression_type;
+       u8 out_solid_compression_type;
 
-       /* Uncompressed size of compressed chunks in this WIM (cached from
-        * header).  */
+       /* If this WIM is backed by a file, then this is the compression chunk
+        * size for non-solid resources in that file.  */
        u32 chunk_size;
 
        /* Overridden chunk size for wimlib_overwrite() or wimlib_write().  Can
@@ -83,9 +145,9 @@ struct WIMStruct {
         * as chunk_size.  */
        u32 out_chunk_size;
 
-       /* Chunk size for writing packed streams; can be set with
+       /* Chunk size for writing solid resources; can be set with
         * wimlib_set_output_pack_chunk_size().  */
-       u32 out_pack_chunk_size;
+       u32 out_solid_chunk_size;
 
        /* Currently registered progress function for this WIMStruct, or NULL if
         * no progress function is currently registered for this WIMStruct.  */
@@ -93,36 +155,48 @@ struct WIMStruct {
        void *progctx;
 };
 
-static inline bool wim_is_pipable(const WIMStruct *wim)
+/*
+ * Return true if and only if the WIM contains image metadata (actual directory
+ * trees, not just a collection of blobs and their checksums).
+ *
+ * See the description of the 'image_metadata' field.  Note that we return true
+ * when the image count is 0 because it could be a WIM with 0 images.  It's only
+ * when the WIM does not contain the metadata described by its image count that
+ * we return false.
+ */
+static inline bool wim_has_metadata(const WIMStruct *wim)
 {
-       return (wim->hdr.magic == PWM_MAGIC);
+       return (wim->image_metadata != NULL || wim->hdr.image_count == 0);
 }
 
+/* Return true if and only if the WIM has an integrity table.
+ *
+ * If the WIM is not backed by a file, then this always returns false.  */
 static inline bool wim_has_integrity_table(const WIMStruct *wim)
 {
        return (wim->hdr.integrity_table_reshdr.offset_in_wim != 0);
 }
 
-static inline bool wim_has_metadata(const WIMStruct *wim)
+/* Return true if and only if the WIM is in pipable format.
+ *
+ * If the WIM is not backed by a file, then this always returns false.  */
+static inline bool wim_is_pipable(const WIMStruct *wim)
 {
-       return (wim->image_metadata != NULL || wim->hdr.image_count == 0);
+       return (wim->hdr.magic == PWM_MAGIC);
 }
 
-extern int
-set_wim_hdr_cflags(int ctype, struct wim_header *hdr);
+extern void
+finalize_wim_struct(WIMStruct *wim);
 
-extern int
-init_wim_header(struct wim_header *hdr, int ctype, u32 chunk_size);
+extern bool
+wim_has_solid_resources(const WIMStruct *wim);
 
 extern int
 read_wim_header(WIMStruct *wim, struct wim_header *hdr);
 
 extern int
-write_wim_header(const struct wim_header *hdr, struct filedes *out_fd);
-
-extern int
-write_wim_header_at_offset(const struct wim_header *hdr, struct filedes *out_fd,
-                          off_t offset);
+write_wim_header(const struct wim_header *hdr, struct filedes *out_fd,
+                off_t offset);
 
 extern int
 write_wim_header_flags(u32 hdr_flags, struct filedes *out_fd);
@@ -130,11 +204,17 @@ write_wim_header_flags(u32 hdr_flags, struct filedes *out_fd);
 extern int
 select_wim_image(WIMStruct *wim, int image);
 
+extern void
+deselect_current_wim_image(WIMStruct *wim);
+
 extern int
 for_image(WIMStruct *wim, int image, int (*visitor)(WIMStruct *));
 
 extern int
-wim_checksum_unhashed_streams(WIMStruct *wim);
+wim_checksum_unhashed_blobs(WIMStruct *wim);
+
+extern int
+delete_wim_image(WIMStruct *wim, int image);
 
 /* Internal open flags (pass to open_wim_as_WIMStruct(), not wimlib_open_wim())
  */