+ struct ntfs_3g_apply_ctx *ctx = (struct ntfs_3g_apply_ctx *)_ctx;
+ ntfs_volume *vol;
+ struct wim_dentry *root;
+ int ret;
+
+ /* For NTFS-3g extraction mode we require that the dentries to extract
+ * form a single tree. */
+ root = list_first_entry(dentry_list, struct wim_dentry,
+ d_extraction_list_node);
+
+ /* Mount the NTFS volume. */
+ vol = ntfs_mount(ctx->common.target, 0);
+ if (!vol) {
+ ERROR_WITH_ERRNO("Failed to mount \"%s\" with NTFS-3g",
+ ctx->common.target);
+ return WIMLIB_ERR_NTFS_3G;
+ }
+ ctx->vol = vol;
+
+ /* Create all inodes and aliases, including short names, and set
+ * metadata (attributes, security descriptors, and timestamps). */
+
+ ret = start_file_structure_phase(&ctx->common,
+ ntfs_3g_count_dentries(dentry_list));
+ if (ret)
+ goto out_unmount;
+
+ ret = ntfs_3g_create_directories(root, dentry_list, ctx);
+ if (ret)
+ goto out_unmount;
+
+ ret = ntfs_3g_create_nondirectories(dentry_list, ctx);
+ if (ret)
+ goto out_unmount;
+
+ ret = end_file_structure_phase(&ctx->common);
+ if (ret)
+ goto out_unmount;
+
+ /* Extract blobs. */
+ struct read_blob_callbacks cbs = {
+ .begin_blob = ntfs_3g_begin_extract_blob,
+ .consume_chunk = ntfs_3g_extract_chunk,
+ .end_blob = ntfs_3g_end_extract_blob,
+ .ctx = ctx,
+ };
+ ret = extract_blob_list(&ctx->common, &cbs);
+
+ /* We do not need a final pass to set timestamps because libntfs-3g does
+ * not update timestamps automatically (exception:
+ * ntfs_set_ntfs_dos_name() does, but we handle this elsewhere). */
+
+out_unmount:
+ if (ntfs_umount(ctx->vol, FALSE) && !ret) {
+ ERROR_WITH_ERRNO("Failed to unmount \"%s\" with NTFS-3g",
+ ctx->common.target);
+ ret = WIMLIB_ERR_NTFS_3G;
+ }
+ return ret;