manコマンドでマニュアルを確認しても挙動が分かりづらいコマンドがあります。
cpや、mvなどのコアユーティリティについてググると、マニュアルのまとめ直しばかりでノイズが酷く役に立ちません。
ここで、一次情報であるソースコードを取得する手段をまとめます。
目次
環境
- CentOS Linux release 7.4.1708
概要
ソースコードは公式サイトで公開されているので取得するのは簡単です。
このまとめは、ただコードが見たいのではなく、使用中のOSにインストールされているコマンドのソースコードを取得する方法です。
大まかな手順は以下のようになります。
- コマンドが含まれているパッケージ名を取得する
- OSのバージョンを取得する
- 公式サイトから対象のパッケージをダウンロードする
- パッケージからファイルを抜き出して展開する
詳細
cpコマンドのソースコードを例にします。
コマンドが含まれているパッケージ名を取得する
コマンド名がそのままパッケージ名になっていないので、インストールされているコマンドからパッケージ名を知る必要があります。
$ rpm -qfi `which cp`
Name : coreutils
Version : 8.22
Release : 18.el7
Architecture: x86_64
Install Date: Mon 11 Sep 2017 06:35:22 PM UTC
Group : System Environment/Base
Size : 14589167
License : GPLv3+
Signature : RSA/SHA256, Sun 20 Nov 2016 05:26:24 PM UTC, Key ID 24c6a8a7f4a80eb5
Source RPM : coreutils-8.22-18.el7.src.rpm
Build Date : Sat 05 Nov 2016 08:49:48 PM UTC
Build Host : worker1.bsys.centos.org
Relocations : (not relocatable)
Packager : CentOS BuildSystem
Vendor : CentOS
URL : http://www.gnu.org/software/coreutils/
Summary : A set of basic GNU tools commonly used in shell scripts
Description :
These are the GNU core utilities. This package is the combination of
the old GNU fileutils, sh-utils, and textutils packages.
以下の項目がソースコードのパッケージ名になります。
# | 項目 | 値 |
1 | Source RPM | coreutils-8.22-18.el7.src.rpm |
ディストリビューションのバージョンを取得する
公式サイト(ミラーも含めて)では、バージョン別にファイルがまとめられているので、使用中のバージョンを知る必要があります。
$ cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
公式サイトから対象のパッケージをダウンロードする
URLが変化することも考えてトップページからの順序をまとめます。
公式サイト:The CentOS Project
トップページの「GET CENTOS」リンクからダウンロードページへ
ダウンロードページの下の方にある「Need the Source?」の案内に従ってvault.centos.orgへ
vault.centos.orgのページで、ディストリビューションのバージョンのリンク以下のサブディレクトリへ進みます。
(「7.4.1708/」 > 「os/」 > 「Source/」 > 「SPackages/」)
パッケージ名で検索して該当のパッケージをダウンロードします。
ブラウザのダウンロードでも構いませんが、仮想マシンなどCUIしかなければ、wgetでもダウンロードできます。
$ wget http://vault.centos.org/7.4.1708/os/Source/SPackages/coreutils-8.22-18.el7.src.rpm
--2017-09-29 10:21:05-- http://vault.centos.org/7.4.1708/os/Source/SPackages/coreutils-8.22-18.el7.src.rpm
Resolving vault.centos.org (vault.centos.org)... 108.61.16.227, 2607:f128:40:1600:225:90ff:fe00:bde6
Connecting to vault.centos.org (vault.centos.org)|108.61.16.227|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5503579 (5.2M) [application/x-rpm]
Saving to: ‘coreutils-8.22-18.el7.src.rpm’
100%[==============================================================================================>] 5,503,579 1.85MB/s in 2.8s
2017-09-29 10:21:09 (1.85 MB/s) - ‘coreutils-8.22-18.el7.src.rpm’ saved [5503579/5503579]
パッケージからファイルを抜き出して展開する
rpm形式はファイル単位の扱いが面倒なので、cpio形式へ変換してから欲しいファイルを取り出します。
ファイル形式を変換する
$ rpm2cpio coreutils-8.22-18.el7.src.rpm > src.cpio
$ cpio -tv < src.cpio
-rw-rw-r-- 1 root root 868 Nov 4 2016 coreutils-4.5.3-langinfo.patch
-rw-rw-r-- 1 root root 5427 Nov 4 2016 coreutils-6.10-configuration.patch
-rw-rw-r-- 1 root root 576 Nov 4 2016 coreutils-6.10-manpages.patch
...省略
-rw-rw-r-- 1 root root 2593 Nov 4 2016 coreutils-8.22-xfsbuildfailure.patch
-rw-rw-r-- 1 root root 5335124 Nov 4 2016 coreutils-8.22.tar.xz
...省略
-rw-rw-r-- 1 root root 2249 Nov 4 2016 coreutils-selinuxmanpages.patch
-rw-rw-r-- 1 root root 71176 Nov 4 2016 coreutils.spec
-rw-rw-r-- 1 root root 590 Nov 4 2016 sh-utils-2.0.11-dateman.patch
11191 blocks
パッチファイル(*.patch)が沢山ありますがパッケージ名の命名ルールから推測して、coreutils-8.22.tar.xzがソースファイルになります。
xz形式で圧縮されていますが、GNU tar バージョン1.22以降ならば対応しています。
(対応していなければ、xzコマンドを使用してからtarで展開します)
ファイルの抜き出して展開する
$ cpio -i *.xz < src.cpio
11191 blocks
$ tar xf coreutils-8.22.tar.xz
$ ls coreutils-8.22/src/
ls -w 80 coreutils-8.22/src/
base64.c factor.c mknod.c sleep.c
basename.c false.c mktemp.c sort.c
c99-to-c89.diff fiemap.h mv.c split.c
cat.c find-mount-point.c nice.c stat.c
chcon.c find-mount-point.h nl.c stdbuf.c
chgrp.c fmt.c nohup.c stty.c
chmod.c fold.c nproc.c sum.c
chown.c fs.h numfmt.c sync.c
chown-core.c fs-is-local.h od.c system.h
chown-core.h getlimits.c operand2sig.c tac.c
chroot.c group-list.c operand2sig.h tac-pipe.c
cksum.c group-list.h paste.c tail.c
comm.c groups.c pathchk.c tee.c
copy.c head.c pinky.c test.c
copy.h hostid.c pr.c timeout.c
cp.c hostname.c primes.h touch.c
cp-hash.c id.c printenv.c tr.c
cp-hash.h install.c printf.c true.c
csplit.c ioblksize.h prog-fprintf.c truncate.c
cu-progs.mk join.c prog-fprintf.h tsort.c
cut.c kill.c ptx.c tty.c
date.c lbracket.c pwd.c uname-arch.c
dcgen libstdbuf.c readlink.c uname.c
dd.c link.c realpath.c uname.h
df.c ln.c relpath.c uname-uname.c
dircolors.c local.mk relpath.h unexpand.c
dircolors.h logname.c remove.c uniq.c
dircolors.hin longlong.h remove.h unlink.c
dirname.c ls.c rm.c uptime.c
du.c ls-dir.c rmdir.c users.c
echo.c ls.h runcon.c wc.c
env.c ls-ls.c selinux.c whoami.c
expand.c ls-vdir.c selinux.h who.c
expr.c make-prime-list.c seq.c yes.c
extent-scan.c md5sum.c setuidgid.c
extent-scan.h mkdir.c shred.c
extract-magic mkfifo.c shuf.c
展開したファイルの中にあるcp.cが、cpコマンドのソースファイルとなります。