/* OPTIONAL: Set file attributes. Calling code calls this if non-NULL.
*/
int (*set_file_attributes)
- (const tchar *path, u32 attributes, struct apply_ctx *ctx);
+ (const tchar *path, u32 attributes, struct apply_ctx *ctx,
+ unsigned pass);
/* OPTIONAL: Set reparse data. In start_extract(), set
* ctx->supported_features.reparse_data if supported. */
* then be passed to callbacks taking a 'file_spec_t', rather than the
* path. */
unsigned uses_cookies : 1;
+
+ /* OPTIONAL: Set to 1 if set_file_attributes() needs to be called a
+ * second time towards the end of the extraction. */
+ unsigned requires_final_set_attributes_pass : 1;
};
struct wim_features {
* extraction mode. */
static int
extract_file_attributes(const tchar *path, struct apply_ctx *ctx,
- struct wim_dentry *dentry)
+ struct wim_dentry *dentry, unsigned pass)
{
int ret;
if (attributes == 0)
attributes = FILE_ATTRIBUTE_NORMAL;
- ret = ctx->ops->set_file_attributes(path, attributes, ctx);
+ ret = ctx->ops->set_file_attributes(path, attributes, ctx, pass);
if (ret) {
ERROR_WITH_ERRNO("Failed to set attributes on "
"\"%"TS"\"", path);
}
/* Set file attributes (if supported). */
- ret = extract_file_attributes(path, ctx, dentry);
+ ret = extract_file_attributes(path, ctx, dentry, 0);
if (ret)
return ret;
if (ret)
return ret;
+ if (ctx->ops->requires_final_set_attributes_pass) {
+ /* Set file attributes (if supported). */
+ ret = extract_file_attributes(path, ctx, dentry, 1);
+ if (ret)
+ return ret;
+ }
+
return extract_timestamps(path, ctx, dentry);
}
static int
ntfs_3g_set_file_attributes(const char *path, u32 attributes,
- struct apply_ctx *ctx)
+ struct apply_ctx *ctx, unsigned pass)
{
ntfs_inode *ni;
int ret = 0;
static int
win32_set_file_attributes(const wchar_t *path, u32 attributes,
- struct apply_ctx *ctx)
+ struct apply_ctx *ctx, unsigned pass)
{
u32 special_attributes =
FILE_ATTRIBUTE_REPARSE_POINT |
FILE_ATTRIBUTE_ENCRYPTED;
u32 actual_attributes;
+ /* On FAT filesystems we can't set FILE_ATTRIBUTE_READONLY on the
+ * initial pass (when files are created, but data not extracted);
+ * otherwise the system will refuse access to the file even if the
+ * process has SeRestorePrivilege. */
+ if (pass == 0)
+ attributes &= ~FILE_ATTRIBUTE_READONLY;
+
if (!SetFileAttributes(path, attributes & ~special_attributes))
goto error;
+ if (pass != 0)
+ return 0;
+
if (attributes & (FILE_ATTRIBUTE_SPARSE_FILE |
FILE_ATTRIBUTE_ENCRYPTED |
FILE_ATTRIBUTE_COMPRESSED))
.requires_realtarget_in_paths = 1,
.realpath_works_on_nonexisting_files = 1,
.root_directory_is_special = 1,
+ .requires_final_set_attributes_pass = 1,
};
#endif /* __WIN32__ */