第72章 stat 構造体

 stat 構造体はファイルの情報を取得するための関数の引数として使用されます。

 まあステータス情報を保持するためのオブジェクトぐらいに考えておけば結構です。

 構造体の中身を見るまえにスターテスを取得する関数の宣言です。

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

int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);

 stat は pathname で指定したファイルの情報を statbuf に更新します。

 fstat はファイル記述子 fd で指定したファイルの情報を statbuf に更新します。

 lstat は pathname がシンボリックリンクならば、リンクが指すファイルでなく、リンクの情報を返します。

 次は構造体の宣言・定義を見てみましょう。

struct stat {
    dev_t     st_dev;         /* ID of device containing file */
    ino_t     st_ino;         /* Inode number */
    mode_t    st_mode;        /* File type and mode */
    nlink_t   st_nlink;       /* Number of hard links */
    uid_t     st_uid;         /* User ID of owner */
    gid_t     st_gid;         /* Group ID of owner */
    dev_t     st_rdev;        /* Device ID (if special file) */
    off_t     st_size;        /* Total size, in bytes */
    blksize_t st_blksize;     /* Block size for filesystem I/O */
    blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */

    /* Since Linux 2.6, the kernel supports nanosecond
       precision for the following timestamp fields.
       For the details before Linux 2.6, see NOTES. */

    struct timespec st_atim;  /* Time of last access */
    struct timespec st_mtim;  /* Time of last modification */
    struct timespec st_ctim;  /* Time of last status change */

#define st_atime st_atim.tv_sec      /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};

 まあ情報量が多いので、全部は説明しませんがユーザーID、グループID、inode番号、ブロックサイズ、ブロック数などの情報を取得できます。

 ではファイル情報の取得をするちょっとしたコードを書いて見ましょう。

main.c. 

  1 #include <stdio.h>
  2 #include <sys/stat.h>
  3 #include <sys/types.h>
  4 #include <unistd.h>
  5 #include <fcntl.h>
  6 #include <stdlib.h>
  7
  8 #define BUFSIZE 16
  9
 10 int main()
 11 {
 12   int fd;
 13   struct stat sb;
 14   char buf[BUFSIZE];
 15
 16   fd = open("mm_file",O_CREAT|O_RDWR|O_TRUNC,0644);
 17   if(fd < 0){
 18     perror("ファイルを開けません");
 19     exit(1);
 20   }
 21   write(fd,buf,BUFSIZE);
 22   if(fstat(fd,&sb)==-1){
 23     perror("fstatに失敗");
 24     exit(1);
 25   }
 26   printf("st_size       = %ld\n",sb.st_size);
 27   printf("st_blksize    = %ld\n",sb.st_blksize);
 28   printf("st_blocks     = %ld\n",sb.st_blocks);
 29   printf("st_ino        = %ld\n",sb.st_ino);
 30   printf("st_gid        = %ld\n",(long)sb.st_gid);
 31   printf("st_uid        = %ld\n",(long)sb.st_uid);
 32
 33   switch(sb.st_mode & S_IFMT) {
 34     case S_IFREG:
 35       printf("file\n");
 36       break;
 37     case S_IFBLK:
 38       printf("block device node\n");
 39       break;
 40     case S_IFCHR:
 41       printf("character device node\n");
 42       break;
 43     case S_IFLNK:
 44       printf("symbolic link\n");
 45       break;
 46     case S_IFSOCK:
 47       printf("socket\n");
 48       break;
 49     default:
 50       printf("No match\n");
 51       break;
 52   }
 53   close(fd);
 54
 55   return 0;
 56 }

ビルドと実行の結果. 

$ gcc main.c
$ ./a.out
st_size       = 16
st_blksize    = 4096
st_blocks     = 8
st_ino        = 55452023
st_gid        = 1000
st_uid        = 1000
file

 このソースコードは mm_file というファイルを生成または開いてから buf の中身を書き込み、ファイル情報をチェックしています。

 12   int fd;
 13   struct stat sb;
 14   char buf[BUFSIZE];
 15
 16   fd = open("mm_file",O_CREAT|O_RDWR|O_TRUNC,0644);
 17   if(fd < 0){
 18     perror("ファイルを開けません");
 19     exit(1);
 20   }
 21   write(fd,buf,BUFSIZE);
 22   if(fstat(fd,&sb)==-1){
 23     perror("fstatに失敗");
 24     exit(1);
 25   }

 st_size はファイルサイズですね。

 buf のサイズが 16 バイトですんで、そのままの値です。

 st_blksize は 4KB です。

 st_blocks は 512 バイトのブロック数なので 8 個あります。

 この場合は 4KB が 512B の 8 個分ということになります。

 st_ino は inode 番号です。

 st_gid と st_uid は両方とも 1000 です。

 最後に st_mode は S_IFREG にマッチしています。

 33   switch(sb.st_mode & S_IFMT) {
 34     case S_IFREG:
 35       printf("file\n");

 まあリンクとかでなく普通のファイルって意味です。

Copyright 2018-2019, by Masaki Komatsu