tar

Table of Contents

tar

前回はstatなんてコマンドを調べた。ファイルのメタ情報(管理情報)を表示する奴。lsコ マンドのいわば親分だ。このメタ情報と普通にファイルの読み書きを組み合わ せれば、普段はDiskの中に鎮座してるファイルを外に保存できる事になる。

外に保存で一番利用してるのは、tarコマンド。調べてみる。

ob$ echo I am file of text >aa.txt
ob$ echo '(define myname sakae)' >my.scm
ob$ tar cf test.tar my.scm /tmp/aa.txt
tar: Removing leading / from absolute path names in the archive
ob$ tar tvf test.tar
-rw-r--r--  1 sakae    wheel           22 May 13 06:45 my.scm
-rw-r--r--  1 sakae    wheel           18 May 13 06:43 tmp/aa.txt

適当にファイルを2個作成し、それをtarコマンドでtest.tarにアーカイブして みた。そして、そのリストを確認。続いて、その内容をダンプしてみた。

ob$ hexdump -C test.tar
00000000  6d 79 2e 73 63 6d 00 00  00 00 00 00 00 00 00 00  |my.scm..........|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000060  00 00 00 00 30 31 30 30  36 34 34 00 30 30 30 31  |....0100644.0001|
00000070  37 35 30 00 30 30 30 30  30 30 30 00 30 30 30 30  |750.0000000.0000|
00000080  30 30 30 30 30 32 36 00  31 34 36 32 30 32 33 34  |0000026.14620234|
00000090  31 35 34 00 30 30 31 31  32 30 34 00 30 00 00 00  |154.0011204.0...|
000000a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000100  00 75 73 74 61 72 00 30  30 73 61 6b 61 65 00 00  |.ustar.00sakae..|
00000110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000120  00 00 00 00 00 00 00 00  00 77 68 65 65 6c 00 00  |.........wheel..|
00000130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200  28 64 65 66 69 6e 65 20  6d 79 6e 61 6d 65 20 73  |(define myname s|
00000210  61 6b 61 65 29 0a 00 00  00 00 00 00 00 00 00 00  |akae)...........|
00000220  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400  74 6d 70 2f 61 61 2e 74  78 74 00 00 00 00 00 00  |tmp/aa.txt......|
00000410  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
   :
00000600  49 20 61 6d 20 66 69 6c  65 20 6f 66 20 74 65 78  |I am file of tex|
00000610  74 0a 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |t...............|
00000620  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002800

何となく、ファイル名、(ファイルの)管理情報、ファイルのコンテンツの順に格納されてい る事が分かる。尚、'*' は、すぐ上の行と同じ物が続いている場合の省略を表 わしている(hexdumpの仕様)。

どうでもいい事だけど、my.scmに間違いがあった。

scheme@(guile-user)> (define myname sakae)
Unbound variable: sakae
scheme@(guile-user) [1]> (define myname 'sakae)
scheme@(guile-user) [1]> myname
$1 = sakae
scheme@(guile-user) [1]> (symbol? $1)
$2 = #t

シングルクォートを使って、評価を止めないと、sakae変数を利用しようとし て、そんな変数無いぞエラーに陥いる。

tarの作法

下記は、OpenBSDのマニュアルの冒頭部分

NAME
     tar - tape archiver

SYNOPSIS
     tar {crtux}[014578befHhjLmNOoPpqsvwXZz]
         [blocking-factor | archive | replstr] [-C directory] [-I file]
         [file ...]
     tar {-crtux} [-014578eHhjLmNOoPpqvwXZz] [-b blocking-factor]
         [-C directory] [-f archive] [-I file] [-s replstr] [file ...]

保存先のデフォルトとしてテープ装置が仮定されている。巨大・膨大なファイ ルを何なく保存するのには磁気テープが適しているからね。でもまあ、個人で テープ装置を所有してる人なんて、まれだろうし、アクセスするにも、テープ の先頭から読んでいかないといけないという不自由さがある。

で、fと言う引数に続いて、ファイル名を指定できる事になっている。このファ イルを別なDiskとかUSB等に指定すれば、即席でバックアップ出来ることになる。

引数を指定する場合のUnixの習慣は、'-' で始める事なんだけど、無しでもか まわない。そう、gitに多数のサブコマンド(ex: clone,log,diff…)が有るけ ど、それの元祖みたいなものだ。だから、オイラーは tar -c .. みたいには しないのさ(そう言えば、psコマンドも、その主義だったな)。

c   Create new archive
t   List contents of archive
x   Extract files from archive

あたりが、良く使うサブコマンドかな。一文字ってのが、いかにもUnixって事 で、すがすがしいぞ。

ob$ tar c my.scm
tar: Failed open to write on /dev/rst0: Device not configured

貧乏人は、テープ装置なんて所有してないんで、割り当てなんて、もっての他 です。

tar c

少し動作を追跡。まずは作成モードから。

ob$ gdb -q tar
Reading symbols from tar...
(gdb) b main
Breakpoint 1 at 0x1d627: file pax.c, line 228.
(gdb) r cf test.tar aa.txt my.scm
Breakpoint 1, main (argc=5, argv=0xcf7dfc94) at pax.c:228
228             listf = stderr;
(gdb) b open
Breakpoint 2 at 0x3b96e6b: file /usr/src/lib/libc/sys/w_open.c, line 29.
(gdb) bt
#0  _libc_open_cancel (path=0xcf7dfd50 "test.tar", flags=1537)
    at /usr/src/lib/libc/sys/w_open.c:29
#1  0x15b1ad0f in ar_open (name=0xcf7dfd50 "test.tar") at ar_io.c:123
#2  0x15b20af1 in wr_start () at buf_subs.c:114
#3  0x15b1fea3 in archive () at ar_subs.c:729
#4  0x15b2fa4e in main (argc=5, argv=0xcf7dfc94) at pax.c:314
Breakpoint 2, _libc_open_cancel (path=0x6ccea500 "aa.txt", flags=0)
    at /usr/src/lib/libc/sys/w_open.c:29
29              if (flags & O_CREAT) {
(gdb) bt
#0  _libc_open_cancel (path=0x6ccea500 "aa.txt", flags=0)
    at /usr/src/lib/libc/sys/w_open.c:29
#1  0x15b1f9cf in wr_archive (arcn=0xcf7de380, is_app=0) at ar_subs.c:468
#2  0x15b1feee in archive () at ar_subs.c:734
#3  0x15b2fa4e in main (argc=5, argv=0xcf7dfc94) at pax.c:314

この例では省略しちゃったけれど、/etc/group,/etc/pwd.dbも使ってた。グルー プ名とユーザー名の埋め込みに必要なんだろうね。それはそうと、lstatにBP を置いてもヒットしてこないぞ。なぜだ?

ここで、ちとソースを参照。関係有りそうな所にBP

Breakpoint 1, ustar_wr (arcn=0xcf7c2360) at tar.c:1391
1391            return wr_ustar_or_pax(arcn, 1);
(gdb) bt
#0  ustar_wr (arcn=0xcf7c2360) at tar.c:1391
#1  0x1442ee75 in wr_archive (arcn=0xcf7c2360, is_app=0) at ar_subs.c:500
#2  0x1442f22e in archive () at ar_subs.c:734
#3  0x1443ed8e in main (argc=5, argv=0xcf7c3cb4) at pax.c:314
(gdb) p *arcn
$2 = {nlen = 6, name = "my.scm", '\000' <repeats 3066 times>, ln_nlen = 0,
  ln_name = '\000' <repeats 1960 times>..., org_name = 0x6a680a00 "my.scm",
  pat = 0x1447e96f <_libc_getpagesize+15>, sb = {st_mode = 33188,
    st_dev = 65280, st_ino = 90049, st_nlink = 1, st_uid = 1000, st_gid = 0,
    st_rdev = 360377, st_atim = {tv_sec = 1715641887, tv_nsec = 627223589},
    st_mtim = {tv_sec = 1715550316, tv_nsec = 0}, st_ctim = {
      tv_sec = 1715632743, tv_nsec = 617223334}, st_size = 22, st_blocks = 2,
    st_blksize = 8192, st_flags = 0, st_gen = 0, __st_birthtim = {tv_sec = 0,
      tv_nsec = 0}}, pad = 0, skip = 22, crc = 876706524, type = 4}

実際にstatしてるのは、この中。fstatが利用されてた。ちゃんとmanして関連 品を炙り出しておけばよかった。まだまだ未熟だな。

(gdb) bt
#0  ar_open (name=0xcf7e2248 "test.tar") at ar_io.c:157
#1  0x1b1b3e31 in wr_start () at buf_subs.c:114
#2  0x1b1b31e3 in archive () at ar_subs.c:729
#3  0x1b1c2d8e in main (argc=5, argv=0xcf7e2184) at pax.c:314

んで、大事な構造は下記だ。

pax.h

typedef struct {
        int nlen;                       /* file name length */
        char name[PAXPATHLEN+1];        /* file name */
        int ln_nlen;                    /* link name length */
        char ln_name[PAXPATHLEN+1];     /* name to link to (if any) */
        char *org_name;                 /* orig name in file system */
        PATTERN *pat;                   /* ptr to pattern match (if any) */
        struct stat sb;                 /* stat buffer see stat(2) */
        off_t pad;                      /* bytes of padding after file xfer */
        off_t skip;                     /* bytes of real data after header */
                                        /* IMPORTANT. The st_size field does */
                                        /* not always indicate the amount of */
                                        /* data following the header. */
        u_int32_t crc;                  /* file crc */
        int type;                       /* type of file node */
#define PAX_DIR         1               /* directory */
#define PAX_CHR         2               /* character device */
#define PAX_BLK         3               /* block device */
#define PAX_REG         4               /* regular file */
#define PAX_SLK         5               /* symbolic link */
#define PAX_SCK         6               /* socket */
#define PAX_FIF         7               /* fifo */
#define PAX_HLK         8               /* hard link */
#define PAX_HRG         9               /* hard link to a regular file */
#define PAX_CTG         10              /* high performance file */
#define PAX_GLL         11              /* GNU long symlink */
#define PAX_GLF         12              /* GNU long file */
} ARCHD;

どうもtarファイルに出力する、各ファイルのメタ情報は、オクタル形式になってる。8進数を好んで使うって時代がかっているな。と 思ったら、manの歴史項目に

HISTORY
     A tar command first appeared in Version 7 AT&T UNIX.

開発されたのは、PDP-11とかのミニコンの時代なんですなあ。あの頃は、8進数が良く利用され てたって時代背景が有るのでしょう。歳のせいか、歴史物が好きであります。

tar x

展開ルーチンもザックリ見ておく。

(gdb) bt
#0  file_creat (arcn=0xcf7d01d4) at file_subs.c:72
#1  0x1b7ce066 in extract () at ar_subs.c:321
#2  0x1b7ded81 in main (argc=3, argv=0xcf7d1b34) at pax.c:311
(gdb) bt
#0  file_write (fd=8, str=0x3b7bb6d0 <bufmem+1024> "(define myname sakae)\n",
    cnt=22, rem=0xcf7d0168, isempt=0xcf7d016c, sz=8192,
    name=0xcf7d01d8 "my.scm") at file_subs.c:924
#1  0x1b7d1828 in rd_wrfile (arcn=0xcf7d01d4, ofd=8, left=0xcf7d01c8)
    at buf_subs.c:703
#2  0x1b7ce0dc in extract () at ar_subs.c:330
#3  0x1b7ded81 in main (argc=3, argv=0xcf7d1b34) at pax.c:311

ファイルを作成してから、書き込みなんだな。

(gdb) bt
#0  fset_ftime (fnm=0xcf7d01d8 "my.scm", fd=8, mtimp=0xcf7d1a18,
    atimp=0xcf7d1a0c, frc=0) at file_subs.c:730
#1  0x1b7d535c in file_close (arcn=0xcf7d01d4, fd=8) at file_subs.c:153
#2  0x1b7ce0f8 in extract () at ar_subs.c:331
#3  0x1b7ded81 in main (argc=3, argv=0xcf7d1b34) at pax.c:311

アクセス時刻は、ファイルをクローズする直前に更新するのが上等(常套)手段。

tar size

これ、普通に作成したtarファイルのサイズ。

ob$ ls -l test.tar
-rw-r--r--  1 sakae  wheel  10240 May 17 06:14 test.tar

作成時にbオプションを与えると、サイズが変わる。

ob$ tar cbf 10 test.tar aa.txt my.scm
ob$ ls -l test.tar
-rw-r--r--  1 sakae  wheel  5120 May 17 06:22 test.tar

こんな説明が有った。

-b blocking-factor
        Set blocking factor to use for the archive.  tar uses 512-byte
        blocks.  The default is 20, the maximum is 126.  Archives with a
        blocking factor larger than 63 violate the POSIX standard and
        will not be portable to all systems.

デフォルトでは、このファクターが20なんで、512 x 20 = 10240 になるって 寸法。多分テープ装置には、これぐらいのブロック・サイズが好都合なんだろ うね。まあ、tarファイルそのままで作る事は無くて圧縮しちゃうんで、余り 関係ないけど。

ar_io.c

ar_start_gzip(int fd, const char *path, int wr)
{
        zpid = fork();
        /* parent */
        if (zpid) {
            :
        } else {
                if (wr) {
                        dup2(fds[0], STDIN_FILENO);
                        dup2(fd, STDOUT_FILENO);
                        gzip_flags = "-c";
                } else {
                        dup2(fds[1], STDOUT_FILENO);
                        dup2(fd, STDIN_FILENO);
                        gzip_flags = "-dc";
                }
                putenv("PATH=/usr/bin:/usr/local/bin");

                if (execlp(path, path, gzip_flags, (char *)NULL) == -1)

ってな具合に圧縮と伸長は、tarとは独立した機構に依存してます。そこん所 が、Windowsの標準になってる、zip とは、大違いなのさ。

cpio + tar -> pax ??

そもそも、cpioなんてコマンドを知ったのは、OpenBSDのtarソースを探してい た時。tarの配置は、/bin/tar だった。ならば、/usr/src/bin/tar が有って しかるべき。でも、そんなの無い。で、うろうろしてて、pax群に辿りついた 次第。

POSIXの大失敗 〜 cpio vs tar戦争を平和に導くためにpaxコマンドを作った結果

アーカイブ – TAR と CPIO のアーカイブファイル形式の違いは何ですか?

cpio の使い方

バイナリパッケージを読む by こじまみつひろ

余り使う事は無いだろうけど、cpioをためしてみる。

ob$ ls aa.txt my.scm >list
ob$ cpio -o < list >OUT

そしてダンプ

ob$ hexdump -C OUT
00000000  30 37 30 37 30 32 30 30  30 30 39 36 63 31 30 30  |070702000096c100|
00000010  30 30 38 31 61 34 30 30  30 30 30 33 65 38 30 30  |0081a4000003e800|
00000020  30 30 30 30 30 30 30 30  30 30 30 30 30 31 36 36  |0000000000000166|
00000030  34 31 33 38 30 37 30 30  30 30 30 30 31 32 30 30  |4138070000001200|
00000040  30 30 30 30 66 66 30 30  30 30 30 30 30 30 30 30  |0000ff0000000000|
00000050  30 30 30 30 30 30 30 30  30 30 30 30 30 30 30 30  |0000000000000000|
00000060  30 30 30 30 30 37 30 30  30 30 30 35 64 62 61 61  |000007000005dbaa|
00000070  2e 74 78 74 00 00 00 00  49 20 61 6d 20 66 69 6c  |.txt....I am fil|
00000080  65 20 6f 66 20 74 65 78  74 0a 00 00 30 37 30 37  |e of text...0707|
00000090  30 32 30 30 30 30 30 30  30 34 30 30 30 30 38 31  |0200000004000081|
000000a0  61 34 30 30 30 30 30 33  65 38 30 30 30 30 30 30  |a4000003e8000000|
000000b0  30 30 30 30 30 30 30 30  30 31 36 36 34 33 63 65  |00000000016643ce|
000000c0  36 64 30 30 30 30 30 30  31 37 30 30 30 30 30 30  |6d00000017000000|
000000d0  66 66 30 30 30 30 30 30  30 30 30 30 30 30 30 30  |ff00000000000000|
000000e0  30 30 30 30 30 30 30 30  30 30 30 30 30 30 30 30  |0000000000000000|
000000f0  30 37 30 30 30 30 30 37  62 39 6d 79 2e 73 63 6d  |07000007b9my.scm|
00000100  00 00 00 00 28 64 65 66  69 6e 65 20 6d 79 6e 61  |....(define myna|
00000110  6d 65 20 27 73 61 6b 61  65 29 0a 00 30 37 30 37  |me 'sakae)..0707|
00000120  30 32 30 30 30 30 30 30  30 30 30 30 30 30 30 30  |0200000000000000|
00000130  30 30 30 30 30 30 30 30  30 30 30 30 30 30 30 30  |0000000000000000|
00000140  30 30 30 30 30 30 30 30  30 31 30 30 30 30 30 30  |0000000001000000|
00000150  30 30 30 30 30 30 30 30  30 30 30 30 30 30 30 30  |0000000000000000|
*
00000180  30 62 30 30 30 30 30 30  30 30 54 52 41 49 4c 45  |0b00000000TRAILE|
00000190  52 21 21 21 00 00 00 00  00 00 00 00 00 00 00 00  |R!!!............|
000001a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001400

展開してみる。

ob$ cpio -i <OUT
ob$ stat -x aa.txt my.scm
  File: "aa.txt"
  Size: 18           FileType: Regular File
  Mode: (0644/-rw-r--r--)         Uid: ( 1000/   sakae)  Gid: (    0/   wheel)
Device: 255,0   Inode: 4    Links: 1
Access: Mon May 13 06:43:35 2024
Modify: Wed May 15 08:03:13 2024
Change: Wed May 15 08:03:13 2024
  File: "my.scm"
  Size: 23           FileType: Regular File
  Mode: (0644/-rw-r--r--)         Uid: ( 1000/   sakae)  Gid: (    0/   wheel)
Device: 255,0   Inode: 6    Links: 1
Access: Wed May 15 05:49:49 2024
Modify: Wed May 15 08:03:13 2024
Change: Wed May 15 08:03:13 2024

paxの出番を探してみる。

ob$ pwd
/usr/src/distrib/miniroot
ob$ grep pax -r .
./install.sub:          (cd /mnt/etc/skel; pax -rw -k -pe . $_home)
./list2sh.awk:  printf("(cd %s && pax -pe -rw . ${TARGDIR}/%s)\n", $2, $3);

やっと見付けた。cpioは発見できず。なんかtarの一人勝ちだな。GNUのtar なんて、化け物みたいにオプションが増加してる。unixのシンプルさは、何処 へ行ってしまったのでしょう。

ar

tarみたいに、複数のファイルを一纏めにするコマンドが他にもある。パッと 思いつくのは、 ar - コマンド (プログラム) の説明

ob$ ar cru zz.a aa.txt my.scm
ob$ hexdump -C zz.a
00000000  21 3c 61 72 63 68 3e 0a  61 61 2e 74 78 74 2f 20  |!<arch>.aa.txt/ |
00000010  20 20 20 20 20 20 20 20  30 20 20 20 20 20 20 20  |        0       |
00000020  20 20 20 20 30 20 20 20  20 20 30 20 20 20 20 20  |    0     0     |
00000030  36 34 34 20 20 20 20 20  31 38 20 20 20 20 20 20  |644     18      |
00000040  20 20 60 0a 49 20 61 6d  20 66 69 6c 65 20 6f 66  |  `.I am file of|
00000050  20 74 65 78 74 0a 6d 79  2e 73 63 6d 2f 20 20 20  | text.my.scm/   |
00000060  20 20 20 20 20 20 30 20  20 20 20 20 20 20 20 20  |      0         |
00000070  20 20 30 20 20 20 20 20  30 20 20 20 20 20 36 34  |  0     0     64|
00000080  34 20 20 20 20 20 32 32  20 20 20 20 20 20 20 20  |4     22        |
00000090  60 0a 28 64 65 66 69 6e  65 20 6d 79 6e 61 6d 65  |`.(define myname|
000000a0  20 73 61 6b 61 65 29 0a                           | sakae).|
000000a8

これがarの基本的な利用方法。って、普通は、対象がコンパイル済みのオブジェ クト・ファイルなんだけどね。判り易い様に、あえて対象をテキスト・ファイ ルにしてみた次第。

普通は、

ob$ ar cr pax.a *.o
ob$ ar tv pax.a
rw-r--r-- 0/0  40932 Jan  1 09:00 1970 ar_io.o
rw-r--r-- 0/0  33640 Jan  1 09:00 1970 ar_subs.o
rw-r--r-- 0/0  26872 Jan  1 09:00 1970 buf_subs.o
rw-r--r-- 0/0  30440 Jan  1 09:00 1970 cpio.o
rw-r--r-- 0/0  31320 Jan  1 09:00 1970 file_subs.o
rw-r--r-- 0/0  16968 Jan  1 09:00 1970 ftree.o
rw-r--r-- 0/0  15152 Jan  1 09:00 1970 gen_subs.o
rw-r--r-- 0/0   3384 Jan  1 09:00 1970 getoldopt.o
rw-r--r-- 0/0  47668 Jan  1 09:00 1970 options.o
rw-r--r-- 0/0  26440 Jan  1 09:00 1970 pat_rep.o
rw-r--r-- 0/0  17788 Jan  1 09:00 1970 pax.o
rw-r--r-- 0/0  16620 Jan  1 09:00 1970 sel_subs.o
rw-r--r-- 0/0  39616 Jan  1 09:00 1970 tables.o
rw-r--r-- 0/0  46828 Jan  1 09:00 1970 tar.o
rw-r--r-- 0/0   7920 Jan  1 09:00 1970 tty_subs.o

こんな風にアーカイブ・ファイルを作成する。

ob$ cc -o tar pax.a
ob$ cc -o cpio pax.a
ob$ cc -o pax pax.a

一度アーカイブが出きれば、そこから実行ファイルを作成するのは、簡単。下 記は、作成した実行ファイルが、それらしく振舞うか、適当な引数を与えて (怒らせて)確認。

ob$ ./cpio ss
usage: cpio -o [-AaBcjLvZz] [-C bytes] [-F archive] [-H format]
            [-O archive] < name-list [> archive]
       cpio -i [-6BbcdfjmrSstuvZz] [-C bytes] [-E file] [-F archive] [-H format]
            [-I archive] [pattern ...] [< archive]
       cpio -p [-adLlmuv] destination-directory < name-list
ob$ ./pax -h
pax: unknown option -- h
usage: pax [-0cdjnOvz] [-E limit] [-f archive] [-G group] [-s replstr]
           [-T range] [-U user] [pattern ...]
       pax -r [-0cDdijknOuvYZz] [-E limit] [-f archive] [-G group] [-o options]
           [-p string] [-s replstr] [-T range] [-U user] [pattern ...]
       pax -w [-0adHijLOPtuvXz] [-B bytes] [-b blocksize] [-f archive]
           [-G group] [-o options] [-s replstr] [-T range] [-U user]
           [-x format] [file ...]
       pax -rw [-0DdHikLlnOPtuvXYZ] [-G group] [-p string] [-s replstr]
           [-T range] [-U user] [file ...] directory

どうやら、大丈夫そう。

ob$ ls -l cpio pax tar
-rwxr-xr-x  1 sakae  wheel  305028 May 16 07:34 cpio*
-rwxr-xr-x  1 sakae  wheel  305028 May 16 07:34 pax*
-rwxr-xr-x  1 sakae  wheel  305028 May 16 07:33 tar*

名前は異なるけど、生身は同一。だから、Makefile上では

LINKS=  ${BINDIR}/pax ${BINDIR}/tar ${BINDIR}/pax ${BINDIR}/cpio

こんな風に、リンクを作れって指令になってるのさ。

arコマンドは色々な変遷を得ている。今は、llvm一族になってるんだけど、変 らずに、継承してる部分が、 ar.hに示されている。

struct ar_hdr {
        char ar_name[16];               /* name */
        char ar_date[12];               /* modification time */
        char ar_uid[6];                 /* user id */
        char ar_gid[6];                 /* group id */
        char ar_mode[8];                /* octal file permissions */
        char ar_size[10];               /* size in bytes */
#define ARFMAG  "`\n"
        char ar_fmag[2];                /* consistency check */
};

それはそうと、更新時刻が記録される様になってるのに、先程作ったアーカイ ブは、ことごとくunixの始祖の時刻になってた。利用方法が間違ってる? こういう時は、別OSで確認するのがよかろう。Debian/WSL2上のgauche

sakae@atom:/usr/local/lib$ ar tv libgauche-static-0.98.a | head -5
rw-r--r-- 0/0  23920 Jan  1 09:00 1970 box.o
rw-r--r-- 0/0  87840 Jan  1 09:00 1970 core.o
rw-r--r-- 0/0 628032 Jan  1 09:00 1970 vm.o
rw-r--r-- 0/0  68896 Jan  1 09:00 1970 compaux.o
rw-r--r-- 0/0 113048 Jan  1 09:00 1970 macro.o

Uum …

my.scmを変更した。それをアーカイブに反映してみる。

ob$ ar rU zz.a my.scm
ob$ ar tv zz.a
rw-r--r-- 0/0     18 Jan  1 09:00 1970 aa.txt
rw-r--r-- 1000/0     23 May 17 06:10 2024 my.scm
ob$ hexdump -C zz.a
00000000  21 3c 61 72 63 68 3e 0a  61 61 2e 74 78 74 2f 20  |!<arch>.aa.txt/ |
00000010  20 20 20 20 20 20 20 20  30 20 20 20 20 20 20 20  |        0       |
00000020  20 20 20 20 30 20 20 20  20 20 30 20 20 20 20 20  |    0     0     |
00000030  36 34 34 20 20 20 20 20  31 38 20 20 20 20 20 20  |644     18      |
00000040  20 20 60 0a 49 20 61 6d  20 66 69 6c 65 20 6f 66  |  `.I am file of|
00000050  20 74 65 78 74 0a 6d 79  2e 73 63 6d 2f 20 20 20  | text.my.scm/   |
00000060  20 20 20 20 20 20 31 37  31 35 38 39 33 38 33 36  |      1715893836|
00000070  20 20 31 30 30 30 20 20  30 20 20 20 20 20 36 34  |  1000  0     64|
00000080  34 20 20 20 20 20 32 33  20 20 20 20 20 20 20 20  |4     23        |
00000090  60 0a 28 64 65 66 69 6e  65 20 6d 79 6e 61 6d 65  |`.(define myname|
000000a0  20 27 73 61 6b 61 65 29  0a 0a                    | 'sakae)..|
000000aa

今度は、ちゃんとファイル情報が反映された。

gauche

gaucheを実行する為の部品セットが用意されてるので、容易にgaucheを下敷に したアプリを生成できる。新たに準備する物は、main.c のみだ。 (paxの場合は、main()が既に定義されてオブジェクトファイルの一員になってたか ら、不要だった)

#include <stdio.h>
#include <gauche.h>
 
int main() {   
    ScmObj p;
    ScmObj list;
 
    GC_INIT();
    Scm_Init(GAUCHE_SIGNATURE);
 
    list = SCM_LIST3(SCM_MAKE_INT(1), SCM_MAKE_INT(2), SCM_MAKE_INT(3));
 
    for(p = list; SCM_PAIRP(p); p = Scm_Cdr(p)) {
        printf("%ld\n", SCM_INT_VALUE(Scm_Car(p)));
    }
 
    return 0;
}

(list 1 2 3)を作成して、それをスキャン出力する。

SRC = main.c
OUT = a.out
INCLUDE_DIR = `gauche-config -I`
LIBRARY_DIR = `gauche-config -L`
LIBRARIES = `gauche-config -l`

$(OUT): $(SRC)
        gcc -std=gnu99 -Ofast -Wall -Werror -o $(OUT) $(INCLUDE_DIR) $^ $(LIBRARY_DIR) $(LIBRARIES)

clean:
        rm -f $(OUT)

こちらはMakefile。正確には、上で参照したアーカイブを利用してないけど、 それに順ずるsoファイルをリンクしてる。xx.soとxx.aが存在した場合、xx.so を利用する様になってるからね。その方が、SDG'sだからね。

sakae@atom:/mnt/r$ make
gcc -std=gnu99 -Ofast -Wall -Werror -o a.out `gauche-config -I` main.c `gauche-config -L` \
 `gauche-config -l`
sakae@atom:/mnt/r$ ./a.out
1
2
3

こんな風にコンパイルすれば、本体にアーカイブ・ファイルを取り込める。

gcc -std=gnu99 -Ofast -Wall -Werror -o my `gauche-config -I` main.c `gauche-config -L` \
 /usr/local/lib/libgauche-static-0.98.a -lcrypt -lrt -lm  -lpthread

gaucheの核になる部分で膨れたアプリになってしまう。こんなアプリが複数あっ たら、DISKエリアの無駄になるし、何より貴重なメモリーエリアも無駄使いし ちゃう可能性がある。SDG's的に、いかがなものかと思う昨今ですよ。

sakae@atom:/mnt/r$ ls -l a.out my
-rwxrwxrwx 1 sakae sakae    17672 May 17 07:44 a.out*
-rwxrwxrwx 1 sakae sakae 16678224 May 17 07:50 my*

ChatGPT

GPT-4o を紹介されたぞ。でも、オイラーは古い奴で十分。だって、古い事し か尋ねないから。

Q: Unix系のアーカイバーには、pax,cpio,tarが有ります。そのうちのtarだけが流通してるように見受けられます。その理由を説明してください。

A: Unix系のアーカイバーには、pax、cpio、tarが存在しますが、その中でもtarが広く普及し、一般的に使用されている理由について説明します。以下に、tarの普及の背景、技術的特徴、歴史的経緯、他のアーカイバーとの比較などを通じて、tarが主流となった理由を詳述します。

### 1. tarの技術的特徴と利便性

tar(tape archive)は、ファイルのアーカイブと復元を行うためのツールであり、特に以下の点で優れています。

  • シンプルな構造: tarは一つのアーカイブファイルに複数のファイルやディレクトリをまとめて保存するためのシンプルな形式を採用しています。これにより、扱いやすく、データのバックアップや移行が簡単に行えます。
  • 柔軟なオプション: tarは圧縮機能と組み合わせることで、多用途に使用できます。圧縮なしの単純なアーカイブ作成から、gzip(.tar.gz)やbzip2(.tar.bz2)を使用した圧縮アーカイブの作成まで、多様なニーズに応じた使い方が可能です。
  • ポータビリティ: tarアーカイブは、Unix系システム間での互換性が高く、異なるシステム間でファイルをやり取りする際にも信頼性があります。これにより、多くのUnix系オペレーティングシステムで標準的に使用されています。

### 2. tarの歴史的背景

tarの歴史は非常に古く、1979年に最初に登場しました。UNIXの初期の時代から存在し、以下の点がtarの普及を後押ししました。

  • 初期の標準ツール: tarは、UNIXの標準ツールの一部として採用され、多くのUnix系オペレーティングシステムに組み込まれていました。これにより、ユーザーは追加のインストールや学習を必要とせずにtarを利用できました。
  • ソフトウェア配布のデファクトスタンダード: 多くのオープンソースプロジェクトや商用ソフトウェアは、tarを使用してソースコードやバイナリを配布していました。tarアーカイブを使用することで、開発者やユーザーはソフトウェアのインストールや配布を簡単に行うことができました。

### 3. 他のアーカイバーとの比較

#### pax

paxはPOSIX標準のアーカイブユーティリティであり、tarやcpioの両方の機能を統合しています。しかし、paxがtarほど普及しなかった理由には以下の点が挙げられます。

  • 後発のツール: paxはtarやcpioに比べて後発のツールであり、既に普及していたtarを置き換えることは難しかった。
  • 複雑さ: tarやcpioに比べてオプションや機能が多く、一般ユーザーにはやや複雑に感じられることがありました。

#### cpio

cpioはtarと同様に古い歴史を持つアーカイバーですが、普及しなかった理由には以下の点があります。

  • インターフェースの違い: cpioは、tarと異なり標準入力からファイルリストを読み込むという独特の方法を採用しています。これがユーザーにとってやや直感的ではなく、扱いにくいと感じられることがありました。
  • 圧縮オプションの限定: cpio自体には圧縮機能がなく、別途圧縮ツールと組み合わせて使用する必要があります。この点で、圧縮オプションを直接サポートするtarの方が利便性が高いと評価されました。

### 4. tarのエコシステムとコミュニティサポート

tarが広く普及し、標準的なツールとして定着した背景には、エコシステムやコミュニティのサポートも大きな役割を果たしています。

  • ドキュメントとチュートリアルの豊富さ: tarは広く使用されているため、ドキュメントやチュートリアルが豊富に存在します。これにより、新規ユーザーでも学習コストが低く、簡単に利用を始めることができます。
  • ツールとの統合: tarは、makeやconfigureなどのビルドツールと統合されており、ソフトウェアのビルドプロセスにおいても重要な役割を果たしています。このような統合によって、tarの使用がさらに促進されました。
  • オープンソースコミュニティのサポート: オープンソースプロジェクトの多くがtarを公式のアーカイブフォーマットとして採用しており、コミュニティ全体でのサポートが強力です。これにより、tarは信頼性が高く、長期間にわたり使用され続けています。

### 結論

tarがUnix系アーカイバーの中で広く普及し、主流となっている理由は、そのシンプルな構造と柔軟なオプション、歴史的背景、他のアーカイバーと比較しての利便性、そしてエコシステムとコミュニティの強力なサポートにあります。これらの要素が組み合わさることで、tarは長年にわたり信頼され続け、多くのユーザーに利用されています。


This year's Index

Home