Erik de Castro Lopo | b1982fb | 2013-05-25 17:11:19 +1000 | [diff] [blame] | 1 | /* libFLAC - Free Lossless Audio Codec library |
Erik de Castro Lopo | 39d9791 | 2014-11-25 20:02:22 +1100 | [diff] [blame] | 2 | * Copyright (C) 2013-2014 Xiph.Org Foundation |
Erik de Castro Lopo | b1982fb | 2013-05-25 17:11:19 +1000 | [diff] [blame] | 3 | * |
| 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions |
| 6 | * are met: |
| 7 | * |
| 8 | * - Redistributions of source code must retain the above copyright |
| 9 | * notice, this list of conditions and the following disclaimer. |
| 10 | * |
| 11 | * - Redistributions in binary form must reproduce the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer in the |
| 13 | * documentation and/or other materials provided with the distribution. |
| 14 | * |
| 15 | * - Neither the name of the Xiph.org Foundation nor the names of its |
| 16 | * contributors may be used to endorse or promote products derived from |
| 17 | * this software without specific prior written permission. |
| 18 | * |
| 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR |
| 23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 24 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 26 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| 27 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | */ |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 31 | |
Erik de Castro Lopo | 006b835 | 2014-03-23 21:59:46 +1100 | [diff] [blame] | 32 | #ifdef HAVE_CONFIG_H |
Erik de Castro Lopo | 0b736a5 | 2013-04-21 17:19:37 +1000 | [diff] [blame] | 33 | # include <config.h> |
| 34 | #endif |
| 35 | |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 36 | #include <stdio.h> |
| 37 | #include <sys/stat.h> |
| 38 | #include <sys/utime.h> |
| 39 | #include <io.h> |
| 40 | #include <stdlib.h> |
| 41 | #include <string.h> |
| 42 | #include <stdarg.h> |
Erik de Castro Lopo | 608e246 | 2013-03-22 18:18:14 +1100 | [diff] [blame] | 43 | #include "share/win_utf8_io.h" |
| 44 | |
Erik de Castro Lopo | 1c7e3f1 | 2014-09-22 18:29:32 +1000 | [diff] [blame] | 45 | #define UTF8_BUFFER_SIZE 32768 |
| 46 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 47 | static int local_vsnprintf(char *str, size_t size, const char *fmt, va_list va) |
Erik de Castro Lopo | 1c7e3f1 | 2014-09-22 18:29:32 +1000 | [diff] [blame] | 48 | { |
| 49 | int rc; |
| 50 | |
| 51 | #if defined _MSC_VER |
| 52 | if (size == 0) |
| 53 | return 1024; |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 54 | rc = vsnprintf_s(str, size, _TRUNCATE, fmt, va); |
Erik de Castro Lopo | 1c7e3f1 | 2014-09-22 18:29:32 +1000 | [diff] [blame] | 55 | if (rc < 0) |
| 56 | rc = size - 1; |
| 57 | #elif defined __MINGW32__ |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 58 | rc = __mingw_vsnprintf(str, size, fmt, va); |
Erik de Castro Lopo | 1c7e3f1 | 2014-09-22 18:29:32 +1000 | [diff] [blame] | 59 | #else |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 60 | rc = vsnprintf(str, size, fmt, va); |
Erik de Castro Lopo | 1c7e3f1 | 2014-09-22 18:29:32 +1000 | [diff] [blame] | 61 | #endif |
| 62 | |
| 63 | return rc; |
| 64 | } |
| 65 | |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 66 | /* convert WCHAR stored Unicode string to UTF-8. Caller is responsible for freeing memory */ |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 67 | static char *utf8_from_wchar(const wchar_t *wstr) |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 68 | { |
| 69 | char *utf8str; |
| 70 | int len; |
| 71 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 72 | if (!wstr) |
| 73 | return NULL; |
| 74 | if ((len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL)) == 0) |
| 75 | return NULL; |
| 76 | if ((utf8str = (char *)malloc(len)) == NULL) |
| 77 | return NULL; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 78 | if (WideCharToMultiByte(CP_UTF8, 0, wstr, -1, utf8str, len, NULL, NULL) == 0) { |
| 79 | free(utf8str); |
| 80 | utf8str = NULL; |
| 81 | } |
| 82 | |
| 83 | return utf8str; |
| 84 | } |
| 85 | |
| 86 | /* convert UTF-8 back to WCHAR. Caller is responsible for freeing memory */ |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 87 | static wchar_t *wchar_from_utf8(const char *str) |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 88 | { |
| 89 | wchar_t *widestr; |
| 90 | int len; |
| 91 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 92 | if (!str) |
| 93 | return NULL; |
| 94 | if ((len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0)) == 0) |
| 95 | return NULL; |
| 96 | if ((widestr = (wchar_t *)malloc(len*sizeof(wchar_t))) == NULL) |
| 97 | return NULL; |
| 98 | if (MultiByteToWideChar(CP_UTF8, 0, str, -1, widestr, len) == 0) { |
| 99 | free(widestr); |
| 100 | widestr = NULL; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 101 | } |
| 102 | |
| 103 | return widestr; |
| 104 | } |
| 105 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 106 | void set_filename_utf8(int b); |
| 107 | |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 108 | /* retrieve WCHAR commandline, expand wildcards and convert everything to UTF-8 */ |
| 109 | int get_utf8_argv(int *argc, char ***argv) |
| 110 | { |
Erik de Castro Lopo | db1619d | 2014-06-28 09:17:26 +1000 | [diff] [blame] | 111 | typedef int (__cdecl *wgetmainargs_t)(int*, wchar_t***, wchar_t***, int, int*); |
| 112 | wgetmainargs_t wgetmainargs; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 113 | HMODULE handle; |
| 114 | int wargc; |
| 115 | wchar_t **wargv; |
| 116 | wchar_t **wenv; |
| 117 | char **utf8argv; |
| 118 | int ret, i; |
| 119 | |
| 120 | if ((handle = LoadLibrary("msvcrt.dll")) == NULL) return 1; |
Erik de Castro Lopo | 4f84da5 | 2015-08-09 08:45:44 +1000 | [diff] [blame] | 121 | if ((wgetmainargs = (wgetmainargs_t)GetProcAddress(handle, "__wgetmainargs")) == NULL) { |
| 122 | FreeLibrary(handle); |
| 123 | return 1; |
| 124 | } |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 125 | i = 0; |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 126 | /* when the 4th argument is 1, __wgetmainargs expands wildcards but also erroneously converts \\?\c:\path\to\file.flac to \\file.flac */ |
Erik de Castro Lopo | 4f84da5 | 2015-08-09 08:45:44 +1000 | [diff] [blame] | 127 | if (wgetmainargs(&wargc, &wargv, &wenv, 1, &i) != 0) { |
| 128 | FreeLibrary(handle); |
| 129 | return 1; |
| 130 | } |
| 131 | if ((utf8argv = (char **)calloc(wargc, sizeof(char*))) == NULL) { |
| 132 | FreeLibrary(handle); |
| 133 | return 1; |
| 134 | } |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 135 | |
Erik de Castro Lopo | 4f84da5 | 2015-08-09 08:45:44 +1000 | [diff] [blame] | 136 | ret = 0; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 137 | for (i=0; i<wargc; i++) { |
| 138 | if ((utf8argv[i] = utf8_from_wchar(wargv[i])) == NULL) { |
| 139 | ret = 1; |
| 140 | break; |
| 141 | } |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 142 | } |
| 143 | |
Erik de Castro Lopo | 4f84da5 | 2015-08-09 08:45:44 +1000 | [diff] [blame] | 144 | FreeLibrary(handle); /* do not free it when wargv or wenv are still in use */ |
Erik de Castro Lopo | 6a9a18f | 2013-04-07 13:11:19 +1000 | [diff] [blame] | 145 | |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 146 | if (ret == 0) { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 147 | set_filename_utf8(1); |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 148 | *argc = wargc; |
| 149 | *argv = utf8argv; |
| 150 | } else { |
Erik de Castro Lopo | a87019e | 2014-08-09 13:02:56 +1000 | [diff] [blame] | 151 | for (i=0; i<wargc; i++) |
| 152 | free(utf8argv[i]); |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 153 | free(utf8argv); |
| 154 | } |
| 155 | |
| 156 | return ret; |
| 157 | } |
| 158 | |
Erik de Castro Lopo | d0c219f | 2013-04-21 16:16:44 +1000 | [diff] [blame] | 159 | /* return number of characters in the UTF-8 string */ |
| 160 | size_t strlen_utf8(const char *str) |
| 161 | { |
| 162 | size_t len; |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 163 | len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); /* includes terminating null */ |
| 164 | if (len != 0) |
| 165 | return len-1; |
| 166 | else |
| 167 | return strlen(str); |
Erik de Castro Lopo | d0c219f | 2013-04-21 16:16:44 +1000 | [diff] [blame] | 168 | } |
| 169 | |
| 170 | /* get the console width in characters */ |
Erik de Castro Lopo | 0b736a5 | 2013-04-21 17:19:37 +1000 | [diff] [blame] | 171 | int win_get_console_width(void) |
Erik de Castro Lopo | d0c219f | 2013-04-21 16:16:44 +1000 | [diff] [blame] | 172 | { |
| 173 | int width = 80; |
| 174 | CONSOLE_SCREEN_BUFFER_INFO csbi; |
| 175 | HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 176 | if(hOut != INVALID_HANDLE_VALUE && hOut != NULL) |
| 177 | if (GetConsoleScreenBufferInfo(hOut, &csbi) != 0) |
| 178 | width = csbi.dwSize.X; |
Erik de Castro Lopo | d0c219f | 2013-04-21 16:16:44 +1000 | [diff] [blame] | 179 | return width; |
| 180 | } |
| 181 | |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 182 | /* print functions */ |
| 183 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 184 | static int wprint_console(FILE *stream, const wchar_t *text, size_t len) |
Erik de Castro Lopo | d0c219f | 2013-04-21 16:16:44 +1000 | [diff] [blame] | 185 | { |
Erik de Castro Lopo | d0c219f | 2013-04-21 16:16:44 +1000 | [diff] [blame] | 186 | DWORD out; |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 187 | int ret; |
| 188 | |
| 189 | do { |
| 190 | if (stream == stdout) { |
| 191 | HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); |
| 192 | if (hOut == INVALID_HANDLE_VALUE || hOut == NULL || GetFileType(hOut) != FILE_TYPE_CHAR) |
| 193 | break; |
| 194 | if (WriteConsoleW(hOut, text, len, &out, NULL) == 0) |
| 195 | return -1; |
| 196 | return out; |
| 197 | } |
| 198 | if (stream == stderr) { |
| 199 | HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE); |
| 200 | if (hErr == INVALID_HANDLE_VALUE || hErr == NULL || GetFileType(hErr) != FILE_TYPE_CHAR) |
| 201 | break; |
| 202 | if (WriteConsoleW(hErr, text, len, &out, NULL) == 0) |
| 203 | return -1; |
| 204 | return out; |
| 205 | } |
| 206 | } while(0); |
| 207 | |
| 208 | ret = fputws(text, stream); |
| 209 | if (ret < 0) |
| 210 | return ret; |
| 211 | return len; |
Erik de Castro Lopo | d0c219f | 2013-04-21 16:16:44 +1000 | [diff] [blame] | 212 | } |
| 213 | |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 214 | int printf_utf8(const char *format, ...) |
| 215 | { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 216 | int ret; |
| 217 | va_list argptr; |
| 218 | va_start(argptr, format); |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 219 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 220 | ret = vfprintf_utf8(stdout, format, argptr); |
| 221 | |
| 222 | va_end(argptr); |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 223 | |
| 224 | return ret; |
| 225 | } |
| 226 | |
| 227 | int fprintf_utf8(FILE *stream, const char *format, ...) |
| 228 | { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 229 | int ret; |
| 230 | va_list argptr; |
| 231 | va_start(argptr, format); |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 232 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 233 | ret = vfprintf_utf8(stream, format, argptr); |
| 234 | |
| 235 | va_end(argptr); |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 236 | |
| 237 | return ret; |
| 238 | } |
| 239 | |
| 240 | int vfprintf_utf8(FILE *stream, const char *format, va_list argptr) |
| 241 | { |
| 242 | char *utmp = NULL; |
| 243 | wchar_t *wout = NULL; |
| 244 | int ret = -1; |
| 245 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 246 | do { |
| 247 | if (!(utmp = (char *)malloc(UTF8_BUFFER_SIZE))) break; |
| 248 | if ((ret = local_vsnprintf(utmp, UTF8_BUFFER_SIZE, format, argptr)) <= 0) break; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 249 | if (!(wout = wchar_from_utf8(utmp))) { |
| 250 | ret = -1; |
| 251 | break; |
| 252 | } |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 253 | ret = wprint_console(stream, wout, wcslen(wout)); |
| 254 | } while(0); |
| 255 | |
| 256 | free(utmp); |
| 257 | free(wout); |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 258 | |
| 259 | return ret; |
| 260 | } |
| 261 | |
| 262 | /* file functions */ |
| 263 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 264 | static int utf8_filename = 0; |
| 265 | |
| 266 | static void set_filename_utf8(int b) |
| 267 | { |
| 268 | utf8_filename = b ? 1: 0; |
| 269 | } |
| 270 | |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 271 | FILE *fopen_utf8(const char *filename, const char *mode) |
| 272 | { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 273 | if (0 == utf8_filename) { |
| 274 | return fopen(filename, mode); |
| 275 | } else { |
| 276 | wchar_t *wname = NULL; |
| 277 | wchar_t *wmode = NULL; |
| 278 | FILE *f = NULL; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 279 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 280 | do { |
| 281 | if (!(wname = wchar_from_utf8(filename))) break; |
| 282 | if (!(wmode = wchar_from_utf8(mode))) break; |
| 283 | f = _wfopen(wname, wmode); |
| 284 | } while(0); |
| 285 | |
| 286 | free(wname); |
| 287 | free(wmode); |
| 288 | |
| 289 | return f; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 290 | } |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 291 | } |
| 292 | |
Erik de Castro Lopo | f44c353 | 2013-04-02 06:27:07 +1100 | [diff] [blame] | 293 | int _stat64_utf8(const char *path, struct __stat64 *buffer) |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 294 | { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 295 | if (0 == utf8_filename) { |
| 296 | return _stat64(path, buffer); |
| 297 | } else { |
| 298 | wchar_t *wpath; |
| 299 | int ret; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 300 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 301 | if (!(wpath = wchar_from_utf8(path))) return -1; |
| 302 | ret = _wstat64(wpath, buffer); |
| 303 | free(wpath); |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 304 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 305 | return ret; |
| 306 | } |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 307 | } |
| 308 | |
| 309 | int chmod_utf8(const char *filename, int pmode) |
| 310 | { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 311 | if (0 == utf8_filename) { |
| 312 | return _chmod(filename, pmode); |
| 313 | } else { |
| 314 | wchar_t *wname; |
| 315 | int ret; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 316 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 317 | if (!(wname = wchar_from_utf8(filename))) return -1; |
| 318 | ret = _wchmod(wname, pmode); |
| 319 | free(wname); |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 320 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 321 | return ret; |
| 322 | } |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 323 | } |
| 324 | |
| 325 | int utime_utf8(const char *filename, struct utimbuf *times) |
| 326 | { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 327 | if (0 == utf8_filename) { |
| 328 | return utime(filename, times); |
Janne Hyvärinen | e8ffe52 | 2013-04-20 12:42:24 +0300 | [diff] [blame] | 329 | } else { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 330 | wchar_t *wname; |
| 331 | struct __utimbuf64 ut; |
| 332 | int ret; |
| 333 | |
| 334 | if (!(wname = wchar_from_utf8(filename))) return -1; |
Janne Hyvärinen | e8ffe52 | 2013-04-20 12:42:24 +0300 | [diff] [blame] | 335 | ut.actime = times->actime; |
| 336 | ut.modtime = times->modtime; |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 337 | ret = _wutime64(wname, &ut); |
| 338 | free(wname); |
| 339 | |
| 340 | return ret; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 341 | } |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 342 | } |
| 343 | |
| 344 | int unlink_utf8(const char *filename) |
| 345 | { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 346 | if (0 == utf8_filename) { |
| 347 | return _unlink(filename); |
| 348 | } else { |
| 349 | wchar_t *wname; |
| 350 | int ret; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 351 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 352 | if (!(wname = wchar_from_utf8(filename))) return -1; |
| 353 | ret = _wunlink(wname); |
| 354 | free(wname); |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 355 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 356 | return ret; |
| 357 | } |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 358 | } |
| 359 | |
| 360 | int rename_utf8(const char *oldname, const char *newname) |
| 361 | { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 362 | if (0 == utf8_filename) { |
| 363 | return rename(oldname, newname); |
| 364 | } else { |
| 365 | wchar_t *wold = NULL; |
| 366 | wchar_t *wnew = NULL; |
| 367 | int ret = -1; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 368 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 369 | do { |
| 370 | if (!(wold = wchar_from_utf8(oldname))) break; |
| 371 | if (!(wnew = wchar_from_utf8(newname))) break; |
| 372 | ret = _wrename(wold, wnew); |
| 373 | } while(0); |
| 374 | |
| 375 | free(wold); |
| 376 | free(wnew); |
| 377 | |
| 378 | return ret; |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 379 | } |
Erik de Castro Lopo | 5705b4d | 2013-03-21 19:18:49 +1100 | [diff] [blame] | 380 | } |
Erik de Castro Lopo | 52fab8b | 2013-04-21 17:53:02 +1000 | [diff] [blame] | 381 | |
| 382 | HANDLE WINAPI CreateFile_utf8(const char *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) |
| 383 | { |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 384 | if (0 == utf8_filename) { |
| 385 | return CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); |
| 386 | } else { |
| 387 | wchar_t *wname; |
| 388 | HANDLE handle = INVALID_HANDLE_VALUE; |
Erik de Castro Lopo | 52fab8b | 2013-04-21 17:53:02 +1000 | [diff] [blame] | 389 | |
Erik de Castro Lopo | 7be5df6 | 2016-01-31 12:42:23 +1100 | [diff] [blame] | 390 | if ((wname = wchar_from_utf8(lpFileName)) != NULL) { |
| 391 | handle = CreateFileW(wname, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); |
| 392 | free(wname); |
| 393 | } |
| 394 | |
| 395 | return handle; |
Erik de Castro Lopo | 52fab8b | 2013-04-21 17:53:02 +1000 | [diff] [blame] | 396 | } |
Erik de Castro Lopo | 52fab8b | 2013-04-21 17:53:02 +1000 | [diff] [blame] | 397 | } |