Linux

source codeの追い方 -なぜlessコマンドはバイナリファイルを読めるのか-

なぜlessコマンドはバイナリファイルを読めるのか

lessコマンドでrpmファイルを開くと、リリースノートが読める。

スクリーンショット 2018-02-14 14.30.13.png

なぜバイナリファイルであるはずのrpmをlessで開くと読めるのか。
ソースを読むのが早そうだったのでいろいろ調べつつやってみた。

せっかくなのでインストールしている馴染みのパッケージのsource codeを読むための流れを纏めることにした。

実行コマンドのフルパスを確認

[root@tkd003 tmp]# which less
/usr/bin/less

lessコマンドの実態は
/usr/bin/less
だということがわかる。

rpmファイル名を確認する

どのrpmファイルでインストールされかた確認する

[root@tkd003 tmp]# rpm -qf /usr/bin/less
less-458-9.el7.x86_64

less-458-9.el7.x86_64というファイルらしい。
この名前を元にググる。

rpmファイルをダウンロードする

https://centos.pkgs.org/7/centos-x86_64/less-458-9.el7.x86_64.rpm.html

からダウンロードできる事がわかった。

スクリーンショット 2018-02-14 14.09.40.png

ソースもあるけど、今回は敢えてBinaryファイルをダウンロード

[root@tkd003 less]# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/less-458-9.el7.x86_64.rpm
--2018-02-14 14:09:32--  http://mirror.centos.org/centos/7/os/x86_64/Packages/less-458-9.el7.x86_64.rpm
mirror.centos.org (mirror.centos.org) をDNSに問いあわせています... 111.90.139.14
mirror.centos.org (mirror.centos.org)|111.90.139.14|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 122672 (120K) [application/x-rpm]
`less-458-9.el7.x86_64.rpm' に保存中

100%[===========================================================================================>] 122,672      516KB/s 時間 0.2s   

2018-02-14 14:09:37 (516 KB/s) - `less-458-9.el7.x86_64.rpm' へ保存完了 [122672/122672]

[root@tkd003 less]# 

rpmファイルを解凍する

[root@tkd003 less]# rpm2cpio less-458-9.el7.x86_64.rpm | cpio -idv
./etc/profile.d/less.csh
./etc/profile.d/less.sh
./usr/bin/less
./usr/bin/lessecho
./usr/bin/lesskey
./usr/bin/lesspipe.sh
./usr/share/doc/less-458
./usr/share/doc/less-458/LICENSE
./usr/share/man/man1/less.1.gz
./usr/share/man/man1/lessecho.1.gz
./usr/share/man/man1/lesskey.1.gz
424 blocks
[root@tkd003 less]# 

grepであたりをつける

[root@tkd003 less]# grep rpm -r *
バイナリファイル less-458-9.el7.x86_64.rpm に一致しました
usr/bin/lesspipe.sh:*.rpm) rpm -qpivl --changelog -- "$1" ;;
[root@tkd003 less]# 

usr/bin/lesspipe.shに何か書かれていそうだ。

ソースを読んでみると、
lessコマンドでrpmや、tar、zipを開くと別のコマンドに置き換わることがわかった。

less -N usr/bin/lesspipe.sh

     49 *.tar) tar tvvf "$1" ;;
     50 *.tgz|*.tar.gz|*.tar.[zZ]) tar tzvvf "$1" ;;
     51 *.tar.xz) tar Jtvvf "$1" ;;
     52 *.xz|*.lzma) xz -dc -- "$1" ;;
     53 *.tar.bz2|*.tbz2) bzip2 -dc -- "$1" | tar tvvf - ;;
     54 *.[zZ]|*.gz) gzip -dc -- "$1" ;;
     55 *.bz2) bzip2 -dc -- "$1" ;;
     56 *.zip|*.jar|*.nbm) zipinfo -- "$1" ;;
     57 *.rpm) rpm -qpivl --changelog -- "$1" ;;
     58 *.cpi|*.cpio) cpio -itv < "$1" ;;
     59 *.gpg) gpg -d "$1" ;;
     60 *.gif|*.jpeg|*.jpg|*.pcd|*.png|*.tga|*.tiff|*.tif)

つまり、rpmをlessで開くと実際は

rpm -qpivl --changelog -- less-458-9.el7.x86_64.rpm 

が実行される。ということである。
lessコマンドはバイナリを開いた際、それぞれに対応したコマンドに置き換えられ、結果としてバイナリファイルを読んでいるような事ができる。