man -s 2 stat

英语水平低于一般人之下,不达供参水平。

Linux debian 3.2.0-4-686-pae #1 SMP Debian 3.2.60-1+deb7u3 i686 GNU/Linux


名字

stat,fstat, lstat, fstatat – 获取文件状态


纲要

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

 

int stat(const char *path, struct stat *buf);

int fstat(int fd, struct stat *buf);

int lstat(const char *path, struct stat *buf);

描述

这些函数的功能是检测目标文件相关的信息。目标文件不能有阻碍这些函数来访问的权限,并且,如果使用stat()和lstat()函数时,两函数要有搜索目标文件的路径的权限。


stat()统计path参数指向的文件的相关信息并把这些信息存入参数buf中。


lstat()的第一个参数与stat()不同,path指向的是目标文件的符号链接,统计的是符号链接的信息,并不是符号链接所链接到的目标文件。


fstat()根据目标文件的文件描述符fd检测文件的信息与buf中。


这几个系统调用函数都会返回一个stat类型的结构体(buf),这个结构体由以下元素构成:

struct  stat {

        dev_t     st_dev;     /* ID of device containing file */

        ino_t     st_ino;     /* inode number */

        mode_t    st_mode;    /* protection */

        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; /* blocksize for file system I/O */

        blkcnt_t  st_blocks;  /* number of 512B blocks allocated */

        time_t    st_atime;   /* time of last access */

        time_t    st_mtime;   /* time of last modification */

        time_t    st_ctime;   /* time of last status change */

};

st_dev

st_dev元素描述文件所位于的设备号。(major(3)和minor(3)宏能将保存在这个元素里的设备ID号分解出来。)


st_rdev

st_rdev元素描述文件节点所代表的设备。


st_size

st_size元素以字节为单位给出文件(普通文件或符号链接)的大小。链接符号的大小是其路径及其名字的长度,不包含末尾的空字符的长度。


st_blocks

st_blocks元素描述了为文件分配的内存单元数目,每个内存单元为512bytes。(当文件中有“洞”时,其值有可能小于st_size / 512。)


st_blksize

st_blksize元素为有效的I/O系统的文件给出首选的块大小。(用一种更小的块写文件可能会导致读、修改及重写的无效。)


st_atime

不是所有的Linux系统都实现了关于文件时间的所有元素。一些Linux系统在st_atime中保存的是一个计数值,这个计数值是从上一次更改文件或目录到现在还未更改文件或目录的计数值。(参见mount(8)内的noatime, nodiratime及relatime参数,参见mount(2)里相关部分信息)。除此之外,如果文件是以O_NOATIME方式打开的st_atime的值不会得到更新,参见open(2)。


调用execve(2), mknod(2),pipe(2), utime(2)及read(2)等函数对文件的进行访问(访问内容超过0个字节)会修改st_atime。像其它的程序如mmap(2),不一定会更新st_atime的值。


st_mtime

调用mknod(2), truncate(2),utime(2)及write(2)等函数来修改文件(修改内容超过0个字节)时会改变st_mtime的值。另外,在一个目录里面创建或者删除一个文件时会修改这个目录的st_mtime的值。文件的拥有者(owner)、所属组(group)、硬链接数(hard link count)或者模式(mode)方式修改文件时,其文件的st_mtime的值不会改变。


st_ctime

写文件或者设置文件节点信息(如owner, group, linkcount, mode 等)时其文件的st_ctime的值会发生改变。


st_mode

通常用一下POSIX宏来检查st_mode元素的值是否含有以下列举值的意义:

S_ISREG(m) 是否为一个普通文件

S_ISDIR(m) 是否为一个目录

S_ISCHR(m) 是否为字符设备

S_ISBLK(m) 是否为块设备

S_ISFIFO(m) 是否为FIFO文件(一种管道文件)

S_ISLNK(m) 是否为符号链接(在POSIX.1-1-1996.中无)

S_ISSOCK(m)是否问socket(在POSIX.1-1-1996.中无)


以下列举宏是为st_mode定义的各种标记(flag):

S_IFMT         0170000         文件类型的屏蔽位

S_IFSOCK     0140000         socket类型文件

S_IFLNK       0120000         符号链接类型文件

S_IFREG              0100000         普通文件

S_IFBLK   0060000         块设备

S_IFDIR        0040000       目录

S_IFCHR       0020000       字符设备(ASCII文件?)

S_IFIFO        0010000       FIFO文件

 S_ISUID      0004000  (设置UID的位)set UID bit

 S_ISGID      0002000  set-group-ID bit (see below)

 S_ISVTX     0001000  sticky bit (see below)

 S_IRWXU    00700    屏蔽拥有者权限的位mask for file ownerpermissions

 S_IRUSR     00400    owner has read permission

 S_IWUSR    00200    owner has write permission

 S_IXUSR     00100    owner has execute permission

 S_IRWXG    00070    mask for group permissions

 S_IRGRP     00040    group has read permission

 S_IWGRP    00020    group has write permission

 S_IXGRP     00010    group has execute permission

S_IRWXO    00007    mask for permissions for others (not in group)

 S_IROTH     00004    others have read permission

 S_IWOTH    00002    others have write permission

 S_IXOTH     00001    others have execute permission

set-group-ID位(S_ISGID)有几个特殊的用处。对于目录来说,这几个位表示BSD语法将会被用到这个目录上:在此目录内创建的文件会继承这个目录的组ID号,而不是从创建此文件的进程那里继承有效的组ID号,并且当目录被创建时S_ISGID位将会被设置。对于文件来说,它没有组执行(S_IXGRP)的设置位,set-group-ID位被强制性的锁住了。


目录的sticky位(S_ISVTX)表示其内的文件只有文件的所属者、文件的所属者以及有特权的进行才能对其进行重命名或删除。


返回值

函数执行成功则返回0。出错返回-1,响应的错误会设置在errno参数中。


错误

EACCES

没有访问path参数路径前缀的权限。


EBADF

fd不存在。


EFAULT

地址无效。


ELOOP

当遍历目标文件路径时遇见过多的符号链接。


ENAMETOOLONG

path参数过长。


ENOENT

path参数中的某部分不存在,或者path参数是一个空字符串。


ENOMEM

内存越界(如访问到内核内存)。


ENOTDIR

path参数的目录前缀的某部分不是一个目录。


EOVERFLOW

path或者fd指定文件的大小、节点数目、块的个数呈现不出来。在一个32位平台上不用-D FILE OFFSET BITS=64的参数编译其内调用stat()函数来检测一个文件的程序,这个文件的大小超过了1 <<32 -1 字节时这个错误就会发生。


内核为2.5.48及以上的版本,stat结构体中关于时间的三个元素支持纳秒时间戳。如果_BSD_SOURCE或者_SVID_SOURCE两个宏有定义,那么Glibc标准库将提供st_atime.tv_nsec格式的命名来提供纳秒时间戳。这些元素在POSIX.1-2008中被指定,并且,在2.12及以上版本中,如果_POSIX_C_SOURCE用200809L或者更大的数定义,或者_XOPEN_SOURCE被700或者更大的数定义,那么glibc标准库中也包含了能够使用纳秒的元素。如果以上提到的宏都没有被定义,那么纳秒时间戳被st_atimensec这样的命名提供。在文件系统尚不支持子时间戳,纳秒元素的值将会为0.


In man pages

以下程序调用stat()函数来打印stat结构体的部分元素值:

 #include <sys/types.h>
       #include <sys/stat.h>
       #include <time.h>
       #include <stdio.h>
       #include <stdlib.h>

       int
       main(int argc, char *argv[])
       {
           struct stat sb;

           if (argc != 2) {
               fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           if (stat(argv[1], &sb) == -1) {
               perror("stat");
               exit(EXIT_FAILURE);
           }

           printf("File type:                ");

           switch (sb.st_mode & S_IFMT) {
           case S_IFBLK:  printf("block device\n");            break;
           case S_IFCHR:  printf("character device\n");        break;
           case S_IFDIR:  printf("directory\n");               break;
           case S_IFIFO:  printf("FIFO/pipe\n");               break;
           case S_IFLNK:  printf("symlink\n");                 break;
           case S_IFREG:  printf("regular file\n");            break;
           case S_IFSOCK: printf("socket\n");                  break;
           default:       printf("unknown?\n");                break;
           }

           printf("I-node number:            %ld\n", (long) sb.st_ino);

           printf("Mode:                     %lo (octal)\n",
                   (unsigned long) sb.st_mode);

           printf("Link count:               %ld\n", (long) sb.st_nlink);
           printf("Ownership:                UID=%ld   GID=%ld\n",
                   (long) sb.st_uid, (long) sb.st_gid);
           printf("Preferred I/O block size: %ld bytes\n",
                   (long) sb.st_blksize);
           printf("File size:                %lld bytes\n",
                   (long long) sb.st_size);
           printf("Blocks allocated:         %lld\n",
                   (long long) sb.st_blocks);

           printf("Last status change:       %s", ctime(&sb.st_ctime));
           printf("Last file access:         %s", ctime(&sb.st_atime));
           printf("Last file modification:   %s", ctime(&sb.st_mtime));

           exit(EXIT_SUCCESS);
       }


In my terminal

/*@Filename:    file_size.c
 *@Function:    Get the special file's size
 *@Author:      One fish
 *@Date:        2014.11.4 Thu
 *@Last modified:       2014.11.4 Thu
 */
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>


/*@Function:    Get the size of the path(file)
 *@arg:         path is the special file
 *@revl:        The size of the special file inclued path if stat() sucess,
 *              otherwise exit(1)
 */
int file_size(const char* path)
{
        struct stat buf;

        if ( stat(path, &buf) ) {
                switch(errno){
                        case EACCES:
                                printf("Please chmod the permission of '%s'\n", path);
                                break;
                        case EFAULT:
                                printf("'%s' is invalid\n", path);
                                break;
                        case ENAMETOOLONG:
                                printf("The lengths of '%s' is too long\n", path);
                                break;
                        case ENOENT:
                                printf("Check component of '%s' Or if '%s' is NULL\n", path, path);
                                break;
                        case ENOMEM:
                                printf("Out of memory\n");
                                break;
                        case ENOTDIR:
                                printf("Component of Prefix of the '%s' is not dirctory\n", path);
                                break;
                        default:
                                printf("Unkown errnos\n");
                                break;
                }

                exit(1);
        }

        return buf.st_size;
}

int main(int argc, char *argv[])
{
        if (argc != 2) printf("usage %s file\n", argv[0]);
        printf("The %s size = %d\n", argv[1], file_size(argv[1]) );
        return 0;
}

[2014.11.4 - 14:51]

Try-TNote Over.

你可能感兴趣的:(man -s 2 stat)