X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fntfs-3g_apply.c;h=dc61e4779cc2aa1fc05db15a47b1cd1461f9b91c;hp=9de5774bd256661278f28b270cb2ae4d5cfbf48c;hb=232a2222ad3aaff19dd9061846711a4811e7e909;hpb=aac0f095b5ed1273f91d87009f3b551eedcee085 diff --git a/src/ntfs-3g_apply.c b/src/ntfs-3g_apply.c index 9de5774b..dc61e477 100644 --- a/src/ntfs-3g_apply.c +++ b/src/ntfs-3g_apply.c @@ -280,7 +280,7 @@ ntfs_3g_restore_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, * UTF-16LE internally... which is annoying because we currently have * the UTF-16LE string but not the multibyte string. */ - ret = utf16le_get_tstr(dentry->short_name, dentry->short_name_nbytes, + ret = utf16le_get_tstr(dentry->d_short_name, dentry->d_short_name_nbytes, &dos_name, &dos_name_nbytes); if (ret) goto out_close; @@ -320,33 +320,61 @@ out_close: return ret; } +static int +ntfs_3g_restore_reparse_point(ntfs_inode *ni, const struct wim_inode *inode, + unsigned blob_size, struct ntfs_3g_apply_ctx *ctx) +{ + complete_reparse_point(&ctx->rpbuf, inode, blob_size); + + if (ntfs_set_ntfs_reparse_data(ni, (const char *)&ctx->rpbuf, + REPARSE_DATA_OFFSET + blob_size, 0)) + { + ERROR_WITH_ERRNO("Failed to set reparse data on \"%s\"", + dentry_full_path( + inode_first_extraction_dentry(inode))); + return WIMLIB_ERR_SET_REPARSE_DATA; + } + + return 0; +} + + /* - * Create empty named data streams for the specified file, if there are any. + * Create empty attributes (named data streams and potentially a reparse point) + * for the specified file, if there are any. * * Since these won't have blob descriptors, they won't show up in the call to * extract_blob_list(). Hence the need for the special case. */ static int -ntfs_3g_create_empty_named_data_streams(ntfs_inode *ni, - const struct wim_inode *inode, - const struct ntfs_3g_apply_ctx *ctx) +ntfs_3g_create_empty_attributes(ntfs_inode *ni, + const struct wim_inode *inode, + struct ntfs_3g_apply_ctx *ctx) { + for (unsigned i = 0; i < inode->i_num_streams; i++) { const struct wim_inode_stream *strm = &inode->i_streams[i]; + int ret; - if (!stream_is_named_data_stream(strm) || - stream_blob_resolved(strm) != NULL) + if (stream_blob_resolved(strm) != NULL) continue; - if (ntfs_attr_add(ni, AT_DATA, strm->stream_name, - utf16le_len_chars(strm->stream_name), - NULL, 0)) - { - ERROR_WITH_ERRNO("Failed to create named data stream " - "of \"%s\"", dentry_full_path( - inode_first_extraction_dentry(inode))); - return WIMLIB_ERR_NTFS_3G; + if (strm->stream_type == STREAM_TYPE_REPARSE_POINT) { + ret = ntfs_3g_restore_reparse_point(ni, inode, 0, ctx); + if (ret) + return ret; + } else if (stream_is_named_data_stream(strm)) { + if (ntfs_attr_add(ni, AT_DATA, strm->stream_name, + utf16le_len_chars(strm->stream_name), + NULL, 0)) + { + ERROR_WITH_ERRNO("Failed to create named data " + "stream of \"%s\"", + dentry_full_path( + inode_first_extraction_dentry(inode))); + return WIMLIB_ERR_NTFS_3G; + } } } return 0; @@ -451,7 +479,7 @@ ntfs_3g_create_dirs_recursive(ntfs_inode *dir_ni, struct wim_dentry *dir, if (!ret) ret = ntfs_3g_set_metadata(ni, child->d_inode, ctx); if (!ret) - ret = ntfs_3g_create_empty_named_data_streams(ni, child->d_inode, ctx); + ret = ntfs_3g_create_empty_attributes(ni, child->d_inode, ctx); if (!ret) ret = ntfs_3g_create_dirs_recursive(ni, child, ctx); @@ -563,7 +591,7 @@ fail: static int ntfs_3g_create_nondirectory(struct wim_inode *inode, - const struct ntfs_3g_apply_ctx *ctx) + struct ntfs_3g_apply_ctx *ctx) { struct wim_dentry *first_dentry; ntfs_inode *dir_ni; @@ -636,7 +664,7 @@ ntfs_3g_create_nondirectory(struct wim_inode *inode, if (ret) goto out_close_ni; - ret = ntfs_3g_create_empty_named_data_streams(ni, inode, ctx); + ret = ntfs_3g_create_empty_attributes(ni, inode, ctx); out_close_ni: /* Close the inode. */ @@ -760,28 +788,27 @@ ntfs_3g_cleanup_blob_extract(struct ntfs_3g_apply_ctx *ctx) static ntfs_inode * ntfs_3g_open_inode(struct wim_inode *inode, struct ntfs_3g_apply_ctx *ctx) { - ntfs_inode *ni = NULL; + ntfs_inode *ni; - if (inode->i_visited) { - for (u32 i = 0; i < ctx->num_open_inodes; i++) { + /* If the same blob is being extracted to multiple streams of the same + * inode, then we must only open the inode once. */ + if (unlikely(inode->i_num_streams > 1)) { + for (unsigned i = 0; i < ctx->num_open_inodes; i++) { if (ctx->open_inodes[i]->mft_no == inode->i_mft_no) { - ni = ctx->open_inodes[i]; - break; + return ctx->open_inodes[i]; } } } - if (!ni) { - ni = ntfs_inode_open(ctx->vol, inode->i_mft_no); - ctx->open_inodes[ctx->num_open_inodes++] = ni; - inode->i_visited = 1; - } - if (!ni) { + ni = ntfs_inode_open(ctx->vol, inode->i_mft_no); + if (unlikely(!ni)) { ERROR_WITH_ERRNO("Can't open \"%s\" in NTFS volume", dentry_full_path( inode_first_extraction_dentry(inode))); return NULL; } + + ctx->open_inodes[ctx->num_open_inodes++] = ni; return ni; } @@ -811,8 +838,6 @@ ntfs_3g_begin_extract_blob(struct blob_descriptor *blob, void *_ctx) out_cleanup: ntfs_3g_cleanup_blob_extract(ctx); out: - for (u32 i = 0; i < blob->out_refcnt; i++) - targets[i].inode->i_visited = 0; return ret; } @@ -848,22 +873,11 @@ ntfs_3g_end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx) } for (u32 i = 0; i < ctx->num_reparse_inodes; i++) { - struct wim_inode *inode = ctx->wim_reparse_inodes[i]; - - complete_reparse_point(&ctx->rpbuf, inode, blob->size); - - if (ntfs_set_ntfs_reparse_data(ctx->ntfs_reparse_inodes[i], - (const char *)&ctx->rpbuf, - REPARSE_DATA_OFFSET + blob->size, - 0)) - { - ERROR_WITH_ERRNO("Failed to set reparse " - "data on \"%s\"", - dentry_full_path( - inode_first_extraction_dentry(inode))); - ret = WIMLIB_ERR_SET_REPARSE_DATA; + ret = ntfs_3g_restore_reparse_point(ctx->ntfs_reparse_inodes[i], + ctx->wim_reparse_inodes[i], + blob->size, ctx); + if (ret) goto out; - } } ret = 0; out: