]> wimlib.net Git - wimlib/blobdiff - include/wimlib/lookup_table.h
Cleanup
[wimlib] / include / wimlib / lookup_table.h
index 746d744965718a9dc5090374cb8e74769a5600a3..f99f38d40a7b67e81610233d44ef45aa8120660d 100644 (file)
@@ -49,126 +49,93 @@ struct ntfs_location {
  *
  * If we open a WIM and read its lookup table, the location is set to
  * RESOURCE_IN_WIM since all the streams will initially be located in the WIM.
- * However, to deal with problems such as image capture and image mount, we
- * allow the actual location of the stream to be somewhere else, such as an
- * external file.
+ * However, to handle situations such as image capture and image mount, we allow
+ * the actual location of the stream to be somewhere else, such as an external
+ * file.
  */
 enum resource_location {
-       /* The lookup table entry does not correspond to a stream (this state
-        * should exist only temporarily) */
+       /* The lookup table entry does not yet correspond to a stream; this is a
+        * temporary state only.  */
        RESOURCE_NONEXISTENT = 0,
 
-       /* The stream resource is located in a WIM file.  The WIMStruct for the
-        * WIM file will be pointed to by the @wim member.  The compression type
-        * of the resource will be cached in @compression_type, and the pipable
-        * status of the resource will be cached in @pipable.  */
+       /* The stream is located in a resource in a WIM file identified by the
+        * `struct wim_resource_spec' pointed to by @rspec.  @offset_in_res
+        * identifies the offset at which this particular stream begins in the
+        * uncompressed data of the resource; this is normally 0, but in general
+        * a WIM resource may be "packed" and potentially contain multiple
+        * streams.  */
        RESOURCE_IN_WIM,
 
-       /* The stream resource is located in an external file.  The name of the
-        * file will be provided by @file_on_disk member.
-        *
-        * Note: On Windows @file_on_disk may actually specify a named data
-        * stream.  */
+       /* The stream is located in the external file named by @file_on_disk.
+        * On Windows, @file_on_disk may actually specify a named data stream
+        * (file path, then colon, then name of the stream).  */
        RESOURCE_IN_FILE_ON_DISK,
 
-       /* The stream resource is directly attached in an in-memory buffer
-        * pointed to by @attached_buffer.  */
+       /* The stream is directly attached in the in-memory buffer pointed to by
+        * @attached_buffer.  */
        RESOURCE_IN_ATTACHED_BUFFER,
 
 #ifdef WITH_FUSE
-       /* The stream resource is located in an external file in the staging
-        * directory for a read-write mount.  */
+       /* The stream is located in the external file named by
+        * @staging_file_name, located in the staging directory for a read-write
+        * mount.  */
        RESOURCE_IN_STAGING_FILE,
 #endif
 
 #ifdef WITH_NTFS_3G
-       /* The stream resource is located in an NTFS volume.  It is identified
-        * by volume, filename, data stream name, and by whether it is a reparse
-        * point or not. @ntfs_loc points to a structure containing this
-        * information.  */
+       /* The stream is located in an NTFS volume.  It is identified by volume,
+        * filename, data stream name, and by whether it is a reparse point or
+        * not.  @ntfs_loc points to a structure containing this information.
+        * */
        RESOURCE_IN_NTFS_VOLUME,
 #endif
 
 #ifdef __WIN32__
-       /* Windows only: the file is on disk in the file named @file_on_disk,
-        * but the file is encrypted and must be read using special functions.
-        * */
+       /* Windows only: the stream is located in the external file named by
+        * @file_on_disk, but the file is encrypted and must be read using the
+        * appropriate Windows API.  */
        RESOURCE_WIN32_ENCRYPTED,
 #endif
 
 };
 
-/*
- * An entry in the lookup table in the WIM file.
+/* Specification for a stream, which may be the contents of a file (unnamed data
+ * stream), a named data stream, reparse point data, or a WIM metadata resource.
  *
- * It is used to find data streams for files in the WIM.
- *
- * Metadata resources and reparse point data buffers will also have lookup table
- * entries associated with the data.
- *
- * The lookup_table_entry for a given dentry or alternate stream entry in the
- * WIM is found using the SHA1 message digest field.
- */
+ * One instance of this structure is created for each entry in the WIM's lookup
+ * table, hence the name of the struct.  Each of these entries contains the SHA1
+ * message digest of a stream and the location of the stream data in the WIM
+ * file (size, location, flags).  The in-memory lookup table is a map from SHA1
+ * message digests to stream locations.  */
 struct wim_lookup_table_entry {
 
-       /* List of lookup table entries in this hash bucket */
+       /* List node for a hash bucket of the lookup table.  */
        struct hlist_node hash_list;
 
-       /* Location and size of the stream in the WIM, whether it is compressed
-        * or not, and whether it's a metadata resource or not.  This is an
-        * on-disk field. */
-       struct resource_entry resource_entry;
+       /* Uncompressed size of this stream.  */
+       u64 size;
 
-       /* Specifies which part of the split WIM the resource is located in.
-        * This is on on-disk field.
-        *
-        * In stand-alone WIMs, this must be 1.
-        *
-        * In split WIMs, every split WIM part has its own lookup table, and in
-        * read_lookup_table() it's currently expected that the part number of
-        * each lookup table entry in a split WIM part's lookup table is the
-        * same as the part number of that split WIM part.  So this makes this
-        * field redundant since we store a pointer to the corresponding
-        * WIMStruct in the lookup table entry anyway.
-        */
-       u16 part_number;
+       /* Stream flags (WIM_RESHDR_FLAG_*).  */
+       u32 flags : 8;
 
-       /* One of the `enum resource_location' values documented above. */
-       u16 resource_location : 5;
-
-       /* 1 if this stream is a unique size (only set while writing streams). */
-       u16 unique_size : 1;
+       /* One of the `enum resource_location' values documented above.  */
+       u32 resource_location : 4;
 
        /* 1 if this stream has not had a SHA1 message digest calculated for it
-        * yet */
-       u16 unhashed : 1;
-
-       u16 deferred : 1;
+        * yet.  */
+       u32 unhashed : 1;
 
-       u16 no_progress : 1;
-
-       /* If resource_location == RESOURCE_IN_WIM, this will be a cached value
-        * that specifies the compression type of this stream as one of
-        * WIMLIB_COMPRESSION_TYPE_*.  Otherwise this will be 0, which is the
-        * same as WIMLIB_COMPRESSION_TYPE_NONE.  */
-       u16 compression_type : 2;
-
-       /* If resource_location == RESOURCE_IN_WIM, this flag will be set if the
-        * WIM is pipable and therefore the stream is in a slightly different
-        * format.  See comment above write_pipable_wim().  */
-       u16 is_pipable : 1;
+       /* Temoorary fields used when writing streams; set as documented for
+        * prepare_stream_list_for_write().  */
+       u32 unique_size : 1;
+       u32 will_be_in_output_wim : 1;
 
        /* Set to 1 when a metadata entry has its checksum changed; in such
-        * cases the hash is no longer valid to verify the data if the metadata
-        * resource is read again.  */
-       u16 dont_check_metadata_hash : 1;
-
-       /* (On-disk field)
-        * Number of times this lookup table entry is referenced by dentries.
-        * Unfortunately, this field is not always set correctly in Microsoft's
-        * WIMs, so we have no choice but to fix it if more references to the
-        * lookup table entry are found than stated here.  */
-       u32 refcnt;
+        * cases the hash cannot be used to verify the data if the metadata
+        * resource is read again.  (This could be avoided if we used separate
+        * fields for input/output checksum, but most stream entries wouldn't
+        * need this.)  */
+       u32 dont_check_metadata_hash : 1;
 
        union {
                /* (On-disk field) SHA1 message digest of the stream referenced
@@ -194,16 +161,37 @@ struct wim_lookup_table_entry {
                };
        };
 
-       /* When a WIM file is written, out_refcnt starts at 0 and is incremented
-        * whenever the stream pointed to by this lookup table entry needs to be
-        * written.  The stream only need to be written when out_refcnt is
-        * nonzero, since otherwise it is not referenced by any dentries. */
+       /* Number of times this lookup table entry is referenced by dentries in
+        * the WIM.  When a WIM's lookup table is read, this field is
+        * initialized from a corresponding entry; while it should be correct,
+        * in general it may not be.  wim_recalculate_refcnts() recalculates the
+        * reference counts for all streams and is run before doing any
+        * deletions.  */
+       u32 refcnt;
+
+       /* When a WIM file is written, this is set to the number of references
+        * (by dentries) to this stream in the output WIM file.
+        *
+        * During extraction, this is set to the number of times the stream must
+        * be extracted.
+        *
+        * During image export, this is set to the number of references of this
+        * stream that originated from the source WIM.  */
        u32 out_refcnt;
 
-       /* Pointers to somewhere where the stream is actually located.  See the
-        * comments for the @resource_location field above. */
+#ifdef WITH_FUSE
+       /* Number of times this stream has been opened; used only during
+        * mounting.  */
+       u16 num_opened_fds;
+#endif
+
+       /* Specification of where this stream is actually located.  Which member
+        * is valid is determined by the @resource_location field.  */
        union {
-               WIMStruct *wim;
+               struct {
+                       struct wim_resource_spec *rspec;
+                       u64 offset_in_res;
+               };
                tchar *file_on_disk;
                void *attached_buffer;
        #ifdef WITH_FUSE
@@ -214,64 +202,62 @@ struct wim_lookup_table_entry {
        #endif
        };
 
-       /* Actual reference count to this stream (only used while
-        * verifying an image). */
-       u32 real_refcnt;
-
-       union {
-       #ifdef WITH_FUSE
-               /* Number of times this stream has been opened (used only during
-                * mounting) */
-               u16 num_opened_fds;
-       #endif
+       /* Links together streams that share the same underlying WIM resource.
+        * The head is the `stream_list' member of `struct wim_resource_spec'.
+        */
+       struct list_head rspec_node;
 
-               /* This field is used for the special hardlink or symlink image
-                * extraction mode.   In these mode, all identical files are linked
-                * together, and @extracted_file will be set to the filename of the
-                * first extracted file containing this stream.  */
-               tchar *extracted_file;
-       };
+       /* This field is used during the hardlink and symlink image extraction
+        * modes.   In these modes, all identical files are linked together, and
+        * @extracted_file will be set to the filename of the first extracted
+        * file containing this stream.  */
+       tchar *extracted_file;
 
        /* Temporary fields  */
        union {
-               /* Used temporarily during WIM file writing  */
+               /* Fields used temporarily during WIM file writing.  */
                struct {
-                       struct hlist_node hash_list_2;
+                       union {
+                               /* List node used for stream size table.  */
+                               struct hlist_node hash_list_2;
+
+                               /* Metadata for the underlying packed resource
+                                * in the WIM being written (only valid if
+                                * WIM_RESHDR_FLAG_PACKED_STREAMS set in
+                                * out_reshdr.flags).  */
+                               struct {
+                                       u64 out_res_offset_in_wim;
+                                       u64 out_res_size_in_wim;
+                               };
+                       };
 
                        /* Links streams being written to the WIM.  */
                        struct list_head write_streams_list;
-               };
 
-               /* Used temporarily during WIM file writing (after above)  */
-               struct {
-                       struct list_head msg_list;
-                       struct list_head being_compressed_list;
+                       /* Metadata for this stream in the WIM being written.
+                        */
+                       struct wim_reshdr out_reshdr;
                };
 
-               /* When a WIM file is written, @output_resource_entry is filled
-                * in with the resource entry for the output WIM.  This will not
-                * necessarily be the same as the @resource_entry since:
-                * - The stream may have a different offset in the new WIM
-                * - The stream may have a different compressed size in the new
-                *   WIM if the compression type changed
-                */
-               struct resource_entry output_resource_entry;
-
-
                /* Used temporarily during extraction  */
                union {
-                       /* out_refcnt tracks number of slots filled */
-                       struct wim_dentry *inline_lte_dentries[4];
+                       /* Dentries to extract that reference this stream.
+                        * out_refcnt tracks the number of slots filled.  */
+                       struct wim_dentry *inline_lte_dentries[7];
                        struct {
                                struct wim_dentry **lte_dentries;
-                               unsigned long alloc_lte_dentries;
+                               size_t alloc_lte_dentries;
                        };
                };
+
+               /* Actual reference count to this stream (only used while
+                * verifying an image).  */
+               u32 real_refcnt;
        };
 
-       /* Temporary list fields */
+       /* Temporary list fields */
        union {
-               /* Links streams when writing lookup table.  */
+               /* Links streams for writing lookup table.  */
                struct list_head lookup_table_list;
 
                /* Links streams being extracted.  */
@@ -281,34 +267,16 @@ struct wim_lookup_table_entry {
                struct list_head export_stream_list;
        };
 
-       /* Links streams that are still unhashed after being been added
-        * to a WIM.  */
+       /* Links streams that are still unhashed after being been added to a
+        * WIM.  */
        struct list_head unhashed_list;
 };
 
-static inline u64
-wim_resource_size(const struct wim_lookup_table_entry *lte)
-{
-       return lte->resource_entry.original_size;
-}
-
-static inline u64
-wim_resource_chunks(const struct wim_lookup_table_entry *lte)
-{
-       return DIV_ROUND_UP(wim_resource_size(lte), WIM_CHUNK_SIZE);
-}
-
-static inline u64
-wim_resource_compressed_size(const struct wim_lookup_table_entry *lte)
-{
-       return lte->resource_entry.size;
-}
-
-static inline int
-wim_resource_compression_type(const struct wim_lookup_table_entry *lte)
+static inline bool
+lte_is_partial(const struct wim_lookup_table_entry * lte)
 {
-       BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_NONE != 0);
-       return lte->compression_type;
+       return lte->resource_location == RESOURCE_IN_WIM &&
+              lte->size != lte->rspec->uncompressed_size;
 }
 
 static inline bool
@@ -331,9 +299,12 @@ extern int
 read_wim_lookup_table(WIMStruct *wim);
 
 extern int
-write_wim_lookup_table(WIMStruct *wim, int image, int write_flags,
-                      struct resource_entry *out_res_entry,
-                      struct list_head *stream_list_override);
+write_wim_lookup_table_from_stream_list(struct list_head *stream_list,
+                                       struct filedes *out_fd,
+                                       u16 part_number,
+                                       struct wim_reshdr *out_reshdr,
+                                       int write_resource_flags,
+                                       struct wimlib_lzx_context **comp_ctx);
 
 extern void
 free_lookup_table(struct wim_lookup_table *table);
@@ -341,7 +312,7 @@ free_lookup_table(struct wim_lookup_table *table);
 extern void
 lookup_table_insert(struct wim_lookup_table *table, struct wim_lookup_table_entry *lte);
 
-/* Unlinks a lookup table entry from the table; does not free it. */
+/* Unlinks a lookup table entry from the table; does not free it.  */
 static inline void
 lookup_table_unlink(struct wim_lookup_table *table, struct wim_lookup_table_entry *lte)
 {
@@ -359,8 +330,7 @@ clone_lookup_table_entry(const struct wim_lookup_table_entry *lte)
                        _malloc_attribute;
 
 extern void
-print_lookup_table_entry(const struct wim_lookup_table_entry *entry,
-                        FILE *out);
+print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out);
 
 extern void
 free_lookup_table_entry(struct wim_lookup_table_entry *lte);
@@ -374,6 +344,11 @@ for_lookup_table_entry(struct wim_lookup_table *table,
                       int (*visitor)(struct wim_lookup_table_entry *, void *),
                       void *arg);
 
+extern int
+sort_stream_list(struct list_head *stream_list,
+                size_t list_head_offset,
+                int (*compar)(const void *, const void*));
+
 extern int
 sort_stream_list_by_sequential_order(struct list_head *stream_list,
                                     size_t list_head_offset);
@@ -385,12 +360,14 @@ for_lookup_table_entry_pos_sorted(struct wim_lookup_table *table,
                                  void *arg);
 
 extern struct wim_lookup_table_entry *
-__lookup_resource(const struct wim_lookup_table *table, const u8 hash[]);
+lookup_resource(const struct wim_lookup_table *table, const u8 hash[]);
 
 extern int
-lookup_resource(WIMStruct *wim, const tchar *path,
-               int lookup_flags, struct wim_dentry **dentry_ret,
-               struct wim_lookup_table_entry **lte_ret, u16 *stream_idx_ret);
+wim_pathname_to_stream(WIMStruct *wim, const tchar *path,
+                      int lookup_flags,
+                      struct wim_dentry **dentry_ret,
+                      struct wim_lookup_table_entry **lte_ret,
+                      u16 *stream_idx_ret);
 
 extern void
 lte_decrement_refcnt(struct wim_lookup_table_entry *lte,
@@ -401,23 +378,36 @@ lte_decrement_num_opened_fds(struct wim_lookup_table_entry *lte);
 #endif
 
 extern int
-lte_zero_out_refcnt(struct wim_lookup_table_entry *entry, void *ignore);
+lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *ignore);
 
 extern int
-lte_zero_real_refcnt(struct wim_lookup_table_entry *entry, void *ignore);
+lte_zero_real_refcnt(struct wim_lookup_table_entry *lte, void *ignore);
 
 extern int
 lte_free_extracted_file(struct wim_lookup_table_entry *lte, void *ignore);
 
-extern void
-lte_init_wim(struct wim_lookup_table_entry *lte, WIMStruct *wim);
+static inline void
+lte_bind_wim_resource_spec(struct wim_lookup_table_entry *lte,
+                          struct wim_resource_spec *rspec)
+{
+       lte->resource_location = RESOURCE_IN_WIM;
+       lte->rspec = rspec;
+       list_add_tail(&lte->rspec_node, &rspec->stream_list);
+}
+
+static inline void
+lte_unbind_wim_resource_spec(struct wim_lookup_table_entry *lte)
+{
+       list_del(&lte->rspec_node);
+       lte->resource_location = RESOURCE_NONEXISTENT;
+}
 
 extern int
 inode_resolve_ltes(struct wim_inode *inode, struct wim_lookup_table *table,
                   bool force);
 
 extern int
-resource_not_found_error(struct wim_inode *inode, const u8 *hash);
+resource_not_found_error(const struct wim_inode *inode, const u8 *hash);
 
 extern void
 inode_unresolve_ltes(struct wim_inode *inode);
@@ -442,9 +432,9 @@ inode_stream_lte_unresolved(const struct wim_inode *inode, unsigned stream_idx,
        if (!table)
                return NULL;
        if (stream_idx == 0)
-               return __lookup_resource(table, inode->i_hash);
+               return lookup_resource(table, inode->i_hash);
        else
-               return __lookup_resource(table,
+               return lookup_resource(table,
                                         inode->i_ads_entries[
                                                stream_idx - 1].hash);
 }
@@ -502,6 +492,9 @@ inode_stream_name_nbytes(const struct wim_inode *inode, unsigned stream_idx)
                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);
 
@@ -512,9 +505,8 @@ inode_unnamed_lte_unresolved(const struct wim_inode *inode,
 extern struct wim_lookup_table_entry *
 inode_unnamed_lte(const struct wim_inode *inode, const struct wim_lookup_table *table);
 
-extern u64
-lookup_table_total_stream_size(struct wim_lookup_table *table);
-
+extern const u8 *
+inode_unnamed_stream_hash(const struct wim_inode *inode);
 
 static inline void
 lookup_table_insert_unhashed(struct wim_lookup_table *table,