windows_unicode_filenames.c (4548B)
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 _WIN32 33 34 #define WIN32_MEAN_AND_LEAN 35 #include <io.h> 36 #include <windows.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 wname = wchar_from_utf8(filename); 86 if (!wname) break; 87 wmode = wchar_from_utf8(mode); 88 if (!wmode) break; 89 f = _wfopen(wname, wmode); 90 } while(0); 91 92 free(wname); 93 free(wmode); 94 95 return f; 96 } 97 } 98 99 int flac_internal_stat64_utf8(const char *path, struct __stat64 *buffer) 100 { 101 if (!utf8_filenames) { 102 return _stat64(path, buffer); 103 } else { 104 wchar_t *wpath; 105 int ret; 106 107 wpath = wchar_from_utf8(path); 108 if (!wpath) return -1; 109 ret = _wstat64(wpath, buffer); 110 free(wpath); 111 112 return ret; 113 } 114 } 115 116 int flac_internal_chmod_utf8(const char *filename, int pmode) 117 { 118 if (!utf8_filenames) { 119 return _chmod(filename, pmode); 120 } else { 121 wchar_t *wname; 122 int ret; 123 124 wname = wchar_from_utf8(filename); 125 if (!wname) return -1; 126 ret = _wchmod(wname, pmode); 127 free(wname); 128 129 return ret; 130 } 131 } 132 133 int flac_internal_utime_utf8(const char *filename, struct utimbuf *times) 134 { 135 if (!utf8_filenames) { 136 return utime(filename, times); 137 } else { 138 wchar_t *wname; 139 struct __utimbuf64 ut; 140 int ret; 141 142 wname = wchar_from_utf8(filename); 143 if (!wname) return -1; 144 ut.actime = times->actime; 145 ut.modtime = times->modtime; 146 ret = _wutime64(wname, &ut); 147 free(wname); 148 149 return ret; 150 } 151 } 152 153 int flac_internal_unlink_utf8(const char *filename) 154 { 155 if (!utf8_filenames) { 156 return _unlink(filename); 157 } else { 158 wchar_t *wname; 159 int ret; 160 161 wname = wchar_from_utf8(filename); 162 if (!wname) return -1; 163 ret = _wunlink(wname); 164 free(wname); 165 166 return ret; 167 } 168 } 169 170 int flac_internal_rename_utf8(const char *oldname, const char *newname) 171 { 172 if (!utf8_filenames) { 173 return rename(oldname, newname); 174 } else { 175 wchar_t *wold = NULL; 176 wchar_t *wnew = NULL; 177 int ret = -1; 178 179 do { 180 wold = wchar_from_utf8(oldname); 181 if (!wold) break; 182 wnew = wchar_from_utf8(newname); 183 if (!wnew) break; 184 ret = _wrename(wold, wnew); 185 } while(0); 186 187 free(wold); 188 free(wnew); 189 190 return ret; 191 } 192 } 193 194 #endif