]> wimlib.net Git - wimlib/blob - include/wimlib/blob_table.h
wim_inode: Remove i_list, leaving only i_hlist
[wimlib] / include / wimlib / blob_table.h
1 #ifndef _WIMLIB_BLOB_TABLE_H
2 #define _WIMLIB_BLOB_TABLE_H
3
4 #include "wimlib/list.h"
5 #include "wimlib/resource.h"
6 #include "wimlib/sha1.h"
7 #include "wimlib/types.h"
8
9 /* An enumerated type that identifies where a blob's data is located.  */
10 enum blob_location {
11
12         /* The blob's data does not exist.  This is a temporary state only.  */
13         BLOB_NONEXISTENT = 0,
14
15         /* The blob's data is available in the WIM resource identified by the
16          * `struct wim_resource_descriptor' pointed to by @rdesc.
17          * @offset_in_res identifies the offset at which this particular blob
18          * begins in the uncompressed data of the resource.  */
19         BLOB_IN_WIM,
20
21         /* The blob's data is available as the contents of the file named by
22          * @file_on_disk.  */
23         BLOB_IN_FILE_ON_DISK,
24
25         /* The blob's data is available as the contents of the in-memory buffer
26          * pointed to by @attached_buffer.  */
27         BLOB_IN_ATTACHED_BUFFER,
28
29 #ifdef WITH_FUSE
30         /* The blob's data is available as the contents of the file with name
31          * @staging_file_name relative to the open directory file descriptor
32          * @staging_dir_fd.  */
33         BLOB_IN_STAGING_FILE,
34 #endif
35
36 #ifdef WITH_NTFS_3G
37         /* The blob's data is available as the contents of an NTFS attribute
38          * accessible through libntfs-3g.  The attribute is identified by
39          * volume, path to an inode, attribute name, and attribute type.
40          * @ntfs_loc points to a structure containing this information.  */
41         BLOB_IN_NTFS_VOLUME,
42 #endif
43
44 #ifdef __WIN32__
45         /* Windows only: the blob's data is available as the contents of the
46          * data stream named by @file_on_disk.  @file_on_disk is an NT namespace
47          * path that may be longer than the Win32-level MAX_PATH.  Furthermore,
48          * the stream may require "backup semantics" to access.  */
49         BLOB_IN_WINNT_FILE_ON_DISK,
50
51         /* Windows only: the blob's data is available as the raw encrypted data
52          * of the external file named by @file_on_disk.  @file_on_disk is a
53          * Win32 namespace path.  */
54         BLOB_WIN32_ENCRYPTED,
55 #endif
56 };
57
58 /* A "blob extraction target" is a stream, and the inode to which that stream
59  * belongs, to which a blob needs to be extracted as part of an extraction
60  * operation.  Since blobs are single-instanced, a blob may have multiple
61  * extraction targets.  */
62 struct blob_extraction_target {
63         struct wim_inode *inode;
64         struct wim_inode_stream *stream;
65 };
66
67 /*
68  * Descriptor for a "blob", which is a known length sequence of binary data.
69  *
70  * Within a WIM file, blobs are single instanced and are identified by SHA-1
71  * message digest.
72  */
73 struct blob_descriptor {
74
75         /* List node for a hash bucket of the blob table  */
76         struct hlist_node hash_list;
77
78         /* Uncompressed size of this blob  */
79         u64 size;
80
81         union {
82                 /*
83                  * For unhashed == 0: 'hash' is the SHA-1 message digest of the
84                  * blob's data.  'hash_short' allows accessing just a prefix of
85                  * the SHA-1 message digest, which is useful for getting a "hash
86                  * code" for hash table lookup/insertion.
87                  */
88                 u8 hash[SHA1_HASH_SIZE];
89                 size_t hash_short;
90
91                 /* For unhashed == 1: these variables make it possible to find
92                  * the stream that references this blob.  There can be at most
93                  * one such reference, since duplicate blobs can only be joined
94                  * after they have been hashed.  */
95                 struct {
96                         struct wim_inode *back_inode;
97                         u32 back_stream_id;
98                 };
99         };
100
101         /* Number of times this blob is referenced by file streams in WIM
102          * images.  See blob_decrement_refcnt() for information about the
103          * limitations of this field.  */
104         u32 refcnt;
105
106         /*
107          * When a WIM file is written, this is set to the number of references
108          * (from file streams) to this blob in the output WIM file.
109          *
110          * During extraction, this is set to the number of targets to which this
111          * blob is being extracted.
112          *
113          * During image export, this is set to the number of references of this
114          * blob that originated from the source WIM.
115          *
116          * When mounting a WIM image read-write, this is set to the number of
117          * extra references to this blob preemptively taken to allow later
118          * saving the modified image as a new image and leaving the original
119          * image alone.
120          */
121         u32 out_refcnt;
122
123 #ifdef WITH_FUSE
124         /* Number of open file descriptors to this blob during a FUSE mount of
125          * a WIM image.  */
126         u16 num_opened_fds;
127 #endif
128
129         /* One of the `enum blob_location' values documented above.  */
130         u16 blob_location : 4;
131
132         /* 1 iff this blob contains "metadata" as opposed to data.  */
133         u16 is_metadata : 1;
134
135         /* 1 iff the SHA-1 message digest of this blob is unknown.  */
136         u16 unhashed : 1;
137
138         /* Temporary fields used when writing blobs; set as documented for
139          * prepare_blob_list_for_write().  */
140         u16 unique_size : 1;
141         u16 will_be_in_output_wim : 1;
142
143         /* Set to 1 if this blob represents a metadata resource that has been
144          * changed.  In such cases, the hash cannot be used to verify the data
145          * if the metadata resource is read again.  (This could be avoided if we
146          * used separate fields for input/output checksum, but most blobs
147          * wouldn't need this.)  */
148         u16 dont_check_metadata_hash : 1;
149
150         u16 may_send_done_with_file : 1;
151
152         /* Only used by wimlib_export_image() */
153         u16 was_exported : 1;
154
155         /* Specification of where this blob's data is located.  Which member of
156          * this union is valid is determined by the @blob_location field.  */
157         union {
158                 /* BLOB_IN_WIM  */
159                 struct {
160                         struct wim_resource_descriptor *rdesc;
161                         u64 offset_in_res;
162
163                         /* Links together blobs that share the same underlying
164                          * WIM resource.  The head is rdesc->blob_list.  */
165                         struct list_head rdesc_node;
166                 };
167
168                 struct {
169
170                         union {
171
172                                 /* BLOB_IN_FILE_ON_DISK
173                                  * BLOB_IN_WINNT_FILE_ON_DISK
174                                  * BLOB_WIN32_ENCRYPTED  */
175                                 struct {
176                                         tchar *file_on_disk;
177                                         struct wim_inode *file_inode;
178                                 };
179
180                                 /* BLOB_IN_ATTACHED_BUFFER */
181                                 void *attached_buffer;
182
183                         #ifdef WITH_FUSE
184                                 /* BLOB_IN_STAGING_FILE  */
185                                 struct {
186                                         char *staging_file_name;
187                                         int staging_dir_fd;
188                                 };
189                         #endif
190
191                         #ifdef WITH_NTFS_3G
192                                 /* BLOB_IN_NTFS_VOLUME  */
193                                 struct ntfs_location *ntfs_loc;
194                         #endif
195                         };
196
197                         /* List link for per-WIM-image list of unhashed blobs */
198                         struct list_head unhashed_list;
199                 };
200         };
201
202         /* Temporary fields  */
203         union {
204                 /* Fields used temporarily during WIM file writing.  */
205                 struct {
206                         union {
207                                 /* List node used for blob size table.  */
208                                 struct hlist_node hash_list_2;
209
210                                 /* Metadata for the underlying solid resource in
211                                  * the WIM being written (only valid if
212                                  * WIM_RESHDR_FLAG_SOLID set in
213                                  * out_reshdr.flags).  */
214                                 struct {
215                                         u64 out_res_offset_in_wim;
216                                         u64 out_res_size_in_wim;
217                                         u64 out_res_uncompressed_size;
218                                 };
219                         };
220
221                         /* Links blobs being written to the WIM.  */
222                         struct list_head write_blobs_list;
223
224                         union {
225                                 /* Metadata for this blob in the WIM being
226                                  * written.  */
227                                 struct wim_reshdr out_reshdr;
228
229                                 struct {
230                                         /* Name under which this blob is being
231                                          * sorted; used only when sorting blobs
232                                          * for solid compression.  */
233                                         utf16lechar *solid_sort_name;
234                                         size_t solid_sort_name_nbytes;
235                                 };
236                         };
237                 };
238
239                 /* Used temporarily during extraction.  This is an array of
240                  * references to the streams being extracted that use this blob.
241                  * out_refcnt tracks the number of slots filled.  */
242                 union {
243                         struct blob_extraction_target inline_blob_extraction_targets[3];
244                         struct {
245                                 struct blob_extraction_target *blob_extraction_targets;
246                                 u32 alloc_blob_extraction_targets;
247                         };
248                 };
249         };
250
251         /* Temporary list fields.  */
252         union {
253                 /* Links blobs for writing blob table.  */
254                 struct list_head blob_table_list;
255
256                 /* Links blobs being extracted.  */
257                 struct list_head extraction_list;
258
259                 /* Links blobs being exported.  */
260                 struct list_head export_blob_list;
261
262                 /* Links original list of blobs in the read-write mounted image.  */
263                 struct list_head orig_blob_list;
264         };
265 };
266
267 extern struct blob_table *
268 new_blob_table(size_t capacity) _malloc_attribute;
269
270 extern void
271 free_blob_table(struct blob_table *table);
272
273 extern int
274 read_blob_table(WIMStruct *wim);
275
276 extern int
277 write_blob_table_from_blob_list(struct list_head *blob_list,
278                                 struct filedes *out_fd,
279                                 u16 part_number,
280                                 struct wim_reshdr *out_reshdr,
281                                 int write_resource_flags);
282
283 extern struct blob_descriptor *
284 new_blob_descriptor(void) _malloc_attribute;
285
286 extern struct blob_descriptor *
287 clone_blob_descriptor(const struct blob_descriptor *blob) _malloc_attribute;
288
289 extern void
290 blob_decrement_refcnt(struct blob_descriptor *blob, struct blob_table *table);
291
292 extern void
293 blob_subtract_refcnt(struct blob_descriptor *blob, struct blob_table *table,
294                      u32 count);
295
296 #ifdef WITH_FUSE
297 extern void
298 blob_decrement_num_opened_fds(struct blob_descriptor *blob);
299 #endif
300
301 extern void
302 free_blob_descriptor(struct blob_descriptor *blob);
303
304 extern void
305 blob_table_insert(struct blob_table *table, struct blob_descriptor *blob);
306
307 extern void
308 blob_table_unlink(struct blob_table *table, struct blob_descriptor *blob);
309
310 extern struct blob_descriptor *
311 lookup_blob(const struct blob_table *table, const u8 *hash);
312
313 extern int
314 for_blob_in_table(struct blob_table *table,
315                   int (*visitor)(struct blob_descriptor *, void *), void *arg);
316
317 extern int
318 for_blob_in_table_sorted_by_sequential_order(struct blob_table *table,
319                                              int (*visitor)(struct blob_descriptor *, void *),
320                                              void *arg);
321
322 struct wimlib_resource_entry;
323
324 extern void
325 blob_to_wimlib_resource_entry(const struct blob_descriptor *blob,
326                               struct wimlib_resource_entry *wentry);
327
328 extern int
329 sort_blob_list(struct list_head *blob_list,
330                size_t list_head_offset,
331                int (*compar)(const void *, const void*));
332
333 extern int
334 sort_blob_list_by_sequential_order(struct list_head *blob_list,
335                                    size_t list_head_offset);
336
337 extern int
338 cmp_blobs_by_sequential_order(const void *p1, const void *p2);
339
340 static inline const struct blob_extraction_target *
341 blob_extraction_targets(struct blob_descriptor *blob)
342 {
343         if (blob->out_refcnt <= ARRAY_LEN(blob->inline_blob_extraction_targets))
344                 return blob->inline_blob_extraction_targets;
345         else
346                 return blob->blob_extraction_targets;
347 }
348
349 /*
350  * Declare that the specified blob is located in the specified WIM resource at
351  * the specified offset.  The caller is expected to set blob->size if required.
352  */
353 static inline void
354 blob_set_is_located_in_wim_resource(struct blob_descriptor *blob,
355                                     struct wim_resource_descriptor *rdesc,
356                                     u64 offset_in_res)
357 {
358         blob->blob_location = BLOB_IN_WIM;
359         blob->rdesc = rdesc;
360         list_add_tail(&blob->rdesc_node, &rdesc->blob_list);
361         blob->offset_in_res = offset_in_res;
362 }
363
364 /*
365  * Declare that the specified blob is located in the specified non-solid WIM
366  * resource.  In this case, the blob data is the entire uncompressed resource.
367  */
368 static inline void
369 blob_set_is_located_in_nonsolid_wim_resource(struct blob_descriptor *blob,
370                                              struct wim_resource_descriptor *rdesc)
371 {
372         blob_set_is_located_in_wim_resource(blob, rdesc, 0);
373         blob->size = rdesc->uncompressed_size;
374 }
375
376 static inline void
377 blob_unset_is_located_in_wim_resource(struct blob_descriptor *blob)
378 {
379         list_del(&blob->rdesc_node);
380         blob->blob_location = BLOB_NONEXISTENT;
381 }
382
383 static inline void
384 blob_set_is_located_in_attached_buffer(struct blob_descriptor *blob,
385                                        void *buffer, size_t size)
386 {
387         blob->blob_location = BLOB_IN_ATTACHED_BUFFER;
388         blob->attached_buffer = buffer;
389         blob->size = size;
390 }
391
392 extern struct blob_descriptor *
393 new_blob_from_data_buffer(const void *buffer, size_t size,
394                           struct blob_table *blob_table);
395
396 extern struct blob_descriptor *
397 after_blob_hashed(struct blob_descriptor *blob,
398                   struct blob_descriptor **back_ptr,
399                   struct blob_table *blob_table);
400
401 extern int
402 hash_unhashed_blob(struct blob_descriptor *blob,
403                    struct blob_table *blob_table,
404                    struct blob_descriptor **blob_ret);
405
406 extern struct blob_descriptor **
407 retrieve_pointer_to_unhashed_blob(struct blob_descriptor *blob);
408
409 static inline void
410 prepare_unhashed_blob(struct blob_descriptor *blob,
411                       struct wim_inode *back_inode, u32 stream_id,
412                       struct list_head *unhashed_blobs)
413 {
414         if (!blob)
415                 return;
416         blob->unhashed = 1;
417         blob->back_inode = back_inode;
418         blob->back_stream_id = stream_id;
419         list_add_tail(&blob->unhashed_list, unhashed_blobs);
420 }
421
422 #endif /* _WIMLIB_BLOB_TABLE_H */