前面对usb挂载的流程及各种格式的支持做了分析,这一篇也基本是收尾篇了,主要是把各种格式的挂载在vold模块种加进去,这里对这部分做了一些更改,如直接 挂载到/mnt/sdcard,没有先挂载到/mnt/secure/staging,还有把一些状态的转换去掉了,以及格式化、格式检查的去掉了,因为暂时还没听到这方面的奢求,哈哈,也是为了省事吧,这里把所有的挂载都在一个文件中实现了,先看下Android.mk

BUILD_VOLD2 := falseifneq ($(TARGET_SIMULATOR),true)    BUILD_VOLD2 := trueendififeq ($(BUILD_VOLD2),true)LOCAL_PATH:= $(call my-dir)common_src_files := \VolumeManager.cpp \CommandListener.cpp \VoldCommand.cpp \NetlinkManager.cpp \NetlinkHandler.cpp \Volume.cpp \DirectVolume.cpp \logwrapper.c \Process.cpp \StorageMount.cpp \Loop.cpp \Devmapper.cpp \ResponseCode.cpp \Xwarp.cppcommon_c_includes := \$(KERNEL_HEADERS) \kernel/include \external/openssl/include   ...
这里去掉了FAT.cpp,把真正的挂载都在StorageMount.cpp实现了。

对mountVol函数进行了修改。

int Volume::mountVol() {    dev_t deviceNodes[4];    int n, i, rc = 0;    char errmsg[255];    char  file_type[8]  = {0};    bool mountflat = false;    int loopCount = 10;loop:    if (getState() == Volume::State_NoMedia) {        snprintf(errmsg, sizeof(errmsg),                 "Volume %s %s mount failed - no media",                 getLabel(), getMountpoint());if(loopCount > 0){loopCount --;sleep(1);SLOGW("loopCount = %d.", loopCount);goto loop;}        mVm->getBroadcaster()->sendBroadcast(                                         ResponseCode::VolumeMountFailedNoMedia,                                         errmsg, false);        errno = ENODEV;        return -1;    } else if (getState() != Volume::State_Idle) {    if(loopCount > 0){loopCount --;sleep(1);SLOGW("loopCount = %d.", loopCount);goto loop;}        errno = EBUSY;        return -1;    }    if (isMountpointMounted(getMountpoint())) {        SLOGW("Volume is idle but appears to be mounted - fixing");        setState(Volume::State_Mounted);        // mCurrentlyMountedKdev = XXX        return 0;    }    n = getDeviceNodes((dev_t *) &deviceNodes, 4);    if (!n) {        SLOGE("Failed to get device nodes (%s)\n", strerror(errno));        return -1;    }    for (i = 0; i < n; i++) {        char devicePath[255];        int result = 0;        const char *disktype = "fat";        sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),                MINOR(deviceNodes[i]));        SLOGI("%s being considered for volume %s\n", devicePath, getLabel());        if((StorageMount::doMount(devicePath, "/mnt/secure/staging", false, false, 1000, 1015, 0702, true)) != 0)continue;        SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint());        protectFromAutorunStupidity();        if (createBindMounts()) {            SLOGE("Failed to create bindmounts (%s)", strerror(errno));            umount("/mnt/secure/staging");            setState(Volume::State_Idle);            return -1;        }        /*         * Now that the bindmount trickery is done, atomically move the         * whole subtree to expose it to non priviledged users.         */        if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) {            SLOGE("Failed to move mount (%s)", strerror(errno));            umount("/mnt/secure/staging");            setState(Volume::State_Idle);            return -1;        }        setState(Volume::State_Mounted);        mCurrentlyMountedKdev = deviceNodes[i];        return 0;    }    SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());    setState(Volume::State_Idle);    return -1;}
这里开始加了个loop,是因为有时候已经发送了VolumeDiskInserted给FrameWork层,FrameWork层会下发挂载命令,但在这里判断状态的时候不对,因为DirectVolume类中的handlePartitionAdded函数还未调用 完,未将状态改过来

在挂载的时候直接调用StorageMount::doMount进行挂载,这里代码还有点问题,没有去掉一些没用的代码。

int StorageMount::doMount(const char *fsPath, const char *mountPoint,                 bool ro, bool remount, int ownerUid, int ownerGid,                 int permMask, bool createLost) {int rc;unsigned long flags;char mountData[255];char filetype[8];int fd;bool mountDataFlag = true;enum ANDROID_FILESYSTEM_TYPE  e_filesystem_type = IPANEL_ANDROID_FILESYSTEM_UNKNOW;enum ANDROID_MOUNT_FLAG e_mount_flag = IPANEL_ANDROID_MOUNT_FLAG_FAT;flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC;flags |= (ro ? MS_RDONLY : 0);flags |= (remount ? MS_REMOUNT : 0);/** 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;}fd = open(fsPath, O_RDONLY | O_NONBLOCK, 777);if(fd < 0){return -1;}e_filesystem_type = disk_get_file_system(fd);switch(e_filesystem_type){case IPANEL_ANDROID_FILESYSTEM_NTFS:strcpy(filetype, "ntfs");e_mount_flag= IPANEL_ANDROID_MOUNT_FLAG_NTFS;break;case IPANEL_ANDROID_FILESYSTEM_FAT16:strcpy(filetype, "vfat");e_mount_flag= IPANEL_ANDROID_MOUNT_FLAG_NTFS;break;case IPANEL_ANDROID_FILESYSTEM_FAT32:strcpy(filetype, "vfat");e_mount_flag= IPANEL_ANDROID_MOUNT_FLAG_FAT;break;case IPANEL_ANDROID_FILESYSTEM_EXT2:strcpy(filetype, "ext2");e_mount_flag= IPANEL_ANDROID_MOUNT_FLAG_EXT;break;case IPANEL_ANDROID_FILESYSTEM_EXT3:strcpy(filetype, "ext3");e_mount_flag= IPANEL_ANDROID_MOUNT_FLAG_EXT;break;case IPANEL_ANDROID_FILESYSTEM_EXT4:strcpy(filetype, "ext4");e_mount_flag= IPANEL_ANDROID_MOUNT_FLAG_EXT;break;case IPANEL_ANDROID_FILESYSTEM_UNKNOW:SLOGE("filesystem unknow or not support");return -1;}if(IPANEL_ANDROID_MOUNT_FLAG_EXT == e_mount_flag|| IPANEL_ANDROID_MOUNT_FLAG_NTFS == e_mount_flag){sprintf(mountData, "uid=%d,gid=%d,fmask=%o,dmask=%o",           ownerUid, ownerGid, permMask, permMask);}else if(IPANEL_ANDROID_MOUNT_FLAG_FAT == e_mount_flag){sprintf(mountData, "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",           ownerUid, ownerGid, permMask, permMask);}else{}SLOGI("mountData = %s. \n", mountData);if(e_filesystem_type == IPANEL_ANDROID_FILESYSTEM_NTFS){const char *args[8];args[0] = "/system/bin/ntfs-3g";args[1] = fsPath;args[2] = mountPoint;args[3] = NULL;    rc = logwrap(7, args, 0);}else{rc = mount(fsPath, mountPoint, filetype, flags, mountData);}SLOGI("rc = %d.", rc);if (rc == 0 && createLost) {char *lost_path;asprintf(&lost_path, "%s/LOST.DIR", mountPoint);if (access(lost_path, F_OK)) {/** Create a LOST.DIR in the root so we have somewhere to put* lost cluster chains (fsck_msdos doesn't currently do this)*/if (mkdir(lost_path, 0075)) {SLOGE("Unable to create LOST.DIR (%s)", strerror(errno));}}free(lost_path);}return rc;ERR:return -1;}
这里会打开这个文件系统的,获取超级块,然后判断是什么类型的文件系统,再进行挂载,判断文件类型的函数:

ANDROID_FILESYSTEM_TYPE StorageMount::disk_get_file_system(int  fd){unsigned char fsystem[8];unsigned char FAT[8];int i;unsigned char *blockbuffer;int file_system;unsigned char hasjounal;int sec_size = disk_get_sector_size(fd);enum ANDROID_FILESYSTEM_TYPE  e_filesystem_type;SLOGW("lijj disk_get_file_system");blockbuffer = (unsigned char*)calloc(1,sec_size);disk_read_sector(fd, 0, blockbuffer);//dump_disk_sector(DBR,512);/*0x03--0x0a 为 OEM ID*/for (i = 0; i < 8; i++) //modify by yanglb (i<=8 Memory out of bounds)fsystem[i] = blockbuffer[0x3 + i];/*OEM ID 等于 "NTFS",则为NTFS文件系统*/if (    fsystem[0] == 0x4e && fsystem[1] == 0x54 && fsystem[2] == 0x46 && fsystem[3] == 0x53 && fsystem[4] == 0x20    && fsystem[5] == 0x20 && fsystem[6] == 0x20 && fsystem[7] == 0x20    ){e_filesystem_type = IPANEL_ANDROID_FILESYSTEM_NTFS;SLOGW("lijj IPANEL_ANDROID_FILESYSTEM_NTFS");goto FS_END;}/*FAT32 在 0x52-0x59描述了文件系统*/for (i = 0; i < 8; i++) //modify by yanglb (i<=8 Memory out of bounds)FAT[i] = blockbuffer[0x52 + i];if (    FAT[0] == 0x46 && FAT[1] == 0x41 && FAT[2] == 0x54 && FAT[3] == 0x33 && FAT[4] == 0x32 && FAT[5] == 0x20&& FAT[6] == 0x20 && FAT[7] == 0x20    ){e_filesystem_type = IPANEL_ANDROID_FILESYSTEM_FAT32; //FAT32SLOGW("lijj IPANEL_ANDROID_FILESYSTEM_FAT32");        goto FS_END;}/*FAT16在 0x36-0x3d字节描述了文件系统*/for (i = 0; i < 8; i++) //modify by yanglb (i<=8 Memory out of bounds)FAT[i] = blockbuffer[0x36 + i];if (    FAT[0] == 0x46 && FAT[1] == 0x41 && FAT[2] == 0x54 && FAT[3] == 0x31 && FAT[4] == 0x36 && FAT[5] == 0x20 && FAT[6] == 0x20 && FAT[7] == 0x20    ){        e_filesystem_type = IPANEL_ANDROID_FILESYSTEM_FAT16; //FAT16        SLOGW("lijj IPANEL_ANDROID_FILESYSTEM_FAT16");        goto FS_END;}if( blockbuffer[0x1FE] == 0x55 && blockbuffer[0x1FF] == 0xaa)goto FS_ERR;/*如果分区引导记录PBR没有描述NTFS,FAT,则查询是否为EXT*//*查询超级块,若0x38,0x39位和EXT格式的魔数吻合,则可确定为EXT*//*另根据无日志判断EXT2,有日志默认为EXT3*/memset(blockbuffer, 0, sec_size);disk_read_sector(fd,  2, blockbuffer);if (blockbuffer[0x38] != 0x53 || blockbuffer[0x39] != 0xef){goto  FS_ERR;}/*ext2 ext3 从0x178开始的后面几位都为0*/if (blockbuffer[0x178] != 0 || blockbuffer[0x179] != 0||blockbuffer[0x17a] != 0 || blockbuffer[0x17b] != 0||blockbuffer[0x17c] != 0 || blockbuffer[0x17d] != 0||blockbuffer[0x17e] != 0 || blockbuffer[0x17f] != 0){e_filesystem_type = IPANEL_ANDROID_FILESYSTEM_EXT4; //ext3        goto FS_END;}hasjounal = (blockbuffer[0x5c] >> 2) &0x1;if (hasjounal == 1){e_filesystem_type = IPANEL_ANDROID_FILESYSTEM_EXT3; //ext3        goto FS_END;}else{e_filesystem_type = IPANEL_ANDROID_FILESYSTEM_EXT2; //ext3        goto FS_END;}FS_END:free(blockbuffer);return e_filesystem_type;FS_ERR:e_filesystem_type = IPANEL_ANDROID_FILESYSTEM_UNKNOW;free(blockbuffer);return e_filesystem_type;}

这里ext4类型的判断粊笨拙,这里的方法是因为ext4超级块的结构比其它ext2 ext3大,后面的 这引起字段不为0,而其它两种格式这些字段都是0的。


类型判断好之后,就可以挂载了,这里根据不同的类型,挂载的时候参数或命令不一样。



更多相关文章

  1. android 中.9图片的用法 详解
  2. Android(安卓)TextView 判断文字内容是否超出显示省略号
  3. Android把svg图片转为jpg保存到相册图库
  4. YUV 400 格式图像转换成 ARGB 格式图像中犯的一个低级 Bug
  5. 【原创】Android(安卓)判断默认数据网络是否为开,若关则跳转到网
  6. android 判断当前所否为锁屏界面
  7. android app develop utils
  8. RingTest
  9. android调试中怎样使用gcc提供的工具

随机推荐

  1. Android中PopupWindow自定义坐标实现
  2. Android(安卓)屏幕旋转时保存状态
  3. Android(安卓)将View 转化为bitmap 图片
  4. Android(安卓)显示Emoji表情字符
  5. MAC中设置android adb环境变量
  6. 错误 'roundIcon' in package 'android'
  7. 读取android手机流量信息
  8. ViewModel、ViewModelProviders、ViewMod
  9. android 状态栏和导航栏(status and navi
  10. Android(安卓)Studio 启动 无缘故报 Erro