移植ntfs-3g到nuc960

移植ntfs-3gnuc960

 

一相关环境

1.编译环境:

Linux 主机:Ubuntu 12.04

编译器:arm-linux-gcc v4.2.1

2.硬件环境

硬件开发板:nuc960evb norflash boot

3.软件bsp

Nuc900 2.6.17 bsp

Kernel:2.6.17.14

 

二软件源码

 

1.fuse-2.6.0源码

fuse-2.6.0.tar.gz

2. ntfs-3g源码

 

ntfs-3g_ntfsprogs-2012.1.15.gz

 

三交叉编译安装ntfs-3g

 

解压

#tar zxvf ntfs-3g_ntfsprogs-2012.1.15.gz

#cd ntfs-3g_ntfsprogs-2012.1.15

配置

# ./configure  --prefix=/work/linux9nuc/bsp17/ntfs \

 --enable-really-static --disable-library  \

--host=arm-linux --disable-ntfsprogs  \

CC=arm-linux-gcc  AR=arm-linux-ar

 

#make

 

不要运行make install

 

安装

直接复制ntfs-3g到文件系统bin目录下

 

 

四编译fuse到内核

 

1.直接使用内核里的fuse

 

#make menuconfig

打开

File systems -->

<*> Filesystem in Userspace Support

 

#make

 

kernel和文件系统烧写到norflash

 

运行

#ntfs-3g  /dev/sda2 /mnt/sda2

出现如下警告信息:

 

WARNING: Deficient Linux kernel detected. Some driver features are

         not available (swap file on NTFS, boot from NTFS by LILO), and

         unmount is not safe unless it's made sure the ntfs-3g process

         naturally terminates after calling 'umount'. If you wish this

         message to disappear then you shouersion 2.6.20, or request help from your distribution to fix

         the kernel problem. The below web page has more information:

         http://tuxera.com/community/ntfs-3g-faq/#fuse26

 

ls /mnt/sda2时系统挂起

说明使用内核中的fuse,不能成功.

 

 

 

2.使用下载的fuse-2.6.0

解压

#tar zxvf fuse-2.6.0.tar.gz

#cd fuse-2.6.0

复制fuse-2.6.0 kernel目录下的:

control.c

dev.c

dir.c

file.c

fuse_i.h

fuse_kernel.h

inode.c

linux2.6.17.14fs/fuse目录下

 

编译

#make

出现错误

In file included from fs/fuse/dev.c:9:

fs/fuse/fuse_i.h:49:20: error: config.h: No such file or directory

make[2]: *** [fs/fuse/dev.o] Error 1

make[1]: *** [fs/fuse] Error 2

make: *** [fs] Error 2

 

 

 

fuse2.6.0下配置fuse

./configure \

--host=arm-linux \

--enable-kernel-module \

--with-kernel=/work/linux9nuc/bsp17/nuc900bsp/linux-2.6.17.14    \

CC=arm-linux-gcc AR=arm-linux-ar

 

复制config.hlinuxkernelfs/fuse

 

再次编译

 

出现如下错误:

fs/fuse/inode.c: In function 'fuse_init':

fs/fuse/inode.c:875: error: 'FUSE_VERSION' undeclared (first use in this function)

fs/fuse/inode.c:875: error: (Each undeclared identifier is reported only once

fs/fuse/inode.c:875: error: for each function it appears in.)

make[2]: *** [fs/fuse/inode.o] Error 1

make[1]: *** [fs/fuse] Error 2

make: *** [fs] Error 2

找到错误位置文件inode.c:875

#ifndef FUSE_MAINLINE

         printk("fuse distribution version: %s\n", FUSE_VERSION);

#endif

注销

//printk("fuse distribution version: %s\n", FUSE_VERSION);

编译

#make

出现如下错误

fs/built-in.o: In function `fuse_put_super':

inode.c:(.text+0x83a2c): undefined reference to `fuse_ctl_remove_conn'

fs/built-in.o: In function `fuse_fill_super':

inode.c:(.text+0x84158): undefined reference to `fuse_ctl_add_conn'

fs/built-in.o: In function `fuse_init':

inode.c:(.init.text+0x1b40): undefined reference to `fuse_ctl_init'

make: *** [.tmp_vmlinux1] Error 1

修改makefile

fuse-objs := dev.o dir.o file.o inode.o

改为

fuse-objs := dev.o dir.o file.o inode.o control.o

#make

成功

 ntfs-3g使用ntfs分区

1.挂载分区

#ntfs-3g /dev/sda1 /mnt/sda1

 

 

2. 测试读写速度

 

date;cp /mnt/sda1/music.zip  /tmp;sync;date

date;cp /tmp/music.zip /mnt/sda1/music.zip;date

 

 

 

sh-3.2# ls -l
drwxrwxrwx    1 root     root            0 Oct 28  2013 System Volume Information
-rwxrwxrwx    1 root     root     51715390 Jan  1 00:03 linux-2.6.17.14.tar.gz
-rwxrwxrwx    1 root     root     13289438 Oct 28  2013 music.zip
-rwxrwxrwx    2 root     root     12976128 Jul 23  2013 rootfs-t.yaffs2

 

sh-3.2# date;cp /mnt/sda1/music.zip /tmp;sync;date
Thu Jan  1 00:01:28 UTC 1970
Thu Jan  1 00:01:30 UTC 1970

 

sh-3.2# date;cp /tmp/music.zip /mnt/sda1music2.zip;sync;date
Thu Jan  1 00:02:47 UTC 1970
Thu Jan  1 00:02:59 UTC 1970
sh-3.2# date;cp /tmp/music.zip /mnt/sda1/music2.zip;sync;date
Thu Jan  1 00:03:15 UTC 1970
Thu Jan  1 00:03:28 UTC 1970

 

 

六移植中的问题

1Kernel中的fuse无法使用,出现挂起问题

2Fuse2.6.0编译成模块加载,运行不起来

 

附录:

Ntfs-3g挂载usb移动硬盘后无法显示中文的问题

 

解决此问题需要使用libiconv,并需要修改ntfs-3gunistr.c

 

中文的问题在ntfs-3g中是使用locale解决的,但把locale移植到arm非常困难.

网络上,Bob Zhang成功的使用iconv库解决了ntfs-3g在arm上显示中文的问题.具体可以参考

http://unixresources.net/linux/clf/embedded/archive/00/00/63/27/632737.html

http://en.verysource.com/code/4850902_1/unistr.c.html

 

参考以上,nuc960上的解决步骤如下

 

1.下载libiconv并编译

下载

http://www.gnu.org/software/libiconv/

libiconv-1.14.tar.gz

编译:

 

#./configure CC=arm-linux-gcc --target=arm-linux --host=arm-linux \

--prefix=/work/linux9nuc/bsp17/iconv --enable-shared --enable-static

 

#make

#make install

2.修改ntfs-3gunistr.c(libntfs-3g目录下)

 

主要用新的

int ntfs_mbstoucs(const char *ins, ntfschar **outs)

int ntfs_ucstombs(const ntfschar *ins, const int ins_len, char **outs,

int outs_len)

 

替换就的相应函数.修改后的unistr.c文件如下:

[cpp]  view plain copy
  1. /** 
  2.  * unistr.c - Unicode string handling. Originated from the Linux-NTFS project. 
  3.  * 
  4.  * Copyright (c) 2000-2004 Anton Altaparmakov 
  5.  * Copyright (c) 2002-2009 Szabolcs Szakacsits 
  6.  * Copyright (c) 2008-2011 Jean-Pierre Andre 
  7.  * Copyright (c) 2008      Bernhard Kaindl 
  8.  * 
  9.  * This program/include file is free software; you can redistribute it and/or 
  10.  * modify it under the terms of the GNU General Public License as published 
  11.  * by the Free Software Foundation; either version 2 of the License, or 
  12.  * (at your option) any later version. 
  13.  * 
  14.  * This program/include file is distributed in the hope that it will be 
  15.  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 
  16.  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  17.  * GNU General Public License for more details. 
  18.  * 
  19.  * You should have received a copy of the GNU General Public License 
  20.  * along with this program (in the main directory of the NTFS-3G 
  21.  * distribution in the file COPYING); if not, write to the Free Software 
  22.  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  23.  */  
  24.   
  25. #ifdef HAVE_CONFIG_H  
  26. #include "config.h"  
  27. #endif  
  28.   
  29. #ifdef HAVE_STDIO_H  
  30. #include <stdio.h>  
  31. #endif  
  32. #ifdef HAVE_STDLIB_H  
  33. #include <stdlib.h>  
  34. #endif  
  35. #ifdef HAVE_WCHAR_H  
  36. #include <wchar.h>  
  37. #endif  
  38. #ifdef HAVE_STRING_H  
  39. #include <string.h>  
  40. #endif  
  41. #ifdef HAVE_ERRNO_H  
  42. #include <errno.h>  
  43. #endif  
  44. #ifdef HAVE_LOCALE_H  
  45. #include <locale.h>  
  46. #endif  
  47.   
  48. #if defined(__APPLE__) || defined(__DARWIN__)  
  49. #ifdef ENABLE_NFCONV  
  50. #include <CoreFoundation/CoreFoundation.h>  
  51. #endif /* ENABLE_NFCONV */  
  52. #endif /* defined(__APPLE__) || defined(__DARWIN__) */  
  53.   
  54. #include "compat.h"  
  55. #include "attrib.h"  
  56. #include "types.h"  
  57. #include "unistr.h"  
  58. #include "debug.h"  
  59. #include "logging.h"  
  60. #include "misc.h"  
  61.   
  62. #define HAVE_USE_ICONV 1     //自己测试用的  
  63.   
  64.   
  65. #if defined(HAVE_USE_ICONV)  
  66. #include <wchar.h>  
  67. #include <iconv.h>  
  68. //#define USER_CHARSET  "CP936"  
  69. //extern char charset4libiconv[20];  
  70. //#define USER_CHARSET charset4libiconv  
  71. //#define UNICODE_CHARSET   "WCHAR_T"  
  72.   
  73. #define SIMPLE_CN           "CP936"  
  74. #define WCHAR_CHARSET           "WCHAR_T"  
  75.   
  76. #endif  
  77. #define NOREVBOM 0  /* JPA rejecting U+FFFE and U+FFFF, open to debate */  
  78.   
  79. /* 
  80.  * IMPORTANT 
  81.  * ========= 
  82.  * 
  83.  * All these routines assume that the Unicode characters are in little endian 
  84.  * encoding inside the strings!!! 
  85.  */  
  86.   
  87. static int use_utf8 = 1; /* use UTF-8 encoding for file names */  
  88.   
  89. #if defined(__APPLE__) || defined(__DARWIN__)  
  90. #ifdef ENABLE_NFCONV  
  91. /** 
  92.  * This variable controls whether or not automatic normalization form conversion 
  93.  * should be performed when translating NTFS unicode file names to UTF-8. 
  94.  * Defaults to on, but can be controlled from the outside using the function 
  95.  *   int ntfs_macosx_normalize_filenames(int normalize); 
  96.  */  
  97. static int nfconvert_utf8 = 1;  
  98. #endif /* ENABLE_NFCONV */  
  99. #endif /* defined(__APPLE__) || defined(__DARWIN__) */  
  100.   
  101. /* 
  102.  * This is used by the name collation functions to quickly determine what 
  103.  * characters are (in)valid. 
  104.  */  
  105. #if 0  
  106. static const u8 legal_ansi_char_array[0x40] = {  
  107.     0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,  
  108.     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,  
  109.   
  110.     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,  
  111.     0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,  
  112.   
  113.     0x17, 0x07, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17,  
  114.     0x17, 0x17, 0x18, 0x16, 0x16, 0x17, 0x07, 0x00,  
  115.   
  116.     0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,  
  117.     0x17, 0x17, 0x04, 0x16, 0x18, 0x16, 0x18, 0x18,  
  118. };  
  119. #endif  
  120.   
  121. /** 
  122.  * ntfs_names_are_equal - compare two Unicode names for equality 
  123.  * @s1:         name to compare to @s2 
  124.  * @s1_len:     length in Unicode characters of @s1 
  125.  * @s2:         name to compare to @s1 
  126.  * @s2_len:     length in Unicode characters of @s2 
  127.  * @ic:         ignore case bool 
  128.  * @upcase:     upcase table (only if @ic == IGNORE_CASE) 
  129.  * @upcase_size:    length in Unicode characters of @upcase (if present) 
  130.  * 
  131.  * Compare the names @s1 and @s2 and return TRUE (1) if the names are 
  132.  * identical, or FALSE (0) if they are not identical. If @ic is IGNORE_CASE, 
  133.  * the @upcase table is used to perform a case insensitive comparison. 
  134.  */  
  135. BOOL ntfs_names_are_equal(const ntfschar *s1, size_t s1_len,  
  136.         const ntfschar *s2, size_t s2_len,  
  137.         const IGNORE_CASE_BOOL ic,  
  138.         const ntfschar *upcase, const u32 upcase_size)  
  139. {  
  140.     if (s1_len != s2_len)  
  141.         return FALSE;  
  142.     if (!s1_len)  
  143.         return TRUE;  
  144.     if (ic == CASE_SENSITIVE)  
  145.         return ntfs_ucsncmp(s1, s2, s1_len) ? FALSE: TRUE;  
  146.     return ntfs_ucsncasecmp(s1, s2, s1_len, upcase, upcase_size) ? FALSE:  
  147.                                        TRUE;  
  148. }  
  149.   
  150. /* 
  151.  * ntfs_names_full_collate() fully collate two Unicode names 
  152.  * 
  153.  * @name1:  first Unicode name to compare 
  154.  * @name1_len:  length of first Unicode name to compare 
  155.  * @name2:  second Unicode name to compare 
  156.  * @name2_len:  length of second Unicode name to compare 
  157.  * @ic:     either CASE_SENSITIVE or IGNORE_CASE 
  158.  * @upcase: upcase table (ignored if @ic is CASE_SENSITIVE) 
  159.  * @upcase_len: upcase table size (ignored if @ic is CASE_SENSITIVE) 
  160.  * 
  161.  *  -1 if the first name collates before the second one, 
  162.  *   0 if the names match, 
  163.  *   1 if the second name collates before the first one, or 
  164.  * 
  165.  */  
  166. int ntfs_names_full_collate(const ntfschar *name1, const u32 name1_len,  
  167.         const ntfschar *name2, const u32 name2_len,  
  168.         const IGNORE_CASE_BOOL ic, const ntfschar *upcase,  
  169.         const u32 upcase_len)  
  170. {  
  171.     u32 cnt;  
  172.     u16 c1, c2;  
  173.     u16 u1, u2;  
  174.   
  175. #ifdef DEBUG  
  176.     if (!name1 || !name2 || (ic && (!upcase || !upcase_len))) {  
  177.         ntfs_log_debug("ntfs_names_collate received NULL pointer!\n");  
  178.         exit(1);  
  179.     }  
  180. #endif  
  181.     cnt = min(name1_len, name2_len);  
  182.     if (cnt > 0) {  
  183.         if (ic == CASE_SENSITIVE) {  
  184.             while (--cnt && (*name1 == *name2)) {  
  185.                 name1++;  
  186.                 name2++;  
  187.             }  
  188.             u1 = c1 = le16_to_cpu(*name1);  
  189.             u2 = c2 = le16_to_cpu(*name2);  
  190.             if (u1 < upcase_len)  
  191.                 u1 = le16_to_cpu(upcase[u1]);  
  192.             if (u2 < upcase_len)  
  193.                 u2 = le16_to_cpu(upcase[u2]);  
  194.             if ((u1 == u2) && cnt)  
  195.                 do {  
  196.                     name1++;  
  197.                     u1 = le16_to_cpu(*name1);  
  198.                     name2++;  
  199.                     u2 = le16_to_cpu(*name2);  
  200.                     if (u1 < upcase_len)  
  201.                         u1 = le16_to_cpu(upcase[u1]);  
  202.                     if (u2 < upcase_len)  
  203.                         u2 = le16_to_cpu(upcase[u2]);  
  204.                 } while ((u1 == u2) && --cnt);  
  205.             if (u1 < u2)  
  206.                 return -1;  
  207.             if (u1 > u2)  
  208.                 return 1;  
  209.             if (name1_len < name2_len)  
  210.                 return -1;  
  211.             if (name1_len > name2_len)  
  212.                 return 1;  
  213.             if (c1 < c2)  
  214.                 return -1;  
  215.             if (c1 > c2)  
  216.                 return 1;  
  217.         } else {  
  218.             do {  
  219.                 u1 = c1 = le16_to_cpu(*name1);  
  220.                 name1++;  
  221.                 u2 = c2 = le16_to_cpu(*name2);  
  222.                 name2++;  
  223.                 if (u1 < upcase_len)  
  224.                     u1 = le16_to_cpu(upcase[u1]);  
  225.                 if (u2 < upcase_len)  
  226.                     u2 = le16_to_cpu(upcase[u2]);  
  227.             } while ((u1 == u2) && --cnt);  
  228.             if (u1 < u2)  
  229.                 return -1;  
  230.             if (u1 > u2)  
  231.                 return 1;  
  232.             if (name1_len < name2_len)  
  233.                 return -1;  
  234.             if (name1_len > name2_len)  
  235.                 return 1;  
  236.         }  
  237.     } else {  
  238.         if (name1_len < name2_len)  
  239.             return -1;  
  240.         if (name1_len > name2_len)  
  241.             return 1;  
  242.     }  
  243.     return 0;  
  244. }  
  245.   
  246. /** 
  247.  * ntfs_ucsncmp - compare two little endian Unicode strings 
  248.  * @s1:     first string 
  249.  * @s2:     second string 
  250.  * @n:      maximum unicode characters to compare 
  251.  * 
  252.  * Compare the first @n characters of the Unicode strings @s1 and @s2, 
  253.  * The strings in little endian format and appropriate le16_to_cpu() 
  254.  * conversion is performed on non-little endian machines. 
  255.  * 
  256.  * The function returns an integer less than, equal to, or greater than zero 
  257.  * if @s1 (or the first @n Unicode characters thereof) is found, respectively, 
  258.  * to be less than, to match, or be greater than @s2. 
  259.  */  
  260. int ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n)  
  261. {  
  262.     ntfschar c1, c2;  
  263.     size_t i;  
  264.   
  265. #ifdef DEBUG  
  266.     if (!s1 || !s2) {  
  267.         ntfs_log_debug("ntfs_wcsncmp() received NULL pointer!\n");  
  268.         exit(1);  
  269.     }  
  270. #endif  
  271.     for (i = 0; i < n; ++i) {  
  272.         c1 = le16_to_cpu(s1[i]);  
  273.         c2 = le16_to_cpu(s2[i]);  
  274.         if (c1 < c2)  
  275.             return -1;  
  276.         if (c1 > c2)  
  277.             return 1;  
  278.         if (!c1)  
  279.             break;  
  280.     }  
  281.     return 0;  
  282. }  
  283.   
  284. /** 
  285.  * ntfs_ucsncasecmp - compare two little endian Unicode strings, ignoring case 
  286.  * @s1:         first string 
  287.  * @s2:         second string 
  288.  * @n:          maximum unicode characters to compare 
  289.  * @upcase:     upcase table 
  290.  * @upcase_size:    upcase table size in Unicode characters 
  291.  * 
  292.  * Compare the first @n characters of the Unicode strings @s1 and @s2, 
  293.  * ignoring case. The strings in little endian format and appropriate 
  294.  * le16_to_cpu() conversion is performed on non-little endian machines. 
  295.  * 
  296.  * Each character is uppercased using the @upcase table before the comparison. 
  297.  * 
  298.  * The function returns an integer less than, equal to, or greater than zero 
  299.  * if @s1 (or the first @n Unicode characters thereof) is found, respectively, 
  300.  * to be less than, to match, or be greater than @s2. 
  301.  */  
  302. int ntfs_ucsncasecmp(const ntfschar *s1, const ntfschar *s2, size_t n,  
  303.         const ntfschar *upcase, const u32 upcase_size)  
  304. {  
  305.     u16 c1, c2;  
  306.     size_t i;  
  307.   
  308. #ifdef DEBUG  
  309.     if (!s1 || !s2 || !upcase) {  
  310.         ntfs_log_debug("ntfs_wcsncasecmp() received NULL pointer!\n");  
  311.         exit(1);  
  312.     }  
  313. #endif  
  314.     for (i = 0; i < n; ++i) {  
  315.         if ((c1 = le16_to_cpu(s1[i])) < upcase_size)  
  316.             c1 = le16_to_cpu(upcase[c1]);  
  317.         if ((c2 = le16_to_cpu(s2[i])) < upcase_size)  
  318.             c2 = le16_to_cpu(upcase[c2]);  
  319.         if (c1 < c2)  
  320.             return -1;  
  321.         if (c1 > c2)  
  322.             return 1;  
  323.         if (!c1)  
  324.             break;  
  325.     }  
  326.     return 0;  
  327. }  
  328.   
  329. /** 
  330.  * ntfs_ucsnlen - determine the length of a little endian Unicode string 
  331.  * @s:      pointer to Unicode string 
  332.  * @maxlen: maximum length of string @s 
  333.  * 
  334.  * Return the number of Unicode characters in the little endian Unicode 
  335.  * string @s up to a maximum of maxlen Unicode characters, not including 
  336.  * the terminating (ntfschar)'\0'. If there is no (ntfschar)'\0' between @s 
  337.  * and @s + @maxlen, @maxlen is returned. 
  338.  * 
  339.  * This function never looks beyond @s + @maxlen. 
  340.  */  
  341. u32 ntfs_ucsnlen(const ntfschar *s, u32 maxlen)  
  342. {  
  343.     u32 i;  
  344.   
  345.     for (i = 0; i < maxlen; i++) {  
  346.         if (!le16_to_cpu(s[i]))  
  347.             break;  
  348.     }  
  349.     return i;  
  350. }  
  351.   
  352. /** 
  353.  * ntfs_ucsndup - duplicate little endian Unicode string 
  354.  * @s:      pointer to Unicode string 
  355.  * @maxlen: maximum length of string @s 
  356.  * 
  357.  * Return a pointer to a new little endian Unicode string which is a duplicate 
  358.  * of the string s.  Memory for the new string is obtained with ntfs_malloc(3), 
  359.  * and can be freed with free(3). 
  360.  * 
  361.  * A maximum of @maxlen Unicode characters are copied and a terminating 
  362.  * (ntfschar)'\0' little endian Unicode character is added. 
  363.  * 
  364.  * This function never looks beyond @s + @maxlen. 
  365.  * 
  366.  * Return a pointer to the new little endian Unicode string on success and NULL 
  367.  * on failure with errno set to the error code. 
  368.  */  
  369. ntfschar *ntfs_ucsndup(const ntfschar *s, u32 maxlen)  
  370. {  
  371.     ntfschar *dst;  
  372.     u32 len;  
  373.   
  374.     len = ntfs_ucsnlen(s, maxlen);  
  375.     dst = ntfs_malloc((len + 1) * sizeof(ntfschar));  
  376.     if (dst) {  
  377.         memcpy(dst, s, len * sizeof(ntfschar));  
  378.         dst[len] = cpu_to_le16(L'\0');  
  379.     }  
  380.     return dst;  
  381. }  
  382.   
  383. /** 
  384.  * ntfs_name_upcase - Map an Unicode name to its uppercase equivalent 
  385.  * @name: 
  386.  * @name_len: 
  387.  * @upcase: 
  388.  * @upcase_len: 
  389.  * 
  390.  * Description... 
  391.  * 
  392.  * Returns: 
  393.  */  
  394. void ntfs_name_upcase(ntfschar *name, u32 name_len, const ntfschar *upcase,  
  395.         const u32 upcase_len)  
  396. {  
  397.     u32 i;  
  398.     u16 u;  
  399.   
  400.     for (i = 0; i < name_len; i++)  
  401.         if ((u = le16_to_cpu(name[i])) < upcase_len)  
  402.             name[i] = upcase[u];  
  403. }  
  404.   
  405. /** 
  406.  * ntfs_name_locase - Map a Unicode name to its lowercase equivalent 
  407.  */  
  408. void ntfs_name_locase(ntfschar *name, u32 name_len, const ntfschar *locase,  
  409.         const u32 locase_len)  
  410. {  
  411.     u32 i;  
  412.     u16 u;  
  413.   
  414.     if (locase)  
  415.         for (i = 0; i < name_len; i++)  
  416.             if ((u = le16_to_cpu(name[i])) < locase_len)  
  417.                 name[i] = locase[u];  
  418. }  
  419.   
  420. /** 
  421.  * ntfs_file_value_upcase - Convert a filename to upper case 
  422.  * @file_name_attr: 
  423.  * @upcase: 
  424.  * @upcase_len: 
  425.  * 
  426.  * Description... 
  427.  * 
  428.  * Returns: 
  429.  */  
  430. void ntfs_file_value_upcase(FILE_NAME_ATTR *file_name_attr,  
  431.         const ntfschar *upcase, const u32 upcase_len)  
  432. {  
  433.     ntfs_name_upcase((ntfschar*)&file_name_attr->file_name,  
  434.             file_name_attr->file_name_length, upcase, upcase_len);  
  435. }  
  436.   
  437. /* 
  438.    NTFS uses Unicode (UTF-16LE [NTFS-3G uses UCS-2LE, which is enough 
  439.    for now]) for path names, but the Unicode code points need to be 
  440.    converted before a path can be accessed under NTFS. For 7 bit ASCII/ANSI, 
  441.    glibc does this even without a locale in a hard-coded fashion as that 
  442.    appears to be is easy because the low 7-bit ASCII range appears to be 
  443.    available in all charsets but it does not convert anything if 
  444.    there was some error with the locale setup or none set up like 
  445.    when mount is called during early boot where he (by policy) do 
  446.    not use locales (and may be not available if /usr is not yet mounted), 
  447.    so this patch fixes the resulting issues for systems which use 
  448.    UTF-8 and for others, specifying the locale in fstab brings them 
  449.    the encoding which they want. 
  450.    
  451.    If no locale is defined or there was a problem with setting one 
  452.    up and whenever nl_langinfo(CODESET) returns a sting starting with 
  453.    "ANSI", use an internal UCS-2LE <-> UTF-8 codeset converter to fix 
  454.    the bug where NTFS-3G does not show any path names which include 
  455.    international characters!!! (and also fails on creating them) as result. 
  456.    
  457.    Author: Bernhard Kaindl <bk@suse.de> 
  458.    Jean-Pierre Andre made it compliant with RFC3629/RFC2781. 
  459. */  
  460.    
  461. /*  
  462.  * Return the amount of 8-bit elements in UTF-8 needed (without the terminating 
  463.  * null) to store a given UTF-16LE string. 
  464.  * 
  465.  * Return -1 with errno set if string has invalid byte sequence or too long. 
  466.  */  
  467. static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_len)  
  468. {  
  469.     int i, ret = -1;  
  470.     int count = 0;  
  471.     BOOL surrog;  
  472.   
  473.     surrog = FALSE;  
  474.     for (i = 0; i < ins_len && ins[i]; i++) {  
  475.         unsigned short c = le16_to_cpu(ins[i]);  
  476.         if (surrog) {  
  477.             if ((c >= 0xdc00) && (c < 0xe000)) {  
  478.                 surrog = FALSE;  
  479.                 count += 4;  
  480.             } else   
  481.                 goto fail;  
  482.         } else  
  483.             if (c < 0x80)  
  484.                 count++;  
  485.             else if (c < 0x800)  
  486.                 count += 2;  
  487.             else if (c < 0xd800)  
  488.                 count += 3;  
  489.             else if (c < 0xdc00)  
  490.                 surrog = TRUE;  
  491. #if NOREVBOM  
  492.             else if ((c >= 0xe000) && (c < 0xfffe))  
  493. #else  
  494.             else if (c >= 0xe000)  
  495. #endif  
  496.                 count += 3;  
  497.             else   
  498.                 goto fail;  
  499.         if (count > outs_len) {  
  500.             errno = ENAMETOOLONG;  
  501.             goto out;  
  502.         }  
  503.     }  
  504.     if (surrog)   
  505.         goto fail;  
  506.   
  507.     ret = count;  
  508. out:  
  509.     return ret;  
  510. fail:  
  511.     errno = EILSEQ;  
  512.     goto out;  
  513. }  
  514.   
  515. /* 
  516.  * ntfs_utf16_to_utf8 - convert a little endian UTF16LE string to an UTF-8 string 
  517.  * @ins:    input utf16 string buffer 
  518.  * @ins_len:    length of input string in utf16 characters 
  519.  * @outs:   on return contains the (allocated) output multibyte string 
  520.  * @outs_len:   length of output buffer in bytes 
  521.  * 
  522.  * Return -1 with errno set if string has invalid byte sequence or too long. 
  523.  */  
  524. static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len,  
  525.                   char **outs, int outs_len)  
  526. {  
  527. #if defined(__APPLE__) || defined(__DARWIN__)  
  528. #ifdef ENABLE_NFCONV  
  529.     char *original_outs_value = *outs;  
  530.     int original_outs_len = outs_len;  
  531. #endif /* ENABLE_NFCONV */  
  532. #endif /* defined(__APPLE__) || defined(__DARWIN__) */  
  533.   
  534.     char *t;  
  535.     int i, size, ret = -1;  
  536.     int halfpair;  
  537.   
  538.     halfpair = 0;  
  539.     if (!*outs)  
  540.         outs_len = PATH_MAX;  
  541.   
  542.     size = utf16_to_utf8_size(ins, ins_len, outs_len);  
  543.   
  544.     if (size < 0)  
  545.         goto out;  
  546.   
  547.     if (!*outs) {  
  548.         outs_len = size + 1;  
  549.         *outs = ntfs_malloc(outs_len);  
  550.         if (!*outs)  
  551.             goto out;  
  552.     }  
  553.   
  554.     t = *outs;  
  555.   
  556.     for (i = 0; i < ins_len && ins[i]; i++) {  
  557.         unsigned short c = le16_to_cpu(ins[i]);  
  558.             /* size not double-checked */  
  559.         if (halfpair) {  
  560.             if ((c >= 0xdc00) && (c < 0xe000)) {  
  561.                 *t++ = 0xf0 + (((halfpair + 64) >> 8) & 7);  
  562.                 *t++ = 0x80 + (((halfpair + 64) >> 2) & 63);  
  563.                 *t++ = 0x80 + ((c >> 6) & 15) + ((halfpair & 3) << 4);  
  564.                 *t++ = 0x80 + (c & 63);  
  565.                 halfpair = 0;  
  566.             } else   
  567.                 goto fail;  
  568.         } else if (c < 0x80) {  
  569.             *t++ = c;  
  570.             } else {  
  571.             if (c < 0x800) {  
  572.                 *t++ = (0xc0 | ((c >> 6) & 0x3f));  
  573.                     *t++ = 0x80 | (c & 0x3f);  
  574.             } else if (c < 0xd800) {  
  575.                 *t++ = 0xe0 | (c >> 12);  
  576.                 *t++ = 0x80 | ((c >> 6) & 0x3f);  
  577.                     *t++ = 0x80 | (c & 0x3f);  
  578.             } else if (c < 0xdc00)  
  579.                 halfpair = c;  
  580.             else if (c >= 0xe000) {  
  581.                 *t++ = 0xe0 | (c >> 12);  
  582.                 *t++ = 0x80 | ((c >> 6) & 0x3f);  
  583.                     *t++ = 0x80 | (c & 0x3f);  
  584.             } else   
  585.                 goto fail;  
  586.             }  
  587.     }  
  588.     *t = '\0';  
  589.       
  590. #if defined(__APPLE__) || defined(__DARWIN__)  
  591. #ifdef ENABLE_NFCONV  
  592.     if(nfconvert_utf8 && (t - *outs) > 0) {  
  593.         char *new_outs = NULL;  
  594.         int new_outs_len = ntfs_macosx_normalize_utf8(*outs, &new_outs, 0); // Normalize to decomposed form  
  595.         if(new_outs_len >= 0 && new_outs != NULL) {  
  596.             if(original_outs_value != *outs) {  
  597.                 // We have allocated outs ourselves.  
  598.                 free(*outs);  
  599.                 *outs = new_outs;  
  600.                 t = *outs + new_outs_len;  
  601.             }  
  602.             else {  
  603.                 // We need to copy new_outs into the fixed outs buffer.  
  604.                 memset(*outs, 0, original_outs_len);  
  605.                 strncpy(*outs, new_outs, original_outs_len-1);  
  606.                 t = *outs + original_outs_len;  
  607.                 free(new_outs);  
  608.             }  
  609.         }  
  610.         else {  
  611.             ntfs_log_error("Failed to normalize NTFS string to UTF-8 NFD: %s\n", *outs);  
  612.             ntfs_log_error("  new_outs=0x%p\n", new_outs);  
  613.             ntfs_log_error("  new_outs_len=%d\n", new_outs_len);  
  614.         }  
  615.     }  
  616. #endif /* ENABLE_NFCONV */  
  617. #endif /* defined(__APPLE__) || defined(__DARWIN__) */  
  618.       
  619.     ret = t - *outs;  
  620. out:  
  621.     return ret;  
  622. fail:  
  623.     errno = EILSEQ;  
  624.     goto out;  
  625. }  
  626.   
  627. /*  
  628.  * Return the amount of 16-bit elements in UTF-16LE needed  
  629.  * (without the terminating null) to store given UTF-8 string. 
  630.  * 
  631.  * Return -1 with errno set if it's longer than PATH_MAX or string is invalid. 
  632.  * 
  633.  * Note: This does not check whether the input sequence is a valid utf8 string, 
  634.  *   and should be used only in context where such check is made! 
  635.  */  
  636. static int utf8_to_utf16_size(const char *s)  
  637. {  
  638.     int ret = -1;  
  639.     unsigned int byte;  
  640.     size_t count = 0;  
  641.   
  642.     while ((byte = *((const unsigned char *)s++))) {  
  643.         if (++count >= PATH_MAX)   
  644.             goto fail;  
  645.         if (byte >= 0xc0) {  
  646.             if (byte >= 0xF5) {  
  647.                 errno = EILSEQ;  
  648.                 goto out;  
  649.             }  
  650.             if (!*s)   
  651.                 break;  
  652.             if (byte >= 0xC0)   
  653.                 s++;  
  654.             if (!*s)   
  655.                 break;  
  656.             if (byte >= 0xE0)   
  657.                 s++;  
  658.             if (!*s)   
  659.                 break;  
  660.             if (byte >= 0xF0) {  
  661.                 s++;  
  662.                 if (++count >= PATH_MAX)  
  663.                     goto fail;  
  664.             }  
  665.         }  
  666.     }  
  667.     ret = count;  
  668. out:  
  669.     return ret;  
  670. fail:  
  671.     errno = ENAMETOOLONG;  
  672.     goto out;  
  673. }  
  674. /*  
  675.  * This converts one UTF-8 sequence to cpu-endian Unicode value 
  676.  * within range U+0 .. U+10ffff and excluding U+D800 .. U+DFFF 
  677.  * 
  678.  * Return the number of used utf8 bytes or -1 with errno set  
  679.  * if sequence is invalid. 
  680.  */  
  681. static int utf8_to_unicode(u32 *wc, const char *s)  
  682. {  
  683.         unsigned int byte = *((const unsigned char *)s);  
  684.   
  685.                     /* single byte */  
  686.     if (byte == 0) {  
  687.         *wc = (u32) 0;  
  688.         return 0;  
  689.     } else if (byte < 0x80) {  
  690.         *wc = (u32) byte;  
  691.         return 1;  
  692.                     /* double byte */  
  693.     } else if (byte < 0xc2) {  
  694.         goto fail;  
  695.     } else if (byte < 0xE0) {  
  696.         if ((s[1] & 0xC0) == 0x80) {  
  697.             *wc = ((u32)(byte & 0x1F) << 6)  
  698.                 | ((u32)(s[1] & 0x3F));  
  699.             return 2;  
  700.         } else  
  701.             goto fail;  
  702.                     /* three-byte */  
  703.     } else if (byte < 0xF0) {  
  704.         if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80)) {  
  705.             *wc = ((u32)(byte & 0x0F) << 12)  
  706.                 | ((u32)(s[1] & 0x3F) << 6)  
  707.                 | ((u32)(s[2] & 0x3F));  
  708.             /* Check valid ranges */  
  709. #if NOREVBOM  
  710.             if (((*wc >= 0x800) && (*wc <= 0xD7FF))  
  711.               || ((*wc >= 0xe000) && (*wc <= 0xFFFD)))  
  712.                 return 3;  
  713. #else  
  714.             if (((*wc >= 0x800) && (*wc <= 0xD7FF))  
  715.               || ((*wc >= 0xe000) && (*wc <= 0xFFFF)))  
  716.                 return 3;  
  717. #endif  
  718.         }  
  719.         goto fail;  
  720.                     /* four-byte */  
  721.     } else if (byte < 0xF5) {  
  722.         if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80)  
  723.           && ((s[3] & 0xC0) == 0x80)) {  
  724.             *wc = ((u32)(byte & 0x07) << 18)  
  725.                 | ((u32)(s[1] & 0x3F) << 12)  
  726.                 | ((u32)(s[2] & 0x3F) << 6)  
  727.                 | ((u32)(s[3] & 0x3F));  
  728.         /* Check valid ranges */  
  729.         if ((*wc <= 0x10ffff) && (*wc >= 0x10000))  
  730.             return 4;  
  731.         }  
  732.         goto fail;  
  733.     }  
  734. fail:  
  735.     errno = EILSEQ;  
  736.     return -1;  
  737. }  
  738.   
  739. /** 
  740.  * ntfs_utf8_to_utf16 - convert a UTF-8 string to a UTF-16LE string 
  741.  * @ins:    input multibyte string buffer 
  742.  * @outs:   on return contains the (allocated) output utf16 string 
  743.  * @outs_len:   length of output buffer in utf16 characters 
  744.  *  
  745.  * Return -1 with errno set. 
  746.  */  
  747. static int ntfs_utf8_to_utf16(const char *ins, ntfschar **outs)  
  748. {  
  749. #if defined(__APPLE__) || defined(__DARWIN__)  
  750. #ifdef ENABLE_NFCONV  
  751.     char *new_ins = NULL;  
  752.     if(nfconvert_utf8) {  
  753.         int new_ins_len;  
  754.         new_ins_len = ntfs_macosx_normalize_utf8(ins, &new_ins, 1); // Normalize to composed form  
  755.         if(new_ins_len >= 0)  
  756.             ins = new_ins;  
  757.         else  
  758.             ntfs_log_error("Failed to normalize NTFS string to UTF-8 NFC: %s\n", ins);  
  759.     }  
  760. #endif /* ENABLE_NFCONV */  
  761. #endif /* defined(__APPLE__) || defined(__DARWIN__) */  
  762.     const char *t = ins;  
  763.     u32 wc;  
  764.     BOOL allocated;  
  765.     ntfschar *outpos;  
  766.     int shorts, ret = -1;  
  767.   
  768.     shorts = utf8_to_utf16_size(ins);  
  769.     if (shorts < 0)  
  770.         goto fail;  
  771.   
  772.     allocated = FALSE;  
  773.     if (!*outs) {  
  774.         *outs = ntfs_malloc((shorts + 1) * sizeof(ntfschar));  
  775.         if (!*outs)  
  776.             goto fail;  
  777.         allocated = TRUE;  
  778.     }  
  779.   
  780.     outpos = *outs;  
  781.   
  782.     while(1) {  
  783.         int m  = utf8_to_unicode(&wc, t);  
  784.         if (m <= 0) {  
  785.             if (m < 0) {  
  786.                 /* do not leave space allocated if failed */  
  787.                 if (allocated) {  
  788.                     free(*outs);  
  789.                     *outs = (ntfschar*)NULL;  
  790.                 }  
  791.                 goto fail;  
  792.             }  
  793.             *outpos++ = const_cpu_to_le16(0);  
  794.             break;  
  795.         }  
  796.         if (wc < 0x10000)  
  797.             *outpos++ = cpu_to_le16(wc);  
  798.         else {  
  799.             wc -= 0x10000;  
  800.             *outpos++ = cpu_to_le16((wc >> 10) + 0xd800);  
  801.             *outpos++ = cpu_to_le16((wc & 0x3ff) + 0xdc00);  
  802.         }  
  803.         t += m;  
  804.     }  
  805.       
  806.     ret = --outpos - *outs;  
  807. fail:  
  808. #if defined(__APPLE__) || defined(__DARWIN__)  
  809. #ifdef ENABLE_NFCONV  
  810.     if(new_ins != NULL)  
  811.         free(new_ins);  
  812. #endif /* ENABLE_NFCONV */  
  813. #endif /* defined(__APPLE__) || defined(__DARWIN__) */  
  814.     return ret;  
  815. }  
  816.   
  817.   
  818. #if !defined(HAVE_USE_ICONV)  
  819. /** 
  820.  * ntfs_ucstombs - convert a little endian Unicode string to a multibyte string 
  821.  * @ins:    input Unicode string buffer 
  822.  * @ins_len:    length of input string in Unicode characters 
  823.  * @outs:   on return contains the (allocated) output multibyte string 
  824.  * @outs_len:   length of output buffer in bytes 
  825.  * 
  826.  * Convert the input little endian, 2-byte Unicode string @ins, of length 
  827.  * @ins_len into the multibyte string format dictated by the current locale. 
  828.  * 
  829.  * If *@outs is NULL, the function allocates the string and the caller is 
  830.  * responsible for calling free(*@outs); when finished with it. 
  831.  * 
  832.  * On success the function returns the number of bytes written to the output 
  833.  * string *@outs (>= 0), not counting the terminating NULL byte. If the output 
  834.  * string buffer was allocated, *@outs is set to it. 
  835.  * 
  836.  * On error, -1 is returned, and errno is set to the error code. The following 
  837.  * error codes can be expected: 
  838.  *  EINVAL      Invalid arguments (e.g. @ins or @outs is NULL). 
  839.  *  EILSEQ      The input string cannot be represented as a multibyte 
  840.  *          sequence according to the current locale. 
  841.  *  ENAMETOOLONG    Destination buffer is too small for input string. 
  842.  *  ENOMEM      Not enough memory to allocate destination buffer. 
  843.  */  
  844. int ntfs_ucstombs(const ntfschar *ins, const int ins_len, char **outs,  
  845.         int outs_len)  
  846. {  
  847.     char *mbs;  
  848.     int mbs_len;  
  849. #ifdef MB_CUR_MAX  
  850.     wchar_t wc;  
  851.     int i, o;  
  852.     int cnt = 0;  
  853. #ifdef HAVE_MBSINIT  
  854.     mbstate_t mbstate;  
  855. #endif  
  856. #endif /* MB_CUR_MAX */  
  857.   
  858.     if (!ins || !outs) {  
  859.         errno = EINVAL;  
  860.         return -1;  
  861.     }  
  862.     mbs = *outs;  
  863.     mbs_len = outs_len;  
  864.     if (mbs && !mbs_len) {  
  865.         errno = ENAMETOOLONG;  
  866.         return -1;  
  867.     }  
  868.     if (use_utf8)  
  869.         return ntfs_utf16_to_utf8(ins, ins_len, outs, outs_len);  
  870. #ifdef MB_CUR_MAX  
  871.     if (!mbs) {  
  872.         mbs_len = (ins_len + 1) * MB_CUR_MAX;  
  873.         mbs = ntfs_malloc(mbs_len);  
  874.         if (!mbs)  
  875.             return -1;  
  876.     }  
  877. #ifdef HAVE_MBSINIT  
  878.     memset(&mbstate, 0, sizeof(mbstate));  
  879. #else  
  880.     wctomb(NULL, 0);  
  881. #endif  
  882.     for (i = o = 0; i < ins_len; i++) {  
  883.         /* Reallocate memory if necessary or abort. */  
  884.         if ((int)(o + MB_CUR_MAX) > mbs_len) {  
  885.             char *tc;  
  886.             if (mbs == *outs) {  
  887.                 errno = ENAMETOOLONG;  
  888.                 return -1;  
  889.             }  
  890.             tc = ntfs_malloc((mbs_len + 64) & ~63);  
  891.             if (!tc)  
  892.                 goto err_out;  
  893.             memcpy(tc, mbs, mbs_len);  
  894.             mbs_len = (mbs_len + 64) & ~63;  
  895.             free(mbs);  
  896.             mbs = tc;  
  897.         }  
  898.         /* Convert the LE Unicode character to a CPU wide character. */  
  899.         wc = (wchar_t)le16_to_cpu(ins[i]);  
  900.         if (!wc)  
  901.             break;  
  902.         /* Convert the CPU endian wide character to multibyte. */  
  903. #ifdef HAVE_MBSINIT  
  904.         cnt = wcrtomb(mbs + o, wc, &mbstate);  
  905. #else  
  906.         cnt = wctomb(mbs + o, wc);  
  907. #endif  
  908.         if (cnt == -1)  
  909.             goto err_out;  
  910.         if (cnt <= 0) {  
  911.             ntfs_log_debug("Eeek. cnt <= 0, cnt = %i\n", cnt);  
  912.             errno = EINVAL;  
  913.             goto err_out;  
  914.         }  
  915.         o += cnt;  
  916.     }  
  917. #ifdef HAVE_MBSINIT  
  918.     /* Make sure we are back in the initial state. */  
  919.     if (!mbsinit(&mbstate)) {  
  920.         ntfs_log_debug("Eeek. mbstate not in initial state!\n");  
  921.         errno = EILSEQ;  
  922.         goto err_out;  
  923.     }  
  924. #endif  
  925.     /* Now write the NULL character. */  
  926.     mbs[o] = '\0';  
  927.     if (*outs != mbs)  
  928.         *outs = mbs;  
  929.     return o;  
  930. err_out:  
  931.     if (mbs != *outs) {  
  932.         int eo = errno;  
  933.         free(mbs);  
  934.         errno = eo;  
  935.     }  
  936. #else /* MB_CUR_MAX */  
  937.     errno = EILSEQ;  
  938. #endif /* MB_CUR_MAX */  
  939.     return -1;  
  940. }  
  941.   
  942. #else   
  943.   
  944.   
  945. /*我的思路是还是先malloc一段内存用来存储 wchar_t 类型的 
  946.  * 然后用iconv 转换 
  947.  * 最后得到的就是mbs 
  948.  * 这个函数 比 ntfs_mbstoucs 简单多了。因为多了一个ins_len参数, 处理个数就方便多了, 
  949.  
  950.  */  
  951. int ntfs_ucstombs(const ntfschar *ins, const int ins_len, char **outs,  
  952.         int outs_len)  
  953. {  
  954.     wchar_t *ucs_wchar, *ucs_wchar_start = NULL;  
  955.     char *mbs, *mbs_start = NULL;  
  956.     size_t mbs_len, ucs_wchar_len, cnt;  
  957.     iconv_t cd = (iconv_t)-1;  
  958.   
  959.     if (!ins || !outs) {  
  960.         errno = EINVAL;  
  961.         return -1;  
  962.     }  
  963.     mbs = *outs;  
  964.     mbs_len = outs_len;  
  965.     if (mbs && !mbs_len) {  
  966.         errno = ENAMETOOLONG;  
  967.         return -1;  
  968.     }  
  969.     if (mbs == NULL) {  
  970.         mbs_len = (ins_len + 1) * sizeof(wchar_t);  
  971.         mbs = malloc(mbs_len);  
  972.         if(!mbs)  
  973.             return -1;  
  974.         *outs = mbs;  
  975.     }  
  976.     mbs_start = mbs;  
  977.   
  978.     ucs_wchar = (wchar_t *)malloc((ins_len + 1) * sizeof(wchar_t));  
  979.     if (ucs_wchar == NULL)  
  980.         goto err_out;  
  981.     ucs_wchar_start = ucs_wchar;  
  982.     ucs_wchar_len = ins_len * sizeof(wchar_t);  
  983.   
  984.     for(cnt=0; cnt<ins_len; cnt++)  
  985.         ucs_wchar[cnt] = (wchar_t)le16_to_cpu(ins[cnt]);  
  986.     ucs_wchar[cnt] = (wchar_t)(L'\0');  
  987.   
  988.     cd = iconv_open(SIMPLE_CN, WCHAR_CHARSET);  
  989.     if (cd == (iconv_t)-1)  
  990.         goto err_out;  
  991.     cnt = iconv(cd, (char **)&ucs_wchar, &ucs_wchar_len, &mbs, &mbs_len);  
  992.     if (cnt == (size_t)-1)  
  993.         goto err_out;  
  994.     *mbs = '\0';  
  995.     iconv_close(cd);  
  996.   
  997.     free(ucs_wchar_start);  
  998.     return mbs - mbs_start;  
  999.   
  1000. err_out:  
  1001.     *outs = NULL;  
  1002.     if (cd != (iconv_t)-1)  
  1003.         libiconv_close(cd);  
  1004.     if (mbs_start)  
  1005.         free(mbs_start);  
  1006.     if (ucs_wchar_start)  
  1007.         free(ucs_wchar_start);  
  1008.     return -1;  
  1009. }  
  1010.   
  1011.   
  1012.   
  1013. #endif  
  1014.   
  1015. //--------------------------------------------------------------------  
  1016. #if !defined(HAVE_USE_ICONV)  
  1017. /** 
  1018.  * ntfs_mbstoucs - convert a multibyte string to a little endian Unicode string 
  1019.  * @ins:    input multibyte string buffer 
  1020.  * @outs:   on return contains the (allocated) output Unicode string 
  1021.  * 
  1022.  * Convert the input multibyte string @ins, from the current locale into the 
  1023.  * corresponding little endian, 2-byte Unicode string. 
  1024.  * 
  1025.  * The function allocates the string and the caller is responsible for calling  
  1026.  * free(*@outs); when finished with it. 
  1027.  * 
  1028.  * On success the function returns the number of Unicode characters written to 
  1029.  * the output string *@outs (>= 0), not counting the terminating Unicode NULL 
  1030.  * character. 
  1031.  * 
  1032.  * On error, -1 is returned, and errno is set to the error code. The following 
  1033.  * error codes can be expected: 
  1034.  *  EINVAL      Invalid arguments (e.g. @ins or @outs is NULL). 
  1035.  *  EILSEQ      The input string cannot be represented as a Unicode 
  1036.  *          string according to the current locale. 
  1037.  *  ENAMETOOLONG    Destination buffer is too small for input string. 
  1038.  *  ENOMEM      Not enough memory to allocate destination buffer. 
  1039.  */  
  1040. int ntfs_mbstoucs(const char *ins, ntfschar **outs)  
  1041. {  
  1042. #ifdef MB_CUR_MAX  
  1043.     ntfschar *ucs;  
  1044.     const char *s;  
  1045.     wchar_t wc;  
  1046.     int i, o, cnt, ins_len, ucs_len, ins_size;  
  1047. #ifdef HAVE_MBSINIT  
  1048.     mbstate_t mbstate;  
  1049. #endif  
  1050. #endif /* MB_CUR_MAX */  
  1051.   
  1052.     if (!ins || !outs) {  
  1053.         errno = EINVAL;  
  1054.         return -1;  
  1055.     }  
  1056.       
  1057.     if (use_utf8)  
  1058.         return ntfs_utf8_to_utf16(ins, outs);  
  1059.   
  1060. #ifdef MB_CUR_MAX  
  1061.     /* Determine the size of the multi-byte string in bytes. */  
  1062.     ins_size = strlen(ins);  
  1063.     /* Determine the length of the multi-byte string. */  
  1064.     s = ins;  
  1065. #if defined(HAVE_MBSINIT)  
  1066.     memset(&mbstate, 0, sizeof(mbstate));  
  1067.     ins_len = mbsrtowcs(NULL, (const char **)&s, 0, &mbstate);  
  1068. #ifdef __CYGWIN32__  
  1069.     if (!ins_len && *ins) {  
  1070.         /* Older Cygwin had broken mbsrtowcs() implementation. */  
  1071.         ins_len = strlen(ins);  
  1072.     }  
  1073. #endif  
  1074. #elif !defined(DJGPP)  
  1075.     ins_len = mbstowcs(NULL, s, 0);  
  1076. #else  
  1077.     /* Eeek!!! DJGPP has broken mbstowcs() implementation!!! */  
  1078.     ins_len = strlen(ins);  
  1079. #endif  
  1080.     if (ins_len == -1)  
  1081.         return ins_len;  
  1082. #ifdef HAVE_MBSINIT  
  1083.     if ((s != ins) || !mbsinit(&mbstate)) {  
  1084. #else  
  1085.     if (s != ins) {  
  1086. #endif  
  1087.         errno = EILSEQ;  
  1088.         return -1;  
  1089.     }  
  1090.     /* Add the NULL terminator. */  
  1091.     ins_len++;  
  1092.     ucs_len = ins_len;  
  1093.     ucs = ntfs_malloc(ucs_len * sizeof(ntfschar));  
  1094.     if (!ucs)  
  1095.         return -1;  
  1096. #ifdef HAVE_MBSINIT  
  1097.     memset(&mbstate, 0, sizeof(mbstate));  
  1098. #else  
  1099.     mbtowc(NULL, NULL, 0);  
  1100. #endif  
  1101.     for (i = o = cnt = 0; i < ins_size; i += cnt, o++) {  
  1102.         /* Reallocate memory if necessary. */  
  1103.         if (o >= ucs_len) {  
  1104.             ntfschar *tc;  
  1105.             ucs_len = (ucs_len * sizeof(ntfschar) + 64) & ~63;  
  1106.             tc = realloc(ucs, ucs_len);  
  1107.             if (!tc)  
  1108.                 goto err_out;  
  1109.             ucs = tc;  
  1110.             ucs_len /= sizeof(ntfschar);  
  1111.         }  
  1112.         /* Convert the multibyte character to a wide character. */  
  1113. #ifdef HAVE_MBSINIT  
  1114.         cnt = mbrtowc(&wc, ins + i, ins_size - i, &mbstate);  
  1115. #else  
  1116.         cnt = mbtowc(&wc, ins + i, ins_size - i);  
  1117. #endif  
  1118.         if (!cnt)  
  1119.             break;  
  1120.         if (cnt == -1)  
  1121.             goto err_out;  
  1122.         if (cnt < -1) {  
  1123.             ntfs_log_trace("Eeek. cnt = %i\n", cnt);  
  1124.             errno = EINVAL;  
  1125.             goto err_out;  
  1126.         }  
  1127.         /* Make sure we are not overflowing the NTFS Unicode set. */  
  1128.         if ((unsigned long)wc >= (unsigned long)(1 <<  
  1129.                 (8 * sizeof(ntfschar)))) {  
  1130.             errno = EILSEQ;  
  1131.             goto err_out;  
  1132.         }  
  1133.         /* Convert the CPU wide character to a LE Unicode character. */  
  1134.         ucs[o] = cpu_to_le16(wc);  
  1135.     }  
  1136. #ifdef HAVE_MBSINIT  
  1137.     /* Make sure we are back in the initial state. */  
  1138.     if (!mbsinit(&mbstate)) {  
  1139.         ntfs_log_trace("Eeek. mbstate not in initial state!\n");  
  1140.         errno = EILSEQ;  
  1141.         goto err_out;  
  1142.     }  
  1143. #endif  
  1144.     /* Now write the NULL character. */  
  1145.     ucs[o] = cpu_to_le16(L'\0');  
  1146.     *outs = ucs;  
  1147.     return o;  
  1148. err_out:  
  1149.     free(ucs);  
  1150. #else /* MB_CUR_MAX */  
  1151.     errno = EILSEQ;  
  1152. #endif /* MB_CUR_MAX */  
  1153.     return -1;  
  1154. }  
  1155. #else   //I use iconv() instead of mbrtowc ,bob  
  1156. int ntfs_mbstoucs(const char *ins, ntfschar **outs)  
  1157. {  
  1158.     ntfschar *ucs_ntfschar = NULL;  
  1159.     wchar_t *ucs_wchar = NULL, *ucs_wchar_start;  
  1160.     size_t ins_len, ucs_wchar_len, cnt;  
  1161.     iconv_t cd = (iconv_t)-1;  
  1162.   
  1163.     if (!ins || !outs) {  
  1164.         errno = EINVAL;  
  1165.         return -1;  
  1166.     }  
  1167.   
  1168.     ins_len = strlen(ins);  
  1169.     ucs_ntfschar = *outs;  
  1170.     if (!ucs_ntfschar) {  
  1171.         ucs_ntfschar = (ntfschar *)malloc((ins_len + 1) * sizeof(ntfschar));  
  1172.         if(ucs_ntfschar == NULL)  
  1173.             return -1;  
  1174.         *outs = ucs_ntfschar;  
  1175.     }  
  1176.   
  1177.     ucs_wchar = (wchar_t *)malloc((ins_len + 1) * sizeof(wchar_t));  
  1178.     ucs_wchar_len = (ins_len + 1) * sizeof(wchar_t);  
  1179.     if(ucs_wchar == NULL)  
  1180.         goto err_out;  
  1181.     ucs_wchar_start = (char *)ucs_wchar;  
  1182.   
  1183.     cd = iconv_open(WCHAR_CHARSET, SIMPLE_CN);  
  1184.     if (cd == (iconv_t)-1)  
  1185.         goto err_out;  
  1186.     cnt = iconv(cd, (char **)&ins, &ins_len, (char **)&ucs_wchar, &ucs_wchar_len);  
  1187.     if (cnt == (size_t)-1)  
  1188.         goto err_out;  
  1189.     *ucs_wchar = (wchar_t)cpu_to_le16(L'\0');  
  1190.     iconv_close(cd);  
  1191.   
  1192.     for(cnt=0; cnt<ucs_wchar-ucs_wchar_start; cnt++)  
  1193.         ucs_ntfschar[cnt] = cpu_to_le16(ucs_wchar_start[cnt]);  
  1194.     ucs_ntfschar[cnt] = cpu_to_le16(L'\0');  
  1195.   
  1196.     free(ucs_wchar_start);  
  1197.     return ucs_wchar - ucs_wchar_start;  
  1198.   
  1199. err_out:  
  1200.     *outs = NULL;  
  1201.     if (ucs_wchar_start)  
  1202.         free(ucs_wchar_start);  
  1203.     if (ucs_ntfschar)  
  1204.         free(ucs_ntfschar);  
  1205.     if (cd != (iconv_t)-1)  
  1206.         libiconv_close(cd);  
  1207.     return -1;  
  1208. }  
  1209. #endif  
  1210. /* 
  1211.  *      Turn a UTF8 name uppercase 
  1212.  * 
  1213.  *  Returns an allocated uppercase name which has to be freed by caller 
  1214.  *  or NULL if there is an error (described by errno) 
  1215.  */  
  1216.   
  1217. char *ntfs_uppercase_mbs(const char *low,  
  1218.             const ntfschar *upcase, u32 upcase_size)  
  1219. {  
  1220.     int size;  
  1221.     char *upp;  
  1222.     u32 wc;  
  1223.     int n;  
  1224.     const char *s;  
  1225.     char *t;  
  1226.   
  1227.     size = strlen(low);  
  1228.     upp = (char*)ntfs_malloc(3*size + 1);  
  1229.     if (upp) {  
  1230.         s = low;  
  1231.         t = upp;  
  1232.         do {  
  1233.             n = utf8_to_unicode(&wc, s);  
  1234.             if (n > 0) {  
  1235.                 if (wc < upcase_size)  
  1236.                     wc = le16_to_cpu(upcase[wc]);  
  1237.                 if (wc < 0x80)  
  1238.                     *t++ = wc;  
  1239.                 else if (wc < 0x800) {  
  1240.                     *t++ = (0xc0 | ((wc >> 6) & 0x3f));  
  1241.                     *t++ = 0x80 | (wc & 0x3f);  
  1242.                 } else if (wc < 0x10000) {  
  1243.                     *t++ = 0xe0 | (wc >> 12);  
  1244.                     *t++ = 0x80 | ((wc >> 6) & 0x3f);  
  1245.                     *t++ = 0x80 | (wc & 0x3f);  
  1246.                 } else {  
  1247.                     *t++ = 0xf0 | ((wc >> 18) & 7);  
  1248.                     *t++ = 0x80 | ((wc >> 12) & 63);  
  1249.                     *t++ = 0x80 | ((wc >> 6) & 0x3f);  
  1250.                     *t++ = 0x80 | (wc & 0x3f);  
  1251.                 }  
  1252.             s += n;  
  1253.             }  
  1254.         } while (n > 0);  
  1255.         if (n < 0) {  
  1256.             free(upp);  
  1257.             upp = (char*)NULL;  
  1258.             errno = EILSEQ;  
  1259.         }  
  1260.         *t = 0;  
  1261.     }  
  1262.     return (upp);  
  1263. }  
  1264.   
  1265. /** 
  1266.  * ntfs_upcase_table_build - build the default upcase table for NTFS 
  1267.  * @uc:     destination buffer where to store the built table 
  1268.  * @uc_len: size of destination buffer in bytes 
  1269.  * 
  1270.  * ntfs_upcase_table_build() builds the default upcase table for NTFS and 
  1271.  * stores it in the caller supplied buffer @uc of size @uc_len. 
  1272.  * 
  1273.  * Note, @uc_len must be at least 128kiB in size or bad things will happen! 
  1274.  */  
  1275. void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len)  
  1276. {  
  1277. #if 1 /* Vista */  
  1278.     /* 
  1279.      *  This is the table as defined by Vista 
  1280.      */  
  1281.     /* 
  1282.      * "Start" is inclusive and "End" is exclusive, every value has the 
  1283.      * value of "Add" added to it. 
  1284.      */  
  1285.     static int uc_run_table[][3] = { /* Start, End, Add */  
  1286.     {0x0061, 0x007b,   -32}, {0x00e0, 0x00f7,  -32}, {0x00f8, 0x00ff, -32},   
  1287.     {0x0256, 0x0258,  -205}, {0x028a, 0x028c, -217}, {0x037b, 0x037e, 130},   
  1288.     {0x03ac, 0x03ad,   -38}, {0x03ad, 0x03b0,  -37}, {0x03b1, 0x03c2, -32},  
  1289.     {0x03c2, 0x03c3,   -31}, {0x03c3, 0x03cc,  -32}, {0x03cc, 0x03cd, -64},  
  1290.     {0x03cd, 0x03cf,   -63}, {0x0430, 0x0450,  -32}, {0x0450, 0x0460, -80},  
  1291.     {0x0561, 0x0587,   -48}, {0x1f00, 0x1f08,    8}, {0x1f10, 0x1f16,   8},  
  1292.     {0x1f20, 0x1f28,     8}, {0x1f30, 0x1f38,    8}, {0x1f40, 0x1f46,   8},  
  1293.     {0x1f51, 0x1f52,     8}, {0x1f53, 0x1f54,    8}, {0x1f55, 0x1f56,   8},  
  1294.     {0x1f57, 0x1f58,     8}, {0x1f60, 0x1f68,    8}, {0x1f70, 0x1f72,  74},  
  1295.     {0x1f72, 0x1f76,    86}, {0x1f76, 0x1f78,  100}, {0x1f78, 0x1f7a, 128},  
  1296.     {0x1f7a, 0x1f7c,   112}, {0x1f7c, 0x1f7e,  126}, {0x1f80, 0x1f88,   8},  
  1297.     {0x1f90, 0x1f98,     8}, {0x1fa0, 0x1fa8,    8}, {0x1fb0, 0x1fb2,   8},  
  1298.     {0x1fb3, 0x1fb4,     9}, {0x1fcc, 0x1fcd,   -9}, {0x1fd0, 0x1fd2,   8},  
  1299.     {0x1fe0, 0x1fe2,     8}, {0x1fe5, 0x1fe6,    7}, {0x1ffc, 0x1ffd,  -9},  
  1300.     {0x2170, 0x2180,   -16}, {0x24d0, 0x24ea,  -26}, {0x2c30, 0x2c5f, -48},  
  1301.     {0x2d00, 0x2d26, -7264}, {0xff41, 0xff5b,  -32}, {0}  
  1302.     };  
  1303.     /* 
  1304.      * "Start" is exclusive and "End" is inclusive, every second value is 
  1305.      * decremented by one. 
  1306.      */  
  1307.     static int uc_dup_table[][2] = { /* Start, End */  
  1308.     {0x0100, 0x012f}, {0x0132, 0x0137}, {0x0139, 0x0149}, {0x014a, 0x0178},  
  1309.     {0x0179, 0x017e}, {0x01a0, 0x01a6}, {0x01b3, 0x01b7}, {0x01cd, 0x01dd},  
  1310.     {0x01de, 0x01ef}, {0x01f4, 0x01f5}, {0x01f8, 0x01f9}, {0x01fa, 0x0220},  
  1311.     {0x0222, 0x0234}, {0x023b, 0x023c}, {0x0241, 0x0242}, {0x0246, 0x024f},  
  1312.     {0x03d8, 0x03ef}, {0x03f7, 0x03f8}, {0x03fa, 0x03fb}, {0x0460, 0x0481},  
  1313.     {0x048a, 0x04bf}, {0x04c1, 0x04c4}, {0x04c5, 0x04c8}, {0x04c9, 0x04ce},  
  1314.     {0x04ec, 0x04ed}, {0x04d0, 0x04eb}, {0x04ee, 0x04f5}, {0x04f6, 0x0513},  
  1315.     {0x1e00, 0x1e95}, {0x1ea0, 0x1ef9}, {0x2183, 0x2184}, {0x2c60, 0x2c61},  
  1316.     {0x2c67, 0x2c6c}, {0x2c75, 0x2c76}, {0x2c80, 0x2ce3}, {0}  
  1317.     };  
  1318.     /* 
  1319.      * Set the Unicode character at offset "Offset" to "Value".  Note, 
  1320.      * "Value" is host endian. 
  1321.      */  
  1322.     static int uc_byte_table[][2] = { /* Offset, Value */  
  1323.     {0x00ff, 0x0178}, {0x0180, 0x0243}, {0x0183, 0x0182}, {0x0185, 0x0184},  
  1324.     {0x0188, 0x0187}, {0x018c, 0x018b}, {0x0192, 0x0191}, {0x0195, 0x01f6},  
  1325.     {0x0199, 0x0198}, {0x019a, 0x023d}, {0x019e, 0x0220}, {0x01a8, 0x01a7},  
  1326.     {0x01ad, 0x01ac}, {0x01b0, 0x01af}, {0x01b9, 0x01b8}, {0x01bd, 0x01bc},  
  1327.     {0x01bf, 0x01f7}, {0x01c6, 0x01c4}, {0x01c9, 0x01c7}, {0x01cc, 0x01ca},  
  1328.     {0x01dd, 0x018e}, {0x01f3, 0x01f1}, {0x023a, 0x2c65}, {0x023e, 0x2c66},  
  1329.     {0x0253, 0x0181}, {0x0254, 0x0186}, {0x0259, 0x018f}, {0x025b, 0x0190},  
  1330.     {0x0260, 0x0193}, {0x0263, 0x0194}, {0x0268, 0x0197}, {0x0269, 0x0196},  
  1331.     {0x026b, 0x2c62}, {0x026f, 0x019c}, {0x0272, 0x019d}, {0x0275, 0x019f},  
  1332.     {0x027d, 0x2c64}, {0x0280, 0x01a6}, {0x0283, 0x01a9}, {0x0288, 0x01ae},  
  1333.     {0x0289, 0x0244}, {0x028c, 0x0245}, {0x0292, 0x01b7}, {0x03f2, 0x03f9},  
  1334.     {0x04cf, 0x04c0}, {0x1d7d, 0x2c63}, {0x214e, 0x2132}, {0}  
  1335.     };  
  1336. #else /* Vista */  
  1337.     /* 
  1338.      *  This is the table as defined by Windows XP 
  1339.      */  
  1340.     static int uc_run_table[][3] = { /* Start, End, Add */  
  1341.     {0x0061, 0x007B,  -32}, {0x0451, 0x045D, -80}, {0x1F70, 0x1F72,  74},  
  1342.     {0x00E0, 0x00F7,  -32}, {0x045E, 0x0460, -80}, {0x1F72, 0x1F76,  86},  
  1343.     {0x00F8, 0x00FF,  -32}, {0x0561, 0x0587, -48}, {0x1F76, 0x1F78, 100},  
  1344.     {0x0256, 0x0258, -205}, {0x1F00, 0x1F08,   8}, {0x1F78, 0x1F7A, 128},  
  1345.     {0x028A, 0x028C, -217}, {0x1F10, 0x1F16,   8}, {0x1F7A, 0x1F7C, 112},  
  1346.     {0x03AC, 0x03AD,  -38}, {0x1F20, 0x1F28,   8}, {0x1F7C, 0x1F7E, 126},  
  1347.     {0x03AD, 0x03B0,  -37}, {0x1F30, 0x1F38,   8}, {0x1FB0, 0x1FB2,   8},  
  1348.     {0x03B1, 0x03C2,  -32}, {0x1F40, 0x1F46,   8}, {0x1FD0, 0x1FD2,   8},  
  1349.     {0x03C2, 0x03C3,  -31}, {0x1F51, 0x1F52,   8}, {0x1FE0, 0x1FE2,   8},  
  1350.     {0x03C3, 0x03CC,  -32}, {0x1F53, 0x1F54,   8}, {0x1FE5, 0x1FE6,   7},  
  1351.     {0x03CC, 0x03CD,  -64}, {0x1F55, 0x1F56,   8}, {0x2170, 0x2180, -16},  
  1352.     {0x03CD, 0x03CF,  -63}, {0x1F57, 0x1F58,   8}, {0x24D0, 0x24EA, -26},  
  1353.     {0x0430, 0x0450,  -32}, {0x1F60, 0x1F68,   8}, {0xFF41, 0xFF5B, -32},  
  1354.     {0}  
  1355.     };  
  1356.     static int uc_dup_table[][2] = { /* Start, End */  
  1357.     {0x0100, 0x012F}, {0x01A0, 0x01A6}, {0x03E2, 0x03EF}, {0x04CB, 0x04CC},  
  1358.     {0x0132, 0x0137}, {0x01B3, 0x01B7}, {0x0460, 0x0481}, {0x04D0, 0x04EB},  
  1359.     {0x0139, 0x0149}, {0x01CD, 0x01DD}, {0x0490, 0x04BF}, {0x04EE, 0x04F5},  
  1360.     {0x014A, 0x0178}, {0x01DE, 0x01EF}, {0x04BF, 0x04BF}, {0x04F8, 0x04F9},  
  1361.     {0x0179, 0x017E}, {0x01F4, 0x01F5}, {0x04C1, 0x04C4}, {0x1E00, 0x1E95},  
  1362.     {0x018B, 0x018B}, {0x01FA, 0x0218}, {0x04C7, 0x04C8}, {0x1EA0, 0x1EF9},  
  1363.     {0}  
  1364.     };  
  1365.     static int uc_byte_table[][2] = { /* Offset, Value */  
  1366.     {0x00FF, 0x0178}, {0x01AD, 0x01AC}, {0x01F3, 0x01F1}, {0x0269, 0x0196},  
  1367.     {0x0183, 0x0182}, {0x01B0, 0x01AF}, {0x0253, 0x0181}, {0x026F, 0x019C},  
  1368.     {0x0185, 0x0184}, {0x01B9, 0x01B8}, {0x0254, 0x0186}, {0x0272, 0x019D},  
  1369.     {0x0188, 0x0187}, {0x01BD, 0x01BC}, {0x0259, 0x018F}, {0x0275, 0x019F},  
  1370.     {0x018C, 0x018B}, {0x01C6, 0x01C4}, {0x025B, 0x0190}, {0x0283, 0x01A9},  
  1371.     {0x0192, 0x0191}, {0x01C9, 0x01C7}, {0x0260, 0x0193}, {0x0288, 0x01AE},  
  1372.     {0x0199, 0x0198}, {0x01CC, 0x01CA}, {0x0263, 0x0194}, {0x0292, 0x01B7},  
  1373.     {0x01A8, 0x01A7}, {0x01DD, 0x018E}, {0x0268, 0x0197},  
  1374.     {0}  
  1375.     };  
  1376. #endif /* Vista */  
  1377.     int i, r;  
  1378.     int k, off;  
  1379.   
  1380.     memset((char*)uc, 0, uc_len);  
  1381.     uc_len >>= 1;  
  1382.     if (uc_len > 65536)  
  1383.         uc_len = 65536;  
  1384.     for (i = 0; (u32)i < uc_len; i++)  
  1385.         uc[i] = cpu_to_le16(i);  
  1386.     for (r = 0; uc_run_table[r][0]; r++) {  
  1387.         off = uc_run_table[r][2];  
  1388.         for (i = uc_run_table[r][0]; i < uc_run_table[r][1]; i++)  
  1389.             uc[i] = cpu_to_le16(i + off);  
  1390.     }  
  1391.     for (r = 0; uc_dup_table[r][0]; r++)  
  1392.         for (i = uc_dup_table[r][0]; i < uc_dup_table[r][1]; i += 2)  
  1393.             uc[i + 1] = cpu_to_le16(i);  
  1394.     for (r = 0; uc_byte_table[r][0]; r++) {  
  1395.         k = uc_byte_table[r][1];  
  1396.         uc[uc_byte_table[r][0]] = cpu_to_le16(k);  
  1397.     }  
  1398. }  
  1399.   
  1400. /* 
  1401.  *      Allocate and build the default upcase table 
  1402.  * 
  1403.  *  Returns the number of entries 
  1404.  *      0 if failed 
  1405.  */  
  1406.   
  1407. #define UPCASE_LEN 65536 /* default number of entries in upcase */  
  1408.   
  1409. u32 ntfs_upcase_build_default(ntfschar **upcase)  
  1410. {  
  1411.     u32 upcase_len = 0;  
  1412.   
  1413.     *upcase = (ntfschar*)ntfs_malloc(UPCASE_LEN*2);  
  1414.     if (*upcase) {  
  1415.         ntfs_upcase_table_build(*upcase, UPCASE_LEN*2);  
  1416.         upcase_len = UPCASE_LEN;  
  1417.     }  
  1418.     return (upcase_len);  
  1419. }  
  1420.   
  1421. /* 
  1422.  *      Build a table for converting to lower case 
  1423.  * 
  1424.  *  This is only meaningful when there is a single lower case 
  1425.  *  character leading to an upper case one, and currently the 
  1426.  *  only exception is the greek letter sigma which has a single 
  1427.  *  upper case glyph (code U+03A3), but two lower case glyphs 
  1428.  *  (code U+03C3 and U+03C2, the latter to be used at the end 
  1429.  *  of a word). In the following implementation the upper case 
  1430.  *  sigma will be lowercased as U+03C3. 
  1431.  */  
  1432.   
  1433. ntfschar *ntfs_locase_table_build(const ntfschar *uc, u32 uc_cnt)  
  1434. {  
  1435.     ntfschar *lc;  
  1436.     u32 upp;  
  1437.     u32 i;  
  1438.   
  1439.     lc = (ntfschar*)ntfs_malloc(uc_cnt*sizeof(ntfschar));  
  1440.     if (lc) {  
  1441.         for (i=0; i<uc_cnt; i++)  
  1442.             lc[i] = cpu_to_le16(i);  
  1443.         for (i=0; i<uc_cnt; i++) {  
  1444.             upp = le16_to_cpu(uc[i]);  
  1445.             if ((upp != i) && (upp < uc_cnt))  
  1446.                 lc[upp] = cpu_to_le16(i);  
  1447.         }  
  1448.     } else  
  1449.         ntfs_log_error("Could not build the locase table\n");  
  1450.     return (lc);  
  1451. }  
  1452.   
  1453. /** 
  1454.  * ntfs_str2ucs - convert a string to a valid NTFS file name 
  1455.  * @s:      input string 
  1456.  * @len:    length of output buffer in Unicode characters 
  1457.  * 
  1458.  * Convert the input @s string into the corresponding little endian, 
  1459.  * 2-byte Unicode string. The length of the converted string is less  
  1460.  * or equal to the maximum length allowed by the NTFS format (255). 
  1461.  * 
  1462.  * If @s is NULL then return AT_UNNAMED. 
  1463.  * 
  1464.  * On success the function returns the Unicode string in an allocated  
  1465.  * buffer and the caller is responsible to free it when it's not needed 
  1466.  * anymore. 
  1467.  * 
  1468.  * On error NULL is returned and errno is set to the error code. 
  1469.  */  
  1470. ntfschar *ntfs_str2ucs(const char *s, int *len)  
  1471. {  
  1472.     ntfschar *ucs = NULL;  
  1473.   
  1474.     if (s && ((*len = ntfs_mbstoucs(s, &ucs)) == -1)) {  
  1475.         ntfs_log_perror("Couldn't convert '%s' to Unicode", s);  
  1476.         return NULL;  
  1477.     }  
  1478.     if (*len > NTFS_MAX_NAME_LEN) {  
  1479.         free(ucs);  
  1480.         errno = ENAMETOOLONG;  
  1481.         return NULL;  
  1482.     }  
  1483.     if (!ucs || !*len) {  
  1484.         ucs  = AT_UNNAMED;  
  1485.         *len = 0;  
  1486.     }  
  1487.     return ucs;  
  1488. }  
  1489.   
  1490. /** 
  1491.  * ntfs_ucsfree - free memory allocated by ntfs_str2ucs() 
  1492.  * @ucs     input string to be freed 
  1493.  * 
  1494.  * Free memory at @ucs and which was allocated by ntfs_str2ucs. 
  1495.  * 
  1496.  * Return value: none. 
  1497.  */  
  1498. void ntfs_ucsfree(ntfschar *ucs)  
  1499. {  
  1500.     if (ucs && (ucs != AT_UNNAMED))  
  1501.         free(ucs);  
  1502. }  
  1503.   
  1504. /* 
  1505.  *      Check whether a name contains no chars forbidden 
  1506.  *  for DOS or Win32 use 
  1507.  * 
  1508.  *  If there is a bad char, errno is set to EINVAL 
  1509.  */  
  1510.   
  1511. BOOL ntfs_forbidden_chars(const ntfschar *name, int len)  
  1512. {  
  1513.     BOOL forbidden;  
  1514.     int ch;  
  1515.     int i;  
  1516.     u32 mainset =     (1L << ('\"' - 0x20))  
  1517.             | (1L << ('*' - 0x20))  
  1518.             | (1L << ('/' - 0x20))  
  1519.             | (1L << (':' - 0x20))  
  1520.             | (1L << ('<' - 0x20))  
  1521.             | (1L << ('>' - 0x20))  
  1522.             | (1L << ('?' - 0x20));  
  1523.   
  1524.     forbidden = (len == 0)  
  1525.             || (le16_to_cpu(name[len-1]) == ' ')  
  1526.             || (le16_to_cpu(name[len-1]) == '.');  
  1527.     for (i=0; i<len; i++) {  
  1528.         ch = le16_to_cpu(name[i]);  
  1529.         if ((ch < 0x20)  
  1530.             || ((ch < 0x40)  
  1531.             && ((1L << (ch - 0x20)) & mainset))  
  1532.             || (ch == '\\')  
  1533.             || (ch == '|'))  
  1534.             forbidden = TRUE;  
  1535.     }  
  1536.     if (forbidden)  
  1537.         errno = EINVAL;  
  1538.     return (forbidden);  
  1539. }  
  1540.   
  1541. /* 
  1542.  *      Check whether the same name can be used as a DOS and 
  1543.  *  a Win32 name 
  1544.  * 
  1545.  *  The names must be the same, or the short name the uppercase 
  1546.  *  variant of the long name 
  1547.  */  
  1548.   
  1549. BOOL ntfs_collapsible_chars(ntfs_volume *vol,  
  1550.             const ntfschar *shortname, int shortlen,  
  1551.             const ntfschar *longname, int longlen)  
  1552. {  
  1553.     BOOL collapsible;  
  1554.     unsigned int ch;  
  1555.     unsigned int cs;  
  1556.     int i;  
  1557.   
  1558.     collapsible = shortlen == longlen;  
  1559.     for (i=0; collapsible && (i<shortlen); i++) {  
  1560.         ch = le16_to_cpu(longname[i]);  
  1561.         cs = le16_to_cpu(shortname[i]);  
  1562.         if ((cs != ch)  
  1563.             && ((ch >= vol->upcase_len)  
  1564.             || (cs >= vol->upcase_len)  
  1565.             || (vol->upcase[cs] != vol->upcase[ch])))  
  1566.                 collapsible = FALSE;  
  1567.     }  
  1568.     return (collapsible);  
  1569. }  
  1570.   
  1571. /* 
  1572.  * Define the character encoding to be used. 
  1573.  * Use UTF-8 unless specified otherwise. 
  1574.  */  
  1575.   
  1576. int ntfs_set_char_encoding(const char *locale)  
  1577. {  
  1578.     use_utf8 = 0;  
  1579.     if (!locale || strstr(locale,"utf8") || strstr(locale,"UTF8")  
  1580.         || strstr(locale,"utf-8") || strstr(locale,"UTF-8"))  
  1581.         use_utf8 = 1;  
  1582.     else  
  1583.         if (setlocale(LC_ALL, locale))  
  1584.             use_utf8 = 0;  
  1585.         else {  
  1586.             ntfs_log_error("Invalid locale, encoding to UTF-8\n");  
  1587.             use_utf8 = 1;  
  1588.         }  
  1589.     return 0; /* always successful */  
  1590. }  
  1591.   
  1592. #if defined(__APPLE__) || defined(__DARWIN__)  
  1593.   
  1594. int ntfs_macosx_normalize_filenames(int normalize) {  
  1595. #ifdef ENABLE_NFCONV  
  1596.     if(normalize == 0 || normalize == 1) {  
  1597.         nfconvert_utf8 = normalize;  
  1598.         return 0;  
  1599.     }  
  1600.     else  
  1601.         return -1;  
  1602. #else  
  1603.     return -1;  
  1604. #endif /* ENABLE_NFCONV */  
  1605. }   
  1606.   
  1607. int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target,  
  1608.  int composed) {  
  1609. #ifdef ENABLE_NFCONV  
  1610.     /* For this code to compile, the CoreFoundation framework must be fed to the linker. */  
  1611.     CFStringRef cfSourceString;  
  1612.     CFMutableStringRef cfMutableString;  
  1613.     CFRange rangeToProcess;  
  1614.     CFIndex requiredBufferLength;  
  1615.     char *result = NULL;  
  1616.     int resultLength = -1;  
  1617.       
  1618.     /* Convert the UTF-8 string to a CFString. */  
  1619.     cfSourceString = CFStringCreateWithCString(kCFAllocatorDefault, utf8_string, kCFStringEncodingUTF8);  
  1620.     if(cfSourceString == NULL) {  
  1621.         ntfs_log_error("CFStringCreateWithCString failed!\n");  
  1622.         return -2;  
  1623.     }  
  1624.       
  1625.     /* Create a mutable string from cfSourceString that we are free to modify. */  
  1626.     cfMutableString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfSourceString);  
  1627.     CFRelease(cfSourceString); /* End-of-life. */  
  1628.     if(cfMutableString == NULL) {  
  1629.         ntfs_log_error("CFStringCreateMutableCopy failed!\n");  
  1630.         return -3;  
  1631.     }  
  1632.     
  1633.     /* Normalize the mutable string to the desired normalization form. */  
  1634.     CFStringNormalize(cfMutableString, (composed != 0 ? kCFStringNormalizationFormC : kCFStringNormalizationFormD));  
  1635.       
  1636.     /* Store the resulting string in a '\0'-terminated UTF-8 encoded char* buffer. */  
  1637.     rangeToProcess = CFRangeMake(0, CFStringGetLength(cfMutableString));  
  1638.     if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8, 0, false, NULL, 0, &requiredBufferLength) > 0) {  
  1639.         resultLength = sizeof(char)*(requiredBufferLength + 1);  
  1640.         result = ntfs_calloc(resultLength);  
  1641.           
  1642.         if(result != NULL) {  
  1643.             if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8,  
  1644.                         0, false, (UInt8*)result, resultLength-1, &requiredBufferLength) <= 0) {  
  1645.                 ntfs_log_error("Could not perform UTF-8 conversion of normalized CFMutableString.\n");  
  1646.                 free(result);  
  1647.                 result = NULL;  
  1648.             }  
  1649.         }  
  1650.         else  
  1651.             ntfs_log_error("Could not perform a ntfs_calloc of %d bytes for char *result.\n", resultLength);  
  1652.     }  
  1653.     else  
  1654.         ntfs_log_error("Could not perform check for required length of UTF-8 conversion of normalized CFMutableString.\n");  
  1655.   
  1656.       
  1657.     CFRelease(cfMutableString);  
  1658.       
  1659.     if(result != NULL) {  
  1660.         *target = result;  
  1661.         return resultLength - 1;  
  1662.     }  
  1663.     else  
  1664.         return -1;  
  1665. #else  
  1666.     return -1;  
  1667. #endif /* ENABLE_NFCONV */  
  1668. }  
  1669. #endif /* defined(__APPLE__) || defined(__DARWIN__) */  


 

3.配置编译ntfs-3g

配置

#./configure  --prefix=/work/linux9nuc/bsp17/ntfs \

--enable-really-static --disable-library  \

--host=arm-linux --disable-ntfsprogs  \

CC=arm-linux-gcc \

CFLAGS='-I/work/linux9nuc/bsp17/iconv/include' \

LDFLAGS=-L/work/linux9nuc/bsp17/iconv/lib \

LIBS=-liconv \

AR=arm-linux-ar

 

编译

#make

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值