chmodが呼び出しているシステムコール


アニメ『百錬の覇王と聖約の戦乙女』

主人公がどういう経緯で異世界へ来たかっていうシーンはざっくり削除して、戦から始まったので見るのが楽でした。最近異世界が多くて、導入シーンはマンネリですからね。
主人公はスマホで戦術とか調べて戦に連勝してるっぽいのだけど、スマホで調べるってことはあんまり重要じゃなくて、大事なのは、やはりハーレムアニメってところ。親子や義兄弟の契りは、絶対で、親ならば、親に従わないといけないらしく。無能で文句しか言わないおっさん達であっても、親ならば、歯向かってはいけないんです。
という設定ぽいんですが、主人公は、あっさり覆す。ん~、もう少しストレス溜めてくれないと。サクセスストーリーもそろそろ飽きがきたので、老害たちが、主人公を陥れるストーリーが見たい、と切に願ってます。

親子は義兄弟の契りは、交わすとどうなるのかというと、結局は、権限の付与ってことになると思います。軍の指揮権や、財産相続権につながっていくのでしょう。

Linuxもファイル権限ってのがありますね。すごく良くできた仕組みだと思います。
まだCP/MやMS-DOSしか使ってなかった時に、UNIXってのに憧れました。ファイルパーミッションってものに関わりたい! 将来chmodを使って、ファイル権限を変更したりできる身分になれるだろうか!? と思ってたのですが、あっという間に一人一台コンピュータの時代がやってきました。
個人で気楽にUnixライクなOSを触れるようになったので、新規にUnix/Linuxを学習する人たちから見ると、ファイルパーミッションって、あたり前すぎて感動薄いかもしれません。

今回はchmodコマンド見ていきます。
man chmodの冒頭。

CHMOD(1)                 ユーザーコマンド                 CHMOD(1)

名前
       chmod - ファイルのモードビットを変更する

書式
       chmod [OPTION]... MODE[,MODE]... FILE...
       chmod [OPTION]... OCTAL-MODE FILE...
       chmod [OPTION]... --reference=RFILE FILE...

説明
       このマニュアルページでは  GNU バージョンの chmod について説
  

chmodって動作から推測するに、ファイルシステムは、カーネルからじゃないと触れないので。chmod内部ではシステムコール絶対使ってますよね。つまり、man 2 chmod。確認してみましょう。

CHMOD(2)             Linux Programmer's Manual            CHMOD(2)

名前
       chmod, fchmod, fchmodat - ファイルのモードを変更する

書式
       #include <sys/stat.h>

       int chmod(const char *pathname, mode_t mode);
       int fchmod(int fd, mode_t mode);

       #include <fcntl.h>           /* AT_* 定数の定義 */
       #include <sys/stat.h>

       int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);


ありましたね。chmodとfchmodとfchmodat関数が提供されているようです。共通するキーワードはchmodなので、coreutilsのchmodのソースで、これらのシステムコールが使われているか確認してみましょう。

いつものようにcoreutilsのソースをダウンロード。

takk@deb9:~/src$ apt-get source coreutils

自動展開されるので、cdします。

takk@deb9:~/src$ cd coreutils-8.26
takk@deb9:~/src/coreutils-8.26$ 

コマンドのソースは、コマンド名.cになっているハズですので、chmodコマンドは、chmod.cで検索します。

takk@deb9:~/src/coreutils-8.26$ find -name chmod.c
./src/chmod.c
takk@deb9:~/src/coreutils-8.26$ 

ありました。

では、このソースで、~chmod~システムコールが疲れているかgrepで確認。

takk@deb9:~/src/coreutils-8.26$ !! | xargs grep -n chmod
find -name chmod.c | xargs grep -n chmod
1:/* chmod -- change permission modes of files
36:#define PROGRAM_NAME "chmod"
74:/* If true, diagnose surprises from naive misuses like "chmod -r file".
76:   "chmod -- -r file".  */
110:/* Return true if the chmodable permission bits of FILE changed.
119:      /* The new mode contains unusual bits that the call to chmod may
196:  bool chmod_succeeded = false;
206:         With programs like chmod, chown, and chgrp, that modify
273:          if (chmodat (fts->fts_cwd_fd, file, new_mode) == 0)
274:            chmod_succeeded = true;
287:      bool changed = (chmod_succeeded
295:             : !chmod_succeeded ? CH_NOT_APPLIED
302:  if (chmod_succeeded && diagnose_surprises)
458:          /* Support nonportable uses like "chmod -w", but diagnose
takk@deb9:~/src/coreutils-8.26$ 

273行目のchmodatってのが見つかりましたが、残念ながら、manで調べたシステムコールは、chmod fchmod fchmodatの3つなので、該当するものがありません。

ん~。これはGNUによくあるラッパーなのでは?

ctagを打ってvimでchmodatの定義場所を表示してみます。

takk@deb9:~/src/coreutils-8.26$ ctags -R *
takk@deb9:~/src/coreutils-8.26$ vi -c'ta chmodat'

Vimの表示。

 81 FCHMODAT_INLINE int
 82 chmodat (int fd, char const *file, mode_t mode)
 83 {
 84   return fchmodat (fd, file, mode, 0);
 85 }
 86 
 87 FCHMODAT_INLINE int
 88 lchmodat (int fd, char const *file, mode_t mode)
 89 {
 90   return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW);
 91 }
 92 
 93 #endif
"lib/openat.h" 123L, 3059C   

見つかりました。chmodatの中で、fchmodatを呼び出ししています。
chmodコマンドは、fchmodatを使っているってことで、間違いないようです。

man 2 chmodの説明の続きを見ると、fchmodatに関して書いてあります。

   fchmodat()
       fchmodat()  システムコールは  chmod()  と全く同様に動作する
       が、以下で説明する点が異なる。

       pathname   で指定されたパス名が相対パスの場合、このパス名は
       ファイルディスクリプター dirfd が参照するディレクトリに対す
       る相対パスと解釈される  (chmod() に相対パス名を渡した場合の
       ように、呼び出したプロセスのカレントワーキングディレクトリ
       に対する相対パスではない)。

       pathname  で指定されたパス名が相対パスで、 dirfd が特別な値
       AT_FDCWD の場合、 (chmod() と同様に) pathname  は呼び出した
       プロセスのカレントワーキングディレクトリに対する相対パスと
       解釈される。

       pathname で指定されたパス名が絶対パスの場合、 dirfd  は無視
       される。

       flags には 0 か、以下のフラグを指定することができる。

       AT_SYMLINK_NOFOLLOW
              pathname  がシンボリックリンクの場合、リンクの展開を
              行わない。代わりに、リンク自身に対して操作を行う。こ
              のフラグは現在のところ実装されていない。

       fchmodat()  の必要性についての説明については openat(2) を参
       照。

返り値
       成功した場合は 0 が返される。エラーの場合は  -1  が返され、
       errno が適切に設定される。

このシステムコールを、使いこなしてみたくなりました。

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA