mirror of
https://github.com/LibreOffice/core.git
synced 2026-01-17 13:21:34 +00:00
We don't use it yet from any C source file, but the plan is to do that. Mainly from freetype, fontconfig, and cairo, when these are built for Windows when the --enable-headless options is used (for the new Collabora Office). Also some cleanups, sorting #include lines, avoiding warnings, etc. Change-Id: Ifef3588d06fdcceaeaeb3482399737faaf558d7d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195602 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Tested-by: Jenkins
337 lines
8.5 KiB
C
337 lines
8.5 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
/* Wrappers to use Unix-style file APIs on Windows.
|
|
*
|
|
* Of course, LibreOffice has tons of APIs from before whose whole point is to hide system
|
|
* dependencies behind a cross-platform API. All the "sal" and "osl" stuff, for starters. The
|
|
* wrappers in this file is not intended to replace those. The point with these wrappers is to
|
|
* quickly port code that was written for Unix *only* to Windows, with minimal changes to the source
|
|
* code. Basically you just need to prefix calls to functions like open() and stat() with wrap_.
|
|
*
|
|
* In Windows, "file descriptors" are a thing in the C library, not the operating system. But the C
|
|
* library does provide the same core set of functionality as Unix-like systems do. The functions
|
|
* use almost the same names, except that for some reason, to avoid compilation warnings, you need
|
|
* to call variants with names preceded by an underscore, like _close().
|
|
|
|
* Another Windows complication is that the file system is based on UTF-16 names. You can't just
|
|
* pass file names as eight-bit characters to _open() and expect it to work for all file
|
|
* names. Instead, you need to call a function with a "w" prefix, like _wopen(), that takes a wide
|
|
* character string (UTF-16).
|
|
|
|
* This header is in C, not C++, because we want it to be usable from some external libraries
|
|
* written in C that we compile as part of LibreOffice in some circumstances, particularly for
|
|
* Windows.
|
|
*
|
|
* All functions behave like the wrapped ones, set errno on errors.
|
|
*/
|
|
|
|
#include <fcntl.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <wchar.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#include <io.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <Windows.h>
|
|
/* Undo the mapping in <Windows.h> of CreateFont => CreateFontW etc, as vcl also uses these
|
|
* identifiers.
|
|
*/
|
|
#undef CreateFont
|
|
#undef GetGlyphOutline
|
|
#else
|
|
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
|
|
#define MAP_FAILED ((void*)-1)
|
|
|
|
#define S_ISDIR(m) (((m)&_S_IFMT) == _S_IFDIR)
|
|
|
|
#define F_OK 00
|
|
#define W_OK 02
|
|
#define R_OK 04
|
|
#define X_OK R_OK
|
|
|
|
#define PATH_MAX MAX_PATH
|
|
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
#define UNIXWRAPPERS_H_MAYBE_UNUSED [[maybe_unused]]
|
|
#else
|
|
#define UNIXWRAPPERS_H_MAYBE_UNUSED
|
|
#endif
|
|
|
|
#ifdef __GNUC__
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
static wchar_t* string_to_wide_string(const char* string)
|
|
{
|
|
const size_t len = strlen(string);
|
|
if (len == 0)
|
|
{
|
|
return _wcsdup(L"");
|
|
}
|
|
|
|
if (len > INT_MAX)
|
|
{
|
|
/* Trying to be funny, eh? */
|
|
return _wcsdup(L"");
|
|
}
|
|
|
|
const int wlen = MultiByteToWideChar(CP_UTF8, 0, string, (int)len, NULL, 0);
|
|
if (wlen <= 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
wchar_t* result = (wchar_t*)malloc(wlen * 2 + 2);
|
|
assert(result);
|
|
MultiByteToWideChar(CP_UTF8, 0, string, (int)len, result, wlen);
|
|
result[wlen] = L'\0';
|
|
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
/* Pass in UTF-8 filename */
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static int wrap_open(const char* path, int flags, int mode)
|
|
{
|
|
#ifdef _WIN32
|
|
wchar_t* wpath = string_to_wide_string(path);
|
|
int result = _wopen(wpath, flags, mode);
|
|
free(wpath);
|
|
return result;
|
|
#else
|
|
return open(path, flags, mode);
|
|
#endif
|
|
}
|
|
|
|
#if 0
|
|
|
|
/* Pass in UTF-16 filename */
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static int wrap_wopen(const wchar_t* path, int flags, int mode)
|
|
{
|
|
#ifdef _WIN32
|
|
return _wopen(path, flags, mode);
|
|
#else
|
|
rtl_String* str;
|
|
int len = wcslen(path);
|
|
bool success = rtl_convertUStringToString(&str, path, len, RTL_TEXTENCODING_UTF8,
|
|
RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|
|
| RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR);
|
|
int result;
|
|
if (success)
|
|
{
|
|
char* spath = malloc(len + 1);
|
|
strcat(spath, str, len);
|
|
spath[len] = 0;
|
|
result = open(str->buffer, flags, path);
|
|
free(spath);
|
|
}
|
|
else
|
|
{
|
|
result = -1;
|
|
errno = EIO;
|
|
}
|
|
rtl_string_release(str);
|
|
return result;
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static int wrap_read(int fd, void* buf, int nbytes)
|
|
{
|
|
#ifdef _WIN32
|
|
return _read(fd, buf, nbytes);
|
|
#else
|
|
return read(fd, buf, nbytes);
|
|
#endif
|
|
}
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static int wrap_write(int fd, const void* buf, int nbytes)
|
|
{
|
|
#ifdef _WIN32
|
|
return _write(fd, buf, nbytes);
|
|
#else
|
|
return write(fd, buf, nbytes);
|
|
#endif
|
|
}
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static int wrap_fstat(int fd, struct stat* st)
|
|
{
|
|
#ifdef _WIN32
|
|
/* Sadly just "struct stat" in the Microsoft C library means a legacy one with 32-bit size,
|
|
* 32-bit time one. But it is a *different* type than struct _stat32, even if identical.
|
|
*/
|
|
struct _stat32 st32;
|
|
int result = _fstat32(fd, &st32);
|
|
if (result != -1)
|
|
{
|
|
st->st_dev = st32.st_dev;
|
|
st->st_ino = st32.st_ino;
|
|
st->st_mode = st32.st_mode;
|
|
st->st_nlink = st32.st_nlink;
|
|
st->st_uid = st32.st_uid;
|
|
st->st_gid = st32.st_gid;
|
|
st->st_rdev = st32.st_rdev;
|
|
st->st_size = st32.st_size;
|
|
st->st_atime = st32.st_atime;
|
|
st->st_mtime = st32.st_mtime;
|
|
st->st_ctime = st32.st_ctime;
|
|
}
|
|
return result;
|
|
#else
|
|
return fstat(fd, st);
|
|
#endif
|
|
}
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static void* wrap_mmap(int64_t size, int fd, intptr_t* handle)
|
|
{
|
|
#ifdef _WIN32
|
|
*handle = (intptr_t)CreateFileMappingW((HANDLE)_get_osfhandle(fd), NULL,
|
|
SEC_COMMIT | PAGE_READONLY, 0, 0, NULL);
|
|
return MapViewOfFile((HANDLE)*handle, FILE_MAP_READ, 0, 0, size);
|
|
#else
|
|
/* No handle needs to be stored */
|
|
(void)handle;
|
|
return mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
|
|
#endif
|
|
}
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static int wrap_munmap(void* pointer, int64_t size, intptr_t handle)
|
|
{
|
|
#ifdef _WIN32
|
|
(void)size;
|
|
CloseHandle((HANDLE)handle);
|
|
if (!UnmapViewOfFile(pointer))
|
|
{
|
|
errno = EIO;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
#else
|
|
(void)handle;
|
|
return munmap(pointer, size);
|
|
#endif
|
|
}
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static int wrap_dup(int fd)
|
|
{
|
|
#ifdef _WIN32
|
|
return _dup(fd);
|
|
#else
|
|
return dup(fd);
|
|
#endif
|
|
}
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static int wrap_close(int fd)
|
|
{
|
|
#ifdef _WIN32
|
|
return _close(fd);
|
|
#else
|
|
return close(fd);
|
|
#endif
|
|
}
|
|
|
|
/* This doesn't usea file descriptor but is related to the above functionality so keep here
|
|
* anyway.
|
|
*/
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static FILE* wrap_fopen(const char* path, const char* mode)
|
|
{
|
|
#ifdef _WIN32
|
|
wchar_t* wpath = string_to_wide_string(path);
|
|
wchar_t* wmode = string_to_wide_string(mode);
|
|
FILE* result = _wfopen(wpath, wmode);
|
|
free(wpath);
|
|
free(wmode);
|
|
return result;
|
|
#else
|
|
return fopen(path, mode);
|
|
#endif
|
|
}
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static int wrap_stat(const char* path, struct stat* st)
|
|
{
|
|
#ifdef _WIN32
|
|
struct _stat32 st32;
|
|
wchar_t* wpath = string_to_wide_string(path);
|
|
int result = _wstat32(wpath, &st32);
|
|
free(wpath);
|
|
if (result != -1)
|
|
{
|
|
st->st_dev = st32.st_dev;
|
|
st->st_ino = st32.st_ino;
|
|
st->st_mode = st32.st_mode;
|
|
st->st_nlink = st32.st_nlink;
|
|
st->st_uid = st32.st_uid;
|
|
st->st_gid = st32.st_gid;
|
|
st->st_rdev = st32.st_rdev;
|
|
st->st_size = st32.st_size;
|
|
st->st_atime = st32.st_atime;
|
|
st->st_mtime = st32.st_mtime;
|
|
st->st_ctime = st32.st_ctime;
|
|
}
|
|
return result;
|
|
#else
|
|
return stat(path, st);
|
|
#endif
|
|
}
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static int wrap_access(const char* path, int mode)
|
|
{
|
|
#ifdef _WIN32
|
|
wchar_t* wpath = string_to_wide_string(path);
|
|
int result = _waccess(wpath, mode);
|
|
free(wpath);
|
|
return result;
|
|
#else
|
|
return access(path, mode);
|
|
#endif
|
|
}
|
|
|
|
UNIXWRAPPERS_H_MAYBE_UNUSED static const char* wrap_realpath(const char* path, char* resolved_path)
|
|
{
|
|
#ifdef _WIN32
|
|
strcpy(resolved_path, path);
|
|
return resolved_path;
|
|
#else
|
|
return realpath(path, resolved_path);
|
|
#endif
|
|
}
|
|
|
|
#ifdef __GNUC__
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#undef UNIXWRAPPERS_H_MAYBE_UNUSED
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|