From: Eric Biggers Date: Tue, 29 Jul 2014 02:12:25 +0000 (-0500) Subject: Add WIMLIB_PROGRESS_MSG_EXTRACT_{FILE_STRUCTURE,METADATA} X-Git-Tag: v1.7.1~21 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=156bb1de48ff4a594f6a2a2f86e86213d65a6b08;ds=sidebyside Add WIMLIB_PROGRESS_MSG_EXTRACT_{FILE_STRUCTURE,METADATA} These are essentially updated versions of WIMLIB_PROGRESS_MSG_EXTRACT_{DIR_STRUCTURE,TIMESTAMPS} which were removed in v1.7.0. The new versions will file periodically, so they can be used as cancellation points where the library user provides WIMLIB_PROGRESS_STATUS_ABORT. --- diff --git a/NEWS b/NEWS index 982089e4..d9296240 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,10 @@ Version 1.7.1-BETA: error messages to be sent to, rather than the default of standard error. + New progress messages: + WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE, + WIMLIB_PROGRESS_MSG_EXTRACT_METADATA. + New function: wimlib_verify_wim(). Version 1.7.0: diff --git a/include/wimlib.h b/include/wimlib.h index db8d5d52..f1734fc3 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -504,6 +504,12 @@ enum wimlib_progress_msg { * single extraction operation for optimization purposes. */ WIMLIB_PROGRESS_MSG_EXTRACT_TREE_BEGIN = 1, + /** This message may be sent periodically (not for every file) while + * files or directories are being created, prior to data stream + * extraction. @p info will point to ::wimlib_progress_info.extract. + */ + WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE = 3, + /** File data is currently being extracted. @p info will point to * ::wimlib_progress_info.extract. This is the main message to track * the progress of an extraction operation. */ @@ -513,6 +519,12 @@ enum wimlib_progress_msg { * @p info will point to ::wimlib_progress_info.extract. */ WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN = 5, + /** This message may be sent periodically (not for every file) while + * file and directory metadata is being applied, following data stream + * extraction. @p info will point to ::wimlib_progress_info.extract. + */ + WIMLIB_PROGRESS_MSG_EXTRACT_METADATA = 6, + /** Confirms that the image has been successfully extracted. @p info * will point to ::wimlib_progress_info.extract. This is paired with * ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN. */ @@ -850,7 +862,9 @@ union wimlib_progress_info { * ::WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN, * ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN, * ::WIMLIB_PROGRESS_MSG_EXTRACT_TREE_BEGIN, + * ::WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE, * ::WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS, + * ::WIMLIB_PROGRESS_MSG_EXTRACT_METADATA, * ::WIMLIB_PROGRESS_MSG_EXTRACT_TREE_END, and * ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END. * @@ -2657,7 +2671,9 @@ wimlib_export_image(WIMStruct *src_wim, int src_image, * * 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 + * zero or more ::WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE messages, then zero + * or more ::WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS messages, then zero or more + * ::WIMLIB_PROGRESS_MSG_EXTRACT_METADATA messages, then * ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END. */ extern int diff --git a/include/wimlib/apply.h b/include/wimlib/apply.h index 2f3b1cb9..8a1bf87e 100644 --- a/include/wimlib/apply.h +++ b/include/wimlib/apply.h @@ -1,6 +1,7 @@ #ifndef _WIMLIB_APPLY_H #define _WIMLIB_APPLY_H +#include "wimlib/compiler.h" #include "wimlib/file_io.h" #include "wimlib/list.h" #include "wimlib/progress.h" @@ -70,6 +71,7 @@ struct apply_ctx { u64 cur_stream_offset; struct filedes tmpfile_fd; tchar *tmpfile_name; + unsigned int count_until_file_progress; }; /* Maximum number of UNIX file descriptors, NTFS attributes, or Windows file @@ -83,6 +85,39 @@ extract_progress(struct apply_ctx *ctx, enum wimlib_progress_msg msg) return call_progress(ctx->progfunc, msg, &ctx->progress, ctx->progctx); } +extern int +do_file_extract_progress(struct apply_ctx *ctx, enum wimlib_progress_msg msg); + +static inline int +maybe_do_file_progress(struct apply_ctx *ctx, enum wimlib_progress_msg msg) +{ + if (unlikely(!--ctx->count_until_file_progress)) + return do_file_extract_progress(ctx, msg); + return 0; +} + +/* Call this to reset the counter for report_file_created() and + * report_file_metadata_applied(). */ +static inline void +reset_file_progress(struct apply_ctx *ctx) +{ + ctx->count_until_file_progress = 1; +} + +/* Report that a file was created, prior to stream extraction. */ +static inline int +report_file_created(struct apply_ctx *ctx) +{ + return maybe_do_file_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE); +} + +/* Report that file metadata was applied, after stream extraction. */ +static inline int +report_file_metadata_applied(struct apply_ctx *ctx) +{ + return maybe_do_file_progress(ctx, WIMLIB_PROGRESS_MSG_EXTRACT_METADATA); +} + /* 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/src/extract.c b/src/extract.c index eaee41dd..e8fd7a69 100644 --- a/src/extract.c +++ b/src/extract.c @@ -90,6 +90,15 @@ WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE | \ WIMLIB_EXTRACT_FLAG_WIMBOOT) +/* Send WIMLIB_PROGRESS_MSG_EXTRACT_FILE_STRUCTURE or + * WIMLIB_PROGRESS_MSG_EXTRACT_METADATA. */ +int +do_file_extract_progress(struct apply_ctx *ctx, enum wimlib_progress_msg msg) +{ + ctx->count_until_file_progress = 512; /* Arbitrary value to limit calls */ + return extract_progress(ctx, msg); +} + /* Check whether the extraction of a dentry should be skipped completely. */ static bool dentry_is_supported(struct wim_dentry *dentry, diff --git a/src/ntfs-3g_apply.c b/src/ntfs-3g_apply.c index d1cebb9c..5f0e7c7e 100644 --- a/src/ntfs-3g_apply.c +++ b/src/ntfs-3g_apply.c @@ -425,7 +425,7 @@ ntfs_3g_set_metadata(ntfs_inode *ni, const struct wim_inode *inode, * the NTFS inode @dir_ni. */ static int ntfs_3g_create_dirs_recursive(ntfs_inode *dir_ni, struct wim_dentry *dir, - const struct ntfs_3g_apply_ctx *ctx) + struct ntfs_3g_apply_ctx *ctx) { struct wim_dentry *child; @@ -448,7 +448,9 @@ ntfs_3g_create_dirs_recursive(ntfs_inode *dir_ni, struct wim_dentry *dir, child->d_inode->i_mft_no = ni->mft_no; - ret = ntfs_3g_set_metadata(ni, child->d_inode, ctx); + ret = report_file_created(&ctx->common); + if (!ret) + ret = ntfs_3g_set_metadata(ni, child->d_inode, ctx); if (!ret) ret = ntfs_3g_create_any_empty_ads(ni, child->d_inode, ctx); if (!ret) @@ -470,7 +472,7 @@ ntfs_3g_create_dirs_recursive(ntfs_inode *dir_ni, struct wim_dentry *dir, static int ntfs_3g_create_directories(struct wim_dentry *root, struct list_head *dentry_list, - const struct ntfs_3g_apply_ctx *ctx) + struct ntfs_3g_apply_ctx *ctx) { ntfs_inode *root_ni; int ret; @@ -504,6 +506,9 @@ ntfs_3g_create_directories(struct wim_dentry *root, ret = ntfs_3g_restore_dos_name(NULL, NULL, dentry, ctx->vol); if (ret) return ret; + ret = report_file_created(&ctx->common); + if (ret) + return ret; } return 0; } @@ -660,7 +665,7 @@ out_close_ni: * Directories must have already been created. */ static int ntfs_3g_create_nondirectories(struct list_head *dentry_list, - const struct ntfs_3g_apply_ctx *ctx) + struct ntfs_3g_apply_ctx *ctx) { struct wim_dentry *dentry; struct wim_inode *inode; @@ -675,6 +680,9 @@ ntfs_3g_create_nondirectories(struct list_head *dentry_list, ret = ntfs_3g_create_nondirectory(inode, ctx); if (ret) return ret; + ret = report_file_created(&ctx->common); + if (ret) + return ret; } return 0; } @@ -908,6 +916,8 @@ ntfs_3g_extract(struct list_head *dentry_list, struct apply_ctx *_ctx) /* Create all inodes and aliases, including short names, and set * metadata (attributes, security descriptors, and timestamps). */ + reset_file_progress(&ctx->common); + ret = ntfs_3g_create_directories(root, dentry_list, ctx); if (ret) goto out_unmount; diff --git a/src/unix_apply.c b/src/unix_apply.c index a683b4da..7ed14225 100644 --- a/src/unix_apply.c +++ b/src/unix_apply.c @@ -372,7 +372,8 @@ unix_create_if_directory(const struct wim_dentry *dentry, ERROR_WITH_ERRNO("Can't create directory \"%s\"", path); return WIMLIB_ERR_MKDIR; } - return 0; + + return report_file_created(&ctx->common); } /* If @dentry represents an empty regular file or a special file, create it, set @@ -444,7 +445,11 @@ unix_extract_if_empty_file(const struct wim_dentry *dentry, if (ret) return ret; - return unix_create_hardlinks(inode, dentry, path, ctx); + ret = unix_create_hardlinks(inode, dentry, path, ctx); + if (ret) + return ret; + + return report_file_created(&ctx->common); } static int @@ -680,6 +685,9 @@ unix_set_dir_metadata(struct list_head *dentry_list, struct unix_apply_ctx *ctx) ret = unix_set_metadata(-1, dentry->d_inode, NULL, ctx); if (ret) return ret; + ret = report_file_metadata_applied(&ctx->common); + if (ret) + return ret; } } return 0; @@ -712,6 +720,7 @@ unix_extract(struct list_head *dentry_list, struct apply_ctx *_ctx) * because we can't extract any other files until their directories * exist. Empty files are needed because they don't have * representatives in the stream list. */ + reset_file_progress(&ctx->common); ret = unix_create_dirs_and_empty_files(dentry_list, ctx); if (ret) goto out; @@ -742,8 +751,10 @@ unix_extract(struct list_head *dentry_list, struct apply_ctx *_ctx) if (ret) goto out; + /* Set directory metadata. We do this last so that we get the right * directory timestamps. */ + reset_file_progress(&ctx->common); ret = unix_set_dir_metadata(dentry_list, ctx); if (ret) goto out; diff --git a/src/win32_apply.c b/src/win32_apply.c index 0da07937..c0487c62 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -974,6 +974,10 @@ create_directories(struct list_head *dentry_list, ret = create_any_empty_ads(dentry, ctx); if (ret) return ret; + + ret = report_file_created(&ctx->common); + if (ret) + return ret; } return 0; } @@ -1221,6 +1225,9 @@ create_nondirectories(struct list_head *dentry_list, struct win32_apply_ctx *ctx ret = create_nondirectory(inode, ctx); if (ret) return ret; + ret = report_file_created(&ctx->common); + if (ret) + return ret; } return 0; } @@ -1984,6 +1991,9 @@ apply_metadata(struct list_head *dentry_list, struct win32_apply_ctx *ctx) ret = apply_metadata_to_file(dentry, ctx); if (ret) return ret; + ret = report_file_metadata_applied(&ctx->common); + if (ret) + return ret; } return 0; } @@ -2031,6 +2041,8 @@ win32_extract(struct list_head *dentry_list, struct apply_ctx *_ctx) goto out; } + reset_file_progress(&ctx->common); + ret = create_directories(dentry_list, ctx); if (ret) goto out; @@ -2051,6 +2063,8 @@ win32_extract(struct list_head *dentry_list, struct apply_ctx *_ctx) if (ret) goto out; + reset_file_progress(&ctx->common); + ret = apply_metadata(dentry_list, ctx); if (ret) goto out;