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