#include "wimlib_internal.h"
+/* Calculates the unaligned length, in bytes, of an on-disk WIM dentry that has
+ * a file name and short name that take the specified numbers of bytes. This
+ * excludes any alternate data stream entries that may follow the dentry. */
static u64 __dentry_correct_length_unaligned(u16 file_name_len,
u16 short_name_len)
{
return length;
}
+/* Calculates the unaligned length, in bytes, of an on-disk WIM dentry, based on
+ * the file name length and short name length. Note that dentry->length is
+ * ignored; also, this excludes any alternate data stream entries that may
+ * follow the dentry. */
static u64 dentry_correct_length_unaligned(const struct dentry *dentry)
{
return __dentry_correct_length_unaligned(dentry->file_name_len,
dentry->short_name_len);
}
-/* Return the "correct" value to write in the length field of the dentry, based
- * on the file name length and short name length */
+/* Return the "correct" value to write in the length field of a WIM dentry,
+ * based on the file name length and short name length. */
static u64 dentry_correct_length(const struct dentry *dentry)
{
return (dentry_correct_length_unaligned(dentry) + 7) & ~7;
}
-/*
- * Returns true if @dentry has the UTF-8 file name @name that has length
- * @name_len.
- */
+/* Return %true iff @dentry has the UTF-8 file name @name that has length
+ * @name_len bytes. */
static bool dentry_has_name(const struct dentry *dentry, const char *name,
size_t name_len)
{
return memcmp(dentry->file_name_utf8, name, name_len) == 0;
}
+/* Return %true iff the alternate data stream entry @entry has the UTF-8 stream
+ * name @name that has length @name_len bytes. */
static inline bool ads_entry_has_name(const struct ads_entry *entry,
const char *name, size_t name_len)
{
return (length + 7) & ~7;
}
+/* Calculate the aligned *total* length of an on-disk WIM dentry. This includes
+ * all alternate data streams. */
u64 dentry_correct_total_length(const struct dentry *dentry)
{
return __dentry_total_length(dentry,
dentry_correct_length_unaligned(dentry));
}
-/* Real length of a dentry, including the alternate data stream entries, which
- * are not included in the dentry->length field... */
+/* Like dentry_correct_total_length(), but use the existing dentry->length field
+ * instead of calculating its "correct" value. */
static u64 dentry_total_length(const struct dentry *dentry)
{
return __dentry_total_length(dentry, dentry->length);
*
* @dentry: The root of the directory tree.
* @subdir_offset_p: The current subdirectory offset; i.e., the subdirectory
- * offset for @dentry.
+ * offset for @dentry.
*/
void calculate_subdir_offsets(struct dentry *dentry, u64 *subdir_offset_p)
{
- struct dentry *child;
+ struct dentry *child, *children;
- child = dentry->d_inode->children;
+ children = dentry->d_inode->children;
+ child = children;
dentry->subdir_offset = *subdir_offset_p;
if (child) {
do {
*subdir_offset_p += dentry_correct_total_length(child);
child = child->next;
- } while (child != dentry->d_inode->children);
+ } while (child != children);
/* End-of-directory dentry on disk. */
*subdir_offset_p += 8;
do {
calculate_subdir_offsets(child, subdir_offset_p);
child = child->next;
- } while (child != dentry->d_inode->children);
+ } while (child != children);
} else {
/* On disk, childless directories have a valid subdir_offset
* that points to an 8-byte end-of-directory dentry. Regular
* @parent itself, which has already been written. */
static u8 *write_dentry_tree_recursive(const struct dentry *parent, u8 *p)
{
- const struct dentry *child;
+ const struct dentry *child, *children;
/* Nothing to do if this dentry has no children. */
if (parent->subdir_offset == 0)
* recursively writing the directory trees rooted at each of the child
* dentries, since the on-disk dentries for a dentry's children are
* always located at consecutive positions in the metadata resource! */
- child = parent->d_inode->children;
+ children = parent->d_inode->children;
+ child = children;
if (child) {
do {
p = write_dentry(child, p);
child = child->next;
- } while (child != parent->d_inode->children);
+ } while (child != children);
}
/* write end of directory entry */
do {
p = write_dentry_tree_recursive(child, p);
child = child->next;
- } while (child != parent->d_inode->children);
+ } while (child != children);
}
return p;
}
*/
u8 *write_dentry_tree(const struct dentry *root, u8 *p)
{
+ DEBUG("Writing dentry tree.");
wimlib_assert(dentry_is_root(root));
/* If we're the root dentry, we have no parent that already
int write_integrity_table(FILE *out, u64 end_header_offset,
u64 end_lookup_table_offset, int show_progress)
{
- u64 bytes_to_check;
- u64 bytes_remaining;
- u8 *buf;
- u8 *p;
- u8 *chunk_buf;
- u32 num_entries;
- u32 integrity_table_size;
- int ret;
-
- DEBUG("Writing integrity table");
+ u64 bytes_to_check;
+ u64 bytes_remaining;
+ u8 *buf;
+ u8 *p;
+ u8 *chunk_buf;
+ u32 num_entries;
+ u32 integrity_table_size;
+ int ret;
+
+ DEBUG("Calculating integrity table");
if (fseeko(out, end_header_offset, SEEK_SET) != 0) {
ERROR_WITH_ERRNO("Failed to seek to byte %"PRIu64" of WIM to "
"calculate integrity data", end_header_offset);
}
bytes_to_check = end_lookup_table_offset - end_header_offset;
- num_entries = bytes_to_check / INTEGRITY_CHUNK_SIZE +
- (bytes_to_check % INTEGRITY_CHUNK_SIZE != 0);
+ num_entries = (bytes_to_check + INTEGRITY_CHUNK_SIZE - 1) /
+ INTEGRITY_CHUNK_SIZE;
integrity_table_size = num_entries * SHA1_HASH_SIZE + 3 * sizeof(u32);
- DEBUG("integrity table size = %u", integrity_table_size);
-
+ DEBUG("integrity_table_size = %u", integrity_table_size);
buf = MALLOC(integrity_table_size);
if (!buf) {
ERROR("Failed to allocate %u bytes for integrity chunk buffer",
INTEGRITY_CHUNK_SIZE);
ret = WIMLIB_ERR_NOMEM;
- goto err2;
+ goto out_free_buf;
}
bytes_remaining = bytes_to_check;
"checksums");
}
ret = WIMLIB_ERR_READ;
- goto err2;
+ goto out_free_chunk_buf;
}
sha1_buffer(chunk_buf, bytes_read, p);
p += SHA1_HASH_SIZE;
ERROR_WITH_ERRNO("Failed to seek to end of WIM to write "
"integrity table");
ret = WIMLIB_ERR_WRITE;
- goto err1;
+ goto out_free_chunk_buf;
}
if (fwrite(buf, 1, integrity_table_size, out) != integrity_table_size) {
ERROR_WITH_ERRNO("Failed to write integrity table to end of "
"WIM");
ret = WIMLIB_ERR_WRITE;
- goto err1;
+ goto out_free_chunk_buf;
}
ret = 0;
-err1:
+out_free_chunk_buf:
FREE(chunk_buf);
-err2:
+out_free_buf:
FREE(buf);
return ret;
}
* attached to it. */
swms[0]->hdr.flags &= ~WIM_HDR_FLAG_SPANNED;
swms[0]->hdr.total_parts = 1;
- return finish_write(swms[0], WIM_ALL_IMAGES, write_flags, 0);
+ return finish_write(swms[0], WIM_ALL_IMAGES,
+ write_flags | WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE);
}
int read_wim_resource(const struct lookup_table_entry *lte, u8 buf[],
size_t size, u64 offset, bool raw)
{
+ int ctype;
+ int ret = 0;
+ FILE *fp;
+
/* We shouldn't be allowing read over-runs in any part of the library.
* */
if (raw)
else
wimlib_assert(offset + size <= lte->resource_entry.original_size);
- int ctype;
- int ret;
- FILE *fp;
switch (lte->resource_location) {
case RESOURCE_IN_WIM:
/* The resource is in a WIM file, and its WIMStruct is given by
* the lte->wim member. The resource may be either compressed
* or uncompressed. */
- wimlib_assert(lte->wim);
- wimlib_assert(lte->wim->fp);
+ wimlib_assert(lte->wim != NULL);
+ wimlib_assert(lte->wim->fp != NULL);
ctype = wim_resource_compression_type(lte);
wimlib_assert(ctype != WIM_COMPRESSION_TYPE_NONE ||
lte->resource_entry.size));
if (raw || ctype == WIM_COMPRESSION_TYPE_NONE)
- return read_uncompressed_resource(lte->wim->fp,
- lte->resource_entry.offset + offset,
- size, buf);
+ ret = read_uncompressed_resource(lte->wim->fp,
+ lte->resource_entry.offset + offset,
+ size, buf);
else
- return read_compressed_resource(lte->wim->fp,
- lte->resource_entry.size,
- lte->resource_entry.original_size,
- lte->resource_entry.offset,
- ctype, size, offset, buf);
+ ret = read_compressed_resource(lte->wim->fp,
+ lte->resource_entry.size,
+ lte->resource_entry.original_size,
+ lte->resource_entry.offset,
+ ctype, size, offset, buf);
break;
case RESOURCE_IN_STAGING_FILE:
case RESOURCE_IN_FILE_ON_DISK:
if (!fp) {
ERROR_WITH_ERRNO("Failed to open the file "
"`%s'", lte->file_on_disk);
- return WIMLIB_ERR_OPEN;
+ ret = WIMLIB_ERR_OPEN;
+ break;
}
}
ret = read_uncompressed_resource(fp, offset, size, buf);
if (fp != lte->file_on_disk_fp)
fclose(fp);
- return ret;
break;
case RESOURCE_IN_ATTACHED_BUFFER:
/* The resource is directly attached uncompressed in an
* in-memory buffer. */
- wimlib_assert(lte->attached_buffer);
+ wimlib_assert(lte->attached_buffer != NULL);
memcpy(buf, lte->attached_buffer + offset, size);
- return 0;
break;
#ifdef WITH_NTFS_3G
case RESOURCE_IN_NTFS_VOLUME:
- wimlib_assert(lte->ntfs_loc);
- if (lte->attr) {
+ wimlib_assert(lte->ntfs_loc != NULL);
+ wimlib_assert(lte->attr != NULL);
+ {
u64 adjusted_offset;
if (lte->ntfs_loc->is_reparse_point)
adjusted_offset = offset + 8;
else
adjusted_offset = offset;
- if (ntfs_attr_pread(lte->attr, offset, size, buf) == size) {
- return 0;
- } else {
+ if (ntfs_attr_pread(lte->attr, offset, size, buf) != size) {
ERROR_WITH_ERRNO("Error reading NTFS attribute "
"at `%s'",
lte->ntfs_loc->path_utf8);
- return WIMLIB_ERR_NTFS_3G;
+ ret = WIMLIB_ERR_NTFS_3G;
}
- } else {
- wimlib_assert(0);
+ break;
}
- break;
#endif
default:
- assert(0);
+ wimlib_assert(0);
+ ret = -1;
+ break;
}
+ return ret;
}
/*
struct chunk_table *chunk_tab = CALLOC(1, alloc_size);
int ret;
-
if (!chunk_tab) {
ERROR("Failed to allocate chunk table for %"PRIu64" byte "
"resource", size);
u64 original_size;
u64 old_compressed_size;
u64 new_compressed_size;
- u64 offset = 0;
- int ret = 0;
+ u64 offset;
+ int ret;
struct chunk_table *chunk_tab = NULL;
bool raw;
off_t file_offset;
/* While there are still bytes remaining in the WIM resource, read a
* chunk of the resource, update SHA1, then write that chunk using the
* desired compression type. */
+ offset = 0;
do {
u64 to_read = min(bytes_remaining, WIM_CHUNK_SIZE);
ret = read_wim_resource(lte, buf, to_read, offset, raw);
if (ftruncate(fileno(out_fp), file_offset + out_res_entry->size) != 0) {
ERROR_WITH_ERRNO("Failed to truncate output WIM file");
ret = WIMLIB_ERR_WRITE;
+ goto out_fclose;
+ }
+ } else {
+ if (out_res_entry) {
+ out_res_entry->size = new_compressed_size;
+ out_res_entry->original_size = original_size;
+ out_res_entry->offset = file_offset;
+ out_res_entry->flags = lte->resource_entry.flags
+ & ~WIM_RESHDR_FLAG_COMPRESSED;
+ if (out_ctype != WIM_COMPRESSION_TYPE_NONE)
+ out_res_entry->flags |= WIM_RESHDR_FLAG_COMPRESSED;
}
- goto out_fclose;
- }
- wimlib_assert(new_compressed_size <= original_size || raw);
- if (out_res_entry) {
- out_res_entry->size = new_compressed_size;
- out_res_entry->original_size = original_size;
- out_res_entry->offset = file_offset;
- out_res_entry->flags = lte->resource_entry.flags
- & ~WIM_RESHDR_FLAG_COMPRESSED;
- if (out_ctype != WIM_COMPRESSION_TYPE_NONE)
- out_res_entry->flags |= WIM_RESHDR_FLAG_COMPRESSED;
}
+ ret = 0;
out_fclose:
if (lte->resource_location == RESOURCE_IN_FILE_ON_DISK
- && lte->file_on_disk_fp) {
+ && lte->file_on_disk_fp) {
fclose(lte->file_on_disk_fp);
lte->file_on_disk_fp = NULL;
}
if (lte->attr) {
ntfs_attr_close(lte->attr);
lte->attr = NULL;
- } if (ni) {
- ntfs_inode_close(ni);
}
+ if (ni)
+ ntfs_inode_close(ni);
}
#endif
out:
struct resource_entry *out_res_entry,
u8 hash[SHA1_HASH_SIZE])
{
- /* Set up a temporary lookup table entry that we provide to
+ /* Set up a temporary lookup table entry to provide to
* write_wim_resource(). */
struct lookup_table_entry lte;
int ret;
/* We do not allow the security data pointer to be NULL, although it may
* point to an empty security data with no entries. */
- wimlib_assert(sd);
+ wimlib_assert(root != NULL);
+ wimlib_assert(sd != NULL);
/* Offset of first child of the root dentry. It's equal to:
* - The total length of the security data, rounded to the next 8-byte
p = write_security_data(sd, buf);
/* Write the dentry tree into the resource buffer */
- DEBUG("Writing dentry tree.");
p = write_dentry_tree(root, p);
/*
* it. */
lte = wim_metadata_lookup_table_entry(w);
+ wimlib_assert(lte != NULL);
+
/* Write the metadata resource to the output WIM using the proper
* compression type. The lookup table entry for the metadata resource
* is updated. */
w->hdr.lookup_table_res_entry.offset = lookup_table_offset;
w->hdr.lookup_table_res_entry.size =
xml_data_offset - lookup_table_offset;
- ret = finish_write(w, WIM_ALL_IMAGES, write_flags, 0);
+ ret = finish_write(w, WIM_ALL_IMAGES,
+ write_flags | WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE);
if (ret != 0)
return ret;
= "Could not read the target of a symbolic link",
[WIMLIB_ERR_RENAME]
= "Could not rename a file",
+ [WIMLIB_ERR_RESOURCE_ORDER]
+ = "The components of the WIM were arranged in an unexpected order",
[WIMLIB_ERR_SPECIAL_FILE]
= "Encountered a special file that cannot be archived",
[WIMLIB_ERR_SPLIT_INVALID]
WIMLIB_ERR_READLINK,
WIMLIB_ERR_READ,
WIMLIB_ERR_RENAME,
+ WIMLIB_ERR_RESOURCE_ORDER,
WIMLIB_ERR_SPECIAL_FILE,
WIMLIB_ERR_SPLIT_INVALID,
WIMLIB_ERR_SPLIT_UNSUPPORTED,
* from the WIM file associated with @a wim could not be read to compute
* the SHA1 message digests, or the old integrity table (if it existed)
* could not be read.
+ * @retval ::WIMLIB_ERR_RESOURCE_ORDER
+ * Stream resources appeared in the WIM after the XML data or integrity
+ * table, so we could not safely overwrite the XML data and integrity
+ * table. Note: this error should never be received from WIMs that were
+ * written by this library.
* @retval ::WIMLIB_ERR_WRITE
* Failed to write the WIM header, the XML data, or the integrity table to
* the WIM file associated with @a wim.
extern int wim_hdr_flags_compression_type(int wim_hdr_flags);
extern int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *));
-/* write.c */
-extern int finish_write(WIMStruct *w, int image, int flags,
- int write_lookup_table);
+/* Internal use only */
+#define WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE 0x80000000
-extern int begin_write(WIMStruct *w, const char *path, int flags);
+/* write.c */
+extern int begin_write(WIMStruct *w, const char *path, int write_flags);
+extern int finish_write(WIMStruct *w, int image, int write_flags);
#include "wimlib.h"
#include "xml.h"
#include <unistd.h>
+
/* Reopens the FILE* for a WIM read-write. */
static int reopen_rw(WIMStruct *w)
{
if (fclose(w->fp) != 0)
ERROR_WITH_ERRNO("Failed to close the file `%s'", w->filename);
+ w->fp = NULL;
fp = fopen(w->filename, "r+b");
if (!fp) {
ERROR_WITH_ERRNO("Failed to open `%s' for reading and writing",
/*
* Writes a WIM file to the original file that it was read from, overwriting it.
*/
-WIMLIBAPI int wimlib_overwrite(WIMStruct *w, int flags)
+WIMLIBAPI int wimlib_overwrite(WIMStruct *w, int write_flags)
{
const char *wimfile_name;
size_t wim_name_len;
if (!w)
return WIMLIB_ERR_INVALID_PARAM;
+ write_flags &= ~WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE;
+
wimfile_name = w->filename;
DEBUG("Replacing WIM file `%s'.", wimfile_name);
randomize_char_array_with_alnum(tmpfile + wim_name_len, 9);
tmpfile[wim_name_len + 9] = '\0';
- ret = wimlib_write(w, tmpfile, WIM_ALL_IMAGES, flags);
+ ret = wimlib_write(w, tmpfile, WIM_ALL_IMAGES, write_flags);
if (ret != 0) {
ERROR("Failed to write the WIM file `%s'", tmpfile);
return ret;
return 0;
}
+static int check_resource_offset(struct lookup_table_entry *lte, void *arg)
+{
+ u64 xml_data_offset = *(u64*)arg;
+ if (lte->resource_entry.offset > xml_data_offset) {
+ ERROR("The following resource is *after* the XML data:");
+ print_lookup_table_entry(lte);
+ return WIMLIB_ERR_RESOURCE_ORDER;
+ }
+ return 0;
+}
-WIMLIBAPI int wimlib_overwrite_xml_and_header(WIMStruct *w, int flags)
+WIMLIBAPI int wimlib_overwrite_xml_and_header(WIMStruct *w, int write_flags)
{
int ret;
FILE *fp;
off_t xml_size;
size_t bytes_written;
- DEBUG("Overwriting XML and header of `%s', flags = %d",
- w->filename, flags);
+ DEBUG("Overwriting XML and header of `%s', write_flags = %#x",
+ w->filename, write_flags);
+
if (!w->filename)
return WIMLIB_ERR_NO_FILENAME;
+ write_flags &= ~WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE;
+
+ /* Make sure that the integrity table (if present) is after the XML
+ * data, and that there are no stream resources, metadata resources, or
+ * lookup tables after the XML data. Otherwise, these data would be
+ * destroyed by this function. */
+ if (w->hdr.integrity.offset != 0 &&
+ w->hdr.integrity.offset < w->hdr.xml_res_entry.offset) {
+ ERROR("Didn't expect the integrity table to be before the XML data");
+ return WIMLIB_ERR_RESOURCE_ORDER;
+ }
+
+ if (w->hdr.lookup_table_res_entry.offset >
+ w->hdr.xml_res_entry.offset) {
+ ERROR("Didn't expect the lookup table to be after the XML data");
+ return WIMLIB_ERR_RESOURCE_ORDER;
+ }
+
+ ret = for_lookup_table_entry(w->lookup_table, check_resource_offset,
+ &w->hdr.xml_res_entry.offset);
+ if (ret != 0)
+ return ret;
+
ret = reopen_rw(w);
if (ret != 0)
return ret;
* the integrity table include neither the header nor the XML data.
* Save it for later if it exists and an integrity table was required.
* */
- if (flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY &&
- w->hdr.integrity.offset != 0) {
+ if ((write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY)
+ && w->hdr.integrity.offset != 0)
+ {
DEBUG("Reading existing integrity table.");
integrity_table = MALLOC(w->hdr.integrity.size);
if (!integrity_table)
xml_size = xml_end - w->hdr.xml_res_entry.offset;
w->hdr.xml_res_entry.size = xml_size;
w->hdr.xml_res_entry.original_size = xml_size;
+ /* XML data offset is unchanged. */
- if (flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) {
+ if (write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) {
DEBUG("Writing integrity table.");
- w->hdr.integrity.offset = xml_end;
+ w->hdr.integrity.offset = xml_end;
if (integrity_table) {
/* The existing integrity table was saved. */
bytes_written = fwrite(integrity_table, 1,
ret = write_integrity_table(fp, WIM_HEADER_DISK_SIZE,
w->hdr.lookup_table_res_entry.offset +
w->hdr.lookup_table_res_entry.size,
- flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS);
+ write_flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS);
if (ret != 0)
- goto err;
+ return ret;
+
+ off_t end_integrity = ftello(fp);
+ if (end_integrity == -1)
+ return WIMLIB_ERR_WRITE;
- off_t integrity_size = ftello(fp) - xml_end;
+ off_t integrity_size = end_integrity - xml_end;
w->hdr.integrity.size = integrity_size;
w->hdr.integrity.original_size = integrity_size;
w->hdr.integrity.flags = 0;
return for_dentry_in_tree(wim_root_dentry(w), write_dentry_resources, w);
}
-/* Write the lookup table, xml data, and integrity table, then overwrite the WIM
+/*
+ * Write the lookup table, xml data, and integrity table, then overwrite the WIM
* header.
- *
- * write_lt is zero iff the lookup table is not to be written; i.e. it is
- * handled elsewhere. */
-int finish_write(WIMStruct *w, int image, int flags, int write_lt)
+ */
+int finish_write(WIMStruct *w, int image, int write_flags)
{
off_t lookup_table_offset;
off_t xml_data_offset;
struct wim_header hdr;
FILE *out = w->out_fp;
- if (write_lt) {
+ if (!(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) {
+ /* Write the lookup table. */
lookup_table_offset = ftello(out);
if (lookup_table_offset == -1)
return WIMLIB_ERR_WRITE;
- DEBUG("Writing lookup table (offset %"PRIu64")", lookup_table_offset);
- /* Write the lookup table. */
+ DEBUG("Writing lookup table (offset %"PRIu64")",
+ lookup_table_offset);
ret = write_lookup_table(w->lookup_table, out);
if (ret != 0)
return ret;
}
-
xml_data_offset = ftello(out);
if (xml_data_offset == -1)
return WIMLIB_ERR_WRITE;
- DEBUG("Writing XML data (offset %"PRIu64")", xml_data_offset);
/* @hdr will be the header for the new WIM. First copy all the data
* from the header in the WIMStruct; then set all the fields that may
* have changed, including the resource entries, boot index, and image
* count. */
memcpy(&hdr, &w->hdr, sizeof(struct wim_header));
- if (write_lt) {
+ if (!(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) {
lookup_table_size = xml_data_offset - lookup_table_offset;
- hdr.lookup_table_res_entry.offset = lookup_table_offset;
- hdr.lookup_table_res_entry.size = lookup_table_size;
+ hdr.lookup_table_res_entry.offset = lookup_table_offset;
+ hdr.lookup_table_res_entry.size = lookup_table_size;
}
hdr.lookup_table_res_entry.original_size = hdr.lookup_table_res_entry.size;
- hdr.lookup_table_res_entry.flags = WIM_RESHDR_FLAG_METADATA;
+ hdr.lookup_table_res_entry.flags = WIM_RESHDR_FLAG_METADATA;
+ DEBUG("Writing XML data (offset %"PRIu64")", xml_data_offset);
ret = write_xml_data(w->wim_info, image, out,
- write_lt ? 0 : wim_info_get_total_bytes(w->wim_info));
+ (write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE) ?
+ wim_info_get_total_bytes(w->wim_info) : 0);
if (ret != 0)
return ret;
hdr.xml_res_entry.original_size = xml_data_size;
hdr.xml_res_entry.flags = 0;
- if (flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) {
+ if (write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) {
ret = write_integrity_table(out, WIM_HEADER_DISK_SIZE,
xml_data_offset,
- flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS);
+ write_flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS);
if (ret != 0)
return ret;
end_offset = ftello(out);
if (end_offset == -1)
return WIMLIB_ERR_WRITE;
- integrity_size = end_offset - integrity_offset;
- hdr.integrity.offset = integrity_offset;
- hdr.integrity.size = integrity_size;
+ integrity_size = end_offset - integrity_offset;
+ hdr.integrity.offset = integrity_offset;
+ hdr.integrity.size = integrity_size;
hdr.integrity.original_size = integrity_size;
} else {
hdr.integrity.offset = 0;
}
/* Open file stream and write dummy header for WIM. */
-int begin_write(WIMStruct *w, const char *path, int flags)
+int begin_write(WIMStruct *w, const char *path, int write_flags)
{
const char *mode;
DEBUG("Opening `%s' for new WIM", path);
/* checking the integrity requires going back over the file to read it.
* XXX
- * (It also would be possible to keep a running sha1sum as the file
- * as written-- this would be faster, but a bit more complicated) */
- if (flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY)
+ * (It also would be possible to keep a running sha1sum as the file is
+ * written-- this would be faster, but a bit more complicated) */
+ if (write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY)
mode = "w+b";
else
mode = "wb";
return write_header(&w->hdr, w->out_fp);
}
-/* Writes the WIM to a file. */
-WIMLIBAPI int wimlib_write(WIMStruct *w, const char *path, int image, int flags)
+/* Writes a stand-alone WIM to a file. */
+WIMLIBAPI int wimlib_write(WIMStruct *w, const char *path,
+ int image, int write_flags)
{
int ret;
if (!w || !path)
return WIMLIB_ERR_INVALID_PARAM;
+ write_flags &= ~WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE;
+
if (image != WIM_ALL_IMAGES &&
(image < 1 || image > w->hdr.image_count))
return WIMLIB_ERR_INVALID_IMAGE;
else
DEBUG("Writing image %d to `%s'.", image, path);
- ret = begin_write(w, path, flags);
+ ret = begin_write(w, path, write_flags);
if (ret != 0)
- goto done;
+ goto out;
for_lookup_table_entry(w->lookup_table, lte_zero_out_refcnt, NULL);
- w->write_flags = flags;
+ w->write_flags = write_flags;
ret = for_image(w, image, write_file_resources);
if (ret != 0) {
ERROR("Failed to write WIM file resources to `%s'", path);
- goto done;
+ goto out;
}
ret = for_image(w, image, write_metadata_resource);
if (ret != 0) {
ERROR("Failed to write WIM image metadata to `%s'", path);
- goto done;
+ goto out;
}
- ret = finish_write(w, image, flags, 1);
+ ret = finish_write(w, image, write_flags);
-done:
+out:
DEBUG("Closing output file.");
if (w->out_fp != NULL) {
if (fclose(w->out_fp) != 0) {