public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: Andy Koppe <andy.koppe@gmail.com>
To: cygwin@cygwin.com
Subject: Re: [1.7] Invalid UTF8 while creating a file -> cannot delete?
Date: Mon, 21 Sep 2009 18:54:00 -0000	[thread overview]
Message-ID: <416096c60909211154u5ddd5869v986011aa4ee13d57@mail.gmail.com> (raw)
In-Reply-To: <20090921161014.GI20981@calimero.vinschen.de>

2009/9/21 Corinna Vinschen:
>> % cat t.c
>> int main() {
>>     fopen("a-\xF6\xE4\xFC\xDF", "w"); //ISO-8859-1
>>     fopen("b-\xF6\xE4\xFC\xDFz", "w");
>>     fopen("c-\xF6\xE4\xFC\xDFzz", "w");
>>     fopen("d-\xF6\xE4\xFC\xDFzzz", "w");
>>     fopen("e-\xF6\xE4\xFC\xDF\xF6\xE4\xFC\xDF", "w");
>>     return 0;
>> }
>
> Ok, I see what happens.  The problem is that the mechanism which is
> supposed to handle invalid multibyte sequences handles the first such
> byte, but misses to reset the multibyte shift state after the byte has
> been handled.  Basically, resetting the shift state after such a
> sequence has been encountered fixes that problem.

Great!


> Unfortunately this is only the first half of a solution.  This is what
> `ls' prints after running t:
>
>  $ ls -l --show-control-chars
>  total 21
>  -rw-r--r-- 1 corinna vinschen     0 Sep 21 17:35 a-öäüß
>  -rw-r--r-- 1 corinna vinschen     0 Sep 21 17:35 c-öäüßzz
>  -rw-r--r-- 1 corinna vinschen     0 Sep 21 17:35 d-öäüßzzz
>  -rw-r--r-- 1 corinna vinschen     0 Sep 21 17:35 e-öäüßöäüß
>
> But this is what ls prints when setting $LANG to something "non-C":
>
>  $ setenv LANG en      (implies codepage 1252)
>  $ ls -l --show-control-chars
>  ls: cannot access a-öäüß: No such file or directory
>  ls: cannot access c-öäüßzz: No such file or directory
>  ls: cannot access d-öäüßzzz: No such file or directory
>  ls: cannot access e-öäüßöäüß: No such file or directory
>  total 21
>  -????????? ? ?       ?            ?                ? a-öäüß
>  -????????? ? ?       ?            ?                ? c-öäüßzz
>  -????????? ? ?       ?            ?                ? d-öäüßzzz
>  -????????? ? ?       ?            ?                ? e-öäüßöäüß

Btw, the same thing will happen with en.C-ISO-8859-1 or C.ASCII too.


> As you might know, invalid bytes >= 0x80 are translated to UTF-16 by
> transposing them into the 0xdc00 - 0xdcff range by just or'ing 0xdc00.
> The problem now is that readdir() will return the transposed characters
> as if they are the original characters.

Yep, that's where the bug is. Those 0xDC?? words represent invalid
UTF-8 bytes. They do not represent CP1252 or ISO-8859-1 characters.

Therefore, when converting a UTF-16 Windows filename to the current
charset, 0xDC?? words should be treated like any other UTF-16 word
that can't be represented in the current charset: it should be encoded
as a ^N sequence.


> ls uses some mbtowc function
> to create a valid widechar string, and then uses the resulting widechar
> string in some wctomb function to call stat().

It's not 'ls' that does that conversion. On the POSIX side, filenames
are simply sequences of bytes, hence 'ls' would be very wrong to do
any conversion between readdir() and stat().

No, it's stat() itself converting the CP1252 sequence "a-öäüß" to
UTF-16, which yields L"a-öäüß". This does not contain the 0xDC??
codepoints that the actual filename contained, hence stat() fails.


> So it looks like the current mechanism to handle invalid multibyte
> sequences is too complicated for us.  As far as I can see, it would be
> much simpler and less error prone to translate the invalid bytes simply
> to the equivalent UTF-16 value.  That creates filenames with UTF-16
> values from the ISO-8859-1 range.

This won't work correctly, because different POSIX filenames will map
to the same Windows filename. For example, the filenames "\xC3\xA4"
(valid UTF-8 for a-umlaut) and "\xC4" (invalid UTF-8 sequence that
represents a-umlaut in 8859-1), will both map to Windows filename
"U+00C4", i.e a-umlaut in UTF-16. Furthermore, after creating a file
called "\xC4", a readdir() would show that file as "\xC3\xA4".

Note also that invalid UTF-8 sequences would be much less of an issue
if the C locale didn't mix UTF-8 filenames with a ISO-8859-1 console.
They'd still occur e.g. when unpacking a tarball with ISO-encoded
filenames while a UTF-8 locale is active. However, that sort of
situation is not handled well on Linux either.

Regards,
Andy

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

  reply	other threads:[~2009-09-21 18:54 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-09-10 19:31 Lapo Luchini
2009-09-10 22:12 ` Andy Koppe
2009-09-15 22:38   ` Lapo Luchini
2009-09-21 16:10     ` Corinna Vinschen
2009-09-21 18:54       ` Andy Koppe [this message]
2009-09-22  9:45         ` Corinna Vinschen
2009-09-22 16:12           ` Andy Koppe
2009-09-22 17:07             ` Corinna Vinschen
2009-09-23 11:52               ` Andy Koppe
2009-09-23 12:02               ` Corinna Vinschen
2009-09-23 12:35                 ` Andy Koppe
2009-09-23 12:43                   ` Corinna Vinschen
2009-09-23 13:39                     ` Corinna Vinschen
2009-09-23 21:31                       ` Ross Smith
2009-09-25 22:36                         ` Robert Pendell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=416096c60909211154u5ddd5869v986011aa4ee13d57@mail.gmail.com \
    --to=andy.koppe@gmail.com \
    --cc=cygwin@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).