概述
前面对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 %sn", 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;
}
这里ext4类型的判断粊笨拙,这里的方法是因为ext4超级块的结构比其它ext2 ext3大,后面的 这引起字段不为0,而其它两种格式这些字段都是0的。
类型判断好之后,就可以挂载了,这里根据不同的类型,挂载的时候参数或命令不一样。
最后
以上就是热情星月为你收集整理的android usb挂载分析--各种格式支持的全部内容,希望文章能够帮你解决android usb挂载分析--各种格式支持所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复