5cfbd45cb966d99b2375c3e546b8f95434a3c1b4
[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 get_wim_reshdr(const struct wim_reshdr_disk *disk_reshdr,
128                struct wim_reshdr *reshdr);
129
130 extern void
131 put_wim_reshdr(const struct wim_reshdr *reshdr,
132                struct wim_reshdr_disk *disk_reshdr);
133
134 /* Alternate chunk table format for resources with WIM_RESHDR_FLAG_SOLID set.
135  */
136 struct alt_chunk_table_header_disk {
137         /* Uncompressed size of the resource in bytes.  */
138         le64 res_usize;
139
140         /* Number of bytes each compressed chunk decompresses into, except
141          * possibly the last which decompresses into the remainder.  This
142          * overrides the chunk size specified by the WIM header.  */
143         le32 chunk_size;
144
145         /* Compression format used for compressed chunks:
146          * 0 = None
147          * 1 = XPRESS
148          * 2 = LZX
149          * 3 = LZMS
150          *
151          * This overrides the compression type specified by the WIM header.  */
152         le32 compression_format;
153
154         /* This header is directly followed by a table of compressed sizes of
155          * the chunks (4 bytes per entry).  */
156 } _packed_attribute;
157
158 static inline unsigned int
159 get_chunk_entry_size(u64 res_size, bool is_alt)
160 {
161         if (res_size <= UINT32_MAX || is_alt)
162                 return 4;
163         else
164                 return 8;
165 }
166
167 /* Functions to read blobs  */
168
169 extern int
170 read_partial_wim_blob_into_buf(const struct blob_descriptor *blob,
171                                u64 offset, size_t size, void *buf);
172
173 extern int
174 read_blob_into_buf(const struct blob_descriptor *blob, void *buf);
175
176 extern int
177 read_blob_into_alloc_buf(const struct blob_descriptor *blob, void **buf_ret);
178
179 extern int
180 wim_reshdr_to_data(const struct wim_reshdr *reshdr, WIMStruct *wim,
181                    void **buf_ret);
182
183 extern int
184 wim_reshdr_to_hash(const struct wim_reshdr *reshdr, WIMStruct *wim,
185                    u8 hash[SHA1_HASH_SIZE]);
186
187 extern int
188 skip_wim_resource(const struct wim_resource_descriptor *rdesc);
189
190 /* Callback functions for reading blobs  */
191 struct read_blob_callbacks {
192
193         /* Called when starting to read a blob.  Must return 0 on success, or a
194          * positive wimlib error code on failure, or in the case of
195          * read_blob_list(), the special value BEGIN_BLOB_STATUS_SKIP_BLOB which
196          * indicates that the data for this blob should not be read.  */
197         int (*begin_blob)(struct blob_descriptor *blob, void *ctx);
198 #define BEGIN_BLOB_STATUS_SKIP_BLOB     (-1)
199
200         /* Called when the next chunk of uncompressed data is available.  'size'
201          * is guaranteed to be nonzero.  Must return 0 on success, or a positive
202          * wimlib error code on failure.  */
203         int (*consume_chunk)(const void *chunk, size_t size, void *ctx);
204
205         /* Called when a blob has been successfully read (status=0), or when
206          * begin_blob() was successfully called but an error occurred before the
207          * blob was fully read (status != 0; in this case the implementation
208          * should do cleanup and then pass on the status).  Must return 0 on
209          * success, or a positive wimlib error code on failure.  */
210         int (*end_blob)(struct blob_descriptor *blob, int status, void *ctx);
211
212         /* Parameter passed to each of the callback functions.  */
213         void *ctx;
214 };
215
216 /* Call cbs->begin_blob() if present.  */
217 static inline int
218 call_begin_blob(struct blob_descriptor *blob,
219                 const struct read_blob_callbacks *cbs)
220 {
221         if (!cbs->begin_blob)
222                 return 0;
223         return (*cbs->begin_blob)(blob, cbs->ctx);
224 }
225
226 /* Call cbs->consume_chunk() if present.  */
227 static inline int
228 call_consume_chunk(const void *chunk, size_t size,
229                    const struct read_blob_callbacks *cbs)
230 {
231         if (!cbs->consume_chunk)
232                 return 0;
233         return (*cbs->consume_chunk)(chunk, size, cbs->ctx);
234 }
235
236 /* Call cbs->end_blob() if present.  */
237 static inline int
238 call_end_blob(struct blob_descriptor *blob, int status,
239               const struct read_blob_callbacks *cbs)
240 {
241         if (!cbs->end_blob)
242                 return status;
243         return (*cbs->end_blob)(blob, status, cbs->ctx);
244 }
245
246 /* Flags for read_blob_list()  */
247 #define VERIFY_BLOB_HASHES              0x1
248 #define COMPUTE_MISSING_BLOB_HASHES     0x2
249 #define BLOB_LIST_ALREADY_SORTED        0x4
250
251 extern int
252 read_blob_list(struct list_head *blob_list, size_t list_head_offset,
253                const struct read_blob_callbacks *cbs, int flags);
254
255 extern int
256 read_blob_with_cbs(struct blob_descriptor *blob,
257                    const struct read_blob_callbacks *cbs);
258
259 extern int
260 read_blob_with_sha1(struct blob_descriptor *blob,
261                     const struct read_blob_callbacks *cbs);
262
263 extern int
264 extract_blob_prefix_to_fd(struct blob_descriptor *blob, u64 size,
265                           struct filedes *fd);
266
267 extern int
268 extract_blob_to_fd(struct blob_descriptor *blob, struct filedes *fd);
269
270 /* Miscellaneous blob functions.  */
271
272 extern int
273 sha1_blob(struct blob_descriptor *blob);
274
275 /* Functions to read/write metadata resources.  */
276
277 extern int
278 read_metadata_resource(struct wim_image_metadata *imd);
279
280 extern int
281 write_metadata_resource(WIMStruct *wim, int image, int write_resource_flags);
282
283 /* Definitions specific to pipable WIM resources.  */
284
285 /* Arbitrary number to begin each blob in the pipable WIM, used for sanity
286  * checking.  */
287 #define PWM_BLOB_MAGIC 0x2b9b9ba2443db9d8ULL
288
289 /* Header that precedes each blob in a pipable WIM.  */
290 struct pwm_blob_hdr {
291         le64 magic;                     /* +0   */
292         le64 uncompressed_size;         /* +8   */
293         u8 hash[SHA1_HASH_SIZE];        /* +16  */
294         le32 flags;                     /* +36  */
295                                         /* +40  */
296 } _packed_attribute;
297
298 /* Header that precedes each chunk of a compressed resource in a pipable WIM.
299  */
300 struct pwm_chunk_hdr {
301         le32 compressed_size;
302 } _packed_attribute;
303
304 #endif /* _WIMLIB_RESOURCE_H */