admin管理员组

文章数量:1529449

Android10 U盘支持EXFAT和NTFS

前言
大家知道目前安卓AOSP只支持FAT32,还不支持EXFAT和NTFS,这两种windows支持的格式使用上还是比较普遍的,所以安卓也能支持那就相当nice了,不然安卓就会提醒让格式化,这是很危险的,格式化后数据就丢失了,目前网上有很多资料可以实现安卓支持EXFAT/NTFS,特别是EXFAT,参照资料就能完美的支持,但是NTFS就没那么明确,我这里根据之前的经验做个总结,方便大家参考

系统信息:
Android10
kernel 4.19

第一步需要kernel支持EXFAT和NTFS
kernel中移植exfat-nofuse

源码:https://github/dorimanx/exfat-nofuse

将代码下载解压后,更名exfat放到kernel/fs下, 修改kernel下Kconfig、Makefile:

diff
-git a/kernel/fs/Kconfigb/kernel/fs/Kconfig
index b8d003f. .65ce644 100644
a/kernel/fs/Kconfig
+ b/kernel/fs/Kconfig
60 - 133,10 +133,11 ea endmenu
endif # BLOCK
if BLOCK
source "fs/fat/Kconfig"
source "fs/ntfs/Kconfig"
+source "fs/exfat/Kconfig
endmenu
endif # BLOCK
diff --git a/kernel/fs/Makefile b/kernel/fs/Makefile
index 5030ac9. .d6c02f2 100644
a/kernel/fs/Makefile
+ b/kernel/fs/Makefile
60 -80,6 +80,7 (@ obj -$(CONFIG_HUGETLBFS)+= hugetlbfs/
obj-(CONFIG_MINIX_FS)+= minix/
obj-(CONFIG_FAT_FS)+= fat/
+ obj-(CONFIG_EXFAT_FS)+= exfat/
+ obj-(CONFIG_NTFS_FS)+= ntfs/
obj-(CONFIG_BFS_FS)+= bfs/
obj-(CONFIG_IS09660_FS)+=isofs/

在kernel默认编译配置文件中打开NTFS和EXFAT配置:

@@ -927,3 +927,6 CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_BUG_ON_DATA_CORRUPTION=Y
CONFIG_LEDS_AM20108=y
+CONFIG_NTFS_FS=Y
+CONETG_NTES_BW=Y
+CONFIG_EXFAT_FS=Y

编译kernel,生产的image替换后,通过cat /proc/filesystems查看,有exfat和ntfs就可以了(图片来自网络)

移植fuse:
https://github/Shawnsongs/Android_P_external_exfat_ntfs-3g/tree/master/external-exfat-fuse

下载后改名exfat放到external中,编译生成mkfs.exfat和fsck.exfat

目前AOSP已经在system/vold/fs/Exfat.cpp支持EXFAT,所以当上一步kennel已经加载exfat,exfat应该已经可以使用了,如果还是不行就需要看下是不是selinux的问题,selinux的比较简单,只需要针对缺少的权限加上就可以了

但是ntfs的源码是没有的,这里我们可以参考EXFAT来模拟写一份

Ntfs.cpp

/*
   * Copyright (C) 2018 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  #include <sys/mount.h>
  
  #include <android-base/logging.h>
  #include <android-base/stringprintf.h>
  
  #include <logwrap/logwrap.h>
  
  #include "Ntfs.h"
  #include "Utils.h"
  
  using android::base::StringPrintf;
  
  namespace android {
  namespace vold {
  namespace ntfs {
  
  static const char* kNtfsPath = "/system/bin/ntfs-3g";
  
  bool IsSupported() {
      return access(kNtfsPath, X_OK) == 0 &&
             IsFilesystemSupported("ntfs");
  }
  
  status_t Check(const std::string& source) {
      return 0;
  }
  
  status_t Mount(const std::string& source, const std::string& target, int ownerUid, int ownerGid,
                 int permMask) {
      int mountFlags = MS_NODEV | MS_NOSUID | MS_DIRSYNC | MS_NOATIME | MS_NOEXEC;
      auto mountData = android::base::StringPrintf("uid=%d,gid=%d,fmask=%o,dmask=%o", ownerUid,
                                                   ownerGid, permMask, permMask);
  
      if (mount(source.c_str(), target.c_str(), "ntfs", mountFlags, mountData.c_str()) == 0) {
          return 0;
      }
  
      PLOG(ERROR) << "Mount failed; attempting read-only";
      mountFlags |= MS_RDONLY;
      if (mount(source.c_str(), target.c_str(), "ntfs", mountFlags, mountData.c_str()) == 0) {
          return 0;
      }
  
      return -1;
  }
  
  status_t Format(const std::string& source) {
      return 0;
  }
  
  }  // namespace exfat
  }  // namespace vold
  }  // namespace android

Ntfs.h

  /*
   * Copyright (C) 2018 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  #include <utils/Errors.h>
  
  #include <string>
  
  namespace android {
  namespace vold {
  namespace ntfs {
  
  bool IsSupported();
  
  status_t Check(const std::string& source);
  status_t Mount(const std::string& source, const std::string& target, int ownerUid, int ownerGid,
                 int permMask);
  status_t Format(const std::string& source);
  
  }  // namespace ntfs
  }  // namespace vold
  }  // namespace android
  
  #endif

把这两个文件加入到Exfat.cpp同目录下,再修改/system/vold/model/PublicVolume.cpp跟exfat相同的地方加上ntfs,这里我们不支持格式化成ntfs了

status_t PublicVolume::doMount() {
      readMetadata();
  
      if (mFsType == "vfat" && vfat::IsSupported()) {
          if (vfat::Check(mDevPath)) {
              LOG(ERROR) << getId() << " failed filesystem check";
              return -EIO;
          }
      } else if (mFsType == "exfat" && exfat::IsSupported()) {
          if (exfat::Check(mDevPath)) {
              LOG(ERROR) << getId() << " failed filesystem check";
              return -EIO;
          }
      +} else if (mFsType == "ntfs" && exfat::IsSupported()) {
      +    if (exfat::Check(mDevPath)) {
      +        LOG(ERROR) << getId() << " failed filesystem check";
      +        return -EIO;
      +    }
      } 
	......
	if (mFsType == "vfat") {
          if (vfat::Mount(mDevPath, mRawPath, false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007,
                          true)) {
              PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
              return -EIO;
          }
      } else if (mFsType == "exfat") {
          if (exfat::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) {
              PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
              return -EIO;
          }
      +}else if (mFsType == "ntfs") {
      +    if (ntfs::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) {
      +        PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
      +        return -EIO;
      +    }
      }

ntfs-3g网上可以下载到bin档可以直接使用,并且ntfs支持会有selinux问题,这块需要针对性修改,到此,EXFAT和NTFS就已经支持了,如有问题,可以联系我大家讨论。

本文标签: exFATNTFS