* described by @blob. */
int
read_winnt_stream_prefix(const struct blob_descriptor *blob, u64 size,
- consume_data_callback_t cb, void *cb_ctx)
+ const struct read_blob_callbacks *cbs)
{
const wchar_t *path;
HANDLE h;
bytes_read = iosb.Information;
bytes_remaining -= bytes_read;
- ret = (*cb)(buf, bytes_read, cb_ctx);
+ ret = call_consume_chunk(buf, bytes_read, cbs);
if (ret)
break;
}
}
struct win32_encrypted_read_ctx {
- consume_data_callback_t read_prefix_cb;
- void *read_prefix_ctx;
+ const struct read_blob_callbacks *cbs;
int wimlib_err_code;
u64 bytes_remaining;
};
if (bytes_to_consume == 0)
return ERROR_SUCCESS;
- ret = (*ctx->read_prefix_cb)(data, bytes_to_consume, ctx->read_prefix_ctx);
+ ret = call_consume_chunk(data, bytes_to_consume, ctx->cbs);
if (ret) {
ctx->wimlib_err_code = ret;
/* It doesn't matter what error code is returned here, as long
int
read_win32_encrypted_file_prefix(const struct blob_descriptor *blob,
u64 size,
- consume_data_callback_t cb, void *cb_ctx)
+ const struct read_blob_callbacks *cbs)
{
struct win32_encrypted_read_ctx export_ctx;
DWORD err;
if (blob->file_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
flags |= CREATE_FOR_DIR;
- export_ctx.read_prefix_cb = cb;
- export_ctx.read_prefix_ctx = cb_ctx;
+ export_ctx.cbs = cbs;
export_ctx.wimlib_err_code = 0;
export_ctx.bytes_remaining = size;
/*
* Load the short name of a file into a WIM dentry.
*/
-static NTSTATUS
+static noinline_for_stack NTSTATUS
winnt_get_short_name(HANDLE h, struct wim_dentry *dentry)
{
/* It's not any harder to just make the NtQueryInformationFile() system
FileAlternateNameInformation);
info = (const FILE_NAME_INFORMATION *)buf;
if (NT_SUCCESS(status) && info->FileNameLength != 0) {
- dentry->short_name = utf16le_dupz(info->FileName,
- info->FileNameLength);
- if (!dentry->short_name)
+ dentry->d_short_name = utf16le_dupz(info->FileName,
+ info->FileNameLength);
+ if (!dentry->d_short_name)
return STATUS_NO_MEMORY;
- dentry->short_name_nbytes = info->FileNameLength;
+ dentry->d_short_name_nbytes = info->FileNameLength;
}
return status;
}
* Load the security descriptor of a file into the corresponding inode and the
* WIM image's security descriptor set.
*/
-static NTSTATUS
+static noinline_for_stack NTSTATUS
winnt_get_security_descriptor(HANDLE h, struct wim_inode *inode,
struct wim_sd_set *sd_set,
struct winnt_scan_stats *stats, int add_flags)
{
const FILE_NAMES_INFORMATION *info = buf;
for (;;) {
- if (!(info->FileNameLength == 2 && info->FileName[0] == L'.') &&
- !(info->FileNameLength == 4 && info->FileName[0] == L'.' &&
- info->FileName[1] == L'.'))
+ if (!should_ignore_filename(info->FileName,
+ info->FileNameLength / 2))
{
wchar_t *p;
wchar_t *filename;
if (ret)
goto out_free_buf;
- if (child)
- dentry_add_child(parent, child);
+ attach_scanned_tree(parent, child, params->blob_table);
}
if (info->NextEntryOffset == 0)
break;
}
/* Reparse point fixup status code */
-enum rp_status {
- /* Reparse point will be captured literally (no fixup) */
- RP_NOT_FIXED = -1,
-
- /* Reparse point will be captured with fixup */
- RP_FIXED = -2,
-};
+#define RP_FIXED (-1)
static bool
file_has_ino_and_dev(HANDLE h, u64 ino, u64 dev)
}
/*
- * Given an (expected) NT namespace symbolic link or junction target @target of
- * length @target_nbytes, determine if a prefix of the target points to a file
- * identified by @capture_root_ino and @capture_root_dev.
- *
- * If yes, return a pointer to the portion of the link following this prefix.
- *
- * If no, return NULL.
- *
- * If the link target does not appear to be a valid NT namespace path, return
- * @target itself.
+ * This is the Windows equivalent of unix_relativize_link_target(); see there
+ * for general details. This version works with an "absolute" Windows link
+ * target, specified from the root of the Windows kernel object namespace. Note
+ * that we have to open directories with a trailing slash when present because
+ * \??\E: opens the E: device itself and not the filesystem root directory.
*/
static const wchar_t *
-winnt_get_root_relative_target(const wchar_t *target, size_t target_nbytes,
- u64 capture_root_ino, u64 capture_root_dev)
+winnt_relativize_link_target(const wchar_t *target, size_t target_nbytes,
+ u64 ino, u64 dev)
{
UNICODE_STRING name;
OBJECT_ATTRIBUTES attr;
name.Buffer = (wchar_t *)p;
name.Length = 0;
- if (file_has_ino_and_dev(h, capture_root_ino,
- capture_root_dev))
+ if (file_has_ino_and_dev(h, ino, dev))
goto out_close_root_dir;
}
} while (p != target_end);
- p = NULL;
+ p = target;
out_close_root_dir:
if (attr.RootDirectory)
(*func_NtClose)(attr.RootDirectory);
+ while (p > target && *(p - 1) == L'\\')
+ p--;
return p;
}
static int
winnt_rpfix_progress(struct capture_params *params, const wchar_t *path,
- const struct reparse_data *rpdata, int scan_status)
+ const struct link_reparse_point *link, int scan_status)
{
- size_t print_name_nchars = rpdata->print_name_nbytes / sizeof(wchar_t);
+ size_t print_name_nchars = link->print_name_nbytes / sizeof(wchar_t);
wchar_t print_name0[print_name_nchars + 1];
- wmemcpy(print_name0, rpdata->print_name, print_name_nchars);
+ wmemcpy(print_name0, link->print_name, print_name_nchars);
print_name0[print_name_nchars] = L'\0';
params->progress.scan.cur_path = printable_path(path);
}
static int
-winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
- u64 capture_root_ino, u64 capture_root_dev,
+winnt_try_rpfix(struct reparse_buffer_disk *rpbuf, u16 *rpbuflen_p,
const wchar_t *path, struct capture_params *params)
{
- struct reparse_data rpdata;
+ struct link_reparse_point link;
const wchar_t *rel_target;
int ret;
- if (parse_reparse_data(rpbuf, *rpbuflen_p, &rpdata)) {
- /* Couldn't even understand the reparse data. Don't try the
- * fixup. */
- return RP_NOT_FIXED;
+ if (parse_link_reparse_point(rpbuf, *rpbuflen_p, &link)) {
+ /* Couldn't understand the reparse data; don't do the fixup. */
+ return 0;
}
/*
* SYMBOLIC_LINK_RELATIVE. We will use this information, although this
* may not always do what the user expects, since drive-relative
* symbolic links such as "\Users\Public" have SYMBOLIC_LINK_RELATIVE
- * set, in addition to truely relative symbolic links such as "Users" or
+ * set, in addition to truly relative symbolic links such as "Users" or
* "Users\Public". However, WIMGAPI (as of Windows 8.1) has this same
* behavior.
*
* - \??\Volume{c47cb07c-946e-4155-b8f7-052e9cec7628}\Users\Public
* - \DosDevices\Volume{c47cb07c-946e-4155-b8f7-052e9cec7628}\Users\Public
*/
- if (rpdata.rptag == WIM_IO_REPARSE_TAG_SYMLINK &&
- (rpdata.rpflags & SYMBOLIC_LINK_RELATIVE))
- return RP_NOT_FIXED;
-
- rel_target = winnt_get_root_relative_target(rpdata.substitute_name,
- rpdata.substitute_name_nbytes,
- capture_root_ino,
- capture_root_dev);
- if (!rel_target) {
- /* Target points outside of the tree being captured. Don't
- * adjust it. */
- ret = winnt_rpfix_progress(params, path, &rpdata,
- WIMLIB_SCAN_DENTRY_NOT_FIXED_SYMLINK);
- if (ret)
- return ret;
- return RP_NOT_FIXED;
- }
+ if (link_is_relative_symlink(&link))
+ return 0;
- if (rel_target == rpdata.substitute_name) {
- /* Weird target --- keep the reparse point and don't mess with
- * it. */
- return RP_NOT_FIXED;
+ rel_target = winnt_relativize_link_target(link.substitute_name,
+ link.substitute_name_nbytes,
+ params->capture_root_ino,
+ params->capture_root_dev);
+
+ if (rel_target == link.substitute_name) {
+ /* Target points outside of the tree being captured or had an
+ * unrecognized path format. Don't adjust it. */
+ return winnt_rpfix_progress(params, path, &link,
+ WIMLIB_SCAN_DENTRY_NOT_FIXED_SYMLINK);
}
/* We have an absolute target pointing within the directory being
*
* We will cut off the prefix before this part (which is the path to the
* directory being captured) and add a dummy prefix. Since the process
- * will need to be reversed when applying the image, it shouldn't matter
+ * will need to be reversed when applying the image, it doesn't matter
* what exactly the prefix is, as long as it looks like an absolute
- * path.
- */
+ * path. */
- {
- size_t rel_target_nbytes =
- rpdata.substitute_name_nbytes - ((const u8 *)rel_target -
- (const u8 *)rpdata.substitute_name);
- size_t rel_target_nchars = rel_target_nbytes / sizeof(wchar_t);
+ static const wchar_t prefix[6] = L"\\??\\X:";
+ static const size_t num_unprintable_chars = 4;
- wchar_t tmp[rel_target_nchars + 7];
+ size_t rel_target_nbytes =
+ link.substitute_name_nbytes - ((const u8 *)rel_target -
+ (const u8 *)link.substitute_name);
- wmemcpy(tmp, L"\\??\\X:\\", 7);
- wmemcpy(tmp + 7, rel_target, rel_target_nchars);
+ wchar_t tmp[(sizeof(prefix) + rel_target_nbytes) / sizeof(wchar_t)];
- rpdata.substitute_name = tmp;
- rpdata.substitute_name_nbytes = rel_target_nbytes + (7 * sizeof(wchar_t));
- rpdata.print_name = tmp + 4;
- rpdata.print_name_nbytes = rel_target_nbytes + (3 * sizeof(wchar_t));
+ memcpy(tmp, prefix, sizeof(prefix));
+ memcpy(tmp + ARRAY_LEN(prefix), rel_target, rel_target_nbytes);
- if (make_reparse_buffer(&rpdata, rpbuf, rpbuflen_p))
- return RP_NOT_FIXED;
- }
- ret = winnt_rpfix_progress(params, path, &rpdata,
+ link.substitute_name = tmp;
+ link.substitute_name_nbytes = sizeof(tmp);
+
+ link.print_name = link.substitute_name + num_unprintable_chars;
+ link.print_name_nbytes = link.substitute_name_nbytes -
+ (num_unprintable_chars * sizeof(wchar_t));
+
+ if (make_link_reparse_point(&link, rpbuf, rpbuflen_p))
+ return 0;
+
+ ret = winnt_rpfix_progress(params, path, &link,
WIMLIB_SCAN_DENTRY_FIXED_SYMLINK);
if (ret)
return ret;
return RP_FIXED;
}
-/*
- * Loads the reparse point data from a reparse point into memory, optionally
- * fixing the targets of absolute symbolic links and junction points to be
- * relative to the root of capture.
- *
- * @h:
- * Open handle to the reparse point file.
- * @path:
- * Path to the reparse point file.
- * @params:
- * Capture parameters. add_flags, capture_root_ino, capture_root_dev,
- * progfunc, progctx, and progress are used.
- * @rpbuf:
- * Buffer of length at least REPARSE_POINT_MAX_SIZE bytes into which the
- * reparse point buffer will be loaded.
- * @rpbuflen_ret:
- * On success, the length of the reparse point buffer in bytes is written
- * to this location.
- *
- * On success, returns a negative `enum rp_status' value.
- * On failure, returns a positive error code.
- */
-static int
-winnt_get_reparse_data(HANDLE h, const wchar_t *path,
- struct capture_params *params,
- u8 *rpbuf, u16 *rpbuflen_ret)
+/* Load the reparse data of a file into the corresponding WIM inode. If the
+ * reparse point is a symbolic link or junction with an absolute target and
+ * RPFIX mode is enabled, then also rewrite its target to be relative to the
+ * capture root. */
+static noinline_for_stack int
+winnt_load_reparse_data(HANDLE h, struct wim_inode *inode,
+ const wchar_t *full_path, struct capture_params *params)
{
+ struct reparse_buffer_disk rpbuf;
DWORD bytes_returned;
- u32 reparse_tag;
- int ret;
u16 rpbuflen;
+ int ret;
+
+ if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
+ /* See comment above assign_stream_types_encrypted() */
+ WARNING("Ignoring reparse data of encrypted file \"%ls\"",
+ printable_path(full_path));
+ return 0;
+ }
if (!DeviceIoControl(h, FSCTL_GET_REPARSE_POINT,
- NULL, 0, rpbuf, REPARSE_POINT_MAX_SIZE,
+ NULL, 0, &rpbuf, REPARSE_POINT_MAX_SIZE,
&bytes_returned, NULL))
{
- win32_error(GetLastError(), L"\"%ls\": Can't get reparse data",
- printable_path(path));
- return WIMLIB_ERR_READ;
+ win32_error(GetLastError(), L"\"%ls\": Can't get reparse point",
+ printable_path(full_path));
+ return WIMLIB_ERR_READLINK;
}
- if (unlikely(bytes_returned < REPARSE_DATA_OFFSET)) {
- ERROR("\"%ls\": Reparse point data is invalid",
- printable_path(path));
+ rpbuflen = bytes_returned;
+
+ if (unlikely(rpbuflen < REPARSE_DATA_OFFSET)) {
+ ERROR("\"%ls\": reparse point buffer is too short",
+ printable_path(full_path));
return WIMLIB_ERR_INVALID_REPARSE_DATA;
}
- rpbuflen = bytes_returned;
- reparse_tag = le32_to_cpu(*(le32*)rpbuf);
- ret = RP_NOT_FIXED;
- if (params->add_flags & WIMLIB_ADD_FLAG_RPFIX &&
- (reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK ||
- reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT))
- {
- ret = winnt_try_rpfix(rpbuf, &rpbuflen,
- params->capture_root_ino,
- params->capture_root_dev,
- path, params);
+ if (params->add_flags & WIMLIB_ADD_FLAG_RPFIX) {
+ ret = winnt_try_rpfix(&rpbuf, &rpbuflen, full_path, params);
+ if (ret == RP_FIXED)
+ inode->i_rp_flags &= ~WIM_RP_FLAG_NOT_FIXED;
+ else if (ret)
+ return ret;
}
- *rpbuflen_ret = rpbuflen;
- return ret;
+
+ inode->i_reparse_tag = le32_to_cpu(rpbuf.rptag);
+ inode->i_rp_reserved = le16_to_cpu(rpbuf.rpreserved);
+
+ if (!inode_add_stream_with_data(inode,
+ STREAM_TYPE_REPARSE_POINT,
+ NO_STREAM_NAME,
+ rpbuf.rpdata,
+ rpbuflen - REPARSE_DATA_OFFSET,
+ params->blob_table))
+ return WIMLIB_ERR_NOMEM;
+
+ return 0;
}
static DWORD WINAPI
* and later, whereas the stream support in NtQueryInformationFile() was
* already present in Windows XP.
*/
-static int
+static noinline_for_stack int
winnt_scan_data_streams(HANDLE h, const wchar_t *path, size_t path_nchars,
struct wim_inode *inode, struct list_head *unhashed_blobs,
u64 file_size, u32 vol_flags)
{
int ret;
- u8 _buf[1024] _aligned_attribute(8);
+ u8 _buf[4096] _aligned_attribute(8);
u8 *buf;
size_t bufsize;
IO_STATUS_BLOCK iosb;
return ret;
}
-static u64
+static noinline_for_stack u64
get_sort_key(HANDLE h)
{
STARTING_VCN_INPUT_BUFFER in = { .StartingVcn.QuadPart = 0 };
}
}
+static noinline_for_stack u32
+get_volume_information(HANDLE h, const wchar_t *full_path,
+ struct capture_params *params)
+{
+ FILE_FS_ATTRIBUTE_INFORMATION attr_info;
+ FILE_FS_VOLUME_INFORMATION vol_info;
+ IO_STATUS_BLOCK iosb;
+ NTSTATUS status;
+ u32 vol_flags;
+
+ /* Get volume flags */
+ status = (*func_NtQueryVolumeInformationFile)(h, &iosb,
+ &attr_info,
+ sizeof(attr_info),
+ FileFsAttributeInformation);
+ if (likely((NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
+ (iosb.Information >=
+ offsetof(FILE_FS_ATTRIBUTE_INFORMATION,
+ FileSystemAttributes) +
+ sizeof(attr_info.FileSystemAttributes))))
+ {
+ vol_flags = attr_info.FileSystemAttributes;
+ } else {
+ winnt_warning(status, L"\"%ls\": Can't get volume attributes",
+ printable_path(full_path));
+ vol_flags = 0;
+ }
+
+ /* Get volume ID. */
+ status = (*func_NtQueryVolumeInformationFile)(h, &iosb,
+ &vol_info,
+ sizeof(vol_info),
+ FileFsVolumeInformation);
+ if (likely((NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
+ (iosb.Information >=
+ offsetof(FILE_FS_VOLUME_INFORMATION,
+ VolumeSerialNumber) +
+ sizeof(vol_info.VolumeSerialNumber))))
+ {
+ params->capture_root_dev = vol_info.VolumeSerialNumber;
+ } else {
+ winnt_warning(status, L"\"%ls\": Can't get volume ID",
+ printable_path(full_path));
+ params->capture_root_dev = 0;
+ }
+ return vol_flags;
+}
+
+struct file_info {
+ u32 attributes;
+ u32 num_links;
+ u64 creation_time;
+ u64 last_write_time;
+ u64 last_access_time;
+ u64 ino;
+ u64 end_of_file;
+};
+
+static noinline_for_stack NTSTATUS
+get_file_info(HANDLE h, struct file_info *info)
+{
+ IO_STATUS_BLOCK iosb;
+ NTSTATUS status;
+ FILE_ALL_INFORMATION all_info;
+
+ status = (*func_NtQueryInformationFile)(h, &iosb, &all_info,
+ sizeof(all_info),
+ FileAllInformation);
+
+ if (unlikely(!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW))
+ return status;
+
+ info->attributes = all_info.BasicInformation.FileAttributes;
+ info->num_links = all_info.StandardInformation.NumberOfLinks;
+ info->creation_time = all_info.BasicInformation.CreationTime.QuadPart;
+ info->last_write_time = all_info.BasicInformation.LastWriteTime.QuadPart;
+ info->last_access_time = all_info.BasicInformation.LastAccessTime.QuadPart;
+ info->ino = all_info.InternalInformation.IndexNumber.QuadPart;
+ info->end_of_file = all_info.StandardInformation.EndOfFile.QuadPart;
+ return STATUS_SUCCESS;
+}
+
static int
winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
HANDLE cur_dir,
HANDLE h = NULL;
int ret;
NTSTATUS status;
- FILE_ALL_INFORMATION file_info;
+ struct file_info file_info;
ACCESS_MASK requestedPerms;
u64 sort_key;
- ret = try_exclude(full_path, full_path_nchars, params);
- if (ret < 0) /* Excluded? */
+ ret = try_exclude(full_path, params);
+ if (unlikely(ret < 0)) /* Excluded? */
goto out_progress;
- if (ret > 0) /* Error? */
+ if (unlikely(ret > 0)) /* Error? */
goto out;
/* Open the file. */
}
/* Get information about the file. */
- {
- IO_STATUS_BLOCK iosb;
-
- status = (*func_NtQueryInformationFile)(h, &iosb,
- &file_info,
- sizeof(file_info),
- FileAllInformation);
-
- if (unlikely(!NT_SUCCESS(status) &&
- status != STATUS_BUFFER_OVERFLOW))
- {
- winnt_error(status,
- L"\"%ls\": Can't get file information",
- printable_path(full_path));
- ret = WIMLIB_ERR_STAT;
- goto out;
- }
+ status = get_file_info(h, &file_info);
+ if (!NT_SUCCESS(status)) {
+ winnt_error(status, L"\"%ls\": Can't get file information",
+ printable_path(full_path));
+ ret = WIMLIB_ERR_STAT;
+ goto out;
}
if (unlikely(!(requestedPerms & FILE_READ_DATA)) &&
- !(file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ENCRYPTED))
+ !(file_info.attributes & FILE_ATTRIBUTE_ENCRYPTED))
{
ERROR("\"%ls\": Permission to read data was denied",
printable_path(full_path));
}
if (unlikely(!cur_dir)) {
-
/* Root of tree being captured; get volume information. */
-
- FILE_FS_ATTRIBUTE_INFORMATION attr_info;
- FILE_FS_VOLUME_INFORMATION vol_info;
- IO_STATUS_BLOCK iosb;
-
- /* Get volume flags */
- status = (*func_NtQueryVolumeInformationFile)(h, &iosb,
- &attr_info,
- sizeof(attr_info),
- FileFsAttributeInformation);
- if (likely((NT_SUCCESS(status) ||
- (status == STATUS_BUFFER_OVERFLOW)) &&
- (iosb.Information >=
- offsetof(FILE_FS_ATTRIBUTE_INFORMATION,
- FileSystemAttributes) +
- sizeof(attr_info.FileSystemAttributes))))
- {
- vol_flags = attr_info.FileSystemAttributes;
- } else {
- winnt_warning(status,
- L"\"%ls\": Can't get volume attributes",
- printable_path(full_path));
- vol_flags = 0;
- }
-
- /* Set inode number of root directory */
- params->capture_root_ino =
- file_info.InternalInformation.IndexNumber.QuadPart;
-
- /* Get volume ID. */
- status = (*func_NtQueryVolumeInformationFile)(h, &iosb,
- &vol_info,
- sizeof(vol_info),
- FileFsVolumeInformation);
- if (likely((NT_SUCCESS(status) ||
- (status == STATUS_BUFFER_OVERFLOW)) &&
- (iosb.Information >=
- offsetof(FILE_FS_VOLUME_INFORMATION,
- VolumeSerialNumber) +
- sizeof(vol_info.VolumeSerialNumber))))
- {
- params->capture_root_dev = vol_info.VolumeSerialNumber;
- } else {
- winnt_warning(status, L"\"%ls\": Can't get volume ID",
- printable_path(full_path));
- params->capture_root_dev = 0;
- }
+ vol_flags = get_volume_information(h, full_path, params);
+ params->capture_root_ino = file_info.ino;
}
+
/* Create a WIM dentry with an associated inode, which may be shared.
*
* However, we need to explicitly check for directories and files with
* files on different volumes. */
ret = inode_table_new_dentry(params->inode_table,
filename,
- file_info.InternalInformation.IndexNumber.QuadPart,
+ file_info.ino,
params->capture_root_dev,
- (file_info.StandardInformation.NumberOfLinks <= 1 ||
- (file_info.BasicInformation.FileAttributes &
- FILE_ATTRIBUTE_DIRECTORY)),
+ (file_info.num_links <= 1),
&root);
if (ret)
goto out;
goto out_progress;
}
- inode->i_attributes = file_info.BasicInformation.FileAttributes;
- inode->i_creation_time = file_info.BasicInformation.CreationTime.QuadPart;
- inode->i_last_write_time = file_info.BasicInformation.LastWriteTime.QuadPart;
- inode->i_last_access_time = file_info.BasicInformation.LastAccessTime.QuadPart;
+ inode->i_attributes = file_info.attributes;
+ inode->i_creation_time = file_info.creation_time;
+ inode->i_last_write_time = file_info.last_write_time;
+ inode->i_last_access_time = file_info.last_access_time;
/* Get the file's security descriptor, unless we are capturing in
* NO_ACLS mode or the volume does not support security descriptors. */
/* If this is a reparse point, load the reparse data. */
if (unlikely(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
- if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
- /* See comment above assign_stream_types_encrypted() */
- WARNING("Ignoring reparse data of encrypted file \"%ls\"",
- printable_path(full_path));
- } else {
- u8 rpbuf[REPARSE_POINT_MAX_SIZE] _aligned_attribute(8);
- u16 rpbuflen;
-
- ret = winnt_get_reparse_data(h, full_path, params,
- rpbuf, &rpbuflen);
- switch (ret) {
- case RP_FIXED:
- inode->i_not_rpfixed = 0;
- break;
- case RP_NOT_FIXED:
- inode->i_not_rpfixed = 1;
- break;
- default:
- goto out;
- }
- inode->i_reparse_tag = le32_to_cpu(*(le32*)rpbuf);
- if (!inode_add_stream_with_data(inode,
- STREAM_TYPE_REPARSE_POINT,
- NO_STREAM_NAME,
- rpbuf + REPARSE_DATA_OFFSET,
- rpbuflen - REPARSE_DATA_OFFSET,
- params->blob_table))
- {
- ret = WIMLIB_ERR_NOMEM;
- goto out;
- }
- }
+ ret = winnt_load_reparse_data(h, inode, full_path, params);
+ if (ret)
+ goto out;
}
sort_key = get_sort_key(h);
full_path_nchars,
inode,
params->unhashed_blobs,
- file_info.StandardInformation.EndOfFile.QuadPart,
+ file_info.end_of_file,
vol_flags);
if (ret)
goto out;