stat関数を使う

今回は、stat関数を使います。
まずは、man 2 statの冒頭です。

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

名前
       stat, fstat, lstat, fstatat - ファイルの状態を取得する

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

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

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

       int fstatat(int dirfd, const char *pathname, struct stat *buf,
                   int flags);


型が分かったので、statをコールするプログラムを作ります。

takk@deb9:~/tmp$ cat -n mystat.c
     1	#include <sys/types.h>
     2	#include <sys/stat.h>
     3	#include <unistd.h>
     4	
     5	int main(int argc, char* argv[])
     6	{
     7		struct stat buf;
     8		char* filename;
     9	
    10		filename = argv[1];
    11	
    12		stat(filename, buf);	
    13	
    14		return 0;
    15	}
takk@deb9:~/tmp$ 

まあ、後はgdbで値を見ていけば、bufの使い方は分かってくるでしょう。ということで、-g付きでビルドします。

takk@deb9:~/tmp$ gcc -g mystat.c
mystat.c: In function ‘main’:
mystat.c:12:17: error: incompatible type for argument 2 of ‘stat’
  stat(filename, buf);
                 ^~~
In file included from mystat.c:2:0:
/usr/include/x86_64-linux-gnu/sys/stat.h:208:12: note: expected ‘struct stat * restrict’ but argument is of type ‘struct stat’
 extern int stat (const char *__restrict __file,
            ^~~~
takk@deb9:~/tmp$ 

エラーになりました。ポインタだといってるのに、ポインタにしてないからです。
struct stat bufがスカラーになってます。配列に変えます。
テキストエディタを開くのが面倒なので、sedで置換。

takk@deb9:~/tmp$ sed 's/buf;/buf[1];/' -i mystat.c
takk@deb9:~/tmp$ cat -n mystat.c
     1	#include <sys/types.h>
     2	#include <sys/stat.h>
     3	#include <unistd.h>
     4	
     5	int main(int argc, char* argv[])
     6	{
     7		struct stat buf[1];
     8		char* filename;
     9	
    10		filename = argv[1];
    11	
    12		stat(filename, buf);	
    13	
    14		return 0;
    15	}
takk@deb9:~/tmp$ 

改めて、ビルドします。

takk@deb9:~/tmp$ !g
gcc -g mystat.c
takk@deb9:~/tmp$ 

gdbで動かす前に、statをかけるファイルを作成。

takk@deb9:~/tmp$ echo -n 123>test.bin
takk@deb9:~/tmp$

gdbを起動します。set argsでtest.binも指定しておきます。

takk@deb9:~/tmp$ gdb a.out

~省略~

(gdb) b main
Breakpoint 1 at 0x6c8: file mystat.c, line 10.
(gdb) set args test.bin
(gdb) r
Starting program: /home/takk/tmp/a.out test.bin

Breakpoint 1, main (argc=2, argv=0x7fffffffe5b8) at mystat.c:10
10              filename = argv[1];
(gdb) n
12              stat(filename, buf);
(gdb)
14              return 0;
(gdb)

statをコール後、bufの中身を表示してみました。

(gdb) p buf
$1 = {{st_dev = 2049, st_ino = 1739370, st_nlink = 1, st_mode = 33188,
    st_uid = 1000, st_gid = 1000, __pad0 = 0, st_rdev = 0, st_size = 0,
    st_blksize = 4096, st_blocks = 0, st_atim = {tv_sec = 1523796082,
      tv_nsec = 116000000}, st_mtim = {tv_sec = 1523796082,
      tv_nsec = 116000000}, st_ctim = {tv_sec = 1523796082,
      tv_nsec = 116000000}, __glibc_reserved = {0, 0, 0}}}
(gdb)

各メンバのことは、statコマンドを参考に見ていけば、分かりそうです。

takk@deb9:~/tmp$ stat test.bin
  File: test.bin
  Size: 0               Blocks: 0          IO Block: 4096   通常の空ファイル
Device: 801h/2049d      Inode: 1739370     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/    takk)   Gid: ( 1000/    takk)
Access: 2018-04-15 21:41:22.116000000 +0900
Modify: 2018-04-15 21:41:22.116000000 +0900
Change: 2018-04-15 21:41:22.116000000 +0900
 Birth: -
takk@deb9:~/tmp$

続く

Leave a Reply

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

CAPTCHA