ファイルシステムにはファイルやディレクトリ,リンクといった異なる種類の実体があります.また,それらにはアクセスされた時刻の情報も属性として記録されています.
ここでは,指定したパスの実体の属性を調べる方法について説明します.
指定したパスの属性を取得するには stat という関数を呼び出します.
また,stat の呼び出しで得られた属性の情報は stat 構造体に格納されます.
例.ポインタ cahr *path によって示されるパス名の文字列があるとき,そのパスの属性を得る方法
struct stat buf; r = stat(path,&buf); |
(int r は戻り値で,stat の処理が正常に終了した場合は 0 となる)
これにより,構造体 buf にパスの各種の属性が格納される.
指定したパスがシンボリックリンクである場合,そのリンク先の実体の属性を求めるのか,あるいはリンクそのものの属性を求めるかは全く意味が異なります.
「リンクであるかどうか」の情報が必要な場合は stat ではなく lstat を用います.
構造体 stat の定義
struct stat { dev_t st_dev; /* ファイルがあるデバイスの ID */ ino_t st_ino; /* inode 番号 */ mode_t st_mode; /* アクセス保護 */ nlink_t st_nlink; /* ハードリンクの数 */ uid_t st_uid; /* 所有者のユーザー ID */ gid_t st_gid; /* 所有者のグループ ID */ dev_t st_rdev; /* デバイス ID (特殊ファイルの場合) */ off_t st_size; /* 全体のサイズ (バイト単位) */ blksize_t st_blksize; /* ファイルシステム I/O での ブロックサイズ */ blkcnt_t st_blocks; /* 割り当てられた 512B のブロック数 */ struct timespec st_atim; /* 最終アクセス時刻 */ struct timespec st_mtim; /* 最終修正時刻 */ struct timespec st_ctim; /* 最終状態変更時刻 */ }; #define st_atime st_atim.tv_sec #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec |
この構造体のメンバにファイルに関する各種の情報が格納されています.
特に st_mode には,それがファイルなのかディレクトリなのか,
あるいはシンボリックリンクなのかという情報が格納されており,
実体の種別を識別するのに使うことができます.
ファイル/ディレクトリ/シンボリックリンクの判別
st_mode から種別を判定する下記のような関数があります.
S_ISREG : 通常のファイルであることを判定
S_ISDIR : ディレクトリであることを判定
S_ISLNK : シンボリックリンクであることを判定
サンプルプログラム : 指定したパスの情報を表示するプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #include <stdio.h> #include <unistd.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> struct stat buf; struct tm *ts; int main(ac,av) int ac; char **av; { int r, size, mode; char *path, tf[128]; if ( ac < 2 ) { fprintf(stderr,"No arguments.\n"); return(-1); } path = av[1]; // パス名を取得 fprintf(stderr,"path: %s\n",path); // r = stat(path,&buf); // パスの属性を取得 r = lstat(path,&buf); // パスの属性を取得 if ( r != 0 ) { // エラー処理 fprintf(stderr,"error: stat = %d\n",r); return(-1); } // ts = localtime(&(buf.st_atime)); // 最終アクセス時刻を取得 ts = gmtime(&(buf.st_atime)); // 最終アクセス時刻を取得 // strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S(%z)",ts); strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S",ts); printf("Last access(st_atime) = %s\n",tf); // 表示 // ts = localtime(&(buf.st_mtime)); // 最終修正時刻を取得 ts = gmtime(&(buf.st_mtime)); // 最終修正時刻を取得 // strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S(%z)",ts); strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S",ts); printf("Last modified(st_mtime) = %s\n",tf); // 表示 // ts = localtime(&(buf.st_ctime)); // 最終状態変更時刻を取得 ts = gmtime(&(buf.st_ctime)); // 最終状態変更時刻を取得 // strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S(%z)",ts); strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S",ts); printf("Last state change(st_ctime) = %s\n",tf); // 表示 size = (int)(buf.st_size); // サイズを取得 printf("size: %d (bytes)\n",size); // 表示 mode = (int)(buf.st_mode); // アクセス属性の取得 printf("mode: %o\n",mode); // 表示 // ファイル/ディレクトリ/シンボリックリンクの判定 printf("type: /"); if ( S_ISREG(buf.st_mode) ) { printf("regular file/"); } if ( S_ISDIR(buf.st_mode) ) { printf("directory/"); } if ( S_ISLNK(buf.st_mode) ) { printf("simlink/"); } printf("\n"); } |
このプログラムを s_fstat という名前で作成して実行した例を次に示します.
実行例1 ディクレイトリ “.” の属性を調べる例
$ s_fstat . path: . Last access(st_atime) = 2015/03/27(Fri) 10:28:37 Last modified(st_mtime) = 2015/03/16(Mon) 11:08:31 Last state change(st_ctime) = 2015/03/16(Mon) 11:08:31 size: 442 (bytes) mode: 40755 type: /directory/ $ |
実行例2 ソースファイル “s_fstat.c” の属性を調べる例
$ s_fstat s_fstat.c path: s_fstat.c Last access(st_atime) = 2015/03/23(Mon) 10:15:09 Last modified(st_mtime) = 2015/03/15(Sun) 07:55:09 Last state change(st_ctime) = 2015/03/15(Sun) 07:55:09 size: 1488 (bytes) mode: 100640 type: /regular file/ $ |
実行例3 シンボリックリンク “sl” の属性を調べる例
$ s_fstat sl path: sl Last access(st_atime) = 2015/03/15(Sun) 07:22:56 Last modified(st_mtime) = 2015/03/15(Sun) 07:22:56 Last state change(st_ctime) = 2015/03/15(Sun) 07:22:56 size: 9 (bytes) mode: 120755 type: /simlink/ $ |