From: Eric Biggers Date: Sat, 17 Aug 2013 17:38:54 +0000 (-0500) Subject: extract.c: Omit encrypted files when unsupported X-Git-Tag: v1.5.0~59 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=04dcfc0042a286557e6a0cf358793538d6500379 extract.c: Omit encrypted files when unsupported --- diff --git a/include/wimlib/apply.h b/include/wimlib/apply.h index 8a556263..97497d7b 100644 --- a/include/wimlib/apply.h +++ b/include/wimlib/apply.h @@ -175,6 +175,7 @@ struct wim_features { unsigned long system_files; unsigned long compressed_files; unsigned long encrypted_files; + unsigned long encrypted_directories; unsigned long not_context_indexed_files; unsigned long sparse_files; unsigned long named_data_streams; @@ -198,6 +199,7 @@ struct apply_ctx { struct wim_dentry *extract_root; const struct apply_operations *ops; struct wim_features supported_features; + u32 supported_attributes_mask; struct list_head stream_list; tchar *realtarget; size_t realtarget_nchars; diff --git a/src/extract.c b/src/extract.c index 88b277ac..b7b3399b 100644 --- a/src/extract.c +++ b/src/extract.c @@ -646,12 +646,25 @@ extract_file_attributes(const tchar *path, struct apply_ctx *ctx, { int ret; - if (ctx->ops->set_file_attributes) { - if (dentry == ctx->extract_root && ctx->root_dentry_is_special) - return 0; - ret = ctx->ops->set_file_attributes(path, - dentry->d_inode->i_attributes, - ctx); + if (ctx->ops->set_file_attributes && + !(dentry == ctx->extract_root && ctx->root_dentry_is_special)) { + u32 attributes = dentry->d_inode->i_attributes; + + /* Clear unsupported attributes. */ + attributes &= ctx->supported_attributes_mask; + + if ((attributes & FILE_ATTRIBUTE_DIRECTORY && + !ctx->supported_features.encrypted_directories) || + (!(attributes & FILE_ATTRIBUTE_DIRECTORY) && + !ctx->supported_features.encrypted_files)) + { + attributes &= ~FILE_ATTRIBUTE_ENCRYPTED; + } + + if (attributes == 0) + attributes = FILE_ATTRIBUTE_NORMAL; + + ret = ctx->ops->set_file_attributes(path, attributes, ctx); if (ret) { ERROR_WITH_ERRNO("Failed to set attributes on " "\"%"TS"\"", path); @@ -804,12 +817,15 @@ dentry_is_supported(struct wim_dentry *dentry, struct wim_inode *inode = dentry->d_inode; if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (supported_features->reparse_points) - return true; - if (supported_features->symlink_reparse_points && - inode_is_symlink(inode)) - return true; - return false; + return supported_features->reparse_points || + (inode_is_symlink(inode) && + supported_features->symlink_reparse_points); + } + if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) { + if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) + return supported_features->encrypted_directories != 0; + else + return supported_features->encrypted_files != 0; } return true; } @@ -1717,8 +1733,12 @@ dentry_tally_features(struct wim_dentry *dentry, void *_features) features->system_files++; if (inode->i_attributes & FILE_ATTRIBUTE_COMPRESSED) features->compressed_files++; - if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) - features->encrypted_files++; + if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) { + if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) + features->encrypted_directories++; + else + features->encrypted_files++; + } if (inode->i_attributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) features->not_context_indexed_files++; if (inode->i_attributes & FILE_ATTRIBUTE_SPARSE_FILE) @@ -1760,6 +1780,35 @@ dentry_tree_get_features(struct wim_dentry *root, struct wim_features *features) for_dentry_in_tree(root, dentry_clear_inode_visited, NULL); } +static u32 +compute_supported_attributes_mask(const struct wim_features *supported_features) +{ + u32 mask = ~(u32)0; + + if (!supported_features->archive_files) + mask &= ~FILE_ATTRIBUTE_ARCHIVE; + + if (!supported_features->hidden_files) + mask &= ~FILE_ATTRIBUTE_HIDDEN; + + if (!supported_features->system_files) + mask &= ~FILE_ATTRIBUTE_SYSTEM; + + if (!supported_features->not_context_indexed_files) + mask &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; + + if (!supported_features->compressed_files) + mask &= ~FILE_ATTRIBUTE_COMPRESSED; + + if (!supported_features->sparse_files) + mask &= ~FILE_ATTRIBUTE_SPARSE_FILE; + + if (!supported_features->reparse_points) + mask &= ~FILE_ATTRIBUTE_REPARSE_POINT; + + return mask; +} + static int do_feature_check(const struct wim_features *required_features, const struct wim_features *supported_features, @@ -1818,10 +1867,20 @@ do_feature_check(const struct wim_features *required_features, WARNING( "%lu files in %"TS" are marked as being encrypted,\n" " but encryption is not supported in %"TS". These files\n" -" will be extracted as raw encrypted data instead.", +" will not be extracted.", required_features->encrypted_files, loc, mode); } + if (required_features->encrypted_directories && + !supported_features->encrypted_directories) + { + WARNING( + "%lu directories in %"TS" are marked as being encrypted,\n" +" but encryption is not supported in %"TS".\n" +" These directories will be extracted as unencrypted.", + required_features->encrypted_directories, loc, mode); + } + if (required_features->not_context_indexed_files && !supported_features->not_context_indexed_files) { @@ -2077,6 +2136,9 @@ extract_tree(WIMStruct *wim, const tchar *wim_source_path, const tchar *target, if (ret) goto out_finish_or_abort_extract; + ctx.supported_attributes_mask = + compute_supported_attributes_mask(&ctx.supported_features); + /* Figure out whether the root dentry is being extracted to the root of * a volume and therefore needs to be treated "specially", for example * not being explicitly created and not having attributes set. */ diff --git a/src/win32_apply.c b/src/win32_apply.c index 00ace99e..6a447074 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -49,6 +49,7 @@ win32_start_extract(const wchar_t *path, struct apply_ctx *ctx) ctx->supported_features.system_files = 1; ctx->supported_features.compressed_files = !!(vol_flags & FILE_FILE_COMPRESSION); ctx->supported_features.encrypted_files = !!(vol_flags & FILE_SUPPORTS_ENCRYPTION); + ctx->supported_features.encrypted_directories = !!(vol_flags & FILE_SUPPORTS_ENCRYPTION); ctx->supported_features.not_context_indexed_files = 1; ctx->supported_features.sparse_files = !!(vol_flags & FILE_SUPPORTS_SPARSE_FILES); ctx->supported_features.named_data_streams = !!(vol_flags & FILE_NAMED_STREAMS);