+ if (progress_func) {
+ progress_func(*wim_source_path ? WIMLIB_PROGRESS_MSG_EXTRACT_TREE_BEGIN :
+ WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN,
+ &args.progress);
+ }
+
+ /* If a sequential extraction was specified, sort the streams to be
+ * extracted by their position in the WIM file, so that the WIM file can
+ * be read sequentially. */
+ if (extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL) {
+ ret = sort_stream_list_by_wim_position(&stream_list);
+ if (ret != 0) {
+ WARNING("Falling back to non-sequential extraction");
+ extract_flags &= ~WIMLIB_EXTRACT_FLAG_SEQUENTIAL;
+ }
+ }
+
+ if (progress_func) {
+ progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DIR_STRUCTURE_BEGIN,
+ &args.progress);
+ }
+
+ /* Make the directory structure and extract empty files */
+ args.extract_flags |= WIMLIB_EXTRACT_FLAG_NO_STREAMS;
+ args.apply_dentry = ops->apply_dentry;
+ ret = for_dentry_in_tree(root, maybe_apply_dentry, &args);
+ args.extract_flags &= ~WIMLIB_EXTRACT_FLAG_NO_STREAMS;
+ if (ret)
+ goto out_dentry_reset_needs_extraction;
+
+ if (progress_func) {
+ progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DIR_STRUCTURE_END,
+ &args.progress);
+ }
+
+ if (extract_flags & WIMLIB_EXTRACT_FLAG_RPFIX) {
+ args.target_realpath = realpath(target, NULL);
+ if (!args.target_realpath) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_dentry_reset_needs_extraction;
+ }
+ args.target_realpath_len = tstrlen(args.target_realpath);
+ }
+
+ /* Extract non-empty files */
+ ret = apply_stream_list(&stream_list, &args, ops, progress_func);
+ if (ret)
+ goto out_free_target_realpath;
+
+ if (progress_func) {
+ progress_func(WIMLIB_PROGRESS_MSG_APPLY_TIMESTAMPS,
+ &args.progress);
+ }
+
+ /* Apply timestamps */
+ ret = for_dentry_in_tree_depth(root,
+ ops->apply_dentry_timestamps, &args);
+ if (ret)
+ goto out_free_target_realpath;
+
+ if (progress_func) {
+ progress_func(*wim_source_path ? WIMLIB_PROGRESS_MSG_EXTRACT_TREE_END :
+ WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END,
+ &args.progress);
+ }
+out_free_target_realpath:
+ FREE(args.target_realpath);
+out_dentry_reset_needs_extraction:
+ for_dentry_in_tree(root, dentry_reset_needs_extraction, NULL);
+out_ntfs_umount: