X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fextract_image.c;h=8e5d130ec07df2b152114ffc3f8c6db1a966dc41;hb=399e095d7d2e245634b53d7771217bd7614347a3;hp=6735602f495d489a545598bddd85a3efe6060265;hpb=09301b8018e00f51ba96ba02adca676e817b8827;p=wimlib diff --git a/src/extract_image.c b/src/extract_image.c index 6735602f..8e5d130e 100644 --- a/src/extract_image.c +++ b/src/extract_image.c @@ -2,11 +2,6 @@ * extract_image.c * * Support for extracting WIM files. - * - * This code does NOT contain any filesystem-specific features. In particular, - * security information (i.e. file permissions) and alternate data streams are - * ignored, except possibly to read an alternate data stream that contains - * symbolic link data. */ /* @@ -31,30 +26,30 @@ #include "config.h" #if defined(__CYGWIN__) || defined(__WIN32__) -#include -#ifdef ERROR -#undef ERROR -#endif -#include +# include +# ifdef ERROR +# undef ERROR +# endif +# include +#else +# include +# ifdef HAVE_UTIME_H +# include +# endif +# include "timestamp.h" +# include #endif -#include #include #include +#include #include #include -#include -#include - -#ifdef HAVE_UTIME_H -#include -#endif #include #include "dentry.h" #include "lookup_table.h" -#include "timestamp.h" #include "wimlib_internal.h" #include "xml.h" @@ -64,8 +59,6 @@ #ifdef HAVE_ALLOCA_H #include -#else -#include #endif #if defined(__CYGWIN__) || defined(__WIN32__) @@ -176,19 +169,19 @@ static int win32_extract_stream(const struct wim_inode *inode, /* Named stream. Create a buffer that contains the UTF-16LE * string [./]@path:@stream_name_utf16. This is needed to * create and open the stream using CreateFileW(). I'm not - * aware of any other APIs to do this. Note: note that the - * '$DATA' suffix seems to be unneeded; Additional note: a "./" - * prefix needs to be added when the path is not absolute to - * avoid ambiguity with drive letters. */ + * aware of any other APIs to do this. Note: the '$DATA' suffix + * seems to be unneeded. Additional note: a "./" prefix needs + * to be added when the path is not absolute to avoid ambiguity + * with drive letters. */ size_t stream_path_nchars; size_t path_nchars; size_t stream_name_nchars; const wchar_t *prefix; - path_nchars = wcslen(path); + path_nchars = wcslen(path); stream_name_nchars = wcslen(stream_name_utf16); stream_path_nchars = path_nchars + 1 + stream_name_nchars; - if (path[0] != L'/' && path[1] != L'\\') { + if (path[0] != L'/' && path[0] != L'\\') { prefix = L"./"; stream_path_nchars += 2; } else { @@ -198,8 +191,8 @@ static int win32_extract_stream(const struct wim_inode *inode, swprintf(stream_path, stream_path_nchars + 1, L"%ls%ls:%ls", prefix, path, stream_name_utf16); } else { - /* Unnamed stream; it's path is just the path to the file - * itself. */ + /* Unnamed stream; its path is just the path to the file itself. + * */ stream_path = (wchar_t*)path; /* Directories must be created with CreateDirectoryW(). Then @@ -210,7 +203,7 @@ static int win32_extract_stream(const struct wim_inode *inode, err = GetLastError(); if (err != ERROR_ALREADY_EXISTS) { ERROR("Failed to create directory \"%ls\"", - path); + stream_path); win32_error(err); ret = WIMLIB_ERR_MKDIR; goto fail; @@ -227,7 +220,7 @@ static int win32_extract_stream(const struct wim_inode *inode, DEBUG("Opening \"%ls\"", stream_path); h = CreateFileW(stream_path, - GENERIC_WRITE | WRITE_OWNER | WRITE_DAC, + GENERIC_WRITE | WRITE_OWNER | WRITE_DAC | ACCESS_SYSTEM_SECURITY, 0, NULL, creationDisposition, @@ -252,7 +245,7 @@ static int win32_extract_stream(const struct wim_inode *inode, goto fail_close_handle; } else { if (lte) { - DEBUG("Extracting \"%ls\" (len = %zu)", + DEBUG("Extracting \"%ls\" (len = %"PRIu64")", stream_path, wim_resource_size(lte)); ret = do_win32_extract_stream(h, lte); if (ret) @@ -289,7 +282,7 @@ out: * Returns 0 on success; nonzero on failure. */ static int win32_extract_streams(struct wim_inode *inode, - const wchar_t *path) + const wchar_t *path, u64 *completed_bytes_p) { struct wim_lookup_table_entry *unnamed_lte; int ret; @@ -298,6 +291,8 @@ static int win32_extract_streams(struct wim_inode *inode, ret = win32_extract_stream(inode, path, NULL, unnamed_lte); if (ret) goto out; + if (unnamed_lte) + *completed_bytes_p += wim_resource_size(unnamed_lte); for (u16 i = 0; i < inode->i_num_ads; i++) { const struct wim_ads_entry *ads_entry = &inode->i_ads_entries[i]; if (ads_entry->stream_name_len != 0) { @@ -314,6 +309,8 @@ static int win32_extract_streams(struct wim_inode *inode, ads_entry->lte); if (ret) break; + if (ads_entry->lte) + *completed_bytes_p += wim_resource_size(ads_entry->lte); } } out: @@ -327,7 +324,6 @@ out: * @inode: The WIM inode that was extracted and has a security descriptor. * @path: UTF-16LE external path that the inode was extracted to. * @sd: Security data for the WIM image. - * @path_utf8: @path in UTF-8 for error messages only. * * Returns 0 on success; nonzero on failure. */ @@ -350,7 +346,7 @@ static int win32_set_security_data(const struct wim_inode *inode, return 0; } -#else +#else /* __CYGWIN__ || __WIN32__ */ static int extract_regular_file_linked(struct wim_dentry *dentry, const char *output_path, struct apply_args *args, @@ -619,7 +615,7 @@ static int extract_symlink(struct wim_dentry *dentry, return 0; } -#endif /* !__CYGWIN__ && !__WIN32__ */ +#endif /* !(__CYGWIN__ || __WIN32__) */ static int extract_directory(struct wim_dentry *dentry, const char *output_path, bool is_root) @@ -714,7 +710,8 @@ static int apply_dentry_normal(struct wim_dentry *dentry, void *arg) } else { /* Create the file, directory, or reparse point, and extract the * data streams. */ - ret = win32_extract_streams(inode, (const wchar_t*)utf16_path); + ret = win32_extract_streams(inode, (const wchar_t*)utf16_path, + &args->progress.extract.completed_bytes); if (ret) goto out_free_utf16_path; @@ -778,15 +775,17 @@ static int apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg) size_t utf16_path_len; DWORD err; HANDLE h; - BOOL bret1, bret2; ret = utf8_to_utf16(output_path, len, &utf16_path, &utf16_path_len); if (ret) return ret; - DEBUG("Opening \"%ls\" to set timestamps", utf16_path); - h = CreateFileW(utf16_path, GENERIC_WRITE, FILE_SHARE_READ, - NULL, OPEN_EXISTING, + DEBUG("Opening \"%s\" to set timestamps", output_path); + h = CreateFileW((const wchar_t*)utf16_path, + GENERIC_WRITE | WRITE_OWNER | WRITE_DAC | ACCESS_SYSTEM_SECURITY, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); @@ -796,12 +795,12 @@ static int apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg) if (h == INVALID_HANDLE_VALUE) goto fail; - FILETIME creationTime = {.dwLowDateTime = dentry->d_inode->i_creation_time & 0xffffffff, - .dwHighDateTime = dentry->d_inode->i_creation_time >> 32}; - FILETIME lastAccessTime = {.dwLowDateTime = dentry->d_inode->i_last_access_time & 0xffffffff, - .dwHighDateTime = dentry->d_inode->i_last_access_time >> 32}; - FILETIME lastWriteTime = {.dwLowDateTime = dentry->d_inode->i_last_write_time & 0xffffffff, - .dwHighDateTime = dentry->d_inode->i_last_write_time >> 32}; + FILETIME creationTime = {.dwLowDateTime = inode->i_creation_time & 0xffffffff, + .dwHighDateTime = inode->i_creation_time >> 32}; + FILETIME lastAccessTime = {.dwLowDateTime = inode->i_last_access_time & 0xffffffff, + .dwHighDateTime = inode->i_last_access_time >> 32}; + FILETIME lastWriteTime = {.dwLowDateTime = inode->i_last_write_time & 0xffffffff, + .dwHighDateTime = inode->i_last_write_time >> 32}; DEBUG("Calling SetFileTime() on \"%s\"", output_path); if (!SetFileTime(h, &creationTime, &lastAccessTime, &lastWriteTime)) { @@ -814,11 +813,13 @@ static int apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg) err = GetLastError(); goto fail; } - return 0; + goto out; fail: - ERROR("Can't set timestamps on \"%s\"", output_path); + /* Only warn if setting timestamps failed. */ + WARNING("Can't set timestamps on \"%s\"", output_path); win32_error(err); - return WIMLIB_ERR_WRITE; +out: + return 0; #else /* UNIX */ @@ -1317,6 +1318,11 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, w->lookup_table = joined_tab; } +#if defined(__CYGWIN__) || defined(__WIN32__) + win32_acquire_privilege(SE_RESTORE_NAME); + win32_acquire_privilege(SE_SECURITY_NAME); + win32_acquire_privilege(SE_TAKE_OWNERSHIP_NAME); +#endif if (image == WIMLIB_ALL_IMAGES) { extract_flags |= WIMLIB_EXTRACT_FLAG_MULTI_IMAGE; ret = extract_all_images(w, target, extract_flags, @@ -1326,6 +1332,11 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, ret = extract_single_image(w, image, target, extract_flags, progress_func); } +#if defined(__CYGWIN__) || defined(__WIN32__) + win32_release_privilege(SE_RESTORE_NAME); + win32_release_privilege(SE_SECURITY_NAME); + win32_release_privilege(SE_TAKE_OWNERSHIP_NAME); +#endif if (extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK))