Busybox支持中文的解决办法

来源:互联网 发布:java heap size 编辑:程序博客网 时间:2024/06/01 09:40

在嵌入式linux系统中,busybox是最常见的用来构建文件系统的。可是从busybox1.17.0以上之后,对ls命令不做修改是无法显示中文的。就算是内核设置了支持中文的话,在shell下用ls命令也是无法显示中文的,这是因为busybox1.17.0以后版本对中文的支持进行了限制。现在就来讲讲如何修改让busybox1.17.0以上版本支持中文,要想让busybox1.17.0以上支持中文,需要修改两个文件:printable_string.c以及unicode.c 。下面来分析,为什么ls命令无法显示中文。请看printable_string.c未修改过的代码:

[cpp] view plaincopy
  1. const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str)  
  2. {  
  3.     static char *saved[4];  
  4.     static unsigned cur_saved; /* = 0 */  
  5.   
  6.     char *dst;  
  7.     const char *s;  
  8.   
  9.     s = str;  
  10.     while (1) {  
  11.         unsigned char c = *s;  
  12.         if (c == '\0') {  
  13.             /* 99+% of inputs do not need conversion */  
  14.             if (stats) {  
  15.                 stats->byte_count = (s - str);  
  16.                 stats->unicode_count = (s - str);  
  17.                 stats->unicode_width = (s - str);  
  18.             }  
  19.             return str;  
  20.         }  
  21.         if (c < ' ')  
  22.             break;  
  23.         if (c >= 0x7f)  
  24.             break;  
  25.         s++;  
  26.     }  
  27.   
  28. #if ENABLE_UNICODE_SUPPORT  
  29.     dst = unicode_conv_to_printable(stats, str);  
  30. #else  
  31.     {  
  32.         char *d = dst = xstrdup(str);  
  33.         while (1) {  
  34.             unsigned char c = *d;  
  35.             if (c == '\0')  
  36.                 break;  
  37.                 if (c < ' ' || c >= 0x7f)  
  38.                    *d = '?';  
  39.             d++;  
  40.         }  
  41.         if (stats) {  
  42.             stats->byte_count = (d - dst);  
  43.             stats->unicode_count = (d - dst);  
  44.             stats->unicode_width = (d - dst);  
  45.         }  
  46.     }  
  47. #endif  
  48.   
  49.     free(saved[cur_saved]);  
  50.     saved[cur_saved] = dst;  
  51.     cur_saved = (cur_saved + 1) & (ARRAY_SIZE(saved)-1);  
  52.   
  53.     return dst;  
  54. }  
   从上面代码23和24行以及37和38行可以看出:大于0x7F的字符直接被break掉,或者直接被“?”代替了。所以就算是linux内核设置了支持中文,也是无法显示出来的,被“?”代替了。修改红色加粗的代码如下:

[cpp] view plaincopy
  1. const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str)  
  2. {  
  3.     static char *saved[4];  
  4.     static unsigned cur_saved; /* = 0 */  
  5.   
  6.     char *dst;  
  7.     const char *s;  
  8.   
  9.     s = str;  
  10.     while (1) {  
  11.         unsigned char c = *s;  
  12.         if (c == '\0') {  
  13.             /* 99+% of inputs do not need conversion */  
  14.             if (stats) {  
  15.                 stats->byte_count = (s - str);  
  16.                 stats->unicode_count = (s - str);  
  17.                 stats->unicode_width = (s - str);  
  18.             }  
  19.             return str;  
  20.         }  
  21.         if (c < ' ')  
  22.             break;  
  23.     /* 
  24.         if (c >= 0x7f) 
  25.             break; 
  26.     */  
  27.         s++;  
  28.     }  
  29.   
  30. #if ENABLE_UNICODE_SUPPORT  
  31.     dst = unicode_conv_to_printable(stats, str);  
  32. #else  
  33.     {  
  34.         char *d = dst = xstrdup(str);  
  35.         while (1) {  
  36.             unsigned char c = *d;  
  37.             if (c == '\0')  
  38.                 break;  
  39.             if (c < ' ' /*|| c >= 0x7f */)  
  40.                 *d = '?';  
  41.             d++;  
  42.         }  
  43.         if (stats) {  
  44.             stats->byte_count = (d - dst);  
  45.             stats->unicode_count = (d - dst);  
  46.             stats->unicode_width = (d - dst);  
  47.         }  
  48.     }  
  49. #endif  
  50.   
  51.     free(saved[cur_saved]);  
  52.     saved[cur_saved] = dst;  
  53.     cur_saved = (cur_saved + 1) & (ARRAY_SIZE(saved)-1);  
  54.   
  55.     return dst;  
  56. }  
经过以上的修改之后,同时busybox1.17.0配置的时候没有选中[] Support Unicode的话,那么采用ls命令是可以看到中文的,这个我自己已经亲自测试过的。可是还有一种情况:busybox1.17.0在配置的时候选中了:[*] Support Unicode,见下:

[html] view plaincopy
  1. 在配置里,有Support Unicode选上的:   
  2. Busybox Settings->General Configuration->  
  3.    │ │[ ] Enable locale support (system needs locale for this to work)     │ │    
  4.    │ │[*] Support Unicode                                                  │ │    
  5.    │ │[*] Support for --long-options                                       │ │    
  6.     
那么这样还需要修改一个文件,这个文件就是:unicode.c。如果不修改这个文件,ls命令也是无法显示出中文的。见下未修改的代码:

[cpp] view plaincopy
  1. static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t *stats, const char *src, unsigned width, int flags)  
  2. {  
  3.     char *dst;  
  4.     unsigned dst_len;  
  5.     unsigned uni_count;  
  6.     unsigned uni_width;  
  7.   
  8.     if (unicode_status != UNICODE_ON) {  
  9.         char *d;  
  10.         if (flags & UNI_FLAG_PAD) {  
  11.             d = dst = xmalloc(width + 1);  
  12.             while ((int)--width >= 0) {  
  13.                 unsigned char c = *src;  
  14.                 if (c == '\0') {  
  15.                     do  
  16.                         *d++ = ' ';  
  17.                     while ((int)--width >= 0);  
  18.                     break;  
  19.                 }  
  20.                 *d++ = (c >= ' ' && c < 0x7f) ? c : '?';  
  21.                 src++;  
  22.             }  
  23.             *d = '\0';  
  24.         } else {  
  25.             d = dst = xstrndup(src, width);  
  26.             while (*d) {  
  27.                 unsigned char c = *d;  
  28.                 if (c < ' ' || c >= 0x7f)  
  29.                     *d = '?';  
  30.                 d++;  
  31.             }  
  32.         }  
  33.         if (stats) {  
  34.             stats->byte_count = (d - dst);  
  35.             stats->unicode_count = (d - dst);  
  36.             stats->unicode_width = (d - dst);  
  37.         }  
  38.         return dst;  
  39.     }  
  40.   
  41.     dst = NULL;  
  42.     uni_count = uni_width = 0;  
  43.     dst_len = 0;  
  44.     while (1) {  
  45.         int w;  
  46.         wchar_t wc;  
  47.   
  48. #if ENABLE_UNICODE_USING_LOCALE  
  49.         {  
  50.             mbstate_t mbst = { 0 };  
  51.             ssize_t rc = mbsrtowcs(&wc, &src, 1, &mbst);  
  52.             /* If invalid sequence is seen: -1 is returned, 
  53.              * src points to the invalid sequence, errno = EILSEQ. 
  54.              * Else number of wchars (excluding terminating L'\0') 
  55.              * written to dest is returned. 
  56.              * If len (here: 1) non-L'\0' wchars stored at dest, 
  57.              * src points to the next char to be converted. 
  58.              * If string is completely converted: src = NULL. 
  59.              */  
  60.             if (rc == 0) /* end-of-string */  
  61.                 break;  
  62.             if (rc < 0) { /* error */  
  63.                 src++;  
  64.                 goto subst;  
  65.             }  
  66.             if (!iswprint(wc))  
  67.                 goto subst;  
  68.         }  
  69. #else  
  70.         src = mbstowc_internal(&wc, src);  
  71.         /* src is advanced to next mb char 
  72.          * wc == ERROR_WCHAR: invalid sequence is seen 
  73.          * else: wc is set 
  74.          */  
  75.         if (wc == ERROR_WCHAR) /* error */  
  76.             goto subst;  
  77.         if (wc == 0) /* end-of-string */  
  78.             break;  
  79. #endif  
  80.         if (CONFIG_LAST_SUPPORTED_WCHAR && wc > CONFIG_LAST_SUPPORTED_WCHAR)  
  81.             goto subst;  
  82.         w = wcwidth(wc);  
  83.         if ((ENABLE_UNICODE_COMBINING_WCHARS && w < 0) /* non-printable wchar */  
  84.          || (!ENABLE_UNICODE_COMBINING_WCHARS && w <= 0)  
  85.          || (!ENABLE_UNICODE_WIDE_WCHARS && w > 1)  
  86.         ) {  
  87.  subst:  
  88.             wc = CONFIG_SUBST_WCHAR;  
  89.             w = 1;  
  90.         }  
  91.         width -= w;  
  92.         /* Note: if width == 0, we still may add more chars, 
  93.          * they may be zero-width or combining ones */  
  94.         if ((int)width < 0) {  
  95.             /* can't add this wc, string would become longer than width */  
  96.             width += w;  
  97.             break;  
  98.         }  
  99.   
  100.         uni_count++;  
  101.         uni_width += w;  
  102.         dst = xrealloc(dst, dst_len + MB_CUR_MAX);  
  103. #if ENABLE_UNICODE_USING_LOCALE  
  104.         {  
  105.             mbstate_t mbst = { 0 };  
  106.             dst_len += wcrtomb(&dst[dst_len], wc, &mbst);  
  107.         }  
  108. #else  
  109.         dst_len += wcrtomb_internal(&dst[dst_len], wc);  
  110. #endif  
  111.     }  
  112.   
  113.     /* Pad to remaining width */  
  114.     if (flags & UNI_FLAG_PAD) {  
  115.         dst = xrealloc(dst, dst_len + width + 1);  
  116.         uni_count += width;  
  117.         uni_width += width;  
  118.         while ((int)--width >= 0) {  
  119.             dst[dst_len++] = ' ';  
  120.         }  
  121.     }  
  122.     dst[dst_len] = '\0';  
  123.     if (stats) {  
  124.         stats->byte_count = dst_len;  
  125.         stats->unicode_count = uni_count;  
  126.         stats->unicode_width = uni_width;  
  127.     }  
  128.   
  129.     return dst;  
  130. }  
      见上面20行和28行,需要修改一下,修改后的代码见下:

[cpp] view plaincopy
  1. static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t *stats, const char *src, unsigned width, int flags)  
  2. {  
  3.     char *dst;  
  4.     unsigned dst_len;  
  5.     unsigned uni_count;  
  6.     unsigned uni_width;  
  7.   
  8.     if (unicode_status != UNICODE_ON) {  
  9.         char *d;  
  10.         if (flags & UNI_FLAG_PAD) {  
  11.             d = dst = xmalloc(width + 1);  
  12.             while ((int)--width >= 0) {  
  13.                 unsigned char c = *src;  
  14.                 if (c == '\0') {  
  15.                     do  
  16.                         *d++ = ' ';  
  17.                     while ((int)--width >= 0);  
  18.                     break;  
  19.                 }  
  20.                 *d++ = (c >= ' '/* && c < 0x7f */) ? c : '?';  
  21.                 src++;  
  22.             }  
  23.             *d = '\0';  
  24.         } else {  
  25.             d = dst = xstrndup(src, width);  
  26.             while (*d) {  
  27.                 unsigned char c = *d;  
  28.                 if (c < ' '/* || c >= 0x7f */)  
  29.                     *d = '?';  
  30.                 d++;  
  31.             }  
  32.         }  
  33.         if (stats) {  
  34.             stats->byte_count = (d - dst);  
  35.             stats->unicode_count = (d - dst);  
  36.             stats->unicode_width = (d - dst);  
  37.         }  
  38.         return dst;  
  39.     }  
  40.   
  41.     dst = NULL;  
  42.     uni_count = uni_width = 0;  
  43.     dst_len = 0;  
  44.     while (1) {  
  45.         int w;  
  46.         wchar_t wc;  
  47.   
  48. #if ENABLE_UNICODE_USING_LOCALE  
  49.         {  
  50.             mbstate_t mbst = { 0 };  
  51.             ssize_t rc = mbsrtowcs(&wc, &src, 1, &mbst);  
  52.             /* If invalid sequence is seen: -1 is returned, 
  53.              * src points to the invalid sequence, errno = EILSEQ. 
  54.              * Else number of wchars (excluding terminating L'\0') 
  55.              * written to dest is returned. 
  56.              * If len (here: 1) non-L'\0' wchars stored at dest, 
  57.              * src points to the next char to be converted. 
  58.              * If string is completely converted: src = NULL. 
  59.              */  
  60.             if (rc == 0) /* end-of-string */  
  61.                 break;  
  62.             if (rc < 0) { /* error */  
  63.                 src++;  
  64.                 goto subst;  
  65.             }  
  66.             if (!iswprint(wc))  
  67.                 goto subst;  
  68.         }  
  69. #else  
  70.         src = mbstowc_internal(&wc, src);  
  71.         /* src is advanced to next mb char 
  72.          * wc == ERROR_WCHAR: invalid sequence is seen 
  73.          * else: wc is set 
  74.          */  
  75.         if (wc == ERROR_WCHAR) /* error */  
  76.             goto subst;  
  77.         if (wc == 0) /* end-of-string */  
  78.             break;  
  79. #endif  
  80.         if (CONFIG_LAST_SUPPORTED_WCHAR && wc > CONFIG_LAST_SUPPORTED_WCHAR)  
  81.             goto subst;  
  82.         w = wcwidth(wc);  
  83.         if ((ENABLE_UNICODE_COMBINING_WCHARS && w < 0) /* non-printable wchar */  
  84.          || (!ENABLE_UNICODE_COMBINING_WCHARS && w <= 0)  
  85.          || (!ENABLE_UNICODE_WIDE_WCHARS && w > 1)  
  86.         ) {  
  87.  subst:  
  88.             wc = CONFIG_SUBST_WCHAR;  
  89.             w = 1;  
  90.         }  
  91.         width -= w;  
  92.         /* Note: if width == 0, we still may add more chars, 
  93.          * they may be zero-width or combining ones */  
  94.         if ((int)width < 0) {  
  95.             /* can't add this wc, string would become longer than width */  
  96.             width += w;  
  97.             break;  
  98.         }  
  99.   
  100.         uni_count++;  
  101.         uni_width += w;  
  102.         dst = xrealloc(dst, dst_len + MB_CUR_MAX);  
  103. #if ENABLE_UNICODE_USING_LOCALE  
  104.         {  
  105.             mbstate_t mbst = { 0 };  
  106.             dst_len += wcrtomb(&dst[dst_len], wc, &mbst);  
  107.         }  
  108. #else  
  109.         dst_len += wcrtomb_internal(&dst[dst_len], wc);  
  110. #endif  
  111.     }  
  112.   
  113.     /* Pad to remaining width */  
  114.     if (flags & UNI_FLAG_PAD) {  
  115.         dst = xrealloc(dst, dst_len + width + 1);  
  116.         uni_count += width;  
  117.         uni_width += width;  
  118.         while ((int)--width >= 0) {  
  119.             dst[dst_len++] = ' ';  
  120.         }  
  121.     }  
  122.     dst[dst_len] = '\0';  
  123.     if (stats) {  
  124.         stats->byte_count = dst_len;  
  125.         stats->unicode_count = uni_count;  
  126.         stats->unicode_width = uni_width;  
  127.     }  
  128.   
  129.     return dst;  
  130. }  
经过以上修改之后,就算配置支持Unicode,ls命令也是可以支持中文的。同时也可以进入中文目录可以文件夹。
0 0