Update progress functions
authorEric Biggers <ebiggers3@gmail.com>
Thu, 22 May 2014 15:50:47 +0000 (10:50 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Thu, 22 May 2014 15:56:23 +0000 (10:56 -0500)
- Register progress function with WIM instead of explicitly specifying it
  with each function call
- Add support for user-supplied context
- Add support for aborting the current operation by returning a status
  from the progress function

30 files changed:
Makefile.am
NEWS
examples/applywim.c
examples/capturewim.c
include/wimlib.h
include/wimlib/apply.h
include/wimlib/capture.h
include/wimlib/integrity.h
include/wimlib/progress.h [new file with mode: 0644]
include/wimlib/wim.h
include/wimlib/write.h
programs/imagex.c
src/add_image.c
src/capture_common.c
src/export_image.c
src/extract.c
src/integrity.c
src/join.c
src/mount_image.c
src/ntfs-3g_capture.c
src/reference.c
src/split.c
src/template.c
src/unix_capture.c
src/update_image.c
src/util.c
src/wim.c
src/win32_apply.c
src/win32_capture.c
src/write.c

index 82a1b5d..1ff845a 100644 (file)
@@ -108,6 +108,7 @@ libwim_la_SOURCES =         \
        include/wimlib/metadata.h       \
        include/wimlib/pathlist.h       \
        include/wimlib/paths.h          \
+       include/wimlib/progress.h       \
        include/wimlib/reparse.h        \
        include/wimlib/resource.h       \
        include/wimlib/security.h       \
diff --git a/NEWS b/NEWS
index 3a79d47..1c78f53 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -35,6 +35,9 @@ Version 1.6.3-BETA:
                  WIMLIB_COMPRESSION_TYPE_LZX is now 2 (so it's the same as
                  WIMGAPI).
 
+               - Progress functions, including their prototypes as well as how
+                 they are provided to the library, have been changed.
+
                - 'struct wimlib_capture_config' has been removed.  The library
                  now takes the path to the configuration file directly.  This
                  affects wimlib_add_image(), wimlib_add_image_multisource(),
index a92b263..d687316 100644 (file)
@@ -8,9 +8,9 @@
 #define TO_PERCENT(numerator, denominator) \
        ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator))))
 
-static int
+static enum wimlib_progress_status
 extract_progress(enum wimlib_progress_msg msg,
-                const union wimlib_progress_info *info)
+                union wimlib_progress_info *info, void *progctx)
 {
        switch (msg) {
        case WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS:
@@ -21,7 +21,7 @@ extract_progress(enum wimlib_progress_msg msg,
        default:
                break;
        }
-       return 0;
+       return WIMLIB_PROGRESS_STATUS_CONTINUE;
 }
 
 int main(int argc, char **argv)
@@ -43,17 +43,18 @@ int main(int argc, char **argv)
        /* Open the WIM file as a WIMStruct.  */
        ret = wimlib_open_wim(wimpath,  /* Path of WIM file to open  */
                              0,        /* WIMLIB_OPEN_FLAG_* flags (0 means all defaults)  */
-                             &wim,     /* Return the WIMStruct pointer in this location  */
-                             NULL);    /* Progress function (NULL means none)  */
+                             &wim);    /* Return the WIMStruct pointer in this location  */
        if (ret != 0) /* Always should check the error codes.  */
                goto out;
 
+       /* Register our progress function.  */
+       wimlib_register_progress_function(wim, extract_progress, NULL);
+
        /* Extract the first image.  */
        ret = wimlib_extract_image(wim,     /* WIMStruct from which to extract the image  */
                                   1,       /* Image to extract  */
                                   destdir, /* Directory to extract the image to  */
-                                  0,       /* WIMLIB_EXTRACT_FLAG_* flags (0 means all defaults)  */
-                                  extract_progress);  /* Progress function  */
+                                  0);      /* WIMLIB_EXTRACT_FLAG_* flags (0 means all defaults)  */
 
 out:
        /* Free the WIMStruct.  Has no effect if the pointer to it is NULL.  */
index f271970..e6d4c5a 100644 (file)
@@ -8,9 +8,9 @@
 #define TO_PERCENT(numerator, denominator) \
        ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator))))
 
-static int
+static enum wimlib_progress_status
 write_progress(enum wimlib_progress_msg msg,
-              const union wimlib_progress_info *info)
+              union wimlib_progress_info *info, void *progctx)
 {
        switch (msg) {
        case WIMLIB_PROGRESS_MSG_WRITE_STREAMS:
@@ -21,7 +21,7 @@ write_progress(enum wimlib_progress_msg msg,
        default:
                break;
        }
-       return 0;
+       return WIMLIB_PROGRESS_STATUS_CONTINUE;
 }
 
 int main(int argc, char **argv)
@@ -45,14 +45,16 @@ int main(int argc, char **argv)
        if (ret != 0)  /* Always should check the error codes.  */
                goto out;
 
+       /* Register our progress function.  */
+       wimlib_register_progress_function(wim, write_progress, NULL);
+
        /* Add the directory tree to the WIMStruct as an image.  */
 
        ret = wimlib_add_image(wim,     /* WIMStruct to which to add the image    */
                               srcdir,  /* Directory from which to add the image  */
                               NULL,    /* Name to give the image (NULL means none)  */
                               NULL,    /* Capture configuration structure (NULL means none)  */
-                              0,       /* WIMLIB_ADD_FLAG_* flags (0 means all defaults)  */
-                              NULL);   /* Progress function (NULL means none) */
+                              0);      /* WIMLIB_ADD_FLAG_* flags (0 means all defaults)  */
        if (ret != 0)
                goto out;
 
@@ -62,8 +64,7 @@ int main(int argc, char **argv)
                           wimpath,  /* Path to write the WIM to             */
                           WIMLIB_ALL_IMAGES, /*  Image(s) in the WIM to write */
                           0,        /* WIMLIB_WRITE_FLAG_* flags (0 means all defaults)   */
-                          0,        /* Number of compressor threads (0 means default)  */
-                          write_progress); /* Progress function  */
+                          0);       /* Number of compressor threads (0 means default)  */
 
 out:
        /* Free the WIMStruct.  Has no effect if the pointer to it is NULL.  */
index a958bd0..728d132 100644 (file)
  * image read-write is an alternative to calling wimlib_update_image().
  */
 
-/** @defgroup G_progress Progress Messages
+/**
+ * @defgroup G_progress Progress Messages
  *
  * @brief Track the progress of long WIM operations.
  *
- * When operating on large archives, operations such as extraction will
- * naturally take a while to complete.  Because of this and to improve the
- * potential user-friendliness of library clients, a number of functions take a
- * pointer to a progress function of type ::wimlib_progress_func_t.  This
- * function will be called periodically during the WIM operation(s) to report on
- * the progress of the operation (for example, how many bytes have been written
- * so far).
+ * Library users can provide a progress function which will be called
+ * periodically during operations such as extracting a WIM image or writing a
+ * WIM image.  A ::WIMStruct can have a progress function of type
+ * ::wimlib_progress_func_t associated with it by calling
+ * wimlib_register_progress_function() or by opening the ::WIMStruct using
+ * wimlib_open_wim_with_progress().  Once this is done, the progress function
+ * will be called automatically during many operations, such as
+ * wimlib_extract_image() and wimlib_write().
+ *
+ * Some functions that do not operate directly on a user-provided ::WIMStruct,
+ * such as wimlib_join(), also take the progress function directly using an
+ * extended version of the function, such as wimlib_join_with_progress().
+ *
+ * In wimlib v1.6.3 and later, progress functions are no longer just
+ * unidirectional.  You can now return ::WIMLIB_PROGRESS_STATUS_ABORT to cause
+ * the current operation to be aborted.  wimlib v1.6.3 also added the third
+ * argument to ::wimlib_progress_func_t, which is a user-supplied context.
  */
 
 /** @defgroup G_writing_and_overwriting_wims Writing and Overwriting WIMs
@@ -519,7 +530,7 @@ enum wimlib_progress_msg {
        /** The contents of the WIM file are being checked against the integrity
         * table.  @p info will point to ::wimlib_progress_info.integrity.  This
         * message is only received (and may be received many times) when
-        * wimlib_open_wim() is called with the
+        * wimlib_open_wim_with_progress() is called with the
         * ::WIMLIB_OPEN_FLAG_CHECK_INTEGRITY flag.  */
        WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY = 16,
 
@@ -566,6 +577,23 @@ enum wimlib_progress_msg {
        WIMLIB_PROGRESS_MSG_WIMBOOT_EXCLUDE = 24,
 };
 
+/** Valid return values from user-provided progress functions
+ * (::wimlib_progress_func_t).
+ *
+ * (Note: if an invalid value is returned, ::WIMLIB_ERR_UNKNOWN_PROGRESS_STATUS
+ * will be issued.)
+ */
+enum wimlib_progress_status {
+
+       /** The operation should be continued.  This is the normal return value.
+        */
+       WIMLIB_PROGRESS_STATUS_CONTINUE = 0,
+
+       /** The operation should be aborted.  This will cause the current
+        * operation to fail with ::WIMLIB_ERR_ABORTED_BY_PROGRESS.  */
+       WIMLIB_PROGRESS_STATUS_ABORT    = 1,
+};
+
 /** A pointer to this union is passed to the user-supplied
  * ::wimlib_progress_func_t progress function.  One (or none) of the structures
  * contained in this union will be applicable for the operation
@@ -923,17 +951,28 @@ union wimlib_progress_info {
        } wimboot_exclude;
 };
 
-/** A user-supplied function that will be called periodically during certain WIM
- * operations.  The first argument will be the type of operation that is being
- * performed or is about to be started or has been completed.  The second
- * argument will be a pointer to one of a number of structures depending on the
- * first argument.  It may be @c NULL for some message types.
+/**
+ * A user-supplied function that will be called periodically during certain WIM
+ * operations.
+ *
+ * The first argument will be the type of operation that is being performed or
+ * is about to be started or has been completed.
+ *
+ * The second argument will be a pointer to one of a number of structures
+ * depending on the first argument.  It may be @c NULL for some message types.
+ * Note that although this argument is not @c const, users should not modify it
+ * except in explicitly documented cases.
  *
- * The return value of the progress function is currently ignored, but it may do
- * something in the future.  (Set it to 0 for now.)
+ * The third argument will be a user-supplied value that was provided when
+ * registering or specifying the progress function.
+ *
+ * This function must return one of the ::wimlib_progress_status values.  By
+ * default, you should return ::WIMLIB_PROGRESS_STATUS_CONTINUE (0).
  */
-typedef int (*wimlib_progress_func_t)(enum wimlib_progress_msg msg_type,
-                                     const union wimlib_progress_info *info);
+typedef enum wimlib_progress_status
+       (*wimlib_progress_func_t)(enum wimlib_progress_msg msg_type,
+                                 union wimlib_progress_info *info,
+                                 void *progctx);
 
 /** @} */
 /** @ingroup G_modifying_wims
@@ -2023,6 +2062,8 @@ enum wimlib_error_code {
        WIMLIB_ERR_XML,
        WIMLIB_ERR_WIM_IS_ENCRYPTED,
        WIMLIB_ERR_WIMBOOT,
+       WIMLIB_ERR_ABORTED_BY_PROGRESS,
+       WIMLIB_ERR_UNKNOWN_PROGRESS_STATUS,
 };
 
 
@@ -2110,12 +2151,6 @@ wimlib_add_empty_image(WIMStruct *wim,
  *     ::WIMLIB_ADD_FLAG_WIMBOOT flags modify the default.
  * @param add_flags
  *     Bitwise OR of flags prefixed with WIMLIB_ADD_FLAG.
- * @param progress_func
- *     If non-NULL, a function that will be called periodically with the
- *     progress of the current operation.  The progress messages that will be
- *     received are ::WIMLIB_PROGRESS_MSG_SCAN_BEGIN,
- *     ::WIMLIB_PROGRESS_MSG_SCAN_END, and, if ::WIMLIB_ADD_FLAG_VERBOSE was
- *     included in @p add_flags, also ::WIMLIB_PROGRESS_MSG_SCAN_DENTRY.
  *
  * @return 0 on success; nonzero on error.  On error, changes to @p wim are
  * discarded so that it appears to be in the same state as when this function
@@ -2126,14 +2161,18 @@ wimlib_add_empty_image(WIMStruct *wim,
  * returned by wimlib_add_empty_image() may be returned, as well as any error
  * codes returned by wimlib_update_image() other than ones documented as only
  * being returned specifically by an update involving delete or rename commands.
+ *
+ * If a progress function is registered with @p wim, it will receive the
+ * messages ::WIMLIB_PROGRESS_MSG_SCAN_BEGIN and ::WIMLIB_PROGRESS_MSG_SCAN_END.
+ * In addition, if ::WIMLIB_ADD_FLAG_VERBOSE is specified in @p add_flags, it
+ * will receive ::WIMLIB_PROGRESS_MSG_SCAN_DENTRY.
  */
 extern int
 wimlib_add_image(WIMStruct *wim,
                 const wimlib_tchar *source,
                 const wimlib_tchar *name,
                 const wimlib_tchar *config_file,
-                int add_flags,
-                wimlib_progress_func_t progress_func);
+                int add_flags);
 
 /**
  * @ingroup G_modifying_wims
@@ -2161,8 +2200,7 @@ wimlib_add_image_multisource(WIMStruct *wim,
                             size_t num_sources,
                             const wimlib_tchar *name,
                             const wimlib_tchar *config_file,
-                            int add_flags,
-                            wimlib_progress_func_t progress_func);
+                            int add_flags);
 
 /**
  * @ingroup G_modifying_wims
@@ -2303,10 +2341,6 @@ wimlib_delete_path(WIMStruct *wim, int image,
  *     parameter is overridden by ::WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS.
  * @param export_flags
  *     Bitwise OR of flags prefixed with WIMLIB_EXPORT_FLAG.
- * @param progress_func
- *     Currently ignored, but reserved for a function that will be called with
- *     information about the operation.  Use NULL if no additional information
- *     is desired.
  *
  * @return 0 on success; nonzero on error.
  * @retval ::WIMLIB_ERR_IMAGE_NAME_COLLISION
@@ -2348,9 +2382,7 @@ wimlib_export_image(WIMStruct *src_wim, int src_image,
                    WIMStruct *dest_wim,
                    const wimlib_tchar *dest_name,
                    const wimlib_tchar *dest_description,
-                   int export_flags,
-                   wimlib_progress_func_t progress_func);
-
+                   int export_flags);
 
 /**
  * @ingroup G_extracting_wims
@@ -2383,11 +2415,6 @@ wimlib_export_image(WIMStruct *src_wim, int src_image,
  *     the unmounted NTFS volume to which to extract the image.
  * @param extract_flags
  *     Bitwise OR of flags prefixed with WIMLIB_EXTRACT_FLAG.
- * @param progress_func
- *     If non-NULL, a function that will be called periodically with the
- *     progress of the current operation.  The main message to look for is
- *     ::WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS; however, there are others as
- *     well.
  *
  * @return 0 on success; nonzero on error.
  * @retval ::WIMLIB_ERR_DECOMPRESSION
@@ -2463,12 +2490,15 @@ wimlib_export_image(WIMStruct *src_wim, int src_image,
  *     there was a problem creating WIMBoot pointer files.
  * @retval ::WIMLIB_ERR_WRITE
  *     Failed to write data to a file being extracted.
+ *
+ * If a progress function is registered with @p wim, then as each image is
+ * extracted it will receive ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN, then
+ * zero or more ::WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS messages, then
+ * ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END.
  */
 extern int
 wimlib_extract_image(WIMStruct *wim, int image,
-                    const wimlib_tchar *target,
-                    int extract_flags,
-                    wimlib_progress_func_t progress_func);
+                    const wimlib_tchar *target, int extract_flags);
 
 /**
  * @ingroup G_extracting_wims
@@ -2499,10 +2529,6 @@ wimlib_extract_image(WIMStruct *wim, int image,
  *     Same as the corresponding parameter to wimlib_extract_image().
  * @param extract_flags
  *     Same as the corresponding parameter to wimlib_extract_image().
- * @param progress_func
- *     Same as the corresponding parameter to wimlib_extract_image(), except
- *     ::WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN messages will also be
- *     received by the progress function.
  *
  * @return 0 on success; nonzero on error.  The possible error codes include
  * those returned by wimlib_extract_image() and wimlib_open_wim() as well as the
@@ -2516,8 +2542,24 @@ wimlib_extract_image(WIMStruct *wim, int image,
 extern int
 wimlib_extract_image_from_pipe(int pipe_fd,
                               const wimlib_tchar *image_num_or_name,
-                              const wimlib_tchar *target, int extract_flags,
-                              wimlib_progress_func_t progress_func);
+                              const wimlib_tchar *target, int extract_flags);
+
+/*
+ * @ingroup G_extracting_wims
+ *
+ * Same as wimlib_extract_image_from_pipe(), but allows specifying a progress
+ * function.  The progress function will be used while extracting the WIM image
+ * and will receive the normal extraction progress messages, such as
+ * ::WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS, in addition to
+ * ::WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN.
+ */
+extern int
+wimlib_extract_image_from_pipe_with_progress(int pipe_fd,
+                                            const wimlib_tchar *image_num_or_name,
+                                            const wimlib_tchar *target,
+                                            int extract_flags,
+                                            wimlib_progress_func_t progfunc,
+                                            void *progctx);
 
 /**
  * @ingroup G_extracting_wims
@@ -2538,8 +2580,7 @@ extern int
 wimlib_extract_pathlist(WIMStruct *wim, int image,
                        const wimlib_tchar *target,
                        const wimlib_tchar *path_list_file,
-                       int extract_flags,
-                       wimlib_progress_func_t progress_func);
+                       int extract_flags);
 
 /**
  * @ingroup G_extracting_wims
@@ -2593,15 +2634,6 @@ wimlib_extract_pathlist(WIMStruct *wim, int image,
  *     systems it may not contain backslashes, for example.
  * @param extract_flags
  *     Bitwise OR of flags prefixed with WIMLIB_EXTRACT_FLAG.
- * @param progress_func
- *     If non-NULL, a function that will be called periodically with the
- *     progress of the current operation.  The main message to look for is
- *     ::WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS; however, there are others as
- *     well.  Note: because the extraction code is stream-based and not
- *     file-based, there is no way to get information about which path is
- *     currently being extracted, but based on byte count you can still
- *     calculate an approximate percentage complete for the extraction overall
- *     which may be all you really need anyway.
  *
  * @return 0 on success; nonzero on error.  Most of the error codes are the same
  * as those returned by wimlib_extract_image().  Below, some of the error codes
@@ -2619,6 +2651,13 @@ wimlib_extract_pathlist(WIMStruct *wim, int image,
  * @retval ::WIMLIB_ERR_NOT_A_REGULAR_FILE
  *     ::WIMLIB_EXTRACT_FLAG_TO_STDOUT was specified in @p extract_flags, but
  *     one of the paths to extract did not name a regular file.
+ *
+ * If a progress function is registered with @p wim, it will receive
+ * ::WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS.  Note that because the extraction code
+ * is stream-based and not file-based, there is no way to get information about
+ * which path is currently being extracted, but based on byte count you can
+ * still calculate an approximate percentage complete for the extraction overall
+ * which may be all you really need anyway.
  */
 extern int
 wimlib_extract_paths(WIMStruct *wim,
@@ -2626,8 +2665,7 @@ wimlib_extract_paths(WIMStruct *wim,
                     const wimlib_tchar *target,
                     const wimlib_tchar * const *paths,
                     size_t num_paths,
-                    int extract_flags,
-                    wimlib_progress_func_t progress_func);
+                    int extract_flags);
 
 /**
  * @ingroup G_wim_information
@@ -2964,9 +3002,6 @@ wimlib_iterate_lookup_table(WIMStruct *wim, int flags,
  *     be used to write the joined WIM.
  * @param output_path
  *     The path to write the joined WIM file to.
- * @param progress_func
- *     If non-NULL, a function that will be called periodically with the
- *     progress of the current operation.
  *
  * @return 0 on success; nonzero on error.  This function may return most error
  * codes that can be returned by wimlib_open_wim() and wimlib_write(), as well
@@ -2989,8 +3024,27 @@ wimlib_join(const wimlib_tchar * const *swms,
            unsigned num_swms,
            const wimlib_tchar *output_path,
            int swm_open_flags,
-           int wim_write_flags,
-           wimlib_progress_func_t progress_func);
+           int wim_write_flags);
+
+/**
+ * @ingroup G_nonstandalone_wims
+ *
+ * Same as wimlib_join(), but allows specifying a progress function.  The
+ * progress function will receive the write progress messages, such as
+ * ::WIMLIB_PROGRESS_MSG_WRITE_STREAMS, while writing the joined WIM.  In
+ * addition, if ::WIMLIB_OPEN_FLAG_CHECK_INTEGRITY is specified in @p
+ * swm_open_flags, the progress function will receive a series of
+ * ::WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY messages when each of the split WIM
+ * parts is opened.
+ */
+extern int
+wimlib_join_with_progress(const wimlib_tchar * const *swms,
+                         unsigned num_swms,
+                         const wimlib_tchar *output_path,
+                         int swm_open_flags,
+                         int wim_write_flags,
+                         wimlib_progress_func_t progfunc,
+                         void *progctx);
 
 
 /**
@@ -3091,12 +3145,6 @@ wimlib_mount_image(WIMStruct *wim,
  * @param open_flags
  *     Bitwise OR of flags prefixed with WIMLIB_OPEN_FLAG.
  *
- * @param progress_func
- *     If non-NULL, a function that will be called periodically with the
- *     progress of the current operation.  Currently, the only messages sent
- *     will be ::WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY, and only if
- *     ::WIMLIB_OPEN_FLAG_CHECK_INTEGRITY was specified in @p open_flags.
- *
  * @param wim_ret
  *     On success, a pointer to an opaque ::WIMStruct for the opened WIM file
  *     is written to the memory location pointed to by this parameter.  The
@@ -3158,8 +3206,24 @@ wimlib_mount_image(WIMStruct *wim,
 extern int
 wimlib_open_wim(const wimlib_tchar *wim_file,
                int open_flags,
-               WIMStruct **wim_ret,
-               wimlib_progress_func_t progress_func);
+               WIMStruct **wim_ret);
+
+/**
+ * @ingroup G_creating_and_opening_wims
+ *
+ * Same as wimlib_open_wim(), but allows specifying a progress function and
+ * progress context.  If successful, the progress function will be registered in
+ * the newly open ::WIMStruct.  In addition, if
+ * ::WIMLIB_OPEN_FLAG_CHECK_INTEGRITY is specified in @p open_flags, the
+ * progress function will receive ::WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY
+ * messages while checking the WIM's integrity.
+ */
+extern int
+wimlib_open_wim_with_progress(const wimlib_tchar *wim_file,
+                             int open_flags,
+                             WIMStruct **wim_ret,
+                             wimlib_progress_func_t progfunc,
+                             void *progctx);
 
 /**
  * @ingroup G_writing_and_overwriting_wims
@@ -3213,9 +3277,6 @@ wimlib_open_wim(const wimlib_tchar *wim_file,
  *     Bitwise OR of relevant flags prefixed with WIMLIB_WRITE_FLAG.
  * @param num_threads
  *     Number of threads to use for compression (see wimlib_write()).
- * @param progress_func
- *     If non-NULL, a function that will be called periodically with the
- *     progress of the current operation.
  *
  * @return 0 on success; nonzero on error.  This function may return most error
  * codes returned by wimlib_write() as well as the following error codes:
@@ -3235,10 +3296,14 @@ wimlib_open_wim(const wimlib_tchar *wim_file,
  *     The WIM file is considered read-only because of any of the reasons
  *     mentioned in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS
  *     flag.
+ *
+ * If a progress function is registered with @p wim, it will receive the
+ * messages ::WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
+ * ::WIMLIB_PROGRESS_MSG_WRITE_METADATA_BEGIN, and
+ * ::WIMLIB_PROGRESS_MSG_WRITE_METADATA_END.
  */
 extern int
-wimlib_overwrite(WIMStruct *wim, int write_flags, unsigned num_threads,
-                wimlib_progress_func_t progress_func);
+wimlib_overwrite(WIMStruct *wim, int write_flags, unsigned num_threads);
 
 /**
  * @ingroup G_wim_information
@@ -3297,8 +3362,6 @@ wimlib_print_header(const WIMStruct *wim) _wimlib_deprecated;
  * @param open_flags
  *     Additional open flags, such as ::WIMLIB_OPEN_FLAG_CHECK_INTEGRITY, to
  *     pass to internal calls to wimlib_open_wim() on the reference files.
- * @param progress_func
- *     Passed to internal calls to wimlib_open_wim() on the reference files.
  *
  * @return 0 on success; nonzero on error.
  *
@@ -3319,8 +3382,7 @@ wimlib_reference_resource_files(WIMStruct *wim,
                                const wimlib_tchar * const *resource_wimfiles_or_globs,
                                unsigned count,
                                int ref_flags,
-                               int open_flags,
-                               wimlib_progress_func_t progress_func);
+                               int open_flags);
 
 /**
  * @ingroup G_nonstandalone_wims
@@ -3400,10 +3462,6 @@ wimlib_reference_resources(WIMStruct *wim, WIMStruct **resource_wims,
  *     of the directory tree being captured.
  * @param flags
  *     Reserved; must be 0.
- * @param progress_func
- *     Currently ignored, but reserved for a function that will be called with
- *     information about the operation.  Use NULL if no additional information
- *     is desired.
  *
  * @return 0 on success; nonzero on error.
  *
@@ -3429,7 +3487,27 @@ wimlib_reference_resources(WIMStruct *wim, WIMStruct **resource_wims,
 extern int
 wimlib_reference_template_image(WIMStruct *wim, int new_image,
                                WIMStruct *template_wim, int template_image,
-                               int flags, wimlib_progress_func_t progress_func);
+                               int flags);
+
+/**
+ * @ingroup G_general
+ *
+ * Registers a progress function with a ::WIMStruct.
+ *
+ * @param wim
+ *     The ::WIMStruct for which to register the progress function.
+ * @param progfunc
+ *     Pointer to the progress function to register.  If the WIM already has a
+ *     progress function registered, it will be replaced with this one.  If @p
+ *     NULL, the current progress function (if any) will be unregistered.
+ * @param progctx
+ *     The value which will be passed as the third argument to calls to @p
+ *     progfunc.
+ */
+extern void
+wimlib_register_progress_function(WIMStruct *wim,
+                                 wimlib_progress_func_t progfunc,
+                                 void *progctx);
 
 /**
  * @ingroup G_modifying_wims
@@ -3742,11 +3820,6 @@ wimlib_set_print_errors(bool show_messages);
  *     Bitwise OR of relevant flags prefixed with @c WIMLIB_WRITE_FLAG.  These
  *     flags will be used to write each split WIM part.  Specify 0 here to get
  *     the default behavior.
- * @param progress_func
- *     If non-NULL, a function that will be called periodically with the
- *     progress of the current operation
- *     (::WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART and
- *     ::WIMLIB_PROGRESS_MSG_SPLIT_END_PART).
  *
  * @return 0 on success; nonzero on error.  This function may return most error
  * codes that can be returned by wimlib_write() as well as the following error
@@ -3759,13 +3832,17 @@ wimlib_set_print_errors(bool show_messages);
  * when they are copied from the joined WIM to the split WIM parts, nor are
  * compressed resources re-compressed (unless explicitly requested with
  * ::WIMLIB_WRITE_FLAG_RECOMPRESS).
+ *
+ * If a progress function is registered with @p wim, for each split WIM part
+ * that is written it will receive the messages
+ * ::WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART and
+ * ::WIMLIB_PROGRESS_MSG_SPLIT_END_PART.
  */
 extern int
 wimlib_split(WIMStruct *wim,
             const wimlib_tchar *swm_name,
             uint64_t part_size,
-            int write_flags,
-            wimlib_progress_func_t progress_func);
+            int write_flags);
 
 /**
  * @ingroup G_mounting_wim_images
@@ -3789,10 +3866,6 @@ wimlib_split(WIMStruct *wim,
  *     ::WIMLIB_UNMOUNT_FLAG_COMMIT, ::WIMLIB_UNMOUNT_FLAG_REBUILD, and/or
  *     ::WIMLIB_UNMOUNT_FLAG_RECOMPRESS.  None of these flags affect read-only
  *     mounts.
- * @param progress_func
- *     If non-NULL, a function that will be called periodically with the
- *     progress of the current operation.  Currently, only
- *     ::WIMLIB_PROGRESS_MSG_WRITE_STREAMS will be sent.
  *
  * @return 0 on success; nonzero on error.
  *
@@ -3833,8 +3906,20 @@ wimlib_split(WIMStruct *wim,
  */
 extern int
 wimlib_unmount_image(const wimlib_tchar *dir,
-                    int unmount_flags,
-                    wimlib_progress_func_t progress_func);
+                    int unmount_flags);
+
+/**
+ * @ingroup G_mounting_wim_images
+ *
+ * Same as wimlib_unmount_image(), but allows specifying a progress function.
+ * If changes are committed from a read-write mount, the progress function will
+ * receive ::WIMLIB_PROGRESS_MSG_WRITE_STREAMS messages.
+ */
+extern int
+wimlib_unmount_image_with_progress(const wimlib_tchar *dir,
+                                  int unmount_flags,
+                                  wimlib_progress_func_t progfunc,
+                                  void *progctx);
 
 /**
  * @ingroup G_modifying_wims
@@ -3853,9 +3938,6 @@ wimlib_unmount_image(const wimlib_tchar *dir,
  *     Number of commands in @p cmds.
  * @param update_flags
  *     ::WIMLIB_UPDATE_FLAG_SEND_PROGRESS or 0.
- * @param progress_func
- *     If non-NULL, a function that will be called periodically with the
- *     progress of the current operation.
  *
  * @return 0 on success; nonzero on error.  On failure, all update commands will
  * be rolled back, and no visible changes shall have been made to @p wim.
@@ -3946,8 +4028,7 @@ wimlib_update_image(WIMStruct *wim,
                    int image,
                    const struct wimlib_update_command *cmds,
                    size_t num_cmds,
-                   int update_flags,
-                   wimlib_progress_func_t progress_func);
+                   int update_flags);
 
 /**
  * @ingroup G_writing_and_overwriting_wims
@@ -3983,12 +4064,6 @@ wimlib_update_image(WIMStruct *wim,
  *     exporting an image from a compressed WIM to another WIM of the same
  *     compression type without ::WIMLIB_WRITE_FLAG_RECOMPRESS specified in @p
  *     write_flags).
- * @param progress_func
- *     If non-NULL, a function that will be called periodically with the
- *     progress of the current operation.  The possible messages are
- *     ::WIMLIB_PROGRESS_MSG_WRITE_METADATA_BEGIN,
- *     ::WIMLIB_PROGRESS_MSG_WRITE_METADATA_END, and
- *     ::WIMLIB_PROGRESS_MSG_WRITE_STREAMS.
  *
  * @return 0 on success; nonzero on error.
  *
@@ -4027,14 +4102,18 @@ wimlib_update_image(WIMStruct *wim,
  * ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE, all of which indicate failure (for
  * different reasons) to read the metadata resource for an image that needed to
  * be written.
+ *
+ * If a progress function is registered with @p wim, it will receive the
+ * messages ::WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
+ * ::WIMLIB_PROGRESS_MSG_WRITE_METADATA_BEGIN, and
+ * ::WIMLIB_PROGRESS_MSG_WRITE_METADATA_END.
  */
 extern int
 wimlib_write(WIMStruct *wim,
             const wimlib_tchar *path,
             int image,
             int write_flags,
-            unsigned num_threads,
-            wimlib_progress_func_t progress_func);
+            unsigned num_threads);
 
 /**
  * @ingroup G_writing_and_overwriting_wims
@@ -4061,8 +4140,7 @@ wimlib_write_to_fd(WIMStruct *wim,
                   int fd,
                   int image,
                   int write_flags,
-                  unsigned num_threads,
-                  wimlib_progress_func_t progress_func);
+                  unsigned num_threads);
 
 /**
  * @defgroup G_compression Compression and decompression functions
index 72c21b5..6c595d5 100644 (file)
@@ -2,6 +2,7 @@
 #define _WIMLIB_APPLY_H
 
 #include "wimlib/list.h"
+#include "wimlib/progress.h"
 #include "wimlib/types.h"
 #include "wimlib.h"
 
@@ -46,7 +47,8 @@ struct apply_ctx {
        int extract_flags;
 
        /* User-provided progress function, or NULL if not specified.  */
-       wimlib_progress_func_t progress_func;
+       wimlib_progress_func_t progfunc;
+       void *progctx;
 
        /* Progress data buffer, with progress.extract initialized.  */
        union wimlib_progress_info progress;
@@ -66,6 +68,12 @@ struct apply_ctx {
        struct wim_lookup_table_entry *cur_stream;
 };
 
+static inline int
+extract_progress(struct apply_ctx *ctx, enum wimlib_progress_msg msg)
+{
+       return call_progress(ctx->progfunc, msg, &ctx->progress, ctx->progctx);
+}
+
 /* Returns any of the aliases of an inode that are being extracted.  */
 #define inode_first_extraction_dentry(inode)           \
        list_first_entry(&(inode)->i_extraction_aliases,        \
index f7ae1ad..58e0eac 100644 (file)
@@ -45,9 +45,9 @@ struct add_image_params {
         * libntfs-3g capture.  */
        void *extra_arg;
 
-
        /* If non-NULL, the user-supplied progress function. */
-       wimlib_progress_func_t progress_func;
+       wimlib_progress_func_t progfunc;
+       void *progctx;
 
        /* Progress data.  */
        union wimlib_progress_info progress;
@@ -58,10 +58,9 @@ struct add_image_params {
        size_t capture_root_nchars;
 };
 
-
 /* capture_common.c */
 
-extern void
+extern int
 do_capture_progress(struct add_image_params *params, int status,
                    const struct wim_inode *inode);
 
index c9e07ca..1d115ff 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _WIMLIB_INTEGRITY_H
 #define _WIMLIB_INTEGRITY_H
 
-#include "wimlib.h"
+#include "wimlib/types.h"
 #include <sys/types.h>
 
 #define WIM_INTEGRITY_OK 0
 extern int
 write_integrity_table(WIMStruct *wim,
                      off_t new_lookup_table_end,
-                     off_t old_lookup_table_end,
-                     wimlib_progress_func_t progress_func);
+                     off_t old_lookup_table_end);
 
 extern int
-check_wim_integrity(WIMStruct *wim, wimlib_progress_func_t progress_func);
+check_wim_integrity(WIMStruct *wim);
 
 #endif /* _WIMLIB_INTEGRITY_H */
diff --git a/include/wimlib/progress.h b/include/wimlib/progress.h
new file mode 100644 (file)
index 0000000..387afd8
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _WIMLIB_PROGRESS_H
+#define _WIMLIB_PROGRESS_H
+
+#include "wimlib.h"
+
+/* If specified, call the user-provided progress function and check its result.
+ */
+static inline int
+call_progress(wimlib_progress_func_t progfunc,
+             enum wimlib_progress_msg msg,
+             union wimlib_progress_info *info,
+             void *progctx)
+{
+       if (progfunc) {
+               enum wimlib_progress_status status;
+
+               status = (*progfunc)(msg, info, progctx);
+
+               switch (status) {
+               case WIMLIB_PROGRESS_STATUS_CONTINUE:
+                       return 0;
+               case WIMLIB_PROGRESS_STATUS_ABORT:
+                       return WIMLIB_ERR_ABORTED_BY_PROGRESS;
+               default:
+                       return WIMLIB_ERR_UNKNOWN_PROGRESS_STATUS;
+               }
+       }
+       return 0;
+}
+
+#endif
index ea916aa..86926d8 100644 (file)
@@ -92,6 +92,11 @@ struct WIMStruct {
        /* Chunk size for writing packed streams; can be set with
         * wimlib_set_output_pack_chunk_size().  */
        u32 out_pack_chunk_size;
+
+       /* Currently registered progress function for this WIMStruct, or NULL if
+        * no progress function is currently registered for this WIMStruct.  */
+       wimlib_progress_func_t progfunc;
+       void *progctx;
 };
 
 static inline bool wim_is_pipable(const WIMStruct *wim)
@@ -147,7 +152,7 @@ wim_checksum_unhashed_streams(WIMStruct *wim);
 extern int
 open_wim_as_WIMStruct(const void *wim_filename_or_fd, int open_flags,
                      WIMStruct **wim_ret,
-                     wimlib_progress_func_t progress_func);
+                     wimlib_progress_func_t progfunc, void *progctx);
 
 extern int
 close_wim(WIMStruct *wim);
index 7e913e1..68ada29 100644 (file)
@@ -49,7 +49,6 @@ write_wim_part(WIMStruct *wim,
               int image,
               int write_flags,
               unsigned num_threads,
-              wimlib_progress_func_t progress_func,
               unsigned part_number,
               unsigned total_parts,
               struct list_head *stream_list_override,
index 8cd5f67..41ab646 100644 (file)
@@ -130,9 +130,6 @@ static void usage_all(FILE *fp);
 static void recommend_man_page(int cmd, FILE *fp);
 static const tchar *get_cmd_string(int cmd, bool nospace);
 
-static int imagex_progress_func(enum wimlib_progress_msg msg,
-                               const union wimlib_progress_info *info);
-
 static bool imagex_be_quiet = false;
 static FILE *imagex_info_file;
 
@@ -580,8 +577,7 @@ wim_reference_globs(WIMStruct *wim, struct string_set *set, int open_flags)
        return wimlib_reference_resource_files(wim, set->strings,
                                               set->num_strings,
                                               WIMLIB_REF_FLAG_GLOB_ENABLE,
-                                              open_flags,
-                                              imagex_progress_func);
+                                              open_flags);
 }
 
 static void
@@ -1020,18 +1016,18 @@ report_scan_progress(const struct wimlib_progress_info_scan *scan, bool done)
                last_scan_progress = *scan;
        }
 }
-
 /* Progress callback function passed to various wimlib functions. */
-static int
+static enum wimlib_progress_status
 imagex_progress_func(enum wimlib_progress_msg msg,
-                    const union wimlib_progress_info *info)
+                    union wimlib_progress_info *info,
+                    void *_ignored_context)
 {
        unsigned percent_done;
        unsigned unit_shift;
        const tchar *unit_name;
 
        if (imagex_be_quiet)
-               return 0;
+               return WIMLIB_PROGRESS_STATUS_CONTINUE;
        switch (msg) {
        case WIMLIB_PROGRESS_MSG_WRITE_STREAMS:
                {
@@ -1206,7 +1202,7 @@ imagex_progress_func(enum wimlib_progress_msg msg,
                break;
        }
        fflush(imagex_info_file);
-       return 0;
+       return WIMLIB_PROGRESS_STATUS_CONTINUE;
 }
 
 static unsigned
@@ -1526,8 +1522,8 @@ imagex_apply(int argc, tchar **argv, int cmd)
                }
                wim = NULL;
        } else {
-               ret = wimlib_open_wim(wimfile, open_flags, &wim,
-                                     imagex_progress_func);
+               ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
+                                                   imagex_progress_func, NULL);
                if (ret)
                        goto out_free_refglobs;
 
@@ -1589,14 +1585,16 @@ imagex_apply(int argc, tchar **argv, int cmd)
 #endif
 
        if (wim) {
-               ret = wimlib_extract_image(wim, image, target, extract_flags,
-                                          imagex_progress_func);
+               ret = wimlib_extract_image(wim, image, target, extract_flags);
        } else {
                set_fd_to_binary_mode(STDIN_FILENO);
-               ret = wimlib_extract_image_from_pipe(STDIN_FILENO,
-                                                    image_num_or_name,
-                                                    target, extract_flags,
-                                                    imagex_progress_func);
+               ret = wimlib_extract_image_from_pipe_with_progress(
+                                          STDIN_FILENO,
+                                          image_num_or_name,
+                                          target,
+                                          extract_flags,
+                                          imagex_progress_func,
+                                          NULL);
        }
        if (ret == 0) {
                imagex_printf(T("Done applying WIM image.\n"));
@@ -1938,13 +1936,17 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
        }
 
        /* Open the existing WIM, or create a new one.  */
-       if (cmd == CMD_APPEND)
-               ret = wimlib_open_wim(wimfile, open_flags, &wim,
-                                     imagex_progress_func);
-       else
+       if (cmd == CMD_APPEND) {
+               ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
+                                                   imagex_progress_func, NULL);
+               if (ret)
+                       goto out_free_capture_sources;
+       } else {
                ret = wimlib_create_new_wim(compression_type, &wim);
-       if (ret)
-               goto out_free_capture_sources;
+               if (ret)
+                       goto out_free_capture_sources;
+               wimlib_register_progress_function(wim, imagex_progress_func, NULL);
+       }
 
        /* Set chunk size if non-default.  */
        if (chunk_size != UINT32_MAX) {
@@ -2017,9 +2019,10 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                }
 
                for (size_t i = 0; i < base_wimfiles.num_strings; i++) {
-                       ret = wimlib_open_wim(base_wimfiles.strings[i],
-                                             open_flags, &base_wims[i],
-                                             imagex_progress_func);
+                       ret = wimlib_open_wim_with_progress(
+                                   base_wimfiles.strings[i],
+                                   open_flags, &base_wims[i],
+                                   imagex_progress_func, NULL);
                        if (ret)
                                goto out_free_base_wims;
 
@@ -2053,8 +2056,11 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                } else if (template_wimfile == wimfile) {
                        template_wim = wim;
                } else {
-                       ret = wimlib_open_wim(template_wimfile, open_flags,
-                                             &template_wim, imagex_progress_func);
+                       ret = wimlib_open_wim_with_progress(template_wimfile,
+                                                           open_flags,
+                                                           &template_wim,
+                                                           imagex_progress_func,
+                                                           NULL);
                        if (ret)
                                goto out_free_base_wims;
                }
@@ -2090,8 +2096,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                                           num_sources,
                                           name,
                                           config_file,
-                                          add_image_flags,
-                                          imagex_progress_func);
+                                          add_image_flags);
        if (ret)
                goto out_free_template_wim;
 
@@ -2128,7 +2133,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                                                              info.image_count,
                                                              template_wim,
                                                              template_image,
-                                                             0, NULL);
+                                                             0);
                        if (ret)
                                goto out_free_template_wim;
                }
@@ -2137,16 +2142,13 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
        /* Write the new WIM or overwrite the existing WIM with the new image
         * appended.  */
        if (cmd == CMD_APPEND) {
-               ret = wimlib_overwrite(wim, write_flags, num_threads,
-                                      imagex_progress_func);
+               ret = wimlib_overwrite(wim, write_flags, num_threads);
        } else if (wimfile) {
                ret = wimlib_write(wim, wimfile, WIMLIB_ALL_IMAGES,
-                                  write_flags, num_threads,
-                                  imagex_progress_func);
+                                  write_flags, num_threads);
        } else {
                ret = wimlib_write_to_fd(wim, wim_fd, WIMLIB_ALL_IMAGES,
-                                        write_flags, num_threads,
-                                        imagex_progress_func);
+                                        write_flags, num_threads);
        }
 out_free_template_wim:
        /* template_wim may alias base_wims[0] or wim.  */
@@ -2214,8 +2216,8 @@ imagex_delete(int argc, tchar **argv, int cmd)
        wimfile = argv[0];
        image_num_or_name = argv[1];
 
-       ret = wimlib_open_wim(wimfile, open_flags, &wim,
-                             imagex_progress_func);
+       ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
+                                           imagex_progress_func, NULL);
        if (ret)
                goto out;
 
@@ -2232,7 +2234,7 @@ imagex_delete(int argc, tchar **argv, int cmd)
                goto out_wimlib_free;
        }
 
-       ret = wimlib_overwrite(wim, write_flags, 0, imagex_progress_func);
+       ret = wimlib_overwrite(wim, write_flags, 0);
        if (ret) {
                imagex_error(T("Failed to write the file \"%"TS"\" with image "
                               "deleted"), wimfile);
@@ -2497,7 +2499,8 @@ imagex_dir(int argc, tchar **argv, int cmd)
        }
 
        wimfile = argv[0];
-       ret = wimlib_open_wim(wimfile, 0, &wim, imagex_progress_func);
+       ret = wimlib_open_wim_with_progress(wimfile, 0, &wim,
+                                           imagex_progress_func, NULL);
        if (ret)
                goto out;
 
@@ -2639,8 +2642,8 @@ imagex_export(int argc, tchar **argv, int cmd)
        dest_wimfile          = argv[2];
        dest_name             = (argc >= 4) ? argv[3] : NULL;
        dest_desc             = (argc >= 5) ? argv[4] : NULL;
-       ret = wimlib_open_wim(src_wimfile, open_flags, &src_wim,
-                             imagex_progress_func);
+       ret = wimlib_open_wim_with_progress(src_wimfile, open_flags, &src_wim,
+                                           imagex_progress_func, NULL);
        if (ret)
                goto out_free_refglobs;
 
@@ -2680,9 +2683,12 @@ imagex_export(int argc, tchar **argv, int cmd)
                        ret = -1;
                        goto out_free_src_wim;
                }
-               ret = wimlib_open_wim(dest_wimfile,
-                                     open_flags | WIMLIB_OPEN_FLAG_WRITE_ACCESS,
-                                     &dest_wim, imagex_progress_func);
+               ret = wimlib_open_wim_with_progress(dest_wimfile,
+                                                   open_flags |
+                                                       WIMLIB_OPEN_FLAG_WRITE_ACCESS,
+                                                   &dest_wim,
+                                                   imagex_progress_func,
+                                                   NULL);
                if (ret)
                        goto out_free_src_wim;
 
@@ -2730,6 +2736,9 @@ imagex_export(int argc, tchar **argv, int cmd)
                if (ret)
                        goto out_free_src_wim;
 
+               wimlib_register_progress_function(dest_wim,
+                                                 imagex_progress_func, NULL);
+
                if ((export_flags & WIMLIB_EXPORT_FLAG_WIMBOOT)
                    && compression_type == WIMLIB_COMPRESSION_TYPE_XPRESS)
                {
@@ -2781,7 +2790,7 @@ imagex_export(int argc, tchar **argv, int cmd)
        }
 
        ret = wimlib_export_image(src_wim, image, dest_wim, dest_name,
-                                 dest_desc, export_flags, imagex_progress_func);
+                                 dest_desc, export_flags);
        if (ret) {
                if (ret == WIMLIB_ERR_RESOURCE_NOT_FOUND) {
                        do_resource_not_found_warning(src_wimfile,
@@ -2791,16 +2800,14 @@ imagex_export(int argc, tchar **argv, int cmd)
        }
 
        if (!wim_is_new)
-               ret = wimlib_overwrite(dest_wim, write_flags, num_threads,
-                                      imagex_progress_func);
+               ret = wimlib_overwrite(dest_wim, write_flags, num_threads);
        else if (dest_wimfile)
                ret = wimlib_write(dest_wim, dest_wimfile, WIMLIB_ALL_IMAGES,
-                                  write_flags, num_threads,
-                                  imagex_progress_func);
+                                  write_flags, num_threads);
        else
                ret = wimlib_write_to_fd(dest_wim, dest_wim_fd,
                                         WIMLIB_ALL_IMAGES, write_flags,
-                                        num_threads, imagex_progress_func);
+                                        num_threads);
 out_free_dest_wim:
        wimlib_free(dest_wim);
 out_free_src_wim:
@@ -2910,7 +2917,8 @@ imagex_extract(int argc, tchar **argv, int cmd)
        argc -= 2;
        argv += 2;
 
-       ret = wimlib_open_wim(wimfile, open_flags, &wim, imagex_progress_func);
+       ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
+                                           imagex_progress_func, NULL);
        if (ret)
                goto out_free_refglobs;
 
@@ -2945,15 +2953,13 @@ imagex_extract(int argc, tchar **argv, int cmd)
                        ret = wimlib_extract_paths(wim, image, dest_dir,
                                                   (const tchar **)argv,
                                                   num_paths,
-                                                  extract_flags | notlist_extract_flags,
-                                                  imagex_progress_func);
+                                                  extract_flags | notlist_extract_flags);
                        argc -= num_paths;
                        argv += num_paths;
                } else {
                        ret = wimlib_extract_pathlist(wim, image, dest_dir,
                                                      argv[0] + 1,
-                                                     extract_flags,
-                                                     imagex_progress_func);
+                                                     extract_flags);
                        argc--;
                        argv++;
                }
@@ -3064,7 +3070,8 @@ imagex_info(int argc, tchar **argv, int cmd)
        if (check)
                open_flags |= WIMLIB_OPEN_FLAG_CHECK_INTEGRITY;
 
-       ret = wimlib_open_wim(wimfile, open_flags, &wim, imagex_progress_func);
+       ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
+                                           imagex_progress_func, NULL);
        if (ret)
                goto out;
 
@@ -3234,8 +3241,7 @@ imagex_info(int argc, tchar **argv, int cmd)
                                write_flags |= WIMLIB_WRITE_FLAG_CHECK_INTEGRITY;
                        if (nocheck)
                                write_flags |= WIMLIB_WRITE_FLAG_NO_CHECK_INTEGRITY;
-                       ret = wimlib_overwrite(wim, write_flags, 1,
-                                              imagex_progress_func);
+                       ret = wimlib_overwrite(wim, write_flags, 1);
                } else {
                        imagex_printf(T("The file \"%"TS"\" was not modified "
                                        "because nothing needed to be done.\n"),
@@ -3284,12 +3290,13 @@ imagex_join(int argc, tchar **argv, int cmd)
                goto out_usage;
        }
        output_path = argv[0];
-       ret = wimlib_join((const tchar * const *)++argv,
-                         --argc,
-                         output_path,
-                         swm_open_flags,
-                         wim_write_flags,
-                         imagex_progress_func);
+       ret = wimlib_join_with_progress((const tchar * const *)++argv,
+                                       --argc,
+                                       output_path,
+                                       swm_open_flags,
+                                       wim_write_flags,
+                                       imagex_progress_func,
+                                       NULL);
 out:
        return ret;
 
@@ -3369,7 +3376,8 @@ imagex_mount_rw_or_ro(int argc, tchar **argv, int cmd)
 
        wimfile = argv[0];
 
-       ret = wimlib_open_wim(wimfile, open_flags, &wim, imagex_progress_func);
+       ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
+                                           imagex_progress_func, NULL);
        if (ret)
                goto out_free_refglobs;
 
@@ -3503,7 +3511,8 @@ imagex_optimize(int argc, tchar **argv, int cmd)
 
        wimfile = argv[0];
 
-       ret = wimlib_open_wim(wimfile, open_flags, &wim, imagex_progress_func);
+       ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
+                                           imagex_progress_func, NULL);
        if (ret)
                goto out;
 
@@ -3538,8 +3547,7 @@ imagex_optimize(int argc, tchar **argv, int cmd)
        else
                tprintf(T("%"PRIu64" KiB\n"), old_size >> 10);
 
-       ret = wimlib_overwrite(wim, write_flags, num_threads,
-                              imagex_progress_func);
+       ret = wimlib_overwrite(wim, write_flags, num_threads);
        if (ret) {
                imagex_error(T("Optimization of \"%"TS"\" failed."), wimfile);
                goto out_wimlib_free;
@@ -3607,11 +3615,12 @@ imagex_split(int argc, tchar **argv, int cmd)
                               "floating-point number of megabytes."));
                goto out_err;
        }
-       ret = wimlib_open_wim(argv[0], open_flags, &wim, imagex_progress_func);
+       ret = wimlib_open_wim_with_progress(argv[0], open_flags, &wim,
+                                           imagex_progress_func, NULL);
        if (ret)
                goto out;
 
-       ret = wimlib_split(wim, argv[1], part_size, write_flags, imagex_progress_func);
+       ret = wimlib_split(wim, argv[1], part_size, write_flags);
        wimlib_free(wim);
 out:
        return ret;
@@ -3667,8 +3676,8 @@ imagex_unmount(int argc, tchar **argv, int cmd)
                imagex_printf(T("Committing changes as new image...\n"));
        }
 
-       ret = wimlib_unmount_image(argv[0], unmount_flags,
-                                  imagex_progress_func);
+       ret = wimlib_unmount_image_with_progress(argv[0], unmount_flags,
+                                                imagex_progress_func, NULL);
        if (ret)
                imagex_error(T("Failed to unmount \"%"TS"\""), argv[0]);
 out:
@@ -3785,7 +3794,8 @@ imagex_update(int argc, tchar **argv, int cmd)
                goto out_usage;
        wimfile = argv[0];
 
-       ret = wimlib_open_wim(wimfile, open_flags, &wim, imagex_progress_func);
+       ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
+                                           imagex_progress_func, NULL);
        if (ret)
                goto out_free_command_str;
 
@@ -3861,8 +3871,7 @@ imagex_update(int argc, tchar **argv, int cmd)
        }
 
        /* Execute the update commands */
-       ret = wimlib_update_image(wim, image, cmds, num_cmds, update_flags,
-                                 imagex_progress_func);
+       ret = wimlib_update_image(wim, image, cmds, num_cmds, update_flags);
        if (ret)
                goto out_free_cmds;
 
@@ -3878,15 +3887,13 @@ imagex_update(int argc, tchar **argv, int cmd)
                cmd.add.config_file = NULL;
                cmd.add.add_flags = 0;
 
-               ret = wimlib_update_image(wim, image, &cmd, 1,
-                                         update_flags, imagex_progress_func);
+               ret = wimlib_update_image(wim, image, &cmd, 1, update_flags);
                if (ret)
                        goto out_free_cmds;
        }
 
        /* Overwrite the updated WIM */
-       ret = wimlib_overwrite(wim, write_flags, num_threads,
-                              imagex_progress_func);
+       ret = wimlib_overwrite(wim, write_flags, num_threads);
 out_free_cmds:
        free(cmds);
 out_free_cmd_file_contents:
index a544c7b..cd27039 100644 (file)
@@ -157,8 +157,7 @@ wimlib_add_image_multisource(WIMStruct *wim,
                             size_t num_sources,
                             const tchar *name,
                             const tchar *config_file,
-                            int add_flags,
-                            wimlib_progress_func_t progress_func)
+                            int add_flags)
 {
        int ret;
        struct wimlib_update_command *add_cmds;
@@ -182,7 +181,7 @@ wimlib_add_image_multisource(WIMStruct *wim,
 
        /* Delegate the work to wimlib_update_image().  */
        ret = wimlib_update_image(wim, wim->hdr.image_count, add_cmds,
-                                 num_sources, 0, progress_func);
+                                 num_sources, 0);
        FREE(add_cmds);
        if (ret)
                goto out_delete_image;
@@ -215,8 +214,7 @@ wimlib_add_image(WIMStruct *wim,
                 const tchar *source,
                 const tchar *name,
                 const tchar *config_file,
-                int add_flags,
-                wimlib_progress_func_t progress_func)
+                int add_flags)
 {
        /* Use the more general wimlib_add_image_multisource().  */
        const struct wimlib_capture_source capture_src = {
@@ -225,6 +223,5 @@ wimlib_add_image(WIMStruct *wim,
                .reserved = 0,
        };
        return wimlib_add_image_multisource(wim, &capture_src, 1, name,
-                                           config_file, add_flags,
-                                           progress_func);
+                                           config_file, add_flags);
 }
index 4db070f..943d919 100644 (file)
@@ -30,6 +30,7 @@
 #include "wimlib/error.h"
 #include "wimlib/lookup_table.h"
 #include "wimlib/paths.h"
+#include "wimlib/progress.h"
 #include "wimlib/textfile.h"
 #include "wimlib/wildcard.h"
 
  *     seen, inode->i_nlink will be 1.  On subsequent visits of the same inode
  *     via additional hard links, inode->i_nlink will be greater than 1.
  */
-void
+int
 do_capture_progress(struct add_image_params *params, int status,
                    const struct wim_inode *inode)
 {
        switch (status) {
        case WIMLIB_SCAN_DENTRY_OK:
                if (!(params->add_flags & WIMLIB_ADD_FLAG_VERBOSE))
-                       return;
+                       return 0;
        case WIMLIB_SCAN_DENTRY_UNSUPPORTED:
        case WIMLIB_SCAN_DENTRY_EXCLUDED:
        case WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK:
                if (!(params->add_flags & WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE))
-                       return;
+                       return 0;
        }
        params->progress.scan.status = status;
        if (status == WIMLIB_SCAN_DENTRY_OK && inode->i_nlink == 1) {
@@ -84,11 +85,10 @@ do_capture_progress(struct add_image_params *params, int status,
                else
                        params->progress.scan.num_nondirs_scanned++;
        }
+
        /* Call the user-provided progress function.  */
-       if (params->progress_func) {
-               params->progress_func(WIMLIB_PROGRESS_MSG_SCAN_DENTRY,
-                                     &params->progress);
-       }
+       return call_progress(params->progfunc, WIMLIB_PROGRESS_MSG_SCAN_DENTRY,
+                            &params->progress, params->progctx);
 }
 
 /*
index 9c25be7..34b9242 100644 (file)
@@ -110,8 +110,7 @@ wimlib_export_image(WIMStruct *src_wim,
                    WIMStruct *dest_wim,
                    const tchar *dest_name,
                    const tchar *dest_description,
-                   int export_flags,
-                   wimlib_progress_func_t progress_func)
+                   int export_flags)
 {
        int ret;
        int start_image;
index 05c3d16..3adbca3 100644 (file)
@@ -190,10 +190,10 @@ load_streams_from_pipe(struct apply_ctx *ctx,
        memcpy(ctx->progress.extract.guid, ctx->wim->hdr.guid, WIM_GUID_LEN);
        ctx->progress.extract.part_number = ctx->wim->hdr.part_number;
        ctx->progress.extract.total_parts = ctx->wim->hdr.total_parts;
-       if (ctx->progress_func) {
-               ctx->progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN,
-                                  &ctx->progress);
-       }
+       ret = extract_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN);
+       if (ret)
+               goto out;
+
        while (ctx->num_streams_remaining) {
                struct wim_header_disk pwm_hdr;
                struct wim_lookup_table_entry *needed_lte;
@@ -251,11 +251,10 @@ load_streams_from_pipe(struct apply_ctx *ctx,
                                ctx->progress.extract.total_parts = total_parts;
                                memcpy(ctx->progress.extract.guid,
                                       pwm_hdr.guid, WIM_GUID_LEN);
-                               if (ctx->progress_func) {
-                                       ctx->progress_func(
-                                               WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN,
-                                                          &ctx->progress);
-                               }
+                               ret = extract_progress(ctx,
+                                                      WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN);
+                               if (ret)
+                                       goto out;
                        }
                }
        }
@@ -283,8 +282,8 @@ static int
 consume_chunk_with_progress(const void *chunk, size_t size, void *_ctx)
 {
        struct apply_ctx *ctx = _ctx;
-       wimlib_progress_func_t progress_func = ctx->progress_func;
        union wimlib_progress_info *progress = &ctx->progress;
+       int ret;
 
        if (likely(ctx->supported_features.hard_links)) {
                progress->extract.completed_bytes +=
@@ -304,7 +303,11 @@ consume_chunk_with_progress(const void *chunk, size_t size, void *_ctx)
                }
        }
        if (progress->extract.completed_bytes >= ctx->next_progress) {
-               progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS, progress);
+
+               ret = extract_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS);
+               if (ret)
+                       return ret;
+
                if (progress->extract.completed_bytes >=
                    progress->extract.total_bytes)
                {
@@ -342,7 +345,7 @@ extract_stream_list(struct apply_ctx *ctx,
                .end_stream        = cbs->end_stream,
                .end_stream_ctx    = cbs->end_stream_ctx,
        };
-       if (ctx->progress_func) {
+       if (ctx->progfunc) {
                ctx->saved_cbs = cbs;
                cbs = &wrapper_cbs;
        }
@@ -1169,8 +1172,7 @@ select_apply_operations(int extract_flags)
 
 static int
 extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees,
-             const tchar *target, int extract_flags,
-             wimlib_progress_func_t progress_func)
+             const tchar *target, int extract_flags)
 {
        const struct apply_operations *ops;
        struct apply_ctx *ctx;
@@ -1206,8 +1208,9 @@ extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees,
        ctx->target = target;
        ctx->target_nchars = tstrlen(target);
        ctx->extract_flags = extract_flags;
-       if (progress_func) {
-               ctx->progress_func = progress_func;
+       if (ctx->wim->progfunc) {
+               ctx->progfunc = ctx->wim->progfunc;
+               ctx->progctx = ctx->wim->progctx;
                ctx->progress.extract.image = wim->current_image;
                ctx->progress.extract.extract_flags = (extract_flags &
                                                       WIMLIB_EXTRACT_MASK_PUBLIC);
@@ -1268,38 +1271,31 @@ extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees,
                }
        }
 
-       if (ctx->progress_func) {
-               int msg;
-               if (extract_flags & WIMLIB_EXTRACT_FLAG_IMAGEMODE)
-                       msg = WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN;
-               else
-                       msg = WIMLIB_PROGRESS_MSG_EXTRACT_TREE_BEGIN;
-               (*ctx->progress_func)(msg, &ctx->progress);
-       }
+       ret = extract_progress(ctx,
+                              ((extract_flags & WIMLIB_EXTRACT_FLAG_IMAGEMODE) ?
+                                      WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN :
+                                      WIMLIB_PROGRESS_MSG_EXTRACT_TREE_BEGIN));
+       if (ret)
+               goto out_cleanup;
 
        ret = (*ops->extract)(&dentry_list, ctx);
        if (ret)
                goto out_cleanup;
 
-       if (ctx->progress_func &&
-           ctx->progress.extract.completed_bytes <
-               ctx->progress.extract.total_bytes)
+       if (ctx->progress.extract.completed_bytes <
+           ctx->progress.extract.total_bytes)
        {
                ctx->progress.extract.completed_bytes =
                        ctx->progress.extract.total_bytes;
-               (*ctx->progress_func)(WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS,
-                                     &ctx->progress);
+               ret = extract_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS);
+               if (ret)
+                       goto out_cleanup;
        }
 
-       if (ctx->progress_func) {
-               int msg;
-               if (extract_flags & WIMLIB_EXTRACT_FLAG_IMAGEMODE)
-                       msg = WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END;
-               else
-                       msg = WIMLIB_PROGRESS_MSG_EXTRACT_TREE_END;
-               (*ctx->progress_func)(msg, &ctx->progress);
-       }
-       ret = 0;
+       ret = extract_progress(ctx,
+                              ((extract_flags & WIMLIB_EXTRACT_FLAG_IMAGEMODE) ?
+                                      WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END :
+                                      WIMLIB_PROGRESS_MSG_EXTRACT_TREE_END));
 out_cleanup:
        destroy_stream_list(&ctx->stream_list);
        destroy_dentry_list(&dentry_list);
@@ -1427,7 +1423,7 @@ append_dentry_cb(struct wim_dentry *dentry, void *_ctx)
 static int
 do_wimlib_extract_paths(WIMStruct *wim, int image, const tchar *target,
                        const tchar * const *paths, size_t num_paths,
-                       int extract_flags, wimlib_progress_func_t progress_func)
+                       int extract_flags)
 {
        int ret;
        struct wim_dentry **trees;
@@ -1519,8 +1515,7 @@ do_wimlib_extract_paths(WIMStruct *wim, int image, const tchar *target,
                goto out_free_trees;
        }
 
-       ret = extract_trees(wim, trees, num_trees,
-                           target, extract_flags, progress_func);
+       ret = extract_trees(wim, trees, num_trees, target, extract_flags);
 out_free_trees:
        FREE(trees);
        return ret;
@@ -1528,13 +1523,11 @@ out_free_trees:
 
 static int
 extract_single_image(WIMStruct *wim, int image,
-                    const tchar *target, int extract_flags,
-                    wimlib_progress_func_t progress_func)
+                    const tchar *target, int extract_flags)
 {
        const tchar *path = WIMLIB_WIM_ROOT_PATH;
        extract_flags |= WIMLIB_EXTRACT_FLAG_IMAGEMODE;
-       return do_wimlib_extract_paths(wim, image, target, &path, 1,
-                                      extract_flags, progress_func);
+       return do_wimlib_extract_paths(wim, image, target, &path, 1, extract_flags);
 }
 
 static const tchar * const filename_forbidden_chars =
@@ -1560,10 +1553,7 @@ image_name_ok_as_dir(const tchar *image_name)
 /* Extracts all images from the WIM to the directory @target, with the images
  * placed in subdirectories named by their image names. */
 static int
-extract_all_images(WIMStruct *wim,
-                  const tchar *target,
-                  int extract_flags,
-                  wimlib_progress_func_t progress_func)
+extract_all_images(WIMStruct *wim, const tchar *target, int extract_flags)
 {
        size_t image_name_max_len = max(xml_get_max_image_name_len(wim), 20);
        size_t output_path_len = tstrlen(target);
@@ -1593,8 +1583,7 @@ extract_all_images(WIMStruct *wim,
                         * Use image number instead. */
                        tsprintf(buf + output_path_len + 1, T("%d"), image);
                }
-               ret = extract_single_image(wim, image, buf, extract_flags,
-                                          progress_func);
+               ret = extract_single_image(wim, image, buf, extract_flags);
                if (ret)
                        return ret;
        }
@@ -1602,11 +1591,8 @@ extract_all_images(WIMStruct *wim,
 }
 
 static int
-do_wimlib_extract_image(WIMStruct *wim,
-                       int image,
-                       const tchar *target,
-                       int extract_flags,
-                       wimlib_progress_func_t progress_func)
+do_wimlib_extract_image(WIMStruct *wim, int image, const tchar *target,
+                       int extract_flags)
 {
        if (extract_flags & (WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE |
                             WIMLIB_EXTRACT_FLAG_TO_STDOUT |
@@ -1614,11 +1600,9 @@ do_wimlib_extract_image(WIMStruct *wim,
                return WIMLIB_ERR_INVALID_PARAM;
 
        if (image == WIMLIB_ALL_IMAGES)
-               return extract_all_images(wim, target, extract_flags,
-                                         progress_func);
+               return extract_all_images(wim, target, extract_flags);
        else
-               return extract_single_image(wim, image, target, extract_flags,
-                                           progress_func);
+               return extract_single_image(wim, image, target, extract_flags);
 }
 
 
@@ -1629,19 +1613,18 @@ do_wimlib_extract_image(WIMStruct *wim,
 WIMLIBAPI int
 wimlib_extract_paths(WIMStruct *wim, int image, const tchar *target,
                     const tchar * const *paths, size_t num_paths,
-                    int extract_flags, wimlib_progress_func_t progress_func)
+                    int extract_flags)
 {
        if (extract_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC)
                return WIMLIB_ERR_INVALID_PARAM;
 
        return do_wimlib_extract_paths(wim, image, target, paths, num_paths,
-                                      extract_flags, progress_func);
+                                      extract_flags);
 }
 
 WIMLIBAPI int
 wimlib_extract_pathlist(WIMStruct *wim, int image, const tchar *target,
-                       const tchar *path_list_file, int extract_flags,
-                       wimlib_progress_func_t progress_func)
+                       const tchar *path_list_file, int extract_flags)
 {
        int ret;
        tchar **paths;
@@ -1657,16 +1640,19 @@ wimlib_extract_pathlist(WIMStruct *wim, int image, const tchar *target,
 
        ret = wimlib_extract_paths(wim, image, target,
                                   (const tchar * const *)paths, num_paths,
-                                  extract_flags, progress_func);
+                                  extract_flags);
        FREE(paths);
        FREE(mem);
        return ret;
 }
 
 WIMLIBAPI int
-wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name,
-                              const tchar *target, int extract_flags,
-                              wimlib_progress_func_t progress_func)
+wimlib_extract_image_from_pipe_with_progress(int pipe_fd,
+                                            const tchar *image_num_or_name,
+                                            const tchar *target,
+                                            int extract_flags,
+                                            wimlib_progress_func_t progfunc,
+                                            void *progctx)
 {
        int ret;
        WIMStruct *pwm;
@@ -1681,9 +1667,8 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name,
         * the pipable WIM.  Caveats:  Unlike getting a WIMStruct with
         * wimlib_open_wim(), getting a WIMStruct in this way will result in
         * an empty lookup table, no XML data read, and no filename set.  */
-       ret = open_wim_as_WIMStruct(&pipe_fd,
-                                   WIMLIB_OPEN_FLAG_FROM_PIPE,
-                                   &pwm, progress_func);
+       ret = open_wim_as_WIMStruct(&pipe_fd, WIMLIB_OPEN_FLAG_FROM_PIPE, &pwm,
+                                   progfunc, progctx);
        if (ret)
                return ret;
 
@@ -1814,20 +1799,31 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name,
        }
        /* Extract the image.  */
        extract_flags |= WIMLIB_EXTRACT_FLAG_FROM_PIPE;
-       ret = do_wimlib_extract_image(pwm, image, target,
-                                     extract_flags, progress_func);
+       ret = do_wimlib_extract_image(pwm, image, target, extract_flags);
        /* Clean up and return.  */
 out_wimlib_free:
        wimlib_free(pwm);
        return ret;
 }
 
+
+WIMLIBAPI int
+wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name,
+                              const tchar *target, int extract_flags)
+{
+       return wimlib_extract_image_from_pipe_with_progress(pipe_fd,
+                                                           image_num_or_name,
+                                                           target,
+                                                           extract_flags,
+                                                           NULL,
+                                                           NULL);
+}
+
 WIMLIBAPI int
 wimlib_extract_image(WIMStruct *wim, int image, const tchar *target,
-                    int extract_flags, wimlib_progress_func_t progress_func)
+                    int extract_flags)
 {
        if (extract_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC)
                return WIMLIB_ERR_INVALID_PARAM;
-       return do_wimlib_extract_image(wim, image, target, extract_flags,
-                                      progress_func);
+       return do_wimlib_extract_image(wim, image, target, extract_flags);
 }
index 350b3a2..ebde930 100644 (file)
@@ -34,6 +34,7 @@
 #include "wimlib/error.h"
 #include "wimlib/file_io.h"
 #include "wimlib/integrity.h"
+#include "wimlib/progress.h"
 #include "wimlib/resource.h"
 #include "wimlib/sha1.h"
 #include "wimlib/wim.h"
@@ -170,10 +171,6 @@ invalid:
  *     If @old_table is non-NULL, the byte after the last byte that was checked
  *     in the old table.  Must be less than or equal to new_check_end.
  *
- * @progress_func:
- *     If non-NULL, a progress function that will be called after every
- *     calculated chunk.
- *
  * @integrity_table_ret:
  *     On success, a pointer to the calculated integrity table is written into
  *     this location.
@@ -189,8 +186,9 @@ calculate_integrity_table(struct filedes *in_fd,
                          off_t new_check_end,
                          const struct integrity_table *old_table,
                          off_t old_check_end,
-                         wimlib_progress_func_t progress_func,
-                         struct integrity_table **integrity_table_ret)
+                         struct integrity_table **integrity_table_ret,
+                         wimlib_progress_func_t progfunc,
+                         void *progctx)
 {
        int ret;
        size_t chunk_size = INTEGRITY_CHUNK_SIZE;
@@ -228,16 +226,17 @@ calculate_integrity_table(struct filedes *in_fd,
        u64 offset = WIM_HEADER_DISK_SIZE;
        union wimlib_progress_info progress;
 
-       if (progress_func) {
-               progress.integrity.total_bytes      = new_check_bytes;
-               progress.integrity.total_chunks     = new_num_chunks;
-               progress.integrity.completed_chunks = 0;
-               progress.integrity.completed_bytes  = 0;
-               progress.integrity.chunk_size       = chunk_size;
-               progress.integrity.filename         = NULL;
-               progress_func(WIMLIB_PROGRESS_MSG_CALC_INTEGRITY,
-                             &progress);
-       }
+       progress.integrity.total_bytes      = new_check_bytes;
+       progress.integrity.total_chunks     = new_num_chunks;
+       progress.integrity.completed_chunks = 0;
+       progress.integrity.completed_bytes  = 0;
+       progress.integrity.chunk_size       = chunk_size;
+       progress.integrity.filename         = NULL;
+
+       ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_CALC_INTEGRITY,
+                           &progress, progctx);
+       if (ret)
+               goto out_free_new_table;
 
        for (u32 i = 0; i < new_num_chunks; i++) {
                size_t this_chunk_size;
@@ -256,21 +255,24 @@ calculate_integrity_table(struct filedes *in_fd,
                        /* Calculate the SHA1 message digest of this chunk */
                        ret = calculate_chunk_sha1(in_fd, this_chunk_size,
                                                   offset, new_table->sha1sums[i]);
-                       if (ret) {
-                               FREE(new_table);
-                               return ret;
-                       }
+                       if (ret)
+                               goto out_free_new_table;
                }
                offset += this_chunk_size;
-               if (progress_func) {
-                       progress.integrity.completed_chunks++;
-                       progress.integrity.completed_bytes += this_chunk_size;
-                       progress_func(WIMLIB_PROGRESS_MSG_CALC_INTEGRITY,
-                                     &progress);
-               }
+
+               progress.integrity.completed_chunks++;
+               progress.integrity.completed_bytes += this_chunk_size;
+               ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_CALC_INTEGRITY,
+                                   &progress, progctx);
+               if (ret)
+                       goto out_free_new_table;
        }
        *integrity_table_ret = new_table;
        return 0;
+
+out_free_new_table:
+       FREE(new_table);
+       return ret;
 }
 
 /*
@@ -305,10 +307,6 @@ calculate_integrity_table(struct filedes *in_fd,
  *     If nonzero, the offset of the byte directly following the old lookup
  *     table in the WIM.
  *
- * @progress_func
- *     If non-NULL, a progress function that will be called after every
- *     calculated chunk.
- *
  * Return values:
  *     WIMLIB_ERR_SUCCESS (0)
  *     WIMLIB_ERR_NOMEM
@@ -318,8 +316,7 @@ calculate_integrity_table(struct filedes *in_fd,
 int
 write_integrity_table(WIMStruct *wim,
                      off_t new_lookup_table_end,
-                     off_t old_lookup_table_end,
-                     wimlib_progress_func_t progress_func)
+                     off_t old_lookup_table_end)
 {
        struct integrity_table *old_table;
        struct integrity_table *new_table;
@@ -348,7 +345,7 @@ write_integrity_table(WIMStruct *wim,
 
        ret = calculate_integrity_table(&wim->out_fd, new_lookup_table_end,
                                        old_table, old_lookup_table_end,
-                                       progress_func, &new_table);
+                                       &new_table, wim->progfunc, wim->progctx);
        if (ret)
                goto out_free_old_table;
 
@@ -389,10 +386,6 @@ out_free_old_table:
  *     Number of bytes in the WIM that need to be checked (offset of end of the
  *     lookup table minus offset of end of the header).
  *
- * @progress_func
- *     If non-NULL, a progress function that will be called after every
- *     verified chunk.
- *
  * Returns:
  *     > 0 (WIMLIB_ERR_READ, WIMLIB_ERR_UNEXPECTED_END_OF_FILE) on error
  *     0 (WIM_INTEGRITY_OK) if the integrity was checked successfully and there
@@ -403,23 +396,25 @@ static int
 verify_integrity(struct filedes *in_fd, const tchar *filename,
                 const struct integrity_table *table,
                 u64 bytes_to_check,
-                wimlib_progress_func_t progress_func)
+                wimlib_progress_func_t progfunc, void *progctx)
 {
        int ret;
        u64 offset = WIM_HEADER_DISK_SIZE;
        u8 sha1_md[SHA1_HASH_SIZE];
        union wimlib_progress_info progress;
 
-       if (progress_func) {
-               progress.integrity.total_bytes      = bytes_to_check;
-               progress.integrity.total_chunks     = table->num_entries;
-               progress.integrity.completed_chunks = 0;
-               progress.integrity.completed_bytes  = 0;
-               progress.integrity.chunk_size       = table->chunk_size;
-               progress.integrity.filename         = filename;
-               progress_func(WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY,
-                             &progress);
-       }
+       progress.integrity.total_bytes      = bytes_to_check;
+       progress.integrity.total_chunks     = table->num_entries;
+       progress.integrity.completed_chunks = 0;
+       progress.integrity.completed_bytes  = 0;
+       progress.integrity.chunk_size       = table->chunk_size;
+       progress.integrity.filename         = filename;
+
+       ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY,
+                           &progress, progctx);
+       if (ret)
+               return ret;
+
        for (u32 i = 0; i < table->num_entries; i++) {
                size_t this_chunk_size;
                if (i == table->num_entries - 1)
@@ -436,12 +431,13 @@ verify_integrity(struct filedes *in_fd, const tchar *filename,
                        return WIM_INTEGRITY_NOT_OK;
 
                offset += this_chunk_size;
-               if (progress_func) {
-                       progress.integrity.completed_chunks++;
-                       progress.integrity.completed_bytes += this_chunk_size;
-                       progress_func(WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY,
-                                     &progress);
-               }
+               progress.integrity.completed_chunks++;
+               progress.integrity.completed_bytes += this_chunk_size;
+
+               ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY,
+                                   &progress, progctx);
+               if (ret)
+                       return ret;
        }
        return WIM_INTEGRITY_OK;
 }
@@ -457,10 +453,6 @@ verify_integrity(struct filedes *in_fd, const tchar *filename,
  * @wim:
  *     The WIM, opened for reading.
  *
- * @progress_func
- *     If non-NULL, a progress function that will be called after every
- *     verified chunk.
- *
  * Returns:
  *     > 0 (WIMLIB_ERR_INVALID_INTEGRITY_TABLE, WIMLIB_ERR_READ,
  *          WIMLIB_ERR_UNEXPECTED_END_OF_FILE) on error
@@ -471,7 +463,7 @@ verify_integrity(struct filedes *in_fd, const tchar *filename,
  *     information.
  */
 int
-check_wim_integrity(WIMStruct *wim, wimlib_progress_func_t progress_func)
+check_wim_integrity(WIMStruct *wim)
 {
        int ret;
        u64 bytes_to_check;
@@ -497,7 +489,7 @@ check_wim_integrity(WIMStruct *wim, wimlib_progress_func_t progress_func)
        if (ret)
                return ret;
        ret = verify_integrity(&wim->in_fd, wim->filename, table,
-                              bytes_to_check, progress_func);
+                              bytes_to_check, wim->progfunc, wim->progctx);
        FREE(table);
        return ret;
 }
index 71e43c0..3a60f1c 100644 (file)
@@ -149,14 +149,14 @@ verify_swm_set(WIMStruct *wim, WIMStruct **additional_swms,
        return 0;
 }
 
-/* API function documented in wimlib.h  */
 WIMLIBAPI int
-wimlib_join(const tchar * const *swm_names,
-           unsigned num_swms,
-           const tchar *output_path,
-           int swm_open_flags,
-           int wim_write_flags,
-           wimlib_progress_func_t progress_func)
+wimlib_join_with_progress(const tchar * const *swm_names,
+                         unsigned num_swms,
+                         const tchar *output_path,
+                         int swm_open_flags,
+                         int wim_write_flags,
+                         wimlib_progress_func_t progfunc,
+                         void *progctx)
 {
        int ret;
        unsigned i;
@@ -178,8 +178,11 @@ wimlib_join(const tchar * const *swm_names,
        for (i = 0, j = 0; i < num_swms; i++) {
                WIMStruct *swm;
 
-               ret = wimlib_open_wim(swm_names[i], swm_open_flags, &swm,
-                                     progress_func);
+               ret = wimlib_open_wim_with_progress(swm_names[i],
+                                                   swm_open_flags,
+                                                   &swm,
+                                                   progfunc,
+                                                   progctx);
                if (ret)
                        goto out_free_swms;
                if (swm->hdr.part_number == 1 && swm0 == NULL)
@@ -210,7 +213,7 @@ wimlib_join(const tchar * const *swm_names,
                           wim_write_flags |
                                WIMLIB_WRITE_FLAG_STREAMS_OK |
                                WIMLIB_WRITE_FLAG_RETAIN_GUID,
-                          1, progress_func);
+                          1);
 out_free_swms:
        for (i = 0; i < num_additional_swms + 1; i++)
                wimlib_free(additional_swms[i]);
@@ -218,3 +221,16 @@ out_free_swms:
        wimlib_free(swm0);
        return ret;
 }
+
+/* API function documented in wimlib.h  */
+WIMLIBAPI int
+wimlib_join(const tchar * const *swm_names,
+           unsigned num_swms,
+           const tchar *output_path,
+           int swm_open_flags,
+           int wim_write_flags)
+{
+       return wimlib_join_with_progress(swm_names, num_swms, output_path,
+                                        swm_open_flags, wim_write_flags,
+                                        NULL, NULL);
+}
index 06890db..e1ff886 100644 (file)
@@ -46,6 +46,7 @@
 #include "wimlib/lookup_table.h"
 #include "wimlib/metadata.h"
 #include "wimlib/paths.h"
+#include "wimlib/progress.h"
 #include "wimlib/reparse.h"
 #include "wimlib/resource.h"
 #include "wimlib/timestamp.h"
@@ -798,8 +799,7 @@ inode_close_fds(struct wim_inode *inode)
 
 /* Overwrites the WIM file, with changes saved. */
 static int
-rebuild_wim(struct wimfs_context *ctx, int write_flags,
-           wimlib_progress_func_t progress_func)
+rebuild_wim(struct wimfs_context *ctx, int write_flags)
 {
        int ret;
        struct wim_lookup_table_entry *lte, *tmp;
@@ -826,7 +826,7 @@ rebuild_wim(struct wimfs_context *ctx, int write_flags,
        }
 
        xml_update_image_info(wim, wim->current_image);
-       ret = wimlib_overwrite(wim, write_flags, 0, progress_func);
+       ret = wimlib_overwrite(wim, write_flags, 0);
        if (ret)
                ERROR("Failed to commit changes to mounted WIM image");
        return ret;
@@ -1078,7 +1078,8 @@ struct unmount_msg_handler_context {
        pid_t daemon_pid;
        int mount_flags;
        int status;
-       wimlib_progress_func_t progress_func;
+       wimlib_progress_func_t progfunc;
+       void *progctx;
 };
 
 struct daemon_msg_handler_context {
@@ -1150,9 +1151,9 @@ send_unmount_finished_msg(mqd_t mq, int status)
                ERROR_WITH_ERRNO("Failed to send status to unmount process");
 }
 
-static int
+static enum wimlib_progress_status
 unmount_progress_func(enum wimlib_progress_msg msg,
-                     const union wimlib_progress_info *info)
+                     union wimlib_progress_info *info, void *_ignored_context)
 {
        if (msg == WIMLIB_PROGRESS_MSG_WRITE_STREAMS) {
                struct msg_write_streams_progress msg = {
@@ -1171,7 +1172,7 @@ unmount_progress_func(enum wimlib_progress_msg msg,
                                         "to unmount process");
                }
        }
-       return 0;
+       return WIMLIB_PROGRESS_STATUS_CONTINUE;
 }
 
 static void
@@ -1257,7 +1258,6 @@ msg_unmount_request_handler(const void *_msg, void *_handler_ctx)
        int status = 0;
        int ret;
        int unmount_flags;
-       wimlib_progress_func_t progress_func;
 
        DEBUG("Handling unmount request msg");
 
@@ -1268,10 +1268,11 @@ msg_unmount_request_handler(const void *_msg, void *_handler_ctx)
        }
 
        unmount_flags = msg->unmount_flags;
-       if (msg->want_progress_messages)
-               progress_func = unmount_progress_func;
-       else
-               progress_func = NULL;
+
+       wimlib_register_progress_function(wimfs_ctx->wim,
+                                         (msg->want_progress_messages ?
+                                          unmount_progress_func : NULL),
+                                         NULL);
 
        ret = send_daemon_info_msg(wimfs_ctx->daemon_to_unmount_mq, getpid(),
                                   wimfs_ctx->mount_flags);
@@ -1301,8 +1302,7 @@ msg_unmount_request_handler(const void *_msg, void *_handler_ctx)
                                write_flags |= WIMLIB_WRITE_FLAG_REBUILD;
                        if (unmount_flags & WIMLIB_UNMOUNT_FLAG_RECOMPRESS)
                                write_flags |= WIMLIB_WRITE_FLAG_RECOMPRESS;
-                       status = rebuild_wim(wimfs_ctx, write_flags,
-                                            progress_func);
+                       status = rebuild_wim(wimfs_ctx, write_flags);
                }
        } else {
                DEBUG("Read-only mount");
@@ -1349,11 +1349,10 @@ msg_write_streams_progress_handler(const void *_msg, void *_handler_ctx)
 
        if (msg->hdr.msg_size < sizeof(*msg))
                return WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE;
-       if (handler_ctx->progress_func) {
-               handler_ctx->progress_func(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
-                                          &msg->info);
-       }
-       return 0;
+       return call_progress(handler_ctx->progfunc,
+                            WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
+                            (union wimlib_progress_info *)&msg->info,
+                            handler_ctx->progctx);
 }
 
 static int
@@ -2675,8 +2674,8 @@ out_free_message_queue_names:
 
 /* API function documented in wimlib.h  */
 WIMLIBAPI int
-wimlib_unmount_image(const char *dir, int unmount_flags,
-                    wimlib_progress_func_t progress_func)
+wimlib_unmount_image_with_progress(const tchar *dir, int unmount_flags,
+                                  wimlib_progress_func_t progfunc, void *progctx)
 {
        int ret;
        struct wimfs_context wimfs_ctx;
@@ -2701,7 +2700,7 @@ wimlib_unmount_image(const char *dir, int unmount_flags,
 
        ret = send_unmount_request_msg(wimfs_ctx.unmount_to_daemon_mq,
                                       unmount_flags,
-                                      progress_func != NULL);
+                                      progfunc != NULL);
        if (ret != 0)
                goto out_close_message_queues;
 
@@ -2714,7 +2713,8 @@ wimlib_unmount_image(const char *dir, int unmount_flags,
                        .timeout_seconds = 5,
                },
                .daemon_pid = 0,
-               .progress_func = progress_func,
+               .progfunc = progfunc,
+               .progctx = progctx,
        };
 
        ret = message_loop(wimfs_ctx.daemon_to_unmount_mq,
@@ -2746,8 +2746,8 @@ mount_unsupported_error(void)
 }
 
 WIMLIBAPI int
-wimlib_unmount_image(const tchar *dir, int unmount_flags,
-                    wimlib_progress_func_t progress_func)
+wimlib_unmount_image_with_progress(const tchar *dir, int unmount_flags,
+                                  wimlib_progress_func_t progfunc, void *progctx)
 {
        return mount_unsupported_error();
 }
@@ -2760,3 +2760,10 @@ wimlib_mount_image(WIMStruct *wim, int image, const tchar *dir,
 }
 
 #endif /* !WITH_FUSE */
+
+
+WIMLIBAPI int
+wimlib_unmount_image(const tchar *dir, int unmount_flags)
+{
+       return wimlib_unmount_image_with_progress(dir, unmount_flags, NULL, NULL);
+}
index 5c5b97a..80abca0 100644 (file)
@@ -559,8 +559,7 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
                        goto out;
                }
                params->progress.scan.cur_path = path;
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL);
-               ret = 0;
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL);
                goto out;
        }
 
@@ -696,9 +695,9 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
 out_progress:
        params->progress.scan.cur_path = path;
        if (root == NULL)
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
        else
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode);
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode);
 out:
        if (ret == 0)
                *root_ret = root;
index c423bdd..d1e34e1 100644 (file)
@@ -155,8 +155,7 @@ reference_resource_paths(WIMStruct *wim,
                         const tchar * const *resource_wimfiles,
                         unsigned num_resource_wimfiles,
                         int ref_flags,
-                        int open_flags,
-                        wimlib_progress_func_t progress_func)
+                        int open_flags)
 {
        WIMStruct **resource_wims;
        unsigned i;
@@ -169,8 +168,11 @@ reference_resource_paths(WIMStruct *wim,
        for (i = 0; i < num_resource_wimfiles; i++) {
                DEBUG("Referencing resources from path \"%"TS"\"",
                      resource_wimfiles[i]);
-               ret = wimlib_open_wim(resource_wimfiles[i], open_flags,
-                                     &resource_wims[i], progress_func);
+               ret = wimlib_open_wim_with_progress(resource_wimfiles[i],
+                                                   open_flags,
+                                                   &resource_wims[i],
+                                                   wim->progfunc,
+                                                   wim->progctx);
                if (ret)
                        goto out_free_resource_wims;
        }
@@ -197,8 +199,7 @@ out_free_array:
 
 static int
 reference_resource_glob(WIMStruct *wim, const tchar *refglob,
-                       int ref_flags, int open_flags,
-                       wimlib_progress_func_t progress_func)
+                       int ref_flags, int open_flags)
 {
        glob_t globbuf;
        int ret;
@@ -215,8 +216,7 @@ reference_resource_glob(WIMStruct *wim, const tchar *refglob,
                                                                &refglob,
                                                                1,
                                                                ref_flags,
-                                                               open_flags,
-                                                               progress_func);
+                                                               open_flags);
                        }
                } else {
                        ERROR_WITH_ERRNO("Failed to process glob \"%"TS"\"", refglob);
@@ -231,8 +231,7 @@ reference_resource_glob(WIMStruct *wim, const tchar *refglob,
                                       (const tchar * const *)globbuf.gl_pathv,
                                       globbuf.gl_pathc,
                                       ref_flags,
-                                      open_flags,
-                                      progress_func);
+                                      open_flags);
        globfree(&globbuf);
        return ret;
 }
@@ -243,8 +242,7 @@ wimlib_reference_resource_files(WIMStruct *wim,
                                const tchar * const * resource_wimfiles_or_globs,
                                unsigned count,
                                int ref_flags,
-                               int open_flags,
-                               wimlib_progress_func_t progress_func)
+                               int open_flags)
 {
        unsigned i;
        int ret;
@@ -257,15 +255,13 @@ wimlib_reference_resource_files(WIMStruct *wim,
                        ret = reference_resource_glob(wim,
                                                      resource_wimfiles_or_globs[i],
                                                      ref_flags,
-                                                     open_flags,
-                                                     progress_func);
+                                                     open_flags);
                        if (ret)
                                return ret;
                }
                return 0;
        } else {
                return reference_resource_paths(wim, resource_wimfiles_or_globs,
-                                               count, ref_flags,
-                                               open_flags, progress_func);
+                                               count, ref_flags, open_flags);
        }
 }
index d1317cf..a611816 100644 (file)
@@ -32,6 +32,7 @@
 #include "wimlib/list.h"
 #include "wimlib/lookup_table.h"
 #include "wimlib/metadata.h"
+#include "wimlib/progress.h"
 #include "wimlib/resource.h"
 #include "wimlib/wim.h"
 #include "wimlib/write.h"
@@ -64,8 +65,7 @@ struct swm_info {
 
 static int
 write_split_wim(WIMStruct *orig_wim, const tchar *swm_name,
-               struct swm_info *swm_info, int write_flags,
-               wimlib_progress_func_t progress_func)
+               struct swm_info *swm_info, int write_flags)
 {
        size_t swm_name_len;
        tchar *swm_name_buf;
@@ -103,6 +103,7 @@ write_split_wim(WIMStruct *orig_wim, const tchar *swm_name,
 
        for (part_number = 1; part_number <= swm_info->num_parts; part_number++) {
                int part_write_flags;
+               wimlib_progress_func_t progfunc;
 
                if (part_number != 1) {
                        tsprintf(swm_name_buf + swm_base_name_len,
@@ -110,34 +111,42 @@ write_split_wim(WIMStruct *orig_wim, const tchar *swm_name,
                }
 
                progress.split.cur_part_number = part_number;
-               if (progress_func) {
-                       progress_func(WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART,
-                                     &progress);
-               }
+
+               ret = call_progress(orig_wim->progfunc,
+                                   WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART,
+                                   &progress,
+                                   orig_wim->progctx);
+               if (ret)
+                       return ret;
 
                part_write_flags = write_flags;
                part_write_flags |= WIMLIB_WRITE_FLAG_USE_EXISTING_TOTALBYTES;
                if (part_number != 1)
                        part_write_flags |= WIMLIB_WRITE_FLAG_NO_METADATA;
 
+               progfunc = orig_wim->progfunc;
+               orig_wim->progfunc = NULL;
                ret = write_wim_part(orig_wim,
                                     swm_name_buf,
                                     WIMLIB_ALL_IMAGES,
                                     part_write_flags,
                                     1,
-                                    NULL,
                                     part_number,
                                     swm_info->num_parts,
                                     &swm_info->parts[part_number - 1].stream_list,
                                     guid);
+               orig_wim->progfunc = progfunc;
                if (ret)
                        return ret;
 
                progress.split.completed_bytes += swm_info->parts[part_number - 1].size;
-               if (progress_func) {
-                       progress_func(WIMLIB_PROGRESS_MSG_SPLIT_END_PART,
-                                     &progress);
-               }
+
+               ret = call_progress(orig_wim->progfunc,
+                                   WIMLIB_PROGRESS_MSG_SPLIT_END_PART,
+                                   &progress,
+                                   orig_wim->progctx);
+               if (ret)
+                       return ret;
        }
        return 0;
 }
@@ -201,8 +210,7 @@ add_stream_to_swm(struct wim_lookup_table_entry *lte, void *_swm_info)
 /* API function documented in wimlib.h  */
 WIMLIBAPI int
 wimlib_split(WIMStruct *wim, const tchar *swm_name,
-            u64 part_size, int write_flags,
-            wimlib_progress_func_t progress_func)
+            u64 part_size, int write_flags)
 {
        struct swm_info swm_info;
        unsigned i;
@@ -233,8 +241,7 @@ wimlib_split(WIMStruct *wim, const tchar *swm_name,
        if (ret)
                goto out_free_swm_info;
 
-       ret = write_split_wim(wim, swm_name, &swm_info, write_flags,
-                             progress_func);
+       ret = write_split_wim(wim, swm_name, &swm_info, write_flags);
 out_free_swm_info:
        FREE(swm_info.parts);
        return ret;
index 6b21015..844f2f6 100644 (file)
@@ -207,7 +207,7 @@ dentry_reference_template(struct wim_dentry *dentry, void *_args)
 WIMLIBAPI int
 wimlib_reference_template_image(WIMStruct *wim, int new_image,
                                WIMStruct *template_wim, int template_image,
-                               int flags, wimlib_progress_func_t progress_func)
+                               int flags)
 {
        int ret;
        struct wim_image_metadata *new_imd;
index 281cbcb..c6444d3 100644 (file)
@@ -291,10 +291,9 @@ unix_scan_symlink(struct wim_dentry **root_p, const char *full_path,
                        *root_p = NULL;
                        params->progress.scan.cur_path = full_path;
                        params->progress.scan.symlink_target = deref_name_buf;
-                       do_capture_progress(params,
-                                           WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK,
-                                           NULL);
-                       return 0;
+                       return do_capture_progress(params,
+                                                  WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK,
+                                                  NULL);
                }
                inode->i_not_rpfixed = 0;
        }
@@ -358,8 +357,7 @@ unix_build_dentry_tree_recursive(struct wim_dentry **tree_ret,
                        goto out;
                }
                params->progress.scan.cur_path = full_path;
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL);
-               ret = 0;
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL);
                goto out;
        }
 
@@ -418,9 +416,9 @@ unix_build_dentry_tree_recursive(struct wim_dentry **tree_ret,
 out_progress:
        params->progress.scan.cur_path = full_path;
        if (likely(tree))
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode);
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode);
        else
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
 out:
        if (likely(ret == 0))
                *tree_ret = tree;
index 6779a12..ef53280 100644 (file)
@@ -35,6 +35,7 @@
 #  include "wimlib/ntfs_3g.h" /* for do_ntfs_umount() */
 #endif
 #include "wimlib/paths.h"
+#include "wimlib/progress.h"
 #include "wimlib/xml.h"
 
 #include <errno.h>
@@ -460,7 +461,8 @@ rollback_update(struct update_command_journal *j)
 static int
 handle_conflict(struct wim_dentry *branch, struct wim_dentry *existing,
                struct update_command_journal *j,
-               int add_flags, wimlib_progress_func_t progress_func)
+               int add_flags,
+               wimlib_progress_func_t progfunc, void *progctx)
 {
        bool branch_is_dir = dentry_is_directory(branch);
        bool existing_is_dir = dentry_is_directory(existing);
@@ -497,7 +499,8 @@ handle_conflict(struct wim_dentry *branch, struct wim_dentry *existing,
                        unlink_dentry(new_child);
                        if (existing_child) {
                                ret = handle_conflict(new_child, existing_child,
-                                                     j, add_flags, progress_func);
+                                                     j, add_flags,
+                                                     progfunc, progctx);
                        } else {
                                ret = journaled_link(j, new_child, existing);
                        }
@@ -517,6 +520,7 @@ handle_conflict(struct wim_dentry *branch, struct wim_dentry *existing,
                /* Replace nondirectory file  */
                struct wim_dentry *parent;
                int ret;
+               union wimlib_progress_info info;
 
                parent = existing->parent;
 
@@ -532,20 +536,18 @@ handle_conflict(struct wim_dentry *branch, struct wim_dentry *existing,
                if (ret)
                        return ret;
 
-               if (progress_func && (add_flags & WIMLIB_ADD_FLAG_VERBOSE)) {
-                       union wimlib_progress_info info;
 
-                       info.replace.path_in_wim = existing->_full_path;
-                       progress_func(WIMLIB_PROGRESS_MSG_REPLACE_FILE_IN_WIM, &info);
-               }
-               return 0;
+               info.replace.path_in_wim = existing->_full_path;
+               return call_progress(progfunc,
+                                    WIMLIB_PROGRESS_MSG_REPLACE_FILE_IN_WIM,
+                                    &info, progctx);
        }
 }
 
 static int
 do_attach_branch(struct wim_dentry *branch, const utf16lechar *target,
                 struct update_command_journal *j,
-                int add_flags, wimlib_progress_func_t progress_func)
+                int add_flags, wimlib_progress_func_t progfunc, void *progctx)
 {
        struct wim_dentry *parent;
        struct wim_dentry *existing;
@@ -629,8 +631,8 @@ do_attach_branch(struct wim_dentry *branch, const utf16lechar *target,
 
        /* Last component  */
        if (existing) {
-               return handle_conflict(branch, existing, j,
-                                      add_flags, progress_func);
+               return handle_conflict(branch, existing, j, add_flags,
+                                      progfunc, progctx);
        } else {
                return journaled_link(j, branch, parent);
        }
@@ -651,8 +653,8 @@ do_attach_branch(struct wim_dentry *branch, const utf16lechar *target,
  */
 static int
 attach_branch(struct wim_dentry *branch, const tchar *target_tstr,
-             struct update_command_journal *j,
-             int add_flags, wimlib_progress_func_t progress_func)
+             struct update_command_journal *j, int add_flags,
+             wimlib_progress_func_t progfunc, void *progctx)
 {
        int ret;
        const utf16lechar *target;
@@ -670,7 +672,7 @@ attach_branch(struct wim_dentry *branch, const tchar *target_tstr,
        if (ret)
                goto out_free_target;
 
-       ret = do_attach_branch(branch, target, j, add_flags, progress_func);
+       ret = do_attach_branch(branch, target, j, add_flags, progfunc, progctx);
        if (ret)
                goto out_free_target;
        /* branch was successfully committed to the journal  */
@@ -755,8 +757,7 @@ execute_add_command(struct update_command_journal *j,
                    const struct wimlib_update_command *add_cmd,
                    struct wim_inode_table *inode_table,
                    struct wim_sd_set *sd_set,
-                   struct list_head *unhashed_streams,
-                   wimlib_progress_func_t progress_func)
+                   struct list_head *unhashed_streams)
 {
        int ret;
        int add_flags;
@@ -807,11 +808,14 @@ execute_add_command(struct update_command_journal *j,
        params.add_flags = add_flags;
        params.extra_arg = extra_arg;
 
-       params.progress_func = progress_func;
+       params.progfunc = wim->progfunc;
+       params.progctx = wim->progctx;
        params.progress.scan.source = fs_source_path;
        params.progress.scan.wim_target_path = wim_target_path;
-       if (progress_func)
-               progress_func(WIMLIB_PROGRESS_MSG_SCAN_BEGIN, &params.progress);
+       ret = call_progress(params.progfunc, WIMLIB_PROGRESS_MSG_SCAN_BEGIN,
+                           &params.progress, params.progctx);
+       if (ret)
+               goto out_destroy_config;
 
        if (WIMLIB_IS_WIM_ROOT_PATH(wim_target_path))
                params.add_flags |= WIMLIB_ADD_FLAG_ROOT;
@@ -819,8 +823,12 @@ execute_add_command(struct update_command_journal *j,
        if (ret)
                goto out_destroy_config;
 
-       if (progress_func)
-               progress_func(WIMLIB_PROGRESS_MSG_SCAN_END, &params.progress);
+       ret = call_progress(params.progfunc, WIMLIB_PROGRESS_MSG_SCAN_END,
+                           &params.progress, params.progctx);
+       if (ret) {
+               free_dentry_tree(branch, wim->lookup_table);
+               goto out_cleanup_after_capture;
+       }
 
        if (WIMLIB_IS_WIM_ROOT_PATH(wim_target_path) &&
            branch && !dentry_is_directory(branch))
@@ -832,7 +840,7 @@ execute_add_command(struct update_command_journal *j,
        }
 
        ret = attach_branch(branch, wim_target_path, j,
-                           add_flags, params.progress_func);
+                           add_flags, params.progfunc, params.progctx);
        if (ret)
                goto out_cleanup_after_capture;
 
@@ -840,7 +848,7 @@ execute_add_command(struct update_command_journal *j,
            WIMLIB_IS_WIM_ROOT_PATH(wim_target_path))
        {
                params.add_flags = 0;
-               params.progress_func = NULL;
+               params.progfunc = NULL;
                params.config = NULL;
 
                /* If a capture configuration file was explicitly specified when
@@ -850,7 +858,7 @@ execute_add_command(struct update_command_journal *j,
                if (ret)
                        goto out_cleanup_after_capture;
 
-               ret = attach_branch(branch, wimboot_cfgfile, j, 0, NULL);
+               ret = attach_branch(branch, wimboot_cfgfile, j, 0, NULL, NULL);
                if (ret)
                        goto out_cleanup_after_capture;
        }
@@ -1087,8 +1095,7 @@ static int
 execute_update_commands(WIMStruct *wim,
                        const struct wimlib_update_command *cmds,
                        size_t num_cmds,
-                       int update_flags,
-                       wimlib_progress_func_t progress_func)
+                       int update_flags)
 {
        struct wim_inode_table *inode_table;
        struct wim_sd_set *sd_set;
@@ -1134,19 +1141,20 @@ execute_update_commands(WIMStruct *wim,
        for (size_t i = 0; i < num_cmds; i++) {
                DEBUG("Executing update command %zu of %zu (op=%"TS")",
                      i + 1, num_cmds, update_op_to_str(cmds[i].op));
-               if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS &&
-                   progress_func)
-               {
-                       info.update.command = &cmds[i];
-                       (*progress_func)(WIMLIB_PROGRESS_MSG_UPDATE_BEGIN_COMMAND,
-                                        &info);
+               info.update.command = &cmds[i];
+               if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS) {
+                       ret = call_progress(wim->progfunc,
+                                           WIMLIB_PROGRESS_MSG_UPDATE_BEGIN_COMMAND,
+                                           &info, wim->progctx);
+                       if (ret)
+                               goto rollback;
                }
+
                ret = WIMLIB_ERR_INVALID_PARAM;
                switch (cmds[i].op) {
                case WIMLIB_UPDATE_OP_ADD:
                        ret = execute_add_command(j, wim, &cmds[i], inode_table,
-                                                 sd_set, &unhashed_streams,
-                                                 progress_func);
+                                                 sd_set, &unhashed_streams);
                        break;
                case WIMLIB_UPDATE_OP_DELETE:
                        ret = execute_delete_command(j, wim, &cmds[i]);
@@ -1158,11 +1166,12 @@ execute_update_commands(WIMStruct *wim,
                if (unlikely(ret))
                        goto rollback;
                info.update.completed_commands++;
-               if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS &&
-                   progress_func)
-               {
-                       (*progress_func)(WIMLIB_PROGRESS_MSG_UPDATE_END_COMMAND,
-                                        &info);
+               if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS) {
+                       ret = call_progress(wim->progfunc,
+                                           WIMLIB_PROGRESS_MSG_UPDATE_END_COMMAND,
+                                           &info, wim->progctx);
+                       if (ret)
+                               goto rollback;
                }
                next_command(j);
        }
@@ -1415,8 +1424,7 @@ wimlib_update_image(WIMStruct *wim,
                    int image,
                    const struct wimlib_update_command *cmds,
                    size_t num_cmds,
-                   int update_flags,
-                   wimlib_progress_func_t progress_func)
+                   int update_flags)
 {
        int ret;
        struct wimlib_update_command *cmds_copy;
@@ -1457,8 +1465,7 @@ wimlib_update_image(WIMStruct *wim,
 
        /* Actually execute the update commands. */
        DEBUG("Executing %zu update commands", num_cmds);
-       ret = execute_update_commands(wim, cmds_copy, num_cmds, update_flags,
-                                     progress_func);
+       ret = execute_update_commands(wim, cmds_copy, num_cmds, update_flags);
        if (ret)
                goto out_free_cmds_copy;
 
@@ -1477,7 +1484,7 @@ out:
 static int
 update1(WIMStruct *wim, int image, const struct wimlib_update_command *cmd)
 {
-       return wimlib_update_image(wim, image, cmd, 1, 0, NULL);
+       return wimlib_update_image(wim, image, cmd, 1, 0);
 }
 
 WIMLIBAPI int
index 1addc85..02017d0 100644 (file)
@@ -346,6 +346,10 @@ static const tchar *error_strings[] = {
                = T("The WIM file (or parts of it) is encrypted"),
        [WIMLIB_ERR_WIMBOOT]
                = T("Failed to set WIMBoot pointer data"),
+       [WIMLIB_ERR_ABORTED_BY_PROGRESS]
+               = T("The operation was aborted by the library user"),
+       [WIMLIB_ERR_UNKNOWN_PROGRESS_STATUS]
+               = T("The user-provided progress function returned an unrecognized value"),
 };
 
 /* API function documented in wimlib.h  */
index 960a9d5..ff4ac29 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -622,6 +622,15 @@ wimlib_set_output_pack_chunk_size(WIMStruct *wim, uint32_t chunk_size)
                                  &wim->out_pack_chunk_size);
 }
 
+WIMLIBAPI void
+wimlib_register_progress_function(WIMStruct *wim,
+                                 wimlib_progress_func_t progfunc,
+                                 void *progctx)
+{
+       wim->progfunc = progfunc;
+       wim->progctx = progctx;
+}
+
 static int
 open_wim_file(const tchar *filename, struct filedes *fd_ret)
 {
@@ -641,8 +650,7 @@ open_wim_file(const tchar *filename, struct filedes *fd_ret)
  * lookup table, and optionally checks the integrity.
  */
 static int
-begin_read(WIMStruct *wim, const void *wim_filename_or_fd,
-          int open_flags, wimlib_progress_func_t progress_func)
+begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags)
 {
        int ret;
        int xml_num_images;
@@ -743,7 +751,7 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd,
        }
 
        if (open_flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY) {
-               ret = check_wim_integrity(wim, progress_func);
+               ret = check_wim_integrity(wim);
                if (ret == WIM_INTEGRITY_NONEXISTENT) {
                        WARNING("No integrity information for `%"TS"'; skipping "
                                "integrity check.", wimfile);
@@ -791,7 +799,8 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd,
 
 int
 open_wim_as_WIMStruct(const void *wim_filename_or_fd, int open_flags,
-                     WIMStruct **wim_ret, wimlib_progress_func_t progress_func)
+                     WIMStruct **wim_ret,
+                     wimlib_progress_func_t progfunc, void *progctx)
 {
        WIMStruct *wim;
        int ret;
@@ -810,7 +819,10 @@ open_wim_as_WIMStruct(const void *wim_filename_or_fd, int open_flags,
        if (wim == NULL)
                return WIMLIB_ERR_NOMEM;
 
-       ret = begin_read(wim, wim_filename_or_fd, open_flags, progress_func);
+       wim->progfunc = progfunc;
+       wim->progctx = progctx;
+
+       ret = begin_read(wim, wim_filename_or_fd, open_flags);
        if (ret) {
                wimlib_free(wim);
                return ret;
@@ -823,8 +835,9 @@ open_wim_as_WIMStruct(const void *wim_filename_or_fd, int open_flags,
 
 /* API function documented in wimlib.h  */
 WIMLIBAPI int
-wimlib_open_wim(const tchar *wimfile, int open_flags,
-               WIMStruct **wim_ret, wimlib_progress_func_t progress_func)
+wimlib_open_wim_with_progress(const tchar *wimfile, int open_flags,
+                             WIMStruct **wim_ret,
+                             wimlib_progress_func_t progfunc, void *progctx)
 {
        if (open_flags & ~(WIMLIB_OPEN_FLAG_CHECK_INTEGRITY |
                           WIMLIB_OPEN_FLAG_ERROR_IF_SPLIT |
@@ -832,7 +845,15 @@ wimlib_open_wim(const tchar *wimfile, int open_flags,
                return WIMLIB_ERR_INVALID_PARAM;
 
        return open_wim_as_WIMStruct(wimfile, open_flags, wim_ret,
-                                    progress_func);
+                                    progfunc, progctx);
+}
+
+/* API function documented in wimlib.h  */
+WIMLIBAPI int
+wimlib_open_wim(const tchar *wimfile, int open_flags, WIMStruct **wim_ret)
+{
+       return wimlib_open_wim_with_progress(wimfile, open_flags, wim_ret,
+                                            NULL, NULL);
 }
 
 /* Checksum all streams that are unhashed (other than the metadata streams),
index 5c861c2..f741b44 100644 (file)
@@ -1344,17 +1344,17 @@ begin_extract_stream_instance(const struct wim_lookup_table_entry *stream,
                if (ret)
                        return ret;
                if (in_prepopulate_list(dentry, ctx)) {
-                       if (ctx->common.progress_func) {
-                               union wimlib_progress_info info;
+                       union wimlib_progress_info info;
 
-                               info.wimboot_exclude.path_in_wim = dentry->_full_path;
-                               info.wimboot_exclude.extraction_path = current_path(ctx);
+                       info.wimboot_exclude.path_in_wim = dentry->_full_path;
+                       info.wimboot_exclude.extraction_path = current_path(ctx);
 
-                               ctx->common.progress_func(WIMLIB_PROGRESS_MSG_WIMBOOT_EXCLUDE,
-                                                         &info);
-                               FREE(dentry->_full_path);
-                               dentry->_full_path = NULL;
-                       }
+                       ret = call_progress(ctx->common.progfunc,
+                                           WIMLIB_PROGRESS_MSG_WIMBOOT_EXCLUDE,
+                                           &info, ctx->common.progctx);
+                       FREE(dentry->_full_path);
+                       dentry->_full_path = NULL;
+                       return ret;
                } else {
                        FREE(dentry->_full_path);
                        dentry->_full_path = NULL;
index 4556ba9..0115ed0 100644 (file)
@@ -589,7 +589,7 @@ out_close_root_dir:
        return p;
 }
 
-static enum rp_status
+static int
 winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
                u64 capture_root_ino, u64 capture_root_dev,
                const wchar_t *path, struct add_image_params *params)
@@ -644,7 +644,11 @@ winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
 
                params->progress.scan.cur_path = printable_path(path);
                params->progress.scan.symlink_target = print_name0;
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK, NULL);
+               int ret = do_capture_progress(params,
+                                             WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK,
+                                             NULL);
+               if (ret)
+                       return ret;
                return RP_EXCLUDED;
        }
 
@@ -698,7 +702,7 @@ winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
  *     Path to the reparse point file.
  * @params:
  *     Capture parameters.  add_flags, capture_root_ino, capture_root_dev,
- *     progress_func, and progress are used.
+ *     progfunc, progctx, and progress are used.
  * @rpbuf:
  *     Buffer of length at least REPARSE_POINT_MAX_SIZE bytes into which the
  *     reparse point buffer will be loaded.
@@ -1329,9 +1333,9 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
 out_progress:
        params->progress.scan.cur_path = printable_path(full_path);
        if (likely(root))
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode);
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode);
        else
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
 out:
        if (likely(h != INVALID_HANDLE_VALUE))
                (*func_NtClose)(h);
index ae17548..2b8347d 100644 (file)
@@ -43,6 +43,7 @@
 #include "wimlib/integrity.h"
 #include "wimlib/lookup_table.h"
 #include "wimlib/metadata.h"
+#include "wimlib/progress.h"
 #include "wimlib/resource.h"
 #ifdef __WIN32__
 #  include "wimlib/win32.h" /* win32_rename_replacement() */
@@ -270,12 +271,13 @@ write_pwm_stream_header(const struct wim_lookup_table_entry *lte,
 }
 
 struct write_streams_progress_data {
-       wimlib_progress_func_t progress_func;
+       wimlib_progress_func_t progfunc;
+       void *progctx;
        union wimlib_progress_info progress;
        uint64_t next_progress;
 };
 
-static void
+static int
 do_write_streams_progress(struct write_streams_progress_data *progress_data,
                          struct wim_lookup_table_entry *cur_stream,
                          u64 complete_size,
@@ -283,6 +285,7 @@ do_write_streams_progress(struct write_streams_progress_data *progress_data,
                          bool discarded)
 {
        union wimlib_progress_info *progress = &progress_data->progress;
+       int ret;
 
        if (discarded) {
                progress->write_streams.total_bytes -= complete_size;
@@ -297,11 +300,15 @@ do_write_streams_progress(struct write_streams_progress_data *progress_data,
                progress->write_streams.completed_streams += complete_count;
        }
 
-       if (progress_data->progress_func
-           && (progress->write_streams.completed_bytes >= progress_data->next_progress))
+       if (progress->write_streams.completed_bytes >= progress_data->next_progress)
        {
-               progress_data->progress_func(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
-                                            progress);
+               ret = call_progress(progress_data->progfunc,
+                                   WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
+                                   progress,
+                                   progress_data->progctx);
+               if (ret)
+                       return ret;
+
                if (progress_data->next_progress == progress->write_streams.total_bytes) {
                        progress_data->next_progress = ~(uint64_t)0;
                } else {
@@ -311,6 +318,7 @@ do_write_streams_progress(struct write_streams_progress_data *progress_data,
                                        progress->write_streams.total_bytes / 100);
                }
        }
+       return 0;
 }
 
 struct write_streams_ctx {
@@ -658,9 +666,9 @@ write_stream_begin_read(struct wim_lookup_table_entry *lte,
                                 * duplicate stream in the former case.  */
                                DEBUG("Discarding duplicate stream of "
                                      "length %"PRIu64, lte->size);
-                               do_write_streams_progress(&ctx->progress_data,
-                                                         lte, lte->size,
-                                                         1, true);
+                               ret = do_write_streams_progress(&ctx->progress_data,
+                                                               lte, lte->size,
+                                                               1, true);
                                list_del(&lte->write_streams_list);
                                list_del(&lte->lookup_table_list);
                                if (lte_new->will_be_in_output_wim)
@@ -668,6 +676,8 @@ write_stream_begin_read(struct wim_lookup_table_entry *lte,
                                if (ctx->write_resource_flags & WRITE_RESOURCE_FLAG_PACK_STREAMS)
                                        ctx->cur_write_res_size -= lte->size;
                                free_lookup_table_entry(lte);
+                               if (ret)
+                                       return ret;
                                return BEGIN_STREAM_STATUS_SKIP_STREAM;
                        } else {
                                /* The duplicate stream can validly be written,
@@ -876,11 +886,9 @@ write_chunk(struct write_streams_ctx *ctx, const void *cchunk,
                }
        }
 
-       do_write_streams_progress(&ctx->progress_data, lte,
-                                 completed_size, completed_stream_count,
-                                 false);
-
-       return 0;
+       return do_write_streams_progress(&ctx->progress_data, lte,
+                                        completed_size, completed_stream_count,
+                                        false);
 
 error:
        ERROR_WITH_ERRNO("Write error");
@@ -1169,8 +1177,10 @@ write_raw_copy_resources(struct list_head *raw_copy_streams,
                                return ret;
                        lte->rspec->raw_copy_ok = 0;
                }
-               do_write_streams_progress(progress_data, lte, lte->size,
-                                         1, false);
+               ret = do_write_streams_progress(progress_data, lte, lte->size,
+                                               1, false);
+               if (ret)
+                       return ret;
        }
        return 0;
 }
@@ -1278,12 +1288,6 @@ remove_zero_length_streams(struct list_head *stream_list)
  *     no streams are hard-filtered or no streams are unhashed, this parameter
  *     can be NULL.
  *
- * @progress_func
- *     If non-NULL, a progress function that will be called periodically with
- *     WIMLIB_PROGRESS_MSG_WRITE_STREAMS messages.  Note that on-the-fly
- *     deduplication of unhashed streams may result in the total bytes provided
- *     in the progress data to decrease from one message to the next.
- *
  * This function will write the streams in @stream_list to resources in
  * consecutive positions in the output WIM file, or to a single packed resource
  * if WRITE_RESOURCE_FLAG_PACK_STREAMS was specified in @write_resource_flags.
@@ -1341,7 +1345,8 @@ write_stream_list(struct list_head *stream_list,
                  unsigned num_threads,
                  struct wim_lookup_table *lookup_table,
                  struct filter_context *filter_ctx,
-                 wimlib_progress_func_t progress_func)
+                 wimlib_progress_func_t progfunc,
+                 void *progctx)
 {
        int ret;
        struct write_streams_ctx ctx;
@@ -1393,7 +1398,8 @@ write_stream_list(struct list_head *stream_list,
 
        compute_stream_list_stats(stream_list, &ctx);
 
-       ctx.progress_data.progress_func = progress_func;
+       ctx.progress_data.progfunc = progfunc;
+       ctx.progress_data.progctx = progctx;
 
        ctx.num_bytes_to_compress = find_raw_copy_streams(stream_list,
                                                          write_resource_flags,
@@ -1454,10 +1460,12 @@ write_stream_list(struct list_head *stream_list,
        INIT_LIST_HEAD(&ctx.pending_streams);
        INIT_LIST_HEAD(&ctx.pack_streams);
 
-       if (ctx.progress_data.progress_func) {
-               (*ctx.progress_data.progress_func)(WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
-                                                  &ctx.progress_data.progress);
-       }
+       ret = call_progress(ctx.progress_data.progfunc,
+                           WIMLIB_PROGRESS_MSG_WRITE_STREAMS,
+                           &ctx.progress_data.progress,
+                           ctx.progress_data.progctx);
+       if (ret)
+               goto out_destroy_context;
 
        if (write_resource_flags & WRITE_RESOURCE_FLAG_PACK_STREAMS) {
                ret = begin_write_resource(&ctx, ctx.num_bytes_to_compress);
@@ -1553,8 +1561,7 @@ wim_write_stream_list(WIMStruct *wim,
                      struct list_head *stream_list,
                      int write_flags,
                      unsigned num_threads,
-                     struct filter_context *filter_ctx,
-                     wimlib_progress_func_t progress_func)
+                     struct filter_context *filter_ctx)
 {
        int out_ctype;
        u32 out_chunk_size;
@@ -1588,7 +1595,8 @@ wim_write_stream_list(WIMStruct *wim,
                                 num_threads,
                                 wim->lookup_table,
                                 filter_ctx,
-                                progress_func);
+                                wim->progfunc,
+                                wim->progctx);
 }
 
 static int
@@ -1609,6 +1617,7 @@ write_wim_resource(struct wim_lookup_table_entry *lte,
                                 1,
                                 NULL,
                                 NULL,
+                                NULL,
                                 NULL);
 }
 
@@ -2006,7 +2015,6 @@ prepare_stream_list_for_write(WIMStruct *wim, int image,
 static int
 write_wim_streams(WIMStruct *wim, int image, int write_flags,
                  unsigned num_threads,
-                 wimlib_progress_func_t progress_func,
                  struct list_head *stream_list_override,
                  struct list_head *lookup_table_list_ret)
 {
@@ -2047,13 +2055,11 @@ write_wim_streams(WIMStruct *wim, int image, int write_flags,
                                     stream_list,
                                     write_flags,
                                     num_threads,
-                                    filter_ctx,
-                                    progress_func);
+                                    filter_ctx);
 }
 
 static int
-write_wim_metadata_resources(WIMStruct *wim, int image, int write_flags,
-                            wimlib_progress_func_t progress_func)
+write_wim_metadata_resources(WIMStruct *wim, int image, int write_flags)
 {
        int ret;
        int start_image;
@@ -2072,8 +2078,11 @@ write_wim_metadata_resources(WIMStruct *wim, int image, int write_flags,
        DEBUG("Writing metadata resources (offset=%"PRIu64")",
              wim->out_fd.offset);
 
-       if (progress_func)
-               progress_func(WIMLIB_PROGRESS_MSG_WRITE_METADATA_BEGIN, NULL);
+       ret = call_progress(wim->progfunc,
+                           WIMLIB_PROGRESS_MSG_WRITE_METADATA_BEGIN,
+                           NULL, wim->progctx);
+       if (ret)
+               return ret;
 
        if (image == WIMLIB_ALL_IMAGES) {
                start_image = 1;
@@ -2112,9 +2121,10 @@ write_wim_metadata_resources(WIMStruct *wim, int image, int write_flags,
                if (ret)
                        return ret;
        }
-       if (progress_func)
-               progress_func(WIMLIB_PROGRESS_MSG_WRITE_METADATA_END, NULL);
-       return 0;
+
+       return call_progress(wim->progfunc,
+                            WIMLIB_PROGRESS_MSG_WRITE_METADATA_END,
+                            NULL, wim->progctx);
 }
 
 static int
@@ -2278,7 +2288,6 @@ write_wim_lookup_table(WIMStruct *wim, int image, int write_flags,
  */
 static int
 finish_write(WIMStruct *wim, int image, int write_flags,
-            wimlib_progress_func_t progress_func,
             struct list_head *lookup_table_list)
 {
        int ret;
@@ -2347,8 +2356,7 @@ finish_write(WIMStruct *wim, int image, int write_flags,
 
                ret = write_integrity_table(wim,
                                            new_lookup_table_end,
-                                           old_lookup_table_end,
-                                           progress_func);
+                                           old_lookup_table_end);
                if (ret)
                        return ret;
        } else {
@@ -2497,7 +2505,7 @@ lock_wim(WIMStruct *wim, int fd)
  */
 static int
 write_pipable_wim(WIMStruct *wim, int image, int write_flags,
-                 unsigned num_threads, wimlib_progress_func_t progress_func,
+                 unsigned num_threads,
                  struct list_head *stream_list_override,
                  struct list_head *lookup_table_list_ret)
 {
@@ -2532,16 +2540,14 @@ write_pipable_wim(WIMStruct *wim, int image, int write_flags,
 
        /* Write metadata resources for the image(s) being included in the
         * output WIM.  */
-       ret = write_wim_metadata_resources(wim, image, write_flags,
-                                          progress_func);
+       ret = write_wim_metadata_resources(wim, image, write_flags);
        if (ret)
                return ret;
 
        /* Write streams needed for the image(s) being included in the output
         * WIM, or streams needed for the split WIM part.  */
        return write_wim_streams(wim, image, write_flags, num_threads,
-                                progress_func, stream_list_override,
-                                lookup_table_list_ret);
+                                stream_list_override, lookup_table_list_ret);
 
        /* The lookup table, XML data, and header at end are handled by
         * finish_write().  */
@@ -2555,7 +2561,6 @@ write_wim_part(WIMStruct *wim,
               int image,
               int write_flags,
               unsigned num_threads,
-              wimlib_progress_func_t progress_func,
               unsigned part_number,
               unsigned total_parts,
               struct list_head *stream_list_override,
@@ -2631,7 +2636,7 @@ write_wim_part(WIMStruct *wim,
                DEBUG("Number of threads: autodetect");
        else
                DEBUG("Number of threads: %u", num_threads);
-       DEBUG("Progress function: %s", (progress_func ? "yes" : "no"));
+       DEBUG("Progress function: %s", (wim->progfunc ? "yes" : "no"));
        DEBUG("Stream list:       %s", (stream_list_override ? "specified" : "autodetect"));
        DEBUG("GUID:              %s", (write_flags &
                                        WIMLIB_WRITE_FLAG_RETAIN_GUID) ? "retain"
@@ -2799,19 +2804,18 @@ write_wim_part(WIMStruct *wim,
        if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE)) {
                /* Default case: create a normal (non-pipable) WIM.  */
                ret = write_wim_streams(wim, image, write_flags, num_threads,
-                                       progress_func, stream_list_override,
+                                       stream_list_override,
                                        &lookup_table_list);
                if (ret)
                        goto out_restore_hdr;
 
-               ret = write_wim_metadata_resources(wim, image, write_flags,
-                                                  progress_func);
+               ret = write_wim_metadata_resources(wim, image, write_flags);
                if (ret)
                        goto out_restore_hdr;
        } else {
                /* Non-default case: create pipable WIM.  */
                ret = write_pipable_wim(wim, image, write_flags, num_threads,
-                                       progress_func, stream_list_override,
+                                       stream_list_override,
                                        &lookup_table_list);
                if (ret)
                        goto out_restore_hdr;
@@ -2820,8 +2824,7 @@ write_wim_part(WIMStruct *wim,
 
 
        /* Write lookup table, XML data, and (optional) integrity table.  */
-       ret = finish_write(wim, image, write_flags, progress_func,
-                          &lookup_table_list);
+       ret = finish_write(wim, image, write_flags, &lookup_table_list);
 out_restore_hdr:
        memcpy(&wim->hdr, &hdr_save, sizeof(struct wim_header));
        (void)close_wim_writable(wim, write_flags);
@@ -2832,18 +2835,16 @@ out_restore_hdr:
 /* Write a standalone WIM to a file or file descriptor.  */
 static int
 write_standalone_wim(WIMStruct *wim, const void *path_or_fd,
-                    int image, int write_flags, unsigned num_threads,
-                    wimlib_progress_func_t progress_func)
+                    int image, int write_flags, unsigned num_threads)
 {
        return write_wim_part(wim, path_or_fd, image, write_flags,
-                             num_threads, progress_func, 1, 1, NULL, NULL);
+                             num_threads, 1, 1, NULL, NULL);
 }
 
 /* API function documented in wimlib.h  */
 WIMLIBAPI int
 wimlib_write(WIMStruct *wim, const tchar *path,
-            int image, int write_flags, unsigned num_threads,
-            wimlib_progress_func_t progress_func)
+            int image, int write_flags, unsigned num_threads)
 {
        if (write_flags & ~WIMLIB_WRITE_MASK_PUBLIC)
                return WIMLIB_ERR_INVALID_PARAM;
@@ -2851,15 +2852,13 @@ wimlib_write(WIMStruct *wim, const tchar *path,
        if (path == NULL || path[0] == T('\0'))
                return WIMLIB_ERR_INVALID_PARAM;
 
-       return write_standalone_wim(wim, path, image, write_flags,
-                                   num_threads, progress_func);
+       return write_standalone_wim(wim, path, image, write_flags, num_threads);
 }
 
 /* API function documented in wimlib.h  */
 WIMLIBAPI int
 wimlib_write_to_fd(WIMStruct *wim, int fd,
-                  int image, int write_flags, unsigned num_threads,
-                  wimlib_progress_func_t progress_func)
+                  int image, int write_flags, unsigned num_threads)
 {
        if (write_flags & ~WIMLIB_WRITE_MASK_PUBLIC)
                return WIMLIB_ERR_INVALID_PARAM;
@@ -2869,8 +2868,7 @@ wimlib_write_to_fd(WIMStruct *wim, int fd,
 
        write_flags |= WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR;
 
-       return write_standalone_wim(wim, &fd, image, write_flags,
-                                   num_threads, progress_func);
+       return write_standalone_wim(wim, &fd, image, write_flags, num_threads);
 }
 
 static bool
@@ -2974,9 +2972,7 @@ check_resource_offsets(WIMStruct *wim, off_t end_offset)
  * small amount of space compared to the streams, however.)
  */
 static int
-overwrite_wim_inplace(WIMStruct *wim, int write_flags,
-                     unsigned num_threads,
-                     wimlib_progress_func_t progress_func)
+overwrite_wim_inplace(WIMStruct *wim, int write_flags, unsigned num_threads)
 {
        int ret;
        off_t old_wim_end;
@@ -3088,19 +3084,17 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags,
                                    &stream_list,
                                    write_flags,
                                    num_threads,
-                                   &filter_ctx,
-                                   progress_func);
+                                   &filter_ctx);
        if (ret)
                goto out_truncate;
 
-       ret = write_wim_metadata_resources(wim, WIMLIB_ALL_IMAGES,
-                                          write_flags, progress_func);
+       ret = write_wim_metadata_resources(wim, WIMLIB_ALL_IMAGES, write_flags);
        if (ret)
                goto out_truncate;
 
        write_flags |= WIMLIB_WRITE_FLAG_REUSE_INTEGRITY_TABLE;
        ret = finish_write(wim, WIMLIB_ALL_IMAGES, write_flags,
-                          progress_func, &lookup_table_list);
+                          &lookup_table_list);
        if (ret)
                goto out_truncate;
 
@@ -3127,9 +3121,7 @@ out_restore_memory_hdr:
 }
 
 static int
-overwrite_wim_via_tmpfile(WIMStruct *wim, int write_flags,
-                         unsigned num_threads,
-                         wimlib_progress_func_t progress_func)
+overwrite_wim_via_tmpfile(WIMStruct *wim, int write_flags, unsigned num_threads)
 {
        size_t wim_name_len;
        int ret;
@@ -3148,7 +3140,7 @@ overwrite_wim_via_tmpfile(WIMStruct *wim, int write_flags,
                           write_flags |
                                WIMLIB_WRITE_FLAG_FSYNC |
                                WIMLIB_WRITE_FLAG_RETAIN_GUID,
-                          num_threads, progress_func);
+                          num_threads);
        if (ret) {
                tunlink(tmpfile);
                return ret;
@@ -3176,13 +3168,11 @@ overwrite_wim_via_tmpfile(WIMStruct *wim, int write_flags,
                return WIMLIB_ERR_RENAME;
        }
 
-       if (progress_func) {
-               union wimlib_progress_info progress;
-               progress.rename.from = tmpfile;
-               progress.rename.to = wim->filename;
-               progress_func(WIMLIB_PROGRESS_MSG_RENAME, &progress);
-       }
-       return 0;
+       union wimlib_progress_info progress;
+       progress.rename.from = tmpfile;
+       progress.rename.to = wim->filename;
+       return call_progress(wim->progfunc, WIMLIB_PROGRESS_MSG_RENAME,
+                            &progress, wim->progctx);
 }
 
 /* Determine if the specified WIM file may be updated by appending in-place
@@ -3216,9 +3206,7 @@ can_overwrite_wim_inplace(const WIMStruct *wim, int write_flags)
 
 /* API function documented in wimlib.h  */
 WIMLIBAPI int
-wimlib_overwrite(WIMStruct *wim, int write_flags,
-                unsigned num_threads,
-                wimlib_progress_func_t progress_func)
+wimlib_overwrite(WIMStruct *wim, int write_flags, unsigned num_threads)
 {
        int ret;
        u32 orig_hdr_flags;
@@ -3238,12 +3226,10 @@ wimlib_overwrite(WIMStruct *wim, int write_flags,
                return ret;
 
        if (can_overwrite_wim_inplace(wim, write_flags)) {
-               ret = overwrite_wim_inplace(wim, write_flags, num_threads,
-                                           progress_func);
+               ret = overwrite_wim_inplace(wim, write_flags, num_threads);
                if (ret != WIMLIB_ERR_RESOURCE_ORDER)
                        return ret;
                WARNING("Falling back to re-building entire WIM");
        }
-       return overwrite_wim_via_tmpfile(wim, write_flags, num_threads,
-                                        progress_func);
+       return overwrite_wim_via_tmpfile(wim, write_flags, num_threads);
 }