Linux(CentOS7)コマンドのソースファイルを取得する方法

投稿者: | 2017年9月30日

manコマンドでマニュアルを確認しても挙動が分かりづらいコマンドがあります。
cpや、mvなどのコアユーティリティについてググると、マニュアルのまとめ直しばかりでノイズが酷く役に立ちません。
ここで、一次情報であるソースコードを取得する手段をまとめます。

環境

    CentOS Linux release 7.4.1708

概要

ソースコードは公式サイトで公開されているので取得するのは簡単です。
このまとめは、ただコードが見たいのではなく、使用中のOSにインストールされているコマンドのソースコードを取得する方法です。

大まかな手順は以下のようになります。

  1. コマンドが含まれているパッケージ名を取得する
  2. OSのバージョンを取得する
  3. 公式サイトから対象のパッケージをダウンロードする
  4. パッケージからファイルを抜き出して展開する

詳細

 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.

以下の項目がソースコードのパッケージ名になります。

#項目
1Source RPMcoreutils-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コマンドのソースファイルとなります。