]> wimlib.net Git - wimlib/blob - include/wimlib/resource.h
v1.14.4
[wimlib] / include / wimlib / resource.h
1 #ifndef _WIMLIB_RESOURCE_H
2 #define _WIMLIB_RESOURCE_H
3
4 #include "wimlib/list.h"
5 #include "wimlib/sha1.h"
6 #include "wimlib/types.h"
7
8 struct blob_descriptor;
9 struct filedes;
10 struct wim_image_metadata;
11
12 /*
13  * Description of a "resource" in a WIM file.  A "resource" is a standalone,
14  * possibly compressed region of data.  Normally, there is a one-to-one
15  * correspondence between "blobs" (each of which may be the contents of a file,
16  * for example) and resources.  However, a resource with the
17  * WIM_RESHDR_FLAG_SOLID flag set is a "solid" resource that contains multiple
18  * blobs compressed together.
19  */
20 struct wim_resource_descriptor {
21         /* The WIM containing this resource.  @wim->in_fd is expected to be a
22          * file descriptor to the underlying WIM file, opened for reading.  */
23         WIMStruct *wim;
24
25         /* The offset, in bytes, from the start of WIM file at which this
26          * resource starts.  */
27         u64 offset_in_wim;
28
29         /* The size of this resource in the WIM file.  For compressed resources
30          * this is the compressed size, including overhead such as the chunk
31          * table.  */
32         u64 size_in_wim;
33
34         /* The number of bytes of uncompressed data this resource decompresses
35          * to.  */
36         u64 uncompressed_size;
37
38         /* The list of blobs this resource contains.  */
39         struct list_head blob_list;
40
41         /* Flags for this resource (WIM_RESHDR_FLAG_*).  */
42         u32 flags : 8;
43
44         /* [wimlib extension] This flag will be set if the WIM is pipable.  In
45          * such cases, the resource will be in a slightly different format if it
46          * is compressed.  */
47         u32 is_pipable : 1;
48
49         /* Temporary flag.  */
50         u32 raw_copy_ok : 1;
51
52         /* Compression type of this resource.  */
53         u32 compression_type : 22;
54
55         /* Compression chunk size of this resource.  Irrelevant if the resource
56          * is uncompressed.  */
57         u32 chunk_size;
58 };
59
60 /* On-disk version of a WIM resource header.  */
61 struct wim_reshdr_disk {
62         /* Size of the resource as it appears in the WIM file (possibly
63          * compressed).  */
64         u8 size_in_wim[7];
65
66         /* Zero or more of the WIM_RESHDR_FLAG_* flags.  These indicate, for
67          * example, whether the resource is compressed or not.  */
68         u8 flags;
69
70         /* Offset of the resource from the start of the WIM file, in bytes.  */
71         le64 offset_in_wim;
72
73         /* Uncompressed size of the resource, in bytes.  */
74         le64 uncompressed_size;
75 } _packed_attribute;
76
77 /* In-memory version of a WIM resource header (`struct wim_reshdr_disk').  */
78 struct wim_reshdr {
79         u64 size_in_wim : 56;
80         u64 flags : 8;
81         u64 offset_in_wim;
82         u64 uncompressed_size;
83 };
84
85 /* Flags for the `flags' field of WIM resource headers (`struct wim_reshdr').
86  */
87
88 /* Unknown meaning; currently ignored by wimlib.  */
89 #define WIM_RESHDR_FLAG_FREE            0x01
90
91 /* The resource is a metadata resource for a WIM image, or is the blob table or
92  * XML data for the WIM.  */
93 #define WIM_RESHDR_FLAG_METADATA        0x02
94
95 /* The resource is a non-solid resource compressed using the WIM's default
96  * compression type.  */
97 #define WIM_RESHDR_FLAG_COMPRESSED      0x04
98
99 /* Unknown meaning; currently ignored by wimlib.  */
100 #define WIM_RESHDR_FLAG_SPANNED         0x08
101
102 /* The resource is a solid compressed resource which may contain multiple blobs.
103  * This flag is only allowed if the WIM version number is WIM_VERSION_SOLID.  */
104 #define WIM_RESHDR_FLAG_SOLID           0x10
105
106 /* Magic number in the 'uncompressed_size' field of the resource header that
107  * identifies the main entry for a solid resource.  */
108 #define SOLID_RESOURCE_MAGIC_NUMBER     0x100000000ULL
109
110 static inline void
111 copy_reshdr(struct wim_reshdr *dest, const struct wim_reshdr *src)
112 {
113         memcpy(dest, src, sizeof(struct wim_reshdr));
114 }
115
116 static inline void
117 zero_reshdr(struct wim_reshdr *reshdr)
118 {
119         memset(reshdr, 0, sizeof(struct wim_reshdr));
120 }
121
122 extern void
123 wim_reshdr_to_desc(const struct wim_reshdr *reshdr, WIMStruct *wim,
124                    struct wim_resource_descriptor *rdesc);
125
126 extern void
127 wim_reshdr_to_desc_and_blob(const struct wim_reshdr *reshdr, WIMStruct *wim,
128                             struct wim_resource_descriptor *rdesc,
129                             struct blob_descriptor *blob);
130
131 extern void
132 get_wim_reshdr(const struct wim_reshdr_disk *disk_reshdr,
133                struct wim_reshdr *reshdr);
134
135 extern void
136 put_wim_reshdr(const struct wim_reshdr *reshdr,
137                struct wim_reshdr_disk *disk_reshdr);
138
139 /* Alternate chunk table format for resources with WIM_RESHDR_FLAG_SOLID set.
140  */
141 struct alt_chunk_table_header_disk {
142         /* Uncompressed size of the resource in bytes.  */
143         le64 res_usize;
144
145         /* Number of bytes each compressed chunk decompresses into, except
146          * possibly the last which decompresses into the remainder.  This
147          * overrides the chunk size specified by the WIM header.  */
148         le32 chunk_size;
149
150         /* Compression format used for compressed chunks:
151          * 0 = None
152          * 1 = XPRESS
153          * 2 = LZX
154          * 3 = LZMS
155          *
156          * This overrides the compression type specified by the WIM header.  */
157         le32 compression_format;
158
159         /* This header is directly followed by a table of compressed sizes of
160          * the chunks (4 bytes per entry).  */
161 } _packed_attribute;
162
163 static inline unsigned int
164 get_chunk_entry_size(u64 res_size, bool is_alt)
165 {
166         if (res_size <= UINT32_MAX || is_alt)
167                 return 4;
168         else
169                 return 8;
170 }
171
172 /* Functions to read blobs  */
173
174 extern int
175 read_partial_wim_blob_into_buf(const struct blob_descriptor *blob,
176                                u64 offset, size_t size, void *buf);
177
178 extern int
179 read_blob_into_buf(const struct blob_descriptor *blob, void *buf);
180
181 extern int
182 read_blob_into_alloc_buf(const struct blob_descriptor *blob, void **buf_ret);
183
184 extern int
185 wim_reshdr_to_data(const struct wim_reshdr *reshdr, WIMStruct *wim,
186                    void **buf_ret);
187
188 extern int
189 wim_reshdr_to_hash(const struct wim_reshdr *reshdr, WIMStruct *wim,
190                    u8 hash[SHA1_HASH_SIZE]);
191
192 extern int
193 skip_wim_resource(const struct wim_resource_descriptor *rdesc);
194
195 /*
196  * Callback function for reading chunks.  Called whenever the next chunk of
197  * uncompressed data is available, passing 'ctx' as the last argument. 'size' is
198  * guaranteed to be nonzero.  Must return 0 on success, or a positive wimlib
199  * error code on failure.
200  */
201 struct consume_chunk_callback {
202         int (*func)(const void *chunk, size_t size, void *ctx);
203         void *ctx;
204 };
205
206 /* Pass a chunk of data to the specified consume_chunk callback */
207 static inline int
208 consume_chunk(const struct consume_chunk_callback *cb,
209               const void *chunk, size_t size)
210 {
211         return (*cb->func)(chunk, size, cb->ctx);
212 }
213
214 /* Callback functions for reading blobs  */
215 struct read_blob_callbacks {
216
217         /* Called when starting to read a blob.  Must return 0 on success, or a
218          * positive wimlib error code on failure, or in the case of
219          * read_blob_list(), the special value BEGIN_BLOB_STATUS_SKIP_BLOB which
220          * indicates that the data for this blob should not be read.  */
221         int (*begin_blob)(struct blob_descriptor *blob, void *ctx);
222 #define BEGIN_BLOB_STATUS_SKIP_BLOB     (-1)
223
224         /* Called when the next chunk of uncompressed data is available.  'size'
225          * is guaranteed to be nonzero.  Must return 0 on success, or a positive
226          * wimlib error code on failure.  */
227         int (*continue_blob)(const struct blob_descriptor *blob, u64 offset,
228                              const void *chunk, size_t size, void *ctx);
229
230         /* Called when a blob has been successfully read (status=0), or when
231          * begin_blob() was successfully called but an error occurred before the
232          * blob was fully read (status != 0; in this case the implementation
233          * should do cleanup and then pass on the status).  Must return 0 on
234          * success, or a positive wimlib error code on failure.  */
235         int (*end_blob)(struct blob_descriptor *blob, int status, void *ctx);
236
237         /* Parameter passed to each of the callback functions.  */
238         void *ctx;
239 };
240
241 /* Call cbs->begin_blob() if present.  */
242 static inline int
243 call_begin_blob(struct blob_descriptor *blob,
244                 const struct read_blob_callbacks *cbs)
245 {
246         if (!cbs->begin_blob)
247                 return 0;
248         return (*cbs->begin_blob)(blob, cbs->ctx);
249 }
250
251 /* Call cbs->continue_blob() if present.  */
252 static inline int
253 call_continue_blob(const struct blob_descriptor *blob, u64 offset,
254                    const void *chunk, size_t size,
255                    const struct read_blob_callbacks *cbs)
256 {
257         if (!cbs->continue_blob)
258                 return 0;
259         return (*cbs->continue_blob)(blob, offset, chunk, size, cbs->ctx);
260 }
261
262 /* Call cbs->end_blob() if present.  */
263 static inline int
264 call_end_blob(struct blob_descriptor *blob, int status,
265               const struct read_blob_callbacks *cbs)
266 {
267         if (!cbs->end_blob)
268                 return status;
269         return (*cbs->end_blob)(blob, status, cbs->ctx);
270 }
271
272 /* Flags for read_blob_list()  */
273 #define VERIFY_BLOB_HASHES              0x1
274 #define COMPUTE_MISSING_BLOB_HASHES     0x2
275 #define BLOB_LIST_ALREADY_SORTED        0x4
276 #define RECOVER_DATA                    0x8
277
278 extern int
279 read_blob_list(struct list_head *blob_list, size_t list_head_offset,
280                const struct read_blob_callbacks *cbs, int flags);
281
282 extern int
283 read_blob_with_cbs(struct blob_descriptor *blob,
284                    const struct read_blob_callbacks *cbs, bool recover_data);
285
286 extern int
287 read_blob_with_sha1(struct blob_descriptor *blob,
288                     const struct read_blob_callbacks *cbs, bool recover_data);
289
290 extern int
291 extract_blob_prefix_to_fd(struct blob_descriptor *blob, u64 size,
292                           struct filedes *fd);
293
294 extern int
295 extract_blob_to_fd(struct blob_descriptor *blob, struct filedes *fd,
296                    bool recover_data);
297
298 /* Miscellaneous blob functions.  */
299
300 extern int
301 sha1_blob(struct blob_descriptor *blob);
302
303 /* Functions to read/write metadata resources.  */
304
305 extern int
306 read_metadata_resource(struct wim_image_metadata *imd);
307
308 extern int
309 write_metadata_resource(WIMStruct *wim, int image, int write_resource_flags);
310
311 /* Definitions specific to pipable WIM resources.  */
312
313 /* Arbitrary number to begin each blob in the pipable WIM, used for sanity
314  * checking.  */
315 #define PWM_BLOB_MAGIC 0x2b9b9ba2443db9d8ULL
316
317 /* Header that precedes each blob in a pipable WIM.  */
318 struct pwm_blob_hdr {
319         le64 magic;                     /* +0   */
320         le64 uncompressed_size;         /* +8   */
321         u8 hash[SHA1_HASH_SIZE];        /* +16  */
322         le32 flags;                     /* +36  */
323                                         /* +40  */
324 } _packed_attribute;
325
326 /* Header that precedes each chunk of a compressed resource in a pipable WIM.
327  */
328 struct pwm_chunk_hdr {
329         le32 compressed_size;
330 } _packed_attribute;
331
332 #endif /* _WIMLIB_RESOURCE_H */