From b5b9681794d1f5f13350e3567f6f6e74f5c779cf Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 22 May 2014 10:50:47 -0500 Subject: [PATCH] Update progress functions - 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 --- Makefile.am | 1 + NEWS | 3 + examples/applywim.c | 15 +- examples/capturewim.c | 15 +- include/wimlib.h | 312 +++++++++++++++++++++++-------------- include/wimlib/apply.h | 10 +- include/wimlib/capture.h | 7 +- include/wimlib/integrity.h | 7 +- include/wimlib/progress.h | 31 ++++ include/wimlib/wim.h | 7 +- include/wimlib/write.h | 1 - programs/imagex.c | 171 ++++++++++---------- src/add_image.c | 11 +- src/capture_common.c | 14 +- src/export_image.c | 3 +- src/extract.c | 148 +++++++++--------- src/integrity.c | 112 +++++++------ src/join.c | 36 +++-- src/mount_image.c | 57 ++++--- src/ntfs-3g_capture.c | 7 +- src/reference.c | 28 ++-- src/split.c | 37 +++-- src/template.c | 2 +- src/unix_capture.c | 14 +- src/update_image.c | 95 +++++------ src/util.c | 4 + src/wim.c | 37 ++++- src/win32_apply.c | 18 +-- src/win32_capture.c | 14 +- src/write.c | 174 ++++++++++----------- 30 files changed, 776 insertions(+), 615 deletions(-) create mode 100644 include/wimlib/progress.h diff --git a/Makefile.am b/Makefile.am index 82a1b5d8..1ff845a2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 3a79d47f..1c78f533 100644 --- 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(), diff --git a/examples/applywim.c b/examples/applywim.c index a92b2637..d6873167 100644 --- a/examples/applywim.c +++ b/examples/applywim.c @@ -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. */ diff --git a/examples/capturewim.c b/examples/capturewim.c index f2719705..e6d4c5ac 100644 --- a/examples/capturewim.c +++ b/examples/capturewim.c @@ -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. */ diff --git a/include/wimlib.h b/include/wimlib.h index a958bd0a..728d132a 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -283,17 +283,28 @@ * 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 diff --git a/include/wimlib/apply.h b/include/wimlib/apply.h index 72c21b5d..6c595d51 100644 --- a/include/wimlib/apply.h +++ b/include/wimlib/apply.h @@ -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, \ diff --git a/include/wimlib/capture.h b/include/wimlib/capture.h index f7ae1ada..58e0eac3 100644 --- a/include/wimlib/capture.h +++ b/include/wimlib/capture.h @@ -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); diff --git a/include/wimlib/integrity.h b/include/wimlib/integrity.h index c9e07ca8..1d115ff8 100644 --- a/include/wimlib/integrity.h +++ b/include/wimlib/integrity.h @@ -1,7 +1,7 @@ #ifndef _WIMLIB_INTEGRITY_H #define _WIMLIB_INTEGRITY_H -#include "wimlib.h" +#include "wimlib/types.h" #include #define WIM_INTEGRITY_OK 0 @@ -11,10 +11,9 @@ 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 index 00000000..387afd83 --- /dev/null +++ b/include/wimlib/progress.h @@ -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 diff --git a/include/wimlib/wim.h b/include/wimlib/wim.h index ea916aa6..86926d89 100644 --- a/include/wimlib/wim.h +++ b/include/wimlib/wim.h @@ -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); diff --git a/include/wimlib/write.h b/include/wimlib/write.h index 7e913e1a..68ada298 100644 --- a/include/wimlib/write.h +++ b/include/wimlib/write.h @@ -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, diff --git a/programs/imagex.c b/programs/imagex.c index 8cd5f674..41ab646d 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -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: diff --git a/src/add_image.c b/src/add_image.c index a544c7b8..cd270390 100644 --- a/src/add_image.c +++ b/src/add_image.c @@ -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); } diff --git a/src/capture_common.c b/src/capture_common.c index 4db070f8..943d919b 100644 --- a/src/capture_common.c +++ b/src/capture_common.c @@ -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" @@ -51,19 +52,19 @@ * 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, - ¶ms->progress); - } + return call_progress(params->progfunc, WIMLIB_PROGRESS_MSG_SCAN_DENTRY, + ¶ms->progress, params->progctx); } /* diff --git a/src/export_image.c b/src/export_image.c index 9c25be73..34b92422 100644 --- a/src/export_image.c +++ b/src/export_image.c @@ -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; diff --git a/src/extract.c b/src/extract.c index 05c3d16b..3adbca34 100644 --- a/src/extract.c +++ b/src/extract.c @@ -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); } diff --git a/src/integrity.c b/src/integrity.c index 350b3a20..ebde9306 100644 --- a/src/integrity.c +++ b/src/integrity.c @@ -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; } diff --git a/src/join.c b/src/join.c index 71e43c09..3a60f1c9 100644 --- a/src/join.c +++ b/src/join.c @@ -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); +} diff --git a/src/mount_image.c b/src/mount_image.c index 06890dbc..e1ff886f 100644 --- a/src/mount_image.c +++ b/src/mount_image.c @@ -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); +} diff --git a/src/ntfs-3g_capture.c b/src/ntfs-3g_capture.c index 5c5b97af..80abca02 100644 --- a/src/ntfs-3g_capture.c +++ b/src/ntfs-3g_capture.c @@ -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; diff --git a/src/reference.c b/src/reference.c index c423bdd7..d1e34e19 100644 --- a/src/reference.c +++ b/src/reference.c @@ -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); } } diff --git a/src/split.c b/src/split.c index d1317cf9..a611816d 100644 --- a/src/split.c +++ b/src/split.c @@ -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; diff --git a/src/template.c b/src/template.c index 6b21015a..844f2f6d 100644 --- a/src/template.c +++ b/src/template.c @@ -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; diff --git a/src/unix_capture.c b/src/unix_capture.c index 281cbcb7..c6444d3e 100644 --- a/src/unix_capture.c +++ b/src/unix_capture.c @@ -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; diff --git a/src/update_image.c b/src/update_image.c index 6779a127..ef532805 100644 --- a/src/update_image.c +++ b/src/update_image.c @@ -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 @@ -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, ¶ms.progress); + ret = call_progress(params.progfunc, WIMLIB_PROGRESS_MSG_SCAN_BEGIN, + ¶ms.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, ¶ms.progress); + ret = call_progress(params.progfunc, WIMLIB_PROGRESS_MSG_SCAN_END, + ¶ms.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 diff --git a/src/util.c b/src/util.c index 1addc857..02017d03 100644 --- a/src/util.c +++ b/src/util.c @@ -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 */ diff --git a/src/wim.c b/src/wim.c index 960a9d50..ff4ac29b 100644 --- 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), diff --git a/src/win32_apply.c b/src/win32_apply.c index 5c861c2c..f741b447 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -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; diff --git a/src/win32_capture.c b/src/win32_capture.c index 4556ba91..0115ed0d 100644 --- a/src/win32_capture.c +++ b/src/win32_capture.c @@ -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); diff --git a/src/write.c b/src/write.c index ae175480..2b8347da 100644 --- a/src/write.c +++ b/src/write.c @@ -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(<e->write_streams_list); list_del(<e->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); } -- 2.43.0