Share UTF-8 Windows path conversion with file workers

This commit is contained in:
evgeny committed 2026-10-22 10:18:22 +02:00
1 parent 3100985e4c
commit 85d96fc857
2 files changed
+11 -6

No files matched your search

+6 -6
View File
@@ -8,7 +8,7 @@
#ifdef _WIN32
/* Общие пути API — UTF-8; ANSI Win32 API не применяется. */
static int file_wide(const char *path, wchar_t wide[FILE_IO_PATH_MAX]) {
int file_io_wide(const char *path, wchar_t wide[FILE_IO_PATH_MAX]) {
if (path && *path && strlen(path) < FILE_IO_PATH_MAX
&& MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, -1, wide, FILE_IO_PATH_MAX)) return 0;
DEBUG_ERROR(DEBUG_CATEGORY_SYS, "file invalid UTF-8/oversized path winerr=%lu", GetLastError());
@@ -23,7 +23,7 @@ int file_io_inspect(const char *path, int follow, struct file_io_info *info) {
struct file_io_info result = {0};
#ifdef _WIN32
wchar_t wide[FILE_IO_PATH_MAX];
if (file_wide(path, wide)) return -1;
if (file_io_wide(path, wide)) return -1;
DWORD attributes = GetFileAttributesW(wide);
if (attributes == INVALID_FILE_ATTRIBUTES) {
DWORD error = GetLastError();
@@ -74,7 +74,7 @@ FILE *file_io_open_read(const char *path) {
}
#ifdef _WIN32
wchar_t wide[FILE_IO_PATH_MAX];
if (file_wide(path, wide)) return NULL;
if (file_io_wide(path, wide)) return NULL;
FILE *file = _wfopen(wide, L"rb");
#else
FILE *file = fopen(path, "rb");
@@ -109,7 +109,7 @@ int file_io_temp_open(struct file_io_temp *output, const char *destination) {
snprintf(output->temporary, sizeof(output->temporary), "%s.tmp.%s", destination, suffix);
#ifdef _WIN32
wchar_t wide[FILE_IO_PATH_MAX];
if (file_wide(output->temporary, wide)) { output->temporary[0] = 0; return -1; }
if (file_io_wide(output->temporary, wide)) { output->temporary[0] = 0; return -1; }
int fd = _wopen(wide, _O_CREAT | _O_EXCL | _O_RDWR | _O_BINARY, _S_IREAD | _S_IWRITE);
#else
int fd = open(output->temporary, O_CREAT | O_EXCL | O_RDWR, 0600);
@@ -151,7 +151,7 @@ void file_io_temp_discard(struct file_io_temp *output) {
if (!output->temporary[0]) return;
#ifdef _WIN32
wchar_t wide[FILE_IO_PATH_MAX];
int error = file_wide(output->temporary, wide) ? -1 : _wremove(wide);
int error = file_io_wide(output->temporary, wide) ? -1 : _wremove(wide);
#else
int error = remove(output->temporary);
#endif
@@ -165,7 +165,7 @@ int file_io_temp_publish(struct file_io_temp *output, const char *source, const
}
#ifdef _WIN32
wchar_t from[FILE_IO_PATH_MAX], to[FILE_IO_PATH_MAX];
if (file_wide(output->temporary, from) || file_wide(destination, to)) return -1;
if (file_io_wide(output->temporary, from) || file_io_wide(destination, to)) return -1;
if (!MoveFileExW(from, to, MOVEFILE_REPLACE_EXISTING)) {
DEBUG_ERROR(DEBUG_CATEGORY_SYS, "file publish failed destination=%s winerr=%lu", destination, GetLastError()); return -1;
}
+5
View File
@@ -7,6 +7,7 @@
#define FILE_IO_H
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#define FILE_IO_PATH_MAX 4096
enum file_io_type { FILE_IO_REGULAR = 1, FILE_IO_DIRECTORY, FILE_IO_LINK, FILE_IO_OTHER };
@@ -22,6 +23,10 @@ struct file_io_temp {
// path — UTF-8; follow!=0 разрешает конечную ссылку. info обязателен, заполняется только при успехе.
int file_io_inspect(const char *path, int follow, struct file_io_info *info);
#ifdef _WIN32
// Преобразовать непустой UTF-8 путь в wide[FILE_IO_PATH_MAX]; 0/-1.
int file_io_wide(const char *path, wchar_t wide[FILE_IO_PATH_MAX]);
#endif
// Открыть обычный файл для чтения; путь UTF-8. NULL при ошибке, fclose принадлежит вызывающему.
FILE *file_io_open_read(const char *path);
// Источник должен быть regular; назначение отсутствует или regular без конечной ссылки. 1 — один файл, 0 — разные, -1 — ошибка.