*/
/*
- * 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
#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
/* 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 | \
&& (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;
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)
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);
}
}
* 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 |
}
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;
}
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. */
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. */
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;
}
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("<stdin>"));
return ret;
}