From 1a4696b013a95bf9af1580a93dc2e25c97d10b43 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 17 Aug 2013 19:50:24 -0500 Subject: [PATCH] Win32 apply: Delay setting FILE_ATTRIBUTE_READONLY --- include/wimlib/apply.h | 7 ++++++- src/extract.c | 13 ++++++++++--- src/ntfs-3g_apply.c | 2 +- src/win32_apply.c | 13 ++++++++++++- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/include/wimlib/apply.h b/include/wimlib/apply.h index 1a2647df..31cda98f 100644 --- a/include/wimlib/apply.h +++ b/include/wimlib/apply.h @@ -89,7 +89,8 @@ struct apply_operations { /* 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. */ @@ -167,6 +168,10 @@ struct apply_operations { * 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 { diff --git a/src/extract.c b/src/extract.c index 7ca01220..c9a1dca0 100644 --- a/src/extract.c +++ b/src/extract.c @@ -642,7 +642,7 @@ error: * 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; @@ -664,7 +664,7 @@ extract_file_attributes(const tchar *path, struct apply_ctx *ctx, 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); @@ -1053,7 +1053,7 @@ do_dentry_extract_skeleton(tchar path[], struct wim_dentry *dentry, } /* Set file attributes (if supported). */ - ret = extract_file_attributes(path, ctx, dentry); + ret = extract_file_attributes(path, ctx, dentry, 0); if (ret) return ret; @@ -1472,6 +1472,13 @@ dentry_extract_final(struct wim_dentry *dentry, void *_ctx) 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); } diff --git a/src/ntfs-3g_apply.c b/src/ntfs-3g_apply.c index 2b0eff92..a1c67751 100644 --- a/src/ntfs-3g_apply.c +++ b/src/ntfs-3g_apply.c @@ -299,7 +299,7 @@ ntfs_3g_extract_named_stream(file_spec_t file, const utf16lechar *stream_name, 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; diff --git a/src/win32_apply.c b/src/win32_apply.c index d08ea5d8..ac7e3753 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -332,7 +332,7 @@ error: 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 | @@ -342,9 +342,19 @@ win32_set_file_attributes(const wchar_t *path, u32 attributes, 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)) @@ -560,6 +570,7 @@ const struct apply_operations win32_apply_ops = { .requires_realtarget_in_paths = 1, .realpath_works_on_nonexisting_files = 1, .root_directory_is_special = 1, + .requires_final_set_attributes_pass = 1, }; #endif /* __WIN32__ */ -- 2.43.0