Home | History | Annotate | Download | only in libFLAC
      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