From 13ebe5824f96d958c5177ba3174e5b5882049e22 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Thu, 19 Nov 2015 19:38:39 +0100 Subject: [PATCH] Fix a possible data race in Windows for UTF-8 conversion We had less conversion buffers than possible threads, possibly resulting in a buffer used more than one time. Now converted to use local stack buffers to avoid the need of any kind of syncronization between threads. --- cmdline/mingw.c | 181 +++++++++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 88 deletions(-) diff --git a/cmdline/mingw.c b/cmdline/mingw.c index 4f552b70..b8b77aae 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -238,66 +238,35 @@ void os_done(void) } /** - * Number of conversion buffers. + * Size in chars of conversion buffers for u8to16() and u16to8(). */ -#define CONV_ROLL 4 - -/** - * Buffers for UTF16. - */ -static unsigned conv_utf16 = 0; -static wchar_t conv_utf16_buffer[CONV_ROLL][PATH_MAX]; - -/** - * Buffers for UTF8. - */ -static unsigned conv_utf8 = 0; -static char conv_utf8_buffer[CONV_ROLL][PATH_MAX]; - -/** - * Mutex used for conversion. - */ -static pthread_mutex_t conv_lock = PTHREAD_MUTEX_INITIALIZER; +#define CONV_MAX PATH_MAX /** * Convert a generic string from UTF8 to UTF16. */ -static wchar_t* u8tou16(const char* src) +static wchar_t* u8tou16(wchar_t* conv_buf, const char* src) { int ret; - unsigned roll; - pthread_mutex_lock(&conv_lock); - if (++conv_utf16 == CONV_ROLL) - conv_utf16 = 0; - roll = conv_utf16; - pthread_mutex_unlock(&conv_lock); - - ret = MultiByteToWideChar(CP_UTF8, 0, src, -1, conv_utf16_buffer[roll], sizeof(conv_utf16_buffer[0]) / sizeof(wchar_t)); + ret = MultiByteToWideChar(CP_UTF8, 0, src, -1, conv_buf, CONV_MAX); if (ret <= 0) { log_fatal("Error converting name '%s' from UTF-8 to UTF-16\n", src); exit(EXIT_FAILURE); } - return conv_utf16_buffer[roll]; + return conv_buf; } /** * Convert a generic string from UTF16 to UTF8. */ -static char* u16tou8ex(const wchar_t* src, size_t number_of_wchar, size_t* result_length_without_terminator) +static char* u16tou8ex(char* conv_buf, const wchar_t* src, size_t number_of_wchar, size_t* result_length_without_terminator) { int ret; - unsigned roll; - pthread_mutex_lock(&conv_lock); - if (++conv_utf8 == CONV_ROLL) - conv_utf8 = 0; - roll = conv_utf8; - pthread_mutex_unlock(&conv_lock); - - ret = WideCharToMultiByte(CP_UTF8, 0, src, number_of_wchar, conv_utf8_buffer[roll], sizeof(conv_utf8_buffer[0]), 0, 0); + ret = WideCharToMultiByte(CP_UTF8, 0, src, number_of_wchar, conv_buf, CONV_MAX, 0, 0); if (ret <= 0) { log_fatal("Error converting from UTF-16 to UTF-8\n"); exit(EXIT_FAILURE); @@ -305,15 +274,15 @@ static char* u16tou8ex(const wchar_t* src, size_t number_of_wchar, size_t* resul *result_length_without_terminator = ret; - return conv_utf8_buffer[roll]; + return conv_buf; } -static char* u16tou8(const wchar_t* src) +static char* u16tou8(char* conv_buf, const wchar_t* src) { size_t len; /* convert also the 0 terminator */ - return u16tou8ex(src, wcslen(src) + 1, &len); + return u16tou8ex(conv_buf, src, wcslen(src) + 1, &len); } /** @@ -339,16 +308,13 @@ static int is_slash(char c) * Naming Files, Paths, and Namespaces * http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#maxpath */ -static wchar_t* convert_arg(const char* src, int only_if_required) +static wchar_t* convert_arg(wchar_t* conv_buf, const char* src, int only_if_required) { int ret; wchar_t* dst; int count; - if (++conv_utf16 == CONV_ROLL) - conv_utf16 = 0; - - dst = conv_utf16_buffer[conv_utf16]; + dst = conv_buf; /* note that we always check for both / and \ because the path is blindly */ /* converted to unix format by path_import() */ @@ -389,9 +355,9 @@ static wchar_t* convert_arg(const char* src, int only_if_required) } /* chars already used */ - count = dst - conv_utf16_buffer[conv_utf16]; + count = dst - conv_buf; - ret = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, sizeof(conv_utf16_buffer[0]) / sizeof(wchar_t) - count); + ret = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, CONV_MAX - count); if (ret <= 0) { log_fatal("Error converting name '%s' from UTF-8 to UTF-16\n", src); @@ -408,11 +374,11 @@ static wchar_t* convert_arg(const char* src, int only_if_required) ++dst; } - return conv_utf16_buffer[conv_utf16]; + return conv_buf; } -#define convert(a) convert_arg(a, 0) -#define convert_if_required(a) convert_arg(a, 1) +#define convert(buf, a) convert_arg(buf, a, 0) +#define convert_if_required(buf, a) convert_arg(buf, a, 1) static BOOL GetReparseTagInfoByHandle(HANDLE hFile, FILE_ATTRIBUTE_TAG_INFO* lpFileAttributeTagInfo, DWORD dwFileAttributes) { @@ -622,10 +588,11 @@ static void windows_finddata2stat(const WIN32_FIND_DATAW* info, struct windows_s static void windows_finddata2dirent(const WIN32_FIND_DATAW* info, struct windows_dirent* dirent) { + char conv_buf[CONV_MAX]; const char* name; size_t len; - name = u16tou8ex(info->cFileName, wcslen(info->cFileName), &len); + name = u16tou8ex(conv_buf, info->cFileName, wcslen(info->cFileName), &len); if (len + 1 >= sizeof(dirent->d_name)) { log_fatal("Name too long\n"); @@ -640,10 +607,11 @@ static void windows_finddata2dirent(const WIN32_FIND_DATAW* info, struct windows static void windows_stream2dirent(const BY_HANDLE_FILE_INFORMATION* info, const FILE_ID_BOTH_DIR_INFO* stream, struct windows_dirent* dirent) { + char conv_buf[CONV_MAX]; const char* name; size_t len; - name = u16tou8ex(stream->FileName, stream->FileNameLength / 2, &len); + name = u16tou8ex(conv_buf, stream->FileName, stream->FileNameLength / 2, &len); if (len + 1 >= sizeof(dirent->d_name)) { log_fatal("Name too long\n"); @@ -732,11 +700,12 @@ int windows_fstat(int fd, struct windows_stat* st) int windows_lstat(const char* file, struct windows_stat* st) { + wchar_t conv_buf[CONV_MAX]; HANDLE h; WIN32_FIND_DATAW data; /* FindFirstFileW by default gets information of symbolic links and not of their targets */ - h = FindFirstFileW(convert(file), &data); + h = FindFirstFileW(convert(conv_buf, file), &data); if (h == INVALID_HANDLE_VALUE) { windows_errno(GetLastError()); return -1; @@ -759,7 +728,9 @@ void windows_dirent_lstat(const struct windows_dirent* dd, struct windows_stat* int windows_mkdir(const char* file) { - if (!CreateDirectoryW(convert(file), 0)) { + wchar_t conv_buf[CONV_MAX]; + + if (!CreateDirectoryW(convert(conv_buf, file), 0)) { windows_errno(GetLastError()); return -1; } @@ -769,7 +740,9 @@ int windows_mkdir(const char* file) int windows_rmdir(const char* file) { - if (!RemoveDirectoryW(convert(file))) { + wchar_t conv_buf[CONV_MAX]; + + if (!RemoveDirectoryW(convert(conv_buf, file))) { windows_errno(GetLastError()); return -1; } @@ -828,6 +801,7 @@ static BOOL GetFilePhysicalOffset(HANDLE h, uint64_t* physical) int lstat_sync(const char* file, struct windows_stat* st, uint64_t* physical) { + wchar_t conv_buf[CONV_MAX]; BY_HANDLE_FILE_INFORMATION info; FILE_ATTRIBUTE_TAG_INFO tag; HANDLE h; @@ -843,7 +817,7 @@ int lstat_sync(const char* file, struct windows_stat* st, uint64_t* physical) * cannot be opened like "C:\System Volume Information" resulting * in error ERROR_ACCESS_DENIED. */ - h = CreateFileW(convert(file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); + h = CreateFileW(convert(conv_buf, file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); if (h == INVALID_HANDLE_VALUE) { windows_errno(GetLastError()); return -1; @@ -885,6 +859,7 @@ int lstat_sync(const char* file, struct windows_stat* st, uint64_t* physical) int windows_stat(const char* file, struct windows_stat* st) { + wchar_t conv_buf[CONV_MAX]; BY_HANDLE_FILE_INFORMATION info; FILE_ATTRIBUTE_TAG_INFO tag; HANDLE h; @@ -894,7 +869,7 @@ int windows_stat(const char* file, struct windows_stat* st) * * Use FILE_FLAG_BACKUP_SEMANTICS to open directories (it's just ignored for files). */ - h = CreateFileW(convert(file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + h = CreateFileW(convert(conv_buf, file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); if (h == INVALID_HANDLE_VALUE) { windows_errno(GetLastError()); return -1; @@ -1065,6 +1040,9 @@ int windows_futimens(int fd, struct windows_timespec tv[2]) int windows_rename(const char* from, const char* to) { + wchar_t conv_buf_from[CONV_MAX]; + wchar_t conv_buf_to[CONV_MAX]; + /* * Implements an atomic rename in Windows. * Not really atomic at now to support XP. @@ -1072,7 +1050,7 @@ int windows_rename(const char* from, const char* to) * Is an atomic file rename (with overwrite) possible on Windows? * http://stackoverflow.com/questions/167414/is-an-atomic-file-rename-with-overwrite-possible-on-windows */ - if (!MoveFileExW(convert(from), convert(to), MOVEFILE_REPLACE_EXISTING)) { + if (!MoveFileExW(convert(conv_buf_from, from), convert(conv_buf_to, to), MOVEFILE_REPLACE_EXISTING)) { windows_errno(GetLastError()); return -1; } @@ -1082,7 +1060,9 @@ int windows_rename(const char* from, const char* to) int windows_remove(const char* file) { - if (!DeleteFileW(convert(file))) { + wchar_t conv_buf[CONV_MAX]; + + if (!DeleteFileW(convert(conv_buf, file))) { windows_errno(GetLastError()); return -1; } @@ -1092,19 +1072,23 @@ int windows_remove(const char* file) FILE* windows_fopen(const char* file, const char* mode) { - return _wfopen(convert(file), u8tou16(mode)); + wchar_t conv_buf_file[CONV_MAX]; + wchar_t conv_buf_mode[CONV_MAX]; + + return _wfopen(convert(conv_buf_file, file), u8tou16(conv_buf_mode, mode)); } int windows_open(const char* file, int flags, ...) { + wchar_t conv_buf[CONV_MAX]; va_list args; int ret; va_start(args, flags); if ((flags & O_CREAT) != 0) - ret = _wopen(convert(file), flags, va_arg(args, int)); + ret = _wopen(convert(conv_buf, file), flags, va_arg(args, int)); else - ret = _wopen(convert(file), flags); + ret = _wopen(convert(conv_buf, file), flags); va_end(args); return ret; @@ -1127,6 +1111,7 @@ struct windows_dir_struct { static windows_dir* windows_opendir_find(const char* dir) { + wchar_t conv_buf[CONV_MAX]; wchar_t* wdir; windows_dir* dirstream; size_t len; @@ -1137,7 +1122,7 @@ static windows_dir* windows_opendir_find(const char* dir) exit(EXIT_FAILURE); } - wdir = convert(dir); + wdir = convert(conv_buf, dir); /* add final / and * */ len = wcslen(wdir); @@ -1265,6 +1250,7 @@ static int windows_next_stream(windows_dir* dirstream) static windows_dir* windows_opendir_stream(const char* dir) { + wchar_t conv_buf[CONV_MAX]; windows_dir* dirstream; WCHAR* wdir; @@ -1274,7 +1260,7 @@ static windows_dir* windows_opendir_stream(const char* dir) exit(EXIT_FAILURE); } - wdir = convert(dir); + wdir = convert(conv_buf, dir); /* uses a 64 kB buffer for reading directory */ dirstream->buffer_size = 64 * 1024; @@ -1399,7 +1385,10 @@ void windows_sleep(unsigned seconds) int windows_link(const char* existing, const char* file) { - if (!CreateHardLinkW(convert(file), convert(existing), 0)) { + wchar_t conv_buf_file[CONV_MAX]; + wchar_t conv_buf_existing[CONV_MAX]; + + if (!CreateHardLinkW(convert(conv_buf_file, file), convert(conv_buf_existing, existing), 0)) { windows_errno(GetLastError()); return -1; } @@ -1409,6 +1398,9 @@ int windows_link(const char* existing, const char* file) int windows_symlink(const char* existing, const char* file) { + wchar_t conv_buf_file[CONV_MAX]; + wchar_t conv_buf_existing[CONV_MAX]; + if (!ptr_CreateSymbolicLinkW) { windows_errno(ERROR_NOT_SUPPORTED); return -1; @@ -1418,7 +1410,7 @@ int windows_symlink(const char* existing, const char* file) /* otherwise the link creation fails. */ /* But we don't want to always convert it, to avoid to recreate */ /* user symlinks different than they were before */ - if (!ptr_CreateSymbolicLinkW(convert(file), convert_if_required(existing), 0)) { + if (!ptr_CreateSymbolicLinkW(convert(conv_buf_file, file), convert_if_required(conv_buf_existing, existing), 0)) { windows_errno(GetLastError()); return -1; } @@ -1460,6 +1452,8 @@ typedef struct _REPARSE_DATA_BUFFER { int windows_readlink(const char* file, char* buffer, size_t size) { + wchar_t conv_buf_file[CONV_MAX]; + char conv_buf_name[CONV_MAX]; HANDLE h; const char* name; size_t len; @@ -1474,7 +1468,7 @@ int windows_readlink(const char* file, char* buffer, size_t size) * Use FILE_FLAG_BACKUP_SEMANTICS to open directories (it's just ignored for files). * Use FILE_FLAG_OPEN_REPARSE_POINT to open symbolic links and not the their target. */ - h = CreateFileW(convert(file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); + h = CreateFileW(convert(conv_buf_file, file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); if (h == INVALID_HANDLE_VALUE) { windows_errno(GetLastError()); return -1; @@ -1497,8 +1491,9 @@ int windows_readlink(const char* file, char* buffer, size_t size) } /* convert the name to UTF-8 */ - name = u16tou8ex(rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.PrintNameOffset, - rdb->SymbolicLinkReparseBuffer.PrintNameLength / 2, &len); + name = u16tou8ex(conv_buf_name, + rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.PrintNameOffset, + rdb->SymbolicLinkReparseBuffer.PrintNameLength / 2, &len); /* check for overflow */ if (len > size) { @@ -1520,12 +1515,13 @@ int devuuid(uint64_t device, char* uuid, size_t uuid_size) int filephy(const char* file, uint64_t size, uint64_t* physical) { + wchar_t conv_buf[CONV_MAX]; HANDLE h; (void)size; /* open the handle of the file */ - h = CreateFileW(convert(file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + h = CreateFileW(convert(conv_buf, file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); if (h == INVALID_HANDLE_VALUE) { windows_errno(GetLastError()); return -1; @@ -1544,6 +1540,8 @@ int filephy(const char* file, uint64_t size, uint64_t* physical) int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, uint64_t* free_space) { + wchar_t conv_buf[CONV_MAX]; + /* all FAT/exFAT/NTFS when managed from Windows have persistent inodes */ if (has_persistent_inode) *has_persistent_inode = 1; @@ -1562,7 +1560,7 @@ int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, u strcpy(dir, path); /* get the file attributes */ - attr = GetFileAttributesW(convert(dir)); + attr = GetFileAttributesW(convert(conv_buf, dir)); if (attr == INVALID_FILE_ATTRIBUTES) { DWORD error = GetLastError(); @@ -1596,7 +1594,7 @@ int fsinfo(const char* path, int* has_persistent_inode, uint64_t* total_space, u /* get the free space of the directory */ /* note that it must be a directory */ - if (!GetDiskFreeSpaceExW(convert(dir), 0, &total_bytes, &total_free_bytes)) { + if (!GetDiskFreeSpaceExW(convert(conv_buf, dir), 0, &total_bytes, &total_free_bytes)) { windows_errno(GetLastError()); return -1; } @@ -1840,13 +1838,15 @@ int randomize(void* ptr, size_t size) */ static int devresolve(const char* mount, char* file, size_t file_size, char* wfile, size_t wfile_size) { + wchar_t conv_buf_mount[CONV_MAX]; + char conv_buf_volume_guid[CONV_MAX]; WCHAR volume_mount[MAX_PATH]; WCHAR volume_guid[MAX_PATH]; DWORD i; char* p; /* get the volume mount point from the disk path */ - if (!GetVolumePathNameW(convert(mount), volume_mount, sizeof(volume_mount) / sizeof(WCHAR))) { + if (!GetVolumePathNameW(convert(conv_buf_mount, mount), volume_mount, sizeof(volume_mount) / sizeof(WCHAR))) { windows_errno(GetLastError()); return -1; } @@ -1865,7 +1865,7 @@ static int devresolve(const char* mount, char* file, size_t file_size, char* wfi if (i != 0 && volume_guid[i-1] == '\\') volume_guid[i-1] = 0; - pathcpy(wfile, wfile_size, u16tou8(volume_guid)); + pathcpy(wfile, wfile_size, u16tou8(conv_buf_volume_guid, volume_guid)); /* get the GUID start { */ p = strchr(wfile, '{'); @@ -1889,6 +1889,7 @@ static int devresolve(const char* mount, char* file, size_t file_size, char* wfi */ static int devtree(const char* name, const char* custom, const char* wfile, devinfo_t* parent, tommy_list* list) { + wchar_t conv_buf[CONV_MAX]; HANDLE h; unsigned char vde_buffer[sizeof(VOLUME_DISK_EXTENTS)]; VOLUME_DISK_EXTENTS* vde = (VOLUME_DISK_EXTENTS*)&vde_buffer; @@ -1899,7 +1900,7 @@ static int devtree(const char* name, const char* custom, const char* wfile, devi DWORD i; /* open the volume */ - h = CreateFileW(convert(wfile), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + h = CreateFileW(convert(conv_buf, wfile), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if (h == INVALID_HANDLE_VALUE) { windows_errno(GetLastError()); return -1; @@ -2024,18 +2025,19 @@ static int smartctl_scan(FILE* f, tommy_list* list) */ static int devscan(tommy_list* list) { + char conv_buf[CONV_MAX]; WCHAR cmd[MAX_PATH + 128]; FILE* f; int ret; snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" --scan-open -d pd", exedir); - log_tag("smartctl:scan::run: %s\n", u16tou8(cmd)); + log_tag("smartctl:scan::run: %s\n", u16tou8(conv_buf, cmd)); f = _wpopen(cmd, L"rt"); if (!f) { /* LCOV_EXCL_START */ - log_fatal("Failed to run '%s' (from popen).\n", u16tou8(cmd)); + log_fatal("Failed to run '%s' (from popen).\n", u16tou8(conv_buf, cmd)); return -1; /* LCOV_EXCL_STOP */ } @@ -2053,13 +2055,13 @@ static int devscan(tommy_list* list) if (ret == -1) { /* LCOV_EXCL_START */ - log_fatal("Failed to run '%s' (from pclose).\n", u16tou8(cmd)); + log_fatal("Failed to run '%s' (from pclose).\n", u16tou8(conv_buf, cmd)); return -1; /* LCOV_EXCL_STOP */ } if (ret != 0) { /* LCOV_EXCL_START */ - log_fatal("Failed to run '%s' with return code %xh.\n", u16tou8(cmd), ret); + log_fatal("Failed to run '%s' with return code %xh.\n", u16tou8(conv_buf, cmd), ret); return -1; /* LCOV_EXCL_STOP */ } @@ -2072,6 +2074,7 @@ static int devscan(tommy_list* list) */ static int devsmart(uint64_t device, const char* name, const char* custom, uint64_t* smart, char* serial) { + char conv_buf[CONV_MAX]; WCHAR cmd[MAX_PATH + 128]; char file[128]; FILE* f; @@ -2092,12 +2095,12 @@ static int devsmart(uint64_t device, const char* name, const char* custom, uint6 count = 0; retry: - log_tag("smartctl:%s:%s:run: %s\n", file, name, u16tou8(cmd)); + log_tag("smartctl:%s:%s:run: %s\n", file, name, u16tou8(conv_buf, cmd)); f = _wpopen(cmd, L"rt"); if (!f) { /* LCOV_EXCL_START */ - log_fatal("Failed to run '%s' (from popen).\n", u16tou8(cmd)); + log_fatal("Failed to run '%s' (from popen).\n", u16tou8(conv_buf, cmd)); return -1; /* LCOV_EXCL_STOP */ } @@ -2115,7 +2118,7 @@ retry: if (ret == -1) { /* LCOV_EXCL_START */ - log_fatal("Failed to run '%s' (from pclose).\n", u16tou8(cmd)); + log_fatal("Failed to run '%s' (from pclose).\n", u16tou8(conv_buf, cmd)); return -1; /* LCOV_EXCL_STOP */ } @@ -2157,6 +2160,7 @@ retry: */ static int devdown(uint64_t device, const char* name, const char* custom) { + char conv_buf[CONV_MAX]; WCHAR cmd[MAX_PATH + 128]; char file[128]; FILE* f; @@ -2177,12 +2181,12 @@ static int devdown(uint64_t device, const char* name, const char* custom) count = 0; retry: - log_tag("smartctl:%s:%s:run: %s\n", file, name, u16tou8(cmd)); + log_tag("smartctl:%s:%s:run: %s\n", file, name, u16tou8(conv_buf, cmd)); f = _wpopen(cmd, L"rt"); if (!f) { /* LCOV_EXCL_START */ - log_fatal("Failed to run '%s' (from popen).\n", u16tou8(cmd)); + log_fatal("Failed to run '%s' (from popen).\n", u16tou8(conv_buf, cmd)); return -1; /* LCOV_EXCL_STOP */ } @@ -2200,7 +2204,7 @@ retry: if (ret == -1) { /* LCOV_EXCL_START */ - log_fatal("Failed to run '%s' (from pclose).\n", u16tou8(cmd)); + log_fatal("Failed to run '%s' (from pclose).\n", u16tou8(conv_buf, cmd)); return -1; /* LCOV_EXCL_STOP */ } @@ -2226,7 +2230,7 @@ retry: if (ret != 0) { /* LCOV_EXCL_START */ - log_fatal("Failed to run '%s' with return code %xh.\n", u16tou8(cmd), ret); + log_fatal("Failed to run '%s' with return code %xh.\n", u16tou8(conv_buf, cmd), ret); return -1; /* LCOV_EXCL_STOP */ } @@ -2242,6 +2246,7 @@ retry: */ static int devup(const char* mount) { + wchar_t conv_buf[CONV_MAX]; int f; char path[PATH_MAX]; @@ -2249,7 +2254,7 @@ static int devup(const char* mount) pathprint(path, sizeof(path), "%s.snapraid-spinup.tmp", mount); /* create a temporary file, automatically deleted on close */ - f = _wopen(convert(path), _O_CREAT | _O_TEMPORARY | _O_RDWR, _S_IREAD | _S_IWRITE); + f = _wopen(convert(conv_buf, path), _O_CREAT | _O_TEMPORARY | _O_RDWR, _S_IREAD | _S_IWRITE); if (f != -1) close(f);