From: Eric Biggers Date: Sun, 10 Mar 2013 08:26:18 +0000 (-0500) Subject: Win32 apply X-Git-Tag: v1.3.0~39 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=2d50f9e33814102747da848933793cfdf33c09a0 Win32 apply --- diff --git a/src/add_image.c b/src/add_image.c index 7adc5252..9d88916e 100644 --- a/src/add_image.c +++ b/src/add_image.c @@ -298,7 +298,7 @@ static int win32_sha1sum(const wchar_t *path, u8 hash[SHA1_HASH_SIZE]) DWORD bytesRead; int ret; - hFile = win32_open_file(path); + hFile = win32_open_file(path); if (hFile == INVALID_HANDLE_VALUE) return WIMLIB_ERR_OPEN; @@ -378,7 +378,7 @@ static int win32_capture_stream(const char *path, spath[path_utf16_nchars] = L':'; memcpy(&spath[path_utf16_nchars + 1], p, (colon - p) * sizeof(wchar_t)); } - spath[spath_nchars] = L'\0'; + spath[spath_nchars] = L'\0'; ret = win32_sha1sum(spath, hash); if (ret) { @@ -425,12 +425,24 @@ static int win32_capture_streams(const char *path, int ret; HANDLE hFind; DWORD err; - + hFind = FindFirstStreamW(path_utf16, FindStreamInfoStandard, &dat, 0); if (hFind == INVALID_HANDLE_VALUE) { - ERROR("Win32 API: Failed to look up data streams of \"%s\"", - path); - return WIMLIB_ERR_READ; + err = GetLastError(); + + /* Seems legal for this to return ERROR_HANDLE_EOF on reparse + * points and directories */ + if ((inode->i_attributes & + (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY)) + && err == ERROR_HANDLE_EOF) + { + return 0; + } else { + ERROR("Win32 API: Failed to look up data streams of \"%s\"", + path); + win32_error(err); + return WIMLIB_ERR_READ; + } } do { ret = win32_capture_stream(path, path_utf16, @@ -820,7 +832,7 @@ static int build_dentry_tree(struct wim_dentry **root_ret, /* Directory (not a reparse point) --- recurse to children */ /* But first... directories may have alternate data streams that - * need to be captured */ + * need to be captured (maybe?) */ ret = win32_capture_streams(root_disk_path, path_utf16, path_utf16_nchars, @@ -1375,6 +1387,17 @@ WIMLIBAPI int wimlib_add_image_multisource(WIMStruct *w, extra_arg = NULL; } +#if defined(__CYGWIN__) || defined(__WIN32__) + if (add_image_flags & WIMLIB_ADD_IMAGE_FLAG_UNIX_DATA) { + ERROR("Capturing UNIX-specific data is not supported on Windows"); + return WIMLIB_ERR_INVALID_PARAM; + } + if (add_image_flags & WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE) { + ERROR("Dereferencing symbolic links is not supported on Windows"); + return WIMLIB_ERR_INVALID_PARAM; + } +#endif + if (!name || !*name) { ERROR("Must specify a non-empty string for the image name"); return WIMLIB_ERR_INVALID_PARAM; diff --git a/src/dentry.h b/src/dentry.h index 5517c92e..f5e4687e 100644 --- a/src/dentry.h +++ b/src/dentry.h @@ -323,10 +323,8 @@ struct wim_inode { #define inode_add_dentry(dentry, inode) \ list_add_tail(&(dentry)->d_alias, &(inode)->i_dentry) -static inline struct wim_dentry *inode_first_dentry(struct wim_inode *inode) -{ - return container_of(inode->i_dentry.next, struct wim_dentry, d_alias); -} +#define inode_first_dentry(inode) \ + container_of(inode->i_dentry.next, struct wim_dentry, d_alias) static inline bool dentry_is_first_in_inode(const struct wim_dentry *dentry) { diff --git a/src/extract_image.c b/src/extract_image.c index d91f7262..8d21edac 100644 --- a/src/extract_image.c +++ b/src/extract_image.c @@ -143,6 +143,8 @@ static int win32_extract_stream(const struct wim_inode *inode, wchar_t *stream_path; HANDLE h; int ret; + DWORD err; + DWORD creationDisposition = CREATE_ALWAYS; if (stream_name_utf16) { size_t stream_path_nchars; @@ -163,30 +165,57 @@ static int win32_extract_stream(const struct wim_inode *inode, /*path, stream_name_utf16);*/ } else { stream_path = (wchar_t*)path; + if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) { + if (!CreateDirectoryW(stream_path, NULL)) { + err = GetLastError(); + if (err == ERROR_FILE_EXISTS && + dentry_is_root(inode_first_dentry(inode))) + { + /* Already exists */ + return 0; + } + ERROR("Failed to create directory \"%s\"", path_utf8); + win32_error(err); + ret = WIMLIB_ERR_MKDIR; + goto fail; + } + creationDisposition = OPEN_EXISTING; + } } h = CreateFileW(stream_path, GENERIC_WRITE | WRITE_OWNER | WRITE_DAC, 0, NULL, - CREATE_ALWAYS, + creationDisposition, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS | inode->i_attributes, NULL); - if (!h) { - win32_error(GetLastError()); + if (h == INVALID_HANDLE_VALUE) { + err = GetLastError(); + if (err == ERROR_FILE_EXISTS && + dentry_is_root(inode_first_dentry(inode))) + { + /* Already exists */ + return 0; + } + ERROR("Failed to create \"%s\"", path_utf8); + win32_error(err); ret = WIMLIB_ERR_OPEN; goto fail; } if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) { + DEBUG("Setting reparse data on \"%s\"", path_utf8); ret = win32_set_reparse_data(h, inode->i_reparse_tag, lte, path, path_utf8); if (ret) goto fail_close_handle; } else { if (lte) { + DEBUG("Extracting stream for \"%s\" (len = %zu)", + path_utf8, wim_resource_size(lte)); ret = do_win32_extract_stream(h, lte); if (ret) goto fail_close_handle; @@ -194,7 +223,9 @@ static int win32_extract_stream(const struct wim_inode *inode, } if (!CloseHandle(h)) { - win32_error(GetLastError()); + err = GetLastError(); + ERROR("Failed to close \"%s\"", path_utf8); + win32_error(err); ret = WIMLIB_ERR_WRITE; goto fail; } @@ -556,6 +587,8 @@ static int extract_directory(struct wim_dentry *dentry, return WIMLIB_ERR_MKDIR; } dir_exists: + ret = 0; +#if !defined(__CYGWIN__) && !defined(__WIN32__) if (dentry) { struct wimlib_unix_data unix_data; ret = inode_get_unix_data(dentry->d_inode, &unix_data, NULL); @@ -565,9 +598,8 @@ dir_exists: ret = 0; else ret = dir_apply_unix_data(output_path, &unix_data); - } else { - ret = 0; } +#endif return ret; } @@ -577,20 +609,25 @@ static int apply_dentry_normal(struct wim_dentry *dentry, void *arg) struct apply_args *args = arg; struct wim_inode *inode = dentry->d_inode; size_t len; + char *output_path; len = strlen(args->target); - char output_path[len + dentry->full_path_utf8_len + 1]; - memcpy(output_path, args->target, len); - memcpy(output_path + len, dentry->full_path_utf8, dentry->full_path_utf8_len); - output_path[len + dentry->full_path_utf8_len] = '\0'; + if (dentry_is_root(dentry)) { + output_path = (char*)args->target; + } else { + output_path = alloca(len + dentry->full_path_utf8_len + 1); + memcpy(output_path, args->target, len); + memcpy(output_path + len, dentry->full_path_utf8, dentry->full_path_utf8_len); + output_path[len + dentry->full_path_utf8_len] = '\0'; + len += dentry->full_path_utf8_len; + } #if defined(__CYGWIN__) || defined(__WIN32__) char *utf16_path; size_t utf16_path_len; DWORD err; int ret; - ret = utf8_to_utf16(output_path, len + dentry->full_path_utf8_len, - &utf16_path, &utf16_path_len); + ret = utf8_to_utf16(output_path, len, &utf16_path, &utf16_path_len); if (ret) return ret; @@ -615,6 +652,8 @@ static int apply_dentry_normal(struct wim_dentry *dentry, void *arg) goto out_free_utf16_path; if (inode->i_security_id != -1) { + DEBUG("Setting security descriptor %d on %s", + inode->i_security_id, output_path); ret = win32_set_security_data(inode, (const wchar_t*)utf16_path, wim_const_security_data(args->w), @@ -678,10 +717,10 @@ static int apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg) FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - if (!h) + if (h == INVALID_HANDLE_VALUE) err = GetLastError(); FREE(utf16_path); - if (!h) + if (h == INVALID_HANDLE_VALUE) goto fail; FILETIME creationTime = {.dwLowDateTime = dentry->d_inode->i_creation_time & 0xffffffff, @@ -1162,6 +1201,10 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, ERROR("Extracting UNIX data is not supported on Windows"); return WIMLIB_ERR_INVALID_PARAM; } + if (extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK)) { + ERROR("Linked extraction modes are not supported on Windows"); + return WIMLIB_ERR_INVALID_PARAM; + } #endif if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {