#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK)
/* On BSD, this should be included before "list.h" so that "list.h" can
* overwrite the LIST_HEAD macro. */
-#include <sys/file.h>
+# include <sys/file.h>
+#endif
+
+#ifdef __WIN32__
+# include "win32.h"
#endif
#include "list.h"
#include "lzx.h"
#include "xpress.h"
+
#ifdef ENABLE_MULTITHREADED_COMPRESSION
-#include <pthread.h>
+# include <pthread.h>
#endif
#include <unistd.h>
#include <errno.h>
#ifdef WITH_NTFS_3G
-#include <time.h>
-#include <ntfs-3g/attrib.h>
-#include <ntfs-3g/inode.h>
-#include <ntfs-3g/dir.h>
+# include <time.h>
+# include <ntfs-3g/attrib.h>
+# include <ntfs-3g/inode.h>
+# include <ntfs-3g/dir.h>
#endif
#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
+# include <alloca.h>
#else
-#include <stdlib.h>
+# include <stdlib.h>
#endif
-static int fflush_and_ftruncate(FILE *fp, off_t size)
+#include <limits.h>
+
+#if defined(__WIN32__) && !defined(INVALID_HANDLE_VALUE)
+# define INVALID_HANDLE_VALUE ((HANDLE)(-1))
+#endif
+
+static int
+fflush_and_ftruncate(FILE *fp, off_t size)
{
int ret;
}
/*
- * Pointer to function to compresses a chunk of a WIM resource.
+ * compress_func_t- Pointer to a function to compresses a chunk
+ * of a WIM resource. This may be either xpress_compress()
+ * (xpress-compress.c) or lzx_compress() (lzx-compress.c).
+ *
+ * @chunk: Uncompressed data of the chunk.
+ * @chunk_size: Size of the uncompressed chunk, in bytes.
+ * @out: Pointer to output buffer of size at least (@chunk_size - 1) bytes.
*
- * @chunk: Uncompressed data of the chunk.
- * @chunk_size: Size of the uncompressed chunk in bytes.
- * @compressed_chunk: Pointer to output buffer of size at least
- * (@chunk_size - 1) bytes.
- * @compressed_chunk_len_ret: Pointer to an unsigned int into which the size
- * of the compressed chunk will be
- * returned.
+ * Returns the size of the compressed data written to @out in bytes, or 0 if the
+ * data could not be compressed to (@chunk_size - 1) bytes or fewer.
*
- * Returns zero if compressed succeeded, and nonzero if the chunk could not be
- * compressed to any smaller than @chunk_size. This function cannot fail for
- * any other reasons.
+ * As a special requirement, the compression code is optimized for the WIM
+ * format and therefore requires (@chunk_size <= 32768).
+ *
+ * As another special requirement, the compression code will read up to 8 bytes
+ * off the end of the @chunk array for performance reasons. The values of these
+ * bytes will not affect the output of the compression, but the calling code
+ * must make sure that the buffer holding the uncompressed chunk is actually at
+ * least (@chunk_size + 8) bytes, or at least that these extra bytes are in
+ * mapped memory that will not cause a memory access violation if accessed.
*/
-typedef int (*compress_func_t)(const void *, unsigned, void *, unsigned *);
+typedef unsigned (*compress_func_t)(const void *chunk, unsigned chunk_size,
+ void *out);
-compress_func_t get_compress_func(int out_ctype)
+compress_func_t
+get_compress_func(int out_ctype)
{
if (out_ctype == WIMLIB_COMPRESSION_TYPE_LZX)
return lzx_compress;
*
* Returns 0 on success; nonzero on failure.
*/
-static int write_wim_resource_chunk(const u8 chunk[], unsigned chunk_size,
- FILE *out_fp, compress_func_t compress,
- struct chunk_table *chunk_tab)
+static int
+write_wim_resource_chunk(const u8 chunk[], unsigned chunk_size,
+ FILE *out_fp, compress_func_t compress,
+ struct chunk_table *chunk_tab)
{
const u8 *out_chunk;
unsigned out_chunk_size;
if (chunk_tab) {
u8 *compressed_chunk = alloca(chunk_size);
- int ret;
- ret = compress(chunk, chunk_size, compressed_chunk,
- &out_chunk_size);
- if (ret == 0) {
+ out_chunk_size = compress(chunk, chunk_size, compressed_chunk);
+ if (out_chunk_size) {
+ /* Write compressed */
out_chunk = compressed_chunk;
} else {
+ /* Write uncompressed */
out_chunk = chunk;
out_chunk_size = chunk_size;
}
*chunk_tab->cur_offset_p++ = chunk_tab->cur_offset;
chunk_tab->cur_offset += out_chunk_size;
} else {
+ /* Write uncompressed */
out_chunk = chunk;
out_chunk_size = chunk_size;
}
/* Prepare for multiple reads to a resource by caching a FILE * or NTFS
* attribute pointer in the lookup table entry. */
-static int prepare_resource_for_read(struct wim_lookup_table_entry *lte
+static int
+prepare_resource_for_read(struct wim_lookup_table_entry *lte
- #ifdef WITH_NTFS_3G
- , ntfs_inode **ni_ret
- #endif
- )
+ #ifdef WITH_NTFS_3G
+ , ntfs_inode **ni_ret
+ #endif
+ )
{
switch (lte->resource_location) {
case RESOURCE_IN_FILE_ON_DISK:
- if (!lte->file_on_disk_fp) {
- lte->file_on_disk_fp = fopen(lte->file_on_disk, "rb");
+ if (!lte->file_on_disk_fp) {
+ lte->file_on_disk_fp = tfopen(lte->file_on_disk, T("rb"));
if (!lte->file_on_disk_fp) {
ERROR_WITH_ERRNO("Failed to open the file "
- "`%s'", lte->file_on_disk);
+ "`%"TS"'", lte->file_on_disk);
return WIMLIB_ERR_OPEN;
}
}
struct ntfs_location *loc = lte->ntfs_loc;
ntfs_inode *ni;
wimlib_assert(loc);
- ni = ntfs_pathname_to_inode(*loc->ntfs_vol_p, NULL, loc->path_utf8);
+ ni = ntfs_pathname_to_inode(*loc->ntfs_vol_p, NULL, loc->path);
if (!ni) {
- ERROR_WITH_ERRNO("Failed to open inode `%s' in NTFS "
- "volume", loc->path_utf8);
+ ERROR_WITH_ERRNO("Failed to open inode `%"TS"' in NTFS "
+ "volume", loc->path);
return WIMLIB_ERR_NTFS_3G;
}
lte->attr = ntfs_attr_open(ni,
loc->is_reparse_point ? AT_REPARSE_POINT : AT_DATA,
- (ntfschar*)loc->stream_name_utf16,
- loc->stream_name_utf16_num_chars);
+ loc->stream_name,
+ loc->stream_name_nchars);
if (!lte->attr) {
- ERROR_WITH_ERRNO("Failed to open attribute of `%s' in "
- "NTFS volume", loc->path_utf8);
+ ERROR_WITH_ERRNO("Failed to open attribute of `%"TS"' in "
+ "NTFS volume", loc->path);
ntfs_inode_close(ni);
return WIMLIB_ERR_NTFS_3G;
}
}
break;
#endif
-#if defined(__CYGWIN__) || defined(__WIN32__)
+#ifdef __WIN32__
case RESOURCE_WIN32:
- if (!lte->file_on_disk_fp) {
- lte->file_on_disk_fp = win32_open_file_readonly(lte->file_on_disk);
- if (!lte->file_on_disk_fp)
+ if (lte->win32_file_on_disk_fp == INVALID_HANDLE_VALUE) {
+ lte->win32_file_on_disk_fp =
+ win32_open_file_data_only(lte->file_on_disk);
+ if (lte->win32_file_on_disk_fp == INVALID_HANDLE_VALUE) {
+ ERROR("Win32 API: Can't open %"TS, lte->file_on_disk);
+ win32_error_last();
return WIMLIB_ERR_OPEN;
+ }
}
break;
#endif
/* Undo prepare_resource_for_read() by closing the cached FILE * or NTFS
* attribute. */
-static void end_wim_resource_read(struct wim_lookup_table_entry *lte
- #ifdef WITH_NTFS_3G
- , ntfs_inode *ni
- #endif
- )
+static void
+end_wim_resource_read(struct wim_lookup_table_entry *lte
+ #ifdef WITH_NTFS_3G
+ , ntfs_inode *ni
+ #endif
+ )
{
if (lte->resource_location == RESOURCE_IN_FILE_ON_DISK
&& lte->file_on_disk_fp)
ntfs_inode_close(ni);
}
#endif
-#if defined(__CYGWIN__) || defined(__WIN32__)
+#ifdef __WIN32__
else if (lte->resource_location == RESOURCE_WIN32
- && lte->file_on_disk_fp)
+ && lte->win32_file_on_disk_fp != INVALID_HANDLE_VALUE)
{
- win32_close_file(lte->file_on_disk_fp);
- lte->file_on_disk_fp = NULL;
+ win32_close_file(lte->win32_file_on_disk_fp);
+ lte->win32_file_on_disk_fp = INVALID_HANDLE_VALUE;
}
#endif
}
*
* Returns 0 on success; nonzero on failure.
*/
-int write_wim_resource(struct wim_lookup_table_entry *lte,
- FILE *out_fp, int out_ctype,
- struct resource_entry *out_res_entry,
- int flags)
+int
+write_wim_resource(struct wim_lookup_table_entry *lte,
+ FILE *out_fp, int out_ctype,
+ struct resource_entry *out_res_entry,
+ int flags)
{
u64 bytes_remaining;
u64 original_size;
} else if (!hashes_equal(md, lte->hash)) {
ERROR("WIM resource has incorrect hash!");
if (lte->resource_location == RESOURCE_IN_FILE_ON_DISK) {
- ERROR("We were reading it from `%s'; maybe it changed "
- "while we were reading it.",
+ ERROR("We were reading it from `%"TS"'; maybe "
+ "it changed while we were reading it.",
lte->file_on_disk);
}
ret = WIMLIB_ERR_INVALID_RESOURCE_HASH;
pthread_cond_t space_avail_cond;
};
-static int shared_queue_init(struct shared_queue *q, unsigned size)
+static int
+shared_queue_init(struct shared_queue *q, unsigned size)
{
wimlib_assert(size != 0);
q->array = CALLOC(sizeof(q->array[0]), size);
return 0;
}
-static void shared_queue_destroy(struct shared_queue *q)
+static void
+shared_queue_destroy(struct shared_queue *q)
{
FREE(q->array);
pthread_mutex_destroy(&q->lock);
pthread_cond_destroy(&q->space_avail_cond);
}
-static void shared_queue_put(struct shared_queue *q, void *obj)
+static void
+shared_queue_put(struct shared_queue *q, void *obj)
{
pthread_mutex_lock(&q->lock);
while (q->filled_slots == q->size)
pthread_mutex_unlock(&q->lock);
}
-static void *shared_queue_get(struct shared_queue *q)
+static void *
+shared_queue_get(struct shared_queue *q)
{
void *obj;
u64 begin_chunk;
};
-static void compress_chunks(struct message *msg, compress_func_t compress)
+static void
+compress_chunks(struct message *msg, compress_func_t compress)
{
for (unsigned i = 0; i < msg->num_chunks; i++) {
DEBUG2("compress chunk %u of %u", i, msg->num_chunks);
- int ret = compress(msg->uncompressed_chunks[i],
- msg->uncompressed_chunk_sizes[i],
- msg->compressed_chunks[i],
- &msg->compressed_chunk_sizes[i]);
- if (ret == 0) {
+ unsigned len = compress(msg->uncompressed_chunks[i],
+ msg->uncompressed_chunk_sizes[i],
+ msg->compressed_chunks[i]);
+ if (len) {
+ /* To be written compressed */
msg->out_compressed_chunks[i] = msg->compressed_chunks[i];
+ msg->compressed_chunk_sizes[i] = len;
} else {
+ /* To be written uncompressed */
msg->out_compressed_chunks[i] = msg->uncompressed_chunks[i];
msg->compressed_chunk_sizes[i] = msg->uncompressed_chunk_sizes[i];
+
}
}
}
* res_to_compress_queue, compress them, and put them in the
* compressed_res_queue. A NULL pointer indicates that the thread should stop.
* */
-static void *compressor_thread_proc(void *arg)
+static void *
+compressor_thread_proc(void *arg)
{
struct compressor_thread_params *params = arg;
struct shared_queue *res_to_compress_queue = params->res_to_compress_queue;
DEBUG("Compressor thread terminating");
return NULL;
}
-#endif
+#endif /* ENABLE_MULTITHREADED_COMPRESSION */
-static int do_write_stream_list(struct list_head *my_resources,
- FILE *out_fp,
- int out_ctype,
- wimlib_progress_func_t progress_func,
- union wimlib_progress_info *progress,
- int write_resource_flags)
+static void
+do_write_streams_progress(union wimlib_progress_info *progress,
+ wimlib_progress_func_t progress_func,
+ uint64_t size_added)
+{
+ progress->write_streams.completed_bytes += size_added;
+ progress->write_streams.completed_streams++;
+ if (progress_func &&
+ progress->write_streams.completed_bytes >= progress->write_streams._private)
+ {
+ progress_func(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
+ progress);
+ if (progress->write_streams._private == progress->write_streams.total_bytes) {
+ progress->write_streams._private = ~0;
+ } else {
+ progress->write_streams._private =
+ min(progress->write_streams.total_bytes,
+ progress->write_streams.completed_bytes +
+ progress->write_streams.total_bytes / 100);
+ }
+ }
+}
+
+static int
+do_write_stream_list(struct list_head *my_resources,
+ FILE *out_fp,
+ int out_ctype,
+ wimlib_progress_func_t progress_func,
+ union wimlib_progress_info *progress,
+ int write_resource_flags)
{
int ret;
struct wim_lookup_table_entry *lte, *tmp;
if (ret != 0)
return ret;
list_del(<e->staging_list);
- progress->write_streams.completed_bytes +=
- wim_resource_size(lte);
- progress->write_streams.completed_streams++;
- if (progress_func) {
- progress_func(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
- progress);
- }
+
+ do_write_streams_progress(progress,
+ progress_func,
+ wim_resource_size(lte));
}
return 0;
}
-static int write_stream_list_serial(struct list_head *stream_list,
- FILE *out_fp,
- int out_ctype,
- int write_flags,
- wimlib_progress_func_t progress_func,
- union wimlib_progress_info *progress)
+static int
+write_stream_list_serial(struct list_head *stream_list,
+ FILE *out_fp,
+ int out_ctype,
+ int write_flags,
+ wimlib_progress_func_t progress_func,
+ union wimlib_progress_info *progress)
{
int write_resource_flags;
}
#ifdef ENABLE_MULTITHREADED_COMPRESSION
-static int write_wim_chunks(struct message *msg, FILE *out_fp,
- struct chunk_table *chunk_tab)
+static int
+write_wim_chunks(struct message *msg, FILE *out_fp,
+ struct chunk_table *chunk_tab)
{
for (unsigned i = 0; i < msg->num_chunks; i++) {
unsigned chunk_csize = msg->compressed_chunk_sizes[i];
* res_to_compress_queue, and it is passed back through the
* compressed_res_queue.
*/
-static int main_writer_thread_proc(struct list_head *stream_list,
- FILE *out_fp,
- int out_ctype,
- struct shared_queue *res_to_compress_queue,
- struct shared_queue *compressed_res_queue,
- size_t num_messages,
- int write_flags,
- wimlib_progress_func_t progress_func,
- union wimlib_progress_info *progress)
+static int
+main_writer_thread_proc(struct list_head *stream_list,
+ FILE *out_fp,
+ int out_ctype,
+ struct shared_queue *res_to_compress_queue,
+ struct shared_queue *compressed_res_queue,
+ size_t num_messages,
+ int write_flags,
+ wimlib_progress_func_t progress_func,
+ union wimlib_progress_info *progress)
{
int ret;
struct chunk_table *cur_chunk_tab = NULL;
if (next_lte->resource_location ==
RESOURCE_IN_FILE_ON_DISK)
{
- ERROR("We were reading it from `%s'; "
+ ERROR("We were reading it from `%"TS"'; "
"maybe it changed while we were "
"reading it.",
next_lte->file_on_disk);
WIM_RESHDR_FLAG_COMPRESSED;
}
- progress->write_streams.completed_bytes +=
- wim_resource_size(cur_lte);
- progress->write_streams.completed_streams++;
-
- if (progress_func) {
- progress_func(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
- progress);
- }
+ do_write_streams_progress(progress, progress_func,
+ wim_resource_size(cur_lte));
FREE(cur_chunk_tab);
cur_chunk_tab = NULL;
return ret;
}
+static long
+get_default_num_threads()
+{
+#ifdef __WIN32__
+ return win32_get_number_of_processors();
+#else
+ return sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+}
-static int write_stream_list_parallel(struct list_head *stream_list,
- FILE *out_fp,
- int out_ctype,
- int write_flags,
- unsigned num_threads,
- wimlib_progress_func_t progress_func,
- union wimlib_progress_info *progress)
+static int
+write_stream_list_parallel(struct list_head *stream_list,
+ FILE *out_fp,
+ int out_ctype,
+ int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func,
+ union wimlib_progress_info *progress)
{
int ret;
struct shared_queue res_to_compress_queue;
pthread_t *compressor_threads = NULL;
if (num_threads == 0) {
- long nthreads = sysconf(_SC_NPROCESSORS_ONLN);
- if (nthreads < 1) {
+ long nthreads = get_default_num_threads();
+ if (nthreads < 1 || nthreads > UINT_MAX) {
WARNING("Could not determine number of processors! Assuming 1");
goto out_serial;
} else {
* Write a list of streams to a WIM (@out_fp) using the compression type
* @out_ctype and up to @num_threads compressor threads.
*/
-static int write_stream_list(struct list_head *stream_list, FILE *out_fp,
- int out_ctype, int write_flags,
- unsigned num_threads,
- wimlib_progress_func_t progress_func)
+static int
+write_stream_list(struct list_head *stream_list, FILE *out_fp,
+ int out_ctype, int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func)
{
struct wim_lookup_table_entry *lte;
size_t num_streams = 0;
progress.write_streams.completed_streams = 0;
progress.write_streams.num_threads = num_threads;
progress.write_streams.compression_type = out_ctype;
+ progress.write_streams._private = 0;
#ifdef ENABLE_MULTITHREADED_COMPRESSION
if (total_compression_bytes >= 1000000 && num_threads != 1)
struct list_head *stream_list;
};
-static int lte_overwrite_prepare(struct wim_lookup_table_entry *lte, void *arg)
+static int
+lte_overwrite_prepare(struct wim_lookup_table_entry *lte, void *arg)
{
struct lte_overwrite_prepare_args *args = arg;
lte->out_refcnt = lte->refcnt;
memcpy(<e->output_resource_entry, <e->resource_entry,
sizeof(struct resource_entry));
- if (!(lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA)) {
- wimlib_assert(lte->resource_location != RESOURCE_NONEXISTENT);
+ if (!(lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA))
if (lte->resource_location != RESOURCE_IN_WIM || lte->wim != args->wim)
list_add(<e->staging_list, args->stream_list);
- }
return 0;
}
-static int wim_find_new_streams(WIMStruct *wim, off_t end_offset,
- struct list_head *stream_list)
+static int
+wim_prepare_streams(WIMStruct *wim, off_t end_offset,
+ struct list_head *stream_list)
{
struct lte_overwrite_prepare_args args = {
.wim = wim,
.end_offset = end_offset,
.stream_list = stream_list,
};
+ int ret;
+ for (int i = 0; i < wim->hdr.image_count; i++) {
+ ret = lte_overwrite_prepare(wim->image_metadata[i].metadata_lte,
+ &args);
+ if (ret)
+ return ret;
+ }
return for_lookup_table_entry(wim->lookup_table,
lte_overwrite_prepare, &args);
}
-static int inode_find_streams_to_write(struct wim_inode *inode,
- struct wim_lookup_table *table,
- struct list_head *stream_list)
+static int
+inode_find_streams_to_write(struct wim_inode *inode,
+ struct wim_lookup_table *table,
+ struct list_head *stream_list)
{
struct wim_lookup_table_entry *lte;
for (unsigned i = 0; i <= inode->i_num_ads; i++) {
return 0;
}
-static int image_find_streams_to_write(WIMStruct *w)
+static int
+image_find_streams_to_write(WIMStruct *w)
{
struct wim_inode *inode;
struct hlist_node *cur;
return 0;
}
-static int write_wim_streams(WIMStruct *w, int image, int write_flags,
+static int
+write_wim_streams(WIMStruct *w, int image, int write_flags,
unsigned num_threads,
wimlib_progress_func_t progress_func)
{
* fsync() the output file before closing it.
*
*/
-int finish_write(WIMStruct *w, int image, int write_flags,
- wimlib_progress_func_t progress_func)
+int
+finish_write(WIMStruct *w, int image, int write_flags,
+ wimlib_progress_func_t progress_func)
{
int ret;
struct wim_header hdr;
memcpy(&hdr, &w->hdr, sizeof(struct wim_header));
if (!(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) {
- ret = write_lookup_table(w->lookup_table, out, &hdr.lookup_table_res_entry);
+ ret = write_lookup_table(w, image, &hdr.lookup_table_res_entry);
if (ret != 0)
goto out;
}
}
#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK)
-int lock_wim(WIMStruct *w, FILE *fp)
+int
+lock_wim(WIMStruct *w, FILE *fp)
{
int ret = 0;
if (fp && !w->wim_locked) {
ret = flock(fileno(fp), LOCK_EX | LOCK_NB);
if (ret != 0) {
if (errno == EWOULDBLOCK) {
- ERROR("`%s' is already being modified or has been "
+ ERROR("`%"TS"' is already being modified or has been "
"mounted read-write\n"
" by another process!", w->filename);
ret = WIMLIB_ERR_ALREADY_LOCKED;
} else {
- WARNING_WITH_ERRNO("Failed to lock `%s'",
+ WARNING_WITH_ERRNO("Failed to lock `%"TS"'",
w->filename);
ret = 0;
}
}
#endif
-static int open_wim_writable(WIMStruct *w, const char *path,
- bool trunc, bool readable)
+static int
+open_wim_writable(WIMStruct *w, const tchar *path,
+ bool trunc, bool also_readable)
{
- const char *mode;
+ const tchar *mode;
if (trunc)
- if (readable)
- mode = "w+b";
+ if (also_readable)
+ mode = T("w+b");
else
- mode = "wb";
+ mode = T("wb");
else
- mode = "r+b";
+ mode = T("r+b");
wimlib_assert(w->out_fp == NULL);
- w->out_fp = fopen(path, mode);
+ w->out_fp = tfopen(path, mode);
if (w->out_fp) {
return 0;
} else {
- ERROR_WITH_ERRNO("Failed to open `%s' for writing", path);
+ ERROR_WITH_ERRNO("Failed to open `%"TS"' for writing", path);
return WIMLIB_ERR_OPEN;
}
}
-void close_wim_writable(WIMStruct *w)
+void
+close_wim_writable(WIMStruct *w)
{
if (w->out_fp) {
if (fclose(w->out_fp) != 0) {
}
/* Open file stream and write dummy header for WIM. */
-int begin_write(WIMStruct *w, const char *path, int write_flags)
+int
+begin_write(WIMStruct *w, const tchar *path, int write_flags)
{
int ret;
ret = open_wim_writable(w, path, true,
}
/* Writes a stand-alone WIM to a file. */
-WIMLIBAPI int wimlib_write(WIMStruct *w, const char *path,
- int image, int write_flags, unsigned num_threads,
- wimlib_progress_func_t progress_func)
+WIMLIBAPI int
+wimlib_write(WIMStruct *w, const tchar *path,
+ int image, int write_flags, unsigned num_threads,
+ wimlib_progress_func_t progress_func)
{
int ret;
ret = finish_write(w, image, write_flags, progress_func);
out:
close_wim_writable(w);
- DEBUG("wimlib_write(path=%s) = %d", path, ret);
+ DEBUG("wimlib_write(path=%"TS") = %d", path, ret);
return ret;
}
-static bool any_images_modified(WIMStruct *w)
+static bool
+any_images_modified(WIMStruct *w)
{
for (int i = 0; i < w->hdr.image_count; i++)
if (w->image_metadata[i].modified)
* table, xml data, and integrity table were. (These usually only take up a
* small amount of space compared to the streams, however.)
*/
-static int overwrite_wim_inplace(WIMStruct *w, int write_flags,
- unsigned num_threads,
- wimlib_progress_func_t progress_func)
+static int
+overwrite_wim_inplace(WIMStruct *w, int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func)
{
int ret;
struct list_head stream_list;
off_t old_wim_end;
bool found_modified_image;
- DEBUG("Overwriting `%s' in-place", w->filename);
+ DEBUG("Overwriting `%"TS"' in-place", w->filename);
/* Make sure that the integrity table (if present) is after the XML
* data, and that there are no stream resources, metadata resources, or
WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML;
}
INIT_LIST_HEAD(&stream_list);
- ret = wim_find_new_streams(w, old_wim_end, &stream_list);
+ ret = wim_prepare_streams(w, old_wim_end, &stream_list);
if (ret != 0)
return ret;
found_modified_image = false;
for (int i = 0; i < w->hdr.image_count; i++) {
- if (!found_modified_image)
- found_modified_image = w->image_metadata[i].modified;
- if (found_modified_image) {
+ if (w->image_metadata[i].modified) {
select_wim_image(w, i + 1);
ret = write_metadata_resource(w);
if (ret != 0)
out_ftruncate:
close_wim_writable(w);
if (ret != 0 && !(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) {
- WARNING("Truncating `%s' to its original size (%"PRIu64" bytes)",
+ WARNING("Truncating `%"TS"' to its original size (%"PRIu64" bytes)",
w->filename, old_wim_end);
/* Return value of truncate() is ignored because this is already
* an error path. */
- (void)truncate(w->filename, old_wim_end);
+ (void)ttruncate(w->filename, old_wim_end);
}
w->wim_locked = 0;
return ret;
}
-static int overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
- unsigned num_threads,
- wimlib_progress_func_t progress_func)
+static int
+overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func)
{
size_t wim_name_len;
int ret;
- DEBUG("Overwriting `%s' via a temporary file", w->filename);
+ DEBUG("Overwriting `%"TS"' via a temporary file", w->filename);
/* Write the WIM to a temporary file in the same directory as the
* original WIM. */
- wim_name_len = strlen(w->filename);
- char tmpfile[wim_name_len + 10];
- memcpy(tmpfile, w->filename, wim_name_len);
+ wim_name_len = tstrlen(w->filename);
+ tchar tmpfile[wim_name_len + 10];
+ tmemcpy(tmpfile, w->filename, wim_name_len);
randomize_char_array_with_alnum(tmpfile + wim_name_len, 9);
- tmpfile[wim_name_len + 9] = '\0';
+ tmpfile[wim_name_len + 9] = T('\0');
ret = wimlib_write(w, tmpfile, WIMLIB_ALL_IMAGES,
write_flags | WIMLIB_WRITE_FLAG_FSYNC,
num_threads, progress_func);
if (ret != 0) {
- ERROR("Failed to write the WIM file `%s'", tmpfile);
+ ERROR("Failed to write the WIM file `%"TS"'", tmpfile);
goto err;
}
- DEBUG("Renaming `%s' to `%s'", tmpfile, w->filename);
+ DEBUG("Renaming `%"TS"' to `%"TS"'", tmpfile, w->filename);
+
+#ifdef __WIN32__
+ /* Windows won't let you delete open files unless FILE_SHARE_DELETE was
+ * specified to CreateFile(). The WIM was opened with fopen(), which
+ * didn't provided this flag to CreateFile, so the handle must be closed
+ * before executing the rename(). */
+ if (w->fp != NULL) {
+ fclose(w->fp);
+ w->fp = NULL;
+ }
+#endif
/* Rename the new file to the old file .*/
- if (rename(tmpfile, w->filename) != 0) {
- ERROR_WITH_ERRNO("Failed to rename `%s' to `%s'",
+ if (trename(tmpfile, w->filename) != 0) {
+ ERROR_WITH_ERRNO("Failed to rename `%"TS"' to `%"TS"'",
tmpfile, w->filename);
ret = WIMLIB_ERR_RENAME;
goto err;
}
/* Re-open the WIM read-only. */
- w->fp = fopen(w->filename, "rb");
+ w->fp = tfopen(w->filename, T("rb"));
if (w->fp == NULL) {
ret = WIMLIB_ERR_REOPEN;
- WARNING_WITH_ERRNO("Failed to re-open `%s' read-only",
+ WARNING_WITH_ERRNO("Failed to re-open `%"TS"' read-only",
w->filename);
FREE(w->filename);
w->filename = NULL;
return ret;
err:
/* Remove temporary file. */
- if (unlink(tmpfile) != 0)
- WARNING_WITH_ERRNO("Failed to remove `%s'", tmpfile);
+ if (tunlink(tmpfile) != 0)
+ WARNING_WITH_ERRNO("Failed to remove `%"TS"'", tmpfile);
return ret;
}
/*
* Writes a WIM file to the original file that it was read from, overwriting it.
*/
-WIMLIBAPI int wimlib_overwrite(WIMStruct *w, int write_flags,
- unsigned num_threads,
- wimlib_progress_func_t progress_func)
+WIMLIBAPI int
+wimlib_overwrite(WIMStruct *w, int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func)
{
write_flags &= WIMLIB_WRITE_MASK_PUBLIC;