CyanogenMod 10 修改 Vold 使 Android 自动挂载 NTFS 和 exFAT 格式的 SD 卡
2013-04-25 18:37
549 查看
Android 不支持 NTFS 和 exFAT 格式的文件系统,但是 Linux 已经有相应的开源代码了,因此只需将其移植到 Android 上即可。
这里需要下载两份代码,分别是 ntfs-3g 和 exfat。下载地址
ntfs-3g exfat 。
由于 Android 并没有使用完整的 glibc 库,因此需要对源代码进行修改以使代码能被顺利地编译。
代码与编译好的文件都可以在 CSDN 资源里下载:
CyanogenMod10 ntfs 与 exfat 自动挂载支持
将
大约位于 283 行的 exfat_pread 函数,将里面的 pread 函数改为 pread64;
大约位于 295 行的 exfat_pwrite 函数,将里面的 pwrite 函数改为 pwrite64。
在 system 目录新建 libfuse 文件夹,并建立子文件夹 src 和 include。将 ntfs-3g 中 libfuse-lite 中的所有文件复制到 libfuse/src 目录中,将 ntfs-3g 中 include/fuse-lite 中的所有文件复制到 libfuse/include 目录中,将 ntfs-3g 中的 config.h 复制到 libfuse 目录。
修改 libfuse/src/helper.c,在最后添加如下代码(exfat 需要):
在 libfuse 目录编写 Android.mk:
在 system 目录新建 ntfs-3g 文件夹,并建立子文件夹 include、libntfs-3g 和 src。将 ntfs-3g 中 include/ntfs-3g 中的所有文件复制到 ntfs-3g/include 目录中,将 ntfs-3g 中 libntfs-3g 中的所有文件复制到 ntfs-3g/libntfs-3g 目录中,将 ntfs-3g 中 src 目录中的 ntfs-3g.c ntfs-3g_common.c ntfs-3g_common.h
复制到 ntfs-3g/src 目录中,将 ntfs-3g 中的 config.h 复制到 ntfs-3g 目录。
在 ntfs-3g 目录中编写 Android.mk:
在 system 目录下建立 ntfsfix 目录,并建立子目录 src。将 ntfs-3g 中 ntfsprogs 中的 ntfsfix.c sd.c sd.h utils.c utils.h 复制到 ntfsfix/src 目录,将 ntfs-3g 中的 config.h 复制到 ntfsfix 目录。
在 ntfsfix 目录下建立 Android.mk:
在 system 目录下建立 mkntfs 目录,并建立子目录 src。将 ntfs-3g 中 ntfsprogs 中的 attrdef.c attrdef.h boot.c boot.h mkntfs.c sd.c sd.h utils.c utils.h 复制到 mkntfs/src 目录,将 ntfs-3g 中的 config.h 复制到 mkntfs 目录。
在 mkntfs 目录下建立 Android.mk:
在 system 目录下建立 exfat 目录。将 exfat 源代码中的 fuse 和 libexfat 文件夹复制到 exfat 目录中。
建立 Android.mk:
在 system 目录建立 exfatfsck 目录,并将 exfat 源代码中 fsck/main.c 复制到 exfatfsck 目录中。
建立 Android.mk(这里只列出关键的两行):
在 system 目录下建立 mkexfatfs 目录,并建立子目录 src。将 exfat 源代码中 mkfs 目录下的所有文件复制到 mkexfatfs/src 目录中。
建立 Android.mk(关键部分):
check 函数:
doMount 函数:
format 函数:
关键代码:
找到 Volume::mountVol() 函数
找到 else if (strcmp(fstype, "ntfs") == 0) 部分,在后面添加以下代码:
找到和 if (fstype != NULL) 对应的 else 块,在后面添加以下代码:
然后转到 if (fstype != NULL) 的 else 的末尾,在语句块之后,SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint()); 之前添加 mountSuccess: 跳转标签。
这里需要下载两份代码,分别是 ntfs-3g 和 exfat。下载地址
ntfs-3g exfat 。
由于 Android 并没有使用完整的 glibc 库,因此需要对源代码进行修改以使代码能被顺利地编译。
代码与编译好的文件都可以在 CSDN 资源里下载:
CyanogenMod10 ntfs 与 exfat 自动挂载支持
一、修改 ntfs-3g 代码
关于 ntfs-3g 代码的修改,可以参考 CSDN 上的这篇文章:ntfs-3g移植到android4.0.3方法总结。这里就不在重复叙述了。二、修改 exfat 代码
exfat 也是使用了 fuse,但代码量很小。需要修改的地方不多:1、fuse/main.c 文件
大约位于 264 行的 fuse_exfat_statfs 函数,将参数中的 statvfs 改为 statfs,并将其代码中的 sfs->f_namemax 改为 sfs->f_namelen将
sfs->f_favail = sfs->f_bfree >> ef.sb->spc_bits; sfs->f_ffree = sfs->f_bavail;改为
sfs->f_ffree = sfs->f_bfree >> ef.sb->spc_bits;
2、libexfat/io.c
大约位于 255 行的 exfat_seek 函数,将里面的 lseek 函数改为 lseek64;大约位于 283 行的 exfat_pread 函数,将里面的 pread 函数改为 pread64;
大约位于 295 行的 exfat_pwrite 函数,将里面的 pwrite 函数改为 pwrite64。
3、将所有代码文件中的 off_t 类型全部换为 off64_t 类型
Android 的编译器编译出来的 off_t 类型是4字节的,只有改为 off64_t 才是8字节的。不改的话无法挂载超过 4G 的 SD 卡或 U 盘。三、提取文件,编写 Android.mk 文件
这里我将所有的项目都放在了和 vold 同级的 system 目录下1、libfuse
由于 ntfs-3g 和 exfat 都使用了 fuse,因此他们可以共享这个库。在 system 目录新建 libfuse 文件夹,并建立子文件夹 src 和 include。将 ntfs-3g 中 libfuse-lite 中的所有文件复制到 libfuse/src 目录中,将 ntfs-3g 中 include/fuse-lite 中的所有文件复制到 libfuse/include 目录中,将 ntfs-3g 中的 config.h 复制到 libfuse 目录。
修改 libfuse/src/helper.c,在最后添加如下代码(exfat 需要):
int fuse_daemonize(int foreground) { int res; if (!foreground) { res = daemon(0, 0); if (res == -1) { perror("fuse: failed to daemonize program\n"); return -1; } } return 0; }
在 libfuse 目录编写 Android.mk:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ src/fuse.c \ src/fusermount.c \ src/fuse_kern_chan.c \ src/fuse_loop.c \ src/fuse_lowlevel.c \ src/fuse_opt.c \ src/fuse_session.c \ src/fuse_signals.c \ src/helper.c \ src/mount.c \ src/mount_util.c LOCAL_C_INCLUDES:= $(LOCAL_PATH)/include LOCAL_CFLAGS:= -O2 -g -W -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CONFIG_H LOCAL_MODULE:= libfuse LOCAL_MODULE_TAGS:=eng LOCAL_SYSTEM_SHARED_LIBRARIES:= libc libcutils include $(BUILD_STATIC_LIBRARY)
2、ntfs-3g
则里只提取挂载 NTFS 分区的文件。在 system 目录新建 ntfs-3g 文件夹,并建立子文件夹 include、libntfs-3g 和 src。将 ntfs-3g 中 include/ntfs-3g 中的所有文件复制到 ntfs-3g/include 目录中,将 ntfs-3g 中 libntfs-3g 中的所有文件复制到 ntfs-3g/libntfs-3g 目录中,将 ntfs-3g 中 src 目录中的 ntfs-3g.c ntfs-3g_common.c ntfs-3g_common.h
复制到 ntfs-3g/src 目录中,将 ntfs-3g 中的 config.h 复制到 ntfs-3g 目录。
在 ntfs-3g 目录中编写 Android.mk:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ libntfs-3g/acls.c libntfs-3g/attrib.c libntfs-3g/attrlist.c \ libntfs-3g/bitmap.c libntfs-3g/bootsect.c libntfs-3g/cache.c \ libntfs-3g/collate.c libntfs-3g/compat.c libntfs-3g/compress.c \ libntfs-3g/debug.c libntfs-3g/device.c libntfs-3g/dir.c \ libntfs-3g/efs.c libntfs-3g/index.c libntfs-3g/inode.c \ libntfs-3g/lcnalloc.c libntfs-3g/logfile.c libntfs-3g/logging.c \ libntfs-3g/mft.c libntfs-3g/misc.c libntfs-3g/mst.c \ libntfs-3g/object_id.c libntfs-3g/realpath.c libntfs-3g/reparse.c \ libntfs-3g/runlist.c libntfs-3g/security.c libntfs-3g/unistr.c \ libntfs-3g/unix_io.c libntfs-3g/volume.c LOCAL_C_INCLUDES:= $(LOCAL_PATH)/include system/libfuse/include LOCAL_CFLAGS:= -O2 -g -W -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CONFIG_H LOCAL_MODULE:= libntfs-3g LOCAL_MODULE_TAGS:=eng LOCAL_SYSTEM_SHARED_LIBRARIES:= libc libcutils include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ src/ntfs-3g.c src/ntfs-3g_common.c LOCAL_C_INCLUDES:= $(LOCAL_PATH)/include $(LOCAL_PATH)/src system/libfuse/include LOCAL_CFLAGS:= -O2 -g -W -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CONFIG_H LOCAL_MODULE:= ntfs-3g LOCAL_MODULE_TAGS:=eng LOCAL_SYSTEM_SHARED_LIBRARIES:= libc LOCAL_STATIC_LIBRARIES:= libfuse libntfs-3g include $(BUILD_EXECUTABLE)
3、ntfsfix
这个是用来在挂载 NTFS 分区前检查错误的。在 system 目录下建立 ntfsfix 目录,并建立子目录 src。将 ntfs-3g 中 ntfsprogs 中的 ntfsfix.c sd.c sd.h utils.c utils.h 复制到 ntfsfix/src 目录,将 ntfs-3g 中的 config.h 复制到 ntfsfix 目录。
在 ntfsfix 目录下建立 Android.mk:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ src/ntfsfix.c \ src/utils.c \ src/sd.c LOCAL_C_INCLUDES:= $(LOCAL_PATH)/src system/ntfs-3g/include LOCAL_CFLAGS:= -O2 -g -W -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CONFIG_H LOCAL_MODULE:= ntfsfix LOCAL_MODULE_TAGS:=eng LOCAL_SYSTEM_SHARED_LIBRARIES:= libc LOCAL_STATIC_LIBRARIES:= libntfs-3g libfuse include $(BUILD_EXECUTABLE)
4、mkntfs
这个是用来格式化分区为 NTFS 格式的。在 system 目录下建立 mkntfs 目录,并建立子目录 src。将 ntfs-3g 中 ntfsprogs 中的 attrdef.c attrdef.h boot.c boot.h mkntfs.c sd.c sd.h utils.c utils.h 复制到 mkntfs/src 目录,将 ntfs-3g 中的 config.h 复制到 mkntfs 目录。
在 mkntfs 目录下建立 Android.mk:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ src/attrdef.c \ src/boot.c \ src/utils.c \ src/mkntfs.c \ src/sd.c LOCAL_C_INCLUDES:= $(LOCAL_PATH)/src system/ntfs-3g/include LOCAL_CFLAGS:= -O2 -g -W -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DHAVE_CONFIG_H LOCAL_MODULE:= mkntfs LOCAL_MODULE_TAGS:=eng LOCAL_SYSTEM_SHARED_LIBRARIES:= libc LOCAL_STATIC_LIBRARIES:= libntfs-3g libfuse include $(BUILD_EXECUTABLE)
5、exfat
这里只提取挂载 exFAT 分区所需的文件。在 system 目录下建立 exfat 目录。将 exfat 源代码中的 fuse 和 libexfat 文件夹复制到 exfat 目录中。
建立 Android.mk:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ libexfat/cluster.c libexfat/io.c libexfat/log.c \ libexfat/lookup.c libexfat/mount.c libexfat/node.c \ libexfat/time.c libexfat/utf.c libexfat/utils.c LOCAL_C_INCLUDES:= $(LOCAL_PATH)/libexfat system/libfuse/include LOCAL_CFLAGS:= -O2 -g -W -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -UUSE_UBLIO LOCAL_MODULE:= libexfat LOCAL_MODULE_TAGS:=eng LOCAL_SYSTEM_SHARED_LIBRARIES:= libc libcutils include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ fuse/main.c LOCAL_C_INCLUDES:= $(LOCAL_PATH)/libexfat system/libfuse/include LOCAL_CFLAGS:= -O2 -g -W -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DUSE_UBLIO LOCAL_MODULE:= exfat LOCAL_MODULE_TAGS:=eng LOCAL_SYSTEM_SHARED_LIBRARIES:= libc LOCAL_STATIC_LIBRARIES:= libfuse libexfat include $(BUILD_EXECUTABLE)
6、exfatfsck
这个是用来在挂载 exFAT 分区前检查错误的。在 system 目录建立 exfatfsck 目录,并将 exfat 源代码中 fsck/main.c 复制到 exfatfsck 目录中。
建立 Android.mk(这里只列出关键的两行):
LOCAL_SRC_FILES:= \ main.c LOCAL_C_INCLUDES:= $(LOCAL_PATH)/src system/exfat/libexfat
7、mkexfatfs
这个是用来格式化分区为 exFAT 格式的。在 system 目录下建立 mkexfatfs 目录,并建立子目录 src。将 exfat 源代码中 mkfs 目录下的所有文件复制到 mkexfatfs/src 目录中。
建立 Android.mk(关键部分):
LOCAL_SRC_FILES:= \ src/cbm.c \ src/fat.c \ src/main.c \ src/mkexfat.c \ src/rootdir.c \ src/uct.c \ src/uctc.c \ src/vbr.c LOCAL_C_INCLUDES:= $(LOCAL_PATH)/src system/exfat/libexfat
四、修改 vold 代码
CyanogenMod 的 vold 代码包含了 Ntfs.cpp 和 Ntfs.h,但是需要修改1、修改 Ntfs.cpp
添加全局变量:static char MOUNT_NTFS_PATH[] = "/system/bin/ntfs-3g"; static char MKNTFS_PATH[] = "/system/bin/mkntfs"; static char NTFSFIX_PATH[] = "/system/bin/ntfsfix";
check 函数:
int Ntfs::check(const char *fsPath) { bool rw = true; if (access(NTFSFIX_PATH, X_OK)) { SLOGW("Skipping fs checks\n"); return 0; } int rc = -1; do { const char *args[3]; args[0] = NTFSFIX_PATH; args[1] = fsPath; args[2] = NULL; rc = logwrap(3, args, 1); switch(rc) { case 0: SLOGI("NTFS Filesystem check completed OK.\n"); return 0; case 1: SLOGI("NTFS Filesystem check failed.\n"); return 0; default: SLOGE("NTFS Filesystem check failed (unknown exit code %d).\n", rc); errno = EIO; return -1; } } while (0); return 0; }
doMount 函数:
int Ntfs::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, bool executable, int ownerUid, int ownerGid, int permMask, bool createLost) { int rc; unsigned long flags; char mountData[255]; char options[255] = {}; const char *args[6]; flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC; flags |= (executable ? 0 : MS_NOEXEC); flags |= (ro ? MS_RDONLY : 0); flags |= (remount ? MS_REMOUNT : 0); // Testing/security, mount ro up to now flags |= MS_RDONLY; /* * Note: This is a temporary hack. If the sampling profiler is enabled, * we make the SD card world-writable so any process can write snapshots. * * TODO: Remove this code once we have a drop box in system_server. */ char value[PROPERTY_VALUE_MAX]; property_get("persist.sampling_profiler", value, ""); if (value[0] == '1') { SLOGW("The SD card is world-writable because the" " 'persist.sampling_profiler' system property is set to '1'."); permMask = 0; } sprintf(mountData, "uid=%d,gid=%d,fmask=%o,dmask=%o", ownerUid, ownerGid, permMask, permMask); if (!remount) { SLOGI("Trying to use ntfs-3g program to mount %s", fsPath); if (ro) snprintf(options, sizeof(options), "ro,%s", mountData); else snprintf(options, sizeof(options), "%s", mountData); args[0] = MOUNT_NTFS_PATH; args[1] = "-o"; args[2] = options; args[3] = fsPath; args[4] = mountPoint; args[5] = NULL; rc = logwrap(6, args, 1); if (rc == 0) { SLOGI("ntfs-3g executed successfully."); } else { SLOGE("Failed to execute ntfs-3g."); } } else { rc = mount(fsPath, mountPoint, "fuseblk", flags, mountData); } if (rc && errno == EROFS) { SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath); flags |= MS_RDONLY; if (!remount) { SLOGI("Trying to use ntfs-3g program to mount %s as read-only", fsPath); snprintf(options, sizeof(options), "ro,%s", mountData); args[0] = MOUNT_NTFS_PATH; args[1] = "-o"; args[2] = options; args[3] = fsPath; args[4] = mountPoint; args[5] = NULL; rc = logwrap(6, args, 1); if (rc == 0) { SLOGI("ntfs-3g executed successfully for read-only."); } else { SLOGE("Failed to execute ntfs-3g for read-only."); } } else { rc = mount(fsPath, mountPoint, "fuseblk", flags, mountData); } } return rc; }
format 函数:
int Ntfs::format(const char *fsPath, unsigned int numSectors) { const char *args[5]; char strNumOfSectors[16] = {}; int rc; args[0] = MKNTFS_PATH; args[1] = "-f"; args[2] = fsPath; if (numSectors) { snprintf(strNumOfSectors, sizeof(strNumOfSectors), "%u", numSectors); args[3] = strNumOfSectors; args[4] = NULL; rc = logwrap(5, args, 1); } else { args[3] = NULL; rc = logwrap(4, args, 1); } if (rc == 0) { SLOGI("Filesystem formatted OK"); return 0; } else { SLOGE("Format failed (unknown exit code %d)", rc); errno = EIO; return -1; } return 0; }
2、添加 ExFat.h 和 ExFat.cpp
这里请使用 Ntfs.h 和 Ntfs.cpp 作为模板。关键代码:
static char MOUNT_EXFAT_PATH[] = "/system/bin/exfat"; static char MKFS_EXFAT_PATH[] = "/system/bin/mkexfatfs"; static char FSCK_EXFAT_PATH[] = "/system/bin/exfatfsck"; int ExFat::check(const char *fsPath) { bool rw = true; if (access(FSCK_EXFAT_PATH, X_OK)) { SLOGW("Skipping fs checks\n"); return 0; } int rc = -1; do { const char *args[3]; args[0] = FSCK_EXFAT_PATH; args[1] = fsPath; args[2] = NULL; rc = logwrap(3, args, 1); switch(rc) { case 0: SLOGI("exFAT Filesystem check completed OK.\n"); return 0; case 1: SLOGI("exFAT Filesystem check failed.\n"); return 0; default: SLOGE("exFAT Filesystem check failed (unknown exit code %d).\n", rc); errno = EIO; return -1; } } while (0); return 0; } int ExFat::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, bool executable, int ownerUid, int ownerGid, int permMask, bool createLost) { int rc; unsigned long flags; char mountData[255]; const char *args[4]; flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC; flags |= (executable ? 0 : MS_NOEXEC); flags |= (ro ? MS_RDONLY : 0); flags |= (remount ? MS_REMOUNT : 0); // Testing/security, mount ro up to now flags |= MS_RDONLY; sprintf(mountData, "uid=%d,gid=%d,fmask=%o,dmask=%o", ownerUid, ownerGid, permMask, permMask); if (!remount) { SLOGI("Trying to use exfat program to mount %s", fsPath); args[0] = MOUNT_EXFAT_PATH; args[1] = fsPath; args[2] = mountPoint; args[3] = NULL; rc = logwrap(4, args, 1); if (rc == 0) { SLOGI("exfat executed successfully."); } else { SLOGE("Failed to execute exfat."); } } else { rc = mount(fsPath, mountPoint, "fuseblk", flags, mountData); } return rc; } int ExFat::format(const char *fsPath, unsigned int numSectors) { const char *args[3]; char strNumOfSectors[16] = {}; int rc; args[0] = MKFS_EXFAT_PATH; args[1] = fsPath; args[2] = NULL; rc = logwrap(3, args, 1); if (rc == 0) { SLOGI("Filesystem formatted OK"); return 0; } else { SLOGE("Format failed (unknown exit code %d)", rc); errno = EIO; return -1; } return 0; }
3、修改 Volume.cpp
添加 #include "Ntfs.h"找到 Volume::mountVol() 函数
找到 else if (strcmp(fstype, "ntfs") == 0) 部分,在后面添加以下代码:
if (Ntfs::check(devicePath)) { errno = EIO; /* Badness - abort the mount */ SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); setState(Volume::State_Idle); free(fstype); return -1; }
找到和 if (fstype != NULL) 对应的 else 块,在后面添加以下代码:
//Check if the filesystem is exFAT FILE *volf = fopen(devicePath, "rb"); int bytesRead = 0; if (volf) { char fschar[5]; //Read the signature in the PBR fseek(volf, 3, SEEK_SET); bytesRead = fread(fschar, 1, 5, volf); fclose(volf); if (bytesRead == 5 && strcmp(fschar, "EXFAT") == 0) { if (ExFat::check(devicePath)) { errno = EIO; /* Badness - abort the mount */ SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); setState(Volume::State_Idle); free(fstype); return -1; } if (ExFat::doMount(devicePath, "/mnt/secure/staging", false, false, false, AID_SYSTEM, gid, 0702, true)) { SLOGE("%s failed to mount via exFAT (%s)\n", devicePath, strerror(errno)); continue; } else { goto mountSuccess; } } }
然后转到 if (fstype != NULL) 的 else 的末尾,在语句块之后,SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint()); 之前添加 mountSuccess: 跳转标签。
4、修改 vold 的 Android.mk
天际 common_src_files += ExFat.c五、修改 build/target/product/base.mk
添加PRODUCT_PACKAGES += \ libfuse \ ntfs-3g \ exfat \ mkntfs \ ntfsfix \ mkexfatfs \ exfatfsck
六、编译
如果不出意外的话,编译之后就可以直接使用了。相关文章推荐
- CyanogenMod 10 修改 Vold 使 Android 自动挂载 NTFS 和 exFAT 格式的 SD 卡
- Linux系统下挂载exFAT和NTFS格式硬盘的驱动安装和配置
- 解决LINUX下无法自动挂载NTFS文件格式的移动硬盘访问
- Debian Wheezy 64 - 解决插ntfs格式的u盘或者移动硬盘时报错,不能自动挂载
- Android真机调试自动点亮屏幕(基于CyanogenMod源码修改)
- SUSE LINUX 11.1自动挂载NTFS格式移动硬盘
- Linux系统下挂载exFAT和NTFS格式硬盘的驱动安装和配置
- linux下USB移动硬盘NTFS格式自动挂载
- Linux系统下挂载exFAT和NTFS格式硬盘的驱动安装和配置(原创)
- linux自动挂载NTFS格式移动硬盘
- SUSE 10.3实现开机自动挂载硬盘,ntfs和fat格式
- CentOS6.2自动挂载ntfs格式磁盘
- 如何让 Android 自动挂载 SD 卡
- Android源码分析系列-整理篇 ------ 关于Vold 自动挂载部分
- Android—— 4.2 Vold挂载管理_mmcblk内置-双sdcard (八)
- Linux自动挂载NTFS格式硬盘
- 如何让 Android 自动挂载 SD 卡
- Linux系统下挂载exFAT和NTFS格式硬盘的驱动安装和配置
- 【Linux】Linux 自动挂载NTFS格式移动硬盘
- OSX 挂载 NTFS 格式硬盘