1、davfs 简介
davfs 是一个支持webdav 协议的库,可以将支持webdav 协议的网盘等挂载到本地文件系统,目前国内支持webdav 协议的知道的只有坚果云。davfs 基于neon 库,neon 库实现webdav 协议的交互,davfs 则实现本地文件和网络文件的同步,将远程网络文件mount 到本地。
2、编译以及移植
2.1、编译安装
我是在arm 64的ubuntu开发板上编译的,所以编译方面没有遇到太多的问题(用NDK 编译更好,不过要解决编译一大堆依赖)。ubuntu 下安装neon ,configure、make 一步到位。
apt install libneon27-dev
#apt-get install autoconf automake libtool autopoint
./configure
make && make install
挂载测试
mount -t davfs https://dav.jianguoyun.com/dav/ /home/jianguoyun/
输入用户名和密码,在ubuntu 上可以正常挂载,接下来就是将davfs 移植到安卓下了。
2.2 安卓部署测试
安卓下需配置configure ,重新编译, 修改configure 文件,修改dav_localstatedir 变量,将dav_localstatedir 默认值 /var/run 、/var/cache 改为/data 目录下(因为android 根目录下可能没有var 目录)
9172 if test -z "$dav_localstatedir"; then dav_localstatedir="/data/run"; fi
9173
9174
9175 if test -z "$dav_syscachedir"; then dav_syscachedir="/data/cache"; fi
然后执行(同样是在arm 版ubuntu 上编译)
/configure --sysconfdir=/data
make && make install
编译后的执行文件位于 src/mount.davfs ,src/umount.davfs ,使用ldd 命令,查找mount,.davfs 所有依赖库,根据路径提取出相应的so库
linux-vdso.so.1 => (0x0000007e4c81d000)
libneon.so.27 => /usr/lib/aarch64-linux-gnu/libneon.so.27 (0x0000007e4c7af000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000007e4c669000)
/lib/ld-linux-aarch64.so.1 (0x0000007e4c7f2000)
libz.so.1 => /lib/aarch64-linux-gnu/libz.so.1 (0x0000007e4c642000)
libssl.so.1.0.0 => /lib/aarch64-linux-gnu/libssl.so.1.0.0 (0x0000007e4c5d9000)
libcrypto.so.1.0.0 => /lib/aarch64-linux-gnu/libcrypto.so.1.0.0 (0x0000007e4c436000)
libgssapi_krb5.so.2 => /usr/lib/aarch64-linux-gnu/libgssapi_krb5.so.2 (0x0000007e4c3e7000)
libxml2.so.2 => /usr/lib/aarch64-linux-gnu/libxml2.so.2 (0x0000007e4c255000)
libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2 (0x0000007e4c242000)
libkrb5.so.3 => /usr/lib/aarch64-linux-gnu/libkrb5.so.3 (0x0000007e4c179000)
libk5crypto.so.3 => /usr/lib/aarch64-linux-gnu/libk5crypto.so.3 (0x0000007e4c13e000)
libcom_err.so.2 => /lib/aarch64-linux-gnu/libcom_err.so.2 (0x0000007e4c12a000)
libkrb5support.so.0 => /usr/lib/aarch64-linux-gnu/libkrb5support.so.0 (0x0000007e4c110000)
libicuuc.so.55 => /usr/lib/aarch64-linux-gnu/libicuuc.so.55 (0x0000007e4bf6f000)
liblzma.so.5 => /lib/aarch64-linux-gnu/liblzma.so.5 (0x0000007e4bf42000)
libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000007e4be95000)
libkeyutils.so.1 => /lib/aarch64-linux-gnu/libkeyutils.so.1 (0x0000007e4be81000)
libresolv.so.2 => /lib/aarch64-linux-gnu/libresolv.so.2 (0x0000007e4be5c000)
libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000007e4be30000)
libicudata.so.55 => /usr/lib/aarch64-linux-gnu/libicudata.so.55 (0x0000007e4a569000)
libstdc++.so.6 => /usr/lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007e4a3da000)
libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007e4a3b9000)
修改davfs2.conf
ignore_dav_header 1
使用adb 命令,连接到Android 板卡,板卡必须有root 权限
adb root
adb remount
#如果出现push 出现read only file system,先adb shell 进入板卡,然后执行mount -o rw,remount / #之后就可以读写lib 文件夹
adb push .\lib\ /lib
adb push mount.davfs /system/bin
adb push umount.davfs /system/bin
# 拷贝配置文件
adb push .\davfs2\ /data
#进入android 板卡
adb shell
#创建mount.davfs 需要用到的文件和文件夹
mkdir /data/run -p
mkdir /data/cache -p
touch /data/mtab
#权限赋予
chmod u+x /lib/*
chmod u+x /system/bin/mount.davfs
chmod u+x /system/bin/umount.davfs
#运行测试
mount.davfs https://dav.jianguoyun.com/dav/ /mnt
ls /mnt
2.3 遇到的一些问题
1、运行程序各种Permission denied
有两种情况,要么权限不够,要么缺so 库了,给lib 目录相应的读写权限,查看是否缺库
2、运行报错,mount.davfs: Warning: can't write entry into /etc/mtab, but will mount the file system anyway
出现这个问题是因为android 系统是没有etc/mtab 这个文件的,mtab 保存着文件系统的一些信息,davfs 会读写这个文件,手动创建一个空白文件就行(其实还是能挂载上去,只是报错看着不爽)
3、运行报错 Could not resolve hostname
这问题还是让我挺困扰的,追踪源码发现gethostbyname这个函数报错,DNS 解析失败,直接填ip 是能挂载上去的,新建一个文本命名为resolv.conf,里面信息如下,放到板卡/system/etc/ 目录下,注意libnss_dns.so.2、libnss_dns-2.23.so 丢失也会报这个错误,我猜测是libc dns解析不走android 那一套。
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 114.114.114.114
解决办法
adb push ./resolve.conf /ststem/etc
以上都是在adb 上测试的,部署的时候就不能用adb 了,需要修改rc 文件制作镜像,编写脚本等,这些都是题外话了。
写在结尾
其实这种做法有点邪道,毕竟移植没有用NDK 工具编译,始终是不太妥当的,但也不失为一种方案。因为同事接下任务时是用arm gcc 编译的(就是个大坑,公司都没人懂arm-gcc 移植到android),我接手的时候要么重新NDK 编译,要么继续用他以前的方案,很纠结,最后还是偷懒选择arm gcc 方案,算是一条路走到黑了。
相关链接:
davfs官网: https://savannah.nongnu.org/projects/davfs2
neon 官网 :http://www.webdav.org/neon/doc/html/index.html