• 获取文件信息: 大小, 文件类型等.


    1. stat

      • 说明

        • 主要是文件信息.即关于文件本身的信息.
      • 来源

        • 从文件系统中获取.bits/stat.h + sys/stat.h
    2. 解析

      • struct stat

        struct stat
         {
           __dev_t st_dev;     /* Device.  */
        #ifndef __x86_64__
           unsigned short int __pad1;
        #endif
        #if defined __x86_64__ || !defined __USE_FILE_OFFSET64
           __ino_t st_ino;     /* File serial number.  */
        #else
           __ino_t __st_ino;           /* 32bit file serial number.    */
        #endif
        #ifndef __x86_64__
           __mode_t st_mode;           /* File mode.  */
           __nlink_t st_nlink;         /* Link count.  */
        #else
           __nlink_t st_nlink;     /* Link count.  */
           __mode_t st_mode;       /* File mode.  */
        #endif
           __uid_t st_uid;     /* User ID of the file's owner. */
           __gid_t st_gid;     /* Group ID of the file's group.*/
        #ifdef __x86_64__
           int __pad0;
        #endif
           __dev_t st_rdev;        /* Device number, if device.  */
        #ifndef __x86_64__
           unsigned short int __pad2;
        #endif
        #if defined __x86_64__ || !defined __USE_FILE_OFFSET64
           __off_t st_size;            /* Size of file, in bytes.  */
        #else
           __off64_t st_size;          /* Size of file, in bytes.  */
        #endif
           __blksize_t st_blksize; /* Optimal block size for I/O.  */
        #if defined __x86_64__  || !defined __USE_FILE_OFFSET64
           __blkcnt_t st_blocks;       /* Number 512-byte blocks allocated. */
        #else
           __blkcnt64_t st_blocks;     /* Number 512-byte blocks allocated. */
        #endif
        #ifdef __USE_XOPEN2K8
           /* Nanosecond resolution timestamps are stored in a format
              equivalent to 'struct timespec'.  This is the type used
              whenever possible but the Unix namespace rules do not allow the
              identifier 'timespec' to appear in the  header.
              Therefore we have to handle the use of this header in strictly
              standard-compliant sources special.  */
           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
        #else
           __time_t st_atime;          /* Time of last access.  */
           __syscall_ulong_t st_atimensec; /* Nscecs of last access.  */
           __time_t st_mtime;          /* Time of last modification.  */
           __syscall_ulong_t st_mtimensec; /* Nsecs of last modification.  */
           __time_t st_ctime;          /* Time of last status change.  */
           __syscall_ulong_t st_ctimensec; /* Nsecs of last status change.  */
        #endif
        #ifdef __x86_64__
           __syscall_slong_t __glibc_reserved[3];
        #else
        # ifndef __USE_FILE_OFFSET64
           unsigned long int __glibc_reserved4;
           unsigned long int __glibc_reserved5;
        # else
           __ino64_t st_ino;           /* File serial number.  */
        # endif
        #endif
         };
        
        • 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
        • 69
        • 70
        • st_dev 设备号,即硬盘设备.

        • st_ino 文件在文件系统中的inode, 即文件系统中的文件编号.

        • st_mode 底下详解.

        • st_nlink 同一个文件系统下的硬链接数量.

        • st_uid 文件所属用户id

        • st_gid 文件所属组id

        • st_rdev 字符设备或者块设备才有.

        • st_size 普通文件则是文件大小; 符号链接则是符号链接保存的路径长度; 共享内存文件则是共享内存大小, 字节; typed memory同样是内存大小,字节; 其他文件类型则无内容.

        • st_atim 最后一次被访问(读)时间, 精确到微秒.

        • st_mtim 最后一次被修改(写)时间, 精确到微秒.

        • st_ctim 最后一次被修改文件属性(chmod)时间, 精确到微秒.

        • st_blksize 当前文件系统最优文件块大小.不同系统大小可能不同.

        • st_blocks 当前文件占用文件块.

      • st_mode

        • 首先是位运算进行组合.

        #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.  */
        #define    __S_IFMT    0170000 /* These bits determine file type.  */
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 八进制. 表示文件类型.

        • 通过和S_FIMT进行位于,然后switch获取对应类型.

              S_IFMT      Type of file.
                          S_IFBLK     Block special.
                          S_IFCHR     Character special.
                          S_IFIFO     FIFO special.
                          S_IFREG     Regular.
                          S_IFDIR     Directory.
                          S_IFLNK     Symbolic link.
                          S_IFSOCK    Socket.
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 其他信息
        #define __S_ISUID   04000   /* Set user ID on execution.  */
        #define __S_ISGID   02000   /* Set group ID on execution.  */
        #define __S_ISVTX   01000   /* Save swapped text after use (sticky).  */
        #define __S_IREAD   0400    /* Read by owner.  */
        #define __S_IWRITE  0200    /* Write by owner.  */
        #define __S_IEXEC   0100    /* Execute by owner.  */
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 文件所有者的权限,组权限,其他人的权限. 权限则有: 读写执行任意组合.八进制.
      • 外部使用

        #if 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
        # ifdef __S_IFIFO
        #  define S_IFIFO   __S_IFIFO
        # endif
        # ifdef __S_IFLNK
        #  define S_IFLNK   __S_IFLNK
        # endif
        # if (defined __USE_MISC || defined __USE_XOPEN_EXTENDED) \
            && defined __S_IFSOCK
        #  define S_IFSOCK  __S_IFSOCK
        # endif
        #endif
        
        /* 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_MISC && !defined __S_IFLNK
        # define S_ISLNK(mode)  0
        #endif
        
        #if (defined __USE_XOPEN_EXTENDED || 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
        
        /* These are from POSIX.1b.  If the objects are not implemented using separate
          distinct file types, the macros always will evaluate to zero.  Unlike the
          other S_* macros the following three take a pointer to a `struct stat'
          object as the argument.  */
        #ifdef  __USE_POSIX199309
        # define S_TYPEISMQ(buf) __S_TYPEISMQ(buf)
        # define S_TYPEISSEM(buf) __S_TYPEISSEM(buf)
        # define S_TYPEISSHM(buf) __S_TYPEISSHM(buf)
        #endif
        
        
        /* Protection bits.  */
        
        #define S_ISUID __S_ISUID   /* Set user ID on execution.  */
        #define S_ISGID __S_ISGID   /* Set group ID on execution.  */
        
        #if defined __USE_MISC || defined __USE_XOPEN
        /* Save swapped text after use (sticky bit).  This is pretty well obsolete.  */
        # define S_ISVTX    __S_ISVTX
        #endif
        
        #define S_IRUSR __S_IREAD   /* Read by owner.  */
        #define S_IWUSR __S_IWRITE  /* Write by owner.  */
        #define S_IXUSR __S_IEXEC   /* Execute by owner.  */
        /* Read, write, and execute by owner.  */
        #define S_IRWXU (__S_IREAD|__S_IWRITE|__S_IEXEC)
        
        #ifdef __USE_MISC
        # define S_IREAD    S_IRUSR
        # define S_IWRITE   S_IWUSR
        # define S_IEXEC    S_IXUSR
        #endif
        
        #define S_IRGRP (S_IRUSR >> 3)  /* Read by group.  */
        #define S_IWGRP (S_IWUSR >> 3)  /* Write by group.  */
        #define S_IXGRP (S_IXUSR >> 3)  /* Execute by group.  */
        /* Read, write, and execute by group.  */
        #define S_IRWXG (S_IRWXU >> 3)
        
        #define S_IROTH (S_IRGRP >> 3)  /* Read by others.  */
        #define S_IWOTH (S_IWGRP >> 3)  /* Write by others.  */
        #define S_IXOTH (S_IXGRP >> 3)  /* Execute by others.  */
        /* Read, write, and execute by others.  */
        #define S_IRWXO (S_IRWXG >> 3)
        
        
        #ifdef  __USE_MISC
        /* Macros for common mode bit masks.  */
        # define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) /* 0777 */
        # define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)/* 07777 */
        # define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)/* 0666*/
        
        # define S_BLKSIZE  512 /* Block size for `st_blocks'.  */
        #endif
        
        • 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
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
        • 79
        • 80
        • 81
        • 82
        • 83
        • 84
        • 85
        • 86
        • 87
        • 88
        • 89
        • 90
        • 91
        • 92
        • 93
        • 94
        • 95
        • 96
        • 97
        • 98
        • 定义了一些宏定义和一些简便使用方式.

    3. 案例

      • 执行

        ch@chvm:~/ch/cppfile/test$ gdb -q ./a.out
        Reading symbols from ./a.out...done.
        (gdb) b main
        Breakpoint 1 at 0x705: file test.cpp, line 5.
        (gdb) r
        Starting program: /home/ch/ch/cppfile/test/a.out
        
        Breakpoint 1, main () at test.cpp:5
        5       int main() {
        (gdb) n
        6         const char* pathname = "/root";
        (gdb)
        9         if( stat( pathname, &info ) != 0 )
        (gdb)
        11        else if( info.st_mode & S_IFDIR )
        (gdb) p info
        $1 = {st_dev = 2049, st_ino = 6029313, st_nlink = 5, st_mode = 16832, st_uid = 0, st_gid = 0, __pad0 = 0, st_rdev = 0,
         st_size = 4096, st_blksize = 4096, st_blocks = 8, st_atim = {tv_sec = 1596753951, tv_nsec = 0}, st_mtim = {tv_sec = 1629703454,
           tv_nsec = 266149333}, st_ctim = {tv_sec = 1629703454, tv_nsec = 266149333}, __glibc_reserved = {0, 0, 0}}
        (gdb) !stat /root
         File: /root
         Size: 4096            Blocks: 8          IO Block: 4096   directory
        Device: 801h/2049d      Inode: 6029313     Links: 5
        Access: (0700/drwx------)  Uid: (    0/    root)   Gid: (    0/    root)
        Access: 2020-08-07 06:45:51.000000000 +0800
        Modify: 2021-08-23 15:24:14.266149333 +0800
        Change: 2021-08-23 15:24:14.266149333 +0800
        Birth: -
        (gdb) !cat test.cpp
        #include 
        #include 
        #include 
        
        int main() {
         const char* pathname = "/root";
         struct stat info;
        
         if( stat( pathname, &info ) != 0 )
             printf( "cannot access %s\n", pathname );
         else if( info.st_mode & S_IFDIR )
             printf( "%s is a directory\n", pathname );
         else if( info.st_mode & S_IFREG )
             printf( "%s is a file\n", pathname );
         else
             printf( "%s is no directory\n", pathname );
        }
        
        • 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
        • 首先是编译.

        • 设置断点.

        • 执行获取信息.

        • 这里的st_mode值为16832,应该使用宏定义S_ISDIR(info.st_mode).

        • 然后通过指令获取,和程序执行进行对比.

  • 相关阅读:
    Go语言为任意类型添加方法
    Docker 入门到实战 之 安装RocketMQ
    Vue脚手架创建TS项目
    qlib自动化quant
    c++中类和对象(1)
    STM32CubeMX学习笔记(47)——USB接口使用(MSC基于内部Flash模拟U盘)
    sql 注入(1), union 联合注入
    瑞吉外卖强化(二):数据库优化
    代码随想录笔记_哈希_219存在重复元素II
    弘辽科技:淘宝国庆节活动什么时候结束?活动力度大吗?
  • 原文地址:https://blog.csdn.net/rubikchen/article/details/126283939