CHOWN(2)

名前
chown, fchown, lchown - ファイルの所有者を変更する

書式
#include <unistd.h>

int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);

glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):

fchown(), lchown():
    _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
    || /* glibc 2.12 以降: */ _POSIX_C_SOURCE >= 200809L

説明
これらのシステムコールは、いずれもファイルの所有者 (owner) とグループを変更する。システムコール間の違いは、ファイルの指定の仕方だけである。

*   chown() は path で指定されたファイルの所有権を変更する。 path がシンボリック・リンクの場合は、リンクの展開が行われる。

*   fchown() はオープンされたファイルディスクリプタ fd により参照されるファイルの所有権を変更する。

*   lchown() は chown() と同じだが、シンボリック・リンクを展開しない点が異なる。

特権を持つプロセス (Linux では CAP_CHOWN ケーパビリティ (capability) を持つプロセス) だけが ファイルの所有者を変更できる。 ファイルの所有者は、その所有者が属しているグループのいずれかに ファイルのグループを変更することができる。 特権 (Linux では CAP_CHOWN) を持つプロセスは、任意のグループに変更できる。 owner または group に -1 が指定された場合、それらの ID は変更されない。 非特権ユーザーにより実行ファイルの所有者またはグループが 変更された場合は S_ISUID と ISGID モードビットはクリアされる。 POSIX はこの動作やルートが chown() を行なった場合については特に指定されていない。 Linux における動作はカーネルのバージョンに依存する。 非グループ実行ファイル (S_IXGRP ビットが設定されていないファイル) の場合には S_ISGID ビットは強制ロック (mandatory locking) を意味している。 そしてそれは chown() ではクリアできない。

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

エラー
ファイルシステムによっては他のエラーが返される事がある。 chmod で一般的なエラーを以下に挙げる。

EACCES
    パス名の構成要素に検索許可がない (path_resolution(7) も見よ)。

EFAULT
    path がアクセスできるアドレス空間外を指している。

ELOOP
    path を解決する際に遭遇したシンボリック・リンクが多過ぎる。

ENAMETOOLONG
    path が長過ぎる。

ENOENT
    ファイルが存在しない。

ENOMEM
    カーネルに十分なメモリがない。

ENOTDIR
    パス名の構成要素がディレクトリではない。

EPERM
    呼び出したプロセスに所有者またはグループ (もしくはその両方) を変更するために 要求される許可 (上記を参照) がない。

EROFS
    ファイルが読み込み専用 (read only) のファイル・システム上にある。

fchown() で一般的なエラーを以下に挙げる:

EBADF
    ディスクリプターが有効でない。

EIO i ノード (inode) を変更する際に低レベル I/O エラーが発生した。

ENOENT
    上記を参照。

EPERM
    上記を参照。

EROFS
    上記を参照。

準拠
4.4BSD, SVr4, POSIX.1-2001. 4.4BSD 版ではスーパー・ユーザーのみが使用できる (つまり、普通のユーザーはファイルを手放すことはできない)。

注意
元々の Linux の chown(), fchown(), lchown() システムコールは、 16 ビットのユーザ ID とグループ ID だけに対応していた。 その後、 32 ビットの ID に対応した chown32(), fchown32(), lchown32() が Linux 2.4 で追加された。 chown(), fchown(), and lchown() の glibc のラッパー関数は、 カーネルのバージョンによる違いを吸収している。 (open(2) や mkdir(2) などにより) 新しいファイルが作成されるとき、 その所有者は呼び出したプロセスのファイルシステム・ユーザ ID と 同じに設定される。 そのファイルのグループはいくつかの要因により決定される。 その要因としては、 ファイルシステムの種類、そのファイルシステムのマウント時に 使用されたオプション、親ディレクトリで set-group-ID 許可ビットが 有効になっているどうか、がある。 ファイルシステムが mount(8) オプションの -o grpid (-o bsdgroups も同義語) と -o nogrpid (-o sysvgroups も同義語) に対応している場合、ルールは以下の通りとなる。

*   ファイルシステムが -o grpid 付きでマウントされている場合、新しいファイルのグループは 親ディレクトリのグループと同じになる。

*   ファイルシステムが -o nogrpid 付きでマウントされており、親ディレクトリでは set-group-ID ビットが 無効になっている場合、新しいファイルのグループは プロセスのファイルシステム GID と同じになる。

*   ファイルシステムが -o nogrpid 付きでマウントされており、親ディレクトリでは set-group-ID ビットが 有効になっている場合、新しいファイルのグループは 親ディレクトリのグループと同じになる。

Linux 2.6.25 では、マウントオプション -o grpid と -o nogrpid に対応しているファイルシステムは ext2, ext3, ext4, XFS である。 これらのマウントオプションに対応していないファイルシステムでは、 -o nogrpid に関するルールが適用される。

chown() 方式は UID マッピングを使用した NFS ファイル・システムを侵害する。 さらにファイルの内容にアクセスする全てのシステム・コールを侵害する。 これは chown() が既にオープンされたファイルに対する アクセスをただちに取り消すことによる。 クライアント側のキャッシュにより所有権が変更されて ユーザーのアクセスが許した時点と、実際に他のクライアントでユーザーによって ファイルにアクセスできる時点との間に時間差があるかもしれない。 Linux の 2.1.81 より前のバージョン (特に 2.1.46 以前) では、 chown() はシンボリック・リンクを追跡しない。 Linux 2.1.81 以降では chown() はシンボリック・リンクを追跡し、新たなシステム・コール lchown() はシンボリック・リンクを追跡しない。 Linux 2.1.86 以降ではこの新しいコール (古い chown() と全く同じ動作を行なう) は同じシステムコール番号を持ち chown() は新しく導入された番号を持つ。

例

以下のプログラムは、 二つ目のコマンドライン引き数で指定された名前のファイルの所有者を、 一つ目のコマンドライン引き数で指定された値に変更する。 新しい所有者は、数字のユーザ ID かユーザ名のいずれかで指定できる (ユーザ名で指定した場合には、 getpwnam(3) を使ってシステムのパスワードファイルの検索が行われ、 ユーザ ID への変換が行われる)。
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
    uid_t uid;
    struct passwd *pwd;
    char *endptr;
    if (argc != 3 || argv[1][0] == '\0') {
        fprintf(stderr, "%s <owner> <file>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    uid = strtol(argv[1], &endptr, 10);  /* Allow a numeric string */
    if (*endptr != '\0') {         /* Was not pure numeric string */
        pwd = getpwnam(argv[1]);   /* Try getting UID for username */
        if (pwd == NULL) {
            perror("getpwnam");
            exit(EXIT_FAILURE);
        }
        uid = pwd->pw_uid;
    }
    if (chown(argv[2], uid, -1) == -1) {
        perror("chown");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

関連項目
chmod(2), fchownat(2), flock(2), path_resolution(7), symlink(7)

この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.51 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。