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