diff options
author | Barton E. Schaefer <schaefer@zsh.org> | 2014-06-02 07:26:50 -0700 |
---|---|---|
committer | Barton E. Schaefer <schaefer@zsh.org> | 2014-06-02 07:26:50 -0700 |
commit | b3e5284f13162dc6941d5a5c1f2df9772eff2a8c (patch) | |
tree | 460db4a4833d36f27d1ffcb166976ff145fa161a /Src | |
parent | 09f29ef00cfc0bf69df322f77def5ddd87016eb3 (diff) | |
download | zsh-b3e5284f13162dc6941d5a5c1f2df9772eff2a8c.tar.gz zsh-b3e5284f13162dc6941d5a5c1f2df9772eff2a8c.tar.xz zsh-b3e5284f13162dc6941d5a5c1f2df9772eff2a8c.zip |
36526: when __APPLE__ is defined at compile, normalize Unicode filenames in zreaddir()
Diffstat (limited to 'Src')
-rw-r--r-- | Src/utils.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/Src/utils.c b/Src/utils.c index 943922725..8b512bbd9 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -4270,6 +4270,12 @@ mod_export char * zreaddir(DIR *dir, int ignoredots) { struct dirent *de; +#if defined(HAVE_ICONV) && defined(__APPLE__) + static iconv_t conv_ds = (iconv_t)0; + static char *conv_name = 0; + char *conv_name_ptr, *orig_name_ptr; + size_t conv_name_len, orig_name_len; +#endif do { de = readdir(dir); @@ -4278,6 +4284,31 @@ zreaddir(DIR *dir, int ignoredots) } while(ignoredots && de->d_name[0] == '.' && (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2]))); +#if defined(HAVE_ICONV) && defined(__APPLE__) + if (!conv_ds) + conv_ds = iconv_open("UTF-8", "UTF-8-MAC"); + if (conv_ds) { + /* Force initial state in case re-using conv_ds */ + (void) iconv(conv_ds, 0, &orig_name_len, 0, &conv_name_len); + + orig_name_ptr = de->d_name; + orig_name_len = strlen(de->d_name); + conv_name = zrealloc(conv_name, orig_name_len+1); + conv_name_ptr = conv_name; + conv_name_len = orig_name_len; + if (iconv(conv_ds, + &orig_name_ptr, &orig_name_len, + &conv_name_ptr, &conv_name_len) >= 0) { + if (orig_name_len == 0) { + /* Completely converted, metafy and return */ + *conv_name_ptr = '\0'; + return metafy(conv_name, -1, META_STATIC); + } + } + /* Error, or conversion incomplete, keep the original name */ + } +#endif + return metafy(de->d_name, -1, META_STATIC); } |