-/* Reopens the FILE* for a WIM read-write. */
-static int reopen_rw(WIMStruct *w)
-{
- FILE *fp;
-
- 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",
- w->filename);
- return WIMLIB_ERR_OPEN;
- }
- w->fp = fp;
- return 0;
-}
-
-
-
-/*
- * Writes a WIM file to the original file that it was read from, overwriting it.
- */
-WIMLIBAPI int wimlib_overwrite(WIMStruct *w, int write_flags)
-{
- const char *wimfile_name;
- size_t wim_name_len;
- int ret;
-
- 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);
-
- if (!wimfile_name)
- return WIMLIB_ERR_NO_FILENAME;
-
- /* Write the WIM to a temporary file. */
- /* XXX should the temporary file be somewhere else? */
- wim_name_len = strlen(wimfile_name);
- char tmpfile[wim_name_len + 10];
- memcpy(tmpfile, wimfile_name, wim_name_len);
- randomize_char_array_with_alnum(tmpfile + wim_name_len, 9);
- tmpfile[wim_name_len + 9] = '\0';
-
- ret = wimlib_write(w, tmpfile, WIM_ALL_IMAGES, write_flags);
- if (ret != 0) {
- ERROR("Failed to write the WIM file `%s'", tmpfile);
- if (unlink(tmpfile) != 0)
- WARNING("Failed to remove `%s'", tmpfile);
- return ret;
- }
-
- DEBUG("Closing original WIM file.");
- /* Close the original WIM file that was opened for reading. */
- if (w->fp) {
- if (fclose(w->fp) != 0) {
- WARNING("Failed to close the file `%s'", wimfile_name);
- }
- w->fp = NULL;
- }
-
- DEBUG("Renaming `%s' to `%s'", tmpfile, wimfile_name);
-
- /* Rename the new file to the old file .*/
- if (rename(tmpfile, wimfile_name) != 0) {
- ERROR_WITH_ERRNO("Failed to rename `%s' to `%s'",
- tmpfile, wimfile_name);
- /* Remove temporary file. */
- if (unlink(tmpfile) != 0)
- ERROR_WITH_ERRNO("Failed to remove `%s'", tmpfile);
- return WIMLIB_ERR_RENAME;
- }
-
- if (write_flags & WIMLIB_WRITE_FLAG_VERBOSE)
- printf("Successfully renamed `%s' to `%s'\n", tmpfile, wimfile_name);
-
- 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 write_flags)
-{
- int ret;
- FILE *fp;
- u8 *integrity_table = NULL;
- off_t xml_end;
- off_t xml_size;
- size_t bytes_written;
-
- 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;
-
- fp = w->fp;
-
- /* The old integrity table is still OK, as the SHA1 message digests in
- * 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 ((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)
- return WIMLIB_ERR_NOMEM;
-
- ret = read_uncompressed_resource(fp, w->hdr.integrity.offset,
- w->hdr.integrity.original_size,
- integrity_table);
- if (ret != 0)
- goto err;
- DEBUG("Done reading existing integrity table.");
- }
-
- DEBUG("Overwriting XML data.");
- /* Overwrite the XML data. */
- if (fseeko(fp, w->hdr.xml_res_entry.offset, SEEK_SET) != 0) {
- ERROR_WITH_ERRNO("Failed to seek to byte %"PRIu64" "
- "for XML data", w->hdr.xml_res_entry.offset);
- ret = WIMLIB_ERR_WRITE;
- goto err;
- }
- ret = write_xml_data(w->wim_info, WIM_ALL_IMAGES, fp, 0);
- if (ret != 0)
- goto err;
-
- DEBUG("Updating XML resource entry.");
- /* Update the XML resource entry in the WIM header. */
- xml_end = ftello(fp);
- if (xml_end == -1) {
- ret = WIMLIB_ERR_WRITE;
- goto err;
- }
- 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 (write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) {
- DEBUG("Writing integrity table.");
- w->hdr.integrity.offset = xml_end;
- if (integrity_table) {
- /* The existing integrity table was saved. */
- bytes_written = fwrite(integrity_table, 1,
- w->hdr.integrity.size, fp);
- if (bytes_written != w->hdr.integrity.size) {
- ERROR_WITH_ERRNO("Failed to write integrity "
- "table");
- ret = WIMLIB_ERR_WRITE;
- goto err;
- }
- FREE(integrity_table);
- } else {
- /* There was no existing integrity table, so a new one
- * must be calculated. */
- ret = write_integrity_table(fp, WIM_HEADER_DISK_SIZE,
- w->hdr.lookup_table_res_entry.offset +
- w->hdr.lookup_table_res_entry.size,
- write_flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS);
- if (ret != 0)
- return ret;
-
- off_t end_integrity = ftello(fp);
- if (end_integrity == -1)
- return WIMLIB_ERR_WRITE;