locate用到数据文件 - mlocate.db 具有特殊的权限,普通用户不能直接修改或读取。下面简要分析一下它的特殊之处,以及给出想要修改或读取这个数据库的几种方法。
locate 使用到的数据库文件是/var/lib/mlocate/mlocate.db。这个文件的详细信息如下:
root@ubuntu:/home/mml# ls -l /var/lib/mlocate/mlocate.db
-rw-r----- 1 root mlocate 9768467 3月 27 10:02 /var/lib/mlocate/mlocate.db
它的属主和属组分别为root和mlocate,文件权限为rw-r—–,即640,root拥有读写权限,mlocate组用户拥有只读权限,而其他用户则没有任何权限。
更新mlocate.db文件用到的是updatedb命令,这个命令执行需要root权限,直接切换到root用户执行这个命令,或者使用sudo执行updatedb也可。这个很好理解,因为mlcoate.db文件只有root用户才有权修改。
但为什么明明没有读取mlocate.db文件权限的普通用户却可以直接使用locate命令去读这个数据库文件呢,答案在locate命令身上,下面是locate命令信息:
root@ubuntu:/home/mml# ls -l /usr/bin/locate
lrwxrwxrwx 1 root root 24 9月 2 2014 /usr/bin/locate -> /etc/alternatives/locate
root@ubuntu:/home/mml# ls -l /etc/alternatives/locate
lrwxrwxrwx 1 root root 16 9月 2 2014 /etc/alternatives/locate -> /usr/bin/mlocate
root@ubuntu:/home/mml# ls -l /usr/bin/mlocate
-rwxr-sr-x 1 root mlocate 34452 6月 20 2013 /usr/bin/mlocate
在我的系统(Ubuntu 14.04.3 LTS)中,locate命令经过两次软链接,链接到了/usr/bin/mlocate命令。它的属主为root,属组为mlocate,权限为rwxr-sr-x,即2755,它拥有一个特殊的权限setgid,setgid的作用是让执行该命令的用户以该命令属组的组权限去运行。
也就是说任何人运行mlocate这个命令,最终运行起来的进程的属组都是mlocate,前面讲过mlocate这个组的用户对mlocate.db都有只读权限,所以最终的现象就是任何用户都可以通过locate命令来进行搜索。
EverythingForLinux中读取mlocate.db数据库的方法
在做EverythingForLinux第二版的时候,因为要读取这个数据库文件,涉及到权限问题,本来打算把读取这个数据库文件然后写入sqlite数据库作为一个函数和主窗口程序放到一起,将主程序属组设置为mlocate,并且添加setgid权限的方式来达到读取mlocate.db的目的。但这种方式被我否定了。
一是因为Makefile中使用chown修改文件属组,使用chmod添加setgid都需要root权限,使用sudo来执行这两个命令,每次make都需要输入一遍密码,很不方便。
再一个是因为窗口程序添加setuid或setgid都是十分不安全的,很可能给系统安全带来危害。
基于前面的两点,我决定另外找办法。
- 将更新数据库和查询相互分离,分别写两个程序everything和everything-updatedb,类似locate和updatedb的关系。
- 主窗口程序everything中在后台调用everything-updatedb程序更新mlocate数据库以及将mlocate数据库转换到sqlite数据库中。
- 权限问题,everything和everything-updatedb皆为普通可执行文件,没有特殊权限,也没有修改属组。everything后台调用everything-updatedb使用sudo方式,这样就需要用户输入一个密码,而这个密码又不能在命令行中获取,Ubuntu下有gksudo可以解决这个问题,但在其他发行版中一般都不具有。最终受catfish启发,自己实现一个gksudo,此处应该感慨一下开源软件的伟大,最终参照catfish的python源码使用QT实现了一个自己的gksudo。
最终实现效果图:
提示需要更新数据库时的对话框
用户点击unlock按钮后输入密码时的对话框
mlocate.db及用来查询的sqlite数据库均更新成功时的对话框