1 /* libFLAC - Free Lossless Audio Codec library 2 * Copyright (C) 2013-2016 Xiph.Org Foundation 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 */ 31 32 #ifdef HAVE_CONFIG_H 33 # include <config.h> 34 #endif 35 36 #include <io.h> 37 #include "share/windows_unicode_filenames.h" 38 39 /* convert UTF-8 back to WCHAR. Caller is responsible for freeing memory */ 40 static wchar_t *wchar_from_utf8(const char *str) 41 { 42 wchar_t *widestr; 43 int len; 44 45 if (!str) 46 return NULL; 47 if ((len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0)) == 0) 48 return NULL; 49 if ((widestr = (wchar_t *)malloc(len*sizeof(wchar_t))) == NULL) 50 return NULL; 51 if (MultiByteToWideChar(CP_UTF8, 0, str, -1, widestr, len) == 0) { 52 free(widestr); 53 widestr = NULL; 54 } 55 56 return widestr; 57 } 58 59 60 static FLAC__bool utf8_filenames = false; 61 62 63 void flac_internal_set_utf8_filenames(FLAC__bool flag) 64 { 65 utf8_filenames = flag ? true : false; 66 } 67 68 FLAC__bool flac_internal_get_utf8_filenames(void) 69 { 70 return utf8_filenames; 71 } 72 73 /* file functions */ 74 75 FILE* flac_internal_fopen_utf8(const char *filename, const char *mode) 76 { 77 if (!utf8_filenames) { 78 return fopen(filename, mode); 79 } else { 80 wchar_t *wname = NULL; 81 wchar_t *wmode = NULL; 82 FILE *f = NULL; 83 84 do { 85 if (!(wname = wchar_from_utf8(filename))) break; 86 if (!(wmode = wchar_from_utf8(mode))) break; 87 f = _wfopen(wname, wmode); 88 } while(0); 89 90 free(wname); 91 free(wmode); 92 93 return f; 94 } 95 } 96 97 int flac_internal_stat64_utf8(const char *path, struct __stat64 *buffer) 98 { 99 if (!utf8_filenames) { 100 return _stat64(path, buffer); 101 } else { 102 wchar_t *wpath; 103 int ret; 104 105 if (!(wpath = wchar_from_utf8(path))) return -1; 106 ret = _wstat64(wpath, buffer); 107 free(wpath); 108 109 return ret; 110 } 111 } 112 113 int flac_internal_chmod_utf8(const char *filename, int pmode) 114 { 115 if (!utf8_filenames) { 116 return _chmod(filename, pmode); 117 } else { 118 wchar_t *wname; 119 int ret; 120 121 if (!(wname = wchar_from_utf8(filename))) return -1; 122 ret = _wchmod(wname, pmode); 123 free(wname); 124 125 return ret; 126 } 127 } 128 129 int flac_internal_utime_utf8(const char *filename, struct utimbuf *times) 130 { 131 if (!utf8_filenames) { 132 return utime(filename, times); 133 } else { 134 wchar_t *wname; 135 struct __utimbuf64 ut; 136 int ret; 137 138 if (!(wname = wchar_from_utf8(filename))) return -1; 139 ut.actime = times->actime; 140 ut.modtime = times->modtime; 141 ret = _wutime64(wname, &ut); 142 free(wname); 143 144 return ret; 145 } 146 } 147 148 int flac_internal_unlink_utf8(const char *filename) 149 { 150 if (!utf8_filenames) { 151 return _unlink(filename); 152 } else { 153 wchar_t *wname; 154 int ret; 155 156 if (!(wname = wchar_from_utf8(filename))) return -1; 157 ret = _wunlink(wname); 158 free(wname); 159 160 return ret; 161 } 162 } 163 164 int flac_internal_rename_utf8(const char *oldname, const char *newname) 165 { 166 if (!utf8_filenames) { 167 return rename(oldname, newname); 168 } else { 169 wchar_t *wold = NULL; 170 wchar_t *wnew = NULL; 171 int ret = -1; 172 173 do { 174 if (!(wold = wchar_from_utf8(oldname))) break; 175 if (!(wnew = wchar_from_utf8(newname))) break; 176 ret = _wrename(wold, wnew); 177 } while(0); 178 179 free(wold); 180 free(wnew); 181 182 return ret; 183 } 184 } 185 186 HANDLE WINAPI flac_internal_CreateFile_utf8(const char *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) 187 { 188 if (!utf8_filenames) { 189 return CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 190 } else { 191 wchar_t *wname; 192 HANDLE handle = INVALID_HANDLE_VALUE; 193 194 if ((wname = wchar_from_utf8(lpFileName)) != NULL) { 195 handle = CreateFileW(wname, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 196 free(wname); 197 } 198 199 return handle; 200 } 201 } 202