#define WRITE_RESOURCE_FLAG_SEND_DONE_WITH_FILE 0x00000008
#define WRITE_RESOURCE_FLAG_SOLID_SORT 0x00000010
-static inline int
+static int
write_flags_to_resource_flags(int write_flags)
{
int write_resource_flags = 0;
if (write_flags & WIMLIB_WRITE_FLAG_RECOMPRESS)
write_resource_flags |= WRITE_RESOURCE_FLAG_RECOMPRESS;
+
if (write_flags & WIMLIB_WRITE_FLAG_PIPABLE)
write_resource_flags |= WRITE_RESOURCE_FLAG_PIPABLE;
+
if (write_flags & WIMLIB_WRITE_FLAG_SOLID)
write_resource_flags |= WRITE_RESOURCE_FLAG_SOLID;
+
if (write_flags & WIMLIB_WRITE_FLAG_SEND_DONE_WITH_FILE_MESSAGES)
write_resource_flags |= WRITE_RESOURCE_FLAG_SEND_DONE_WITH_FILE;
+
if ((write_flags & (WIMLIB_WRITE_FLAG_SOLID |
WIMLIB_WRITE_FLAG_NO_SOLID_SORT)) ==
WIMLIB_WRITE_FLAG_SOLID)
write_resource_flags |= WRITE_RESOURCE_FLAG_SOLID_SORT;
+
return write_resource_flags;
}
return false;
}
-static u8
-filter_resource_flags(u8 flags)
+static u32
+reshdr_flags_for_blob(const struct blob_descriptor *blob)
{
- return (flags & ~(WIM_RESHDR_FLAG_SOLID |
- WIM_RESHDR_FLAG_COMPRESSED |
- WIM_RESHDR_FLAG_SPANNED |
- WIM_RESHDR_FLAG_FREE));
+ u32 reshdr_flags = 0;
+ if (blob->is_metadata)
+ reshdr_flags |= WIM_RESHDR_FLAG_METADATA;
+ return reshdr_flags;
}
static void
rdesc = blob->rdesc;
if (rdesc->flags & WIM_RESHDR_FLAG_SOLID) {
-
- wimlib_assert(blob->flags & WIM_RESHDR_FLAG_SOLID);
-
blob->out_reshdr.offset_in_wim = blob->offset_in_res;
blob->out_reshdr.uncompressed_size = 0;
blob->out_reshdr.size_in_wim = blob->size;
blob->out_res_size_in_wim = rdesc->size_in_wim;
blob->out_res_uncompressed_size = rdesc->uncompressed_size;
} else {
- wimlib_assert(!(blob->flags & WIM_RESHDR_FLAG_SOLID));
-
blob->out_reshdr.offset_in_wim = rdesc->offset_in_wim;
blob->out_reshdr.uncompressed_size = rdesc->uncompressed_size;
blob->out_reshdr.size_in_wim = rdesc->size_in_wim;
}
- blob->out_reshdr.flags = blob->flags;
+ blob->out_reshdr.flags = rdesc->flags;
}
/* Write the header for a blob in a pipable WIM. */
static int
write_pwm_blob_header(const struct blob_descriptor *blob,
- struct filedes *out_fd, int additional_reshdr_flags)
+ struct filedes *out_fd, bool compressed)
{
struct pwm_blob_hdr blob_hdr;
u32 reshdr_flags;
int ret;
+ wimlib_assert(!blob->unhashed);
+
blob_hdr.magic = cpu_to_le64(PWM_BLOB_MAGIC);
blob_hdr.uncompressed_size = cpu_to_le64(blob->size);
- if (additional_reshdr_flags & PWM_RESHDR_FLAG_UNHASHED) {
- zero_out_hash(blob_hdr.hash);
- } else {
- wimlib_assert(!blob->unhashed);
- copy_hash(blob_hdr.hash, blob->hash);
- }
-
- reshdr_flags = filter_resource_flags(blob->flags);
- reshdr_flags |= additional_reshdr_flags;
+ copy_hash(blob_hdr.hash, blob->hash);
+ reshdr_flags = reshdr_flags_for_blob(blob);
+ if (compressed)
+ reshdr_flags |= WIM_RESHDR_FLAG_COMPRESSED;
blob_hdr.flags = cpu_to_le32(reshdr_flags);
ret = full_write(out_fd, &blob_hdr, sizeof(blob_hdr));
if (ret)
return 0;
}
-/* Rewrite a blob that was just written compressed as uncompressed instead.
- */
+/* Rewrite a blob that was just written compressed (as a non-solid WIM resource)
+ * as uncompressed instead. */
static int
write_blob_uncompressed(struct blob_descriptor *blob, struct filedes *out_fd)
{
* seeked to the end of the compressed resource, so
* don't issue a hard error; just keep the compressed
* resource instead. */
- WARNING("Recovered compressed blob of "
+ WARNING("Recovered compressed resource of "
"size %"PRIu64", continuing on.", blob->size);
return 0;
}
* uncompressed data by decompressing the compressed data we wrote to
* the output file.
*/
- if ((blob->flags & WIM_RESHDR_FLAG_SOLID) &&
- (blob->out_reshdr.size_in_wim != blob->out_reshdr.uncompressed_size))
+ if (blob->blob_location == BLOB_IN_WIM &&
+ blob->size != blob->rdesc->uncompressed_size &&
+ blob->size != blob->out_reshdr.size_in_wim)
return false;
return true;
/* Starting to write a new blob in non-solid mode. */
if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_PIPABLE) {
- int additional_reshdr_flags = 0;
- if (ctx->compressor != NULL)
- additional_reshdr_flags |= WIM_RESHDR_FLAG_COMPRESSED;
-
DEBUG("Writing pipable WIM blob header "
"(offset=%"PRIu64")", ctx->out_fd->offset);
-
ret = write_pwm_blob_header(blob, ctx->out_fd,
- additional_reshdr_flags);
+ ctx->compressor != NULL);
if (ret)
return ret;
}
if (ret)
return ret;
- blob->out_reshdr.flags = filter_resource_flags(blob->flags);
+ blob->out_reshdr.flags = reshdr_flags_for_blob(blob);
if (ctx->compressor != NULL)
blob->out_reshdr.flags |= WIM_RESHDR_FLAG_COMPRESSED;
blob->out_reshdr.offset_in_wim = 0;
blob->out_reshdr.size_in_wim = 0;
blob->out_reshdr.uncompressed_size = 0;
- blob->out_reshdr.flags = filter_resource_flags(blob->flags);
+ blob->out_reshdr.flags = reshdr_flags_for_blob(blob);
}
}
}
+static inline bool
+blob_is_in_file(const struct blob_descriptor *blob)
+{
+ return blob->blob_location == BLOB_IN_FILE_ON_DISK
+#ifdef __WIN32__
+ || blob->blob_location == BLOB_IN_WINNT_FILE_ON_DISK
+ || blob->blob_location == BLOB_WIN32_ENCRYPTED
+#endif
+ ;
+}
+
static void
init_done_with_file_info(struct list_head *blob_list)
{
offset_in_res = 0;
list_for_each_entry(blob, &ctx.blobs_in_solid_resource, write_blobs_list) {
blob->out_reshdr.size_in_wim = blob->size;
- blob->out_reshdr.flags = filter_resource_flags(blob->flags);
- blob->out_reshdr.flags |= WIM_RESHDR_FLAG_SOLID;
+ blob->out_reshdr.flags = reshdr_flags_for_blob(blob) |
+ WIM_RESHDR_FLAG_SOLID;
blob->out_reshdr.uncompressed_size = 0;
blob->out_reshdr.offset_in_wim = offset_in_res;
blob->out_res_offset_in_wim = reshdr.offset_in_wim;
return ret;
}
-static int
-is_blob_in_solid_resource(struct blob_descriptor *blob, void *_ignore)
-{
- return blob_is_in_solid_wim_resource(blob);
-}
-
-static bool
-wim_has_solid_resources(WIMStruct *wim)
-{
- return for_blob_in_table(wim->blob_table, is_blob_in_solid_resource, NULL);
-}
static int
-wim_write_blob_list(WIMStruct *wim,
- struct list_head *blob_list,
- int write_flags,
- unsigned num_threads,
- struct filter_context *filter_ctx)
+write_file_data_blobs(WIMStruct *wim,
+ struct list_head *blob_list,
+ int write_flags,
+ unsigned num_threads,
+ struct filter_context *filter_ctx)
{
int out_ctype;
u32 out_chunk_size;
wim->progctx);
}
+/* Write the contents of the specified blob as a WIM resource. */
static int
write_wim_resource(struct blob_descriptor *blob,
struct filedes *out_fd,
NULL);
}
+/* Write the contents of the specified buffer as a WIM resource. */
int
-write_wim_resource_from_buffer(const void *buf, size_t buf_size,
- int reshdr_flags, struct filedes *out_fd,
+write_wim_resource_from_buffer(const void *buf,
+ size_t buf_size,
+ bool is_metadata,
+ struct filedes *out_fd,
int out_ctype,
u32 out_chunk_size,
struct wim_reshdr *out_reshdr,
- u8 *hash,
+ u8 *hash_ret,
int write_resource_flags)
{
int ret;
- struct blob_descriptor *blob;
-
- /* Set up a temporary blob descriptor to provide to
- * write_wim_resource(). */
+ struct blob_descriptor blob;
- blob = new_blob_descriptor();
- if (blob == NULL)
- return WIMLIB_ERR_NOMEM;
-
- blob->blob_location = BLOB_IN_ATTACHED_BUFFER;
- blob->attached_buffer = (void*)buf;
- blob->size = buf_size;
- blob->flags = reshdr_flags;
-
- if (write_resource_flags & WRITE_RESOURCE_FLAG_PIPABLE) {
- sha1_buffer(buf, buf_size, blob->hash);
- blob->unhashed = 0;
- } else {
- blob->unhashed = 1;
- }
+ blob_set_is_located_in_attached_buffer(&blob, (void *)buf, buf_size);
+ sha1_buffer(buf, buf_size, blob.hash);
+ blob.unhashed = 0;
+ blob.is_metadata = is_metadata;
- ret = write_wim_resource(blob, out_fd, out_ctype, out_chunk_size,
+ ret = write_wim_resource(&blob, out_fd, out_ctype, out_chunk_size,
write_resource_flags);
if (ret)
- goto out_free_blob;
+ return ret;
- copy_reshdr(out_reshdr, &blob->out_reshdr);
+ copy_reshdr(out_reshdr, &blob.out_reshdr);
- if (hash)
- copy_hash(hash, blob->hash);
- ret = 0;
-out_free_blob:
- blob->blob_location = BLOB_NONEXISTENT;
- free_blob_descriptor(blob);
- return ret;
+ if (hash_ret)
+ copy_hash(hash_ret, blob.hash);
+ return 0;
}
struct blob_size_table {
struct blob_size_table *tab = _tab;
size_t pos;
struct blob_descriptor *same_size_blob;
- struct hlist_node *tmp;
pos = hash_u64(blob->size) % tab->capacity;
blob->unique_size = 1;
- hlist_for_each_entry(same_size_blob, tmp, &tab->array[pos], hash_list_2) {
+ hlist_for_each_entry(same_size_blob, &tab->array[pos], hash_list_2) {
if (same_size_blob->size == blob->size) {
blob->unique_size = 0;
same_size_blob->unique_size = 0;
for (unsigned i = 0; i < inode->i_num_streams; i++) {
struct blob_descriptor *blob;
+ const u8 *hash;
blob = stream_blob(&inode->i_streams[i], table);
- if (blob)
+ if (blob) {
reference_blob_for_write(blob, blob_list, inode->i_nlink);
- else if (!is_zero_hash(stream_hash(&inode->i_streams[i])))
- return WIMLIB_ERR_RESOURCE_NOT_FOUND;
+ } else {
+ hash = stream_hash(&inode->i_streams[i]);
+ if (!is_zero_hash(hash))
+ return blob_not_found_error(inode, hash);
+ }
}
return 0;
}
}
static int
-write_file_blobs(WIMStruct *wim, int image, int write_flags,
- unsigned num_threads,
- struct list_head *blob_list_override,
- struct list_head *blob_table_list_ret)
+write_file_data(WIMStruct *wim, int image, int write_flags,
+ unsigned num_threads,
+ struct list_head *blob_list_override,
+ struct list_head *blob_table_list_ret)
{
int ret;
struct list_head _blob_list;
}
}
- return wim_write_blob_list(wim,
- blob_list,
- write_flags,
- num_threads,
- filter_ctx);
+ return write_file_data_blobs(wim,
+ blob_list,
+ write_flags,
+ num_threads,
+ filter_ctx);
}
static int
-write_metadata_blobs(WIMStruct *wim, int image, int write_flags)
+write_metadata_resources(WIMStruct *wim, int image, int write_flags)
{
int ret;
int start_image;
&& wim_has_integrity_table(wim))
{
old_blob_table_end = wim->hdr.blob_table_reshdr.offset_in_wim +
- wim->hdr.blob_table_reshdr.size_in_wim;
+ wim->hdr.blob_table_reshdr.size_in_wim;
(void)read_integrity_table(wim,
old_blob_table_end - WIM_HEADER_DISK_SIZE,
&old_integrity_table);
* reading the WIM from a pipe. This copy of the XML data is ignored if the
* WIM is read from a seekable file (not a pipe).
*
+ * - Solid resources are not allowed. Each blob is always stored in its own
+ * resource.
+ *
* - The format of resources, or blobs, has been modified to allow them to be
* used before the "blob table" has been read. Each blob is prefixed with a
* `struct pwm_blob_hdr' that is basically an abbreviated form of `struct
WARNING("Creating a pipable WIM, which will "
"be incompatible\n"
- " with Microsoft's software (wimgapi/imagex/Dism).");
+ " with Microsoft's software (WIMGAPI/ImageX/DISM).");
/* At this point, the header at the beginning of the file has already
* been written. */
/* For efficiency, when wimlib adds an image to the WIM with
- * wimlib_add_image(), the SHA-1 message digests of files is not
+ * wimlib_add_image(), the SHA-1 message digests of files are not
* calculated; instead, they are calculated while the files are being
* written. However, this does not work when writing a pipable WIM,
* since when writing a blob to a pipable WIM, its SHA-1 message digest
/* Write metadata resources for the image(s) being included in the
* output WIM. */
- ret = write_metadata_blobs(wim, image, write_flags);
+ ret = write_metadata_resources(wim, image, write_flags);
if (ret)
return ret;
- /* Write blobs needed for the image(s) being included in the output WIM,
- * or blobs needed for the split WIM part. */
- return write_file_blobs(wim, image, write_flags,
- num_threads, blob_list_override,
- blob_table_list_ret);
+ /* Write file data needed for the image(s) being included in the output
+ * WIM, or file data needed for the split WIM part. */
+ return write_file_data(wim, image, write_flags,
+ num_threads, blob_list_override,
+ blob_table_list_ret);
/* The blob table, XML data, and header at end are handled by
* finish_write(). */
if (write_flags & WIMLIB_WRITE_FLAG_SOLID)
DEBUG("\tSOLID");
+ if (write_flags & WIMLIB_WRITE_FLAG_SEND_DONE_WITH_FILE_MESSAGES)
+ DEBUG("\tSEND_DONE_WITH_FILE_MESSAGES");
+
+ if (write_flags & WIMLIB_WRITE_FLAG_NO_SOLID_SORT)
+ DEBUG("\tNO_SOLID_SORT");
+
if (write_flags & WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR)
DEBUG("\tFILE_DESCRIPTOR");
wim->hdr.part_number = part_number;
wim->hdr.total_parts = total_parts;
- /* Set compression type if different. */
- if (wim->compression_type != wim->out_compression_type) {
- ret = set_wim_hdr_cflags(wim->out_compression_type, &wim->hdr);
- wimlib_assert(ret == 0);
- }
-
- /* Set chunk size if different. */
+ /* Set the compression type and chunk size. */
+ set_wim_hdr_cflags(wim->out_compression_type, &wim->hdr);
wim->hdr.chunk_size = wim->out_chunk_size;
/* Set GUID. */
if (total_parts != 1)
wim->hdr.boot_idx = 0;
- /* Initialize output file descriptor. */
+ /* Set up output file descriptor. */
if (write_flags & WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR) {
- /* File descriptor was explicitly provided. Return error if
- * file descriptor is not seekable, unless writing a pipable WIM
- * was requested. */
- wim->out_fd.fd = *(const int*)path_or_fd;
- wim->out_fd.offset = 0;
+ /* File descriptor was explicitly provided. */
+ filedes_init(&wim->out_fd, *(const int *)path_or_fd);
if (!filedes_is_seekable(&wim->out_fd)) {
+ /* The file descriptor is a pipe. */
ret = WIMLIB_ERR_INVALID_PARAM;
if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE))
goto out_restore_hdr;
if (ret)
goto out_restore_hdr;
- /* Write metadata resources and blobs. */
+ /* Write file data and metadata resources. */
if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE)) {
/* Default case: create a normal (non-pipable) WIM. */
- ret = write_file_blobs(wim, image, write_flags,
- num_threads,
- blob_list_override,
- &blob_table_list);
+ ret = write_file_data(wim, image, write_flags,
+ num_threads,
+ blob_list_override,
+ &blob_table_list);
if (ret)
goto out_restore_hdr;
- ret = write_metadata_blobs(wim, image, write_flags);
+ ret = write_metadata_resources(wim, image, write_flags);
if (ret)
goto out_restore_hdr;
} else {
goto out_restore_physical_hdr;
}
- ret = wim_write_blob_list(wim, &blob_list, write_flags,
- num_threads, &filter_ctx);
+ ret = write_file_data_blobs(wim, &blob_list, write_flags,
+ num_threads, &filter_ctx);
if (ret)
goto out_truncate;
- ret = write_metadata_blobs(wim, WIMLIB_ALL_IMAGES, write_flags);
+ ret = write_metadata_resources(wim, WIMLIB_ALL_IMAGES, write_flags);
if (ret)
goto out_truncate;