前面对usb挂载的流程及各种格式的支持做了分析,这一篇也基本是收尾篇了,主要是把各种格式的挂载在vold模块种加进去,这里对这部分做了一些更改,如直接 挂载到/mnt/sdcard,没有先挂载到/mnt/secure/staging,还有把一些状态的转换去掉了,以及格式化、格式检查的去掉了,因为暂时还没听到这方面的奢求,哈哈,也是为了省事吧,这里把所有的挂载都在一个文件中实现了,先看下Android.mk
BUILD_VOLD2 := false ifneq ($(TARGET_SIMULATOR),true) BUILD_VOLD2 := true endif ifeq ($(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.cpp common_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; //FAT32 SLOGW("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; }
类型判断好之后,就可以挂载了,这里根据不同的类型,挂载的时候参数或命令不一样。