]> wimlib.net Git - wimlib/blob - include/wimlib/resource.h
Heuristic sorting of streams for solid compression
[wimlib] / include / wimlib / resource.h
1 #ifndef _WIMLIB_RESOURCE_H
2 #define _WIMLIB_RESOURCE_H
3
4 #include "wimlib/callback.h"
5 #include "wimlib/list.h"
6 #include "wimlib/sha1.h"
7 #include "wimlib/types.h"
8
9 struct filedes;
10 struct wim_lookup_table_entry;
11 struct wim_image_metadata;
12
13 /*
14  * Specification of a resource in a WIM file.
15  *
16  * If a `struct wim_lookup_table_entry' lte has (lte->resource_location ==
17  * RESOURCE_IN_WIM), then lte->rspec points to an instance of this structure.
18  *
19  * Normally, there is a one-to-one correspondence between lookup table entries
20  * ("streams", each of which may be the contents of a file, for example) and
21  * resources.  However, a resource with the WIM_RESHDR_FLAG_SOLID flag set is a
22  * "solid" resource that may contain multiple streams compressed together.
23  */
24 struct wim_resource_spec {
25         /* The WIM containing this resource.  @wim->in_fd is expected to be a
26          * file descriptor to the underlying WIM file, opened for reading.  */
27         WIMStruct *wim;
28
29         /* The offset, in bytes, from the start of WIM file at which this
30          * resource starts.  */
31         u64 offset_in_wim;
32
33         /* The size of this resource in the WIM file.  For compressed resources
34          * this is the compressed size, including overhead such as the chunk
35          * table.  */
36         u64 size_in_wim;
37
38         /* The number of bytes of uncompressed data this resource decompresses
39          * to.  */
40         u64 uncompressed_size;
41
42         /* The list of streams this resource contains.  */
43         struct list_head stream_list;
44
45         /* Flags for this resource (WIM_RESHDR_FLAG_*).  */
46         u32 flags : 8;
47
48         /* [wimlib extension] This flag will be set if the WIM is pipable.  In
49          * such cases, the resource will be in a slightly different format if it
50          * is compressed.  */
51         u32 is_pipable : 1;
52
53         /* Temporary flag.  */
54         u32 raw_copy_ok : 1;
55
56         /* Compression type of this resource.  */
57         u32 compression_type : 22;
58
59         /* Compression chunk size of this resource.  Irrelevant if the resource
60          * is uncompressed.  */
61         u32 chunk_size;
62 };
63
64 /* On-disk version of a WIM resource header.  */
65 struct wim_reshdr_disk {
66         /* Size of the resource as it appears in the WIM file (possibly
67          * compressed).  */
68         u8 size_in_wim[7];
69
70         /* Zero or more of the WIM_RESHDR_FLAG_* flags.  These indicate, for
71          * example, whether the resource is compressed or not.  */
72         u8 flags;
73
74         /* Offset of the resource from the start of the WIM file, in bytes.  */
75         le64 offset_in_wim;
76
77         /* Uncompressed size of the resource, in bytes.  */
78         le64 uncompressed_size;
79 } _packed_attribute;
80
81 /* In-memory version of a WIM resource header (`struct wim_reshdr_disk').  */
82 struct wim_reshdr {
83         u64 size_in_wim : 56;
84         u64 flags : 8;
85         u64 offset_in_wim;
86         u64 uncompressed_size;
87 };
88
89 /* Flags for the `flags' field of WIM resource headers (`struct wim_reshdr').
90  */
91
92 /* Unknown meaning; may be intended to indicate spaces in the WIM that are free
93  * to overwrite.  Currently ignored by wimlib.  */
94 #define WIM_RESHDR_FLAG_FREE            0x01
95
96 /* The resource is a metadata resource for a WIM image, or is the lookup table
97  * or XML data for the WIM.  */
98 #define WIM_RESHDR_FLAG_METADATA        0x02
99
100 /* The resource is a non-solid resource compressed using the WIM's default
101  * compression type.  */
102 #define WIM_RESHDR_FLAG_COMPRESSED      0x04
103
104 /* Unknown meaning; may be intended to indicate a partial stream.  Currently
105  * ignored by wimlib.  */
106 #define WIM_RESHDR_FLAG_SPANNED         0x08
107
108 /* The resource is a solid compressed resource which may contain multiple
109  * streams.  This flag is only allowed if the WIM version number is
110  * WIM_VERSION_SOLID.  */
111 #define WIM_RESHDR_FLAG_SOLID           0x10
112
113 /* Magic number in the 'uncompressed_size' field of the resource header that
114  * identifies the main entry for a solid resource.  */
115 #define SOLID_RESOURCE_MAGIC_NUMBER     0x100000000ULL
116
117 /* Returns true if the specified WIM resource is compressed (may be either solid
118  * or non-solid)  */
119 static inline bool
120 resource_is_compressed(const struct wim_resource_spec *rspec)
121 {
122         return (rspec->flags & (WIM_RESHDR_FLAG_COMPRESSED |
123                                 WIM_RESHDR_FLAG_SOLID));
124 }
125
126 static inline void
127 copy_reshdr(struct wim_reshdr *dest, const struct wim_reshdr *src)
128 {
129         memcpy(dest, src, sizeof(struct wim_reshdr));
130 }
131
132 static inline void
133 zero_reshdr(struct wim_reshdr *reshdr)
134 {
135         memset(reshdr, 0, sizeof(struct wim_reshdr));
136 }
137
138 extern void
139 wim_res_hdr_to_spec(const struct wim_reshdr *reshdr, WIMStruct *wim,
140                     struct wim_resource_spec *rspec);
141
142 extern void
143 wim_res_spec_to_hdr(const struct wim_resource_spec *rspec,
144                     struct wim_reshdr *reshdr);
145
146 extern void
147 get_wim_reshdr(const struct wim_reshdr_disk *disk_reshdr,
148                struct wim_reshdr *reshdr);
149
150 void
151 put_wim_reshdr(const struct wim_reshdr *reshdr,
152                struct wim_reshdr_disk *disk_reshdr);
153
154 /* Alternate chunk table format for resources with WIM_RESHDR_FLAG_SOLID set.
155  */
156 struct alt_chunk_table_header_disk {
157         /* Uncompressed size of the resource in bytes.  */
158         le64 res_usize;
159
160         /* Number of bytes each compressed chunk decompresses into, except
161          * possibly the last which decompresses into the remainder.  This
162          * overrides the chunk size specified by the WIM header.  */
163         le32 chunk_size;
164
165         /* Compression format used for compressed chunks:
166          * 0 = None
167          * 1 = XPRESS
168          * 2 = LZX
169          * 3 = LZMS
170          *
171          * This overrides the compression type specified by the WIM header.  */
172         le32 compression_format;
173
174         /* This header is directly followed by a table of compressed sizes of
175          * the chunks (4 bytes per entry).  */
176 } _packed_attribute;
177
178 static inline unsigned int
179 get_chunk_entry_size(u64 res_size, bool is_alt)
180 {
181         if (res_size <= UINT32_MAX || is_alt)
182                 return 4;
183         else
184                 return 8;
185 }
186
187 /* Functions to read streams  */
188
189 extern int
190 read_partial_wim_stream_into_buf(const struct wim_lookup_table_entry *lte,
191                                  size_t size, u64 offset, void *buf);
192
193 extern int
194 read_full_stream_into_buf(const struct wim_lookup_table_entry *lte, void *buf);
195
196 extern int
197 read_full_stream_into_alloc_buf(const struct wim_lookup_table_entry *lte,
198                                 void **buf_ret);
199
200 extern int
201 wim_reshdr_to_data(const struct wim_reshdr *reshdr,
202                    WIMStruct *wim, void **buf_ret);
203
204 extern int
205 wim_reshdr_to_hash(const struct wim_reshdr *reshdr, WIMStruct *wim,
206                    u8 hash[SHA1_HASH_SIZE]);
207
208 extern int
209 skip_wim_stream(struct wim_lookup_table_entry *lte);
210
211 /*
212  * Type of callback function for beginning to read a stream.
213  *
214  * @lte:
215  *      Stream that is about to be read.
216  *
217  * @ctx:
218  *      User-provided context.
219  *
220  * Must return 0 on success, a positive error code on failure, or the special
221  * value BEGIN_STREAM_STATUS_SKIP_STREAM to indicate that the stream should not
222  * be read, and read_stream_list() should continue on to the next stream
223  * (without calling @consume_chunk or @end_stream).
224  */
225 typedef int (*read_stream_list_begin_stream_t)(struct wim_lookup_table_entry *lte,
226                                                void *ctx);
227
228 #define BEGIN_STREAM_STATUS_SKIP_STREAM -1
229
230 /*
231  * Type of callback function for finishing reading a stream.
232  *
233  * @lte:
234  *      Stream that has been fully read, or stream that started being read but
235  *      could not be fully read due to a read error.
236  *
237  * @status:
238  *      0 if reading the stream was successful; otherwise a nonzero error code
239  *      that specifies the return status.
240  *
241  * @ctx:
242  *      User-provided context.
243  */
244 typedef int (*read_stream_list_end_stream_t)(struct wim_lookup_table_entry *lte,
245                                              int status,
246                                              void *ctx);
247
248
249 /* Callback functions and contexts for read_stream_list().  */
250 struct read_stream_list_callbacks {
251
252         /* Called when a stream is about to be read.  */
253         read_stream_list_begin_stream_t begin_stream;
254
255         /* Called when a chunk of data has been read.  */
256         consume_data_callback_t consume_chunk;
257
258         /* Called when a stream has been fully read.  A successful call to
259          * @begin_stream will always be matched by a call to @end_stream.  */
260         read_stream_list_end_stream_t end_stream;
261
262         /* Parameter passed to @begin_stream.  */
263         void *begin_stream_ctx;
264
265         /* Parameter passed to @consume_chunk.  */
266         void *consume_chunk_ctx;
267
268         /* Parameter passed to @end_stream.  */
269         void *end_stream_ctx;
270 };
271
272 /* Flags for read_stream_list()  */
273 #define VERIFY_STREAM_HASHES            0x1
274 #define COMPUTE_MISSING_STREAM_HASHES   0x2
275 #define STREAM_LIST_ALREADY_SORTED      0x4
276
277 extern int
278 read_stream_list(struct list_head *stream_list,
279                  size_t list_head_offset,
280                  const struct read_stream_list_callbacks *cbs,
281                  int flags);
282
283 /* Functions to extract streams.  */
284
285 extern int
286 extract_stream(struct wim_lookup_table_entry *lte,
287                u64 size,
288                consume_data_callback_t extract_chunk,
289                void *extract_chunk_arg);
290
291 extern int
292 extract_stream_to_fd(struct wim_lookup_table_entry *lte,
293                      struct filedes *fd, u64 size);
294
295 extern int
296 extract_full_stream_to_fd(struct wim_lookup_table_entry *lte,
297                           struct filedes *fd);
298
299 /* Miscellaneous stream functions.  */
300
301 extern int
302 sha1_stream(struct wim_lookup_table_entry *lte);
303
304 /* Functions to read/write metadata resources.  */
305
306 extern int
307 read_metadata_resource(struct wim_image_metadata *imd);
308
309 extern int
310 write_metadata_resource(WIMStruct *wim, int image, int write_resource_flags);
311
312 /* Definitions specific to pipable WIM resources.  */
313
314 /* Arbitrary number to begin each stream in the pipable WIM, used for sanity
315  * checking.  */
316 #define PWM_STREAM_MAGIC 0x2b9b9ba2443db9d8ULL
317
318 /* Header that precedes each resource in a pipable WIM.  */
319 struct pwm_stream_hdr {
320         le64 magic;                     /* +0   */
321         le64 uncompressed_size;         /* +8   */
322         u8 hash[SHA1_HASH_SIZE];        /* +16  */
323         le32 flags;                     /* +36  */
324                                         /* +40  */
325 } _packed_attribute;
326
327 /* Extra flag for the @flags field in `struct pipable_wim_stream_hdr': Indicates
328  * that the SHA1 message digest of the stream has not been calculated.
329  * Currently only used for the XML data.  */
330 #define PWM_RESHDR_FLAG_UNHASHED         0x100
331
332 /* Header that precedes each chunk of a compressed resource in a pipable WIM.
333  */
334 struct pwm_chunk_hdr {
335         le32 compressed_size;
336 } _packed_attribute;
337
338 #endif /* _WIMLIB_RESOURCE_H */