Audacious + Windows 7 + folders with latin characters
I have several folders named with Spanish characters (like á, é, ñ, etc) like "Strauss_Así Habló Zaratustra". If I drag the folder and drop it on Audacious, a error windows appear:
"Cannot open c:\Strauss_As? Habl? Zaratrusta: Permision denied. No decoder found for file:///c:/Strauss_As%C3%AD%20Habl%C3%B3%20Zaratrusta"
On OpenSUSE, I never have had problems with this folders.
"Permission denied" doesn't sound like a problem with special characters in the filenames. Have you checked that permissions on the folders are correct?
It happens also on other versions of Windows.
Disabling File I/O plugin and using GIO plugin instead will resolve the problem.
I don't know yet if that old input plugin based on Windows API can also work.
So, apparently it looks like that the open() function on Windows does not like to receive file names encoded with something different than plain ascii.
I do not know what kind of encoding is used when feeding the file name to open(), but actually, replacing the input plugin has solved the trouble.
Perhaps there could be also some hidden troubles elsewhere... I have seen some calls to uri_to_filename() and later calls to unlink() and opendir()/readdir().
This may be not good, but I do not know if there are some replacements from GLIB to be used instead rather than calling directly system POSIX functions.
Alternatively, the open to the file could be adjusted in unix_io plugin, perhaps with something like this:
/* Convert file name encoding from original (ex: UTF-8?) to UTF-16 */
iRes = MultiByteToWideChar(CP_UTF8, ...bla ...bla);
/* Open an handle to the file */
hFile = CreateFileW(...bla ...bla);
/* Build file descriptor from the handle */
handle = _open_osfhandle((long)hFile, mode_flag);
char * filename = uri_to_filename (uri);
if (handle < 0)
and after the file descriptor has been got, all common functions for file access can be used without changing anything else.
Since I'm reading in the sources of unix_io:
"THIS PLUGIN IS REQUIRED. DO NOT DISABLE IT."
perhaps the code described above could be a solution...
It would be better to fix the root problem in the MinGW runtime rather than patching around it. Has anyone looked at how MinGW's open() handles character encodings?
Unfortunately, it really seems to me that there is no way to customize the behavior of open() function because it is provided by the shared common runtime, provided by MSVCRT.DLL
Other functions, not included into the common runtime, are provided by the components of MinGW runtime (like strcasecmp, getopt, etc) but not the open() itself.
MinGW's open() just calls Microsoft's _open(), is that what you are saying? If that's the case, I'd check that the system locale (i.e. the one used for the "multibyte character set" versions of Windows API functions) is set to something that can handle Spanish characters.
Ok, I tried to do some quick debugging at lunch time and I understood the cause of the problem.
I did a simple 10 lines source code that opens the file "d:\Strauss_Así Habló Zaratustra\a.txt" successfully, so it is not a problem of encoding or locale tables.
In reality, in unix_io, the open() function fails because the plugin tries to call it with the name of a directory instead of a name of a file.
Infact, the parameter received by unix_fopen is:
0066(f) 0069(i) 006C(l) 0065(e) 003A(:) 002F(/) 002F(/) 002F(/) 0044(D) 003A(:)
002F(/) 0053(S) 0074(t) 0072(r) 0061(a) 0075(u) 0073(s) 0073(s) 005F(_) 0041(A)
0073(s) 0025() 0043(C) 0033(3) 0025() 0041(A) 0044(D) 0025() 0032(2) 0030(0)
0048(H) 0061(a) 0062(b) 006C(l) 0025() 0043(C) 0033(3) 0025() 0042(B) 0033(3)
0025() 0032(2) 0030(0) 005A(Z) 0061(a) 0072(r) 0061(a) 0074(t) 0075(u) 0073(s)
0074(t) 0072(r) 0061(a)
and later converted to:
0044(D) 003A(:) 005C(\) 0053(S) 0074(t) 0072(r) 0061(a) 0075(u) 0073(s) 0073(s)
005F(_) 0041(A) 0073(s) FFED 0020( ) 0048(H) 0061(a) 0062(b) 006C(l) FFF3
0020( ) 005A(Z) 0061(a) 0072(r) 0061(a) 0074(t) 0075(u) 0073(s) 0074(t) 0072(r)
but feeding this path name to open() or _open() will never result to a success.
Only a name of a file can be used, a directory cannot be open in that manner.
I do not know how and why this is happening, or if this is an expected action when dragging a directory in the window of Audacious.
Actually, CreateFile() may be used to get an handle to a directory by using FILE_FLAG_BACKUP_SEMANTICS flag, but evidently this is not an expected behavior in the source code of open().
This was also quite evident in the very first message, but unfortunately it escaped to our attention...
You're right, the "no decoder found" for a folder should have stood out as odd, but I overlooked it. I think the problem may be that we are using g_file_test() to check for a folder, but g_file_test() expects UTF-8 on Windows (and only on Windows -- go figure). I banged out a replacement vfs_file_test() that calls stat() directly instead of going through g_file_test(). Can you see if the attached patch fixes the problem?
aud.diff - Reimplement vfs_file_test (1.2 kB)
Hello, I tried your patch.
Does it fix the problem? Yes and no.
I had to remove the test on the VFS_IS_SYMLINK because Windows does not support lstat() and lstat64() and, until now, not even in the MinGW runtime. So, also the macro S_ISLNK does not exist.
At the moment, AFAIK the only way to check for a link or something like that is to call Find File APIs and check for FILE_ATTRIBUTE_REPARSE_POINT in dwFileAttributes.
Besides that, the message disappeared when dragging a directory in Audacious.
But now I'm wondering: is it worth to do this fix?
If I can say my opinion, it would be better to have the most portable code and, if we think that a defect could exist in this function called g_file_test(), we may file a bug to the bugzilla in GTK+...
Strictly speaking, there is no bug in g_file_test(). It's intentional that GLib file functions use UTF-8 on Windows. Probably they use the UTF-16 Win32 functions like CreateFileW internally. Unfortunately this behavior breaks compatibility with POSIX functions like open() and stat(), which use the system codepage. We already use many POSIX functions elsewhere, and since MinGW has fairly decent POSIX coverage, I don't think it makes sense to switch to using GLib wrappers everywhere. We can just #ifdef out the VFS_IS_SYMLINK block on Windows. g_file_test() doesn't handle symlinks on Windows, either, for that matter.