mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-26 21:10:42 +00:00
util/oslib-win32: Use UTF-16 filesystem API
* Introduces qemu_fopen, qemu_access wrappers, and modifies qemu_open to support converting stored UTF-8 paths to UTF-16 to use Unicode filesystem API on Windows platform. * Migrates several native open, fopen, and access calls to their qemu_* counterparts to resolve Unicode path handling issues on Windows.
This commit is contained in:
parent
5a80cfa2d9
commit
5ae39a321a
@ -337,6 +337,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
QemuOpts *opts;
|
||||
Error *local_err = NULL;
|
||||
const char *filename;
|
||||
wchar_t *wfilename;
|
||||
bool use_aio;
|
||||
OnOffAuto locking;
|
||||
int ret;
|
||||
@ -391,9 +392,14 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", buf[0]);
|
||||
}
|
||||
|
||||
s->hfile = CreateFile(filename, access_flags,
|
||||
wfilename = g_utf8_to_utf16(filename, -1, NULL, NULL, NULL);
|
||||
if (!filename) {
|
||||
goto fail;
|
||||
}
|
||||
s->hfile = CreateFileW(wfilename, access_flags,
|
||||
FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, overlapped, NULL);
|
||||
g_free(wfilename);
|
||||
if (s->hfile == INVALID_HANDLE_VALUE) {
|
||||
int err = GetLastError();
|
||||
|
||||
@ -556,27 +562,35 @@ static int64_t raw_getlength(BlockDriverState *bs)
|
||||
|
||||
static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
|
||||
{
|
||||
typedef DWORD (WINAPI * get_compressed_t)(const char *filename,
|
||||
typedef DWORD (WINAPI * get_compressed_t)(const wchar_t *filename,
|
||||
DWORD * high);
|
||||
int64_t size = -1;
|
||||
get_compressed_t get_compressed;
|
||||
struct _stati64 st;
|
||||
const char *filename = bs->filename;
|
||||
wchar_t *wfilename = g_utf8_to_utf16(bs->filename, -1, NULL, NULL, NULL);
|
||||
if (!wfilename) {
|
||||
goto done;
|
||||
}
|
||||
/* WinNT support GetCompressedFileSize to determine allocate size */
|
||||
get_compressed =
|
||||
(get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"),
|
||||
"GetCompressedFileSizeA");
|
||||
"GetCompressedFileSizeW");
|
||||
if (get_compressed) {
|
||||
DWORD high, low;
|
||||
low = get_compressed(filename, &high);
|
||||
low = get_compressed(wfilename, &high);
|
||||
if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR) {
|
||||
return (((int64_t) high) << 32) + low;
|
||||
size = (((int64_t) high) << 32) + low;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (_stati64(filename, &st) < 0) {
|
||||
return -1;
|
||||
if (_wstati64(wfilename, &st) >= 0) {
|
||||
size = st.st_size;
|
||||
}
|
||||
return st.st_size;
|
||||
|
||||
done:
|
||||
g_free(wfilename);
|
||||
return size;
|
||||
}
|
||||
|
||||
static int raw_co_create(BlockdevCreateOptions *options, Error **errp)
|
||||
@ -752,6 +766,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
Error *local_err = NULL;
|
||||
const char *filename;
|
||||
wchar_t *wfilename;
|
||||
bool use_aio;
|
||||
|
||||
QemuOpts *opts = qemu_opts_create(&raw_runtime_opts, NULL, 0,
|
||||
@ -795,9 +810,14 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
create_flags = OPEN_EXISTING;
|
||||
|
||||
s->hfile = CreateFile(filename, access_flags,
|
||||
FILE_SHARE_READ, NULL,
|
||||
create_flags, overlapped, NULL);
|
||||
wfilename = g_utf8_to_utf16(filename, -1, NULL, NULL, NULL);
|
||||
if (!filename) {
|
||||
goto done;
|
||||
}
|
||||
s->hfile = CreateFileW(wfilename, access_flags,
|
||||
FILE_SHARE_READ, NULL,
|
||||
create_flags, overlapped, NULL);
|
||||
g_free(wfilename);
|
||||
if (s->hfile == INVALID_HANDLE_VALUE) {
|
||||
int err = GetLastError();
|
||||
|
||||
|
@ -70,7 +70,7 @@ int64_t get_image_size(const char *filename)
|
||||
{
|
||||
int fd;
|
||||
int64_t size;
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
fd = qemu_open(filename, O_RDONLY | O_BINARY, NULL);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
size = lseek(fd, 0, SEEK_END);
|
||||
@ -84,7 +84,7 @@ ssize_t load_image_size(const char *filename, void *addr, size_t size)
|
||||
int fd;
|
||||
ssize_t actsize, l = 0;
|
||||
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
fd = qemu_open(filename, O_RDONLY | O_BINARY, NULL);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -229,7 +229,7 @@ int load_aout(const char *filename, hwaddr addr, int max_sz,
|
||||
struct exec e;
|
||||
uint32_t magic;
|
||||
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
fd = qemu_open(filename, O_RDONLY | O_BINARY, NULL);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
@ -359,7 +359,7 @@ void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp)
|
||||
}
|
||||
e_ident = hdr;
|
||||
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
fd = qemu_open(filename, O_RDONLY | O_BINARY, NULL);
|
||||
if (fd < 0) {
|
||||
error_setg_errno(errp, errno, "Failed to open file: %s", filename);
|
||||
return;
|
||||
@ -456,7 +456,7 @@ int load_elf_ram_sym(const char *filename,
|
||||
int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
|
||||
uint8_t e_ident[EI_NIDENT];
|
||||
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
fd = qemu_open(filename, O_RDONLY | O_BINARY, NULL);
|
||||
if (fd < 0) {
|
||||
perror(filename);
|
||||
return -1;
|
||||
@ -613,7 +613,7 @@ static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
|
||||
int ret = -1;
|
||||
int do_uncompress = 0;
|
||||
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
fd = qemu_open(filename, O_RDONLY | O_BINARY, NULL);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
@ -962,7 +962,7 @@ int rom_add_file(const char *file, const char *fw_dir,
|
||||
rom->path = g_strdup(file);
|
||||
}
|
||||
|
||||
fd = open(rom->path, O_RDONLY | O_BINARY);
|
||||
fd = qemu_open(rom->path, O_RDONLY | O_BINARY, NULL);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Could not open option rom '%s': %s\n",
|
||||
rom->path, strerror(errno));
|
||||
|
@ -241,7 +241,7 @@ bool xbox_eeprom_generate(const char *file, XboxEEPROMVersion ver) {
|
||||
xbox_rc4_crypt(&rctx, e.confounder, 0x1C);
|
||||
|
||||
// save to file
|
||||
FILE *fd = fopen(file, "wb");
|
||||
FILE *fd = qemu_fopen(file, "wb");
|
||||
if (fd == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ static void smbus_storage_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
int fd = open(s->file, O_RDONLY | O_BINARY);
|
||||
int fd = qemu_open(s->file, O_RDONLY | O_BINARY, NULL);
|
||||
if (fd < 0) {
|
||||
error_setg(errp, "%s: file '%s' could not be opened\n",
|
||||
__func__, s->file);
|
||||
@ -109,7 +109,7 @@ static int smbus_storage_write_data(SMBusDevice *dev, uint8_t *buf, uint8_t len)
|
||||
}
|
||||
|
||||
if (changed && s->file && s->persist) {
|
||||
int fd = open(s->file, O_WRONLY | O_BINARY);
|
||||
int fd = qemu_open(s->file, O_WRONLY | O_BINARY, NULL);
|
||||
if (fd < 0) {
|
||||
DPRINTF("%s: file '%s' could not be opened\n", __func__, s->file);
|
||||
return -1;
|
||||
|
@ -87,7 +87,7 @@ static void xbox_flash_init(MachineState *ms, MemoryRegion *rom_memory)
|
||||
if (!failed_to_load_bios && (filename != NULL)) {
|
||||
/* Read BIOS ROM into memory */
|
||||
failed_to_load_bios = 1;
|
||||
int fd = open(filename, O_RDONLY | O_BINARY);
|
||||
int fd = qemu_open(filename, O_RDONLY | O_BINARY, NULL);
|
||||
if (fd >= 0) {
|
||||
int rc = read(fd, bios_data, bios_size);
|
||||
if (rc == bios_size) {
|
||||
@ -156,7 +156,7 @@ static void xbox_flash_init(MachineState *ms, MemoryRegion *rom_memory)
|
||||
}
|
||||
|
||||
/* Read in MCPX ROM over last 512 bytes of BIOS data */
|
||||
int fd = open(filename, O_RDONLY | O_BINARY);
|
||||
int fd = qemu_open(filename, O_RDONLY | O_BINARY, NULL);
|
||||
assert(fd >= 0);
|
||||
int rc = read(fd, bios_data + bios_size - bootrom_size, bootrom_size);
|
||||
assert(rc == bootrom_size);
|
||||
|
@ -593,6 +593,21 @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive);
|
||||
bool qemu_has_ofd_lock(void);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
FILE *qemu_fopen(const char *filename, const char *mode);
|
||||
int qemu_access(const char *pathname, int mode);
|
||||
#else
|
||||
static inline FILE *qemu_fopen(const char *filename, const char *mode)
|
||||
{
|
||||
return fopen(filename, mode);
|
||||
}
|
||||
|
||||
static inline int qemu_access(const char *pathname, int mode)
|
||||
{
|
||||
return access(pathname, mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__HAIKU__) && defined(__i386__)
|
||||
#define FMT_pid "%ld"
|
||||
#elif defined(WIN64)
|
||||
|
@ -38,7 +38,7 @@ char *qemu_find_file(int type, const char *name)
|
||||
char *buf;
|
||||
|
||||
/* Try the name as a straight path first */
|
||||
if (access(name, R_OK) == 0) {
|
||||
if (qemu_access(name, R_OK) == 0) {
|
||||
trace_load_file(name, name);
|
||||
return g_strdup(name);
|
||||
}
|
||||
@ -56,7 +56,7 @@ char *qemu_find_file(int type, const char *name)
|
||||
|
||||
for (i = 0; i < data_dir_idx; i++) {
|
||||
buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name);
|
||||
if (access(buf, R_OK) == 0) {
|
||||
if (qemu_access(buf, R_OK) == 0) {
|
||||
trace_load_file(name, buf);
|
||||
return buf;
|
||||
}
|
||||
|
@ -2436,7 +2436,7 @@ static void create_default_memdev(MachineState *ms, const char *path)
|
||||
/* Return 1 if file fails to open */
|
||||
static int xemu_check_file(const char *path)
|
||||
{
|
||||
FILE *fd = fopen(path, "rb");
|
||||
FILE *fd = qemu_fopen(path, "rb");
|
||||
if (fd == NULL) {
|
||||
return 1;
|
||||
}
|
||||
@ -3768,7 +3768,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||
if (strcmp(optarg, "-") == 0) {
|
||||
fp = stdout;
|
||||
} else {
|
||||
fp = fopen(optarg, "w");
|
||||
fp = qemu_fopen(optarg, "w");
|
||||
if (fp == NULL) {
|
||||
error_report("open %s: %s", optarg,
|
||||
strerror(errno));
|
||||
@ -3856,7 +3856,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||
"option may be given");
|
||||
exit(1);
|
||||
}
|
||||
vmstate_dump_file = fopen(optarg, "w");
|
||||
vmstate_dump_file = qemu_fopen(optarg, "w");
|
||||
if (vmstate_dump_file == NULL) {
|
||||
error_report("open %s: %s", optarg, strerror(errno));
|
||||
exit(1);
|
||||
|
@ -18,6 +18,7 @@ https://github.com/benhoyt/inih
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "ini.h"
|
||||
|
||||
@ -238,7 +239,7 @@ int ini_parse(const char* filename, ini_handler handler, void* user)
|
||||
FILE* file;
|
||||
int error;
|
||||
|
||||
file = fopen(filename, "r");
|
||||
file = qemu_fopen(filename, "r");
|
||||
if (!file)
|
||||
return -1;
|
||||
error = ini_parse_file(file, handler, user);
|
||||
|
@ -164,48 +164,91 @@ const char *noc_file_dialog_open(int flags,
|
||||
|
||||
#include <windows.h>
|
||||
#include <commdlg.h>
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
const char *noc_file_dialog_open(int flags,
|
||||
const char *filters,
|
||||
const char *default_path,
|
||||
const char *default_name)
|
||||
{
|
||||
OPENFILENAME ofn; // common dialog box structure
|
||||
char szFile[_MAX_PATH]; // buffer for file name
|
||||
char initialDir[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
int ret;
|
||||
OPENFILENAMEW ofn; // common dialog box structure
|
||||
wchar_t szFile[_MAX_PATH]; // buffer for file name
|
||||
wchar_t initialDir[_MAX_PATH];
|
||||
wchar_t drive[_MAX_DRIVE];
|
||||
wchar_t dir[_MAX_DIR];
|
||||
wchar_t fname[_MAX_FNAME];
|
||||
wchar_t ext[_MAX_EXT];
|
||||
int ret = 0;
|
||||
wchar_t *wfilters = NULL;
|
||||
wchar_t *wdefault_path = NULL;
|
||||
wchar_t *wdefault_name = NULL;
|
||||
size_t filters_length = 0;
|
||||
|
||||
if (filters) {
|
||||
// 'filters' is a null-terminated list of null-terminated strings,
|
||||
// so the buffer length must be provided explicitly
|
||||
while (filters[filters_length]) {
|
||||
filters_length += strlen(filters + filters_length) + 1;
|
||||
}
|
||||
wfilters = (wchar_t*)g_convert(filters, filters_length + 1, "UTF-16", "UTF-8", NULL, NULL, NULL);
|
||||
if (!wfilters) {
|
||||
fprintf(stderr, "Failed to convert UTF-8 string to UTF-16\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (default_path) {
|
||||
wdefault_path = g_utf8_to_utf16(default_path, -1, NULL, NULL, NULL);
|
||||
if (!wdefault_path) {
|
||||
fprintf(stderr, "Failed to convert UTF-8 string to UTF-16\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (default_name) {
|
||||
wdefault_name = g_utf8_to_utf16(default_name, -1, NULL, NULL, NULL);
|
||||
if (!wdefault_name) {
|
||||
fprintf(stderr, "Failed to convert UTF-8 string to UTF-16\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
// init default dir and file name
|
||||
_splitpath_s(default_path, drive, _MAX_DRIVE, dir, _MAX_DIR, fname,
|
||||
_MAX_FNAME, ext, _MAX_EXT );
|
||||
_makepath_s(initialDir, _MAX_PATH, drive, dir, NULL, NULL);
|
||||
if (default_name)
|
||||
strncpy(szFile, default_name, sizeof(szFile) - 1);
|
||||
_wsplitpath_s(wdefault_path, drive, G_N_ELEMENTS(drive), dir, G_N_ELEMENTS(dir), fname,
|
||||
G_N_ELEMENTS(fname), ext, G_N_ELEMENTS(ext) );
|
||||
_wmakepath_s(initialDir, G_N_ELEMENTS(initialDir), drive, dir, NULL, NULL);
|
||||
if (wdefault_name)
|
||||
wcscpy_s(szFile, G_N_ELEMENTS(szFile), wdefault_name);
|
||||
else
|
||||
_makepath_s(szFile, _MAX_PATH, NULL, NULL, fname, ext);
|
||||
_wmakepath_s(szFile, G_N_ELEMENTS(szFile), NULL, NULL, fname, ext);
|
||||
|
||||
ZeroMemory(&ofn, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.nMaxFile = sizeof(szFile);
|
||||
ofn.lpstrFilter = filters;
|
||||
ofn.nMaxFile = G_N_ELEMENTS(szFile);
|
||||
ofn.lpstrFilter = wfilters;
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFileTitle = NULL;
|
||||
ofn.nMaxFileTitle = 0;
|
||||
ofn.lpstrInitialDir = initialDir;
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
|
||||
|
||||
if (flags & NOC_FILE_DIALOG_OPEN)
|
||||
ret = GetOpenFileName(&ofn);
|
||||
else
|
||||
ret = GetSaveFileName(&ofn);
|
||||
if (flags & NOC_FILE_DIALOG_OPEN) {
|
||||
ret = GetOpenFileNameW(&ofn);
|
||||
} else {
|
||||
ret = GetSaveFileNameW(&ofn);
|
||||
}
|
||||
|
||||
free(g_noc_file_dialog_ret);
|
||||
g_noc_file_dialog_ret = ret ? strdup(szFile) : NULL;
|
||||
done:
|
||||
g_free(wdefault_name);
|
||||
g_free(wdefault_path);
|
||||
g_free(wfilters);
|
||||
|
||||
g_free(g_noc_file_dialog_ret);
|
||||
if (ret) {
|
||||
g_noc_file_dialog_ret = g_utf16_to_utf8(szFile, -1, NULL, NULL, NULL);
|
||||
} else {
|
||||
g_noc_file_dialog_ret = NULL;
|
||||
}
|
||||
return g_noc_file_dialog_ret;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <stdlib.h>
|
||||
#include <SDL_filesystem.h>
|
||||
#include <string.h>
|
||||
@ -208,7 +209,7 @@ static bool xemu_settings_detect_portable_mode(void)
|
||||
bool val = false;
|
||||
char *portable_path = g_strdup_printf("%s%s", SDL_GetBasePath(), filename);
|
||||
FILE *tmpfile;
|
||||
if ((tmpfile = fopen(portable_path, "r"))) {
|
||||
if ((tmpfile = qemu_fopen(portable_path, "r"))) {
|
||||
fclose(tmpfile);
|
||||
val = true;
|
||||
}
|
||||
@ -392,7 +393,7 @@ void xemu_settings_load(void)
|
||||
|
||||
int xemu_settings_save(void)
|
||||
{
|
||||
FILE *fd = fopen(xemu_settings_get_path(), "wb");
|
||||
FILE *fd = qemu_fopen(xemu_settings_get_path(), "wb");
|
||||
assert(fd != NULL);
|
||||
|
||||
const char *last_section = "";
|
||||
|
20
util/osdep.c
20
util/osdep.c
@ -289,13 +289,29 @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int qemu_open_cloexec_internal(const char *name, int flags, mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
#ifdef _WIN32
|
||||
wchar_t *wname = g_utf8_to_utf16(name, -1, NULL, NULL, NULL);
|
||||
if (!wname) {
|
||||
return -1;
|
||||
}
|
||||
ret = _wopen(wname, flags, mode);
|
||||
g_free(wname);
|
||||
#else
|
||||
ret = open(name, flags, mode);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qemu_open_cloexec(const char *name, int flags, mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
#ifdef O_CLOEXEC
|
||||
ret = open(name, flags | O_CLOEXEC, mode);
|
||||
ret = qemu_open_cloexec_internal(name, flags | O_CLOEXEC, mode);
|
||||
#else
|
||||
ret = open(name, flags, mode);
|
||||
ret = qemu_open_cloexec_internal(name, flags, mode);
|
||||
if (ret >= 0) {
|
||||
qemu_set_cloexec(ret);
|
||||
}
|
||||
|
@ -294,17 +294,28 @@ char *
|
||||
qemu_get_local_state_pathname(const char *relative_pathname)
|
||||
{
|
||||
HRESULT result;
|
||||
char base_path[MAX_PATH+1] = "";
|
||||
char *ret;
|
||||
wchar_t wbase_path[MAX_PATH];
|
||||
char *base_path;
|
||||
|
||||
result = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL,
|
||||
/* SHGFP_TYPE_CURRENT */ 0, base_path);
|
||||
result = SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL,
|
||||
/* SHGFP_TYPE_CURRENT */ 0, wbase_path);
|
||||
if (result != S_OK) {
|
||||
/* misconfigured environment */
|
||||
g_critical("CSIDL_COMMON_APPDATA unavailable: %ld", (long)result);
|
||||
abort();
|
||||
}
|
||||
return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", base_path,
|
||||
base_path = g_utf16_to_utf8(wbase_path, -1, NULL, NULL, NULL);
|
||||
if (!base_path) {
|
||||
g_critical("Failed to convert local_state_pathname to UTF-8");
|
||||
abort();
|
||||
}
|
||||
|
||||
ret = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", base_path,
|
||||
relative_pathname);
|
||||
g_free(base_path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void qemu_set_tty_echo(int fd, bool echo)
|
||||
@ -331,27 +342,27 @@ static const char *exec_dir;
|
||||
void qemu_init_exec_dir(const char *argv0)
|
||||
{
|
||||
|
||||
char *p;
|
||||
char buf[MAX_PATH];
|
||||
wchar_t *p;
|
||||
wchar_t buf[MAX_PATH];
|
||||
DWORD len;
|
||||
|
||||
if (exec_dir) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
|
||||
len = GetModuleFileNameW(NULL, buf, G_N_ELEMENTS(buf) - 1);
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
buf[len] = 0;
|
||||
p = buf + len - 1;
|
||||
while (p != buf && *p != '\\') {
|
||||
while (p != buf && *p != L'\\') {
|
||||
p--;
|
||||
}
|
||||
*p = 0;
|
||||
if (access(buf, R_OK) == 0) {
|
||||
exec_dir = g_strdup(buf);
|
||||
if (_waccess(buf, R_OK) == 0) {
|
||||
exec_dir = g_utf16_to_utf8(buf, -1, NULL, NULL, NULL);
|
||||
} else {
|
||||
exec_dir = CONFIG_BINDIR;
|
||||
}
|
||||
@ -813,11 +824,19 @@ bool qemu_write_pidfile(const char *filename, Error **errp)
|
||||
HANDLE file;
|
||||
OVERLAPPED overlap;
|
||||
BOOL ret;
|
||||
wchar_t *wfilename;
|
||||
memset(&overlap, 0, sizeof(overlap));
|
||||
|
||||
file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
wfilename = g_utf8_to_utf16(filename, -1, NULL, NULL, NULL);
|
||||
if (!wfilename) {
|
||||
error_setg(errp, "Failed to convert PID file's filename");
|
||||
return false;
|
||||
}
|
||||
|
||||
file = CreateFileW(wfilename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
g_free(wfilename);
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
error_setg(errp, "Failed to create PID file");
|
||||
return false;
|
||||
@ -856,3 +875,44 @@ size_t qemu_get_host_physmem(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE *qemu_fopen(const char *filename, const char *mode)
|
||||
{
|
||||
wchar_t *wfilename;
|
||||
wchar_t *wmode = NULL;
|
||||
FILE *file = NULL;
|
||||
|
||||
wfilename = g_utf8_to_utf16(filename, -1, NULL, NULL, NULL);
|
||||
if (!wfilename) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
wmode = g_utf8_to_utf16(mode, -1, NULL, NULL, NULL);
|
||||
if (!wmode) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
file = _wfopen(wfilename, wmode);
|
||||
|
||||
done:
|
||||
g_free(wfilename);
|
||||
g_free(wmode);
|
||||
return file;
|
||||
}
|
||||
|
||||
int qemu_access(const char *pathname, int mode)
|
||||
{
|
||||
wchar_t *wpathname;
|
||||
int ret = -1;
|
||||
|
||||
wpathname = g_utf8_to_utf16(pathname, -1, NULL, NULL, NULL);
|
||||
if (!wpathname) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = _waccess(wpathname, mode);
|
||||
|
||||
done:
|
||||
g_free(wpathname);
|
||||
return ret;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ const char *path(const char *name)
|
||||
char *full = g_build_filename(base, name, NULL);
|
||||
|
||||
/* Look for the path; record the result, pass or fail. */
|
||||
if (access(full, F_OK) == 0) {
|
||||
if (qemu_access(full, F_OK) == 0) {
|
||||
/* Exists. */
|
||||
g_hash_table_insert(hash, save, full);
|
||||
ret = full;
|
||||
|
@ -452,7 +452,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error *
|
||||
|
||||
int qemu_read_config_file(const char *filename, QEMUConfigCB *cb, Error **errp)
|
||||
{
|
||||
FILE *f = fopen(filename, "r");
|
||||
FILE *f = qemu_fopen(filename, "r");
|
||||
int ret;
|
||||
|
||||
if (f == NULL) {
|
||||
|
Loading…
Reference in New Issue
Block a user