にたまごほうれん草アーカイブ

はてなダイアリーで書いてた「にたまごほうれん草」という日記のアーカイブです。現在は「にたまごほうれん草ブログ」を運営中です。

stat関数とstat構造体

stat関数は、ファイルやディレクトリについての情報を返す。
バイスとかを触るには知っておかないといけませんね。

といっても、stat()で得られるstat構造体は、中身を見てみないと何かよくわかりません。
(manを読めば何の意味を持つのか、はある程度わかるけど)
なので、とりあえず、statで情報を出力するプログラムを作ってみました。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>

void print_stat(struct stat *st)
{
    printf("st_dev:     %10d\n", (int)st->st_dev);
    printf("st_ino:     %10d\n", (int)st->st_ino);
    printf("st_mode:    %10d\n", (int)st->st_mode);
    printf("st_nlink:   %10d\n", (int)st->st_nlink);
    printf("st_uid:     %10d\n", (int)st->st_uid);
    printf("st_gid:     %10d\n", (int)st->st_gid);
    printf("st_rdev:    %10d\n", (int)st->st_rdev);
    printf("st_size:    %10d\n", (int)st->st_size);
    printf("st_blksize: %10d\n", (int)st->st_blksize);
    printf("st_blocks:  %10d\n", (int)st->st_blocks);
    printf("st_atime:   %10d\n", (int)st->st_atime);
    printf("st_mtime:   %10d\n", (int)st->st_mtime);
    printf("st_ctime:   %10d\n", (int)st->st_ctime);
}

void check_stat(struct stat *st)
{
    mode_t m = st->st_mode;
    if (S_ISREG(m))  { printf("this is a regular file\n"); }
    if (S_ISDIR(m))  { printf("this is a directory\n"); }
    if (S_ISCHR(m))  { printf("this is a character device\n"); }
    if (S_ISBLK(m))  { printf("this is a block device\n"); }
    if (S_ISFIFO(m)) { printf("this is a FIFO\n"); }
    if (S_ISLNK(m))  { printf("this is a symbolic link\n"); }
    if (S_ISSOCK(m)) { printf("this is a socket\n"); }
}

int main(int argc, char *argv[])
{
    struct stat st;
    
    if (argc != 2) {
        return -1;
    }

    if (stat(argv[1], &st) == -1) {
        return -1;
    }

    print_stat(&st);
    check_stat(&st);

    return 0;
}

これで、実行してみる。

普通のファイルの場合

$ ./check_stat check_stat.c
st_dev:           2049
st_ino:       12225749
st_mode:         33188
st_nlink:            1
st_uid:           1000
st_gid:           1000
st_rdev:             0
st_size:          1514
st_blksize:       4096
st_blocks:           8
st_atime:   1208023991
st_mtime:   1208023985
st_ctime:   1208023985
this is a regular file

ほうほう。
INODE番号やモードは数字をそのまま見てもわかりませんな。

ディレクト

$ ./check_stat /etc
st_dev:           2049
st_ino:        8585217
st_mode:         16877
st_nlink:          147
st_uid:              0
st_gid:              0
st_rdev:             0
st_size:         12288
st_blksize:       4096
st_blocks:          24
st_atime:   1207954697
st_mtime:   1207839560
st_ctime:   1207839560
this is a directory

UID、GIDは0になるのね。

シンボリックリンク

stat()そのままだと、リンク先のファイルまたはディレクトリの情報が出力されるので、シンボリックリンクそのものの情報を出力させたい場合は、以下のようにlstat()を使う。

    if (lstat(argv[1], &st) == -1) {

で、出力。

$ ./check_stat vd
st_dev:           2049
st_ino:       12225746
st_mode:         41471
st_nlink:            1
st_uid:           1000
st_gid:           1000
st_rdev:             0
st_size:             5
st_blksize:       4096
st_blocks:           0
st_atime:   1208024315
st_mtime:   1208023949
st_ctime:   1208023949
this is a symbolic link

おおお、ちゃんとシンボリックリンクだと解釈してくれましたね。