Android 上 用 Fuse 的幾個 project:
第一點有說明 libfuse 難 port 的原因,因為 bionic 的關係。
1的現成的,舊的 :
http://code.google.com/p/fuse-android/downloads/detail?name=fuse-2.8.5-android.tar&can=2&q=
要重新 build kernel,enable FUSE support
xda 上有另一個 port,包含 exfat, prebuild:
http://forum.xda-developers.com/showthread.php?t=1371621&page=3
前幾篇有說 build 的方法:
http://forum.xda-developers.com/showthread.php?t=1371621
這是用 static link,所以完全不管 bionic,也不用 so.
實際使用就是把 prebuild. static link 的檔案 download 回來,解開,push 到 /system/bin 下。
PC 的 XP 要安裝 MS 的
KB955704 號更新 。
然後格式化就會出現 exfat 的選項。
要注意,因為 android 的 vold 在偵測 device mount 後,會用 fsck fix 一些error 標投。
所以直接插入 exfat 格式的 sdcard,標投會被改掉,這樣 mount.exfat-fuse 就不認識這個 partition,
mount 時會出現 "Find no exfat system info" 的msg。
所以要記得把 vold.fstab 的相關行 comment 掉。
插入由 PC 作exfat 格式化的 sdcard。
#mkdir /data/exfat
#mount.exfat-fuse /dev/block/mmcblk1p1 /data/exfat
這樣就 mount 成功了。
vold 問題,找到 CM 的 vold 有 support fat/ext/ntfs ,只是將 fat/ext 寫一起,然後,else 就是 ntfs。
-- 找不到真正 mount 的 function, 都說是 extern ...
這一篇古老的google group 討論有一些方法。
大概就是把 mount 改成執行外部 mount 命令。
由logcat 來看,破壞 partition info 的地方:
I//system/bin/fsck_msdos( 2360): Invalid signature in fsinfo block
I//system/bin/fsck_msdos( 2360): FIXED
I//system/bin/fsck_msdos( 2360): Invalid cluster size: 0
I/logwrapper( 2360): /system/bin/fsck_msdos terminated by exit(8)
I/PackageManager( 2431): Updating external media status from unmounted to unmounted
E/Vold ( 2360): Filesystem check failed (unknown exit code 8)
大概是 fsck_msdos 作的..
比較插入 ext4 的 sd:
/Vold ( 2360): /dev/block/vold/179:9 is checking for volume extsd
D/Vold ( 2360): Volume extsd state changing 1 (Idle-Unmounted) -> 3 (Checking)
I/StorageNotification( 2529): Media {/mnt/sdcard/extsd} state changed from {bad_removal} -> {checking}
I//system/bin/fsck_msdos( 2360): ** /dev/block/vold/179:9
I//system/bin/fsck_msdos( 2360): Invalid signature in boot block: 0000
I/logwrapper( 2360): /system/bin/fsck_msdos terminated by exit(2)
I/PackageManager( 2431): Updating external media status from unmounted to unmounted
E/Vold ( 2360): Filesystem check failed (not a FAT filesystem)
W/Vold ( 2360): /dev/block/vold/179:9 does not contain a FAT filesystem
E/Vold ( 2360): Volume extsd found no suitable devices for mounting :(
ext4 的 sd 插入後,不會被破壞 (拿回 pc 還可以正確 mount)。
所以猜測應該是 exfat 有跟 fat 類似的 partition id info,導致 msdos_fsck 誤判。
-- 所以作法應該是先用 exfat mount fail 再用 fat mount ?
實際使用 Cyanogen 7 的 Fat.cpp/h
ext2 formatted SD, 插入後,e2fsck 說有 error,要手動run 一次 e2fsck。
所以照作,在系統上手動
#e2fsck /dev/block/mmcbpk1p1
果然有寫 error fixed。
再插入後,就 自動 mount OK 了。
另外,用 XP format 成 exfat 的 SD,在系統上用 exfatfsck 檢查,是 OK 的。
所以應該可以用。
--- 是否要看 FAT/FAT32 用 exfatfsck 會不會也 OK ?
結果 OK。
修改 Fat.cpp , Fat.h
在 ::check 和 ::doMount 加入 filesystem 的 id 。
還要注意,FAT 的 fsck 會修改 exfat 的 partition head,所以要放在最後。
這樣,就可以 support ext4, exfat, fat 三種 filesystem 了..
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int Fat::check(const char *fsPath) {
bool rw = true;
SLOGI("Fat::check\n");
if (access(FSCK_MSDOS_PATH, X_OK) || access(FSCK_EXT_PATH, X_OK)) {
SLOGW("Skipping fs checks\n");
return 0;
}
int pass = 1;
int rc = 0;
do {
const char *args[5];
enum { FS_OK, FS_FIXED, FS_MISMATCH, FS_ERROR } status = FS_ERROR;
args[0] = FSCK_EXT_PATH;
args[1] = "-p";
args[2] = "-f";
args[3] = fsPath;
args[4] = NULL;
rc = logwrap(4, args, 1);
if (rc == 0) {
// if rc is 0, the check was ok
// That means the FileSystem is EXT
fsType = 2;
status = FS_OK;
} else if (rc == 1)
status = FS_FIXED;
else if (rc == 8)
status = FS_MISMATCH;
else
status = FS_ERROR;
if (status == FS_MISMATCH) {
args[0] = FSCK_EXFAT_PATH;
args[1] = fsPath;
args[2] = NULL;
rc = logwrap(2,args,1);
if (rc == 0) {
// check OK, FileSystem is ExFAT
fsType = 3;
status = FS_OK;
}else{
status = FS_MISMATCH;
}
}
if (status == FS_MISMATCH) { // not EXT, let's try FAT
args[0] = FSCK_MSDOS_PATH;
args[1] = "-p";
args[2] = "-f";
args[3] = fsPath;
args[4] = NULL;
rc = logwrap(4, args, 1);
if (rc == 0) {
// if rc is 0, the check was ok
// That means the FileSystem is FAT
fsType = 1;
status = FS_OK;
} else if (rc == 2)
status = FS_MISMATCH;
else if (rc == 4)
status = FS_FIXED;
else
status = FS_ERROR;
}
switch(status) {
case FS_OK:
SLOGI("Filesystem check completed OK");
// TODO: Remove this print.
const char *fsTypePrint;
if (fsType == 1)
fsTypePrint = "VFAT";
else if (fsType == 2)
fsTypePrint = "EXT";
else if (fsType == 3)
fsTypePrint = "EXFAT";
F else
fsTypePrint = "Unknown";
SLOGI("Filesystem type is: %s", fsTypePrint);
return 0;
case FS_MISMATCH:
SLOGW("Filesystem check failed (not a FAT or EXT filesystem)");
errno = ENODATA;
return -1;
case FS_FIXED:
if (pass++ <= 3) {
SLOGW("Filesystem modified - rechecking (pass %d)",
pass);
continue;
}
SLOGE("Failing check after too many rechecks");
errno = EIO;
return -1;
default:
SLOGE("Filesystem check failed (unknown exit code %d)", rc);
errno = EIO;
return -1;
}
} while (0);
return 0;
}
int Fat::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 *mntFSType;
flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC;
flags |= (executable ? 0 : MS_NOEXEC);
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;
}
if (fsType == 2) {
sprintf(mountData, "noauto_da_alloc");
mntFSType = "ext4";
rc = mount(fsPath, mountPoint, mntFSType, flags, mountData);
} else if (fsType == 3) {
const char *args[5];
args[0] = "/system/bin/mount.exfat-fuse";
args[1] = fsPath;
args[2] = mountPoint;
args[3] = NULL;
rc = logwrap(3,args,1);
} else {
sprintf(mountData,
"utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",
ownerUid, ownerGid, permMask, permMask);
mntFSType = "vfat";
rc = mount(fsPath, mountPoint, mntFSType, flags, mountData);
}
if (rc && errno == EROFS) {
SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath);
flags |= MS_RDONLY;
rc = mount(fsPath, mountPoint, mntFSType, flags, mountData);
}
if (rc == 0 && createLost && fsType == 1) {
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, 0755)) {
SLOGE("Unable to create LOST.DIR (%s)", strerror(errno));
}
}
free(lost_path);
}
return rc;
}
ntfs 的話,一樣,在
xda 的神人 作了 static link ntfs-3g fuse 的 prebuild binary 。
只要依樣話葫蘆就可以。
但是 ntfs 沒有 fsck,所以只好寫成這樣:
check 時,所有的 filesystem 都是 mismatch 時,assume ntfs。
然後一樣在 domount 用 logwrap( ) 來執行 ntfs-3g 作 mount。