1. 程式人生 > >arm開發板的NTFS-3G完整移植+中文目錄支援+自動掛載(udev)

arm開發板的NTFS-3G完整移植+中文目錄支援+自動掛載(udev)

-NTFS-3G完整移植+中文支援+自動掛載

1核心裁剪

1.1進入核心原始碼目錄下:

$make menuconfig

Linux/arm 2.6.37 Kernel Configuration

   File systems  --->                //NTFS-3G需要依賴使用者空間檔案系統FUSE的支援

<*> FUSE (Filesystem in Userspace) support

<*>Character device in Userspace support

-*- Native language support  --->  //預設語言配置為utf8,幷包含一些其他常用語言的編碼

(utf8) Default NLS Option

<*>   Codepage 437 (United States, Canada)

<*>   Simplified Chinese charset (CP936, GB2312)

<*>   ASCII (United States)                                                                  

<*>   NLS ISO 8859-1  (Latin 1; Western European Languages)

<*>   NLS UTF-8

DOS/FAT/NT Filesystems  --->     //這裡的NTFS是隻讀的,不支援寫,我們使用NTFS-3G軟體包,並且支援讀寫,所以這裡不配置。

< > NTFS file system support

1.2編譯生成新的uImage,放入提供tftp服務資料夾下;

$make uImage

$cp arch/arm/boot/uImage /tftpboot

2 NTFS-3G完整移植

NTFS-3G使用的是時間距離較近的版本,優化了記憶體佔用過多的問題:

2.1解壓:

$tar xvf ntfs-3g_ntfsprogs-2016.2.22

2.2進入ntfs-3g原始碼目錄下:

$cd ntfs-3g_ntfsprogs-2016.2.22

2.3編譯前配置

$  ./configure --build=i386 --host=arm-arago-linux-gnueabi --prefix=/song/usr --exec-prefix=/song

--build=i386 編譯的主機;

--host=arm-arago-linux-gnueabi編譯出來的二進位制程式所執行的主機;

/song/usr和/song 目錄為生成的檔案存放位置,可自己定義;

2.4然後就是make && make install;稍等片刻,就可以了。

$make && make install

2.5 /song/bin資料夾下的ntfsfixntfs-3g拷貝到nfs檔案系統的/bin目錄下

$cp ntfsfix ntfs-3g /DVRRDK_04.00.00.03/target/rfs_816x/bin/

ntfsfix      //ntfs硬碟修復工具

ntfs-3g     //ntfs硬碟掛載工具

2.6 /song/sbin資料夾下的mkntfs拷貝到nfs檔案系統的/sbin目錄下

$cp mkntfs /DVRRDK_04.00.00.03/target/rfs_816x/bin/

mkntfs     //格式化分割槽工具

2.7 /song/lib資料夾下的libntfs-3g.so、libntfs-3g.so.87libntfs-3g.so.87.0.0

拷貝到nfs檔案系統的/lib目錄下

$cp libntfs-3g.so  libntfs-3g.so.87  libntfs-3g.so.87.0.0 /DVRRDK_04.00.00.03/target/rfs_816x/bin/

libntfs-3g.so  libntfs-3g.so.87  libntfs-3g.so.87.0.0   //動態庫

暫時只用到掛載時的ntfs-3g和格式化的mkntfs以及ntfsfix三個工具,注意ntfs-3g需要動態庫libntfs-3g.so.87,需要把lib夾中的so一同一起移植過去。

2.8好了,到此ok,我測試了一下:

[[email protected]:/media]#: ntfs-3g

ntfs-3g: No device is specified.

ntfs-3g 2016.2.22 integrated FUSE 27 - Third Generation NTFS Driver

                Configuration type 1, XATTRS are on, POSIX ACLS are off

Copyright (C) 2005-2007 Yura Pakhuchiy

Copyright (C) 2006-2009 Szabolcs Szakacsits

Copyright (C) 2007-2016 Jean-Pierre Andre

Copyright (C) 2009 Erik Larsson

Usage:    ntfs-3g [-o option[,...]] <device|image_file> <mount_point>

Options:  ro (read-only mount), windows_names, uid=, gid=,

          umask=, fmask=, dmask=, streams_interface=.

          Please see the details in the manual (type: man ntfs-3g).

Example: ntfs-3g /dev/sda1 /mnt/windows

News, support and information:  http://tuxera.com

2.9 ntfs-3g可以顯示版本,再進行掛載測試:

#ntfs-3g /dev/sda1 /mnt  //可以正常掛載,但是不支援中文目錄,在後面進行了解決;

#mount -t ntfs-3g /dev/sda1 /mnt  //不可以使用,ntfs-3g不是ntfs,無法識別,試了好多方法還是不行,原因可能是busybox的mount的缺陷吧,放棄;最後決定自動掛載時使用ntfs-3g,心累!。

3中文支援

這裡採用了這位博主的方法:http://blog.csdn.net/wavemcu/article/details/7202908

3.1進入Busybox原始碼目錄下,busybox版本是1.19.4

$cd libbb/

$vi printable_string.c

  printable_string.c原始碼修改了紅色加粗的程式碼:

中文是“?”的原因:大於0x7F的字元直接被break掉,或者直接被“?”代替了。所以就算是linux核心設定了支援中文,也是無法顯示出來的,被“?”代替了。

1. constchar* FAST_FUNC printable_string(uni_stat_t *stats, constchar *str)  

2. {  

3. staticchar *saved[4];  

4. static unsigned cur_saved; /* = 0 */

5. 

6. char *dst;  

7. constchar *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. }  

3.2修改unicode.c檔案,如果不修改這個,ls命令也是無法顯示出中文的。

$vi unicode.c

原始碼修改紅色加粗的程式碼:

1. staticchar* FAST_FUNC unicode_conv_to_printable2(uni_stat_t *stats, constchar *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命令也是可以支援中文的。同時也可以進入中文目錄可以資料夾。

3.3進入busybox原始碼目錄下,配置支援Unicode

$make menuconfig

Busybox Configuration

Busybox Settings  --->

General Configuration  --->

[*] Support Unicode                                                                         

[*]   Check $LANG environment variable                                                      

(63)  Character code to substitute unprintable characters with

(767) Range of supported Unicode characters                                                 

[ ]   Allow zero-width Unicode characters on output                                         

[*]   Allow wide Unicode characters on output

3.4編譯生成新的busybox,拷貝到nfs檔案系統/bin資料夾下;

$make && make install

$cp _install/bin/busybox /DVRRDK_04.00.00.03/target/rfs_816x/bin/

測試

[[email protected]:/media/sda1]#:ls ls                                                                                                                                                  

2.txt                             新建 Microsoft Word 文件.docx

System Volume Information          新建文字文件123.txt

4自動掛載

我主要是針對mount -t ntfs-3g /dev/sda1 /mnt 不可以使用,在網上找了找論壇,發現都是講mdev;但我的核心Linux/arm 2.6.37 Kernel,支援udev。

udev的規則檔案以行為單位,以”#”開頭的行代表註釋行。其餘的每一行代表一個規則。每個規則分成一個或多個“匹配”和“賦值”部分。“匹配”部分用“匹配“專用的關鍵字來表示,相應的“賦值”部分用“賦值”專用的關鍵字來表示。“匹配”關鍵字包括:ACTION,KERNEL,BUS,SYSFS等等,“賦值”關鍵字包括:NAME,SYMLINK,OWNER等等。具體詳細的描述可以閱讀udev的man文件。

下面舉個例子來說明一下,有這樣一條規則:SUBSYSTEM==”net”, ACTION==”add”, SYSFS{address}==”00:0d:87:f6:59:f3″, IMPORT=”/sbin/rename_netiface %k eth0″
這個規則中的“匹配”部分有三項,分別是SUBSYSTEM,ACTION和SYSFS。而”賦值”部分有一項,是IMPORT。這個規則就是說,當系統中出現的新硬體屬於net子系統範疇,系統對該硬體採取的動作是加入這個硬體,且這個硬體在SYSFS檔案系統中的“address”資訊等於“00:0d…”時,對這個硬體在udev層次施行的動作是呼叫外部程式/sbin/rename_netiface,傳遞的引數有兩個,一個是“%k”,代表核心對該新裝置定義的名稱。另一個是”eth0“。    從上面這個例子中可以看出,udev的規則的寫法比較靈活的,尤其在“匹配”部分中,可以通過諸如”*“, ”?“,[a-c],[1-9]等shell萬用字元來靈活匹配多個匹配項。具體的語法可以參考udev的man文件。

4.1找到規則檔案

$vi /DVRRDK_04.00.00.03/target/rfs_816x/etc/udev/rules.d/local.rules

找到塊裝置的掛載規則如下:

# media automounting

SUBSYSTEM=="block", ACTION=="add"    RUN+="/etc/udev/scripts/mount.sh"

SUBSYSTEM=="block", ACTION=="remove" RUN+="/etc/udev/scripts/mount.sh"

4.2開啟mount.sh檔案修改。

紅色部分為修改的,目的是:

if mount -t auto -o utf8 /裝置檔案 /掛載目錄

else ntfs-3g -o utf8 /裝置檔案 /掛載目錄

$vi mount.sh

#!/bin/sh

#

# Called from udev

#

# Attempt to mount any added block devices and umount any removed devices

MOUNT="/bin/mount"

PMOUNT="/usr/bin/pmount"

UMOUNT="/bin/umount"

NTFS="/bin/ntfs-3g"

for line in `cat /etc/udev/mount.blacklist`

do

        if [ ` expr match "$DEVNAME" "$line" ` -gt 0 ];

        then

                logger "udev/mount.sh" "[$DEVNAME] is blacklisted, ignoring"

                exit 0

        fi

done

automount() {

        name="`basename "$DEVNAME"`"

        ! test -d "/media/$name" && mkdir -p "/media/$name"

        if $MOUNT -t auto -o utf8 $DEVNAME "/media/$name"

        then

                logger "mount.sh/automount" "Auto-mount of [/media/$name] successful"

                touch "/tmp/.automount-$name"

        elif $NTFS -o utf8 $DEVNAME "/media/$name"

        then

                logger "mount.sh/ntfs-3g" "Auto-mount of [/media/$name] successful"

                touch "/tmp/.automount-$name"

        else

                #logger "mount.sh/automount" "$MOUNT -t auto $DEVNAME \"/media/$name\" failed!"

                rm_dir "/media/$name"

        fi

}

rm_dir() {

        # We do not want to rm -r populated directories

        if test "`find "$1" | wc -l | tr -d " "`" -lt 2 -a -d "$1"

        then

                ! test -z "$1" && rm -r "$1"

        else

                logger "mount.sh/automount" "Not removing non-empty directory [$1]"

        fi

}

if [ "$ACTION" = "add" ] && [ -n "$DEVNAME" ]; then

        if [ -x "$PMOUNT" ]; then

                $PMOUNT $DEVNAME 2> /dev/null

        elif [ -x $MOUNT ]; then

                $MOUNT $DEVNAME 2> /dev/null

        fi

        # If the device isn't mounted at this point, it isn't configured in fstab

        grep -q "^$DEVNAME " /proc/mounts || automount

fi

if [ "$ACTION" = "remove" ] && [ -x "$UMOUNT" ] && [ -n "$DEVNAME" ]; then

        for mnt in `cat /proc/mounts | grep "$DEVNAME" | cut -f 2 -d " " `

        do

                $UMOUNT $mnt

        done

        # Remove empty directories from auto-mounter

        name="`basename "$DEVNAME"`"

        test -e "/tmp/.automount-$name" && rm_dir "/media/$name"

Fi

儲存退出測試一下,ok,能自動掛載了,並且FAT32U盤的檔案也可以支援中文了。