/* Have we tried to enable short name support on the target volume yet?
*/
bool tried_to_enable_short_names;
+
+ bool can_open_by_inode_number;
};
/* Get the drive letter from a Windows path, or return the null character if the
if (!ctx->print_buffer)
return WIMLIB_ERR_NOMEM;
+ ctx->can_open_by_inode_number = true;
+
return 0;
}
0);
}
+static NTSTATUS
+do_create_file_by_inode(const struct wim_inode *inode,
+ PHANDLE FileHandle,
+ ACCESS_MASK DesiredAccess,
+ PLARGE_INTEGER AllocationSize,
+ ULONG FileAttributes,
+ ULONG CreateDisposition,
+ ULONG CreateOptions,
+ struct win32_apply_ctx *ctx)
+{
+ UNICODE_STRING str;
+ NTSTATUS status;
+
+ if (ctx->can_open_by_inode_number) {
+ str.Buffer = (wchar_t *)&inode->i_mft_no;
+ str.Length = sizeof(inode->i_mft_no);
+ str.MaximumLength = str.Length;
+ CreateOptions |= FILE_OPEN_BY_FILE_ID;
+ ctx->attr.ObjectName = &str;
+ }
+
+ status = do_create_file(FileHandle,
+ DesiredAccess,
+ AllocationSize,
+ FileAttributes,
+ CreateDisposition,
+ CreateOptions,
+ ctx);
+
+ if (ctx->can_open_by_inode_number)
+ ctx->attr.ObjectName = &ctx->pathbuf;
+
+ return status;
+}
+
/* Like do_create_file(), but builds the extraction path of the @dentry first.
*/
static NTSTATUS
return ret;
}
+static void
+save_inode_number(struct wim_inode *inode, HANDLE h, struct win32_apply_ctx *ctx)
+{
+ if (!ctx->can_open_by_inode_number)
+ return;
+
+ NTSTATUS status;
+ FILE_INTERNAL_INFORMATION info;
+
+ status = (*func_NtQueryInformationFile)(h, &ctx->iosb,
+ &info, sizeof(info),
+ FileInternalInformation);
+ if (NT_SUCCESS(status))
+ inode->i_mft_no = info.IndexNumber.QuadPart;
+ else
+ inode->i_mft_no = 0;
+}
+
/*
* Creates the directory named by @dentry, or uses an existing directory at that
* location. If necessary, sets the short name and/or fixes compression and
}
ret = adjust_compression_attribute(h, dentry, ctx);
+ if (ret)
+ goto out;
+
+ save_inode_number(dentry->d_inode, h, ctx);
out:
(*func_NtClose)(h);
return ret;
if (ret)
goto out_close;
+ save_inode_number(dentry->d_inode, h, ctx);
+
*h_ret = h;
return 0;
build_extraction_path(dentry, ctx);
}
-
/* Open a new handle */
- status = do_create_file(&h,
- FILE_WRITE_DATA | SYNCHRONIZE,
- NULL, 0, FILE_OPEN_IF,
- FILE_SEQUENTIAL_ONLY |
- FILE_SYNCHRONOUS_IO_NONALERT,
- ctx);
+ status = do_create_file_by_inode(dentry->d_inode,
+ &h,
+ FILE_WRITE_DATA | SYNCHRONIZE,
+ NULL, 0, FILE_OPEN_IF,
+ FILE_SEQUENTIAL_ONLY |
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ ctx);
if (!NT_SUCCESS(status)) {
winnt_error(status, L"Can't open \"%ls\" for writing",
current_path(ctx));
build_extraction_path(dentry, ctx);
/* Open a handle with as many relevant permissions as possible. */
- while (!NT_SUCCESS(status = do_create_file(&h, perms, NULL,
- 0, FILE_OPEN, 0, ctx)))
+ while (!NT_SUCCESS(status =
+ do_create_file_by_inode(dentry->d_inode, &h,
+ perms, NULL, 0,
+ FILE_OPEN, 0, ctx)))
{
if (status == STATUS_PRIVILEGE_NOT_HELD ||
status == STATUS_ACCESS_DENIED)