标题: 程序员的片段(4)--在x64/Solaris上挂载NTFS分区
创建: 2015-12-04 11:37 更新: 链接: http://scz.617.cn/unix/201512041137.txt
这个系列有点类似"Old News",绝大多数内容不具有现实意义,但从中可以看到一些 折腾的影子。
起因是在x64/Solaris 10上挂载NTFS分区。如果只读挂载,可以用FSWfsmisc,当然 这个包现在很难找到了,有一个地方还能下到:
https://aminsblog.files.wordpress.com/2012/05/fswpart-tar-gz-remove.png (FSWpart.tar.gz) https://aminsblog.files.wordpress.com/2012/05/fswfsmisc-tar-gz-remove.png (FSWfsmisc.tar.gz)
FSWfsmisc其实是对Martin Rosenau所写mount_ntfs的再封装,前者可以用标准mount 命令,后者得用专用的mount_ntfs命令。实在找不到FSWfsmisc时,就用mount_ntfs 即可。后者的技术原理如下:
The idea here is to use NFSv2 Server that has the ability to read raw blocks from a block device and interpret the raw data as per the NTFS on-disk format. You can use the existing NFS Client in Solaris to mount via the loopback interface.
下载点:
NTFS Mount (x86/Solaris) - Martin Rosenau [2006-08-04] http://mount-ntfs.sourceforge.net/ http://sourceforge.net/projects/mount-ntfs/ (下载mount_ntfs.0.9.1.opensol-x86-binary、mount_ntfs.0.9.1.zip)
前面的方案都是只读挂载NTFS分区,有读写挂载NTFS分区的方案,即ntfs-3g。该方 案同时需要fuse、ntfs-3g,只适用于Solaris 11及以上版本。
这里提到的fuse曾经是OpenSolaris的开源项目,不是下面这个:
当然,最初是从这儿开始移植的。Oracle收购Sun之后这个项目就关闭了,于是你很 难再下到Solaris版的fuse源码。也不是绝对下不到,那是另一个话题。有人提供了 编译好的二进制:
https://blogs.oracle.com/rslee/resource/pkg/SUNWfusefs.pkg https://blogs.oracle.com/rslee/resource/pkg/SUNWlibfuse.pkg
后面是本文的重点部分,再次强调当前系统是x64/Solaris 10,不是11。
SunOS SCZSUN10 5.10 Generic_147148-26 i86pc i386 i86pc
... /usr/kernel/drv/amd64/fuse /usr/kernel/drv/fuse /usr/kernel/drv/fuse.conf ... devfsadm: driver failed to attach: fuse Warning: Driver (fuse) successfully added to system but failed to attach ...
提示fuse驱动已安装到系统中,但attach失败。有Solaris内核模块开发经验的人都 知道,"failed to attach"这个提示就是跎屎,没有提供任何有价值的参考信息。比 如当模块存在无法解析的符号时,attach也会失败,但你得不到别的提示。此时必须 用别的办法获取有价值的参考信息。调试器太重型了,有个简单办法,用getlog.c或 dmesg都能看到:
genunix: [ID 233861 kern.warning] WARNING: file system 'fuse' version mismatch
从中我们可以知道fuse的模块与当前使用的genunix存在某种版本不匹配现象,让我 们去找出它的根源。
用IDA反编译/kernel/amd64/genunix,在Strings window中找到:
"file system '%s' version mismatch"
查看交叉引用,定位mod_installfs():
/*
- if ( modl->fs_vfsdef->def_version == VFSDEF_VERSION ) */ 00000000001CDA85 83 F8 03 cmp eax, 3 00000000001CDA88 0F 85 42 01 00 00 jnz loc_1CDBD0 ... 00000000001CDBDF 4C 89 EA mov rdx, r13 00000000001CDBE2 48 C7 C6 D0 A1 22 00 mov rsi, offset aFileSystemSVer ; "file system '%s' version mismatch"
当前版本的genunix的VFSDEF_VERSION等于3
在OpenSolaris源码中查看之:
usr/src/uts/common/os/modconf.c
我这份源码中VFSDEF_VERSION等于5。那么fuse模块中的def_version等于多少?
/*
- usr/src/uts/common/sys/modctl.h
- For filesystems
*/
struct modlfs
{
struct mod_ops *fs_modops;
char fs_linkinfo;
/
- version may actually vary */ struct vfsdef_v5 *fs_vfsdef; };
/*
- usr/src/uts/common/sys/vfs.h
- Filesystem type definition record. All file systems must export a record
- of this type through their modlfs structure. N.B., changing the version
- number requires a change in sys/modctl.h. / typedef struct vfsdef_v5 { int def_version; / structure version, must be first */ char name; / filesystem type name */ int (init) ( int, char * ); / init routine / int flags; / filesystem flags */ mntopts_t optproto; / mount options table prototype */ } vfsdef_v5;
用IDA反编译fuse_32。
_init() mod_install() Private_modlinkage 1 fuse_dev_drv_modldrv fuse_vfs_modldrv mod_fsops "filesystem for fuse" fs_vfsdef_or_fs_vfssw 5 // def_version "fuse" fuse_init() 1 ...
本来想把fuse_32、fuse_64中的def_version由5改成3,后来放弃了,这样绝对没有 好果子吃。
顺便说一句,在x64/Solaris 10上就不要想着读写挂载NTFS了。