]> wimlib.net Git - wimlib/blobdiff - src/write.c
Win32 fixes
[wimlib] / src / write.c
index 4e59b851ae2a17aafc04799eecfe4b02c7d11fc1..139ecdabc73dd74da20fc45cfaaa772dd8478e59 100644 (file)
 #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 "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
+
+#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)
+static int
+fflush_and_ftruncate(FILE *fp, off_t size)
 {
        int ret;
 
@@ -155,7 +166,8 @@ out:
  */
 typedef int (*compress_func_t)(const void *, unsigned, void *, unsigned *);
 
-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;
@@ -176,9 +188,10 @@ compress_func_t get_compress_func(int out_ctype)
  *
  * 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;
@@ -250,12 +263,13 @@ finish_wim_resource_chunk_tab(struct chunk_table *chunk_tab,
 
 /* 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:
@@ -274,19 +288,19 @@ static int prepare_resource_for_read(struct wim_lookup_table_entry *lte
                        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);
+                                                "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);
+                                                "NTFS volume", loc->path);
                                ntfs_inode_close(ni);
                                return WIMLIB_ERR_NTFS_3G;
                        }
@@ -294,12 +308,16 @@ static int prepare_resource_for_read(struct wim_lookup_table_entry *lte
                }
                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_readonly(lte->win32_file_on_disk, true);
+                       if (lte->win32_file_on_disk_fp == INVALID_HANDLE_VALUE) {
+                               ERROR("Win32 API: Can't open %ls", lte->win32_file_on_disk);
+                               win32_error_last();
                                return WIMLIB_ERR_OPEN;
+                       }
                }
                break;
 #endif
@@ -311,11 +329,12 @@ static int prepare_resource_for_read(struct wim_lookup_table_entry *lte
 
 /* 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)
@@ -333,12 +352,12 @@ static void end_wim_resource_read(struct wim_lookup_table_entry *lte
                        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
 }
@@ -385,10 +404,11 @@ write_uncompressed_resource_and_truncate(struct wim_lookup_table_entry *lte,
  *
  * 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;
@@ -582,7 +602,8 @@ struct shared_queue {
        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);
@@ -598,7 +619,8 @@ static int shared_queue_init(struct shared_queue *q, unsigned 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);
@@ -606,7 +628,8 @@ static void shared_queue_destroy(struct shared_queue *q)
        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)
@@ -620,7 +643,8 @@ static void shared_queue_put(struct shared_queue *q, void *obj)
        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;
 
@@ -659,7 +683,8 @@ struct message {
        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);
@@ -681,7 +706,8 @@ static void compress_chunks(struct message *msg, compress_func_t compress)
  * 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;
@@ -697,14 +723,15 @@ static void *compressor_thread_proc(void *arg)
        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 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;
@@ -729,12 +756,13 @@ static int do_write_stream_list(struct list_head *my_resources,
        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;
 
@@ -751,8 +779,9 @@ static int write_stream_list_serial(struct list_head *stream_list,
 }
 
 #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];
@@ -785,15 +814,16 @@ static int write_wim_chunks(struct message *msg, FILE *out_fp,
  * 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;
@@ -1205,14 +1235,24 @@ out:
        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;
@@ -1220,8 +1260,8 @@ static int write_stream_list_parallel(struct list_head *stream_list,
        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 {
@@ -1314,10 +1354,11 @@ out_serial:
  * 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;
@@ -1367,7 +1408,8 @@ struct lte_overwrite_prepare_args {
        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;
 
@@ -1393,8 +1435,9 @@ static int lte_overwrite_prepare(struct wim_lookup_table_entry *lte, void *arg)
        return 0;
 }
 
-static int wim_find_new_streams(WIMStruct *wim, off_t end_offset,
-                               struct list_head *stream_list)
+static int
+wim_find_new_streams(WIMStruct *wim, off_t end_offset,
+                    struct list_head *stream_list)
 {
        struct lte_overwrite_prepare_args args = {
                .wim         = wim,
@@ -1406,9 +1449,10 @@ static int wim_find_new_streams(WIMStruct *wim, off_t end_offset,
                                      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++) {
@@ -1422,7 +1466,8 @@ static int inode_find_streams_to_write(struct wim_inode *inode,
        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;
@@ -1436,7 +1481,8 @@ static int image_find_streams_to_write(WIMStruct *w)
        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)
 {
@@ -1479,8 +1525,9 @@ static int write_wim_streams(WIMStruct *w, int image, int write_flags,
  *             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;
@@ -1613,7 +1660,8 @@ 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) {
@@ -1637,8 +1685,9 @@ int lock_wim(WIMStruct *w, FILE *fp)
 }
 #endif
 
-static int open_wim_writable(WIMStruct *w, const char *path,
-                            bool trunc, bool readable)
+static int
+open_wim_writable(WIMStruct *w, const mbchar *path,
+                 bool trunc, bool readable)
 {
        const char *mode;
        if (trunc)
@@ -1660,7 +1709,8 @@ static int open_wim_writable(WIMStruct *w, const char *path,
 }
 
 
-void close_wim_writable(WIMStruct *w)
+void
+close_wim_writable(WIMStruct *w)
 {
        if (w->out_fp) {
                if (fclose(w->out_fp) != 0) {
@@ -1671,7 +1721,8 @@ void close_wim_writable(WIMStruct *w)
 }
 
 /* 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 mbchar *path, int write_flags)
 {
        int ret;
        ret = open_wim_writable(w, path, true,
@@ -1683,9 +1734,10 @@ int begin_write(WIMStruct *w, const char *path, int write_flags)
 }
 
 /* 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 mbchar *path,
+            int image, int write_flags, unsigned num_threads,
+            wimlib_progress_func_t progress_func)
 {
        int ret;
 
@@ -1729,7 +1781,8 @@ out:
        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)
@@ -1794,9 +1847,10 @@ static bool any_images_modified(WIMStruct *w)
  * 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;
@@ -1899,9 +1953,10 @@ out_ftruncate:
        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;
@@ -1911,7 +1966,7 @@ static int overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
        /* 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];
+       mbchar tmpfile[wim_name_len + 10];
        memcpy(tmpfile, w->filename, wim_name_len);
        randomize_char_array_with_alnum(tmpfile + wim_name_len, 9);
        tmpfile[wim_name_len + 9] = '\0';
@@ -1967,9 +2022,10 @@ err:
 /*
  * 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;