2fea2f579048759ce3d9b5c9784603b316694ce8
[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 /* Callback functions for reading blobs  */
196 struct read_blob_callbacks {
197
198         /* Called when starting to read a blob.  Must return 0 on success, or a
199          * positive wimlib error code on failure, or in the case of
200          * read_blob_list(), the special value BEGIN_BLOB_STATUS_SKIP_BLOB which
201          * indicates that the data for this blob should not be read.  */
202         int (*begin_blob)(struct blob_descriptor *blob, void *ctx);
203 #define BEGIN_BLOB_STATUS_SKIP_BLOB     (-1)
204
205         /* Called when the next chunk of uncompressed data is available.  'size'
206          * is guaranteed to be nonzero.  Must return 0 on success, or a positive
207          * wimlib error code on failure.  */
208         int (*consume_chunk)(const void *chunk, size_t size, void *ctx);
209
210         /* Called when a blob has been successfully read (status=0), or when
211          * begin_blob() was successfully called but an error occurred before the
212          * blob was fully read (status != 0; in this case the implementation
213          * should do cleanup and then pass on the status).  Must return 0 on
214          * success, or a positive wimlib error code on failure.  */
215         int (*end_blob)(struct blob_descriptor *blob, int status, void *ctx);
216
217         /* Parameter passed to each of the callback functions.  */
218         void *ctx;
219 };
220
221 /* Call cbs->begin_blob() if present.  */
222 static inline int
223 call_begin_blob(struct blob_descriptor *blob,
224                 const struct read_blob_callbacks *cbs)
225 {
226         if (!cbs->begin_blob)
227                 return 0;
228         return (*cbs->begin_blob)(blob, cbs->ctx);
229 }
230
231 /* Call cbs->consume_chunk() if present.  */
232 static inline int
233 call_consume_chunk(const void *chunk, size_t size,
234                    const struct read_blob_callbacks *cbs)
235 {
236         if (!cbs->consume_chunk)
237                 return 0;
238         return (*cbs->consume_chunk)(chunk, size, cbs->ctx);
239 }
240
241 /* Call cbs->end_blob() if present.  */
242 static inline int
243 call_end_blob(struct blob_descriptor *blob, int status,
244               const struct read_blob_callbacks *cbs)
245 {
246         if (!cbs->end_blob)
247                 return status;
248         return (*cbs->end_blob)(blob, status, cbs->ctx);
249 }
250
251 /* Flags for read_blob_list()  */
252 #define VERIFY_BLOB_HASHES              0x1
253 #define COMPUTE_MISSING_BLOB_HASHES     0x2
254 #define BLOB_LIST_ALREADY_SORTED        0x4
255
256 extern int
257 read_blob_list(struct list_head *blob_list, size_t list_head_offset,
258                const struct read_blob_callbacks *cbs, int flags);
259
260 extern int
261 read_blob_with_cbs(struct blob_descriptor *blob,
262                    const struct read_blob_callbacks *cbs);
263
264 extern int
265 read_blob_with_sha1(struct blob_descriptor *blob,
266                     const struct read_blob_callbacks *cbs);
267
268 extern int
269 extract_blob_prefix_to_fd(struct blob_descriptor *blob, u64 size,
270                           struct filedes *fd);
271
272 extern int
273 extract_blob_to_fd(struct blob_descriptor *blob, struct filedes *fd);
274
275 /* Miscellaneous blob functions.  */
276
277 extern int
278 sha1_blob(struct blob_descriptor *blob);
279
280 /* Functions to read/write metadata resources.  */
281
282 extern int
283 read_metadata_resource(struct wim_image_metadata *imd);
284
285 extern int
286 write_metadata_resource(WIMStruct *wim, int image, int write_resource_flags);
287
288 /* Definitions specific to pipable WIM resources.  */
289
290 /* Arbitrary number to begin each blob in the pipable WIM, used for sanity
291  * checking.  */
292 #define PWM_BLOB_MAGIC 0x2b9b9ba2443db9d8ULL
293
294 /* Header that precedes each blob in a pipable WIM.  */
295 struct pwm_blob_hdr {
296         le64 magic;                     /* +0   */
297         le64 uncompressed_size;         /* +8   */
298         u8 hash[SHA1_HASH_SIZE];        /* +16  */
299         le32 flags;                     /* +36  */
300                                         /* +40  */
301 } _packed_attribute;
302
303 /* Header that precedes each chunk of a compressed resource in a pipable WIM.
304  */
305 struct pwm_chunk_hdr {
306         le32 compressed_size;
307 } _packed_attribute;
308
309 #endif /* _WIMLIB_RESOURCE_H */