X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fextract.c;h=0e5d4ec4c900c1aab13d23bdd4f905c51afb6b8e;hb=571e0b066fe7526690d68a5223d1025604c6e48b;hp=a39c1c02210815b503f9c29e81a1806eda1a114c;hpb=7b13472d9515dc87a15bd43a9822ac42217d3af9;p=wimlib diff --git a/src/extract.c b/src/extract.c index a39c1c02..0e5d4ec4 100644 --- a/src/extract.c +++ b/src/extract.c @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2012-2016 Eric Biggers + * Copyright (C) 2012-2018 Eric Biggers * * This file is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free @@ -63,6 +63,7 @@ #include "wimlib/unix_data.h" #include "wimlib/wim.h" #include "wimlib/win32.h" /* for realpath() equivalent */ +#include "wimlib/xattr.h" #include "wimlib/xml.h" #define WIMLIB_EXTRACT_FLAG_FROM_PIPE 0x80000000 @@ -71,6 +72,7 @@ /* Keep in sync with wimlib.h */ #define WIMLIB_EXTRACT_MASK_PUBLIC \ (WIMLIB_EXTRACT_FLAG_NTFS | \ + WIMLIB_EXTRACT_FLAG_RECOVER_DATA | \ WIMLIB_EXTRACT_FLAG_UNIX_DATA | \ WIMLIB_EXTRACT_FLAG_NO_ACLS | \ WIMLIB_EXTRACT_FLAG_STRICT_ACLS | \ @@ -309,7 +311,9 @@ read_blobs_from_pipe(struct apply_ctx *ctx, const struct read_blob_callbacks *cb && (blob->out_refcnt)) { wim_reshdr_to_desc_and_blob(&reshdr, ctx->wim, &rdesc, blob); - ret = read_blob_with_sha1(blob, cbs); + ret = read_blob_with_sha1(blob, cbs, + ctx->extract_flags & + WIMLIB_EXTRACT_FLAG_RECOVER_DATA); blob_unset_is_located_in_wim_resource(blob); if (ret) return ret; @@ -503,18 +507,39 @@ extract_from_tmpfile(const tchar *tmpfile_name, for (u32 i = 0; i < orig_blob->out_refcnt; i++) { tmpfile_blob.inline_blob_extraction_targets[0] = targets[i]; - ret = read_blob_with_cbs(&tmpfile_blob, cbs); + ret = read_blob_with_cbs(&tmpfile_blob, cbs, false); if (ret) return ret; } return 0; } +static void +warn_about_corrupted_file(struct wim_dentry *dentry, + const struct wim_inode_stream *stream) +{ + WARNING("Corruption in %s\"%"TS"\"! Extracting anyway since data recovery mode is enabled.", + stream_is_unnamed_data_stream(stream) ? "" : "alternate stream of ", + dentry_full_path(dentry)); +} + static int end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx) { struct apply_ctx *ctx = _ctx; + if ((ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RECOVER_DATA) && + !status && blob->corrupted) { + const struct blob_extraction_target *targets = + blob_extraction_targets(blob); + for (u32 i = 0; i < blob->out_refcnt; i++) { + struct wim_dentry *dentry = + inode_first_extraction_dentry(targets[i].inode); + + warn_about_corrupted_file(dentry, targets[i].stream); + } + } + if (unlikely(filedes_valid(&ctx->tmpfile_fd))) { filedes_close(&ctx->tmpfile_fd); if (!status) @@ -559,10 +584,15 @@ extract_blob_list(struct apply_ctx *ctx, const struct read_blob_callbacks *cbs) if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_FROM_PIPE) { return read_blobs_from_pipe(ctx, &wrapper_cbs); } else { + int flags = VERIFY_BLOB_HASHES; + + if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RECOVER_DATA) + flags |= RECOVER_DATA; + return read_blob_list(&ctx->blob_list, offsetof(struct blob_descriptor, extraction_list), - &wrapper_cbs, VERIFY_BLOB_HASHES); + &wrapper_cbs, flags); } } @@ -573,11 +603,13 @@ extract_blob_list(struct apply_ctx *ctx, const struct read_blob_callbacks *cbs) * unnamed data stream only. */ static int extract_dentry_to_stdout(struct wim_dentry *dentry, - const struct blob_table *blob_table) + const struct blob_table *blob_table, int extract_flags) { struct wim_inode *inode = dentry->d_inode; struct blob_descriptor *blob; struct filedes _stdout; + bool recover = (extract_flags & WIMLIB_EXTRACT_FLAG_RECOVER_DATA); + int ret; if (inode->i_attributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY | @@ -597,15 +629,23 @@ extract_dentry_to_stdout(struct wim_dentry *dentry, } filedes_init(&_stdout, STDOUT_FILENO); - return extract_blob_to_fd(blob, &_stdout); + ret = extract_blob_to_fd(blob, &_stdout, recover); + if (ret) + return ret; + if (recover && blob->corrupted) + warn_about_corrupted_file(dentry, + inode_get_unnamed_data_stream(inode)); + return 0; } static int extract_dentries_to_stdout(struct wim_dentry **dentries, size_t num_dentries, - const struct blob_table *blob_table) + const struct blob_table *blob_table, + int extract_flags) { for (size_t i = 0; i < num_dentries; i++) { - int ret = extract_dentry_to_stdout(dentries[i], blob_table); + int ret = extract_dentry_to_stdout(dentries[i], blob_table, + extract_flags); if (ret) return ret; } @@ -1224,6 +1264,8 @@ inode_tally_features(const struct wim_inode *inode, features->unix_data++; if (inode_has_object_id(inode)) features->object_ids++; + if (inode_has_xattrs(inode)) + features->xattrs++; } /* Tally features necessary to extract a dentry and the corresponding inode. */ @@ -1361,19 +1403,32 @@ do_feature_check(const struct wim_features *required_features, WARNING("Ignoring Windows NT security descriptors of %lu files", required_features->security_descriptors); - /* UNIX data. */ - if ((extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) && - required_features->unix_data && !supported_features->unix_data) + /* Standard UNIX metadata */ + if (required_features->unix_data && + (!supported_features->unix_data || + !(extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA))) { - ERROR("Extraction backend does not support UNIX data!"); - return WIMLIB_ERR_UNSUPPORTED; + if (extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) { + ERROR("Requested UNIX metadata extraction, but " + "extraction backend does not support it!"); + return WIMLIB_ERR_UNSUPPORTED; + } + WARNING("Ignoring UNIX metadata (uid/gid/mode/rdev) of %lu files%"TS, + required_features->unix_data, + (supported_features->unix_data ? + T("\n (use --unix-data mode to extract these)") : T(""))); } - if (required_features->unix_data && - !(extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA)) + /* Extended attributes */ + if (required_features->xattrs && + (!supported_features->xattrs || + (supported_features->unix_data && + !(extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA)))) { - WARNING("Ignoring UNIX metadata of %lu files", - required_features->unix_data); + WARNING("Ignoring extended attributes of %lu files%"TS, + required_features->xattrs, + (supported_features->xattrs ? + T("\n (use --unix-data mode to extract these)") : T(""))); } /* Object IDs. */ @@ -1430,7 +1485,8 @@ extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees, if (extract_flags & WIMLIB_EXTRACT_FLAG_TO_STDOUT) { ret = extract_dentries_to_stdout(trees, num_trees, - wim->blob_table); + wim->blob_table, + extract_flags); goto out; } @@ -1914,7 +1970,7 @@ wimlib_extract_pathlist(WIMStruct *wim, int image, const tchar *target, ret = read_path_list_file(path_list_file, &paths, &num_paths, &mem); if (ret) { ERROR("Failed to read path list file \"%"TS"\"", - path_list_file); + path_list_file ? path_list_file : T("")); return ret; }