DWORD bytesRead;
int ret;
- hFile = win32_open_file(path);
+ hFile = win32_open_file(path);
if (hFile == INVALID_HANDLE_VALUE)
return WIMLIB_ERR_OPEN;
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) {
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,
/* 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,
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;
wchar_t *stream_path;
HANDLE h;
int ret;
+ DWORD err;
+ DWORD creationDisposition = CREATE_ALWAYS;
if (stream_name_utf16) {
size_t stream_path_nchars;
/*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;
}
if (!CloseHandle(h)) {
- win32_error(GetLastError());
+ err = GetLastError();
+ ERROR("Failed to close \"%s\"", path_utf8);
+ win32_error(err);
ret = WIMLIB_ERR_WRITE;
goto fail;
}
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);
ret = 0;
else
ret = dir_apply_unix_data(output_path, &unix_data);
- } else {
- ret = 0;
}
+#endif
return ret;
}
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;
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),
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,
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) {