【C/C++ファイル処理シリーズ】struct statのst_modeでファイルタイプを判断する


linuxシステムファイルのタイプは、通常ファイル、ディレクトリファイル、文字デバイス、ブロックデバイス、パイプファイル、リンクファイル、ソケットファイルの7種類です.
man 2 statでst_を取得できますmodeは、サービスのタイプを判別するために使用することができる.原文は以下の通り.
The following POSIX macros are defined to check the file type using the st_mode field:

           S_ISREG(m)  is it a regular file?

           S_ISDIR(m)  directory?

           S_ISCHR(m)  character device?

           S_ISBLK(m)  block device?

           S_ISFIFO(m) FIFO (named pipe)?

           S_ISLNK(m)  symbolic link? (Not in POSIX.1-1996.)

           S_ISSOCK(m) socket? (Not in POSIX.1-1996.)

ここでst_modeフィールドのファイルタイプに関する判断は以下の通りです.
       The following flags are defined for the st_mode field:

           S_IFMT     0170000   bit mask for the file type bit fields
           S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO

以上、macrosマクロコマンドS_ISREG(m)は、通常ファイルであるか否かを判断することができ、S_ISDIR(m)パスか否かを判断する…
sys/stat.hファイルでmacrosの定義を見つけることができます.以下のようにします.
/* Test macros for file types.  */

#define __S_ISTYPE(mode, mask)  (((mode) & __S_IFMT) == (mask))

#define S_ISDIR(mode)    __S_ISTYPE((mode), __S_IFDIR)
#define S_ISCHR(mode)    __S_ISTYPE((mode), __S_IFCHR)
#define S_ISBLK(mode)    __S_ISTYPE((mode), __S_IFBLK)
#define S_ISREG(mode)    __S_ISTYPE((mode), __S_IFREG)
#ifdef __S_IFIFO
# define S_ISFIFO(mode)  __S_ISTYPE((mode), __S_IFIFO)
#endif
#ifdef __S_IFLNK
# define S_ISLNK(mode)   __S_ISTYPE((mode), __S_IFLNK)
#endif

#if defined __USE_BSD && !defined __S_IFLNK
# define S_ISLNK(mode)  0
#endif
#if (defined __USE_BSD || defined __USE_UNIX98 || defined __USE_XOPEN2K) \
    && defined __S_IFSOCK
# define S_ISSOCK(mode) __S_ISTYPE((mode), __S_IFSOCK)
#elif defined __USE_XOPEN2K
# define S_ISSOCK(mode) 0
#endif

あらかじめ定義された関数_S_ISTYPE(mode, mask)  (((mode) & __S_IFMT)==(mask))、modeと__を転送するS_IFMTはビット別と後の結果をmaskと比較し,入力したmaskと同様であればそのタイプのファイルと判断する.
まずsys/stat.hで__を検索S_IFMTは、以下のように定義された部分を検索します.
#include 

#if defined __USE_BSD || defined __USE_MISC || defined __USE_XOPEN
# define S_IFMT         __S_IFMT
# define S_IFDIR        __S_IFDIR
# define S_IFCHR        __S_IFCHR
# define S_IFBLK        __S_IFBLK
# define S_IFREG        __S_IFREG
# define S_IFDIR        __S_IFDIR
# define S_IFCHR        __S_IFCHR
# define S_IFBLK        __S_IFBLK
# define S_IFREG        __S_IFREG
# ifdef __S_IFIFO
#  define S_IFIFO       __S_IFIFO
# endif
# ifdef __S_IFLNK
#  define S_IFLNK       __S_IFLNK
# endif
# if (defined __USE_BSD || defined __USE_MISC || defined __USE_UNIX98) \
     && defined __S_IFSOCK
#  define S_IFSOCK      __S_IFSOCK
# endif
#endif

すなわち、#includeで関連定義を見つけ、bits/stat.hファイルを開き、検索を続行することができる_S_IFMTは、以下の内容を得る.
/* Encoding of the file mode.  */

#define __S_IFMT        0170000 /* These bits determine file type.  */

/* File types.  */
#define __S_IFDIR       0040000 /* Directory.  */
#define __S_IFCHR       0020000 /* Character device.  */
#define __S_IFBLK       0060000 /* Block device.  */
#define __S_IFREG       0100000 /* Regular file.  */
#define __S_IFIFO       0010000 /* FIFO.  */
#define __S_IFLNK       0120000 /* Symbolic link.  */
#define __S_IFSOCK      0140000 /* Socket.  */

先に定義したファイルタイプのマスク_S_IFMTは0170000 8進数です.次に、7つのファイルタイプについて異なる符号化を定義します.
###########
以上の各定義を読むことで、マクロコマンドの定義を振り返ってみます(一部のみ羅列されています):
#define __S_ISTYPE(mode, mask)  (((mode) & __S_IFMT) == (mask))

#define S_ISDIR(mode)    __S_ISTYPE((mode), __S_IFDIR)
#define S_ISCHR(mode)    __S_ISTYPE((mode), __S_IFCHR)

1、すなわち、一つのファイルがディレクトリであるか否かを判別する際に、S_を呼び出すことができるISDIR(mode),マクロコマンド,その関数プロトタイプは呼び出し__である.S_ISTYPE((mode), __S_IFDIR)
2、__S_IFDIRの符号化は0040000で、8進法、すなわちパラメータ後_S_ISTYPE((mode), 0040000 )
3、参考_S_ISTYPEのプロトタイプ:#define_S_ISTYPE(mode, mask)  (((mode) & __S_IFMT)==(mask),そのうち_S_IFMTの符号化は0170000,8進法である.
参照後は、#define_S_ISTYPE(mode, __S_IFDIR )    (((mode) & __S_IFMT) == (__S_IFDIR ))
すなわち、#define_S_ISTYPE(mode, 0040000 )    (((mode) & 0170000  ) == (0040000 ))
4、modeパラメータはstruct stat中st_modeの値はstat()関数で取得できます.
    struct stat mystat;
    stat("/data/natpan/tmp/LTars/l_file",&mystat)

つまりmystat.st_modeは着信_S_ISTYPE関数のmode.
5、mystat.を通るst_modeとマスク_S_IFMT按位与,结果与_S_IFDIR比較は、同じディレクトリです.
6、残りのファイルタイプの判断方法は類似している.
ビット単位の演算が容易で、各タイプの定義符号化されたバイナリフォーマットが印刷されます.
S_IFMT   :1111000000000000 Octal: 0170000 ## bit mask for the file type bit fields
S_IFSOCK :1100000000000000 Octal: 0140000  socker
S_IFLNK  :1010000000000000 Octal: 0120000  symbolic link
S_IFREG  :1000000000000000 Octal: 0100000  regular file
S_IFBLK  :0110000000000000 Octal: 0060000  block device
S_IFDIR  :0100000000000000 Octal: 0040000 directory
S_IFCHR  :0010000000000000 Octal: 0020000  character device
S_IFIFO  :0001000000000000 Octal: 0010000  FIFO